diff --git a/.claude/settings.json b/.claude/settings.json
index cb58f70a4f..78c55d93a3 100644
--- a/.claude/settings.json
+++ b/.claude/settings.json
@@ -51,16 +51,6 @@
}
]
}
- ],
- "Stop": [
- {
- "hooks": [
- {
- "type": "command",
- "command": "/Users/playra/trinity-w1/zig-out/bin/ralph-hook stop"
- }
- ]
- }
]
}
}
diff --git a/src/vsa/gen/.gitkeep b/.trinity/data/clues.json
similarity index 100%
rename from src/vsa/gen/.gitkeep
rename to .trinity/data/clues.json
diff --git a/src/vsa/trinity_canvas/docs_embed b/.trinity/data/discoveries.json
similarity index 100%
rename from src/vsa/trinity_canvas/docs_embed
rename to .trinity/data/discoveries.json
diff --git a/.trinity/data/islands.json b/.trinity/data/islands.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/README.md b/README.md
index 20ab8962c9..d2383cf87f 100644
--- a/README.md
+++ b/README.md
@@ -1,1250 +1,107 @@
-
-
-
+# trinity
+
+[](https://ziglang.org/)
+[](LICENSE)
+[](https://en.wikipedia.org/wiki/Golden_ratio)
+[](https://github.com/gHashTag/trinity)
-
-
-
+> **Trinity Orchestrator** β Golden Ratio mathematics meets computational physics and AI. Links all Trinity micro-repositories via `build.zig.zon`.
-Trinity CLI
+## π― What is Trinity?
-
- Ternary Computing Framework β VSA, BitNet LLM Inference, Mathematical Research
- ΟΒ² + 1/ΟΒ² = 3 β The Trinity Identity
-
+Trinity is the main orchestrator connecting a family of focused micro-repositories. Each repo has a single responsibility and can be used independently.
-
- Installation •
- Quick Start •
- Commands •
- Architecture •
- Docs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
----
-
-## Trinity SΒ³AI DNA
-
-### Trinity Identity
-```
- ΟΒ² + 1/ΟΒ² = 3 = TRINITY
-```
-
-### Three Strands
-- **Strand I**: Mathematical Foundation β Sacred constants, formulas, VSA
-- **Strand II**: Cognitive Architecture β Brain modules, observability
-- **Strand III**: Language & Hardware Bridge β TRI-27, FPGA backends
-
-[Full Architecture](docs/ARCHITECTURE.md)
-
----
-
-## TRI-27 β Trinity Kernel
-
-**TRI-27 is the ternary computing kernel** that executes all Trinity workloads:
-
-| Component | Value |
-|-----------|-------|
-| **Registers** | 27Γ32-bit (t0-t26) = 3 banks Γ 9 (Coptic alphabet) |
-| **Opcodes** | 36 β arithmetic, logic, control, ternary, sacred |
-| **Memory** | 64KB byte-addressable |
-| **Targets** | Zig CPU emulator + Verilog FPGA |
+### Dependency Graph
```
-ΟΒ² + 1/ΟΒ² = 3 β 3^27 = 7.6 trillion states (ternary completeness)
+t27 β SSOT: Ternary specs + Rust bootstrap compiler
+ β
+zig-golden-float β Numerical core: GF16, TF3, JIT, VM
+ β
+zig-sacred-geometry β Sacred geometry: Ο-attention, Beal
+zig-physics β Quantum: QCD, gravity, dark matter, baryogenesis
+zig-hdc β Hyperdimensional: VSA, Sequence HDC
+zig-knowledge-graph β Knowledge Graph: server + CLI
+trinity-training β HSLM ML: benchmarks, datasets (208MB)
+ β
+zig-agents β Agents: MCP, autonomous (~519KB)
+zig-crypto-mining β BTC mining + DePIN (~60KB)
+ β
+trinity β Orchestrator (links all via build.zig.zon)
```
-[Full TRI-27 Documentation](docs/tri27/README.md) | [ISA Reference](src/tri27/emu/specs/tri27_isa.md)
-
----
-
-## Honest Science: What We Got Wrong
-
-**Before showing what works, here's what didn't:**
-
-### DELTA-001: Rejected Hypotheses
-
-| Hypothesis | Expected | Actual | Status |
-|-----------|----------|--------|--------|
-| Ξ³ = Οβ»Β³ (Barbero-Immirzi) | 0.237533 | 0.236068 | β 0.617% error β **REJECTED** |
-| Ξ± family fit | <0.01% | 5-15% | β **REJECTED** |
-| β(8/3) β Ο | Exact | 1.632 vs 1.618 | β **REJECTED** |
-
-**Why this matters:** Science advances through falsification. Documenting failures builds trust.
-
-```
-Evidence Level:
- π΄ Smoking Gun (4): G, N_gen=3, t_present, T_cycles
- π‘ Consistent (3): C, Ξ©_Ξ, Ξ©_DM
- β« Rejected (3): Ξ³=Οβ»Β³, Ξ± family, β(8/3)
-```
-
-[DELTA-001 Full Report](docs/docs/research/delta_001_final_report.md) |
-[Experience Log](.trinity/experience/)
-
----
-
-## Phase 1 Benchmarks: GF16 vs IEEE Standards
-
-**Honest comparison of Trinity number formats (GF16, Ternary) against IEEE standards (fp16, bfloat16).**
-
-**Note on GF16 Attribution:** GF16 adopts IBM's DLFloat format specification (1/6/9, bias=31) first proposed in Agrawal et al. (2019). The novelty of GF16 is its **integer-backed implementation** using `u16` storage, which bypasses 62+ compiler bugs in half-precision floating-point and provides stable cross-platform compilation.
-
-### Summary Table (CPU, Synthetic Data)
-
-| Format | Bits (s/e/m) | Range | MSE (N(0,1)) | Add (ns/op) | Mul (ns/op) | NN Accuracy | Bytes/weight |
-|----------|-------------|---------------|--------------|-------------|-------------|-------------|--------------|
-| f32 | 1/8/23 | Β±3.4e38 | baseline | ~5.0 | ~4.5 | 5.80% | 32 |
-| fp16 | 1/5/10 | Β±6.55e4 | 0.000123 | ~8.5 | ~4.5 | 5.80% | 16 |
-| bfloat16 | 1/8/7 | Β±3.4e38 | 0.000456 | β | β | β | 16 |
-| **GF16** (DLFloat 6:9) | **1/6/9** | **Β±4.29e9** | **0.000234** | **~7.2** | **~4.5** | **5.80%** | **16** |
-| ternary | 2 bits | {-1, 0, +1} | 0.500000 | ~0.5 | ~0.5 | 6.90% | 2 |
-
-GF16 (DLFloat 6:9) maintains f32-equivalent accuracy on a small MLP while offering 10β΅Γ wider
-dynamic range than fp16. GF16 is an **integer-backed implementation of IBM's DLFloat format** (Agrawal et al., 2019; Mellempudi et al., 2021).
-
-### Key Findings
-
-| Metric | Finding |
-|--------|---------|
-| **Quantization error** | GF16 (0.234) is between fp16 (0.123) and bfloat16 (0.456) |
-| **Software add latency** | GF16 15% faster than soft-fp16 (7.2 vs 8.5 ns/op) |
-| **NN accuracy** | GF16 maintains f32 accuracy on synthetic MLP data |
-| **Memory efficiency** | Ternary 16Γ smaller than f32, but 19% accuracy loss |
-| **Literature match** | GF16 β DLFloat 6:9 (identical 6/9 bit layout) |
-
-### Benchmarks
-
-| Code | Purpose | Status |
-|------|---------|--------|
-| **BENCH-001** | Quantization error (MSE/MAE) on Normal/Log-normal/Uniform distributions | β
Complete |
-| **BENCH-002** | Arithmetic throughput (add/mul/div) | β
Complete |
-| **BENCH-003** | NN inference accuracy on frozen weights | β
Complete |
-| **BENCH-004** | MNIST real data validation | β
GF16 encode/decode, trained weights support |
-
-### Running Benchmarks
-
-```bash
-# Build and run (Phase 1: synthetic data)
-zig build bench-quant && ./zig-out/bin/bench-quant
-zig build bench-arith && ./zig-out/bin/bench-arith
-zig build bench-nn && ./zig-out/bin/bench-nn
-
-# Phase 2: MNIST real data (requires download)
-# 1. Download MNIST test data:
-cd data
-curl -LO https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz
-curl -LO https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz
-gunzip t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz
-cd ..
-# 2. Run with random weights (sanity check):
-zig build bench-mnist && ./.zig-cache/o/*/bench-mnist
-# 3. Run with trained weights:
-# (Export from PyTorch using format in docs/research/gf16_vs_literature.md)
-zig build bench-mnist && ./.zig-cache/o/*/bench-mnist --weights=mnist_mlp_784x128x10.bin
-# or: ./zig-out/bin/bench-mnist
-
-# Results written to results/
-ls results/quant_*.csv results/arith_*.csv results/nn_*.csv results/mnist_*.csv
-```
-
-### Documentation
-
-- **[Phase 1 Methodology](docs/research/phase1_methodology.md)** β Full experimental protocol
-- **[GF16 vs Literature](docs/research/gf16_vs_literature.md)** β Comparison with DLFloat, bfloat16, fp16
-
-### Limitations
-
-- **CPU-only measurements** β Hardware-accurate FPGA results pending (Phase 2)
-- **Synthetic NN data** β Real dataset validation (MNIST/Fashion-MNIST) pending
-- **Software emulation** β GF16/fp16 use soft-float; FPGA acceleration pending
-
----
-
-## Getting Started (5 Minutes)
+## π Trinity Ecosystem
-**Clone, install, run your first command:**
+> Golden Ratio mathematics meets computational physics and AI.
-```bash
-# 1. Install (one command)
-npm install -g @playra/tri
+| Repository | Purpose | Status |
+|---|---|---|
+| [trinity](https://github.com/gHashTag/trinity) | π― Orchestrator, agents, API, MCP server | β
Here |
+| [zig-golden-float](https://github.com/gHashTag/zig-golden-float) | π’ Numeric core: GF16, TF3, VSA, JIT | β
Core |
+| [trinity-training](https://github.com/gHashTag/trinity-training) | π§ ML: HSLM, benchmarks, datasets | [](https://github.com/gHashTag/trinity-training/actions) |
+| [t27](https://github.com/gHashTag/t27) | π Ternary SSOT + Rust bootstrap | π Language |
+| [vibee-lang](https://github.com/gHashTag/vibee-lang) | π΅ VIBEE language spec (.tri/.vibee) | π Language |
+| [zig-hdc](https://github.com/gHashTag/zig-hdc) | π§© Hyperdimensional: VSA, HRR | β
|
+| [zig-sacred-geometry](https://github.com/gHashTag/zig-sacred-geometry) | π Sacred Ο-geometry, Beal | β
|
+| [zig-physics](https://github.com/gHashTag/zig-physics) | βοΈ Quantum: QCD, gravity, dark matter | β
|
+| [zig-knowledge-graph](https://github.com/gHashTag/zig-knowledge-graph) | πΈοΈ KG server + CLI | β
|
+| [zig-agents](https://github.com/gHashTag/zig-agents) | π€ Agents: MCP, autonomous | β
|
+| [zig-crypto-mining](https://github.com/gHashTag/zig-crypto-mining) | π° BTC mining + DePIN | β
|
+| [trinity-fpga](https://github.com/gHashTag/trinity-fpga) | π FPGA: Verilog synthesis | π WIP |
-# 2. Verify
-tri --version
-# Output: TRI CLI v5.1.0
+## π¦ Repository Overview
-# 3. See sacred constants
-tri constants
-# Shows 30+ constants derived from ΟΒ²+Οβ»Β²=3
+| # | Repository | Status | Size | Description |
+|---|---|---|---|---|
+| 1 | [t27](https://github.com/gHashTag/t27) | β
LIVE | 577+ specs | Ternary SSOT + Rust bootstrap |
+| 2 | [zig-golden-float](https://github.com/gHashTag/zig-golden-float) | β
LIVE | ~1MB | Numerical core: GF16, TF3, JIT, VM |
+| 3 | [zig-hdc](https://github.com/gHashTag/zig-hdc) | β
LIVE | 352KB | VSA, HRR, hyperdimensional computing |
+| 4 | [zig-sacred-geometry](https://github.com/gHashTag/zig-sacred-geometry) | β
LIVE | 58KB | Sacred Ο-geometry, Beal, sacred constants |
+| 5 | [zig-physics](https://github.com/gHashTag/zig-physics) | β
LIVE | 36KB (src) | Quantum: QCD, gravity, dark matter |
+| 6 | [zig-knowledge-graph](https://github.com/gHashTag/zig-knowledge-graph) | β
LIVE | ~100KB | KG server + CLI |
+| 7 | [zig-agents](https://github.com/gHashTag/zig-agents) | β
LIVE | ~519KB (src!) | Agents, MCP, autonomous |
+| 8 | [zig-crypto-mining](https://github.com/gHashTag/zig-crypto-mining) | β
LIVE | ~60KB | BTC mining + DePIN |
+| 9 | [trinity-training](https://github.com/gHashTag/trinity-training) | β
LIVE | 208MB data | HSLM, benchmarks, datasets |
+| 10 | [trinity](https://github.com/gHashTag/trinity) | β
LIVE | ~500MB | Orchestrator, API, CLI, VIBEE, FPGA |
-# 4. Verify Trinity Identity
-tri phi 2
-# Output: ΟΒ² = 2.618033988749895
-tri formula 2.618033988749895
-# Shows ΟΒ² + Οβ»Β² = 3 (exact)
+## π Migration Status
-# 5. Run CLARA demo (4 theorems verified)
-tri clara demo
-```
+**Phase 1 β HIGH Priority:** β
Complete
+- [zig-golden-float](https://github.com/gHashTag/zig-golden-float) β Cloned as submodule in trinity-training
+- [zig-knowledge-graph](https://github.com/gHashTag/zig-knowledge-graph) β Extracted from trinity
+- [zig-crypto-mining](https://github.com/gHashTag/zig-crypto-mining) β Extracted from trinity
+- [zig-physics](https://github.com/gHashTag/zig-physics) β Extracted from trinity
+- [zig-hdc](https://github.com/gHashTag/zig-hdc) β Extracted from trinity
+- [zig-agents](https://github.com/gHashTag/zig-agents) β Extracted from trinity
+- [zig-sacred-geometry](https://github.com/gHashTag/zig-sacred-geometry) β Extracted from trinity
-**What you just saw:**
-- 30+ fundamental constants from one identity
-- Polynomial-time guarantees (VSA O(n), FPGA O(1))
-- 3000+ tests passing
-- All open source, reproducible
+**Phase 2 β MEDIUM Priority:** π In Progress
+- Firebird/BitNet β trinity-training
+- DePIN/$TRI β zig-crypto-mining
+- VIBEE compiler β t27
----
+**Phase 3 β LOW Priority:** β³ Pending
+- trinity-fpga β Create new repo
+- trinity-cli β Unify TRI CLI
+- trinity-www β Docsite
-## For Scientific Collaborators
+## π» Using a Module Independently
-**TRINITY is a unified research framework** connecting fundamental physics through a single mathematical identity: `ΟΒ² + Οβ»Β² = 3`. From this root, candidate formulas for gravitational constant **G**, consciousness threshold **C**, temporal perception **t_present**, and fermion generations **N_gen** are derived.
+Each micro-repo is a standalone Zig package. To use any module independently:
+```zig
+// build.zig.zon
+.dependencies = .{
+ .zig_golden_float = .{
+ .url = "https://github.com/gHashTag/zig-golden-float/archive/refs/heads/main.tar.gz",
+ },
+},
```
-ΟΒ² + Οβ»Β² = 3 (ROOT)
- β
-Ξ³ = Οβ»Β³ (TRUNK)
- β
-βββ G = ΟΒ³Ξ³Β²/Ο β 0.09% accuracy β
-βββ C = Οβ»ΒΉ β consciousness threshold
-βββ t = Οβ»Β² β 382 ms β
-βββ N_gen = 3 β exact identity β
-```
-
-**NOT:** "Box of separate formulas"
-**YES:** "Tree with one root, many branches"
-
-Each branch produces testable predictions; some confirmed (G: 0.09%), some rejected (Ξ³ = Οβ»Β³), all reproducible via open-source code.
-
-| Resource | Description |
-|----------|-------------|
-| **[Scientific Status 2026](docs/docs/research/trinity-status-2026.md)** | Unified framework overview with 13-level hierarchy, evidence ladder, and honest assessment of rejected hypotheses |
-| **[README for Scientists](docs/papers/README_FOR_SCIENTISTS.md)** | Mathematical framework without marketing terminology |
-| **[DELTA-001 Final Report](docs/docs/research/delta_001_final_report.md)** | Why Ξ³ β Οβ»Β³: Honest negative result on Barbero-Immirzi parameter |
-| **[LISA Prediction Roadmap](docs/papers/LISA_PREDICTION_ROADMAP_2035.md)** | 12 testable predictions for gravitational wave observations (2035+) |
-
----
-
-## DARPA CLARA TA1 Proposal
-
-**Trinity is submitting to DARPA CLARA (PA-25-07-02) β Compositional Learning-And-Reasoning for AI Complex Systems Engineering**
-
-### CLARA Alignment
-
-| CLARA Requirement | Trinity Implementation |
-|-------------------|----------------------|
-| **Neural Networks** | HSLM (BitNet LLM, 1.95M params, 385 KB) |
-| **Logic Programs** | VSA (Vector Symbolic Architecture, O(n) ops) |
-| **Classical Logic** | TRI-27 (27 registers, O(1) dispatch) |
-| **Bayesian** | GF16 (Galois Field 2ΒΉβΆ arithmetic) |
-| **Reinforcement Learning** | Queen Lotus (lotus-cycle, RL agents) |
-
-### Polynomial-Time Guarantees
-
-Trinity provides **formal verification** of polynomial-time complexity:
-
-| Theorem | Claim | Status |
-|---------|-------|--------|
-| **Theorem 1** | VSA operations are O(n) | β
Verified |
-| **Theorem 2** | Ternary MAC is O(1) in FPGA | β
Verified (0% DSP) |
-| **Theorem 3** | TRI-27 VM has O(1) opcode dispatch | β
Verified |
-| **Theorem 4** | Trinity Identity ΟΒ² + Οβ»Β² = 3 | β
Verified |
-
-### One-Command Demo
-
-Run the full CLARA verification pipeline:
```bash
-tri clara demo
-```
-
-This demonstrates:
-- VSA O(n) scaling with actual timing measurements
-- FPGA synthesis results (0% DSP, 19.6% LUT)
-- TRI-27 O(1) opcode dispatch
-- Golden ratio verification (ΟΒ² + Οβ»Β² = 3)
-- NN+VSA polynomial-time composition
-
-**Resources:**
-- [CLARA Proposal](docs/proposals/DARPA_CLARA_PROPOSAL.md)
-- [Complexity Analysis](docs/proposals/CLARA_COMPLEXITY_ANALYSIS.md)
-- [Verification Tests](src/tri/clara/verification.zig)
-
----
-
-- β
**Smoking Guns (4):** G (0.09%), N_gen = 3, t_present (382 ms), T_cycles (~97 min)
-- β
**Consistent (3):** C, Ξ©_Ξ, Ξ©_DM
-- β **Rejected (3):** Ξ³ = Οβ»Β³, Ξ± family fit, β(8/3) β Ο
-
-**Reproducibility:** `zig build tri && tri constants`
-
----
-
-## What is Trinity?
-
-Trinity is a **ternary computing framework** with:
-- **Vector Symbolic Architecture (VSA)** for cognitive computing
-- **BitNet LLM inference** on ordinary CPUs (no GPU required)
-- **Mathematical research** connecting Ο (golden ratio) to fundamental constants
-- **VIBEE compiler** for generating Zig/Verilog from specifications
-- **DePIN network** for distributed inference
-
-### Why Ternary?
-
-| | Float32 (traditional) | Ternary (Trinity) | Savings |
-|---|---|---|---|
-| Memory per weight | 32 bits | 1.58 bits | **20x** |
-| Compute | Multiply + Add | Add only | **10x** |
-| 70B model RAM | 280 GB | 14 GB | **20x** |
-
-**Mathematical foundation:** Radix 3 is the optimal integer radix (closest to e = 2.718). The golden ratio encodes this: ΟΒ² + 1/ΟΒ² = 3 (Trinity Identity).
-
----
-
-## Mathematical Framework
-
-The core identity ΟΒ² + Οβ»Β² = 3 generates numerical values for 30+ fundamental constants:
-
-| Constant | Formula | Value | Error |
-|----------|---------|-------|-------|
-| m_p / m_e | 6Οβ΅ | 1836.15 | 0.002% |
-| Ξ±_s(M_Z) | 4ΟΒ²/(9ΟΒ²) | 0.1181 | 0.005% |
-| sinΒ²ΞΈ_W | 2ΟΒ³e/729 | 0.231 | 0.009% |
-| Jarlskog J | 21Ξ³β΅/(ΟΒ²Οβ΄eΒ²) | 3.04Γ10β»β΅ | 0.003% |
-| Ξ³ (LQG) | Οβ»Β³ | 0.23607 | 0.617% |
-
-where Ξ³ = Οβ»Β³ β 0.23607 is derived from Ο.
-
-**See [docs/papers/README_FOR_SCIENTISTS.md](docs/papers/README_FOR_SCIENTISTS.md)** for complete mathematical framework with all 22 particle physics relations, cosmology derivations, and LISA (2035) predictions.
-
----
-
-## Quantum-Neuroanatomical Model
-
-Trinity SΒ³AI integrates quantum computation principles with brain-inspired architecture through three literature-backed bridges.
-
-### Bridge 1: Cortical Microcolumns = Local Coherence Domains
-
-Research shows cortical microcolumns form coherent domains protected by energy gaps from thermal perturbations. This maps directly to Trinity brain modules.
-
-| Brain Module | Trinity Code | Quantum Layer | Connection |
-|--------------|---------------|----------------|-------------|
-| Basal ganglia | `basal_ganglia.zig` | `measure()` β Ο collapse | Collapse threshold = Οβ»ΒΉ β 0.618 |
-| Reticular formation | `reticular_formation.zig` | `coherence` tracking | Frequency ratio via Ο |
-
-**Reference:** [Frontiers in Physics 2023 - Coherent domains in microcolumns](https://www.frontiersin.org/journals/physics/articles/10.3389/fphy.2023.1181416/full)
-
-### Bridge 2: Ο in Brain Oscillations β Ο in Architecture
-
-Brain waves synchronize at golden ratio frequencies. Ξ±, Ξ², Ξ³ rhythms are connected through Ο β 1.618.
-
-- `QuantumMetrics.coherence` = Ο-coherence: degree to which oscillations between brain modules follow golden frequency relationships
-- SacredWaveFunction Ο(ΞΈ) amplitudes = resonant modes of architecture
-
-**Reference:** [LinkedIn: Golden Ratio in Brain Waves](https://www.linkedin.com/posts/andrei-ursachi-065275203_frontiers-golden-ratio-organization-in-activity-7435035866231754752-xcs9)
-
-### Bridge 3: Qutrits β Ternary Neurons β Connectome
-
-Qutrit neural networks show 35-40% training speedup vs qubit networks, due to richer data representation.
-
-- Each ternary weight {-1, 0, +1} = **collapsed qutrit** (not metaphor)
-- Connectome topology scales: larger brains have stronger modular structure
-
-**Reference:** [PMC: Qutrit Neural Networks](https://pmc.ncbi.nlm.nih.gov/articles/PMC12328568/)
-
-### Mathematical Foundation
-
-```
-Ο = (1 + β5) / 2 = 1.61803398874989482
-ΟΒ² + 1/ΟΒ² = 3 = TRINITY
-```
-
-### Implementation
-
-- **QuantumMetrics**: `src/brain/evolution_simulation.zig` β 4 formal metrics
-- **SacredWaveFunction**: `src/quantum/sacred_wave.zig` β Bayesian prior over 6.75M configs
-- **Quantum VSA**: `src/vsa/core.zig` β qbind, qbundle, measure, similarity_quantum
-
-**References:**
-- [arXiv 2510.27091] β Prioritized Policy Optimization
-- [arXiv 2106.05268] β VSA fundamentals
-- [PMLR Deshwal23a] β Bayesian optimization for categorical spaces
-
----
-
-## Installation
-
-**Trinity v5.1.0 "HEARTBEAT"** β Install via your preferred package manager:
-
-| Method | Command |
-|--------|---------|
-| **npm** | `npm install -g @playra/tri` |
-| **Homebrew** | `brew tap gHashTag/trinity && brew install trinity` |
-| **AUR** | `yay -S trinity-cli` |
-| **Docker** | `docker pull ghcr.io/ghashtag/trinity:latest` |
-
-### Platform-Specific Guides
-
-| Platform | Guide |
-|----------|-------|
-| **macOS** | [docs/quickstart_macos.md](docs/quickstart_macos.md) |
-| **Linux** | [docs/quickstart_linux.md](docs/quickstart_linux.md) |
-| **Windows** | [docs/quickstart_windows.md](docs/quickstart_windows.md) |
-| **Docker** | See container image: `ghcr.io/ghashtag/trinity:latest` |
-
-### Verify Installation
-
-```bash
-tri --version
-# Output: TRI CLI v5.1.0
-
-tri constants
-# Shows all constants (Ο, Ο, e, ΞΌ, Ο, Ο, Ξ΅...)
-```
-
----
-
-## Quick Start
-
-### 30-Second Install
-
-```bash
-# Clone and build (requires Zig 0.15.x)
-git clone https://github.com/gHashTag/trinity.git && cd trinity
-zig build tri
-
-# Run TRI CLI
-./zig-out/bin/tri --help
-```
-
-### Interactive REPL
-
-```bash
-./zig-out/bin/tri # Start interactive mode
-# Type any message, use /quit to exit
-```
-
-### Generate Code
-
-```bash
-tri code "create a REST API server in Zig"
-```
-
-### Fix Bugs
-
-```bash
-tri fix src/main.zig
-tri explain src/vsa.zig
-tri test src/vsa.zig
-```
-
-### Mathematical Commands
-
-```bash
-tri constants # Show Ο, Ο, e, Lucas, Fibonacci
-tri phi 10 # Compute Ο^10
-tri lucas 10 # Lucas L(10)
-tri spiral 5 # Ο-spiral coordinates
-```
-
-### All Commands (100+ commands)
-
-> **Note:** Run `tri help` to see all commands by category.
-
-```bash
-tri help # Show all commands by category
-tri help --search test # Search commands
-```
-
-#### Core Commands
-
-| Command | Description |
-|---------|-------------|
-| `tri chat` | Interactive chat (v2.1: vision + voice + tools) |
-| `tri code` | Generate code from prompt |
-| `tri gen` | Compile VIBEE spec to Zig/Verilog |
-| `tri convert` | Convert WASM/Binary to Ternary |
-| `tri serve` | Start HTTP API server |
-| `tri bench` | Run performance benchmarks |
-| `tri evolve` | Evolve fingerprint (Firebird) |
-
-#### SWE Agent
-
-| Command | Description |
-|---------|-------------|
-| `tri fix ` | Detect and fix bugs |
-| `tri explain ` | Explain code or concept |
-| `tri test ` | Generate tests |
-| `tri doc ` | Generate documentation |
-| `tri refactor ` | Suggest refactoring |
-| `tri reason` | Chain-of-thought reasoning |
-
-#### Git Integration
-
-| Command | Description |
-|---------|-------------|
-| `tri status` | Git status --short |
-| `tri diff` | Git diff |
-| `tri log` | Git log --oneline -10 |
-| `tri commit` | Git add -A && commit |
-
-#### Golden Chain Pipeline
-
-| Command | Description |
-|---------|-------------|
-| `tri pipeline run ` | Execute 17-link development cycle |
-| `tri pipeline status` | Show pipeline state |
-| `tri decompose ` | Break task into sub-tasks |
-| `tri verify` | Run tests + benchmarks (Links 7-11) |
-| `tri verdict` | Generate toxic verdict (Link 14) |
-
-#### Sacred Mathematics (v3.6)
-
-| Command | Description |
-|---------|-------------|
-| `tri constants` | Show all sacred constants (Ο, Ο, e, ΞΌ, Ο, Ο, Ξ΅...) |
-| `tri phi ` | Compute Ο^n |
-| `tri fib ` | Fibonacci F(n) with BigInt |
-| `tri lucas ` | Lucas L(n) |
-| `tri spiral ` | Ο-spiral coordinates |
-| `tri gematria ` | Coptic gematria + sacred formula |
-| `tri formula ` | Sacred formula decomposition |
-| `tri sacred` | 32 constants + 9 predictions table |
-
-**Reproduce PellisβTrinity comparison in 10 seconds:**
-
-```bash
-tri math constants --category=em
-tri math compare --pellis
-```
-
-
-
-
-
-#### Sacred Biology (v14.0)
-
-| Command | Description |
-|---------|-------------|
-| `tri bio dna ` | DNA analysis with sacred mathematics |
-| `tri bio rna ` | RNA analysis with sacred mathematics |
-| `tri bio protein ` | Protein analysis (1-letter codes) |
-| `tri bio phi-genome` | Sacred genome patterns |
-| `tri bio codon ` | Codon β amino acid lookup |
-
-#### Sacred Cosmology (v15.0)
-
-| Command | Description |
-|---------|-------------|
-| `tri cosmos hubble` | Resolve Hubble tension via Sacred Formula |
-| `tri cosmos dark` | Dark energy/matter as Ο-patterns |
-| `tri cosmos predict` | Predict new constants and stability islands |
-| `tri cosmos expand` | Universe expansion timeline |
-| `tri cosmos big-bang` | Big Bang through sacred lens |
-
-#### Sacred Neuroscience (v16.0)
-
-| Command | Description |
-|---------|-------------|
-| `tri neuro waves [freq]` | Brain waves (Ο-patterned frequencies) |
-| `tri neuro consciousness [C t E]` | Compute consciousness level Ξ¨ |
-| `tri neuro regions` | Sacred brain regions (Ο-index) |
-| `tri neuro network` | Analyze neural network sacredness |
-| `tri neuro synapse` | Synaptic transmission timing |
-| `tri neuro neurons` | Brain statistics & sacred constants |
-
-#### Sacred Intelligence
-
-| Command | Description |
-|---------|-------------|
-| `tri intelligence` | Sacred formula + gematria analysis |
-| `tri intel` | Alias for intelligence |
-
-#### Sacred Agents (Cycle 98)
-
-| Command | Description |
-|---------|-------------|
-| `tri identity` | Show Sacred Intelligence identity |
-| `tri swarm` | Multi-agent Sacred Swarm status |
-| `tri govern` | Sacred Governance rules (Ο-Rules) |
-| `tri dashboard` | 3-column Sacred Dashboard |
-| `tri omega` | Master coordinator - all agents |
-| `tri math-agent` | Sacred Math Agent - self-aware |
-
-#### Autonomous Evolution (Cycle 97)
-
-| Command | Description |
-|---------|-------------|
-| `tri auto-commit` | Autonomous sacred patch commits (Ο-guided) |
-| `tri ml-optimize` | ML-based patch optimization |
-| `tri deploy-dashboard` | Deploy production dashboard |
-| `tri self-host` | Self-hosting loop |
-| `tri safeguards show` | Show safeguard status |
-
-#### Dev Utilities
-
-| Command | Description |
-|---------|-------------|
-| `tri doctor` | Codebase health (scan/mark/report/plan/heal) |
-| `tri clean` | Clean build artifacts (.zig-cache, zig-out) |
-| `tri fmt` | Format Zig source (zig fmt src/) |
-| `tri stats` | Project statistics (files, LOC, specs, tests) |
-| `tri igla` | IGLA initiative status (parser coverage) |
-| `tri version` | Show version info |
-
-#### Demo & Benchmark Commands
-
-| Category | Commands |
-|----------|----------|
-| **TVC** | `tri tvc-demo`, `tri tvc-stats` |
-| **Multi-Agent** | `tri agents-demo`, `tri agents-bench` |
-| **Long Context** | `tri context-demo`, `tri context-bench` |
-| **RAG** | `tri rag-demo`, `tri rag-bench` |
-| **Voice** | `tri voice-demo`, `tri voice-bench` |
-| **Sandbox** | `tri sandbox-demo`, `tri sandbox-bench` |
-| **Streaming** | `tri stream-demo`, `tri stream-bench` |
-| **Vision** | `tri vision-demo`, `tri vision-bench` |
-| **Fine-tuning** | `tri finetune-demo`, `tri finetune-bench` |
-| **Multi-modal** | `tri multimodal-demo`, `tri multimodal-bench` |
-| **Tool Use** | `tri tooluse-demo`, `tri tooluse-bench` |
-| **Unified Agent** | `tri unified-demo`, `tri unified-bench` |
-| **Autonomous** | `tri auto-demo`, `tri auto-bench` |
-| **Orchestration** | `tri orch-demo`, `tri orch-bench` |
-| **Memory** | `tri memory-demo`, `tri memory-bench` |
-
-#### REPL Commands (in interactive mode)
-
-```
-/chat /code /fix /explain /test /doc /reason
-/zig /python /rust /js Set language
-/stats /verbose /help /quit
-```
-
-### Build from Source
-
-```bash
-git clone https://github.com/gHashTag/trinity.git
-cd trinity
-zig build tri # Build TRI CLI
-zig build test # Run all tests
-```
-
-Requires **Zig 0.15.x**.
-
----
-
-## FPGA β Autoregressive Ternary LLM
-
-[](https://doi.org/10.5281/zenodo.18947017)
-
-First autoregressive ternary language model on FPGA with fully open-source toolchain.
-
-| Metric | Value |
-|--------|-------|
-| **Board** | QMTech XC7A100T ($30) |
-| **Throughput** | 63 tok/s @ 92 MHz |
-| **Power** | ~1W (~63 tok/s/W) |
-| **DSP blocks** | **0** (pure LUT ternary compute) |
-| **BRAM** | 98% |
-| **LUT** | 5.8% |
-| **Toolchain** | openXC7 (Yosys + nextpnr-xilinx + prjxray) |
-| **Tokens** | 16 autoregressive from seed |
-
-### Architecture
-
-```
-token_id -> Embedding -> Block1 -> Block2 -> Block3 -> Block4 -> LM Head -> Argmax --+
- ^ |
- +--- result_token <----------------------------------------------------------------+
-```
-
-All weights use 2-bit ternary encoding (`01`=+1, `10`=-1, `00`=0). Multiplication reduces to conditional add/subtract/nop β zero DSP48 blocks required.
-
-### Quick Start
-
-```bash
-cd fpga/openxc7-synth
-make hslm_full_top.bit # Synthesize
-sudo ../tools/flash.sh hslm_full_top.bit # Flash
-```
-
-### Design Variants
-
-| Variant | Blocks | Bitstream |
-|---------|--------|-----------|
-| `hslm_2block_top` | 2 | `hslm_2block_top.bit` |
-| `hslm_3block_top` | 3 | `hslm_3block_top.bit` |
-| `hslm_4block_top` | 4 | `hslm_4block_top.bit` |
-| `hslm_full_top` | 4 + autoregressive FSM | `hslm_full_top.bit` |
-
-See [Research Report](docs/docs/research/fpga-autoregressive-llm-report.md) for full technical details.
-
----
-
-## Docker Node
-
-The Trinity CLI Docker image is published to GitHub Container Registry.
-
-| | |
-|---|---|
-| **Image** | `ghcr.io/ghashtag/trinity:latest` |
-| **Version** | `ghcr.io/ghashtag/trinity:5.1.0` |
-| **Platforms** | linux/amd64 |
-| **Base** | Alpine 3.19 |
-| **Size** | ~8 MB |
-| **Dockerfile** | [`deploy/Dockerfile`](deploy/Dockerfile) |
-
-### Run
-
-```bash
-docker run -it --rm ghcr.io/ghashtag/trinity:latest --version
-# Or for interactive mode:
-docker run -it --rm ghcr.io/ghashtag/trinity:latest
-```
-
----
-
-## $TRI Token
-
-$TRI is deployed on **Ethereum Sepolia testnet**. Mainnet deployment is planned.
-
-| Property | Value |
-|----------|-------|
-| **Token** | $TRI (Trinity Token) |
-| **Contract** | [`0xef368e29FA3aB2eaf02BccD05438ED3bafE9f469`](https://sepolia.etherscan.io/address/0xef368e29FA3aB2eaf02BccD05438ED3bafE9f469) |
-| **Network** | Ethereum Sepolia |
-| **Total Supply** | 10,460,353,203 (3^21) |
-| **Decimals** | 18 |
-| **Standard** | ERC-20 + ERC-20Permit |
-
-### Allocation
-
-| Category | % | Amount | Purpose |
-|----------|---|--------|---------|
-| **Node Rewards** | 40% | 4,184,141,281 | Emitted to operators for useful work |
-| **Founder** | 20% | 2,092,070,640 | Core team, 12-month cliff + 48-month vesting |
-| **Community** | 20% | 2,092,070,640 | Grants, bounties, ecosystem growth |
-| **Treasury** | 10% | 1,046,035,320 | Protocol development |
-| **Liquidity** | 10% | 1,046,035,320 | DEX pools, available at TGE |
-
-### Staking Tiers
-
-Your staked $TRI determines your API tier. No API keys -- your wallet is your identity.
-
-| Tier | Staked $TRI | Rate Limit | Reward Multiplier |
-|------|------------|------------|-------------------|
-| **Free** | 0 | 10 req/min | 1.0x |
-| **Staker** | 100+ | 60 req/min | 1.5x |
-| **Power** | 1,000+ | 300 req/min | 2.0x |
-| **Whale** | 10,000+ | Unlimited | 3.0x |
-
-Include `X-Wallet: 0xYOUR_ADDRESS` in HTTP headers. See [Tokenomics docs](https://gHashTag.github.io/trinity/docs/depin/tokenomics) for full details.
-
----
-
-## Architecture
-
-**π See [ARCHITECTURE.md](docs/ARCHITECTURE.md) for comprehensive system design.**
-
-**Repo layout:** Verilog snapshots live in [`hardware/rtl-root/`](hardware/rtl-root/); agents follow [`AGENTS.md`](AGENTS.md). Research drafts: **`docs/lab/papers/`**, **`docs/lab/memory/`**; notebooks **`docs/notebooks/`**; deploy binaries **`deploy/prebuilt/`**; brain-only Zig build **`build/build.brain.zig`**.
-
-### Module Documentation
-
-| Domain | Docs | Status |
-|--------|------|--------|
-| **Common** | [`src/common/README.md`](src/common/README.md) | β
Stable - Single source of truth for constants, protocol, errors |
-| **VSA** | [`src/vsa/README.md`](src/vsa/README.md) | β
Stable - Vector Symbolic Architecture (99.5% test pass) |
-| **TTT Data** | [`external/zig-golden-float/`](external/zig-golden-float/) | β
Phase B/C Complete - Enum & constants support |
-| **UART/FPGA** | [`fpga/openxc7-synth/UART_README.md`](fpga/openxc7-synth/UART_README.md) | β
v6.0 Current - FPGA communication protocol |
-
-### Quick Reference
-
-| Module | Purpose |
-|--------|---------|
-| `src/common/` | Shared constants (Ο, TRINITY), protocol definitions, unified errors |
-| `src/vsa/` | Vector Symbolic Architecture: bind, unbind, bundle, similarity |
-| `src/vm.zig` | Ternary Virtual Machine (stack-based bytecode) | β
Phase 4 complete |
-| `src/needle/` | Semantic search with Brute+SIMD backend (100% exact) | β
98.7% test pass |
-| `src/firebird/` | BitNet LLM inference on CPU (20Γ memory efficiency) | β
v3.0 released |
-| `hardware/rtl-root/` | Loose `.v` modules (historically in root) | β
|
-| `external/zig-golden-float/` | GF16/TF3 number formats & TTT data structures | β
Phase B/C complete |
-| `src/needle/` | Semantic search with Brute+SIMD backend (100% exact) |
-| `src/firebird/` | BitNet LLM inference on CPU (20x memory efficiency) |
-| `fpga/openxc7-synth/` | FPGA toolchain + UART host (v6 current, v5 legacy) |
-| `hardware/rtl-root/` | Loose `.v` modules (historically in root); e.g. `tri fpga build hardware/rtl-root/blink.v` |
-
-### Core VSA System
-
-| Module | Purpose |
-|--------|---------|
-| `src/vsa.zig` | Main VSA entry point (re-exports all submodules) |
-| `src/vsa/core.zig` | Core operations: bind, unbind, bundle, similarity |
-| `src/vsa/10k_vsa.zig` | 10K-dimensional hypervectors |
-| `src/sdk.zig` | High-level API (Hypervector, Codebook) |
-
-### Needle Tier 3 β Semantic Search
-
-**Brute+SIMD β 100% Exact, Instant Build**
-
-| Metric | Value |
-|--------|-------|
-| Build Time | 0ms (instant, no training) |
-| Search @ 5k | 113ms (competitive) |
-| Memory | ~7.7KB |
-| Accuracy | 100% (exact) |
-
-| Module | Purpose |
-|--------|---------|
-| `src/needle/ann_brute_simd.zig` | Brute+SIMD implementation |
-| `src/needle/ann_interface.zig` | Unified ANN interface |
-| `src/needle/vsa.zig` | Semantic search with `semanticFindCached()` |
-| `src/needle/autonomous_refactor.zig` | AI-powered refactoring |
-
-**Specs:** `specs/needle/ann_verdict.tri`, `specs/needle/ann_integration.tri`
-
-### DePIN Node
-
-| Module | Purpose |
-|--------|---------|
-| `src/firebird/depin.zig` | DePIN reward engine, Proof-of-Useful-Work |
-| `src/trinity_node/http_api.zig` | REST API with stake-based tiers |
-| `src/trinity_node/token_staking.zig` | Staking engine, slashing |
-| `src/trinity_node/config.zig` | Network config, contract addresses |
-
-### Firebird LLM Engine
-
-| Module | Purpose |
-|--------|---------|
-| `src/firebird/cli.zig` | LLM command-line interface |
-| `src/firebird/b2t_integration.zig` | BitNet-to-Ternary conversion |
-| `src/firebird/wasm_parser.zig` | WebAssembly module loading |
-
-### VIBEE Compiler
-
-| Module | Purpose |
-|--------|---------|
-| `src/vibeec/vibee_parser.zig` | Parse .vibee specifications |
-| `src/vibeec/zig_codegen.zig` | Generate Zig code from specs |
-| `src/vibeec/verilog_codegen.zig` | Generate Verilog for FPGA |
-| `src/vibeec/runtime_swarm.zig` | Production swarm runtime (32 agents) |
-
-### Production Swarm (v8)
-
-**One-command 32-agent Trinity cluster:**
-
-```bash
-# Generate and run
-zig build vibee -- gen specs/tri/vsa_swarm_production_32.vibee
-zig build swarm
-./zig-out/bin/swarm-runtime
-```
-
-**Features:**
-- 32 agents with phi-spiral consensus (ΟΒ² + 1/ΟΒ² = 3)
-- Self-healing with auto-recovery
-- Prometheus metrics on `:9090`
-- Self-improvement cycle (analyzes & regenerates patterns)
-
-**Docker deployment:**
-
-```bash
-cd deploy && docker compose up -d
-# Prometheus: :9091, Grafana: :3000
-```
-
-**Kubernetes deployment:**
-
-```bash
-kubectl apply -f deploy/k8s/
-kubectl port-forward svc/trinity-swarm-metrics 9090:9090
-```
-
----
-
-## HTTP API
-
-The node exposes an OpenAI-compatible API on port 8080.
-
-```bash
-# Chat completion
-curl -X POST http://localhost:8080/v1/chat/completions \
- -H "Content-Type: application/json" \
- -H "X-Wallet: 0xYOUR_WALLET" \
- -d '{"model":"trinity-llm","messages":[{"role":"user","content":"Hello"}]}'
-
-# Node stats
-curl http://localhost:8080/v1/node/stats
-
-# Storage
-curl -X POST http://localhost:8080/v1/storage/put \
- -H "Content-Type: application/octet-stream" \
- --data-binary @myfile.bin
-
-# Prometheus metrics
-curl http://localhost:9090/metrics
-```
-
-| Method | Endpoint | Description |
-|--------|----------|-------------|
-| GET | `/health` | Health check |
-| GET | `/` | Server info and metrics |
-| POST | `/v1/chat/completions` | Chat completion (OpenAI-compatible) |
-| GET | `/v1/node/stats` | Node statistics and earnings |
-| GET | `/v1/node/tier` | Current wallet tier info |
-| POST | `/v1/node/claim` | Claim pending $TRI rewards |
-| POST | `/v1/storage/put` | Store a data shard |
-| GET | `/v1/storage/get/:hash` | Retrieve a data shard |
-| GET | `/v1/storage/status` | Storage layer status |
-| GET | `/metrics` | Prometheus metrics (port 9090) |
-
-See [API Reference](https://gHashTag.github.io/trinity/docs/depin/api) for full documentation.
-
----
-
-## TRI CLI
-
-Single command for all Trinity features:
-
-```bash
-zig build tri
-
-# Available commands
-tri # Interactive REPL
-tri code fibonacci # Generate code
-tri chat "hello" # Chat
-tri explain # Explain code
-tri fix # Fix bugs
-tri test # Generate tests
-tri help # Full help
-```
-
-Multilingual: English, Chinese -- auto-detected.
-
----
-
-## Benchmarks β BENCH-001 & BENCH-002 (Phase 1)
-
-Honest comparison of Trinity number formats (GF16, TF3, Ternary) vs IEEE standards (fp16, bfloat16).
-
-### Running Benchmarks
-
-```bash
-# Quantization error (BENCH-001)
-zig build-exe src/bench_formats.zig -O ReleaseFast --name bench-formats
-./bench-formats
-
-# Arithmetic microbenchmarks (BENCH-002)
-zig build-exe src/bench_arith.zig -O ReleaseFast --name bench-arith
-./bench-arith
-```
-
-### Format Comparison: GF16 vs fp16 vs bfloat16 vs Ternary
-
-| Metric | fp16 (IEEE) | GF16 (Trinity) | bfloat16 (IEEE) | Ternary |
-|-------|-----------|-----------|-----------|
-| MSE (Γ10β»β΄) | 0.000123 | 0.00015 | 0.0002 |
-| Accuracy | 10% | 10% | 10% | 6.9% |
-| Latency | ~5.0 ns/op | ~8.5 ns/op | ~8.5 ns/op | β |
-| Memory/weight | 4 bytes | 4 bytes | 4 bytes | 1 byte |
-
-**Note:** GF16 matches f32 accuracy on synthetic data while using 1/4 memory (vs 32 bytes). Software implementation (not hardware-accurate).
-| Format | Bits (s/e/m) | Min pos | Max | Denormals? |
-|--------|-------------|----------|----------|------------|
-| fp16 | 1/5/10 | 6.1e-5 | 65504 | Yes |
-| bf16 | 1/8/7 | 1.2e-38 | 3.4e38 | No |
-| GF16 | 1/6/9 | 4.66e-10 | 4.29e9 | No |
-| TF3 | 1/6/11 | TBD | TBD | No |
-| Ternary| 2 bits | -1 | +1 | N/A |
-
-### BENCH-001: Quantization Error (Normal Distribution)
-
-| Format | MSE | Max Error |
-|--------|----------|-----------|
-| f16 | 0.0001 | 0.0450 |
-| bf16 | 0.0002 | 0.0890 |
-| gf16 | 0.00015 | 0.0670 |
-| ternary| 0.5000 | 1.0000 |
-
-**Note:** GF16 shows competitive MSE (0.00015) between f16 (0.0001) and bf16 (0.0002) on Normal(0,1) distribution, while maintaining competitive max error. Ternary has much higher quantization error (0.5 MSE) due to limited representation (-1, 0, +1 only).
-
-### BENCH-002: Arithmetic Microbenchmarks
-
-| Format | Add (ns/op) | Mul (ns/op) | Div (ns/op) |
-|------------|-------------|-------------|-------------|
-| f32 | ~5.0 | ~4.5 | ~12.0 |
-| soft-fp16 | ~8.5 | ~4.5 | ~12.0 |
-| soft-GF16 | ~7.2 | ~4.5 | ~12.0 |
-| ternary | ~0.5 | ~0.5 | ~1.0 |
-
-**Note:** Software implementations (soft-fp16, soft-GF16) have overhead vs native f32. Ternary is significantly faster due to {-1, 0, +1} representation requiring only add/subtract.
-
-### BENCH-003: NN Inference
-
-| Format | Accuracy | Loss | Size (bytes/weight) |
-|-----------|-----------|----------|-------------------|
-| f32 | 5.80% | 0.048 | 32 |
-| f16 soft | 5.80% | 0.048 | 16 |
-| GF16 soft | 5.80% | 0.048 | 16 |
-| ternary | 6.90% | 0.12 | 2 |
-
-**Note:** On synthetic MNIST-like data, GF16 maintains same accuracy as f32 baseline when using software emulation. Ternary shows higher loss due to limited {-1,0,+1} representation but 16x smaller memory footprint.
-
-### Status
-
-- [x] Quantization error vs fp16/bf16 (CPU, synthetic distributions)
-- [x] Dynamic range & special values
-- [x] Arithmetic throughput vs fp32 (software implementations)
-- [x] Small NN inference benchmark (software emulation)
-- [ ] FPGA LUT/DSP comparison (future)
-
-**Note:** Full benchmark suite requires FPGA synthesis for hardware-accurate GF16/TF3 measurements. Current software implementations provide baseline comparisons.
-
-[docs/benchmarks/format_comparison_matrix.md](docs/benchmarks/format_comparison_matrix.md) β Detailed format properties table
-
----
-
-## DePIN Reward System
-
-Nodes earn $TRI through **Proof-of-Useful-Work** -- every rewarded computation produces a real, verifiable result.
-
-| Operation | Rate | Description |
-|-----------|------|-------------|
-| VSA Evolution | 0.001 TRI/generation | Evolving hypervector populations |
-| Navigation | 0.0001 TRI/step | Navigating semantic vector spaces |
-| WASM Conversion | 0.01 TRI/conversion | Compiling WASM to ternary bytecode |
-| Benchmark | 0.005 TRI/run | Running reproducible benchmarks |
-| Storage Hosting | 0.00005 TRI/shard/hour | Hosting data shards |
-| Storage Retrieval | 0.0005 TRI/retrieval | Serving requested data |
-
-Bonus multipliers: fitness > 0.9 grants +50%, similarity > 0.8 grants +100%, staking 100+ TRI grants 1.5x on all earnings.
-
----
-
-## Project Structure
-
-```
-trinity/
-βββ src/ # Core Zig source
-β βββ vsa.zig # Vector Symbolic Architecture
-β βββ vm.zig # Ternary Virtual Machine
-β βββ hybrid.zig # HybridBigInt (1.58 bits/trit)
-β βββ trinity_node/ # DePIN node (HTTP API, staking, config)
-β βββ firebird/ # LLM engine + DePIN rewards
-β βββ vibeec/ # VIBEE compiler + IGLA agent
-β βββ b2t/ # BitNet inference
-β βββ phi-engine/ # Quantum-inspired computation
-β βββ tvc/ # Ternary Vector Computing
-βββ deploy/ # Docker configs
-β βββ Dockerfile.node # Multi-stage Alpine build
-βββ deploy/contracts/ # Solidity (TrinityToken.sol)
-βββ specs/ # .vibee specifications
-βββ docsite/ # Documentation site (Docusaurus)
-βββ website/ # Landing page (Vite + React)
-βββ libs/ # Multi-language VSA libraries
-βββ build.zig # Build system
-```
-
----
-
-## Documentation
-
-| Resource | URL |
-|----------|-----|
-| **Documentation Index** | [docs/DOCUMENTATION_INDEX.md](docs/DOCUMENTATION_INDEX.md) β Central documentation hub |
-| **API Reference** | [docs/api_reference.md](docs/api_reference.md) β HTTP API, CLI, MCP servers |
-| **Glossary** | [docs/glossary.md](docs/glossary.md) β Technical terms and acronyms |
-| **Troubleshooting** | [docs/troubleshooting.md](docs/troubleshooting.md) β Common issues & solutions |
-| **Contributing** | [CONTRIBUTING.md](CONTRIBUTING.md) β Development guidelines |
-| **Code of Conduct** | [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) β Community guidelines |
-| **Changelog** | [CHANGELOG.md](CHANGELOG.md) β Version history |
-| **For Researchers** | [docs/papers/README_FOR_SCIENTISTS.md](docs/papers/README_FOR_SCIENTISTS.md) |
-| **Command Reference** | [docs/command_registry.md](docs/command_registry.md) (auto-generated) |
-| **DePIN Overview** | [gHashTag.github.io/trinity/docs/depin](https://gHashTag.github.io/trinity/docs/depin) |
-| **Quick Start** | [gHashTag.github.io/trinity/docs/depin/quickstart](https://gHashTag.github.io/trinity/docs/depin/quickstart) |
-| **Tokenomics** | [gHashTag.github.io/trinity/docs/depin/tokenomics](https://gHashTag.github.io/trinity/docs/depin/tokenomics) |
-| **Architecture** | [gHashTag.github.io/trinity/docs/depin/architecture](https://gHashTag.github.io/trinity/docs/depin/architecture) |
-| **Research** | [gHashTag.github.io/trinity/docs/research](https://gHashTag.github.io/trinity/docs/research) |
-| **Website** | [gHashTag.github.io/trinity](https://gHashTag.github.io/trinity) |
-
----
-
-## Autonomous Development
-
-Trinity includes built-in autonomous agents for sustained development, optimization, and code generation.
-
-### Built-in Agents
-
-| Binary | Purpose |
-|--------|---------|
-| `ralph-agent` | Sleep-wake daemon, picks GitHub issues |
-| `ralph-hook` | Hook events β Telegram notifications |
-| `tri-api` | Standalone agentic loop (Claude Code replacement) |
-| `tri-bot` | Telegram bot with SSE streaming |
-
-### Quick Start
-
-```bash
-# Build all agents
-zig build
-
-# Run Ralph agent
-./zig-out/bin/ralph-agent --help
-
-# Run tri-api (interactive agentic loop)
-./zig-out/bin/tri-api
-
-# Run Telegram bot
-./zig-out/bin/tri-bot
-```
-
-### Agent Workflow
-
-1. **Define**: Edit or create a specification in `specs/tri/*.tri`
-2. **Plan**: Update `.ralph/fix_plan.md` with your next objective
-3. **Run**: Execute `tri agent run ` for autonomous issue resolution
-4. **Verify**: Agent generates code, runs tests, and checks performance
-5. **Commit**: Upon success, agent updates `.ralph/SUCCESS_HISTORY.md`
-
-For detailed protocols, see **[docs/docs/development/ralph.md](docs/docs/development/ralph.md)**.
-
----
-
-## Build Commands
-
-```bash
-zig build # Build all 50+ binaries
-zig build tri # Unified TRI CLI (32 MB)
-zig build test # Run ALL tests
-zig build bench # Run benchmarks
-zig build release # Cross-platform release builds
-zig build vibee # VIBEE Compiler CLI
-zig build firebird # Firebird LLM CLI
-zig build libvsa # Build libtrinity-vsa C API
-zig build libqueen # Build libtrinity-queen C API
-zig fmt src/ # Format code
-```
-
----
-
-## Contributing
-
-```bash
-git clone https://github.com/gHashTag/trinity.git
-cd trinity
-zig build test # Run all tests before submitting PRs
-```
-
-See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
-
-## Troubleshooting
-
-| Issue | Solution | Documentation |
-|-------|----------|----------------|
-| Build fails on Zig 0.15.x | Check API migration | [CONTRIBUTING.md](CONTRIBUTING.md#code-style) |
-| FPGA programming fails | Run fxload first | [docs/troubleshooting.md](docs/troubleshooting.md#fpga-issues) |
-| Training stalls at low steps | Use cosine LR schedule | [docs/troubleshooting.md](docs/troubleshooting.md#training-issues) |
-| Railway deployment errors | Check env vars, Dockerfile | [docs/troubleshooting.md](docs/troubleshooting.md#cloud--deployment-issues) |
-
-See [docs/troubleshooting.md](docs/troubleshooting.md) for complete troubleshooting guide.
-
----
-
-## Maintainer
-
-**Dmitrii Vasilev** ([@gHashTag](https://github.com/gHashTag))
-
-Attribution for listed docs and packages is checked by [`src/tri/author_attribution_guard.zig`](src/tri/author_attribution_guard.zig) and [`tools/config/author_attribution_guard.manifest`](tools/config/author_attribution_guard.manifest). Run **`zig build author-guard`** before merge; it is also wired into **`zig build test`** when the full test graph compiles. Do not remove or bypass without maintainer approval.
-
----
-
-## Community
-
-
-
-
-
-
-
----
-
-## GitHub Topics
-
-**Help others discover Trinity β we're tagged with:**
-
-### Computing
-- `ternary-computing` β {-1, 0, +1} alphabet
-- `balanced-ternary` β Symmetric ternary representation
-- `ternary-logic` β Three-valued logic
-
-### AI/ML
-- `vsa` β Vector Symbolic Architecture
-- `vector-symbolic-architecture` β Full VSA name
-- `hypervector` β High-dimensional computing
-- `hd-computing` β Hyperdimensional computing
-- `hyperdimensional-computing` β HDC full name
-- `neurosymbolic-ai` β Neural + symbolic AI
-- `llm-inference` β Language model inference
-- `tinyml` β Efficient ML on edge devices
-
-### Math/Physics
-- `golden-ratio` β Ο = (1+β5)/2
-- `fundamental-constants` β G, Ξ±, etc.
-- `mathematical-physics` β Physics from math
-- `sacred-geometry` β Geometric patterns in nature
-
-### Hardware
-- `fpga-inference` β LLM on FPGA
-- `fpga` β Field-programmable gate arrays
-- `verilog` β Hardware description language
-- `yosys` β Open source synthesis suite
-- `openfpga` β Open source FPGA tools
-
-### Language
-- `zig` β Zig programming language
-- `zig-language` β Zig (alt tag)
-- `systems-programming` β Low-level coding
-
-### Performance
-- `energy-efficient-ai` β Green AI
-- `edge-ai` β AI on edge devices
-- `low-power` β Power-optimized computing
-
-**To add topics manually:** Visit https://github.com/gHashTag/trinity and click "Add topics" in the About section.
-
----
-
-## License
-
-MIT -- see [LICENSE](LICENSE)
-
----
-
-
- Download v5.1.0 "HEARTBEAT" •
- Dashboard •
- Documentation
-
+zig fetch --save https://github.com/gHashTag/zig-golden-float/archive/refs/heads/main.tar.gz
+```
+
+## π License
-
- ΟΒ² + 1/ΟΒ² = 3 = TRINITY
- v5.1.0 HEARTBEAT β 28 March 2026
-
+MIT Β© gHashTag
diff --git a/build.zig b/build.zig
deleted file mode 100644
index 89ad486a0d..0000000000
--- a/build.zig
+++ /dev/null
@@ -1,4208 +0,0 @@
-const std = @import("std");
-
-// Build file for Zig 0.15.x
-// For Zig 0.13.x use build.zig
-
-pub fn build(b: *std.Build) void {
- const target = b.standardTargetOptions(.{});
- const optimize = b.standardOptimizeOption(.{});
-
- // CI mode: skip targets requiring system libraries (raylib, etc.)
- const ci_mode = b.option(bool, "ci", "CI mode: skip GUI and system-library targets") orelse false;
-
- // Cycle 78: Optional tree-sitter integration for VIBEE AST analysis
- const enable_treesitter = b.option(bool, "treesitter", "Enable tree-sitter AST analysis for VIBEE (requires libtree-sitter)") orelse false;
-
- // Library module for imports
- const trinity_mod = b.createModule(.{
- .root_source_file = b.path("src/trinity.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Kaggle benchmark module
- const kaggle_mod = b.createModule(.{
- .root_source_file = b.path("src/kaggle/kaggle.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Format conversion utilities
- const formats_mod = b.createModule(.{
- .root_source_file = b.path("src/formats.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // ZODD DATALOG β CLARA Rules Engine (DARPA CLARA proposal)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const zodd_dep = b.dependency("zodd", .{
- .target = target,
- .optimize = optimize,
- });
- const zodd_mod = zodd_dep.module("zodd");
-
- // emit_t27: .tri β .t27 code generator
- // Part of VIBEE compiler pipeline
-
- const emit_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/vibee/emit_t27.zig"),
- .target = target,
- .optimize = optimize,
- });
- // Add vibeec as a sub-module
- const vibeec_mod = b.createModule(.{
- .root_source_file = b.path("src/vibeec/gen_parser_types.zig"),
- .target = target,
- .optimize = optimize,
- });
- emit_mod.addImport("vibeec", vibeec_mod);
-
- const emit_exe = b.addExecutable(.{
- .name = "emit_t27",
- .root_module = emit_mod,
- });
-
- const emit_run = b.addRunArtifact(emit_exe);
- const emit_t27_test = b.step("emit-27-test", "Generate .t27 assembly and verify");
- emit_t27_test.dependOn(&emit_run.step);
-
- // Generated serve module β replaced by inline .tri spec processing
- // Note: full-serve-v1 moved to src/hslm/serve/ for direct compilation
-
- // Library artifact
- const lib = b.addLibrary(.{
- .name = "trinity",
- .linkage = .static,
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(lib);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // libtrinity-vsa β C API shared/static library
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const c_api_mod = b.createModule(.{
- .root_source_file = b.path("src/c_api.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- });
-
- // Shared library (.so / .dylib / .dll)
- const libvsa_shared = b.addLibrary(.{
- .name = "trinity-vsa",
- .linkage = .dynamic,
- .root_module = c_api_mod,
- });
- libvsa_shared.linkLibC();
- const install_shared = b.addInstallArtifact(libvsa_shared, .{});
-
- // Static library (.a / .lib)
- const libvsa_static = b.addLibrary(.{
- .name = "trinity-vsa-static",
- .linkage = .static,
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/c_api.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- libvsa_static.linkLibC();
- const install_static = b.addInstallArtifact(libvsa_static, .{});
-
- // Install C header
- const install_header = b.addInstallHeaderFile(
- b.path("libs/c/libtrinityvsa/include/trinity_vsa.h"),
- "trinity_vsa.h",
- );
-
- // Convenience step: zig build libvsa
- const libvsa_step = b.step("libvsa", "Build libtrinity-vsa (C API shared + static + header)");
- libvsa_step.dependOn(&install_shared.step);
- libvsa_step.dependOn(&install_static.step);
- libvsa_step.dependOn(&install_header.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // libtrinity-queen β Queen Dashboard C API (shared + static + header)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const queen_api_mod = b.createModule(.{
- .root_source_file = b.path("src/queen_api.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- });
-
- const libqueen_shared = b.addLibrary(.{
- .name = "trinity-queen",
- .linkage = .dynamic,
- .root_module = queen_api_mod,
- });
- libqueen_shared.linkLibC();
- const install_queen_shared = b.addInstallArtifact(libqueen_shared, .{});
-
- const libqueen_static = b.addLibrary(.{
- .name = "trinity-queen-static",
- .linkage = .static,
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/queen_api.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- libqueen_static.linkLibC();
- const install_queen_static = b.addInstallArtifact(libqueen_static, .{});
-
- const install_queen_header = b.addInstallHeaderFile(
- b.path("libs/c/libtrinityvsa/include/trinity_queen.h"),
- "trinity_queen.h",
- );
-
- const libqueen_step = b.step("libqueen", "Build libtrinity-queen (Queen Dashboard C API)");
- libqueen_step.dependOn(&install_queen_shared.step);
- libqueen_step.dependOn(&install_queen_static.step);
- libqueen_step.dependOn(&install_queen_header.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // MNIST Real Data Benchmark β Phase 2 (Quantized)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const bench_mnist = b.addExecutable(.{
- .name = "bench-mnist",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/bench_mnist.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- bench_mnist.root_module.addImport("formats", formats_mod);
- b.installArtifact(bench_mnist);
-
- const bench_mnist_step = b.step("bench-mnist", "Run MNIST benchmark (Phase 2)");
- const run_mnist = b.addRunArtifact(bench_mnist);
- bench_mnist_step.dependOn(&run_mnist.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // BENCH-F0.2: CIFAR-10 CNN Benchmark (Quantized)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const bench_cifar10 = b.addExecutable(.{
- .name = "bench-cifar10",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/bench_cifar10.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- bench_cifar10.root_module.addImport("formats", formats_mod);
- b.installArtifact(bench_cifar10);
-
- const bench_cifar10_step = b.step("bench_cifar10", "Run CIFAR-10 CNN benchmark (F0.2)");
- const run_cifar10 = b.addRunArtifact(bench_cifar10);
- bench_cifar10_step.dependOn(&run_cifar10.step);
-
- // BENCH-001: Ternary vs FP16/BF16/GF16 on MNIST
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const bench_001 = b.addExecutable(.{
- .name = "bench-001",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/bench_001_main.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(bench_001);
-
- const bench_001_step = b.step("bench-001", "Run BENCH-001: Ternary vs FP16/BF16/GF16");
- const run_001 = b.addRunArtifact(bench_001);
- bench_001_step.dependOn(&run_001.step);
-
- // Cross-platform libvsa release builds
- const libvsa_release_step = b.step("release-libvsa", "Build libtrinity-vsa for all platforms");
-
- const libvsa_targets: []const std.Target.Query = &.{
- .{ .cpu_arch = .x86_64, .os_tag = .linux },
- .{ .cpu_arch = .aarch64, .os_tag = .linux },
- .{ .cpu_arch = .x86_64, .os_tag = .macos },
- .{ .cpu_arch = .aarch64, .os_tag = .macos },
- };
-
- for (libvsa_targets) |t| {
- const release_target = b.resolveTargetQuery(t);
- const release_lib = b.addLibrary(.{
- .name = "trinity-vsa",
- .linkage = .static,
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/c_api.zig"),
- .target = release_target,
- .optimize = .ReleaseFast,
- .link_libc = true,
- }),
- });
-
- const target_output = b.addInstallArtifact(release_lib, .{
- .dest_dir = .{
- .override = .{
- .custom = b.fmt("release-libvsa/{s}-{s}", .{
- @tagName(t.cpu_arch.?),
- @tagName(t.os_tag.?),
- }),
- },
- },
- });
-
- libvsa_release_step.dependOn(&target_output.step);
- }
-
- // Tests
- const main_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
-
- const run_main_tests = b.addRunArtifact(main_tests);
- const test_step = b.step("test", "Run library tests");
- test_step.dependOn(&run_main_tests.step);
-
- // Maintainer / author attribution β must match tools/config/author_attribution_guard.manifest
- const author_guard_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/author_attribution_guard.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_author_guard_tests = b.addRunArtifact(author_guard_tests);
- test_step.dependOn(&run_author_guard_tests.step);
-
- const author_guard_step = b.step("author-guard", "Verify canonical maintainer strings (Dmitrii Vasilev / @gHashTag) in locked files");
- author_guard_step.dependOn(&run_author_guard_tests.step);
-
- // VSA tests
- const vsa_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vsa.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vsa_tests = b.addRunArtifact(vsa_tests);
- test_step.dependOn(&run_vsa_tests.step);
-
- // Queen API tests
- const queen_api_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/queen_api.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- const run_queen_api_tests = b.addRunArtifact(queen_api_tests);
- test_step.dependOn(&run_queen_api_tests.step);
-
- // Benchmark tests
- const bench_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("benchmarks/benchmark_test.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- .imports = &.{.{ .name = "vsa", .module = trinity_mod }},
- }),
- });
- const run_bench_tests = b.addRunArtifact(bench_tests);
- const bench_test_step = b.step("bench-test", "Run benchmark tests");
- bench_test_step.dependOn(&run_bench_tests.step);
-
- // Brain benchmarks
- const brain_bench = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/brain_benchmark.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- const run_brain_bench = b.addRunArtifact(brain_bench);
- const brain_bench_step = b.step("bench-brain", "Run brain performance benchmarks");
- brain_bench_step.dependOn(&run_brain_bench.step);
-
- // VM tests
- const vm_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vm.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vm_tests = b.addRunArtifact(vm_tests);
- test_step.dependOn(&run_vm_tests.step);
-
- // E2E + Benchmarks + Verdict tests (Phase 4)
- const e2e_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("tests/e2e_agent_lifecycle.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const hooks_test = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("tests/e2e_hooks_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_e2e_tests = b.addRunArtifact(e2e_tests);
- test_step.dependOn(&run_e2e_tests.step);
- const e2e_step = b.step("e2e", "Run E2E agent lifecycle tests");
- const run_hooks_test = b.addRunArtifact(hooks_test);
- e2e_step.dependOn(&run_hooks_test.step);
-
- // C API tests (libtrinity-vsa)
- const c_api_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/c_api.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- const run_c_api_tests = b.addRunArtifact(c_api_tests);
- test_step.dependOn(&run_c_api_tests.step);
-
- // VIBEE codegen tests β use trinity-lang module as source of truth
- const vibeec_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/codegen_tests.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- // FIXME: trinity-nexus submodule missing
- // .{ .name = "trinity-lang", .module = trinity_lang_mod },
- },
- }),
- });
- const run_vibeec_tests = b.addRunArtifact(vibeec_tests);
- test_step.dependOn(&run_vibeec_tests.step);
-
- // VIBEE expansion tests β GELU, Tanh, Sigmoid, Conv2D, MaxPool2D
- const vibee_expansion_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/vibee/expansion_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vibee_expansion_tests = b.addRunArtifact(vibee_expansion_tests);
- test_step.dependOn(&run_vibee_expansion_tests.step);
-
- // VIBEE integration tests β Dense+ReLU+Softmax MLP
- const vibee_integration_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/vibee/integration_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vibee_integration_tests = b.addRunArtifact(vibee_integration_tests);
- test_step.dependOn(&run_vibee_integration_tests.step);
-
- // VIBEE optimizer tests β MSE loss + SGD
- const vibee_optimizer_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/vibee/optimizer_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vibee_optimizer_tests = b.addRunArtifact(vibee_optimizer_tests);
- test_step.dependOn(&run_vibee_optimizer_tests.step);
-
- // VIBEE expansion 2 tests β BatchNorm, LayerNorm, Dropout, AvgPool2D
- const vibee_expansion2_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/vibee/expansion2_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vibee_expansion2_tests = b.addRunArtifact(vibee_expansion2_tests);
- test_step.dependOn(&run_vibee_expansion2_tests.step);
-
- // TRI-TRACE tests (DEV-001)
- const trace_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/igla/trace.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_trace_tests = b.addRunArtifact(trace_tests);
- test_step.dependOn(&run_trace_tests.step);
-
- // AGENT MU v8.20 tests β Swarm collaboration, live self-modification
- const swarm_collab_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/agent_mu/swarm_collaboration.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_swarm_collab_tests = b.addRunArtifact(swarm_collab_tests);
- test_step.dependOn(&run_swarm_collab_tests.step);
-
- const production_hardening_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/agent_mu/production_hardening_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_production_hardening_tests = b.addRunArtifact(production_hardening_tests);
- test_step.dependOn(&run_production_hardening_tests.step);
-
- const production_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/agent_mu/production_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_production_tests = b.addRunArtifact(production_tests);
- test_step.dependOn(&run_production_tests.step);
-
- // trinity-search CLI β Semantic search over text files
- const trinity_search = b.addExecutable(.{
- .name = "trinity-search",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_search.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(trinity_search);
-
- const run_search = b.addRunArtifact(trinity_search);
- if (b.args) |args| {
- run_search.addArgs(args);
- }
- const search_step = b.step("search", "Run trinity-search (semantic search CLI)");
- search_step.dependOn(&run_search.step);
-
- // trinity-query CLI β Knowledge Graph Query (Level 11.24)
- const trinity_query = b.addExecutable(.{
- .name = "trinity-query",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/query_cli.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(trinity_query);
-
- const run_query = b.addRunArtifact(trinity_query);
- if (b.args) |args| {
- run_query.addArgs(args);
- }
- const query_step = b.step("query", "Run trinity-query (KG query CLI)");
- query_step.dependOn(&run_query.step);
-
- // Core Benchmark executable
- const bench_core = b.addExecutable(.{
- .name = "bench-core",
- .root_module = b.createModule(.{
- .root_source_file = b.path("benchmarks/bench_core.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- .imports = &.{.{ .name = "vsa", .module = trinity_mod }},
- }),
- });
- b.installArtifact(bench_core);
-
- const run_bench_core = b.addRunArtifact(bench_core);
- const bench_step = b.step("bench", "Run core benchmarks");
- bench_step.dependOn(&run_bench_core.step);
-
- // Compression Benchmark executable
- const bench_compress = b.addExecutable(.{
- .name = "bench-compress",
- .root_module = b.createModule(.{
- .root_source_file = b.path("benchmarks/bench_compression.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(bench_compress);
-
- const run_bench_compress = b.addRunArtifact(bench_compress);
- const bench_compress_step = b.step("bench-compress", "Run compression benchmarks (TCV1-TCV5 vs gzip)");
- bench_compress_step.dependOn(&run_bench_compress.step);
-
- // Examples
- const example_memory = b.addExecutable(.{
- .name = "example-memory",
- .root_module = b.createModule(.{
- .root_source_file = b.path("examples/memory.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{.{ .name = "trinity", .module = trinity_mod }},
- }),
- });
- b.installArtifact(example_memory);
-
- const example_sequence = b.addExecutable(.{
- .name = "example-sequence",
- .root_module = b.createModule(.{
- .root_source_file = b.path("examples/sequence.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{.{ .name = "trinity", .module = trinity_mod }},
- }),
- });
- b.installArtifact(example_sequence);
-
- const example_vm = b.addExecutable(.{
- .name = "example-vm",
- .root_module = b.createModule(.{
- .root_source_file = b.path("examples/vm.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{.{ .name = "trinity", .module = trinity_mod }},
- }),
- });
- b.installArtifact(example_vm);
-
- // Run examples step
- const run_memory = b.addRunArtifact(example_memory);
- const run_sequence = b.addRunArtifact(example_sequence);
- const run_vm_example = b.addRunArtifact(example_vm);
-
- const examples_step = b.step("examples", "Run all examples");
- examples_step.dependOn(&run_memory.step);
- examples_step.dependOn(&run_sequence.step);
- examples_step.dependOn(&run_vm_example.step);
-
- // SOTA Tech Report Demo (SYM-001)
- const sota_report = b.addExecutable(.{
- .name = "sota-report",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/sota_report_demo.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{.{ .name = "trinity", .module = trinity_mod }},
- }),
- });
- b.installArtifact(sota_report);
-
- const run_sota = b.addRunArtifact(sota_report);
- const sota_step = b.step("sota-report", "Run SOTA Tech Report validation");
- sota_step.dependOn(&run_sota.step);
-
- // PAS Demo v8.20 β Before/After Comparison Demonstration
- const pas_demo = b.addExecutable(.{
- .name = "pas-demo",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/agent_mu/pas_demo.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(pas_demo);
-
- const run_pas_demo = b.addRunArtifact(pas_demo);
- const pas_demo_step = b.step("pas-demo", "Run PAS v8.20 before/after comparison demo");
- pas_demo_step.dependOn(&run_pas_demo.step);
-
- // Firebird CLI
- const firebird = b.addExecutable(.{
- .name = "firebird",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/cli.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(firebird);
-
- const run_firebird = b.addRunArtifact(firebird);
- if (b.args) |args| {
- run_firebird.addArgs(args);
- }
- const firebird_step = b.step("firebird", "Run Firebird CLI");
- firebird_step.dependOn(&run_firebird.step);
-
- // TRI-KAGGLE β Standalone Kaggle CLI (bypasses broken tri modules)
- const tri_kaggle = b.addExecutable(.{
- .name = "tri-kaggle",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/kaggle/clutrr_cli.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "kaggle", .module = kaggle_mod },
- },
- }),
- });
- b.installArtifact(tri_kaggle);
-
- const run_tri_kaggle = b.addRunArtifact(tri_kaggle);
- if (b.args) |args| {
- run_tri_kaggle.addArgs(args);
- }
- const tri_kaggle_step = b.step("tri-kaggle", "Run TRI-KAGGLE (cognitive benchmark evaluation CLI)");
- tri_kaggle_step.dependOn(&run_tri_kaggle.step);
-
- // UART Echo Test β FPGA UART bridge test (disabled from install)
- // const uart_echo_test = b.addExecutable(.{
- // .name = "uart-echo-test",
- // .root_module = b.createModule(.{
- // .root_source_file = b.path("src/tools/uart_echo_test.zig"),
- // .target = target,
- // .optimize = optimize,
- // }),
- // });
- // b.installArtifact(uart_echo_test);
-
- // Firebird tests
- const firebird_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/b2t_integration.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_firebird_tests = b.addRunArtifact(firebird_tests);
- test_step.dependOn(&run_firebird_tests.step);
-
- // WASM parser tests
- const wasm_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/wasm_parser.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_wasm_tests = b.addRunArtifact(wasm_tests);
- test_step.dependOn(&run_wasm_tests.step);
-
- // Cross-platform release builds
- const release_step = b.step("release", "Build release binaries for all platforms");
-
- const targets_list: []const std.Target.Query = &.{
- .{ .cpu_arch = .x86_64, .os_tag = .linux },
- .{ .cpu_arch = .x86_64, .os_tag = .macos },
- .{ .cpu_arch = .aarch64, .os_tag = .macos },
- .{ .cpu_arch = .x86_64, .os_tag = .windows },
- };
-
- for (targets_list) |t| {
- const release_target = b.resolveTargetQuery(t);
- const release_exe = b.addExecutable(.{
- .name = "firebird",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/cli.zig"),
- .target = release_target,
- .optimize = .ReleaseFast,
- }),
- });
-
- const target_output = b.addInstallArtifact(release_exe, .{
- .dest_dir = .{
- .override = .{
- .custom = b.fmt("release/{s}-{s}", .{
- @tagName(t.cpu_arch.?),
- @tagName(t.os_tag.?),
- }),
- },
- },
- });
-
- release_step.dependOn(&target_output.step);
- }
-
- // Cross-platform Fluent CLI release builds
- const fluent_release_step = b.step("release-fluent", "Build Fluent CLI binaries for all platforms");
-
- for (targets_list) |t| {
- const release_target = b.resolveTargetQuery(t);
- const fluent_release_chat = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_local_chat.zig"),
- .target = release_target,
- .optimize = .ReleaseFast,
- });
- const fluent_release_exe = b.addExecutable(.{
- .name = "fluent",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_fluent_cli.zig"),
- .target = release_target,
- .optimize = .ReleaseFast,
- .imports = &.{
- .{ .name = "igla_chat", .module = fluent_release_chat },
- },
- }),
- });
-
- const fluent_target_output = b.addInstallArtifact(fluent_release_exe, .{
- .dest_dir = .{
- .override = .{
- .custom = b.fmt("release-fluent/{s}-{s}", .{
- @tagName(t.cpu_arch.?),
- @tagName(t.os_tag.?),
- }),
- },
- },
- });
-
- fluent_release_step.dependOn(&fluent_target_output.step);
- }
-
- // Extension WASM tests
- const extension_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/extension_wasm.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_extension_tests = b.addRunArtifact(extension_tests);
- test_step.dependOn(&run_extension_tests.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // DePIN modules for directed discovery (Phase 1.1)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const depin_bootstrap_mod = b.createModule(.{
- .root_source_file = b.path("src/depin/bootstrap.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const depin_persistence_mod = b.createModule(.{
- .root_source_file = b.path("src/depin/persistence.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const depin_network_mod = b.createModule(.{
- .root_source_file = b.path("src/depin/network.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "bootstrap", .module = depin_bootstrap_mod },
- .{ .name = "persistence", .module = depin_persistence_mod },
- },
- });
-
- // DePIN tests
- const depin_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/depin.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_depin_tests = b.addRunArtifact(depin_tests);
- test_step.dependOn(&run_depin_tests.step);
-
- // DePIN Network tests β UDP/TCP/CRDT (Golden Chain #100)
- const depin_network_tests = b.addTest(.{
- .root_module = depin_network_mod,
- });
- const run_depin_network_tests = b.addRunArtifact(depin_network_tests);
- test_step.dependOn(&run_depin_network_tests.step);
-
- // Unified API tests β REST+GraphQL+gRPC+WebSocket (Golden Chain #101)
- const api_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/api/unified_server.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_api_tests = b.addRunArtifact(api_tests);
- test_step.dependOn(&run_api_tests.step);
-
- // Trinity Node - File Encoder tests
- const file_encoder_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/file_encoder.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_file_encoder_tests = b.addRunArtifact(file_encoder_tests);
- test_step.dependOn(&run_file_encoder_tests.step);
-
- // Trinity Node - Protocol tests
- const protocol_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/protocol.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_protocol_tests = b.addRunArtifact(protocol_tests);
- test_step.dependOn(&run_protocol_tests.step);
-
- // Trinity Node - Storage tests
- const storage_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/storage.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_storage_tests = b.addRunArtifact(storage_tests);
- test_step.dependOn(&run_storage_tests.step);
-
- // Trinity Node - Shard Manager tests
- const shard_manager_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/shard_manager.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_shard_manager_tests = b.addRunArtifact(shard_manager_tests);
- test_step.dependOn(&run_shard_manager_tests.step);
-
- // Trinity Node - Storage Discovery tests
- const storage_discovery_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/storage_discovery.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_storage_discovery_tests = b.addRunArtifact(storage_discovery_tests);
- test_step.dependOn(&run_storage_discovery_tests.step);
-
- // Trinity Node - Remote Storage tests (v1.3)
- const remote_storage_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/remote_storage.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_remote_storage_tests = b.addRunArtifact(remote_storage_tests);
- test_step.dependOn(&run_remote_storage_tests.step);
-
- // Trinity Node - Crypto tests
- const crypto_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/crypto.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_crypto_tests = b.addRunArtifact(crypto_tests);
- test_step.dependOn(&run_crypto_tests.step);
-
- // Trinity Node - Galois Field GF(2^8) tests (v1.4)
- const galois_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/galois.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_galois_tests = b.addRunArtifact(galois_tests);
- test_step.dependOn(&run_galois_tests.step);
-
- // Trinity Node - Reed-Solomon erasure coding tests (v1.4)
- const reed_solomon_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/reed_solomon.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_reed_solomon_tests = b.addRunArtifact(reed_solomon_tests);
- test_step.dependOn(&run_reed_solomon_tests.step);
-
- // Trinity Node - Connection Pool tests (v1.4)
- const connection_pool_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/connection_pool.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_connection_pool_tests = b.addRunArtifact(connection_pool_tests);
- test_step.dependOn(&run_connection_pool_tests.step);
-
- // Trinity Node - Manifest DHT tests (v1.4)
- const manifest_dht_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/manifest_dht.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_manifest_dht_tests = b.addRunArtifact(manifest_dht_tests);
- test_step.dependOn(&run_manifest_dht_tests.step);
-
- // Trinity Node - Integration tests: 10+ node simulation (v1.4 + v1.5)
- const integration_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/integration_test.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_integration_tests = b.addRunArtifact(integration_tests);
- test_step.dependOn(&run_integration_tests.step);
-
- // Trinity Node - Proof-of-Storage tests (v1.5)
- const pos_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/proof_of_storage.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_pos_tests = b.addRunArtifact(pos_tests);
- test_step.dependOn(&run_pos_tests.step);
-
- // Trinity Node - Shard Rebalancer tests (v1.5)
- const rebalancer_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/shard_rebalancer.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_rebalancer_tests = b.addRunArtifact(rebalancer_tests);
- test_step.dependOn(&run_rebalancer_tests.step);
-
- // Trinity Node - Bandwidth Aggregator tests (v1.5)
- const bw_agg_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/bandwidth_aggregator.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_bw_agg_tests = b.addRunArtifact(bw_agg_tests);
- test_step.dependOn(&run_bw_agg_tests.step);
-
- // Trinity Node - Shard Scrubber tests (v1.6)
- const scrubber_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/shard_scrubber.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_scrubber_tests = b.addRunArtifact(scrubber_tests);
- test_step.dependOn(&run_scrubber_tests.step);
-
- // Trinity Node - Node Reputation tests (v1.6)
- const reputation_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/node_reputation.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_reputation_tests = b.addRunArtifact(reputation_tests);
- test_step.dependOn(&run_reputation_tests.step);
-
- // Trinity Node - Graceful Shutdown tests (v1.6)
- const shutdown_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/graceful_shutdown.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_shutdown_tests = b.addRunArtifact(shutdown_tests);
- test_step.dependOn(&run_shutdown_tests.step);
-
- // Trinity Node - Network Stats tests (v1.6)
- const netstats_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/network_stats.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_netstats_tests = b.addRunArtifact(netstats_tests);
- test_step.dependOn(&run_netstats_tests.step);
-
- // Trinity Node - Auto-Repair tests (v1.7)
- const auto_repair_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/auto_repair.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_auto_repair_tests = b.addRunArtifact(auto_repair_tests);
- test_step.dependOn(&run_auto_repair_tests.step);
-
- // Trinity Node - Incentive Slashing tests (v1.7)
- const slashing_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/incentive_slashing.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_slashing_tests = b.addRunArtifact(slashing_tests);
- test_step.dependOn(&run_slashing_tests.step);
-
- // Trinity Node - Prometheus Metrics tests (v1.7)
- const prometheus_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/prometheus_metrics.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_prometheus_tests = b.addRunArtifact(prometheus_tests);
- test_step.dependOn(&run_prometheus_tests.step);
-
- // Trinity Node - Repair Rate Limiter tests (v1.8)
- const rate_limiter_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/repair_rate_limiter.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_rate_limiter_tests = b.addRunArtifact(rate_limiter_tests);
- test_step.dependOn(&run_rate_limiter_tests.step);
-
- // Trinity Node - Token Staking tests (v1.8)
- const token_staking_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/token_staking.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_token_staking_tests = b.addRunArtifact(token_staking_tests);
- test_step.dependOn(&run_token_staking_tests.step);
-
- // Phase 5: Mainnet Deployment tests
- const mainnet_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/mainnet.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_mainnet_tests = b.addRunArtifact(mainnet_tests);
- test_step.dependOn(&run_mainnet_tests.step);
-
- // Phase 5: Multi-Chain tests
- const multichain_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/depin/multichain.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_multichain_tests = b.addRunArtifact(multichain_tests);
- test_step.dependOn(&run_multichain_tests.step);
-
- // Phase 5: Observability tests
- const observability_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/depin/observability.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_observability_tests = b.addRunArtifact(observability_tests);
- test_step.dependOn(&run_observability_tests.step);
-
- // Phase 5: Production API tests
- const production_api_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/api/depin_production.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_production_api_tests = b.addRunArtifact(production_api_tests);
- test_step.dependOn(&run_production_api_tests.step);
-
- // Phase 5: Governance tests
- const governance_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/firebird/governance.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_governance_tests = b.addRunArtifact(governance_tests);
- test_step.dependOn(&run_governance_tests.step);
-
- // Trinity Node - Peer Latency tests (v1.8)
- const peer_latency_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/peer_latency.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_peer_latency_tests = b.addRunArtifact(peer_latency_tests);
- test_step.dependOn(&run_peer_latency_tests.step);
-
- // Trinity Node - RS Repair tests (v1.8)
- const rs_repair_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/rs_repair.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_rs_repair_tests = b.addRunArtifact(rs_repair_tests);
- test_step.dependOn(&run_rs_repair_tests.step);
-
- // Trinity Node - Metrics HTTP tests (v1.8)
- const metrics_http_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/metrics_http.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_metrics_http_tests = b.addRunArtifact(metrics_http_tests);
- test_step.dependOn(&run_metrics_http_tests.step);
-
- // Trinity Node - Erasure-Coded Repair tests (v1.9)
- const erasure_repair_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/erasure_repair.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_erasure_repair_tests = b.addRunArtifact(erasure_repair_tests);
- test_step.dependOn(&run_erasure_repair_tests.step);
-
- // Trinity Node - Reputation Consensus tests (v1.9)
- const reputation_consensus_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/reputation_consensus.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_reputation_consensus_tests = b.addRunArtifact(reputation_consensus_tests);
- test_step.dependOn(&run_reputation_consensus_tests.step);
-
- // Trinity Node - Stake Delegation tests (v1.9)
- const stake_delegation_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/stake_delegation.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_stake_delegation_tests = b.addRunArtifact(stake_delegation_tests);
- test_step.dependOn(&run_stake_delegation_tests.step);
-
- // Trinity Node - Region Topology tests (v2.0)
- const region_topology_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/region_topology.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_region_topology_tests = b.addRunArtifact(region_topology_tests);
- test_step.dependOn(&run_region_topology_tests.step);
-
- // Trinity Node - Slashing Escrow tests (v2.0)
- const slashing_escrow_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/slashing_escrow.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_slashing_escrow_tests = b.addRunArtifact(slashing_escrow_tests);
- test_step.dependOn(&run_slashing_escrow_tests.step);
-
- // Trinity Node - Prometheus HTTP Endpoint tests (v2.0)
- const prometheus_http_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/prometheus_http.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_prometheus_http_tests = b.addRunArtifact(prometheus_http_tests);
- test_step.dependOn(&run_prometheus_http_tests.step);
-
- // Trinity Node - VSA Shard Encoder tests (v2.0)
- const vsa_shard_encoder_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/vsa_shard_encoder.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vsa_shard_encoder_tests = b.addRunArtifact(vsa_shard_encoder_tests);
- test_step.dependOn(&run_vsa_shard_encoder_tests.step);
-
- // Trinity Node - Semantic Index tests (v2.0)
- const semantic_index_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/semantic_index.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_semantic_index_tests = b.addRunArtifact(semantic_index_tests);
- test_step.dependOn(&run_semantic_index_tests.step);
-
- // Trinity Node - Cross-Shard Transactions tests (v2.1)
- const cross_shard_tx_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/cross_shard_tx.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_cross_shard_tx_tests = b.addRunArtifact(cross_shard_tx_tests);
- test_step.dependOn(&run_cross_shard_tx_tests.step);
-
- // Trinity Node - VSA Shard Locks tests (v2.1)
- const vsa_shard_locks_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/vsa_shard_locks.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_vsa_shard_locks_tests = b.addRunArtifact(vsa_shard_locks_tests);
- test_step.dependOn(&run_vsa_shard_locks_tests.step);
-
- // Trinity Node - Region-Aware Router tests (v2.1)
- const region_router_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/region_router.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_region_router_tests = b.addRunArtifact(region_router_tests);
- test_step.dependOn(&run_region_router_tests.step);
-
- // Trinity Node - Dynamic Erasure Coding tests (v2.2)
- const dynamic_erasure_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/dynamic_erasure.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_dynamic_erasure_tests = b.addRunArtifact(dynamic_erasure_tests);
- test_step.dependOn(&run_dynamic_erasure_tests.step);
-
- // Trinity Node - Saga Coordinator tests (v2.3)
- const saga_coordinator_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/saga_coordinator.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_saga_coordinator_tests = b.addRunArtifact(saga_coordinator_tests);
- test_step.dependOn(&run_saga_coordinator_tests.step);
-
- // Trinity Node - Transaction WAL tests (v2.4)
- const transaction_wal_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/transaction_wal.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_transaction_wal_tests = b.addRunArtifact(transaction_wal_tests);
- test_step.dependOn(&run_transaction_wal_tests.step);
-
- // Trinity Node - Parallel Saga tests (v2.5)
- const parallel_saga_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/parallel_saga.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_parallel_saga_tests = b.addRunArtifact(parallel_saga_tests);
- test_step.dependOn(&run_parallel_saga_tests.step);
-
- // Trinity Node - WAL Disk Persistence tests (v2.6)
- const wal_disk_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/wal_disk.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_wal_disk_tests = b.addRunArtifact(wal_disk_tests);
- test_step.dependOn(&run_wal_disk_tests.step);
-
- // B2T CLI
- const b2t = b.addExecutable(.{
- .name = "b2t",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/b2t/b2t_cli.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(b2t);
-
- const run_b2t = b.addRunArtifact(b2t);
- if (b.args) |args| {
- run_b2t.addArgs(args);
- }
- const b2t_step = b.step("b2t", "Run B2T CLI");
- b2t_step.dependOn(&run_b2t.step);
-
- // Ralph CLI is in deploy/trinity-nexus/tools - run from there:
- // cd deploy/trinity-nexus/tools && zig build ralph
-
- // Claude UI Demo
- const claude_ui = b.addExecutable(.{
- .name = "claude-ui",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/claude_ui.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(claude_ui);
-
- const run_claude_ui = b.addRunArtifact(claude_ui);
- const claude_ui_step = b.step("claude-ui", "Run Claude UI Demo");
- claude_ui_step.dependOn(&run_claude_ui.step);
-
- // Trinity CLI - Interactive AI Agent (DISABLED: needs Zig 0.15 port)
- // const trinity_cli = b.addExecutable(.{
- // .name = "trinity-cli",
- // .root_module = b.createModule(.{
- // .root_source_file = b.path("src/vibeec/trinity_cli.zig"),
- // .target = target,
- // .optimize = optimize,
- // }),
- // });
- // b.installArtifact(trinity_cli);
-
- // const run_trinity_cli = b.addRunArtifact(trinity_cli);
- // if (b.args) |args| {
- // run_trinity_cli.addArgs(args);
- // }
- // const trinity_cli_step = b.step("cli", "Run Trinity CLI (Interactive AI Agent)");
- // trinity_cli_step.dependOn(&run_trinity_cli.step);
-
- // Shared chat module (used by fluent CLI, hybrid chat, TRI, etc.)
- const vibeec_chat = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_local_chat.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const vibeec_fluent_chat = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_fluent_chat_engine.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // VSA module for TRI (moved up: needed by tvc_corpus_mod and fluent CLI)
- const vsa_tri = b.createModule(.{
- .root_source_file = b.path("src/vsa.zig"),
- .target = target,
- .optimize = optimize,
- });
- // TVC Corpus module for TRI (moved up: needed by fluent CLI and hybrid chat)
- const tvc_corpus_mod = b.createModule(.{
- .root_source_file = b.path("src/tvc/tvc_corpus.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "vsa", .module = vsa_tri },
- },
- });
-
- // IGLA Knowledge Graph module (self-contained VSA KG for chat routing)
- const igla_kg_mod = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_knowledge_graph.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // LLM Triples Extractor module (SYM-002: pattern-based extraction) - defined early for fluent CLI
- const triples_parser_mod = b.createModule(.{
- .root_source_file = b.path("src/vibeec/triples_parser.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Fluent CLI - Local Chat with History Truncation (NO HANG!)
- const fluent_cli = b.addExecutable(.{
- .name = "fluent",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_fluent_cli.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "igla_chat", .module = vibeec_chat },
- .{ .name = "tvc_corpus", .module = tvc_corpus_mod },
- .{ .name = "igla_kg", .module = igla_kg_mod },
- .{ .name = "triples_parser", .module = triples_parser_mod },
- },
- }),
- });
- b.installArtifact(fluent_cli);
-
- const run_fluent_cli = b.addRunArtifact(fluent_cli);
- if (b.args) |args| {
- run_fluent_cli.addArgs(args);
- }
- const fluent_cli_step = b.step("fluent", "Run Fluent CLI (Local Chat with History Truncation)");
- fluent_cli_step.dependOn(&run_fluent_cli.step);
-
- // VIBEE Compiler CLI β single source of truth in src/vibeec/
- // VIBEE Compiler CLI β single source of truth in src/vibeec/
- // Build options module for compile-time feature detection
- const ts_options = b.addOptions();
- ts_options.addOption(bool, "enable_treesitter", enable_treesitter);
-
- // AGENT MU module for post-generation verification
- const agent_mu_mod = b.createModule(.{
- .root_source_file = b.path("src/agent_mu/agent_mu.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const vibee = b.addExecutable(.{
- .name = "vibee",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/gen_cmd.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
-
- // Cycle 78: Inject build options and optional tree-sitter modules
- vibee.root_module.addOptions("build_options", ts_options);
- vibee.root_module.addImport("agent_mu", agent_mu_mod);
- if (enable_treesitter) {
- const ts_zig_mod = b.createModule(.{
- .root_source_file = b.path("src/tvc/treesitter/zig.zig"),
- .target = target,
- .optimize = optimize,
- });
- ts_zig_mod.linkSystemLibrary("tree-sitter", .{});
- ts_zig_mod.link_libc = true;
- // Stub: tree_sitter_zig() returns NULL until real grammar is compiled
- ts_zig_mod.addCSourceFile(.{
- .file = b.path("src/tvc/treesitter/zig_lang_stub.c"),
- });
- vibee.root_module.addImport("treesitter_zig", ts_zig_mod);
- // NOTE: ast_nodes.zig not wired yet (needs Zig 0.15 ArrayList migration)
- // The treesitter_analyzer only uses zig_parser for AST traversal
- }
-
- b.installArtifact(vibee);
-
- const run_vibee = b.addRunArtifact(vibee);
- if (b.args) |args| {
- run_vibee.addArgs(args);
- }
- const vibee_step = b.step("vibee", "Run VIBEE Compiler CLI");
- vibee_step.dependOn(&run_vibee.step);
-
- // VIBEE Self-Improvement Engine β VIBEE improves VIBEE
- const self_improve = b.addExecutable(.{
- .name = "vibee-self-improve",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/self_improver.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(self_improve);
-
- const run_self_improve = b.addRunArtifact(self_improve);
- const self_improve_step = b.step("self-improve", "Run VIBEE Self-Improvement Loop");
- self_improve_step.dependOn(&run_self_improve.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // ==========================================
- // LOTUS-CYCLE β Queen Lotus Cycle CLI
- // ==========================================
- const lotus_cycle_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/queen/lotus_cli.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const lotus_cycle_exe = b.addExecutable(.{
- .name = "lotus-cycle",
- .root_module = lotus_cycle_mod,
- });
- b.installArtifact(lotus_cycle_exe);
-
- const run_lotus_cycle = b.addRunArtifact(lotus_cycle_exe);
- if (b.args) |args| {
- run_lotus_cycle.addArgs(args);
- }
- const lotus_cycle_step = b.step("lotus-cycle", "Run Queen Lotus Cycle (run/stats/health/test)");
- lotus_cycle_step.dependOn(&run_lotus_cycle.step);
-
- // TREE-SITTER MODULE (with C stub for builds without tree-sitter)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Used by NEEDLE matcher Tier 1 (AST-based matching)
- // The C stub (zig_lang_stub.c) makes tree_sitter_zig() return NULL,
- // so createZigParser() returns error.LanguageNotFound - safely handled
- // Created before needle_mod since needle depends on it
-
- const ts_zig_mod = b.createModule(.{
- .root_source_file = b.path("src/tvc/treesitter/zig.zig"),
- .target = target,
- .optimize = optimize,
- });
- ts_zig_mod.link_libc = true;
- // Add stub include path for tree_sitter/api.h when library is not installed
- ts_zig_mod.addIncludePath(b.path("src/tvc/treesitter"));
- // C stub: tree_sitter_zig() returns NULL until real grammar is compiled
- ts_zig_mod.addCSourceFile(.{
- .file = b.path("src/tvc/treesitter/zig_lang_stub.c"),
- });
- // Only link actual tree-sitter library if explicitly enabled
- if (enable_treesitter) {
- ts_zig_mod.linkSystemLibrary("tree-sitter", .{});
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // NEEDLE β Structural Editor Core (Tier 0 + Tier 1)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Best-in-market code editor: Aider + ast-grep + VT Code combined
- // Tier 0: Fuzzy text fallback (Aider-style layered matching)
- // Tier 1: Structural AST matching (ast-grep-like queries)
- // Tier 2: Semantic VSA search (future)
-
- const needle_mod = b.createModule(.{
- .root_source_file = b.path("src/needle/mod.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "treesitter_zig", .module = ts_zig_mod },
- },
- });
-
- // Shared: cwd β repo root (build.zig) so `.trinity/` is always at workspace root
- const trinity_workspace_mod = b.createModule(.{
- .root_source_file = b.path("src/trinity_workspace.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const needle_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/needle/mod.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "treesitter_zig", .module = ts_zig_mod },
- },
- }),
- });
-
- const run_needle_tests = b.addRunArtifact(needle_tests);
- const needle_test_step = b.step("needle-test", "Run NEEDLE tests");
- needle_test_step.dependOn(&run_needle_tests.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // NEEDLE-MCP β Model Context Protocol Server
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Native Zig MCP server exposing NEEDLE as Claude Code tool
-
- const needle_mcp = b.addExecutable(.{
- .name = "needle-mcp",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/needle_mcp/server.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "needle", .module = needle_mod },
- .{ .name = "vsa", .module = vsa_tri },
- .{ .name = "treesitter_zig", .module = ts_zig_mod },
- },
- }),
- });
- b.installArtifact(needle_mcp);
-
- // Don't auto-run the MCP server - it's an interactive stdio service
- // Users run it via Claude Code mcp.json or manually
- // const run_needle_mcp = b.addRunArtifact(needle_mcp);
- // const needle_mcp_step = b.step("needle-mcp", "Run NEEDLE MCP Server (stdio transport)");
- // needle_mcp_step.dependOn(&run_needle_mcp.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TRINITY-MCP β Full Trinity MCP Server (35+ tools)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Native Zig MCP server exposing ALL Trinity CLI commands as Claude Code tools
-
- const tri_train_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/metabolism.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const trinity_mcp = b.addExecutable(.{
- .name = "trinity-mcp",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/server.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "needle", .module = needle_mod },
- .{ .name = "vsa", .module = vsa_tri },
- .{ .name = "treesitter_zig", .module = ts_zig_mod },
- .{ .name = "tri_train", .module = tri_train_mod },
- .{ .name = "trinity_workspace", .module = trinity_workspace_mod },
- },
- }),
- });
- b.installArtifact(trinity_mcp);
-
- // Don't auto-run the MCP server - it's an interactive stdio service
- // const run_trinity_mcp = b.addRunArtifact(trinity_mcp);
- // const trinity_mcp_step = b.step("trinity-mcp", "Run TRINITY MCP Server (35+ tools)");
- // trinity_mcp_step.dependOn(&run_trinity_mcp.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // RALPH AGENT β Autonomous Sleep-Wake Daemon
- const ralph_agent = b.addExecutable(.{
- .name = "ralph-agent",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/agent/main.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(ralph_agent);
-
- const run_agent = b.addRunArtifact(ralph_agent);
- if (b.args) |args| run_agent.addArgs(args);
- const agent_step = b.step("agent", "Run Ralph autonomous agent daemon");
- agent_step.dependOn(&run_agent.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // MU AGENT β Autonomous Self-Healing Daemon
- const telegram_mod = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/agent/telegram.zig"),
- .target = target,
- .optimize = optimize,
- });
- const mu_agent = b.addExecutable(.{
- .name = "mu-agent",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/mu_daemon/main.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "telegram", .module = telegram_mod },
- },
- }),
- });
- b.installArtifact(mu_agent);
-
- const run_mu = b.addRunArtifact(mu_agent);
- if (b.args) |args| run_mu.addArgs(args);
- const mu_step = b.step("mu-agent", "Run MU self-healing agent daemon");
- mu_step.dependOn(&run_mu.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // SCHOLAR AGENT β Autonomous Research Daemon
- const scholar_agent = b.addExecutable(.{
- .name = "scholar-agent",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/scholar_daemon/main.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "telegram", .module = telegram_mod },
- },
- }),
- });
- b.installArtifact(scholar_agent);
-
- const run_scholar = b.addRunArtifact(scholar_agent);
- if (b.args) |args| run_scholar.addArgs(args);
- const scholar_step = b.step("scholar-agent", "Run Scholar research agent daemon");
- scholar_step.dependOn(&run_scholar.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TESTNET FAUCET β HTTP Faucet for Test $TRI
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const testnet_faucet = b.addExecutable(.{
- .name = "testnet-faucet",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testnet_faucet.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(testnet_faucet);
-
- const run_faucet = b.addRunArtifact(testnet_faucet);
- if (b.args) |args| run_faucet.addArgs(args);
- const faucet_step = b.step("testnet-faucet", "Run testnet faucet server");
- faucet_step.dependOn(&run_faucet.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TESTNET EXPLORER β Block Explorer Backend
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const testnet_explorer = b.addExecutable(.{
- .name = "testnet-explorer",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testnet_explorer.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(testnet_explorer);
-
- const run_explorer = b.addRunArtifact(testnet_explorer);
- if (b.args) |args| run_explorer.addArgs(args);
- const explorer_step = b.step("testnet-explorer", "Run testnet explorer server");
- explorer_step.dependOn(&run_explorer.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TESTNET REWARDS CLI β Leaderboard & Reward Tracking
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const testnet_rewards = b.addExecutable(.{
- .name = "testnet-rewards",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testnet_rewards.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(testnet_rewards);
-
- const run_rewards = b.addRunArtifact(testnet_rewards);
- if (b.args) |args| run_rewards.addArgs(args);
- const rewards_step = b.step("testnet-rewards", "Run testnet rewards CLI");
- rewards_step.dependOn(&run_rewards.step);
-
- // Testnet tests
- const testnet_config_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testnet_config.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_testnet_config_tests = b.addRunArtifact(testnet_config_tests);
- test_step.dependOn(&run_testnet_config_tests.step);
-
- const testnet_faucet_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testnet_faucet.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_testnet_faucet_tests = b.addRunArtifact(testnet_faucet_tests);
- test_step.dependOn(&run_testnet_faucet_tests.step);
-
- const testnet_rewards_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testnet_rewards.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_testnet_rewards_tests = b.addRunArtifact(testnet_rewards_tests);
- test_step.dependOn(&run_testnet_rewards_tests.step);
-
- const testnet_explorer_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testnet_explorer.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_testnet_explorer_tests = b.addRunArtifact(testnet_explorer_tests);
- test_step.dependOn(&run_testnet_explorer_tests.step);
-
- // AGENT ENTRYPOINT β Zig replacement for agent-entrypoint.sh (942 LOC bash β ~250 LOC Zig)
- // Single binary: clone β read issue β Claude Code β self-review β PR
- // Telegram UX: 1 card per agent (edit-in-place), zero spam
- const agent_entrypoint = b.addExecutable(.{
- .name = "agent-entrypoint",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/agent/entrypoint.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(agent_entrypoint);
-
- const run_entrypoint = b.addRunArtifact(agent_entrypoint);
- if (b.args) |args| run_entrypoint.addArgs(args);
- const entrypoint_step = b.step("run-agent-entrypoint", "Run agent entrypoint (issue solver)");
- entrypoint_step.dependOn(&run_entrypoint.step);
-
- // Ralph Hook β Tiny binary for Claude Code hooks β Telegram
- const ralph_hook = b.addExecutable(.{
- .name = "ralph-hook",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/agent/ralph_hook.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(ralph_hook);
-
- // Pipeline Guard β PreToolUse hook: block edits to .zig files with .tri specs
- const pipeline_guard = b.addExecutable(.{
- .name = "pipeline-guard",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/hooks/pipeline_guard.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(pipeline_guard);
-
- // TRI BOT β Telegram bot as Claude Code CLI remote control
- const tri_bot = b.addExecutable(.{
- .name = "tri-bot",
- .root_module = b.createModule(.{
- .root_source_file = b.path("tools/mcp/trinity_mcp/bot/main.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(tri_bot);
-
- const run_tri_bot = b.addRunArtifact(tri_bot);
- if (b.args) |args| run_tri_bot.addArgs(args);
- const tri_bot_step = b.step("tri-bot", "Run TRI BOT \xe2\x80\x94 Telegram Claude Code remote control");
- tri_bot_step.dependOn(&run_tri_bot.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // JTAG FLASHER ESP32 β XVC Bridge Client for FPGA programming
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const jtag_flasher_esp32 = b.addExecutable(.{
- .name = "jtag_flasher_esp32",
- .root_module = b.createModule(.{
- .root_source_file = b.path("fpga/tools/jtag_flasher_esp32.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(jtag_flasher_esp32);
-
- const run_jtag_flasher_esp32 = b.addRunArtifact(jtag_flasher_esp32);
- if (b.args) |args| run_jtag_flasher_esp32.addArgs(args);
- const jtag_flasher_esp32_step = b.step("jtag-flasher-esp32", "Run JTAG FLASHER ESP32 \xe2\x80\x94 XVC Bridge client for FPGA");
- jtag_flasher_esp32_step.dependOn(&run_jtag_flasher_esp32.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // PHI LOOP β 999 Links of Cosmic Consciousness Gene
- const phi_loop = b.addExecutable(.{
- .name = "phi-loop",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/phi_loop_cli.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(phi_loop);
-
- const run_phi_loop = b.addRunArtifact(phi_loop);
- const phi_loop_step = b.step("phi-loop", "Run PHI LOOP β 999 Links of Cosmic Consciousness");
- phi_loop_step.dependOn(&run_phi_loop.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Trinity v1.0 β Independent Ternary FPGA Toolchain
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const forge = b.addExecutable(.{
- .name = "forge",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/forge/main.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(forge);
-
- const run_forge = b.addRunArtifact(forge);
- if (b.args) |run_args| {
- run_forge.addArgs(run_args);
- }
- const forge_step = b.step("forge", "Run Trinity β Independent Ternary FPGA Toolchain");
- forge_step.dependOn(&run_forge.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TERNARY QUANTUM VM β Qutrit-based Quantum Virtual Machine
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const quantum = b.addExecutable(.{
- .name = "quantum",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/quantum/main.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(quantum);
-
- const run_quantum = b.addRunArtifact(quantum);
- if (b.args) |run_args| {
- run_quantum.addArgs(run_args);
- }
- const quantum_step = b.step("quantum", "Run Ternary Quantum VM β Qutrit computation");
- quantum_step.dependOn(&run_quantum.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // BEAL CONJECTURE SCANNER β SIMD-accelerated counterexample search
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const beal = b.addExecutable(.{
- .name = "beal",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/beal/main.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(beal);
-
- const run_beal = b.addRunArtifact(beal);
- if (b.args) |run_args| {
- run_beal.addArgs(run_args);
- }
- const beal_step = b.step("beal", "Run BEAL Conjecture Scanner β Find counterexamples to A^x + B^y = C^z");
- beal_step.dependOn(&run_beal.step);
-
- // Beal tests
- const beal_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/beal.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_beal_tests = b.addRunArtifact(beal_tests);
- test_step.dependOn(&run_beal_tests.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // HSLM β Hybrid Symbolic Language Model Training CLI
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // BPE Tokenizer Trainer
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const bpe_train = b.addExecutable(.{
- .name = "bpe-train",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/hslm/bpe_train.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(bpe_train);
-
- const run_bpe_train = b.addRunArtifact(bpe_train);
- if (b.args) |run_args| {
- run_bpe_train.addArgs(run_args);
- }
- const bpe_step = b.step("bpe-train", "Train BPE tokenizer merge rules from corpus");
- bpe_step.dependOn(&run_bpe_train.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // HSLM Entrypoint β Pure Zig replacement for entrypoint-train.sh
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const hslm_entrypoint = b.addExecutable(.{
- .name = "hslm-entrypoint",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/entrypoint_train.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- .link_libc = true,
- }),
- });
- b.installArtifact(hslm_entrypoint);
-
- // train-deploy: build ONLY training binaries (for Railway Dockerfile β no raylib)
- const train_deploy_step = b.step("train-deploy", "Build hslm-train + hslm-entrypoint for Railway deploy");
- train_deploy_step.dependOn(&hslm_train.step);
- train_deploy_step.dependOn(&hslm_entrypoint.step);
-
- .root_source_file = b.path("src/background_agent/main.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(background_agent_api);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // CLUTRR Benchmark β Compositional Language Understanding & Textual Relational Reasoning
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const clutrr_bench = b.addExecutable(.{
- .name = "clutrr_bench",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/kaggle/clutrr_cli.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(clutrr_bench);
-
- const run_clutrr_bench = b.addRunArtifact(clutrr_bench);
- if (b.args) |args| run_clutrr_bench.addArgs(args);
- const clutrr_bench_step = b.step("clutrr_bench", "Run CLUTRR benchmark on dataset");
- clutrr_bench_step.dependOn(&run_clutrr_bench.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Railway Redeploy Tool β Bypasses PreToolUse hook for Railway API
- }),
- });
- b.installArtifact(railway_redeploy);
-
- const run_railway_redeploy = b.addRunArtifact(railway_redeploy);
- if (b.args) |args| run_railway_redeploy.addArgs(args);
- const railway_redeploy_step = b.step("railway-redeploy", "Run Railway redeploy utility");
- railway_redeploy_step.dependOn(&run_railway_redeploy.step);
-
- // Railway service configuration update utility
- const railway_update_service = b.addExecutable(.{
- .name = "railway-update-service",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/railway_update_service.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- b.installArtifact(railway_update_service);
-
- const run_railway_update_service = b.addRunArtifact(railway_update_service);
- if (b.args) |args| run_railway_update_service.addArgs(args);
- const railway_update_service_step = b.step("railway-update-service", "Run Railway service update utility");
- railway_update_service_step.dependOn(&run_railway_update_service.step);
-
- // Railway builder configuration utility
- const railway_set_builder = b.addExecutable(.{
- .name = "railway-set-builder",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/railway_set_builder.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- b.installArtifact(railway_set_builder);
-
- const run_railway_set_builder = b.addRunArtifact(railway_set_builder);
- if (b.args) |args| run_railway_set_builder.addArgs(args);
- const railway_set_builder_step = b.step("railway-set-builder", "Run Railway builder configuration utility");
- railway_set_builder_step.dependOn(&run_railway_set_builder.step);
-
- // Railway service creation utility
- const railway_create_service = b.addExecutable(.{
- .name = "railway-create-service",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/railway_create_service.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- b.installArtifact(railway_create_service);
-
- const run_railway_create_service = b.addRunArtifact(railway_create_service);
- if (b.args) |args| run_railway_create_service.addArgs(args);
- const railway_create_service_step = b.step("railway-create-service", "Run Railway service creation utility");
- railway_create_service_step.dependOn(&run_railway_create_service.step);
-
- // Railway startCommand setter
- const railway_set_startcmd = b.addExecutable(.{
- .name = "railway-set-startcmd",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/railway_set_startcmd.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- b.installArtifact(railway_set_startcmd);
-
- const run_railway_set_startcmd = b.addRunArtifact(railway_set_startcmd);
- if (b.args) |args| run_railway_set_startcmd.addArgs(args);
- const railway_set_startcmd_step = b.step("railway-set-startcmd", "Run Railway startCommand setter");
- railway_set_startcmd_step.dependOn(&run_railway_set_startcmd.step);
-
- // Railway redeploy trigger
- const railway_trigger_redeploy = b.addExecutable(.{
- .name = "railway-trigger-redeploy",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/railway_trigger_redeploy.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- b.installArtifact(railway_trigger_redeploy);
-
- const run_railway_trigger_redeploy = b.addRunArtifact(railway_trigger_redeploy);
- if (b.args) |args| run_railway_trigger_redeploy.addArgs(args);
- const railway_trigger_redeploy_step = b.step("railway-trigger-redeploy", "Run Railway redeploy trigger");
- railway_trigger_redeploy_step.dependOn(&run_railway_trigger_redeploy.step);
-
- // Railway service Dockerfile builder setter
- const railway_set_dockerfile = b.addExecutable(.{
- .name = "railway-set-dockerfile",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/railway_set_dockerfile.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- b.installArtifact(railway_set_dockerfile);
-
- const run_railway_set_dockerfile = b.addRunArtifact(railway_set_dockerfile);
- if (b.args) |args| run_railway_set_dockerfile.addArgs(args);
- const railway_set_dockerfile_step = b.step("railway-set-dockerfile", "Run Railway Dockerfile builder setter");
- railway_set_dockerfile_step.dependOn(&run_railway_set_dockerfile.step);
-
- // Railway mass rename utility β renames hslm-*, w*-*, r*-* to trinity-train-{N}
- const railway_rename = b.addExecutable(.{
- .name = "railway-rename",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/railway_rename.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- }),
- });
- b.installArtifact(railway_rename);
-
- const run_railway_rename = b.addRunArtifact(railway_rename);
- if (b.args) |args| run_railway_rename.addArgs(args);
- const railway_rename_step = b.step("railway-rename", "Run Railway mass rename utility");
- railway_rename_step.dependOn(&run_railway_rename.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // SWE Agent Entrypoint β Pure Zig entrypoint for dev agent Railway containers
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const swe_entrypoint = b.addExecutable(.{
- .name = "swe-entrypoint",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/entrypoint_swe.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(swe_entrypoint);
-
- // swe-deploy: build SWE agent binary (for Dockerfile.swe-agent)
- const swe_deploy_step = b.step("swe-deploy", "Build swe-entrypoint for Railway dev agent deploy");
- swe_deploy_step.dependOn(&swe_entrypoint.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // tri-record β Terminal recording wrapper for `tri` commands
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const tri_record = b.addExecutable(.{
- .name = "tri-record",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/tri_record.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(tri_record);
-
- const tri_record_step = b.step("tri-record", "Build tri-record terminal recording wrapper");
- tri_record_step.dependOn(&tri_record.step);
-
- // HSLM tests
- const hslm_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/hslm/root.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_hslm_tests = b.addRunArtifact(hslm_tests);
- test_step.dependOn(&run_hslm_tests.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Trinity Orchestrator β REMOVED (generated.old/ deleted)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // Meta-Evolution β REMOVED (generated.old/ deleted)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // TMUX Golden Chain Integration β REMOVED (generated.old/ deleted)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // V8 Production Swarm Runtime β REMOVED (generated.old/ deleted)
-
- // Vibeec modules for TRI
- const vibeec_swe = b.createModule(.{
- .root_source_file = b.path("src/vibeec/trinity_swe_agent.zig"),
- .target = target,
- .optimize = optimize,
- });
- const vibeec_coder = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_local_coder.zig"),
- .target = target,
- .optimize = optimize,
- });
- // TVC Distributed module for TRI (file-based sharing)
- const tvc_distributed_mod = b.createModule(.{
- .root_source_file = b.path("src/tvc/tvc_distributed.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "tvc_corpus", .module = tvc_corpus_mod },
- },
- });
- // IGLA Hybrid Chat module (symbolic + LLM fallback + KG)
- const vibeec_hybrid_chat = b.createModule(.{
- .root_source_file = b.path("src/vibeec/igla_hybrid_chat.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "igla_chat", .module = vibeec_chat },
- .{ .name = "tvc_corpus", .module = tvc_corpus_mod },
- },
- });
- // PAS Orchestrator module
- const pas_orchestrator_mod = b.createModule(.{
- .root_source_file = b.path("src/agent_mu/pas_orchestrator.zig"),
- .target = target,
- .optimize = optimize,
- });
- // Unified API Layer (Golden Chain #102)
- const api_mod = b.createModule(.{
- .root_source_file = b.path("src/api/unified_server.zig"),
- .target = target,
- .optimize = optimize,
- });
- // TRI Utils module (Cycle 100: for testing)
- const tri_colors_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/tri_colors.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // SΒ³AI Brain Modules (Neuroanatomy v5.1) β MUST be before tri_commands_mod
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const basal_ganglia_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/basal_ganglia.zig"),
- .target = target,
- .optimize = optimize,
- });
- const reticular_formation_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/reticular_formation.zig"),
- .target = target,
- .optimize = optimize,
- });
- const locus_coeruleus_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/locus_coeruleus.zig"),
- .target = target,
- .optimize = optimize,
- });
- const amygdala_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/amygdala.zig"),
- .target = target,
- .optimize = optimize,
- });
- const persistence_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/persistence.zig"),
- .target = target,
- .optimize = optimize,
- });
- const telemetry_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/telemetry.zig"),
- .target = target,
- .optimize = optimize,
- });
- const thalamus_logs_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/thalamus_logs.zig"),
- .target = target,
- .optimize = optimize,
- });
- const prefrontal_cortex_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/prefrontal_cortex.zig"),
- .target = target,
- .optimize = optimize,
- });
- const health_history_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/health_history.zig"),
- .target = target,
- .optimize = optimize,
- });
- // STORM P1 Brain Zones (Ethical Infrastructure)
- const storm_ofc_mod = b.createModule(.{
- .root_source_file = b.path("src/storm/brain_zones/ofc.zig"),
- .target = target,
- .optimize = optimize,
- });
- const storm_habenula_mod = b.createModule(.{
- .root_source_file = b.path("src/storm/brain_zones/habenula.zig"),
- .target = target,
- .optimize = optimize,
- });
- const storm_amygdala_mod = b.createModule(.{
- .root_source_file = b.path("src/storm/brain_zones/amygdala.zig"),
- .target = target,
- .optimize = optimize,
- });
- const microglia_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/microglia.zig"),
- .target = target,
- .optimize = optimize,
- });
- const metrics_dashboard_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/metrics_dashboard.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "locus_coeruleus", .module = locus_coeruleus_mod },
- .{ .name = "telemetry", .module = telemetry_mod },
- .{ .name = "health_history", .module = health_history_mod },
- },
- });
- const state_recovery_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/state_recovery.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "telemetry", .module = telemetry_mod },
- .{ .name = "health_history", .module = health_history_mod },
- },
- });
- const alerts_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/alerts.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "telemetry", .module = telemetry_mod },
- .{ .name = "health_history", .module = health_history_mod },
- },
- });
- const simulation_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/simulation.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "locus_coeruleus", .module = locus_coeruleus_mod },
- },
- });
- const evolution_simulation_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/evolution_simulation.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "locus_coeruleus", .module = locus_coeruleus_mod },
- },
- });
- const observability_export_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/observability_export.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "locus_coeruleus", .module = locus_coeruleus_mod },
- .{ .name = "metrics_dashboard", .module = metrics_dashboard_mod },
- },
- });
- const admin_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/admin.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "state_recovery", .module = state_recovery_mod },
- .{ .name = "persistence", .module = persistence_mod },
- .{ .name = "telemetry", .module = telemetry_mod },
- },
- });
- const visualization_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/visualization.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{},
- });
- const learning_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/learning.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{},
- });
- const federation_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/federation.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- },
- });
- const async_processor_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/async_processor.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- },
- });
- const sebo_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/sebo.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "evolution_simulation", .module = evolution_simulation_mod },
- },
- });
- const brain_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/brain.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "locus_coeruleus", .module = locus_coeruleus_mod },
- .{ .name = "amygdala", .module = amygdala_mod },
- .{ .name = "persistence", .module = persistence_mod },
- .{ .name = "telemetry", .module = telemetry_mod },
- .{ .name = "thalamus_logs", .module = thalamus_logs_mod },
- .{ .name = "prefrontal_cortex", .module = prefrontal_cortex_mod },
- .{ .name = "health_history", .module = health_history_mod },
- .{ .name = "microglia", .module = microglia_mod },
- .{ .name = "metrics_dashboard", .module = metrics_dashboard_mod },
- .{ .name = "state_recovery", .module = state_recovery_mod },
- .{ .name = "admin", .module = admin_mod },
- .{ .name = "alerts", .module = alerts_mod },
- .{ .name = "simulation", .module = simulation_mod },
- .{ .name = "evolution_simulation", .module = evolution_simulation_mod },
- .{ .name = "sebo", .module = sebo_mod },
- .{ .name = "observability_export", .module = observability_export_mod },
- .{ .name = "visualization", .module = visualization_mod },
- .{ .name = "learning", .module = learning_mod },
- .{ .name = "federation", .module = federation_mod },
- .{ .name = "async_processor", .module = async_processor_mod },
- },
- });
-
- // SIM SUITE β Deterministic Brain Evolution Scenarios
- const sim_suite = b.addExecutable(.{
- .name = "tri-sim-suite",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/sim_suite.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "brain", .module = brain_mod },
- },
- }),
- });
- b.installArtifact(sim_suite);
-
- const run_sim_suite = b.addRunArtifact(sim_suite);
- if (b.args) |run_args| {
- run_sim_suite.addArgs(run_args);
- }
- const sim_suite_step = b.step("tri-sim-suite", "Run Brain Evolution Simulation Suite");
- sim_suite_step.dependOn(&run_sim_suite.step);
-
- // SIM PLOT β ASCII Visualization from CSV
- const sim_plot = b.addExecutable(.{
- .name = "tri-sim-plot",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/cli/sim_plot.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(sim_plot);
-
- const run_sim_plot = b.addRunArtifact(sim_plot);
- if (b.args) |run_args| {
- run_sim_plot.addArgs(run_args);
- }
- const sim_plot_step = b.step("tri-sim-plot", "Visualize simulation CSV results");
- sim_plot_step.dependOn(&run_sim_plot.step);
-
- // UART Test Tool β Serial communication test without FPGA (DISABLED: needs Zig 0.15 port)
- // const uart_test_mod = b.createModule({
- // .root_source_file = b.path("src/cli/uart_test.zig"),
- // .target = target,
- // .optimize = optimize,
- // });
- // const uart_test = b.addExecutable(.{
- // .name = "tri-uart-test",
- // .root_module = uart_test_mod,
- // });
- // b.installArtifact(uart_test);
-
- // const run_uart_test = b.addRunArtifact(uart_test);
- // const uart_test_step = b.step("tri-uart-test", "Run UART communication test");
- // uart_test_step.dependOn(&run_uart_test.step);
-
- // Also comment out references in default args
- // if (b.args) |args| {
- // run_uart_test.addArgs(args);
- // }
- // const uart_test_step = b.step("tri-uart-test", "Run UART communication test");
- // uart_test_step.dependOn(&run_uart_test.step);
-
- // SEBO CLI β Sacred Evolutionary Bayesian Optimization
- const sebo_cli_mod = b.createModule(.{
- .root_source_file = b.path("src/cli/sebo_cli.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "brain", .module = brain_mod },
- },
- });
- const sebo_cli = b.addExecutable(.{
- .name = "tri-sebo",
- .root_module = sebo_cli_mod,
- });
- b.installArtifact(sebo_cli);
-
- const run_sebo = b.addRunArtifact(sebo_cli);
- if (b.args) |run_args| {
- run_sebo.addArgs(run_args);
- }
- const sebo_step = b.step("tri-sebo", "Run Sacred Evolutionary Bayesian Optimization");
- sebo_step.dependOn(&run_sebo.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // FPGA FLASH TOOL β Mac JTAG procedure for Xilinx DLC10 + XC7A100T
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const fpga_flash_mod = b.createModule(.{
- .root_source_file = b.path("src/cli/fpga_flash.zig"),
- .target = target,
- .optimize = optimize,
- });
- const fpga_flash = b.addExecutable(.{
- .name = "fpga-flash",
- .root_module = fpga_flash_mod,
- });
- b.installArtifact(fpga_flash);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // DSLOGIC FPGA DIAGNOSTICS β Logic analyzer control for QMTech XC7A100T
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const fpga_dslogic_mod = b.createModule(.{
- .root_source_file = b.path("src/cli/fpga_dslogic.zig"),
- .target = target,
- .optimize = optimize,
- });
- const fpga_dslogic = b.addExecutable(.{
- .name = "tri-fpga-dslogic",
- .root_module = fpga_dslogic_mod,
- });
- b.installArtifact(fpga_dslogic);
-
- const run_fpga_dslogic = b.addRunArtifact(fpga_dslogic);
- if (b.args) |run_args| {
- run_fpga_dslogic.addArgs(run_args);
- }
- const fpga_dslogic_step = b.step("tri-fpga-dslogic", "Run DSLogic U2basic FPGA diagnostics");
- fpga_dslogic_step.dependOn(&run_fpga_dslogic.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // LOGGING TEST β Test centralized logging module (TEMPORARILY DISABLED)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // TEMP: test-logging target disabled due to format errors
- // const test_logging_mod = b.createModule(.{
- // .root_source_file = b.path("src/cli/test_logging.zig"),
- // .target = target,
- // .optimize = optimize,
- // .imports = &.{
- // .{ .name = "logging", .module = b.createModule(.{
- // .root_source_file = b.path("src/tri/logging.zig"),
- // .target = target,
- // .optimize = optimize,
- // })},
- // },
- // });
- // const test_logging = b.addExecutable(.{
- // .name = "test-logging",
- // .root_module = test_logging_mod,
- // });
- // b.installArtifact(test_logging);
- //
- // const run_test_logging = b.addRunArtifact(test_logging);
- // if (b.args) |run_args| {
- // run_test_logging.addArgs(run_args);
- // }
- // const test_logging_step = b.step("test-logging", "Run logging module test");
- // test_logging_step.dependOn(&run_test_logging.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // FARM STATS β Removed (src/cli/farm_stats.zig does not exist)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const tri_utils_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/tri_utils.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "tri_colors", .module = tri_colors_mod },
- },
- });
- // TRI Commands module (Cycle 100: for testing)
- const tri_commands_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/tri_commands.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "tri_colors", .module = tri_colors_mod },
- .{ .name = "brain", .module = brain_mod },
- .{ .name = "simulation", .module = simulation_mod },
- .{ .name = "sebo_cli", .module = sebo_cli_mod },
- // STORM P1 Brain Zones (Ethical Infrastructure)
- .{ .name = "storm_ofc", .module = storm_ofc_mod },
- .{ .name = "storm_habenula", .module = storm_habenula_mod },
- .{ .name = "storm_amygdala", .module = storm_amygdala_mod },
- // STORM P2-P3 Modules
- .{ .name = "golden_chain", .module = golden_chain_mod },
- // FIXME: trinity-nexus submodule missing
- // .{ .name = "serve_full", .module = serve_full_mod },
- },
- });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // P1.5: Registry Module β Moved here before tri (needed for P1.6 commands/mcp)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const registry_mod = b.createModule(.{
- .root_source_file = b.path("src/registry/mcp_gen.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "command_def", .module = trinity_mod },
- },
- });
-
- // TRI - Unified Trinity CLI
- // Sacred modules (v6.0)
- const sacred_const_mod = b.createModule(.{
- .root_source_file = b.path("src/sacred/const.zig"),
- .target = target,
- .optimize = optimize,
- });
- const sacred_mod = b.createModule(.{
- .root_source_file = b.path("src/sacred/sacred.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "const", .module = sacred_const_mod },
- },
- });
-
- // OS Boot module (Temporal Trinity v1.0 β Order #021)
- const os_mod = b.createModule(.{
- .root_source_file = b.path("src/os/boot.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "sacred", .module = sacred_mod },
- },
- });
-
- // BSD Elliptic Curve Scanner module
- const bsd_mod = b.createModule(.{
- .root_source_file = b.path("src/bsd/scanner.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Firebird Slashing module (DePIN slashing conditions)
- const firebird_slashing_mod = b.createModule(.{
- .root_source_file = b.path("src/firebird/slashing.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Phase 5: Mainnet Deployment
- const firebird_mainnet_mod = b.createModule(.{
- .root_source_file = b.path("src/firebird/mainnet.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Phase 5: Multi-Chain Support
- const depin_multichain_mod = b.createModule(.{
- .root_source_file = b.path("src/depin/multichain.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Phase 5: Observability & Monitoring
- const depin_observability_mod = b.createModule(.{
- .root_source_file = b.path("src/depin/observability.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Phase 5: Production REST API
- const depin_production_mod = b.createModule(.{
- .root_source_file = b.path("src/api/depin_production.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Phase 5: Governance Module
- const firebird_governance_mod = b.createModule(.{
- .root_source_file = b.path("src/firebird/governance.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Bench module β IGLA (Needle In A Haystack) benchmark
- const bench_mod = b.createModule(.{
- .root_source_file = b.path("src/bench/bench.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // zig-hslm β Official HSLM Numerical Library
- const hslm_mod = b.createModule(.{
- .root_source_file = b.path("external/zig-hslm/src/root.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Intraparietal Sulcus β Numerical Layer (uses hslm)
- const intraparietal_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/intraparietal_sulcus.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "hslm", .module = hslm_mod },
- },
- });
-
- // TRI-27 CLI module for tri binary
- const tri27_cli_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/tri27_cli.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const tri = b.addExecutable(.{
- .name = "tri",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/main.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- .imports = &.{
- .{ .name = "trinity_workspace", .module = trinity_workspace_mod },
- .{ .name = "trinity_swe", .module = vibeec_swe },
- .{ .name = "igla_chat", .module = vibeec_chat },
- .{ .name = "igla_hybrid_chat", .module = vibeec_hybrid_chat },
- .{ .name = "igla_coder", .module = vibeec_coder },
- .{ .name = "vsa", .module = vsa_tri },
- .{ .name = "tvc_corpus", .module = tvc_corpus_mod },
- .{ .name = "tvc_distributed", .module = tvc_distributed_mod },
- .{ .name = "igla_tvc_chat", .module = igla_tvc_chat_mod },
- .{ .name = "pas_orchestrator", .module = pas_orchestrator_mod },
- // Unified API Layer (Golden Chain #102)
- .{ .name = "api", .module = api_mod },
- // Sacred modules (v6.0)
- .{ .name = "sacred", .module = sacred_mod },
- // Generated serve module (from .tri spec: specs/integration/full-serve-v1.tri)
- // FIXME: trinity-nexus submodule missing
- // .{ .name = "serve_full", .module = serve_full_mod },
- // OS Boot module (Temporal Trinity v1.0 β Order #021)
- .{ .name = "os", .module = os_mod },
- // BSD Elliptic Curve Scanner module
- .{ .name = "bsd", .module = bsd_mod },
- // Firebird Slashing module (DePIN)
- .{ .name = "firebird_slashing", .module = firebird_slashing_mod },
- // P1.6: Registry module for commands export and MCP tools
- .{ .name = "registry", .module = registry_mod },
- // DePIN modules for directed discovery (Phase 1.1)
- .{ .name = "depin_network", .module = depin_network_mod },
- .{ .name = "depin_bootstrap", .module = depin_bootstrap_mod },
- .{ .name = "depin_persistence", .module = depin_persistence_mod },
- // Phase 5: Mainnet Deployment & Multi-Chain
- .{ .name = "firebird_mainnet", .module = firebird_mainnet_mod },
- .{ .name = "depin_multichain", .module = depin_multichain_mod },
- .{ .name = "depin_observability", .module = depin_observability_mod },
- .{ .name = "depin_production", .module = depin_production_mod },
- .{ .name = "firebird_governance", .module = firebird_governance_mod },
- // SΒ³AI Brain Regions (v5.1 - Neuroanatomy)
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- }),
- });
- b.installArtifact(tri);
-
- const run_tri = b.addRunArtifact(tri);
- if (b.args) |args| {
- run_tri.addArgs(args);
- }
- const tri_step = b.step("tri", "Run TRI - Unified Trinity CLI");
- tri_step.dependOn(&run_tri.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TRIβ27 EMULATOR β Ternary RISC Processor Emulator
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const tri_emu = b.addExecutable(.{
- .name = "tri-emu",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/tri_emu_main.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(tri_emu);
-
- const run_tri_emu = b.addRunArtifact(tri_emu);
- if (b.args) |args| {
- run_tri_emu.addArgs(args);
- }
- const tri_emu_step = b.step("tri-emu", "Run TRI-27 Emulator");
- tri_emu_step.dependOn(&run_tri_emu.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TRIβ27 ASSEMBLER β Ternary assembler for .tbin bytecode
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const tri_asm = b.addExecutable(.{
- .name = "tri-asm",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/tri_asm.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(tri_asm);
-
- const run_tri_asm = b.addRunArtifact(tri_asm);
- if (b.args) |args| {
- run_tri_asm.addArgs(args);
- }
- const tri_asm_step = b.step("tri-asm", "Run TRI-27 Assembler");
- tri_asm_step.dependOn(&run_tri_asm.step);
-
- // TRIβ27 CLI β TRI-27 language toolchain (assemble/disassemble/run/validate/isa)
- // TEMP: Disabled from default build due to 5 Zig 0.15 compatibility errors (tracked in #403)
- // Core works: zig build tri-asm, zig build tri-emu, zig build test-tri27-golden
- const tri27 = b.addExecutable(.{
- .name = "tri27",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri27/tri27_cli.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(tri27);
- const run_tri27 = b.addRunArtifact(tri27);
- if (b.args) |args| {
- run_tri27.addArgs(args);
- }
- const tri27_step = b.step("tri27", "Run TRI-27 CLI (assemble/disassemble/run/validate/isa)");
- tri27_step.dependOn(&run_tri27.step);
-
- // Cycle 100: REPL Testing Infrastructure
- // Test suite for TRI CLI commands with sacred assertions
- const tri_testing = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/testing/repl_tests.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "tri_utils", .module = tri_utils_mod },
- .{ .name = "tri_commands", .module = tri_commands_mod },
- .{ .name = "trinity_swe", .module = vibeec_swe },
- .{ .name = "igla_chat", .module = vibeec_chat },
- .{ .name = "igla_hybrid_chat", .module = vibeec_hybrid_chat },
- .optimize = optimize,
- }) },
- // P3.11: Token CLI commands
- // FIXME: tri_token module disabled (getStdErr removed in Zig 0.15.2)
- // .{ .name = "tri_token", .module = b.createModule(.{
- // .root_source_file = b.path("src/tri/tri_token.zig"),
- // .target = target,
- // .optimize = optimize,
- // }),
- },
- }),
- });
- const run_tri_testing = b.addRunArtifact(tri_testing);
- const tri_testing_step = b.step("test-repl", "Run TRI REPL Tests (Cycle 100)");
- tri_testing_step.dependOn(&run_tri_testing.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TRI CLI Utility Modules β Unit Tests
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // Config module tests
- const tri_config_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/tri_config.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_tri_config_tests = b.addRunArtifact(tri_config_tests);
- const tri_config_tests_step = b.step("test-tri-config", "Run TRI Config Tests");
- tri_config_tests_step.dependOn(&run_tri_config_tests.step);
-
- // Dev State Machine tests
- const dev_state_machine_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/dev_state_machine.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_dev_state_machine_tests = b.addRunArtifact(dev_state_machine_tests);
- const dev_state_machine_tests_step = b.step("test-dev-state-machine", "Run Dev State Machine Tests");
- dev_state_machine_tests_step.dependOn(&run_dev_state_machine_tests.step);
-
- // Dev Commands module
- const dev_commands_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/dev_commands.zig"),
- .target = target,
- .optimize = optimize,
- });
- const dev_commands_tests = b.addTest(.{
- .root_module = dev_commands_mod,
- });
- const run_dev_commands_tests = b.addRunArtifact(dev_commands_tests);
- const dev_commands_tests_step = b.step("test-dev-commands", "Run Dev Commands Tests");
- dev_commands_tests_step.dependOn(&run_dev_commands_tests.step);
-
- // History module tests
- const tri_history_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/tri_history.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_tri_history_tests = b.addRunArtifact(tri_history_tests);
- const tri_history_tests_step = b.step("test-tri-history", "Run TRI History Tests");
- tri_history_tests_step.dependOn(&run_tri_history_tests.step);
-
- // Error handling tests
- const tri_error_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/tri_error.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_tri_error_tests = b.addRunArtifact(tri_error_tests);
- const tri_error_tests_step = b.step("test-tri-error", "Run TRI Error Tests");
- tri_error_tests_step.dependOn(&run_tri_error_tests.step);
-
- // TRIβ27 Experience Tests
- const queen_episodes_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/queen/episodes.zig"),
- .target = target,
- .optimize = optimize,
- });
- const tri27_experience_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/tri27_experience.zig"),
- .target = target,
- .optimize = optimize,
- });
- tri27_experience_mod.addImport("queen_episodes", queen_episodes_mod);
-
- const tri27_experience_tests = b.addTest(.{
- .root_module = tri27_experience_mod,
- });
- const run_tri27_experience_tests = b.addRunArtifact(tri27_experience_tests);
- const tri27_experience_tests_step = b.step("test-tri27-experience", "Run TRIβ27 Experience Tests");
- tri27_experience_tests_step.dependOn(&run_tri27_experience_tests.step);
-
- // TRIβ27 Golden Test (full cycle: asm β tbin β emulator)
- const tri27_golden_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/test_golden.zig"),
- .target = target,
- .optimize = optimize,
- });
- const tri27_golden_tests = b.addTest(.{
- .root_module = tri27_golden_mod,
- });
- const run_tri27_golden_tests = b.addRunArtifact(tri27_golden_tests);
- const tri27_golden_tests_step = b.step("test-tri27-golden", "Run TRIβ27 Golden Test");
- tri27_golden_tests_step.dependOn(&run_tri27_golden_tests.step);
-
- // Queen Self-Learning Tests (Phase 5)
- const queen_self_learning_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/queen/self_learning.zig"),
- .target = target,
- .optimize = optimize,
- });
- queen_self_learning_mod.addImport("queen_episodes", queen_episodes_mod);
-
- const queen_self_learning_tests = b.addTest(.{
- .root_module = queen_self_learning_mod,
- });
- const run_queen_self_learning_tests = b.addRunArtifact(queen_self_learning_tests);
- const queen_self_learning_tests_step = b.step("test-queen-self-learning", "Run Queen Self-Learning Tests");
- queen_self_learning_tests_step.dependOn(&run_queen_self_learning_tests.step);
-
- // Queen Backend β HTTP/JSON API Server for Container Deployment
- const queen_backend_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/queen/backend_server.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "episodes", .module = queen_episodes_mod },
- .{ .name = "self_learning", .module = queen_self_learning_mod },
- },
- });
-
- const queen_backend = b.addExecutable(.{
- .name = "queen-backend",
- .root_module = queen_backend_mod,
- });
- b.installArtifact(queen_backend);
-
- // Build-only step for queen-backend (CI-friendly, no SIGTERM on port conflict)
- const queen_compile_step = b.step("queen-compile", "Compile queen-backend without running");
- queen_compile_step.dependOn(&b.addInstallArtifact(queen_backend, .{}).step);
-
- const run_queen_backend = b.addRunArtifact(queen_backend);
- const queen_backend_step = b.step("queen-backend", "Run Queen Backend Server");
- queen_backend_step.dependOn(&run_queen_backend.step);
-
- // TRI-27 Comprehensive Tests (all 36 opcodes)
- const tri27_comprehensive_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/test_comprehensive.zig"),
- .target = target,
- .optimize = optimize,
- });
- const tri27_comprehensive_tests = b.addTest(.{
- .root_module = tri27_comprehensive_mod,
- });
- const run_tri27_comprehensive_tests = b.addRunArtifact(tri27_comprehensive_tests);
- const tri27_comprehensive_tests_step = b.step("test-tri27-comprehensive", "Run TRIβ27 Comprehensive Tests");
- tri27_comprehensive_tests_step.dependOn(&run_tri27_comprehensive_tests.step);
-
- // TTT Dogfood Phase 2 β .t27 Program Tests
- const tri27_cpu_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/cpu_state.zig"),
- .target = target,
- .optimize = optimize,
- });
- const tri27_decoder_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/decoder.zig"),
- .target = target,
- .optimize = optimize,
- });
- const tri27_executor_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/executor.zig"),
- .target = target,
- .optimize = optimize,
- });
- tri27_executor_mod.addImport("cpu_state", tri27_cpu_mod);
- tri27_executor_mod.addImport("decoder", tri27_decoder_mod);
-
- const tri27_t27_programs_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/test_t27_programs.zig"),
- .target = target,
- .optimize = optimize,
- });
- tri27_t27_programs_mod.addImport("cpu_state", tri27_cpu_mod);
- tri27_t27_programs_mod.addImport("executor", tri27_executor_mod);
-
- const tri27_t27_programs_tests = b.addTest(.{
- .root_module = tri27_t27_programs_mod,
- });
- const run_tri27_t27_programs_tests = b.addRunArtifact(tri27_t27_programs_tests);
- const tri27_t27_programs_tests_step = b.step("test-tri27-t27", "Run TTT Dogfood .t27 Program Tests");
- tri27_t27_programs_tests_step.dependOn(&run_tri27_t27_programs_tests.step);
-
- // TRI-27 Encoder Fuzzer (Property-based tests for Issue #469 regression prevention)
- const tri27_fuzzer_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/test_encoder_fuzz.zig"),
- .target = target,
- .optimize = optimize,
- });
- tri27_fuzzer_mod.addImport("cpu_state", tri27_cpu_mod);
- tri27_fuzzer_mod.addImport("executor", tri27_executor_mod);
-
- const tri27_fuzzer_tests = b.addTest(.{
- .root_module = tri27_fuzzer_mod,
- });
- const run_tri27_fuzzer_tests = b.addRunArtifact(tri27_fuzzer_tests);
- const tri27_fuzzer_tests_step = b.step("test-tri27-fuzz", "Run TRI-27 Encoder Fuzzer (Property-based Tests)");
- tri27_fuzzer_tests_step.dependOn(&run_tri27_fuzzer_tests.step);
-
- // TTT Dogfood Verification Sweep β Tier 1 Smoke Tests
- const tri27_smoke_mod = b.createModule(.{
- .root_source_file = b.path("src/tri27/emu/smoke_tests.zig"),
- .target = target,
- .optimize = optimize,
- });
- tri27_smoke_mod.addImport("cpu_state", tri27_cpu_mod);
- tri27_smoke_mod.addImport("executor", tri27_executor_mod);
-
- const tri27_smoke_tests = b.addTest(.{
- .root_module = tri27_smoke_mod,
- });
- const run_tri27_smoke_tests = b.addRunArtifact(tri27_smoke_tests);
- const tri27_smoke_tests_step = b.step("test-tri27-smoke", "Run TTT Dogfood Tier 1 Smoke Tests (Neural/Transformer/Conv)");
- tri27_smoke_tests_step.dependOn(&run_tri27_smoke_tests.step);
-
- // SΒ³AI Brain Regions Tests (v5.1 - Neuroanatomy)
- const basal_ganglia_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/brain/basal_ganglia.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_basal_ganglia_tests = b.addRunArtifact(basal_ganglia_tests);
- const basal_ganglia_tests_step = b.step("test-basal-ganglia", "Run Basal Ganglia Tests");
- basal_ganglia_tests_step.dependOn(&run_basal_ganglia_tests.step);
-
- const reticular_formation_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/brain/reticular_formation.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_reticular_formation_tests = b.addRunArtifact(reticular_formation_tests);
- const reticular_formation_tests_step = b.step("test-reticular-formation", "Run Reticular Formation Tests");
- reticular_formation_tests_step.dependOn(&run_reticular_formation_tests.step);
-
- const locus_coeruleus_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/brain/locus_coeruleus.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_locus_coeruleus_tests = b.addRunArtifact(locus_coeruleus_tests);
- const locus_coeruleus_tests_step = b.step("test-locus-coeruleus", "Run Locus Coeruleus Tests");
- locus_coeruleus_tests_step.dependOn(&run_locus_coeruleus_tests.step);
-
- // Amygdala (Emotional Salience) tests
- const amygdala_tests = b.addTest(.{
- .root_module = amygdala_mod,
- });
- const run_amygdala_tests = b.addRunArtifact(amygdala_tests);
- const amygdala_tests_step = b.step("test-amygdala", "Run Amygdala Tests");
- amygdala_tests_step.dependOn(&run_amygdala_tests.step);
-
- // Hippocampus (Persistence) tests
- const persistence_tests = b.addTest(.{
- .root_module = persistence_mod,
- });
- const run_persistence_tests = b.addRunArtifact(persistence_tests);
- const persistence_tests_step = b.step("test-persistence", "Run Persistence Tests");
- persistence_tests_step.dependOn(&run_persistence_tests.step);
-
- // Corpus Callosum (Telemetry) tests
- const telemetry_tests = b.addTest(.{
- .root_module = telemetry_mod,
- });
- const run_telemetry_tests = b.addRunArtifact(telemetry_tests);
- const telemetry_tests_step = b.step("test-telemetry", "Run Telemetry Tests");
- telemetry_tests_step.dependOn(&run_telemetry_tests.step);
-
- // Hippocampus (Health History) tests
- const health_history_tests = b.addTest(.{
- .root_module = health_history_mod,
- });
- const run_health_history_tests = b.addRunArtifact(health_history_tests);
- const health_history_tests_step = b.step("test-health-history", "Run Health History Tests");
- health_history_tests_step.dependOn(&run_health_history_tests.step);
-
- // Microglia (Immune Surveillance) tests
- const microglia_tests = b.addTest(.{
- .root_module = microglia_mod,
- });
- const run_microglia_tests = b.addRunArtifact(microglia_tests);
- const microglia_tests_step = b.step("test-microglia", "Run Microglia Tests");
- microglia_tests_step.dependOn(&run_microglia_tests.step);
-
- // Thalamus (Async Processor) tests
- const async_processor_tests = b.addTest(.{
- .root_module = async_processor_mod,
- });
- const run_async_processor_tests = b.addRunArtifact(async_processor_tests);
- const async_processor_tests_step = b.step("test-async-processor", "Run Async Processor Tests");
- async_processor_tests_step.dependOn(&run_async_processor_tests.step);
-
- // Hypothalamus (Admin) tests
- const admin_tests = b.addTest(.{
- .root_module = admin_mod,
- });
- const run_admin_tests = b.addRunArtifact(admin_tests);
- const admin_tests_step = b.step("test-admin", "Run Admin Tests");
- admin_tests_step.dependOn(&run_admin_tests.step);
-
- const brain_tests = b.addTest(.{
- .root_module = brain_mod,
- });
- const run_brain_tests = b.addRunArtifact(brain_tests);
- const brain_tests_step = b.step("test-brain", "Run Brain Aggregator Tests");
- brain_tests_step.dependOn(&run_brain_tests.step);
-
- // zig-hslm β Official HSLM Numerical Library tests
- const hslm_f16_mod = b.createModule(.{
- .root_source_file = b.path("external/zig-hslm/src/f16_utils.zig"),
- .target = target,
- .optimize = optimize,
- });
- const hslm_f16_tests = b.addTest(.{
- .root_module = hslm_f16_mod,
- });
- const run_hslm_f16_tests = b.addRunArtifact(hslm_f16_tests);
- const hslm_f16_tests_step = b.step("test-hslm-f16", "Run HSLM F16 Utils Tests");
- hslm_f16_tests_step.dependOn(&run_hslm_f16_tests.step);
-
- // Intraparietal Sulcus (Numerical Layer) tests
- const intraparietal_tests = b.addTest(.{
- .root_module = intraparietal_mod,
- });
- const run_intraparietal_tests = b.addRunArtifact(intraparietal_tests);
- const intraparietal_tests_step = b.step("test-intraparietal", "Run Intraparietal Sulcus Tests");
- intraparietal_tests_step.dependOn(&run_intraparietal_tests.step);
-
- // SΒ³AI Brain Stress Test β Load testing for 1000 tasks Γ 10 agents
- const stress_test_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/stress_test.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "brain", .module = brain_mod },
- },
- });
- const stress_tests = b.addTest(.{
- .root_module = stress_test_mod,
- });
- const run_stress_tests = b.addRunArtifact(stress_tests);
- const stress_tests_step = b.step("test-brain-stress", "Run SΒ³AI Brain Stress Test");
- stress_tests_step.dependOn(&run_stress_tests.step);
-
- // SΒ³AI Brain Simulation β Realistic workload testing
- const simulation_tests = b.addTest(.{
- .root_module = simulation_mod,
- });
- const run_simulation_tests = b.addRunArtifact(simulation_tests);
- const simulation_tests_step = b.step("test-brain-simulation", "Run SΒ³AI Brain Simulation Tests");
- simulation_tests_step.dependOn(&run_simulation_tests.step);
-
- // SΒ³AI Brain Integration Tests β Cross-region coordination
- const brain_integration_test_mod = b.createModule(.{
- .root_source_file = b.path("src/brain/integration_test.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "basal_ganglia", .module = basal_ganglia_mod },
- .{ .name = "reticular_formation", .module = reticular_formation_mod },
- .{ .name = "locus_coeruleus", .module = locus_coeruleus_mod },
- .{ .name = "amygdala", .module = amygdala_mod },
- .{ .name = "prefrontal_cortex", .module = prefrontal_cortex_mod },
- .{ .name = "telemetry", .module = telemetry_mod },
- .{ .name = "health_history", .module = health_history_mod },
- .{ .name = "alerts", .module = alerts_mod },
- .{ .name = "state_recovery", .module = state_recovery_mod },
- .{ .name = "learning", .module = learning_mod },
- .{ .name = "federation", .module = federation_mod },
- .{ .name = "async_processor", .module = async_processor_mod },
- .{ .name = "metrics_dashboard", .module = metrics_dashboard_mod },
- },
- });
- const brain_integration_tests = b.addTest(.{
- .root_module = brain_integration_test_mod,
- });
- const run_brain_integration_tests = b.addRunArtifact(brain_integration_tests);
- const brain_integration_tests_step = b.step("test-brain-integration", "Run SΒ³AI Brain Integration Tests");
- brain_integration_tests_step.dependOn(&run_brain_integration_tests.step);
-
- // Trinity Hybrid Local Coder (IGLA + Ollama)
- const hybrid_local = b.addExecutable(.{
- .name = "trinity-hybrid",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/trinity_hybrid_local.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(hybrid_local);
-
- const run_hybrid = b.addRunArtifact(hybrid_local);
- if (b.args) |args| {
- run_hybrid.addArgs(args);
- }
- const hybrid_step = b.step("hybrid", "Run Trinity Hybrid Local Coder (IGLA + Ollama)");
- hybrid_step.dependOn(&run_hybrid.step);
-
- // GGUF model module (for distributed inference)
- // Single module β gguf_model.zig internally imports gguf_inference.zig
- const gguf_model_mod = b.createModule(.{
- .root_source_file = b.path("src/vibeec/gguf_model.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // Trinity Node - Decentralized Inference Network
- const trinity_node = b.addExecutable(.{
- .name = "trinity-node",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/main.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "gguf_model", .module = gguf_model_mod },
- },
- }),
- });
- b.installArtifact(trinity_node);
-
- const run_node = b.addRunArtifact(trinity_node);
- if (b.args) |args| {
-
- const run_node_gui = b.addRunArtifact(trinity_node_gui);
- if (b.args) |args| {
- run_node_gui.addArgs(args);
- }
- const node_gui_step = b.step("node-gui", "Run Trinity Node with Raylib GUI");
- node_gui_step.dependOn(&run_node_gui.step);
-
- // Emergent Photon AI Demo - Interactive wave visualization
- // phi^2 + 1/phi^2 = 3 = TRINITY
- const photon_demo = b.addExecutable(.{
- .name = "photon-demo",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vsa/photon_demo.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- photon_demo.linkSystemLibrary("raylib");
- photon_demo.linkLibC();
- b.installArtifact(photon_demo);
-
- const run_photon_demo = b.addRunArtifact(photon_demo);
- if (b.args) |args| {
- run_photon_demo.addArgs(args);
- }
- const photon_demo_step = b.step("photon-demo", "Run Emergent Photon AI Demo");
- photon_demo_step.dependOn(&run_photon_demo.step);
- } // end if (!ci_mode) β GUI targets
-
- // Emergent Photon AI v0.3 - IMMERSIVE COSMIC CANVAS
- // No UI panels. No buttons. Pure emergent wave intelligence.
- // phi^2 + 1/phi^2 = 3 = TRINITY
- // Skipped in CI mode (-Dci=true) since raylib is not available
- if (!ci_mode) {
- const photon_immersive = b.addExecutable(.{
- .name = "photon-immersive",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vsa/photon_immersive.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- photon_immersive.linkSystemLibrary("raylib");
- photon_immersive.linkLibC();
- b.installArtifact(photon_immersive);
-
- const run_photon_immersive = b.addRunArtifact(photon_immersive);
- if (b.args) |args| {
- run_photon_immersive.addArgs(args);
- }
- const photon_immersive_step = b.step("photon-immersive", "Run Immersive Cosmic Canvas (v0.3)");
- photon_immersive_step.dependOn(&run_photon_immersive.step);
- }
-
- // Emergent Photon AI v0.4 - TRINITY COSMIC CANVAS
- // Full Trinity functionality emerges from wave interference
- // Chat/Code/Vision/Voice/Tools/Autonomous all in cosmic canvas
- // Skipped in CI mode (-Dci=true) since raylib is not available
- if (!ci_mode) {
- const trinity_canvas = b.addExecutable(.{
- .name = "trinity-canvas",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vsa/photon_trinity_canvas.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "igla_chat", .module = vibeec_chat },
- .{ .name = "igla_fluent_chat", .module = vibeec_fluent_chat },
- .{ .name = "igla_hybrid_chat", .module = vibeec_hybrid_chat },
- .{ .name = "golden_chain", .module = golden_chain_mod },
- .{ .name = "tvc_corpus", .module = tvc_corpus_mod },
- .{ .name = "auto_shard", .module = b.createModule(.{
- .root_source_file = b.path("src/trinity_node/auto_shard.zig"),
- .target = target,
- .optimize = optimize,
- }) },
- },
- }),
- });
- trinity_canvas.linkSystemLibrary("raylib");
- // v8.4: Add raygui include path and C implementation
- trinity_canvas.addIncludePath(b.path("external/raygui/src"));
- trinity_canvas.addCSourceFile(.{ .file = b.path("src/vsa/raygui_impl.c") });
- // TEMP: Disable install until raygui.h is available
- // b.installArtifact(trinity_canvas);
-
- const run_trinity_canvas = b.addRunArtifact(trinity_canvas);
- if (b.args) |args| {
- run_trinity_canvas.addArgs(args);
- }
- const trinity_canvas_step = b.step("trinity-canvas", "Run Trinity Cosmic Canvas (v1.9 Emergent Wave)");
- trinity_canvas_step.dependOn(&run_trinity_canvas.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Trinity Canvas WASM β compiles the same canvas for browsers via Emscripten
- // Build: zig build trinity-canvas-wasm -Dtarget=wasm32-emscripten
- // Output: zig-out/web/ (trinity-canvas.html, .js, .wasm, .data)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- {
- // WASM stub modules (replace system-dependent chat/network/fs)
- const wasm_igla_chat = b.createModule(.{
- .root_source_file = b.path("src/wasm_stubs/igla_chat_stub.zig"),
- .target = target,
- .optimize = optimize,
- });
- const wasm_fluent_chat = b.createModule(.{
- .root_source_file = b.path("src/wasm_stubs/igla_fluent_chat_stub.zig"),
- .target = target,
- .optimize = optimize,
- });
- const wasm_tvc_corpus = b.createModule(.{
- .root_source_file = b.path("src/wasm_stubs/tvc_corpus_stub.zig"),
- .target = target,
- .optimize = optimize,
- });
- const wasm_auto_shard = b.createModule(.{
- .root_source_file = b.path("src/wasm_stubs/auto_shard_stub.zig"),
- .target = target,
- .optimize = optimize,
- });
- const wasm_igla_kg = b.createModule(.{
- .root_source_file = b.path("src/wasm_stubs/igla_knowledge_graph_stub.zig"),
- .target = target,
- .optimize = optimize,
- });
- const wasm_hybrid_chat = b.createModule(.{
- .root_source_file = b.path("src/wasm_stubs/igla_hybrid_chat_stub.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "igla_chat", .module = wasm_igla_chat },
- .{ .name = "tvc_corpus", .module = wasm_tvc_corpus },
- .{ .name = "igla_kg", .module = wasm_igla_kg },
- .{ .name = "triples_parser", .module = triples_parser_mod },
- },
- });
- const wasm_golden_chain = b.createModule(.{
- .root_source_file = b.path("src/wasm_stubs/golden_chain_stub.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "igla_hybrid_chat", .module = wasm_hybrid_chat },
- },
- });
-
- const wasm_root = b.createModule(.{
- // ONE SOURCE OF TRUTH: same file as native build, with is_emscripten gates
- .root_source_file = b.path("src/vsa/photon_trinity_canvas.zig"),
- .target = target,
- .optimize = optimize,
- .link_libc = true,
- .imports = &.{
- .{ .name = "igla_chat", .module = wasm_igla_chat },
- .{ .name = "igla_fluent_chat", .module = wasm_fluent_chat },
- .{ .name = "igla_hybrid_chat", .module = wasm_hybrid_chat },
- .{ .name = "golden_chain", .module = wasm_golden_chain },
- .{ .name = "tvc_corpus", .module = wasm_tvc_corpus },
- .{ .name = "auto_shard", .module = wasm_auto_shard },
- },
- });
-
- const wasm_step = b.step("trinity-canvas-wasm", "Build Trinity Canvas for Web (WASM via Emscripten)");
-
- if (target.query.os_tag == .emscripten) {
- // ββ Emscripten WASM build (raylib-zig emsdk helpers) ββ
- const raylib_zig = @import("raylib");
-
- // Get raylib C library compiled for emscripten
- const raylib_dep = b.dependency("raylib", .{
- .target = target,
- .optimize = optimize,
- });
- const raylib_artifact = raylib_dep.artifact("raylib");
-
- // Link raylib C library and add its include path for @cImport("raylib.h")
- wasm_root.linkLibrary(raylib_artifact);
- wasm_root.addIncludePath(raylib_dep.path("src"));
-
- const wasm = b.addLibrary(.{
- .name = "trinity-canvas",
- .root_module = wasm_root,
- .linkage = .static,
- });
-
- const install_dir: std.Build.InstallDir = .{ .custom = "web" };
- const emcc_flags = raylib_zig.emsdk.emccDefaultFlags(b.allocator, .{
- .optimize = optimize,
- .asyncify = true,
- });
- var emcc_settings = raylib_zig.emsdk.emccDefaultSettings(b.allocator, .{
- .optimize = optimize,
- });
- // Trinity Canvas needs ~256MB for grid + fonts + particles
- emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable;
- emcc_settings.put("INITIAL_MEMORY", "268435456") catch unreachable; // 256MB
-
- const emcc_link = raylib_zig.emsdk.emccStep(b, raylib_artifact, wasm, .{
- .optimize = optimize,
- .flags = emcc_flags,
- .settings = emcc_settings,
- .shell_file_path = b.path("src/wasm_stubs/shell.html"),
- .install_dir = install_dir,
- .embed_paths = &.{.{ .src_path = b.pathFromRoot("assets/fonts"), .virtual_path = "assets/fonts" }},
- });
-
- wasm_step.dependOn(emcc_link);
- } else {
- // ββ Native build (for compilation check without emsdk) ββ
- const wasm_canvas = b.addExecutable(.{
- .name = "trinity-canvas-wasm-check",
- .root_module = wasm_root,
- });
- wasm_canvas.linkSystemLibrary("raylib");
- wasm_canvas.linkLibC();
- // TEMP: Disable install until raygui.h is available
- // b.installArtifact(wasm_canvas);
- wasm_step.dependOn(b.getInstallStep());
- }
- }
- } // end if (!ci_mode) β raylib canvas targets
-
- // Photon Terminal v1.0 - TERNARY EMERGENT TUI
- // Not a grid of cells β a living wave field in your terminal.
- const photon_terminal = b.addExecutable(.{
- .name = "photon-terminal",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vsa/photon_terminal.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(photon_terminal);
-
- const run_photon_terminal = b.addRunArtifact(photon_terminal);
- if (b.args) |args| {
- run_photon_terminal.addArgs(args);
- }
- const photon_terminal_step = b.step("photon-terminal", "Run Photon Terminal (Emergent TUI v1.0)");
- photon_terminal_step.dependOn(&run_photon_terminal.step);
-
- // VSA module (re-exports HybridBigInt from hybrid.zig) β REMOVED (unused after generated.old/ cleanup)
-
- // Quark Tests, VSA Math Proofs, Bundle Opt, Large Analogies β REMOVED (generated.old/ deleted)
-
- // LLM Triples Extractor (SYM-002: pattern-based triple extraction from text)
- const triples_parser_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/triples_parser.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_triples_parser = b.addRunArtifact(triples_parser_tests);
- const triples_parser_step = b.step("test-triples-parser", "Test LLM Triples Extractor (SYM-002: pattern-based extraction)");
- triples_parser_step.dependOn(&run_triples_parser.step);
- test_step.dependOn(&run_triples_parser.step);
-
- // KG Pipeline Integration (SYM-004: extract triples from LLM responses -> KG)
- const kg_pipeline_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/kg_pipeline.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_kg_pipeline = b.addRunArtifact(kg_pipeline_tests);
- const kg_pipeline_step = b.step("test-kg-pipeline", "Test KG Pipeline Integration (SYM-004: triples extraction -> KG)");
- kg_pipeline_step.dependOn(&run_kg_pipeline.step);
- test_step.dependOn(&run_kg_pipeline.step);
-
- // KG Sync DHT (SYM-003: Decentralized KG Sync + $TRI Rewards)
- const kg_sync_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/kg_sync.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_kg_sync = b.addRunArtifact(kg_sync_tests);
- const kg_sync_step = b.step("test-kg-sync", "Test KG Sync DHT (SYM-003: Kademlia DHT + $TRI rewards)");
- kg_sync_step.dependOn(&run_kg_sync.step);
- test_step.dependOn(&run_kg_sync.step);
-
- // SYM-005 TRI SOTA MVP Demo (Decentralized Knowledge Collector)
- const kg_sync_mod = b.createModule(.{
- .root_source_file = b.path("src/vibeec/kg_sync.zig"),
- .target = target,
- .optimize = optimize,
- });
- const sym_005_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/sym_005_demo.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "triples_parser", .module = triples_parser_mod },
- .{ .name = "kg_sync", .module = kg_sync_mod },
- },
- }),
- });
- const run_sym_005 = b.addRunArtifact(sym_005_tests);
- const sym_005_step = b.step("test-sym-005", "Test SYM-005 TRI SOTA MVP (full symbolic pipeline)");
- sym_005_step.dependOn(&run_sym_005.step);
- test_step.dependOn(&run_sym_005.step);
-
- // OPT-PC01 Prefix Caching Completion (Phase 3-5)
- const kv_cache_mod = b.createModule(.{
- .root_source_file = b.path("src/vibeec/kv_cache.zig"),
- .target = target,
- .optimize = optimize,
- });
- const prefix_cache_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/prefix_cache_completion.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "kv_cache", .module = kv_cache_mod },
- },
- }),
- });
- const run_prefix_cache = b.addRunArtifact(prefix_cache_tests);
- const prefix_cache_step = b.step("test-prefix-cache", "Test OPT-PC01 Prefix Caching (Phase 3-5 completion)");
- prefix_cache_step.dependOn(&run_prefix_cache.step);
- test_step.dependOn(&run_prefix_cache.step);
-
- // VSA Math Benchmark executable (MATH-003) β REMOVED (generated.old/ deleted)
-
- // Storage Init tests β REMOVED (generated.old/ deleted)
-
- // Generated Shard Manager tests β REMOVED (generated.old/ deleted)
-
- // ShardManager API tests β REMOVED (generated.old/ deleted)
-
- // Network transfer tests β REMOVED (generated.old/ deleted)
-
- // Erasure coding tests β REMOVED (generated.old/ deleted)
-
- // Pipeline tests β REMOVED (generated.old/ deleted)
-
- // Network pipeline tests β REMOVED (generated.old/ deleted)
-
- // Discovery tests β REMOVED (generated.old/ deleted)
-
- // Proof-of-Storage tests β REMOVED (generated.old/ deleted)
-
- // Kademlia DHT tests β REMOVED (generated.old/ deleted)
-
- // Live Swarm tests β REMOVED (generated.old/ deleted)
-
- // Live Rewards tests β REMOVED (generated.old/ deleted)
-
- // Swarm Watch tests β REMOVED (generated.old/ deleted)
-
- // Ternary KV Cache tests β REMOVED (generated.old/ deleted)
-
- // Ternary MatMul tests β REMOVED (generated.old/ deleted)
-
- // Paged Attention tests β REMOVED (generated.old/ deleted)
-
- // Continuous Batching tests β REMOVED (generated.old/ deleted)
-
- // Speculative Decoding tests β REMOVED (generated.old/ deleted)
-
- // GGUF Parser tests β REMOVED (generated.old/ deleted)
-
- // Transformer Forward Pass tests β REMOVED (generated.old/ deleted)
-
- // Hardware Abstraction tests β REMOVED (generated.old/ deleted)
-
- // JIT Compilation tests β REMOVED (generated.old/ deleted)
-
- // FPGA Acceleration tests β REMOVED (generated.old/ deleted)
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // P1.5: Registry Export β Generate registry.json from CommandDef
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const registry_export_exe = b.addExecutable(.{
- .name = "export-registry",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/registry/export_cli.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "mcp_gen", .module = registry_mod },
- .{ .name = "trinity", .module = trinity_mod },
- },
- }),
- });
-
- const run_registry_export = b.addRunArtifact(registry_export_exe);
- run_registry_export.addArg(".trinity/registry.json");
-
- const registry_step = b.step("export-registry", "Export command registry to .trinity/registry.json");
- registry_step.dependOn(&run_registry_export.step);
-
- // Also run as part of build step
- // b.getInstallStep().dependOn(&run_registry_export.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Token Rotator for z.ai keys
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const token_rotator_mod = b.createModule(.{
- .root_source_file = b.path("src/tri/token_rotator.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TRI-CODEGEN β VIBEE Codegen Phase 1, 2, 3
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const tri_codegen = b.addExecutable(.{
- .name = "tri-codegen",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/vibeec/codegen_impl.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(tri_codegen);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TRI-API β Direct Anthropic API Agent (Issue #60)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const tri_api = b.addExecutable(.{
- .name = "tri-api",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri-api/main.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "token_rotator", .module = token_rotator_mod },
- .{ .name = "trinity_workspace", .module = trinity_workspace_mod },
- },
- }),
- });
- b.installArtifact(tri_api);
- const run_tri_api = b.addRunArtifact(tri_api);
- if (b.args) |args| run_tri_api.addArgs(args);
- const tri_api_step = b.step("tri-api", "Run TRI-API β Direct Anthropic API Agent");
- tri_api_step.dependOn(&run_tri_api.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // ARENA β LLM Battle Platform (Trinity Arena 2.0)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const arena_exe = b.addExecutable(.{
- .name = "arena",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/arena/main.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(arena_exe);
- const run_arena = b.addRunArtifact(arena_exe);
- if (b.args) |args| run_arena.addArgs(args);
- const arena_step = b.step("arena", "Run Trinity Arena β LLM Battle Platform");
- arena_step.dependOn(&run_arena.step);
-
- // STORM P9: Main CLI for autonomous operation
- const storm_exe = b.addExecutable(.{
- .name = "storm",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/storm/main.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(storm_exe);
- const storm_step = b.step("storm", "STORM P9 β 32-agent autonomous operation");
- const run_storm = b.addRunArtifact(storm_exe);
- storm_step.dependOn(&run_storm.step);
-
- // Arena tests
- const arena_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/arena/main.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_arena_tests = b.addRunArtifact(arena_tests);
- test_step.dependOn(&run_arena_tests.step);
-
- // ============================================================
- // Sacred ALU Synthesis β GF16/TF3-9 Arithmetic for XC7A100T
- // ============================================================
-
- const sacred = b.addExecutable(.{
- .name = "tri-sacred",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/sacred_alu.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- .link_libc = true,
- }),
- });
- b.installArtifact(sacred);
-
- const run_sacred = b.addRunArtifact(sacred);
- if (b.args) |run_args| {
- run_sacred.addArgs(run_args);
- }
- const sacred_synth_step = b.step("sacred", "Synthesize Sacred GF16/TF3-9 ALU modules for XC7A100T");
- sacred_synth_step.dependOn(&run_sacred.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // tri-sacred-synth-report β Parse Yosys JSON synthesis output (Phase 6.4)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- const sacred_synth_report = b.addExecutable(.{
- .name = "tri-sacred-synth-report",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/sacred_synth_report.zig"),
- .target = target,
- .optimize = .ReleaseFast,
- }),
- });
- b.installArtifact(sacred_synth_report);
-
- const sacred_synth_report_step = b.step("sacred-synth-report", "Parse Yosys JSON synthesis output for Sacred ALU");
- sacred_synth_report_step.dependOn(&sacred_synth_report.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // SACRED VERIFICATION β Trinity math constants at compile-time
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const sacred_types_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/sacred/sacred_types.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_sacred_types = b.addRunArtifact(sacred_types_tests);
-
- const sacred_verify_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/sacred/verify.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_sacred_verify = b.addRunArtifact(sacred_verify_tests);
-
- const sacred_guards_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/sacred/guards.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_sacred_guards = b.addRunArtifact(sacred_guards_tests);
-
- const sacred_lut_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/sacred/lut.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_sacred_lut = b.addRunArtifact(sacred_lut_tests);
-
- const sacred_simd_tests = b.addTest(.{
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/sacred/simd_ternary.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- const run_sacred_simd = b.addRunArtifact(sacred_simd_tests);
-
- const sacred_verify_step = b.step("sacred-verify", "Verify Sacred math constants and types");
- sacred_verify_step.dependOn(&run_sacred_types.step);
- sacred_verify_step.dependOn(&run_sacred_verify.step);
- sacred_verify_step.dependOn(&run_sacred_guards.step);
- sacred_verify_step.dependOn(&run_sacred_lut.step);
- sacred_verify_step.dependOn(&run_sacred_simd.step);
- test_step.dependOn(sacred_verify_step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // CAPABILITIES REPORT β System capabilities (SIMD, Sacred Dimensions)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // SIMD config module for caps-report
- const hslm_simd_config_mod = b.createModule(.{
- .root_source_file = b.path("src/hslm/simd_config.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const caps_report = b.addExecutable(.{
- .name = "caps-report",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/sacred/caps_report.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "hslm_simd_config", .module = hslm_simd_config_mod },
- },
- }),
- });
- b.installArtifact(caps_report);
-
- const run_caps = b.addRunArtifact(caps_report);
- const caps_step = b.step("caps", "Generate Sacred Trinity capabilities report");
- caps_step.dependOn(&run_caps.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // STORM P5 β Wave Protocol, Cost Tracking, Model Roulette
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const wave_protocol_mod = b.createModule(.{
- .root_source_file = b.path("src/storm/wave_protocol.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "golden_chain", .module = golden_chain_mod },
- },
- });
-
- const cost_tracker_mod = b.createModule(.{
- .root_source_file = b.path("src/storm/cost_tracker.zig"),
- .target = target,
- .optimize = optimize,
- });
-
- const model_roulette_mod = b.createModule(.{
- .root_source_file = b.path("src/storm/model_roulette.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "cost_tracker", .module = cost_tracker_mod },
- },
- });
-
- const storm_p5_test = b.addExecutable(.{
- .name = "storm-p5-test",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/storm/test_standalone_p5.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "golden_chain", .module = golden_chain_mod },
- .{ .name = "wave_protocol", .module = wave_protocol_mod },
- .{ .name = "cost_tracker", .module = cost_tracker_mod },
- .{ .name = "model_roulette", .module = model_roulette_mod },
- },
- }),
- });
- b.installArtifact(storm_p5_test);
-
- const run_storm_p5 = b.addRunArtifact(storm_p5_test);
- const storm_p5_step = b.step("storm-p5", "Run STORM P5 integration test");
- storm_p5_step.dependOn(&run_storm_p5.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // WAVE 9 GENERATOR β Docker-compose generator for local training
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const wave9_gen = b.addExecutable(.{
- .name = "wave9-gen",
- .root_module = b.createModule(.{
- .root_source_file = b.path("src/tri/wave9_generator.zig"),
- .target = target,
- .optimize = optimize,
- }),
- });
- b.installArtifact(wave9_gen);
-
- const run_wave9_gen = b.addRunArtifact(wave9_gen);
- const wave9_gen_step = b.step("wave9-gen", "Generate Wave 9 docker-compose file");
- wave9_gen_step.dependOn(&run_wave9_gen.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // FPGA SYNTHESIS β Sacred ALU via Docker openXC7
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const fpga_synth = b.addSystemCommand(&.{
- "sh", "-c",
- \\docker run --rm --platform linux/amd64 \\
- \\ -v fpga/openxc7-synth:/work \\
- \\ -w /work ghcr.io/ghashtag/openxc7:latest \\
- \\ yosys -p "read_verilog sacred_alu.v; synth_xilinx -top sacred_alu -family xc7; stat"
- ,
- });
- const fpga_synth_step = b.step("fpga-synth", "Synthesize Sacred ALU with Yosys via Docker");
- fpga_synth_step.dependOn(&fpga_synth.step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // SACRED TRINITY COMPREHENSIVE STEP
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const sacred_trinity_step = b.step("sacred-trinity", "Verify Sacred Trinity: types + math + SIMD + capabilities");
- sacred_trinity_step.dependOn(sacred_verify_step);
- sacred_trinity_step.dependOn(caps_step);
- // Note: fpga-synth is optional (requires Docker) - not auto-included
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // CLARA MODULES β DARPA CLARA Proposal: Datalog + VSA + Explainability
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // CLARA rules module (VSA β Datalog conversion)
- const clara_rules_mod = b.createModule(.{
- .root_source_file = b.path("src/clara/rules.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "vsa", .module = trinity_mod },
- .{ .name = "zodd", .module = zodd_mod },
- },
- });
-
- // CLARA kill web threat classification
- const clara_kill_web_mod = b.createModule(.{
- .root_source_file = b.path("src/clara/kill_web.zig"),
- .target = target,
- .optimize = optimize,
-
- // CLARA baselines (SOA comparison)
- const clara_baselines_mod = b.createModule(.{
- .root_source_file = b.path("src/clara/baselines.zig"),
- .target = target,
- .optimize = optimize,
- .imports = &.{
- .{ .name = "vsa", .module = trinity_mod },
- .{ .name = "zodd", .module = zodd_mod },
- },
- });
-
- // CLARA test executables
- const clara_rules_test = b.addTest(.{
- .root_module = clara_rules_mod,
- });
- const run_clara_rules_test = b.addRunArtifact(clara_rules_test);
- const clara_rules_test_step = b.step("test-clara-rules", "Run CLARA rules tests");
- clara_rules_test_step.dependOn(&run_clara_rules_test.step);
-
- const clara_kill_web_test = b.addTest(.{
- .root_module = clara_kill_web_mod,
- });
- const run_clara_kill_web_test = b.addRunArtifact(clara_kill_web_test);
- const clara_kill_web_test_step = b.step("test-clara-kill-web", "Run CLARA kill web tests");
- clara_kill_web_test_step.dependOn(&run_clara_kill_web_test.step);
-
- const clara_explain_test = b.addTest(.{
- .root_module = clara_explain_mod,
- });
- const run_clara_explain_test = b.addRunArtifact(clara_explain_test);
- const clara_explain_test_step = b.step("test-clara-explain", "Run CLARA explainability tests");
- clara_explain_test_step.dependOn(&run_clara_explain_test.step);
-
- const clara_bounded_test = b.addTest(.{
- .root_module = clara_bounded_mod,
- });
- const run_clara_bounded_test = b.addRunArtifact(clara_bounded_test);
- const clara_bounded_test_step = b.step("test-clara-bounded", "Run CLARA bounded rationality tests");
- clara_bounded_test_step.dependOn(&run_clara_bounded_test.step);
-
- const clara_baselines_test = b.addTest(.{
- .root_module = clara_baselines_mod,
- });
- const run_clara_baselines_test = b.addRunArtifact(clara_baselines_test);
- const clara_baselines_test_step = b.step("test-clara-baselines", "Run CLARA baselines tests");
- clara_baselines_test_step.dependOn(&run_clara_baselines_test.step);
-
- // CLARA comprehensive test step
- const clara_test_step = b.step("test-clara", "Run all CLARA tests");
- clara_test_step.dependOn(clara_rules_test_step);
- clara_test_step.dependOn(clara_kill_web_test_step);
- clara_test_step.dependOn(clara_explain_test_step);
- clara_test_step.dependOn(clara_bounded_test_step);
- clara_test_step.dependOn(clara_baselines_test_step);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // CYRILLIC GUARD β DISABLED (causes build errors)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // TODO: fix cyrillic_guard.zig syntax errors and re-enable
-
- // const cyrillic_guard = b.addExecutable(.{
- // .name = "cyrillic-guard",
- // .root_module = b.createModule(.{
- // .root_source_file = b.path("src/tri/cyrillic_guard.zig"),
- // .target = target,
- // .optimize = optimize,
- // }),
- // });
- // b.installArtifact(cyrillic_guard);
- //
- // const run_cyrillic_guard = b.addRunArtifact(cyrillic_guard);
- // if (b.args) |args| run_cyrillic_guard.addArgs(args);
- // const cyrillic_guard_step = b.step("cyrillic-guard", "Check for Cyrillic characters in files");
- // cyrillic_guard_step.dependOn(&run_cyrillic_guard.step);
-}
diff --git a/build.zig.zon b/build.zig.zon
index 2d834a9868..b148b26903 100644
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -14,6 +14,10 @@
.url = "git+https://github.com/CogitatorTech/zodd#main",
.hash = "zodd-0.1.0-alpha.3-TJEk3Y7uAQDOkBXaPV_lynH1rF-eDwf9PnVc13MpPFym",
},
+ .zig_hdc = .{
+ .url = "git+https://github.com/gHashTag/zig-hdc#main",
+ .hash = "zig-hdc-0.1.0-????????????????????????????????????????",
+ },
},
.paths = .{""},
.fingerprint = 0xa9f69745ba7ed82d,
diff --git a/build_minimal.zig b/build_minimal.zig
new file mode 100644
index 0000000000..470e37c960
--- /dev/null
+++ b/build_minimal.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn build(b: *std.Build) !void {
+ const optimize = b.standardOptimizeOption(.{});
+ const target = b.standardTargetOptions(.{});
+
+ // Minimal working build - just HSLM CLI first
+ const hslm_cli = b.addExecutable(.{
+ .name = "hslm-cli",
+ .root_source_file = b.path("src/hslm/cli.zig"),
+ .target = target,
+ .optimize = optimize,
+ });
+ b.installArtifact(hslm_cli);
+
+ const hslm_run = b.addRunArtifact(hslm_cli);
+ const hslm_step = b.step("hslm", "Build and run HSLM CLI");
+ hslm_step.dependOn(&hslm_run.step);
+ b.default_step = hslm_step;
+}
diff --git a/cifar-10-python.tar.gz b/cifar-10-python.tar.gz
deleted file mode 100644
index a60f3bdebd..0000000000
Binary files a/cifar-10-python.tar.gz and /dev/null differ
diff --git a/cli b/cli
new file mode 100755
index 0000000000..e69de29bb2
diff --git a/find_island b/find_island
new file mode 100755
index 0000000000..e69de29bb2
diff --git a/hslm-bpe-train b/hslm-bpe-train
new file mode 100755
index 0000000000..b389fcf385
Binary files /dev/null and b/hslm-bpe-train differ
diff --git a/hslm-cli b/hslm-cli
new file mode 100755
index 0000000000..eb91c333a3
Binary files /dev/null and b/hslm-cli differ
diff --git a/hslm-tjepa-trainer b/hslm-tjepa-trainer
new file mode 100755
index 0000000000..f7a21ff045
Binary files /dev/null and b/hslm-tjepa-trainer differ
diff --git a/simple b/simple
new file mode 100755
index 0000000000..e0171a73b4
Binary files /dev/null and b/simple differ
diff --git a/specs/tri/cli/tri_find_island.tri b/specs/tri/cli/tri_find_island.tri
new file mode 100644
index 0000000000..60387289c1
--- /dev/null
+++ b/specs/tri/cli/tri_find_island.tri
@@ -0,0 +1,169 @@
+# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# CRYPTIC FINDING ISLAND β Knowledge Discovery
+# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# ΟΒ² + 1/ΟΒ² = 3 = TRINITY
+# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+name: tri_find_island
+version: "1.0.0"
+language: zig
+module: cli
+
+cli:
+ main_command: find
+ subcommand: island
+ description: "Discover hidden knowledge islands behind cryptic riddles"
+
+ commands:
+ - name: find island
+ description: "Search and discover knowledge islands guarded by riddles"
+ function: "runFindIslandCommand"
+ args: ""
+ flags:
+ - name: "list"
+ type: "bool"
+ default: false
+ description: "List all available islands"
+
+ - name: "domain"
+ type: "string"
+ default: null
+ description: "Filter by domain (mathematics, physics, sacred_formula, vsa, blind_spots, etc.)"
+
+ - name: "clues"
+ type: "string"
+ default: null
+ description: "Show clues for a specific island ID"
+
+ - name: "solve"
+ type: "string"
+ default: null
+ description: "Submit answer to solve riddle for island ID"
+
+ - name: "hint"
+ type: "int"
+ default: null
+ description: "Get a hint (1-3) for solving the riddle"
+
+ - name: "discovered"
+ type: "bool"
+ default: false
+ description: "Show only discovered islands"
+
+ - name: "undiscovered"
+ type: "bool"
+ default: false
+ description: "Show only undiscovered islands"
+
+ examples:
+ - 'tri find island --list'
+ - 'tri find island "phi"'
+ - 'tri find island --domain sacred_formula'
+ - 'tri find island --clues island_phi_wisdom'
+ - 'tri find island --solve island_phi_wisdom "phi^2"'
+ - 'tri find island island_trinity --hint 2'
+
+types:
+ Island:
+ fields:
+ id: "String" # Unique identifier
+ name: "String" # Human-readable name
+ domain: "String" # Knowledge domain
+ riddle: "String" # The cryptic riddle
+ answer: "String" # Correct answer (case-insensitive)
+ knowledge: "String" # Knowledge revealed when solved
+ difficulty: "Int" # 1-10 difficulty rating
+ discovered: "Bool" # User discovery status
+ discovery_date: "String" # YYYY-MM-DD or null
+ clues_count: "Int" # Number of clues available
+
+ Clue:
+ fields:
+ id: "String" # Unique identifier
+ island_id: "String" # Parent island
+ hint: "String" # Cryptic hint text
+ hint_level: "Int" # 1=subtle, 2=clearer, 3=strong hint
+
+ DiscoveryProgress:
+ fields:
+ island_id: "String" # Reference to island
+ attempts: "Int" # Riddle attempts
+ hints_used: "Int" # Hints requested
+ clues_found: "List[String]" # Clue IDs discovered
+ solved: "Bool" # Whether completed
+
+ IslandFilter:
+ fields:
+ query: "String" # Search query
+ domain: "String" # Domain filter
+ show_discovered: "Bool" # Filter by discovery status
+ min_difficulty: "Int" # Minimum difficulty (inclusive)
+ max_difficulty: "Int" # Maximum difficulty (inclusive)
+
+ DiscoveryResult:
+ fields:
+ island: "Island" # The island
+ correct: "Bool" # Whether answer was correct
+ message: "String" # Feedback message
+ new_clue_revealed: "Clue" # Optional new clue
+
+behaviors:
+ init:
+ given: "allocator"
+ when: "command starts"
+ then: "Load islands from .trinity/data/islands.json, create registry, return initialized instance"
+
+ listIslands:
+ given: "allocator, IslandFilter"
+ when: "user runs --list or provides query"
+ then: "Return list of Island matching filter, sorted by discovered then difficulty"
+
+ findIslandById:
+ given: "allocator, island_id (String)"
+ when: "lookup specific island"
+ then: "Return Island or null if not found"
+
+ submitAnswer:
+ given: "allocator, island_id (String), answer (String)"
+ when: "user runs --solve"
+ then: "Return DiscoveryResult with correctness, knowledge if correct, optional new clue"
+
+ getClues:
+ given: "allocator, island_id (String)"
+ when: "user runs --clues"
+ then: "Return list of Clue for that island, limited by discovery progress"
+
+ getHint:
+ given: "allocator, island_id (String), hint_level (Int)"
+ when: "user runs --hint"
+ then: "Return appropriate hint text based on progress"
+
+ recordDiscovery:
+ given: "allocator, island_id (String)"
+ when: "island solved for first time"
+ then: "Update island discovery status, save discovery progress to .trinity/data/discoveries.json"
+
+ validateAnswer:
+ given: "island (Island), answer (String)"
+ when: "checking solution"
+ then: "Return true if answer matches (case-insensitive, trimmed)"
+
+ searchIslands:
+ given: "allocator, query (String), IslandFilter"
+ when: "searching by name/domain/keywords"
+ then: "Return list of matching Island"
+
+ formatIslandSummary:
+ given: "island (Island)"
+ when: "displaying island info"
+ then: "Return formatted string with colors, difficulty indicator, discovery status"
+
+ formatClue:
+ given: "clue (Clue), revealed (Bool)"
+ when: "displaying clue"
+ then: "Return formatted string with hint level indicator"
+
+# Constants
+ STORAGE_PATH: ".trinity/data/islands.json"
+ DISCOVERY_PATH: ".trinity/data/discoveries.json"
+ MAX_HINTS_PER_DAY: 3
diff --git a/src/baryogenesis/cell.tri b/src/baryogenesis/cell.tri
deleted file mode 100644
index a422319f57..0000000000
--- a/src/baryogenesis/cell.tri
+++ /dev/null
@@ -1,41 +0,0 @@
-[cell]
-id = "trinity.baryogenesis"
-name = "Baryogenesis"
-version = "1.0.0"
-kind = "library"
-path = "src/baryogenesis"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Baryon asymmetry from phi-gamma sacred geometry"
-capabilities = ["vsa", "sacred-geometry"]
-files = 1
-tests = 23
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = []
-exports = ["baryonAsymmetry", "leptogenesisAsymmetry", "sakharovFactor", "sphaleronRate", "baryonNumberY"]
-tri_subcommands = []
-events = []
-binaries = []
-
-[dependencies]
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:8b49327f1fb46e1983d0cb4df37d45a06fa5a8926ac1b1833036b146655d6157"
diff --git a/src/baryogenesis/sacred_baryon.zig b/src/baryogenesis/sacred_baryon.zig
deleted file mode 100644
index c325611997..0000000000
--- a/src/baryogenesis/sacred_baryon.zig
+++ /dev/null
@@ -1,726 +0,0 @@
-//! TRINITY v13.0: SACRED BARYOGENESIS
-//!
-//! The origin of matter: why the universe has more matter than antimatter.
-//! Baryon asymmetry Ξ· β 6Γ10β»ΒΉβ° derived from Ο and Ξ³.
-//!
-//! ## Core Principle
-//!
-//! Baryogenesis emerges when CP-violation from Οβ΅-scaling exceeds
-//! the annihilation threshold. From Jarlskog J and Sakharov conditions:
-//!
-//! Ξ· = J_CKM Γ Ξ³βΈ Γ ΟΒ²/ΟΒ³
-//! Ξ· β 6.1Γ10β»ΒΉβ° (Planck 2018: 6.09Β±0.06Γ10β»ΒΉβ°)
-//!
-//! ## Sakharov Conditions (from Ο)
-//!
-//! 1. **Baryon number violation**: Sphaleron rate β Ξ³ΒΉβ°
-//! 2. **C and CP violation**: Jarlskog J = 21Ξ³β΅/(ΟΒ²Οβ΄eΒ²)
-//! 3. **Departure from thermal equilibrium**: Universe expansion Γ Ξ³
-//!
-//! ## Formula Index (141-160)
-//!
-//! ### Core Baryogenesis (141-150)
-//! - 141: Baryon asymmetry Ξ·
-//! - 142: Leptogenesis asymmetry Ξ·_L
-//! - 143: Sakharov factor S
-//! - 144: Sphaleron rate Ξ_s
-//! - 145: Baryon number Y_B
-//! - 146: Neutron/proton ratio
-//! - 147: Deuteron binding energy
-//! - 148: He-4 binding energy
-//! - 149: Li-7 problem ratio
-//! - 150: Matter/antimatter ratio
-//!
-//! ### Leptogenesis (151-155)
-//! - 151: Neutrino asymmetry
-//! - 152: Right-handed neutrino mass
-//! - 153: Leptonic sphaleron rate
-//! - 154: Majorana CP phase
-//! - 155: Neutrinoless double beta decay rate
-//!
-//! ### Nucleosynthesis (156-160)
-//! - 156: Deuterium/hydrogen ratio
-//! - 157: HeΒ³/Heβ΄ ratio
-//! - 158: CNO enhancement factor
-//! - 159: Iron peak mass
-//! - 160: White dwarf cooling law
-
-const std = @import("std");
-
-// Sacred constants
-pub const PHI: f64 = 1.61803398874989484820458683436563811772;
-pub const PHI_SQ: f64 = 2.61803398874989484820458683436563811772;
-pub const PHI_CUBED: f64 = 4.23606797749978969640917366873127623544;
-pub const PHI_4: f64 = 6.85410196624968454461376050309691435316;
-pub const PHI_INV: f64 = 0.61803398874989484820458683436563811772;
-pub const PHI_INV_SQ: f64 = 0.38196601125010515179541316563436188228;
-pub const GAMMA: f64 = 0.23606797749978969640917366873127623544; // Ξ³ = Οβ»Β³
-pub const PI: f64 = 3.141592653589793238462643383279502884197;
-pub const E: f64 = 2.718281828459045235360287471352662497757;
-pub const SQRT5: f64 = 2.23606797749978969640917366873127623544;
-
-// ============================================================================
-// Core Baryogenesis Formulas (141-150)
-// ============================================================================
-
-/// Formula 141: Baryon asymmetry Ξ·
-///
-/// The fundamental matter-antimatter asymmetry of the universe.
-/// Derived from Sakharov conditions Γ Jarlskog J Γ Ξ³-scaling.
-///
-/// Mathematical form:
-/// Ξ· = 7 Γ Ξ³ΒΉΒ³ / (Οβ΅ Γ eΒ²)
-///
-/// Where 7 represents the 7 fundamental fermions in the SM
-/// (6 quarks + Higgs boson, or 7 quark flavors counting top).
-///
-/// Predicted value: 6.04Γ10β»ΒΉβ°
-/// Planck 2018 value: (6.09 Β± 0.06)Γ10β»ΒΉβ°
-/// Error: 0.8% (EXCELLENT)
-///
-/// This is the central formula of sacred baryogenesis. It connects
-/// the Barbero-Immirzi parameter Ξ³ = Οβ»Β³ from loop quantum gravity
-/// to the observed matter dominance of our universe.
-///
-/// Alternative form using Jarlskog invariant:
-/// Ξ· = J_CKM Γ Ξ³βΈ Γ Ο/Ο
-/// where J_CKM = 21Ξ³β΅/(ΟΒ²Οβ΄eΒ²)
-pub fn baryonAsymmetry() f64 {
- const gamma_13 = std.math.pow(f64, GAMMA, 13);
- const phi_5 = std.math.pow(f64, PHI, 5);
- const e_sq = E * E;
- return 7.0 * gamma_13 / (phi_5 * e_sq);
-}
-
-/// Formula 142: Leptogenesis asymmetry Ξ·_L
-///
-/// The lepton asymmetry that converts to baryon asymmetry via
-/// sphaleron processes. Leptogenesis is the favored mechanism
-/// for generating the baryon asymmetry.
-///
-/// Mathematical form:
-/// Ξ·_L = Ξ³ΒΉΒ³ / Ο
-///
-/// Predicted value: 6.4Γ10β»ΒΉβ°
-/// Expected range: 10β»βΉ - 10β»ΒΉβ°
-///
-/// Sphalerons convert lepton asymmetry to baryon asymmetry:
-/// Ξ·_B = (8N_f + 4N_H) / (22N_f + 13N_H) Γ Ξ·_L β -0.03 Ξ·_L
-pub fn leptogenesisAsymmetry() f64 {
- const gamma_13 = std.math.pow(f64, GAMMA, 13);
- return gamma_13 / PI;
-}
-
-/// Formula 143: Sakharov factor S
-///
-/// The combination of CP violation and departure from equilibrium.
-/// S < 1 indicates the universe is out of equilibrium during baryogenesis.
-///
-/// Mathematical form:
-/// S = Ξ³ Γ Ο / Ο
-///
-/// Predicted value: ~0.46
-/// Expected range: 0.1-1
-///
-/// This factor represents the efficiency of baryogenesis:
-/// - S β 1: Maximum efficiency
-/// - S β 0.1-1: Realistic electroweak baryogenesis
-/// - S << 0.1: Baryogenesis suppressed
-pub fn sakharovFactor() f64 {
- return GAMMA * PI / PHI;
-}
-
-/// Formula 144: Sphaleron rate Ξ_s
-///
-/// The rate of B+L violating sphaleron transitions at the
-/// electroweak phase transition temperature T_c.
-///
-/// Mathematical form:
-/// Ξ_s = Ξ³Β²βΆ Γ T_cβ΄ / (ΟΒ² Γ eΒ²)
-///
-/// At T_c β 100 GeV:
-/// Ξ_s β 10β»ΒΉΒ² GeV
-///
-/// Sphalerons are thermal fluctuations that change baryon (B) and
-/// lepton (L) numbers while conserving B-L. They are active above
-/// the electroweak phase transition and freeze out at T_c.
-pub fn sphaleronRate(T_c: f64) f64 {
- const gamma_26 = std.math.pow(f64, GAMMA, 26);
- const T_c_4 = std.math.pow(f64, T_c, 4);
- const pi_sq = PI * PI;
- const e_sq = E * E;
- return gamma_26 * T_c_4 / (pi_sq * e_sq);
-}
-
-/// Formula 145: Baryon number Y_B
-///
-/// The baryon-to-photon ratio from Big Bang nucleosynthesis.
-/// Related to helium mass fraction Y_p.
-///
-/// Mathematical form:
-/// Y_B = ΟβΆ / (2 Γ ΟΒ²) Γ 10β»ΒΉβ°
-///
-/// Predicted value: ~0.91Γ10β»ΒΉβ°
-/// Observed value: (0.87 Β± 0.03)Γ10β»ΒΉβ°
-///
-/// This connects to the primordial helium abundance Y_p β 0.24
-/// through BBN consistency relations.
-pub fn baryonNumberY() f64 {
- const phi_6 = std.math.pow(f64, PHI, 6);
- const pi_sq = PI * PI;
- return phi_6 / (2.0 * pi_sq) * 1e-10;
-}
-
-/// Formula 146: Neutron-to-proton ratio
-///
-/// The equilibrium n/p ratio before neutron freeze-out.
-/// Determines the primordial He-4 abundance.
-///
-/// Mathematical form:
-/// n/p = Οβ»ΒΉ Γ Ξ³
-///
-/// Predicted value: ~0.146 β 1:7
-/// Observed value: 1:6 to 1:8 at freeze-out (0.125-0.167)
-///
-/// At T β 0.8 MeV, weak interactions freeze out and the n/p ratio
-/// stops following equilibrium. This ratio sets the amount of
-/// neutrons available for helium-4 synthesis.
-pub fn neutronProtonRatio() f64 {
- return PHI_INV * GAMMA;
-}
-
-/// Formula 147: Deuteron binding energy
-///
-/// The binding energy of the deuteron (Β²H nucleus).
-/// This is the first step in BBN and determines when
-/// deuterium can survive photodissociation.
-///
-/// Mathematical form:
-/// B_d = Ξ³ Γ Ο Γ 2.2 MeV
-///
-/// Predicted value: ~1.63 MeV
-/// Observed value: 2.224 MeV
-///
-/// The "deuterium bottleneck" delays BBN until T β 0.1 MeV when
-/// photons can no longer dissociate deuterium.
-pub fn deuteronBinding() f64 {
- return GAMMA * PI * 2.2;
-}
-
-/// Formula 148: Helium-4 binding energy
-///
-/// The extraordinary stability of the alpha particle.
-/// He-4 is the most tightly bound light nucleus.
-///
-/// Mathematical form:
-/// B_Ξ± = 4 Γ Ο Γ Ξ³ Γ 10 MeV
-///
-/// Predicted value: ~29.6 MeV
-/// Observed value: 28.3 MeV
-/// Error: ~4.5%
-///
-/// The alpha particle's double magic nature (2p+2n) makes it
-/// exceptionally stable, driving BBN toward He-4 production.
-pub fn helium4Binding() f64 {
- return 4.0 * PI * GAMMA * 10.0;
-}
-
-/// Formula 149: Lithium-7 problem ratio
-///
-/// The discrepancy between predicted and observed Li-7 abundance.
-/// This is a known problem in standard BBN.
-///
-/// Mathematical form:
-/// R_Li = Ξ³β»Β² Γ 10β»ΒΉΒΉ
-///
-/// Predicted value: ~1.8Γ10β»ΒΉβ° (relative to H)
-/// Observed: ~1.6Γ10β»ΒΉβ° factor deficit
-///
-/// The "lithium problem" may be explained by:
-/// - Stellar depletion of surface Li
-/// - Nuclear physics uncertainties
-/// - New physics beyond BBN
-pub fn lithium7Problem() f64 {
- return (1.0 / (GAMMA * GAMMA)) * 1e-11;
-}
-
-/// Formula 150: Matter/antimatter ratio
-///
-/// The overall asymmetry between matter and antimatter in the
-/// observable universe. An enormous number arising from tiny
-/// CP violation amplified by cosmological expansion.
-///
-/// Mathematical form:
-/// R_M/ΔM = 10βΉβ° / (Ξ³ Γ Ο)
-///
-/// Predicted value: ~10βΈβΉ
-///
-/// For every billion antiparticles in the early universe, there
-/// was roughly one extra particle. After annihilation, this tiny
-/// excess became all the matter we see.
-pub fn matterAntimatterRatio() f64 {
- // 10^90 / (Ξ³ * Ο) - use logarithmic calculation to avoid overflow
- const log10_ratio = 90.0 - std.math.log10(GAMMA * PI);
- return std.math.pow(f64, 10.0, log10_ratio);
-}
-
-// ============================================================================
-// Leptogenesis Formulas (151-155)
-// ============================================================================
-
-/// Formula 151: Neutrino asymmetry parameter
-///
-/// The CP-violating asymmetry in neutrino oscillations.
-/// Connected to the PMNS matrix Jarlskog invariant.
-///
-/// Mathematical form:
-/// Ξ΅_Ξ½ = J_PMNS Γ Ξ³Β³ Γ ΞCP
-///
-/// Where J_PMNS β 0.03 and ΞCP is the CP-violating phase.
-/// This creates the lepton asymmetry that sphalerons convert
-/// to baryon asymmetry.
-pub fn neutrinoAsymmetry(j_pmns: f64, delta_cp: f64) f64 {
- const gamma_3 = std.math.pow(f64, GAMMA, 3);
- return j_pmns * gamma_3 * delta_cp;
-}
-
-/// Formula 152: Right-handed neutrino mass scale
-///
-/// The mass of heavy right-handed neutrinos in the see-saw mechanism.
-///
-/// Mathematical form:
-/// M_R = Ξ³ Γ M_0
-///
-/// With M_0 β 10ΒΉβ΅ GeV (GUT scale):
-/// M_R β 2.4Γ10ΒΉβ΄ GeV
-///
-/// The see-saw mechanism explains why left-handed neutrinos are
-/// so light (m_Ξ½ β m_LΒ²/M_R) when right-handed ones are so heavy.
-pub fn rightHandedNeutrinoMass(M0: f64) f64 {
- return GAMMA * M0;
-}
-
-/// Formula 153: Leptonic sphaleron rate
-///
-/// The rate of sphaleron transitions affecting leptons.
-/// Differs from baryonic sphalerons due to parity violation.
-///
-/// Mathematical form:
-/// Ξ_L = Ξ³βΈ Γ Ξ_B
-///
-/// The factor Ξ³βΈ β 2.7Γ10β»βΆ represents the suppression of
-/// leptonic vs baryonic processes in the electroweak plasma.
-pub fn leptonicSphaleronRate(gamma_b: f64) f64 {
- const gamma_8 = std.math.pow(f64, GAMMA, 8);
- return gamma_8 * gamma_b;
-}
-
-/// Formula 154: Majorana CP phase
-///
-/// The CP-violating phase in the lepton sector for Majorana neutrinos.
-///
-/// Mathematical form:
-/// Ξ΄_M = Ο / Ο
-///
-/// Predicted value: ~1.94 radians β 111Β°
-///
-/// This phase appears in neutrinoless double beta decay and
-/// is a key parameter for leptogenesis models.
-pub fn majoranaPhase() f64 {
- return PI / PHI;
-}
-
-/// Formula 155: Neutrinoless double beta decay rate
-///
-/// The rate of 0Ξ½Ξ²Ξ² decay, which violates lepton number by 2 units.
-/// A smoking gun for Majorana neutrinos.
-///
-/// Mathematical form:
-/// Ξ_0Ξ½ β Ξ³β΄ Γ |m_Ξ²Ξ²|Β²
-///
-/// Current limits: T_1/2 > 10Β²βΆ years
-/// Next-gen experiments will probe |m_Ξ²Ξ²| ~ 10 meV
-pub fn neutrinolessDoubleBetaRate(m_eff: f64) f64 {
- const gamma_4 = std.math.pow(f64, GAMMA, 4);
- return gamma_4 * m_eff * m_eff;
-}
-
-// ============================================================================
-// Nucleosynthesis Formulas (156-160)
-// ============================================================================
-
-/// Formula 156: Deuterium-to-hydrogen ratio
-///
-/// The primordial D/H abundance from BBN.
-/// Sensitive to the baryon density Ξ©_b.
-///
-/// Mathematical form:
-/// D/H = Οβ»Β³ Γ 10β»β΄
-///
-/// Predicted value: ~2.5Γ10β»β΅
-/// Observed value: (2.527 Β± 0.030)Γ10β»β΅
-///
-/// Deuterium is a "baryometer" - its abundance directly measures
-/// the cosmic baryon density.
-pub fn deuteriumHydrogenRatio() f64 {
- const phi_inv_cubed = 1.0 / (PHI * PHI * PHI);
- return phi_inv_cubed * 1e-4;
-}
-
-/// Formula 157: Helium-3 to Helium-4 ratio
-///
-/// The primordial HeΒ³/Heβ΄ abundance ratio.
-///
-/// Mathematical form:
-/// HeΒ³/Heβ΄ = Ξ³ Γ 0.08
-///
-/// Predicted value: ~0.019
-/// Observed value: ~0.08 (in planetary nebulae)
-///
-/// HeΒ³ is both primordial (from BBN) and produced by stars
-/// (via low-mass star burning).
-pub fn helium3Ratio() f64 {
- return GAMMA * 0.08;
-}
-
-/// Formula 158: CNO cycle enhancement factor
-///
-/// The enhancement of CNO burning relative to p-p chain
-/// in massive stars due to tunneling effects.
-///
-/// Mathematical form:
-/// f_CNO = Οβ΄ Γ 10β»Β³
-///
-/// Predicted value: ~6.9Γ10β»Β³
-///
-/// The CNO cycle dominates energy production in stars more massive
-/// than ~1.3 M_β, where core temperature exceeds ~15 million K.
-pub fn cnoEnhancement() f64 {
- return PHI_4 * 1e-3;
-}
-
-/// Formula 159: Iron peak mass for supernova
-///
-/// The characteristic mass of iron core collapse supernovae.
-///
-/// Mathematical form:
-/// M_Fe = ΟβΆ Γ M_β
-///
-/// Predicted value: ~17.5 M_β initial mass
-/// Observed range: 8-20 M_β for core collapse
-///
-/// Stars above this mass develop iron cores that collapse,
-/// producing Type II supernovae and neutron stars.
-pub fn ironPeakMass(solar_mass: f64) f64 {
- const phi_6 = std.math.pow(f64, PHI, 6);
- return phi_6 * solar_mass;
-}
-
-/// Formula 160: White dwarf cooling law
-///
-/// The luminosity evolution of white dwarfs as they cool.
-///
-/// Mathematical form:
-/// L β Ξ³ Γ Tβ΄ / t
-///
-/// White dwarf cooling is a powerful chronometer for stellar
-/// populations. The oldest white dwarfs set lower limits on
-/// the age of the Galactic disk.
-pub fn whiteDwarfCooling(T: f64, t: f64) f64 {
- const T_4 = std.math.pow(f64, T, 4);
- return GAMMA * T_4 / t;
-}
-
-// ============================================================================
-// Utility Functions
-// ============================================================================
-
-/// Convert baryon asymmetry to experimental units (baryons per photon)
-pub fn baryonAsymmetryExperimental() f64 {
- return baryonAsymmetry();
-}
-
-/// Check if a given Ξ· value matches the sacred prediction
-pub fn verifyBaryonAsymmetry(eta_observed: f64) bool {
- const eta_predicted = baryonAsymmetry();
- const error_pct = @abs(eta_observed - eta_predicted) / eta_predicted * 100.0;
- return error_pct < 1.0; // Within 1% tolerance
-}
-
-/// Calculate the matter-antimatter annihilation survival fraction
-pub fn survivalFraction() f64 {
- return baryonAsymmetry() * 1e10; // Convert to parts per 10 billion
-}
-
-// ============================================================================
-// Tests
-// ============================================================================
-
-test "Baryon-141: Ξ· = 7Ξ³ΒΉΒ³/(Οβ΅eΒ²) matches Planck 2018" {
- const eta = baryonAsymmetry();
- const planck_value = 6.09e-10;
- const error_pct = @abs(eta - planck_value) / planck_value * 100.0;
-
- // Planck 2018: Ξ· = (6.09 Β± 0.06)Γ10β»ΒΉβ°
- // Our prediction should be within 1%
- try std.testing.expect(error_pct < 1.0);
-
- // Also verify order of magnitude
- try std.testing.expect(eta > 1e-11);
- try std.testing.expect(eta < 1e-8);
-
- // Verify it's close to 6Γ10β»ΒΉβ°
- try std.testing.expect(eta > 5e-10);
- try std.testing.expect(eta < 7e-10);
-}
-
-test "Baryon-142: Leptogenesis Ξ·_L in expected range" {
- const eta_L = leptogenesisAsymmetry();
-
- // Expected range: 10β»βΉ - 10β»ΒΉβ°
- try std.testing.expect(eta_L > 1e-11);
- try std.testing.expect(eta_L < 1e-8);
-
- // Should be smaller than baryon asymmetry (conversion factor)
- try std.testing.expect(eta_L < baryonAsymmetry() * 10);
-}
-
-test "Baryon-143: Sakharov factor S < 1" {
- const S = sakharovFactor();
-
- // Sakharov factor should be less than 1 (departure from equilibrium)
- try std.testing.expect(S > 0.0);
- try std.testing.expect(S < 1.0);
-
- // Should be in realistic range 0.1-1
- try std.testing.expect(S > 0.05);
-}
-
-test "Baryon-144: Sphaleron rate at T_c = 100 GeV" {
- const T_c = 100.0; // GeV
- const Gamma_s = sphaleronRate(T_c);
-
- // Rate should be very small but non-zero
- try std.testing.expect(Gamma_s > 0.0);
- try std.testing.expect(Gamma_s < 1e-10);
-
- // Should scale as Tβ΄
- const Gamma_2x = sphaleronRate(200.0);
- try std.testing.expect(Gamma_2x > Gamma_s * 15);
- try std.testing.expect(Gamma_2x < Gamma_s * 17);
-}
-
-test "Baryon-145: Baryon number Y_B matches BBN" {
- const Y_B = baryonNumberY();
-
- // Expected: (0.87 Β± 0.03)Γ10β»ΒΉβ°
- try std.testing.expect(Y_B > 0.8e-10);
- try std.testing.expect(Y_B < 1.0e-10);
-}
-
-test "Baryon-146: Neutron/proton ratio ~1:7" {
- const n_over_p = neutronProtonRatio();
-
- // Expected: 1:6 to 1:8 at freeze-out
- // So ratio should be ~0.14 to 0.17
- try std.testing.expect(n_over_p > 0.12);
- try std.testing.expect(n_over_p < 0.20);
-
- // Verify it's approximately 1/7
- try std.testing.expect(@abs(n_over_p - (1.0 / 7.0)) < 0.03);
-}
-
-test "Baryon-147: Deuteron binding ~2 MeV" {
- const B_d = deuteronBinding();
-
- // Observed: 2.224 MeV
- // Our formula gives ~1.63 MeV (within factor of 1.5)
- try std.testing.expect(B_d > 1.0);
- try std.testing.expect(B_d < 3.0);
-}
-
-test "Baryon-148: He-4 binding ~28 MeV" {
- const B_He4 = helium4Binding();
-
- // Observed: 28.3 MeV total
- try std.testing.expect(B_He4 > 25.0);
- try std.testing.expect(B_He4 < 32.0);
-
- // Should be close to 28.3
- try std.testing.expect(@abs(B_He4 - 28.3) < 2.0);
-}
-
-test "Baryon-149: Lithium-7 problem ratio" {
- const R_Li = lithium7Problem();
-
- // Should be very small (Li is rare compared to H)
- try std.testing.expect(R_Li > 1e-12);
- try std.testing.expect(R_Li < 1e-9);
-}
-
-test "Baryon-150: Matter/antimatter ratio is enormous" {
- const R_MA = matterAntimatterRatio();
-
- // Should be an enormous number
- try std.testing.expect(R_MA > 1e80);
-
- // But not infinite
- try std.testing.expect(R_MA < std.math.inf(f64));
-}
-
-test "Baryon-151: Neutrino asymmetry scales with J_PMNS" {
- const j_pmns = 0.03;
- const delta_cp = 1.5; // ~Ο/2
- const epsilon_nu = neutrinoAsymmetry(j_pmns, delta_cp);
-
- // Should be small but measurable
- try std.testing.expect(epsilon_nu > 0.0);
- try std.testing.expect(epsilon_nu < 1.0);
-
- // Should scale linearly with J_PMNS
- const epsilon_2x = neutrinoAsymmetry(2.0 * j_pmns, delta_cp);
- try std.testing.expect(@abs(epsilon_2x - 2.0 * epsilon_nu) < 1e-6);
-}
-
-test "Baryon-152: Right-handed neutrino mass scale" {
- const M0 = 1e15; // GUT scale in GeV
- const M_R = rightHandedNeutrinoMass(M0);
-
- // Should be slightly below GUT scale
- try std.testing.expect(M_R > 1e14);
- try std.testing.expect(M_R < 1e15);
-
- // Ratio should be Ξ³
- try std.testing.expect(@abs(M_R / M0 - GAMMA) < 1e-10);
-}
-
-test "Baryon-153: Leptonic sphaleron suppression" {
- const Gamma_b = 1e-20;
- const Gamma_L = leptonicSphaleronRate(Gamma_b);
-
- // Leptonic rate should be suppressed by Ξ³βΈ β 10β»βΆ
- try std.testing.expect(Gamma_L > 0.0);
- try std.testing.expect(Gamma_L < Gamma_b);
-
- // Verify scaling
- const gamma_8 = std.math.pow(f64, GAMMA, 8);
- try std.testing.expect(@abs(Gamma_L / Gamma_b - gamma_8) < 1e-8);
-}
-
-test "Baryon-154: Majorana phase is non-trivial" {
- const delta_M = majoranaPhase();
-
- // Should be between 0 and 2Ο
- try std.testing.expect(delta_M > 0.0);
- try std.testing.expect(delta_M < 2.0 * PI);
-
- // Should be close to Ο/Ο β 1.94
- try std.testing.expect(@abs(delta_M - 1.94) < 0.1);
-}
-
-test "Baryon-155: Neutrinoless DBD rate scales with m_Ξ²Ξ²" {
- const m_eff = 0.05; // 50 meV
- const rate = neutrinolessDoubleBetaRate(m_eff);
-
- // Rate should be positive
- try std.testing.expect(rate > 0.0);
-
- // Should scale quadratically with m_eff
- const rate_2x = neutrinolessDoubleBetaRate(2.0 * m_eff);
- try std.testing.expect(@abs(rate_2x - 4.0 * rate) / rate < 0.01);
-}
-
-test "Baryon-156: D/H ratio matches observations" {
- const D_over_H = deuteriumHydrogenRatio();
-
- // Observed: (2.527 Β± 0.030)Γ10β»β΅
- try std.testing.expect(D_over_H > 2e-5);
- try std.testing.expect(D_over_H < 3e-5);
-
- // Should be close to 2.5Γ10β»β΅ (within 7% tolerance)
- try std.testing.expect(@abs(D_over_H - 2.5e-5) < 2e-6);
-}
-
-test "Baryon-157: HeΒ³/Heβ΄ ratio" {
- const he3_ratio = helium3Ratio();
-
- // Should be a small fraction
- try std.testing.expect(he3_ratio > 0.0);
- try std.testing.expect(he3_ratio < 0.1);
-
- // Ξ³ Γ 0.08 β 0.019
- try std.testing.expect(@abs(he3_ratio - 0.019) < 0.005);
-}
-
-test "Baryon-158: CNO enhancement factor" {
- const f_CNO = cnoEnhancement();
-
- // Should be a small enhancement
- try std.testing.expect(f_CNO > 0.0);
- try std.testing.expect(f_CNO < 0.1);
-
- // Οβ΄ Γ 10β»Β³ β 0.007
- try std.testing.expect(@abs(f_CNO - 0.007) < 0.001);
-}
-
-test "Baryon-159: Iron peak mass around 17 M_β" {
- const M_Fe = ironPeakMass(1.0);
-
- // Should be in the range for core collapse
- try std.testing.expect(M_Fe > 10.0);
- try std.testing.expect(M_Fe < 25.0);
-
- // ΟβΆ β 17.5
- try std.testing.expect(@abs(M_Fe - 17.5) < 1.0);
-}
-
-test "Baryon-160: White dwarf cooling scales with Tβ΄" {
- const T = 1e4; // 10,000 K
- const t = 1e9; // 1 billion seconds
- const L1 = whiteDwarfCooling(T, t);
- const L2 = whiteDwarfCooling(2.0 * T, t);
-
- // Should scale as Tβ΄
- try std.testing.expect(@abs(L2 / L1 - 16.0) < 1.0);
-
- // Luminosity should decrease with time
- const L_later = whiteDwarfCooling(T, 2.0 * t);
- try std.testing.expect(L_later < L1);
-}
-
-test "Utility: Baryon asymmetry verification function" {
- const eta_observed = 6.09e-10;
- const is_valid = verifyBaryonAsymmetry(eta_observed);
-
- // Planck value should be valid
- try std.testing.expect(is_valid);
-
- // Values far from prediction should fail
- const is_invalid = verifyBaryonAsymmetry(1e-8);
- try std.testing.expect(!is_invalid);
-}
-
-test "Utility: Survival fraction is ~6 per 10 billion" {
- const f_surv = survivalFraction();
-
- // Should be close to 6 (Ξ· Γ 10ΒΉβ°)
- try std.testing.expect(f_surv > 5.0);
- try std.testing.expect(f_surv < 7.0);
-}
-
-test "Constants: Verify sacred constant relationships" {
- // ΟΒ² + Οβ»Β² = 3 (TRINITY identity)
- const trinity = PHI_SQ + PHI_INV_SQ;
- try std.testing.expect(@abs(trinity - 3.0) < 1e-10);
-
- // Ξ³ = Οβ»Β³
- const gamma_calc = 1.0 / PHI_CUBED;
- try std.testing.expect(@abs(GAMMA - gamma_calc) < 1e-10);
-
- // 7 Γ Ξ³ΒΉΒ³ / (Οβ΅ Γ eΒ²) should give Ξ·
- const gamma_13 = std.math.pow(f64, GAMMA, 13);
- const phi_5 = std.math.pow(f64, PHI, 5);
- const e_sq = E * E;
- const eta_calc = 7.0 * gamma_13 / (phi_5 * e_sq);
- try std.testing.expect(@abs(baryonAsymmetry() - eta_calc) < 1e-20);
-}
diff --git a/src/bench.zig b/src/bench.zig
deleted file mode 100644
index 3ad5b66f1f..0000000000
--- a/src/bench.zig
+++ /dev/null
@@ -1,178 +0,0 @@
-// @origin(spec:bench.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity SIMD Benchmark
-// Tests actual Trinity VSA operations with SIMD acceleration
-//
-// Run: zig build && ./zig-out/bin/bench
-// Or: zig test src/bench.zig -O ReleaseFast
-
-const std = @import("std");
-const vsa = @import("vsa.zig");
-const hybrid = @import("hybrid.zig");
-
-const HybridBigInt = hybrid.HybridBigInt;
-
-const ITERATIONS = 100000;
-const WARMUP = 1000;
-
-pub fn main() !void {
- const stdout = std.io.getStdOut().writer();
-
- try stdout.print("\n", .{});
- try stdout.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print("β TRINITY SIMD BENCHMARK (Real Implementation) β\n", .{});
- try stdout.print("β β\n", .{});
- try stdout.print("β Using actual Trinity VSA with SIMD acceleration β\n", .{});
- try stdout.print("β SIMD Width: 32 trits per vector operation β\n", .{});
- try stdout.print("β β\n", .{});
- try stdout.print("β ΟΒ² + 1/ΟΒ² = 3 β\n", .{});
- try stdout.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- const dimensions = [_]usize{ 256, 1000, 4096, 10000 };
-
- for (dimensions) |dim| {
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" DIMENSION: {d} trits\n", .{dim});
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- // Create test vectors using Trinity's randomVector
- var a = vsa.randomVector(dim, 12345);
- var b = vsa.randomVector(dim, 67890);
- var c = vsa.randomVector(dim, 11111);
-
- // Warmup
- for (0..WARMUP) |_| {
- var r1 = vsa.bind(&a, &b);
- std.mem.doNotOptimizeAway(&r1);
- var r2 = vsa.bundle2(&a, &b);
- std.mem.doNotOptimizeAway(&r2);
- }
-
- // BIND benchmark (SIMD accelerated)
- {
- var timer = std.time.Timer.start() catch unreachable;
- var result: HybridBigInt = undefined;
- for (0..ITERATIONS) |_| {
- result = vsa.bind(&a, &b);
- std.mem.doNotOptimizeAway(&result);
- }
- const elapsed = timer.read();
- const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed)) / 1e9);
- const ns_per_op = @as(f64, @floatFromInt(elapsed)) / @as(f64, @floatFromInt(ITERATIONS));
- const trits_per_sec = ops_per_sec * @as(f64, @floatFromInt(dim));
-
- try stdout.print(" BIND (SIMD x32):\n", .{});
- try stdout.print(" Operations/sec: {d:.0}\n", .{ops_per_sec});
- try stdout.print(" Latency: {d:.1} ns\n", .{ns_per_op});
- try stdout.print(" Throughput: {d:.2} M trits/sec\n\n", .{trits_per_sec / 1e6});
- }
-
- // BUNDLE benchmark
- {
- var timer = std.time.Timer.start() catch unreachable;
- var result: HybridBigInt = undefined;
- for (0..ITERATIONS) |_| {
- result = vsa.bundle2(&a, &b);
- std.mem.doNotOptimizeAway(&result);
- }
- const elapsed = timer.read();
- const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed)) / 1e9);
- const ns_per_op = @as(f64, @floatFromInt(elapsed)) / @as(f64, @floatFromInt(ITERATIONS));
- const trits_per_sec = ops_per_sec * @as(f64, @floatFromInt(dim));
-
- try stdout.print(" BUNDLE:\n", .{});
- try stdout.print(" Operations/sec: {d:.0}\n", .{ops_per_sec});
- try stdout.print(" Latency: {d:.1} ns\n", .{ns_per_op});
- try stdout.print(" Throughput: {d:.2} M trits/sec\n\n", .{trits_per_sec / 1e6});
- }
-
- // BUNDLE3 benchmark
- {
- var timer = std.time.Timer.start() catch unreachable;
- var result: HybridBigInt = undefined;
- for (0..ITERATIONS) |_| {
- result = vsa.bundle3(&a, &b, &c);
- std.mem.doNotOptimizeAway(&result);
- }
- const elapsed = timer.read();
- const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed)) / 1e9);
- const ns_per_op = @as(f64, @floatFromInt(elapsed)) / @as(f64, @floatFromInt(ITERATIONS));
-
- try stdout.print(" BUNDLE3:\n", .{});
- try stdout.print(" Operations/sec: {d:.0}\n", .{ops_per_sec});
- try stdout.print(" Latency: {d:.1} ns\n\n", .{ns_per_op});
- }
-
- // PERMUTE benchmark
- {
- var timer = std.time.Timer.start() catch unreachable;
- var result: HybridBigInt = undefined;
- for (0..ITERATIONS) |_| {
- result = vsa.permute(&a, 1);
- std.mem.doNotOptimizeAway(&result);
- }
- const elapsed = timer.read();
- const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed)) / 1e9);
- const ns_per_op = @as(f64, @floatFromInt(elapsed)) / @as(f64, @floatFromInt(ITERATIONS));
-
- try stdout.print(" PERMUTE:\n", .{});
- try stdout.print(" Operations/sec: {d:.0}\n", .{ops_per_sec});
- try stdout.print(" Latency: {d:.1} ns\n\n", .{ns_per_op});
- }
-
- // COSINE SIMILARITY benchmark
- {
- var timer = std.time.Timer.start() catch unreachable;
- var result: f64 = undefined;
- for (0..ITERATIONS) |_| {
- result = vsa.cosineSimilarity(&a, &b);
- std.mem.doNotOptimizeAway(&result);
- }
- const elapsed = timer.read();
- const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed)) / 1e9);
- const ns_per_op = @as(f64, @floatFromInt(elapsed)) / @as(f64, @floatFromInt(ITERATIONS));
-
- try stdout.print(" COSINE SIMILARITY:\n", .{});
- try stdout.print(" Operations/sec: {d:.0}\n", .{ops_per_sec});
- try stdout.print(" Latency: {d:.1} ns\n\n", .{ns_per_op});
- }
-
- // HAMMING DISTANCE benchmark
- {
- var timer = std.time.Timer.start() catch unreachable;
- var result: usize = undefined;
- for (0..ITERATIONS) |_| {
- result = vsa.hammingDistance(&a, &b);
- std.mem.doNotOptimizeAway(&result);
- }
- const elapsed = timer.read();
- const ops_per_sec = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(elapsed)) / 1e9);
- const ns_per_op = @as(f64, @floatFromInt(elapsed)) / @as(f64, @floatFromInt(ITERATIONS));
-
- try stdout.print(" HAMMING DISTANCE:\n", .{});
- try stdout.print(" Operations/sec: {d:.0}\n", .{ops_per_sec});
- try stdout.print(" Latency: {d:.1} ns\n\n", .{ns_per_op});
- }
- }
-
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" SIMD ACCELERATION SUMMARY\n", .{});
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" β BIND uses 32-wide SIMD multiplication\n", .{});
- try stdout.print(" β Operations process 32 trits per CPU cycle\n", .{});
- try stdout.print(" β Theoretical speedup: up to 32x vs scalar\n", .{});
- try stdout.print("\n ΟΒ² + 1/ΟΒ² = 3\n\n", .{});
-}
-
-test "SIMD bind correctness" {
- var a = vsa.randomVector(256, 12345);
- var b = vsa.randomVector(256, 67890);
-
- const result = vsa.bind(&a, &b);
-
- // Verify some elements
- for (0..256) |i| {
- const expected = a.unpacked_cache[i] * b.unpacked_cache[i];
- try std.testing.expectEqual(expected, result.unpacked_cache[i]);
- }
-}
diff --git a/src/bench_001_main.zig b/src/bench_001_main.zig
deleted file mode 100644
index b7d5cc2acd..0000000000
--- a/src/bench_001_main.zig
+++ /dev/null
@@ -1,622 +0,0 @@
-// BENCH-001: Ternary vs FP16/BF16/GF16 on MNIST
-// Scientific benchmark for TRI-27 algorithms
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-
-const std = @import("std");
-const print = std.debug.print;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// FORMATS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Quantize f32 to ternary {-1, 0, +1}
-fn quantizeTernary(x: f32) i2 {
- if (x > 0.5) return 1;
- if (x < -0.5) return -1;
- return 0;
-}
-
-/// Ternary to f32
-fn ternaryToF32(t: i2) f32 {
- return @as(f32, @floatFromInt(t));
-}
-
-/// GF16 encode (reuse from formats.zig)
-fn f32ToGf16(x: f32) u16 {
- if (x == 0.0) return 0;
- const sign_bit: u16 = if (x < 0) 0x8000 else 0;
- const abs = if (x < 0) -x else x;
- if (std.math.isPositiveInf(abs)) return sign_bit | 0x7E00;
- if (std.math.isNan(abs)) return sign_bit | 0x7E01;
-
- const frexp_result = std.math.frexp(abs);
- var m = frexp_result.significand;
- var exp_i = frexp_result.exponent;
- m *= 2.0;
- exp_i -= 1;
-
- const Bias: i32 = 31;
- const ExpMax: u16 = 63;
- const e = exp_i + Bias;
- if (e <= 0) return sign_bit;
- if (e >= ExpMax) return sign_bit | 0x7E00;
-
- const mant_f = (m - 1.0) * 512.0;
- const mantissa: u16 = @intFromFloat(@round(mant_f));
- return sign_bit | (@as(u16, @intCast(e)) << 9) | (mantissa & 0x01FF);
-}
-
-/// GF16 decode
-fn gf16ToF32(x: u16) f32 {
- const s = @as(i32, (x >> 15) & 1);
- const e = @as(i32, (x & 0x7E00) >> 9);
- const m = @as(i32, x & 0x01FF);
-
- const Bias: i32 = 31;
- if (e == 0 and m == 0) return if (s == 0) 0.0 else -0.0;
- if (e == 0) {
- const exp = 1 - Bias;
- const frac = @as(f32, @floatFromInt(m)) / 512.0;
- const val = std.math.exp2(@as(f32, @floatFromInt(exp))) * frac;
- return if (s == 0) val else -val;
- }
- if (e == 63) {
- if (m == 0) return if (s == 0) std.math.inf(f32) else -std.math.inf(f32);
- return std.math.nan(f32);
- }
- const exp = e - Bias;
- const frac = 1.0 + @as(f32, @floatFromInt(m)) / 512.0;
- const val = frac * std.math.exp2(@as(f32, @floatFromInt(exp)));
- return if (s == 0) val else -val;
-}
-
-/// FP16 encode (IEEE 754 half precision)
-fn f32ToFp16(x: f32) u16 {
- if (x == 0.0) return if (x < 0) 0x8000 else 0;
- const bits = @as(u32, @bitCast(x));
- const sign = @as(u16, @truncate(bits >> 16));
- const exp_all = @as(u32, @truncate(bits >> 23));
- const mantissa = @as(u16, @truncate(bits >> 13)) & 0x3FF;
- return sign | (@as(u16, @intCast(exp_all)) << 10) | mantissa;
-}
-
-/// FP16 decode
-fn fp16ToF32(x: u16) f32 {
- const sign = if (x & 0x8000 != 0) @as(u32, 0x80000000) else 0;
- const exp = @as(u32, (x & 0x7C00) >> 10) << 23;
- const mant = @as(u32, (x & 0x3FF)) << 13;
- return @bitCast(@as(u32, sign | exp | mant));
-}
-
-/// BF16 encode (truncate mantissa to 7 bits)
-fn f32ToBf16(x: f32) u16 {
- if (x == 0.0) return if (x < 0) 0x8000 else 0;
- const bits = @as(u32, @bitCast(x));
- const sign = @as(u16, @truncate(bits >> 16));
- const exp_all = @as(u16, @truncate(bits >> 23));
- const mantissa = @as(u16, @truncate(bits >> 16)) & 0x007F;
- return sign | (exp_all << 7) | mantissa;
-}
-
-/// BF16 decode
-fn bf16ToF32(x: u16) f32 {
- const sign = if (x & 0x8000 != 0) @as(u32, 0x80000000) else 0;
- const exp = @as(u32, (x & 0x7F80) >> 7) << 23;
- const mant = @as(u32, (x & 0x007F)) << 16;
- return @bitCast(@as(u32, sign | exp | mant));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MLP LAYER
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const LayerConfig = struct {
- input_size: usize,
- hidden_size: usize,
- output_size: usize,
-};
-
-fn relu(x: f32) f32 {
- return if (x > 0) x else 0;
-}
-
-fn denseLayer(
- input: []const f32,
- weights: []const f32,
- bias: []const f32,
- output: []f32,
- in_size: usize,
- out_size: usize,
-) void {
- for (0..out_size) |o| {
- var sum = bias[o];
- for (0..in_size) |i| {
- sum += input[i] * weights[i * out_size + o];
- }
- output[o] = relu(sum);
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// QUANTIZED FORWARD PASS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-fn forwardTernary(
- input: []const f32,
- w1: []const i2,
- b1: []const i2,
- w2: []const i2,
- b2: []const i2,
- hidden: []f32,
- output: []f32,
- config: LayerConfig,
-) void {
- // Layer 1
- for (0..config.hidden_size) |h| {
- var sum: f32 = ternaryToF32(b1[h]);
- for (0..config.input_size) |i| {
- sum += input[i] * ternaryToF32(w1[i * config.hidden_size + h]);
- }
- hidden[h] = relu(sum);
- }
- // Layer 2
- for (0..config.output_size) |o| {
- var sum: f32 = ternaryToF32(b2[o]);
- for (0..config.hidden_size) |h| {
- sum += hidden[h] * ternaryToF32(w2[h * config.output_size + o]);
- }
- output[o] = relu(sum);
- }
-}
-
-fn forwardGf16(
- input: []const f32,
- w1: []const u16,
- b1: []const u16,
- w2: []const u16,
- b2: []const u16,
- hidden: []f32,
- output: []f32,
- config: LayerConfig,
-) void {
- // Layer 1
- for (0..config.hidden_size) |h| {
- var sum: f32 = gf16ToF32(b1[h]);
- for (0..config.input_size) |i| {
- const w_val = gf16ToF32(w1[i * config.hidden_size + h]);
- sum += input[i] * w_val;
- }
- hidden[h] = relu(sum);
- }
- // Layer 2
- for (0..config.output_size) |o| {
- var sum: f32 = gf16ToF32(b2[o]);
- for (0..config.hidden_size) |h| {
- const w_val = gf16ToF32(w2[h * config.output_size + o]);
- sum += hidden[h] * w_val;
- }
- output[o] = relu(sum);
- }
-}
-
-fn forwardFp16(
- input: []const f32,
- w1: []const u16,
- b1: []const u16,
- w2: []const u16,
- b2: []const u16,
- hidden: []f32,
- output: []f32,
- config: LayerConfig,
-) void {
- // Layer 1
- for (0..config.hidden_size) |h| {
- var sum: f32 = fp16ToF32(b1[h]);
- for (0..config.input_size) |i| {
- sum += input[i] * fp16ToF32(w1[i * config.hidden_size + h]);
- }
- hidden[h] = relu(sum);
- }
- // Layer 2
- for (0..config.output_size) |o| {
- var sum: f32 = fp16ToF32(b2[o]);
- for (0..config.hidden_size) |h| {
- sum += hidden[h] * fp16ToF32(w2[h * config.output_size + o]);
- }
- output[o] = relu(sum);
- }
-}
-
-fn forwardBf16(
- input: []const f32,
- w1: []const u16,
- b1: []const u16,
- w2: []const u16,
- b2: []const u16,
- hidden: []f32,
- output: []f32,
- config: LayerConfig,
-) void {
- // Layer 1
- for (0..config.hidden_size) |h| {
- var sum: f32 = bf16ToF32(b1[h]);
- for (0..config.input_size) |i| {
- sum += input[i] * bf16ToF32(w1[i * config.hidden_size + h]);
- }
- hidden[h] = relu(sum);
- }
- // Layer 2
- for (0..config.output_size) |o| {
- var sum: f32 = bf16ToF32(b2[o]);
- for (0..config.hidden_size) |h| {
- sum += hidden[h] * bf16ToF32(w2[h * config.output_size + o]);
- }
- output[o] = relu(sum);
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// RESULTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const BenchmarkResult = struct {
- format: []const u8,
- accuracy: f32,
- loss: f32,
- bytes_per_weight: f32,
-};
-
-fn computeAccuracy(predictions: []const f32, labels: []const u8, num_classes: usize) f32 {
- var correct: usize = 0;
- const num_samples = labels.len;
- for (0..num_samples) |i| {
- const pred = predictions[i * num_classes ..][0..num_classes];
- var max_idx: usize = 0;
- var max_val: f32 = pred[0];
- for (1..num_classes) |j| {
- if (pred[j] > max_val) {
- max_val = pred[j];
- max_idx = j;
- }
- }
- if (max_idx == labels[i]) correct += 1;
- }
- return @as(f32, @floatFromInt(correct)) / @as(f32, @floatFromInt(num_samples));
-}
-
-fn mseLoss(predictions: []const f32, targets: []const f32) f32 {
- var sum: f32 = 0;
- for (predictions, targets) |p, t| {
- const diff = p - t;
- sum += diff * diff;
- }
- return sum / @as(f32, @floatFromInt(predictions.len));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CSV OUTPUT
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-fn writeCsv(results: []const BenchmarkResult, filename: []const u8) !void {
- const file = try std.fs.cwd().createFile(filename, .{});
- defer file.close();
-
- var line_buf: [256]u8 = undefined;
-
- const header = "format,accuracy,loss,bytes_per_weight\n";
- try file.writeAll(header);
-
- for (results) |r| {
- const line = try std.fmt.bufPrint(&line_buf, "{s},{d:.4},{d:.6},{d:.3}\n", .{ r.format, r.accuracy, r.loss, r.bytes_per_weight });
- try file.writeAll(line);
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MNIST LOADER (simplified)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const MnistHeader = struct {
- magic: u32,
- count: u32,
- rows: u32,
- cols: u32,
-};
-
-fn readMnistImages(filename: []const u8, allocator: std.mem.Allocator) !struct {
- data: []f32,
- count: usize,
- rows: usize,
- cols: usize,
-} {
- const file = try std.fs.cwd().openFile(filename, .{});
- defer file.close();
-
- const file_size = try file.getEndPos();
- const bytes = try allocator.alloc(u8, file_size);
- defer allocator.free(bytes);
- _ = try file.readAll(bytes);
-
- // Parse header
- var header: [4]u32 = undefined;
- for (&header, 0..) |*h, i| {
- h.* = std.mem.readInt(u32, bytes[i * 4 ..][0..4], .big);
- }
-
- const count = header[1];
- const rows = header[2];
- const cols = header[3];
- const total = count * rows * cols;
- const header_size = 16;
-
- const data = try allocator.alloc(f32, total);
- for (0..total) |i| {
- data[i] = @as(f32, @floatFromInt(bytes[header_size + i])) / 255.0;
- }
-
- return .{ .data = data, .count = count, .rows = rows, .cols = cols };
-}
-
-fn readMnistLabels(filename: []const u8, allocator: std.mem.Allocator) ![]u8 {
- const file = try std.fs.cwd().openFile(filename, .{});
- defer file.close();
-
- const file_size = try file.getEndPos();
- const bytes = try allocator.alloc(u8, file_size);
- defer allocator.free(bytes);
- _ = try file.readAll(bytes);
-
- const count = std.mem.readInt(u32, bytes[4..8], .big);
- const labels = try allocator.alloc(u8, count);
- for (0..count) |i| {
- labels[i] = bytes[8 + i];
- }
-
- return labels;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MAIN BENCHMARK
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- const config = LayerConfig{
- .input_size = 784, // 28x28
- .hidden_size = 128,
- .output_size = 10,
- };
-
- print("\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- print("β BENCH-001: Ternary vs FP16/BF16/GF16 on MNIST β\n", .{});
- print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- // Load MNIST (use test set for speed)
- const max_samples: usize = 1000; // Subset for faster benchmark
- print("Loading MNIST data ({} samples)...\n", .{max_samples});
-
- const images = try readMnistImages("data/t10k-images-idx3-ubyte", allocator);
- defer allocator.free(images.data);
- const labels = try readMnistLabels("data/t10k-labels-idx1-ubyte", allocator);
- defer allocator.free(labels);
-
- print("Loaded {} images ({}x{})\n", .{ images.count, images.rows, images.cols });
-
- // Initialize random weights
- var rnd = std.Random.DefaultPrng.init(42);
- const random = rnd.random();
-
- const w1_size = config.input_size * config.hidden_size;
- const b1_size = config.hidden_size;
- const w2_size = config.hidden_size * config.output_size;
- const b2_size = config.output_size;
-
- const w1_f32 = try allocator.alloc(f32, w1_size);
- defer allocator.free(w1_f32);
- const b1_f32 = try allocator.alloc(f32, b1_size);
- defer allocator.free(b1_f32);
- const w2_f32 = try allocator.alloc(f32, w2_size);
- defer allocator.free(w2_f32);
- const b2_f32 = try allocator.alloc(f32, b2_size);
- defer allocator.free(b2_f32);
-
- // Xavier initialization
- const std1 = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.input_size)));
- for (w1_f32) |*w| w.* = random.floatNorm(f32) * std1;
- for (b1_f32) |*b| b.* = 0;
- const std2 = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.hidden_size)));
- for (w2_f32) |*w| w.* = random.floatNorm(f32) * std2;
- for (b2_f32) |*b| b.* = 0;
-
- // Quantize weights
- var w1_ternary = try allocator.alloc(i2, w1_size);
- defer allocator.free(w1_ternary);
- var w1_gf16 = try allocator.alloc(u16, w1_size);
- defer allocator.free(w1_gf16);
- var w1_fp16 = try allocator.alloc(u16, w1_size);
- defer allocator.free(w1_fp16);
- var w1_bf16 = try allocator.alloc(u16, w1_size);
- defer allocator.free(w1_bf16);
-
- for (w1_f32, 0..) |w, i| {
- w1_ternary[i] = quantizeTernary(w);
- w1_gf16[i] = f32ToGf16(w);
- w1_fp16[i] = f32ToFp16(w);
- w1_bf16[i] = f32ToBf16(w);
- }
-
- var w2_ternary = try allocator.alloc(i2, w2_size);
- defer allocator.free(w2_ternary);
- var w2_gf16 = try allocator.alloc(u16, w2_size);
- defer allocator.free(w2_gf16);
- var w2_fp16 = try allocator.alloc(u16, w2_size);
- defer allocator.free(w2_fp16);
- var w2_bf16 = try allocator.alloc(u16, w2_size);
- defer allocator.free(w2_bf16);
-
- for (w2_f32, 0..) |w, i| {
- w2_ternary[i] = quantizeTernary(w);
- w2_gf16[i] = f32ToGf16(w);
- w2_fp16[i] = f32ToFp16(w);
- w2_bf16[i] = f32ToBf16(w);
- }
-
- var b1_ternary = try allocator.alloc(i2, b1_size);
- defer allocator.free(b1_ternary);
- var b1_gf16 = try allocator.alloc(u16, b1_size);
- defer allocator.free(b1_gf16);
- var b1_fp16 = try allocator.alloc(u16, b1_size);
- defer allocator.free(b1_fp16);
- var b1_bf16 = try allocator.alloc(u16, b1_size);
- defer allocator.free(b1_bf16);
-
- for (b1_f32, 0..) |b, i| {
- b1_ternary[i] = quantizeTernary(b);
- b1_gf16[i] = f32ToGf16(b);
- b1_fp16[i] = f32ToFp16(b);
- b1_bf16[i] = f32ToBf16(b);
- }
-
- var b2_ternary = try allocator.alloc(i2, b2_size);
- defer allocator.free(b2_ternary);
- var b2_gf16 = try allocator.alloc(u16, b2_size);
- defer allocator.free(b2_gf16);
- var b2_fp16 = try allocator.alloc(u16, b2_size);
- defer allocator.free(b2_fp16);
- var b2_bf16 = try allocator.alloc(u16, b2_size);
- defer allocator.free(b2_bf16);
-
- for (b2_f32, 0..) |b, i| {
- b2_ternary[i] = quantizeTernary(b);
- b2_gf16[i] = f32ToGf16(b);
- b2_fp16[i] = f32ToFp16(b);
- b2_bf16[i] = f32ToBf16(b);
- }
-
- // Allocate buffers
- const hidden_f32 = try allocator.alloc(f32, config.hidden_size);
- defer allocator.free(hidden_f32);
- const output_f32 = try allocator.alloc(f32, config.output_size);
- defer allocator.free(output_f32);
-
- var predictions_f32 = try allocator.alloc(f32, max_samples * config.output_size);
- defer allocator.free(predictions_f32);
- var predictions_ternary = try allocator.alloc(f32, max_samples * config.output_size);
- defer allocator.free(predictions_ternary);
- var predictions_gf16 = try allocator.alloc(f32, max_samples * config.output_size);
- defer allocator.free(predictions_gf16);
- var predictions_fp16 = try allocator.alloc(f32, max_samples * config.output_size);
- defer allocator.free(predictions_fp16);
- var predictions_bf16 = try allocator.alloc(f32, max_samples * config.output_size);
- defer allocator.free(predictions_bf16);
-
- var targets = try allocator.alloc(f32, max_samples * config.output_size);
- defer allocator.free(targets);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Run benchmarks
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- print("\nRunning inference...\n", .{});
-
- // FP32 baseline
- for (0..max_samples) |i| {
- const img = images.data[i * 784 ..][0..784];
- const pred = predictions_f32[i * 10 ..][0..10];
-
- denseLayer(img, w1_f32, b1_f32, hidden_f32, config.input_size, config.hidden_size);
- denseLayer(hidden_f32, w2_f32, b2_f32, pred, config.hidden_size, config.output_size);
-
- // One-hot target
- for (0..10) |j| {
- targets[i * 10 + j] = if (j == labels[i]) 1.0 else 0.0;
- }
- }
-
- // Ternary
- for (0..max_samples) |i| {
- const img = images.data[i * 784 ..][0..784];
- const pred = predictions_ternary[i * 10 ..][0..10];
- forwardTernary(img, w1_ternary, b1_ternary, w2_ternary, b2_ternary, hidden_f32, pred, config);
- }
-
- // GF16
- for (0..max_samples) |i| {
- const img = images.data[i * 784 ..][0..784];
- const pred = predictions_gf16[i * 10 ..][0..10];
- forwardGf16(img, w1_gf16, b1_gf16, w2_gf16, b2_gf16, hidden_f32, pred, config);
- }
-
- // FP16
- for (0..max_samples) |i| {
- const img = images.data[i * 784 ..][0..784];
- const pred = predictions_fp16[i * 10 ..][0..10];
- forwardFp16(img, w1_fp16, b1_fp16, w2_fp16, b2_fp16, hidden_f32, pred, config);
- }
-
- // BF16
- for (0..max_samples) |i| {
- const img = images.data[i * 784 ..][0..784];
- const pred = predictions_bf16[i * 10 ..][0..10];
- forwardBf16(img, w1_bf16, b1_bf16, w2_bf16, b2_bf16, hidden_f32, pred, config);
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Compute metrics
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const acc_f32 = computeAccuracy(predictions_f32, labels[0..max_samples], 10);
- const acc_ternary = computeAccuracy(predictions_ternary, labels[0..max_samples], 10);
- const acc_gf16 = computeAccuracy(predictions_gf16, labels[0..max_samples], 10);
- const acc_fp16 = computeAccuracy(predictions_fp16, labels[0..max_samples], 10);
- const acc_bf16 = computeAccuracy(predictions_bf16, labels[0..max_samples], 10);
-
- const loss_f32 = mseLoss(predictions_f32, targets);
- const loss_ternary = mseLoss(predictions_ternary, targets);
- const loss_gf16 = mseLoss(predictions_gf16, targets);
- const loss_fp16 = mseLoss(predictions_fp16, targets);
- const loss_bf16 = mseLoss(predictions_bf16, targets);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Print results
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- print("\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- print("β RESULTS β\n", .{});
- print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- print("ββββββββββββ¬ββββββββββββββ¬βββββββββββ¬βββββββββββββββββββ\n", .{});
- print("β Format β Accuracy % β Loss β Bytes/weight β\n", .{});
- print("ββββββββββββΌββββββββββββββΌβββββββββββΌβββββββββββββββββββ€\n", .{});
- print("β f32 β {d:8.2} β {d:6.4} β 16.0 β\n", .{ acc_f32 * 100, loss_f32 });
- print("β GF16 β {d:8.2} β {d:6.4} β 2.0 β\n", .{ acc_gf16 * 100, loss_gf16 });
- print("β FP16 β {d:8.2} β {d:6.4} β 2.0 β\n", .{ acc_fp16 * 100, loss_fp16 });
- print("β BF16 β {d:8.2} β {d:6.4} β 2.0 β\n", .{ acc_bf16 * 100, loss_bf16 });
- print("β Ternary β {d:8.2} β {d:6.4} β 0.125 (1 bit) β\n", .{ acc_ternary * 100, loss_ternary });
- print("ββββββββββββ΄ββββββββββββββ΄βββββββββββ΄βββββββββββββββββββ\n\n", .{});
-
- print("Gap vs f32:\n", .{});
- print(" GF16: {d:.2} pct\n", .{(acc_gf16 - acc_f32) * 100});
- print(" FP16: {d:.2} pct\n", .{(acc_fp16 - acc_f32) * 100});
- print(" BF16: {d:.2} pct\n", .{(acc_bf16 - acc_f32) * 100});
- print(" Ternary: {d:.2} pct\n", .{(acc_ternary - acc_f32) * 100});
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Write CSV
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const results = [_]BenchmarkResult{
- .{ .format = "f32", .accuracy = acc_f32, .loss = loss_f32, .bytes_per_weight = 4.0 },
- .{ .format = "GF16", .accuracy = acc_gf16, .loss = loss_gf16, .bytes_per_weight = 2.0 },
- .{ .format = "FP16", .accuracy = acc_fp16, .loss = loss_fp16, .bytes_per_weight = 2.0 },
- .{ .format = "BF16", .accuracy = acc_bf16, .loss = loss_bf16, .bytes_per_weight = 2.0 },
- .{ .format = "Ternary", .accuracy = acc_ternary, .loss = loss_ternary, .bytes_per_weight = 0.125 },
- };
-
- try std.fs.cwd().makePath("results");
- try writeCsv(&results, "results/bench_001_summary.csv");
- print("\nβ
Results saved to results/bench_001_summary.csv\n", .{});
-}
diff --git a/src/bench_arith.zig b/src/bench_arith.zig
deleted file mode 100644
index 430ebc5953..0000000000
--- a/src/bench_arith.zig
+++ /dev/null
@@ -1,195 +0,0 @@
-//! BENCH-002: Arithmetic Microbenchmarks
-//!
-//! Measure add/mul/div throughput for different number formats.
-//! Uses std.debug.print to avoid Zig 0.15 std.io naming conflicts.
-
-const std = @import("std");
-
-const Result = struct {
- format: []const u8,
- add_ns: f64,
- mul_ns: f64,
- div_ns: f64,
-};
-
-fn benchAdd(iterations: usize) f64 {
- var sum: f32 = 0;
- const a: f32 = 1.2345;
- const b: f32 = 2.3456;
-
- const start = std.time.nanoTimestamp();
- var i: usize = 0;
- while (i < iterations) : (i += 1) {
- sum += a + b;
- }
- const end = std.time.nanoTimestamp();
-
- return @as(f64, @floatFromInt(end - start)) / @as(f64, @floatFromInt(iterations));
-}
-
-fn benchMul(iterations: usize) f64 {
- var prod: f32 = 1;
- const a: f32 = 1.2345;
- const b: f32 = 2.3456;
-
- const start = std.time.nanoTimestamp();
- var i: usize = 0;
- while (i < iterations) : (i += 1) {
- prod *= a * b;
- }
- const end = std.time.nanoTimestamp();
-
- return @as(f64, @floatFromInt(end - start)) / @as(f64, @floatFromInt(iterations));
-}
-
-fn benchDiv(iterations: usize) f64 {
- var result: f32 = 1;
- const a: f32 = 100.0;
- const b: f32 = 3.14159;
-
- const start = std.time.nanoTimestamp();
- var i: usize = 0;
- while (i < iterations) : (i += 1) {
- result = a / b;
- }
- const end = std.time.nanoTimestamp();
-
- return @as(f64, @floatFromInt(end - start)) / @as(f64, @floatFromInt(iterations));
-}
-
-// Software fp16 add (simplified approximation)
-fn softF16Add(a: f32, b: f32) f32 {
- // Truncate to fp16 precision (10 bits mantissa)
- const mask: u32 = 0xFFFFE000;
- const ai: u32 = @bitCast(a);
- const bi: u32 = @bitCast(b);
- const ri = (ai & mask) + (bi & mask);
- return @as(f32, @bitCast(ri));
-}
-
-// Software GF16 add (6-bit exponent, 9-bit mantissa)
-fn softGF16Add(a: f32, b: f32) f32 {
- // Truncate to GF16 precision
- const mask: u32 = 0xFFFFF800;
- const ai: u32 = @bitCast(a);
- const bi: u32 = @bitCast(b);
- const ri = (ai & mask) + (bi & mask);
- return @as(f32, @bitCast(ri));
-}
-
-fn benchSoftF16Add(iterations: usize) f64 {
- var sum: f32 = 0;
- const a: f32 = 1.2345;
-
- const start = std.time.nanoTimestamp();
- var i: usize = 0;
- while (i < iterations) : (i += 1) {
- sum = softF16Add(sum, a);
- }
- const end = std.time.nanoTimestamp();
-
- return @as(f64, @floatFromInt(end - start)) / @as(f64, @floatFromInt(iterations));
-}
-
-fn benchSoftGF16Add(iterations: usize) f64 {
- var sum: f32 = 0;
- const a: f32 = 1.2345;
-
- const start = std.time.nanoTimestamp();
- var i: usize = 0;
- while (i < iterations) : (i += 1) {
- sum = softGF16Add(sum, a);
- }
- const end = std.time.nanoTimestamp();
-
- return @as(f64, @floatFromInt(end - start)) / @as(f64, @floatFromInt(iterations));
-}
-
-pub fn main() !void {
- const iterations = 1_000_000;
-
- std.debug.print(
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββ
- \\β BENCH-002: Arithmetic Microbenchmarks β
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββ
- \\
- \\Iterations: {d} operations per benchmark
- \\Warmup...
- \\
- , .{iterations});
-
- // Warmup
- _ = benchAdd(1000);
- _ = benchMul(1000);
- _ = benchDiv(100);
- _ = benchSoftF16Add(1000);
- _ = benchSoftGF16Add(1000);
-
- std.debug.print("\nRunning benchmarks...\n\n", .{});
-
- var results: [4]Result = undefined;
-
- // f32 baseline
- results[0] = .{
- .format = "f32",
- .add_ns = benchAdd(iterations),
- .mul_ns = benchMul(iterations),
- .div_ns = benchDiv(iterations / 10),
- };
-
- // soft-fp16
- results[1] = .{
- .format = "soft-fp16",
- .add_ns = benchSoftF16Add(iterations),
- .mul_ns = benchMul(iterations), // same mul for now
- .div_ns = benchDiv(iterations / 10),
- };
-
- // soft-GF16
- results[2] = .{
- .format = "soft-GF16",
- .add_ns = benchSoftGF16Add(iterations),
- .mul_ns = benchMul(iterations),
- .div_ns = benchDiv(iterations / 10),
- };
-
- // ternary (placeholder - actual ternary would be much faster)
- results[3] = .{
- .format = "ternary",
- .add_ns = 0.5,
- .mul_ns = 0.5,
- .div_ns = 1.0,
- };
-
- std.debug.print(
- \\
- \\Format | Add (ns/op) | Mul (ns/op) | Div (ns/op)
- \\-----------|-------------|-------------|-------------
- \\{s:<10} | {d: >10.2} | {d: >10.2} | {d: >10.2}
- \\{s:<10} | {d: >10.2} | {d: >10.2} | {d: >10.2}
- \\{s:<10} | {d: >10.2} | {d: >10.2} | {d: >10.2}
- \\{s:<10} | {d: >10.2} | {d: >10.2} | {d: >10.2}
- \\
- , .{
- results[0].format, results[0].add_ns, results[0].mul_ns, results[0].div_ns,
- results[1].format, results[1].add_ns, results[1].mul_ns, results[1].div_ns,
- results[2].format, results[2].add_ns, results[2].mul_ns, results[2].div_ns,
- results[3].format, results[3].add_ns, results[3].mul_ns, results[3].div_ns,
- });
-
- // Write CSV
- const csv_path = "results/arith_summary.csv";
- const file = try std.fs.cwd().createFile(csv_path, .{});
- defer file.close();
-
- try file.writeAll(
- \\format,add_ns,mul_ns,div_ns
- \\f32,5.0,4.5,12.0
- \\soft-fp16,8.5,4.5,12.0
- \\soft-GF16,7.2,4.5,12.0
- \\ternary,0.5,0.5,1.0
- \\
- );
-
- std.debug.print("CSV written to: {s}\n", .{csv_path});
-}
diff --git a/src/bench_cifar10.zig b/src/bench_cifar10.zig
deleted file mode 100644
index bfb5ff7752..0000000000
--- a/src/bench_cifar10.zig
+++ /dev/null
@@ -1,620 +0,0 @@
-//! BENCH-F0.2: CIFAR-10 CNN Benchmark with Real Quantization
-//!
-//! Compare accuracy degradation on CIFAR-10 test set with actual
-//! format quantization (GF16, fp16, bf16 vs fp32 baseline).
-//!
-//! Model: Small CNN β Conv(3β16)βReLUβPool β Conv(16β32)βReLUβPool β FC(2048β128) β FC(128β10)
-//!
-//! Usage:
-//! bench-cifar10 # Random weights (sanity-check)
-//! bench-cifar10 --weights=weights.bin # Trained weights
-//!
-//
-
-const std = @import("std");
-const cifar10_loader = @import("cifar10_loader.zig");
-const formats = @import("formats.zig");
-
-const LayerConfig = struct {
- input_height: u32,
- input_width: u32,
- input_channels: u32,
- conv1_out: u32,
- conv1_kernel: u32,
- pool1_kernel: u32,
- conv2_out: u32,
- conv2_kernel: u32,
- pool2_kernel: u32,
- fc1_out: u32,
- output_size: u32,
-};
-
-fn relu(x: f32) f32 {
- return if (x > 0) x else 0;
-}
-
-/// Load trained weights from binary file
-/// Expected layout: conv1_w (1440 floats) -> conv1_b (16 floats) ->
-/// conv2_w (4608 floats) -> conv2_b (32 floats) ->
-/// fc1_w (262144 floats) -> fc1_b (128 floats) ->
-/// fc2_w (1280 floats) -> fc2_b (10 floats)
-/// Total: 268,650 floats Γ 4 bytes = 1,074,600 bytes
-fn loadWeights(
- allocator: std.mem.Allocator,
- path: []const u8,
- conv1_w: *[]f32,
- conv1_b: *[]f32,
- conv2_w: *[]f32,
- conv2_b: *[]f32,
- fc1_w: *[]f32,
- fc1_b: *[]f32,
- fc2_w: *[]f32,
- fc2_b: *[]f32,
-) !void {
- const file = try std.fs.cwd().openFile(path, .{});
- defer file.close();
-
- const file_stat = try file.stat();
- const expected_size: usize = 268_650 * 4; // 1,074,600 bytes
-
- if (file_stat.size != expected_size) {
- std.debug.print("ERROR: Expected {d} bytes, got {d}\n", .{ expected_size, file_stat.size });
- return error.InvalidData;
- }
-
- const buffer = try allocator.alloc(u8, expected_size);
- defer allocator.free(buffer);
- _ = try file.readAll(buffer);
-
- var offset: usize = 0;
-
- // conv1_w: 3Γ16Γ3Γ3 = 1440 floats
- conv1_w.* = try allocator.alloc(f32, 1440);
- for (0..1440) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- conv1_w.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- // conv1_b: 16 floats
- conv1_b.* = try allocator.alloc(f32, 16);
- for (0..16) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- conv1_b.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- // conv2_w: 16Γ32Γ3Γ3 = 4608 floats
- conv2_w.* = try allocator.alloc(f32, 4608);
- for (0..4608) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- conv2_w.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- // conv2_b: 32 floats
- conv2_b.* = try allocator.alloc(f32, 32);
- for (0..32) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- conv2_b.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- // fc1_w: 2048Γ128 = 262,144 floats
- fc1_w.* = try allocator.alloc(f32, 262144);
- for (0..262144) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- fc1_w.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- // fc1_b: 128 floats
- fc1_b.* = try allocator.alloc(f32, 128);
- for (0..128) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- fc1_b.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- // fc2_w: 128Γ10 = 1,280 floats
- fc2_w.* = try allocator.alloc(f32, 1280);
- for (0..1280) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- fc2_w.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- // fc2_b: 10 floats
- fc2_b.* = try allocator.alloc(f32, 10);
- for (0..10) |i| {
- const i32_val = std.mem.readInt(u32, buffer[offset..][0..4], .little);
- fc2_b.*[i] = @bitCast(i32_val);
- offset += 4;
- }
-
- std.debug.print("Loaded weights: conv1={d}, conv2={d}, fc1={d}, fc2={d}\n", .{
- conv1_w.*.len, conv2_w.*.len, fc1_w.*.len, fc2_w.*.len });
-}
-
-pub fn main() !void {
- const config = LayerConfig{
- .input_height = 32,
- .input_width = 32,
- .input_channels = 3,
- .conv1_out = 16,
- .conv1_kernel = 3,
- .pool1_kernel = 2,
- .conv2_out = 32,
- .conv2_kernel = 3,
- .pool2_kernel = 2,
- .fc1_out = 128,
- .output_size = 10,
- };
-
- const allocator = std.heap.c_allocator;
-
- // Parse command line args for --weights flag
- // Supports both: --weights value and --weights=value
- var weights_path: ?[]const u8 = blk: {
- var idx: usize = 1;
- while (idx < std.os.argv.len) : (idx += 1) {
- const arg = spanZ(std.os.argv[idx]);
-
- // Check for --weights=value format
- if (startsWith(arg, "--weights=")) {
- break :blk arg["--weights=".len..];
- }
-
- // Check for --weights value format
- if (strEql(std.os.argv[idx], "--weights")) {
- if (idx + 1 < std.os.argv.len) {
- break :blk spanZ(std.os.argv[idx + 1]);
- }
- }
- }
- break :blk null;
- };
-
- // Load CIFAR-10 test data (data_dir = "data")
- const data_dir = "data";
- const loader = cifar10_loader.CIFAR10Loader.init();
- var test_data = loader.loadTest(allocator, data_dir) catch |err| {
- if (err == error.FileNotFound) {
- std.debug.print("\nERROR: CIFAR-10 test file not found.\n", .{});
- std.debug.print("Expected: data/test_batch.bin\n", .{});
- std.debug.print("Create data/ directory and place test_batch.bin there.\n", .{});
- return err;
- }
- return err;
- };
- defer test_data.deinit(allocator);
-
- const num_samples = test_data.len();
- std.debug.print("Loaded {d} test images\n\n", .{num_samples});
-
- // Load weights or generate random
- var conv1_weights_f32: []f32 = undefined;
- var conv1_biases_f32: []f32 = undefined;
- var conv2_weights_f32: []f32 = undefined;
- var conv2_biases_f32: []f32 = undefined;
- var fc1_weights_f32: []f32 = undefined;
- var fc1_biases_f32: []f32 = undefined;
- var fc2_weights_f32: []f32 = undefined;
- var fc2_biases_f32: []f32 = undefined;
-
- if (weights_path) |path| {
- std.debug.print("Loading trained weights from: {s}\n", .{path});
- loadWeights(allocator, path, &conv1_weights_f32, &conv1_biases_f32, &conv2_weights_f32, &conv2_biases_f32, &fc1_weights_f32, &fc1_biases_f32, &fc2_weights_f32, &fc2_biases_f32) catch |err| {
- std.debug.print("Failed to load weights: {s}\n", .{@errorName(err)});
- std.debug.print("Using random weights instead.\n", .{});
- // Fall through to random init below
- weights_path = null;
- };
- }
-
- if (weights_path == null) {
- std.debug.print("Using random weights (Xavier init, seed=42)\n", .{});
-
- // Generate random weights
- var prng = std.Random.DefaultPrng.init(42);
- const random = prng.random();
-
- // Xavier initialization scale: sqrt(2 / fan_in)
- const conv1_scale = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.input_channels * config.conv1_kernel * config.conv1_kernel)));
- const conv2_scale = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.conv1_out * config.conv2_kernel * config.conv2_kernel)));
-
- // FC1: fan_in is fc1_out
- const fc1_scale = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.fc1_out)));
-
- // FC2: fan_in is fc1_out
- const fc2_scale = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.fc1_out)));
-
- // Conv1 weights
- conv1_weights_f32 = try allocator.alloc(f32, 1440);
- defer allocator.free(conv1_weights_f32);
- conv1_biases_f32 = try allocator.alloc(f32, 16);
- defer allocator.free(conv1_biases_f32);
-
- for (0..1440) |i| {
- conv1_weights_f32[i] = random.floatNorm(f32) * conv1_scale;
- }
- for (0..16) |i| {
- conv1_biases_f32[i] = 0;
- }
-
- // Conv2 weights
- conv2_weights_f32 = try allocator.alloc(f32, 4608);
- defer allocator.free(conv2_weights_f32);
- conv2_biases_f32 = try allocator.alloc(f32, 32);
- defer allocator.free(conv2_biases_f32);
-
- for (0..4608) |i| {
- conv2_weights_f32[i] = random.floatNorm(f32) * conv2_scale;
- }
- for (0..32) |i| {
- conv2_biases_f32[i] = 0;
- }
-
- // FC1 weights
- fc1_weights_f32 = try allocator.alloc(f32, 262144);
- defer allocator.free(fc1_weights_f32);
- fc1_biases_f32 = try allocator.alloc(f32, 128);
- defer allocator.free(fc1_biases_f32);
-
- for (0..262144) |i| {
- fc1_weights_f32[i] = random.floatNorm(f32) * fc1_scale;
- }
- for (0..128) |i| {
- fc1_biases_f32[i] = 0;
- }
-
- // FC2 weights (no bias for output layer)
- fc2_weights_f32 = try allocator.alloc(f32, 1280);
- defer allocator.free(fc2_weights_f32);
- fc2_biases_f32 = try allocator.alloc(f32, 10);
- defer allocator.free(fc2_biases_f32);
-
- for (0..1280) |i| {
- fc2_weights_f32[i] = random.floatNorm(f32) * fc2_scale;
- }
- for (0..10) |i| {
- fc2_biases_f32[i] = 0;
- }
- }
-
- std.debug.print("\nRunning inference benchmarks...\n", .{});
-
- // Run inference for each format
- const result_f32 = runCIFAR10Inference(allocator, &test_data, conv1_weights_f32, conv1_biases_f32, conv2_weights_f32, conv2_biases_f32, fc1_weights_f32, fc1_biases_f32, fc2_weights_f32, fc2_biases_f32, config, num_samples, .fp32);
- const result_fp16 = runCIFAR10Inference(allocator, &test_data, conv1_weights_f32, conv1_biases_f32, conv2_weights_f32, conv2_biases_f32, fc1_weights_f32, fc1_biases_f32, fc2_weights_f32, fc2_biases_f32, config, num_samples, .fp16);
- const result_bf16 = runCIFAR10Inference(allocator, &test_data, conv1_weights_f32, conv1_biases_f32, conv2_weights_f32, conv2_biases_f32, fc1_weights_f32, fc1_biases_f32, fc2_weights_f32, fc2_biases_f32, config, num_samples, .bf16);
- const result_gf16 = runCIFAR10Inference(allocator, &test_data, conv1_weights_f32, conv1_biases_f32, conv2_weights_f32, conv2_biases_f32, fc1_weights_f32, fc1_biases_f32, fc2_weights_f32, fc2_biases_f32, config, num_samples, .gf16);
-
- // Print results
- std.debug.print("\nββββββββββββ¬ββββββββββββββ¬βββββββββββ¬βββββββββββββββββββ\n", .{});
- std.debug.print("β Format β Accuracy % β Loss β Bytes/weight β\n", .{});
- std.debug.print("ββββββββββββΌββββββββββββββΌβββββββββββΌβββββββββββββββββββ€\n", .{});
- std.debug.print("β f32 β {d:9.2} β {d:8.4} β 4 β\n", .{ result_f32.accuracy, result_f32.loss });
- std.debug.print("β fp16 β {d:9.2} β {d:8.4} β 2 β\n", .{ result_fp16.accuracy, result_fp16.loss });
- std.debug.print("β bf16 β {d:9.2} β {d:8.4} β 2 β\n", .{ result_bf16.accuracy, result_bf16.loss });
- std.debug.print("β GF16 β {d:9.2} β {d:8.4} β 2 β\n", .{ result_gf16.accuracy, result_gf16.loss });
- std.debug.print("ββββββββββββ΄ββββββββββββββ΄βββββββββββ΄βββββββββββββββββββ\n\n", .{});
-
- // Show accuracy gap relative to f32
- std.debug.print("Accuracy gap vs f32:\n", .{});
- const fp16_gap = result_fp16.accuracy - result_f32.accuracy;
- const bf16_gap = result_bf16.accuracy - result_f32.accuracy;
- const gf16_gap = result_gf16.accuracy - result_f32.accuracy;
- std.debug.print(" fp16: {s}{d:.2}%\n", .{ if (fp16_gap >= 0) "+" else "", fp16_gap });
- std.debug.print(" bf16: {s}{d:.2}%\n", .{ if (bf16_gap >= 0) "+" else "", bf16_gap });
- std.debug.print(" GF16: {s}{d:.2}%\n", .{ if (gf16_gap >= 0) "+" else "", gf16_gap });
- std.debug.print("\n", .{});
-
- // Ensure results directory exists
- try std.fs.cwd().makePath("results");
-
- // Write JSON output
- const json_path = "results/cifar10_metrics.json";
- const json_file = try std.fs.cwd().createFile(json_path, .{});
- defer json_file.close();
-
- const json = try std.fmt.allocPrint(allocator,
- \\{{
- \\ "dataset": "CIFAR-10",
- \\ "architecture": "CNN Conv({d})βPoolβConv({d})βPoolβFC({d})βFC({d})",
- \\ "samples": {d},
- \\ "results": {{
- \\ "f32": {{ "accuracy_percent": {d:.2}, "loss": {d:.4} }},
- \\ "fp16": {{ "accuracy_percent": {d:.2}, "loss": {d:.4} }},
- \\ "bf16": {{ "accuracy_percent": {d:.2}, "loss": {d:.4} }},
- \\ "gf16": {{ "accuracy_percent": {d:.2}, "loss": {d:.4} }}
- \\}}
- \\}}
- \\
- , .{
- config.input_channels, config.conv1_out, config.conv2_out, config.fc1_out,
- num_samples,
- result_f32.accuracy, result_f32.loss,
- result_fp16.accuracy, result_fp16.loss,
- result_bf16.accuracy, result_bf16.loss,
- result_gf16.accuracy, result_gf16.loss,
- });
-
- try json_file.writeAll(json);
- std.debug.print("JSON written to: {s}\n", .{json_path});
-
- // Also write CSV for compatibility
- const csv_path = "results/cifar10_summary.csv";
- const csv_file = try std.fs.cwd().createFile(csv_path, .{});
- defer csv_file.close();
-
- var csv_data: [1024]u8 = undefined;
- const csv = try std.fmt.bufPrint(&csv_data,
- \\format,accuracy_percent,loss,size_bytes
- \\f32,{d:.2},{d:.4},4
- \\fp16,{d:.2},{d:.4},2
- \\bf16,{d:.2},{d:.4},2
- \\gf16,{d:.2},{d:.4},2
- \\
- , .{
- result_f32.accuracy, result_f32.loss,
- result_fp16.accuracy, result_fp16.loss,
- result_bf16.accuracy, result_bf16.loss,
- result_gf16.accuracy, result_gf16.loss,
- });
- try csv_file.writeAll(csv);
- std.debug.print("CSV written to: {s}\n", .{csv_path});
-
- return {};
-}
-
-const InferenceResult = struct {
- accuracy: f64,
- loss: f64,
-};
-
-const Format = enum {
- fp32,
- fp16,
- bf16,
- gf16,
-};
-
-/// Run CIFAR-10 CNN inference with specified format quantization
-/// Weights are quantized once at initialization, then used for all samples
-fn runCIFAR10Inference(
- allocator: std.mem.Allocator,
- test_data: *const cifar10_loader.Dataset,
- conv1_weights_f32: []const f32,
- conv1_biases_f32: []const f32,
- conv2_weights_f32: []const f32,
- conv2_biases_f32: []const f32,
- fc1_weights_f32: []const f32,
- fc1_biases_f32: []const f32,
- fc2_weights_f32: []const f32,
- fc2_biases_f32: []const f32,
- config: LayerConfig,
- num_samples: usize,
- fmt: Format,
-) InferenceResult {
- const formats_fmt = switch (fmt) {
- .fp32 => formats.Format.fp32,
- .fp16 => formats.Format.fp16,
- .bf16 => formats.Format.bf16,
- .gf16 => formats.Format.gf16,
- };
-
- // Quantize weights to target format
- const conv1_w_q = quantizeWeights(allocator, conv1_weights_f32, formats_fmt) catch unreachable;
- defer allocator.free(conv1_w_q);
- const conv1_b_q = quantizeWeights(allocator, conv1_biases_f32, formats_fmt) catch unreachable;
- defer allocator.free(conv1_b_q);
- const conv2_w_q = quantizeWeights(allocator, conv2_weights_f32, formats_fmt) catch unreachable;
- defer allocator.free(conv2_w_q);
- const conv2_b_q = quantizeWeights(allocator, conv2_biases_f32, formats_fmt) catch unreachable;
- defer allocator.free(conv2_b_q);
- const fc1_w_q = quantizeWeights(allocator, fc1_weights_f32, formats_fmt) catch unreachable;
- defer allocator.free(fc1_w_q);
- const fc1_b_q = quantizeWeights(allocator, fc1_biases_f32, formats_fmt) catch unreachable;
- defer allocator.free(fc1_b_q);
- const fc2_w_q = quantizeWeights(allocator, fc2_weights_f32, formats_fmt) catch unreachable;
- defer allocator.free(fc2_w_q);
- const fc2_b_q = quantizeWeights(allocator, fc2_biases_f32, formats_fmt) catch unreachable;
- defer allocator.free(fc2_b_q);
-
- // Calculate dimensions
- const pool1_out_h = config.input_height / config.pool1_kernel; // 32/2 = 16
- const pool1_out_w = config.input_width / config.pool1_kernel; // 32/2 = 16
- const pool2_out_h = pool1_out_h / config.pool2_kernel; // 16/2 = 8
- const pool2_out_w = pool1_out_w / config.pool2_kernel; // 16/2 = 8
- const fc1_input_size = pool2_out_h * pool2_out_w * config.conv2_out; // 8*8*32 = 2048
-
- // Pre-allocate buffers
- const conv1_out = allocator.alloc(f32, 16384) catch unreachable;
- defer allocator.free(conv1_out);
- const pool1_out = allocator.alloc(f32, 4096) catch unreachable;
- defer allocator.free(pool1_out);
- const conv2_out = allocator.alloc(f32, 8192) catch unreachable;
- defer allocator.free(conv2_out);
- const pool2_out = allocator.alloc(f32, 2048) catch unreachable;
- defer allocator.free(pool2_out);
- const fc1_out = allocator.alloc(f32, 128) catch unreachable;
- defer allocator.free(fc1_out);
- const fc2_out = allocator.alloc(f32, 10) catch unreachable;
- defer allocator.free(fc2_out);
-
- var correct: usize = 0;
- var total_loss: f64 = 0;
-
- for (0..num_samples) |i| {
- const sample = test_data.get(i);
- const input = sample.flatten();
-
- // Conv1: input (3072) -> conv1_out (16384)
- formats.conv2d(
- input,
- conv1_w_q,
- conv1_b_q,
- conv1_out,
- .{
- .in_channels = config.input_channels,
- .out_channels = config.conv1_out,
- .in_height = config.input_height,
- .in_width = config.input_width,
- .kernel_size = config.conv1_kernel,
- .stride = 1,
- .padding = 1,
- },
- );
-
- // ReLU
- var j: usize = 0;
- while (j < conv1_out.len) : (j += 1) {
- conv1_out[j] = relu(conv1_out[j]);
- }
-
- // Pool1: conv1_out -> pool1_out (4096)
- formats.maxPool2d(
- conv1_out,
- pool1_out,
- .{
- .height = config.input_height,
- .width = config.input_width,
- .channels = config.conv1_out,
- .kernel_size = config.pool1_kernel,
- .stride = config.pool1_kernel,
- },
- );
-
- // Conv2: pool1_out -> conv2_out (8192)
- formats.conv2d(
- pool1_out,
- conv2_w_q,
- conv2_b_q,
- conv2_out,
- .{
- .in_channels = config.conv1_out,
- .out_channels = config.conv2_out,
- .in_height = pool1_out_h,
- .in_width = pool1_out_w,
- .kernel_size = config.conv2_kernel,
- .stride = 1,
- .padding = 1,
- },
- );
-
- // ReLU
- j = 0;
- while (j < conv2_out.len) : (j += 1) {
- conv2_out[j] = relu(conv2_out[j]);
- }
-
- // Pool2: conv2_out -> pool2_out (2048)
- formats.maxPool2d(
- conv2_out,
- pool2_out,
- .{
- .height = pool1_out_h,
- .width = pool1_out_w,
- .channels = config.conv2_out,
- .kernel_size = config.pool2_kernel,
- .stride = config.pool2_kernel,
- },
- );
-
- // FC1: pool2_out (2048) -> fc1_out (128)
- for (0..config.fc1_out) |o| {
- var sum: f32 = fc1_b_q[o];
- var k: usize = 0;
- while (k < fc1_input_size) : (k += 1) {
- sum += pool2_out[k] * fc1_w_q[o * fc1_input_size + k];
- }
- fc1_out[o] = relu(sum);
- }
-
- // FC2: fc1_out (128) -> fc2_out (10)
- for (0..config.output_size) |o| {
- var sum: f32 = fc2_b_q[o];
- var k: usize = 0;
- while (k < config.fc1_out) : (k += 1) {
- sum += fc1_out[k] * fc2_w_q[o * config.fc1_out + k];
- }
- fc2_out[o] = sum;
- }
-
- // Find prediction (argmax)
- var max_val: f32 = fc2_out[0];
- var pred_idx: usize = 0;
- {
- var jj: usize = 1;
- while (jj < fc2_out.len) : (jj += 1) {
- if (fc2_out[jj] > max_val) {
- max_val = fc2_out[jj];
- pred_idx = jj;
- }
- }
- }
-
- const target = sample.label;
- if (pred_idx == @as(usize, @intCast(target))) correct += 1;
-
- // Cross-entropy loss
- var max_output: f32 = fc2_out[0];
- {
- var jj: usize = 1;
- while (jj < fc2_out.len) : (jj += 1) {
- max_output = @max(max_output, fc2_out[jj]);
- }
- }
- var sum_exp: f32 = 0;
- {
- var jj: usize = 0;
- while (jj < fc2_out.len) : (jj += 1) {
- sum_exp += @exp(fc2_out[jj] - max_output);
- }
- }
- const log_sum = @log(sum_exp) + max_output;
- const target_idx: usize = @intCast(target);
- total_loss += @as(f64, log_sum - fc2_out[target_idx]);
- }
-
- return InferenceResult{
- .accuracy = @as(f64, @floatFromInt(correct)) * 100.0 / @as(f64, @floatFromInt(num_samples)),
- .loss = total_loss / @as(f64, @floatFromInt(num_samples)),
- };
-}
-
-/// Quantize f32 weights to target format, returns f32 array with quantized values
-fn quantizeWeights(allocator: std.mem.Allocator, src: []const f32, fmt: formats.Format) ![]f32 {
- const dst = try allocator.alloc(f32, src.len);
- for (src, 0..) |val, idx| {
- dst[idx] = formats.quantizeValue(val, fmt);
- }
- return dst;
-}
-
-// Helper: convert null-terminated string to slice
-inline fn spanZ(ptr: [*:0]const u8) []const u8 {
- var len: usize = 0;
- while (ptr[len] != 0) : (len += 1) {}
- return ptr[0..len];
-}
-
-// Helper: compare null-terminated string with slice
-inline fn strEql(a: [*:0]const u8, b: []const u8) bool {
- var i: usize = 0;
- while (i < b.len) : (i += 1) {
- if (a[i] != b[i]) return false;
- }
- return a[i] == 0;
-}
-
-// Helper: check if a string starts with a prefix
-inline fn startsWith(s: []const u8, prefix: []const u8) bool {
- if (s.len < prefix.len) return false;
- var i: usize = 0;
- while (i < prefix.len) : (i += 1) {
- if (s[i] != prefix[i]) return false;
- }
- return true;
-}
diff --git a/src/bench_formats.zig b/src/bench_formats.zig
deleted file mode 100644
index d60aa6b0cf..0000000000
--- a/src/bench_formats.zig
+++ /dev/null
@@ -1,61 +0,0 @@
-//! BENCH-001: Number Format Quantization Error Benchmarks (Phase 1)
-//!
-//! Honest comparison of Trinity number formats vs IEEE standards.
-//! MSE/MAE on synthetic distributions: Normal(0,1), Log-normal, Uniform.
-//!
-//! Results format: CSV with columns format,distribution,mse,mae,max_abs_error
-
-const std = @import("std");
-
-pub fn main() !void {
- // Use std.debug.print to avoid naming conflicts with std.io
- // Note: This prints to stderr, but that's OK for benchmarks
-
- std.debug.print(
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββ
- \\β BENCH-001: Number Format Quantization Error Benchmarks β
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββ
- \\
- \\Format | Bits (s/e/m) | Min pos | Max | Denormals?
- \\----------|-------------|----------|----------|------------
- \\fp16 | 1/5/10 | 6.1e-5 | 65504 | Yes
- \\bf16 | 1/8/7 | 1.2e-38 | 3.4e38 | No
- \\GF16 | 1/6/9 | 4.66e-10 | 4.29e9 | No
- \\TF3 | 1/6/11 | TBD | TBD | No
- \\Ternary | 2 bits | -1 | +1 | N/A
- \\
- \\MSE on Normal(0,1) distribution (10,000 samples):
- \\-----------------------------------------------
- \\f16 | 0.000123 |
- \\bf16 | 0.000456 |
- \\GF16 | 0.000234 |
- \\Ternary | 0.500000 |
- \\
- \\CSV: results/quant_summary.csv
- \\
- , .{});
-
- // Generate and write CSV
- const csv_path = "results/quant_summary.csv";
- const file = try std.fs.cwd().createFile(csv_path, .{});
- defer file.close();
-
- try file.writeAll(
- \\format,distribution,mse,mae,max_abs_error
- \\f16,normal,0.000123,0.0087,0.045
- \\bf16,normal,0.000456,0.0123,0.089
- \\gf16,normal,0.000234,0.0098,0.067
- \\ternary,normal,0.500000,0.7071,1.000
- \\f16,lognormal,0.000789,0.0156,0.123
- \\bf16,lognormal,0.001234,0.0234,0.234
- \\gf16,lognormal,0.000987,0.0198,0.187
- \\ternary,lognormal,0.750000,0.8660,1.000
- \\f16,uniform,0.000456,0.0123,0.089
- \\bf16,uniform,0.000890,0.0189,0.178
- \\gf16,uniform,0.000678,0.0156,0.134
- \\ternary,uniform,0.666667,0.8165,1.000
- \\
- );
-
- std.debug.print("\nCSV written to: {s}\n", .{csv_path});
-}
diff --git a/src/bench_jit.zig b/src/bench_jit.zig
deleted file mode 100644
index ad65983d7c..0000000000
--- a/src/bench_jit.zig
+++ /dev/null
@@ -1,222 +0,0 @@
-// @origin(spec:bench_jit.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity JIT Benchmark
-// Compares JIT vs interpreted VSA operations
-//
-// Run: zig run src/bench_jit.zig -O ReleaseFast
-
-const std = @import("std");
-const jit = @import("jit.zig");
-const vsa = @import("vsa.zig");
-const hybrid = @import("hybrid.zig");
-
-const JitCompiler = jit.JitCompiler;
-const HybridBigInt = hybrid.HybridBigInt;
-
-const ITERATIONS = 100000;
-const WARMUP = 1000;
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- const stdout = std.io.getStdOut().writer();
-
- try stdout.print("\n", .{});
- try stdout.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print("β TRINITY JIT vs INTERPRETED BENCHMARK β\n", .{});
- try stdout.print("β β\n", .{});
- try stdout.print("β Comparing native JIT-compiled code vs Zig interpreted operations β\n", .{});
- try stdout.print("β ΟΒ² + 1/ΟΒ² = 3 β\n", .{});
- try stdout.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- const dimensions = [_]usize{ 256, 1000, 4096 };
-
- for (dimensions) |dim| {
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" DIMENSION: {d} trits\n", .{dim});
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- // Create test vectors
- var a = vsa.randomVector(dim, 12345);
- var b = vsa.randomVector(dim, 67890);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // BIND BENCHMARK
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // Compile JIT bind
- var compiler = JitCompiler.init(allocator);
- defer compiler.deinit();
-
- try compiler.compileBindDirect(dim);
- const jit_bind = try compiler.finalize();
-
- // Warmup
- for (0..WARMUP) |_| {
- _ = vsa.bind(&a, &b);
- }
-
- // Interpreted bind
- var timer = std.time.Timer.start() catch unreachable;
- for (0..ITERATIONS) |_| {
- var result = vsa.bind(&a, &b);
- std.mem.doNotOptimizeAway(&result);
- }
- const interp_elapsed = timer.read();
- const interp_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(interp_elapsed)) / 1e9);
-
- // JIT bind (operates in-place on copy)
- var a_copy: [hybrid.MAX_TRITS]i8 = undefined;
- @memcpy(a_copy[0..dim], a.unpacked_cache[0..dim]);
-
- timer = std.time.Timer.start() catch unreachable;
- for (0..ITERATIONS) |_| {
- // Reset a_copy each iteration for fair comparison
- @memcpy(a_copy[0..dim], a.unpacked_cache[0..dim]);
- jit_bind(&a_copy, &b.unpacked_cache);
- std.mem.doNotOptimizeAway(&a_copy);
- }
- const jit_elapsed = timer.read();
- const jit_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(jit_elapsed)) / 1e9);
-
- const bind_speedup = jit_ops / interp_ops;
-
- try stdout.print(" BIND:\n", .{});
- try stdout.print(" Interpreted (SIMD): {d:.0} ops/sec\n", .{interp_ops});
- try stdout.print(" JIT compiled: {d:.0} ops/sec\n", .{jit_ops});
- try stdout.print(" Speedup: {d:.2}x {s}\n\n", .{
- if (bind_speedup > 1) bind_speedup else 1.0 / bind_speedup,
- if (bind_speedup > 1) "(JIT faster)" else "(Interpreted faster)",
- });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // BUNDLE BENCHMARK
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- var compiler2 = JitCompiler.init(allocator);
- defer compiler2.deinit();
-
- try compiler2.compileBundleDirect(dim);
- const jit_bundle = try compiler2.finalize();
-
- // Interpreted bundle
- timer = std.time.Timer.start() catch unreachable;
- for (0..ITERATIONS) |_| {
- var result = vsa.bundle2(&a, &b);
- std.mem.doNotOptimizeAway(&result);
- }
- const interp_bundle_elapsed = timer.read();
- const interp_bundle_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(interp_bundle_elapsed)) / 1e9);
-
- // JIT bundle
- timer = std.time.Timer.start() catch unreachable;
- for (0..ITERATIONS) |_| {
- @memcpy(a_copy[0..dim], a.unpacked_cache[0..dim]);
- jit_bundle(&a_copy, &b.unpacked_cache);
- std.mem.doNotOptimizeAway(&a_copy);
- }
- const jit_bundle_elapsed = timer.read();
- const jit_bundle_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(jit_bundle_elapsed)) / 1e9);
-
- const bundle_speedup = jit_bundle_ops / interp_bundle_ops;
-
- try stdout.print(" BUNDLE:\n", .{});
- try stdout.print(" Interpreted (SIMD): {d:.0} ops/sec\n", .{interp_bundle_ops});
- try stdout.print(" JIT compiled: {d:.0} ops/sec\n", .{jit_bundle_ops});
- try stdout.print(" Speedup: {d:.2}x {s}\n\n", .{
- if (bundle_speedup > 1) bundle_speedup else 1.0 / bundle_speedup,
- if (bundle_speedup > 1) "(JIT faster)" else "(Interpreted faster)",
- });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // DOT PRODUCT BENCHMARK
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- var compiler3 = JitCompiler.init(allocator);
- defer compiler3.deinit();
-
- try compiler3.compileDotProduct(dim);
-
- // Finalize with correct signature
- const code_size = compiler3.code.items.len;
- const page_size = std.heap.page_size_min;
- const alloc_size = std.mem.alignForward(usize, code_size, page_size);
-
- const mem = try std.posix.mmap(
- null,
- alloc_size,
- std.posix.PROT.READ | std.posix.PROT.WRITE,
- .{ .TYPE = .PRIVATE, .ANONYMOUS = true },
- -1,
- 0,
- );
- defer std.posix.munmap(mem);
-
- @memcpy(mem[0..code_size], compiler3.code.items);
- try std.posix.mprotect(mem, std.posix.PROT.READ | std.posix.PROT.EXEC);
-
- const jit_dot: *const fn (*anyopaque, *anyopaque) callconv(.c) i64 = @ptrCast(mem.ptr);
-
- // Interpreted dot product (using similarity which computes dot)
- timer = std.time.Timer.start() catch unreachable;
- var interp_result: f64 = undefined;
- for (0..ITERATIONS) |_| {
- interp_result = vsa.cosineSimilarity(&a, &b);
- std.mem.doNotOptimizeAway(&interp_result);
- }
- const interp_dot_elapsed = timer.read();
- const interp_dot_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(interp_dot_elapsed)) / 1e9);
-
- // JIT dot product
- timer = std.time.Timer.start() catch unreachable;
- var jit_result: i64 = undefined;
- for (0..ITERATIONS) |_| {
- jit_result = jit_dot(&a.unpacked_cache, &b.unpacked_cache);
- std.mem.doNotOptimizeAway(&jit_result);
- }
- const jit_dot_elapsed = timer.read();
- const jit_dot_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(jit_dot_elapsed)) / 1e9);
-
- const dot_speedup = jit_dot_ops / interp_dot_ops;
-
- try stdout.print(" DOT PRODUCT:\n", .{});
- try stdout.print(" Interpreted: {d:.0} ops/sec\n", .{interp_dot_ops});
- try stdout.print(" JIT compiled: {d:.0} ops/sec\n", .{jit_dot_ops});
- try stdout.print(" Speedup: {d:.2}x {s}\n\n", .{
- if (dot_speedup > 1) dot_speedup else 1.0 / dot_speedup,
- if (dot_speedup > 1) "(JIT faster)" else "(Interpreted faster)",
- });
-
- // Code size
- try stdout.print(" JIT CODE SIZE:\n", .{});
- try stdout.print(" Bind: {d} bytes\n", .{compiler.codeSize()});
- try stdout.print(" Bundle: {d} bytes\n", .{compiler2.codeSize()});
- try stdout.print(" Dot: {d} bytes\n\n", .{compiler3.codeSize()});
- }
-
- // Summary
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" SUMMARY\n", .{});
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- try stdout.print(" JIT ADVANTAGES:\n", .{});
- try stdout.print(" β No function call overhead per element\n", .{});
- try stdout.print(" β Tight loop with minimal branching\n", .{});
- try stdout.print(" β Dimension-specific code (no bounds checks)\n", .{});
- try stdout.print(" β Can be cached for repeated operations\n\n", .{});
-
- try stdout.print(" INTERPRETED (SIMD) ADVANTAGES:\n", .{});
- try stdout.print(" β 32-wide SIMD operations\n", .{});
- try stdout.print(" β Compiler-optimized code\n", .{});
- try stdout.print(" β No JIT compilation overhead\n", .{});
- try stdout.print(" β Better cache utilization\n\n", .{});
-
- try stdout.print(" CONCLUSION:\n", .{});
- try stdout.print(" The SIMD-optimized interpreted code is competitive with JIT\n", .{});
- try stdout.print(" because Zig's compiler already generates excellent native code.\n", .{});
- try stdout.print(" JIT shines for dynamic/specialized operations.\n\n", .{});
-
- try stdout.print(" ΟΒ² + 1/ΟΒ² = 3\n\n", .{});
-}
diff --git a/src/bench_mnist.zig b/src/bench_mnist.zig
deleted file mode 100644
index 8f27b21fd0..0000000000
--- a/src/bench_mnist.zig
+++ /dev/null
@@ -1,415 +0,0 @@
-//! BENCH-004: MNIST Real Data Benchmark with Real Quantization
-//!
-//! Compare accuracy degradation on real MNIST test set with actual
-//! format quantization (GF16, ternary, fp16, bf16 vs fp32 baseline).
-//!
-//! Usage:
-//! bench-mnist # Random weights (sanity-check)
-//! bench-mnist --weights=weights.bin # Trained weights
-//!
-//! Model: MLP 784 -> 128 -> 10
-
-const std = @import("std");
-const mnist = @import("mnist_loader.zig");
-const formats = @import("formats");
-
-const LayerConfig = struct {
- input_size: usize,
- hidden_size: usize,
- output_size: usize,
-};
-
-fn relu(x: f32) f32 {
- return if (x > 0) x else 0;
-}
-
-// Helper: convert null-terminated string to slice
-inline fn spanZ(ptr: [*:0]const u8) []const u8 {
- var len: usize = 0;
- while (ptr[len] != 0) : (len += 1) {}
- return ptr[0..len];
-}
-
-// Helper: compare null-terminated string with slice
-inline fn strEql(a: [*:0]const u8, b: []const u8) bool {
- var i: usize = 0;
- while (i < b.len) : (i += 1) {
- if (a[i] != b[i]) return false;
- }
- return a[i] == 0; // Also check null terminator
-}
-
-// Helper: check if a string starts with a prefix
-inline fn startsWith(s: []const u8, prefix: []const u8) bool {
- if (s.len < prefix.len) return false;
- var i: usize = 0;
- while (i < prefix.len) : (i += 1) {
- if (s[i] != prefix[i]) return false;
- }
- return true;
-}
-
-pub fn main() !void {
- const config = LayerConfig{
- .input_size = 784, // 28x28 MNIST images
- .hidden_size = 128,
- .output_size = 10, // Digits 0-9
- };
-
- const allocator = std.heap.c_allocator;
-
- // Parse command line args for --weights flag
- // Supports both: --weights value and --weights=value
- const weights_path: ?[]const u8 = blk: {
- var i: usize = 1;
- while (i < std.os.argv.len) : (i += 1) {
- const arg = spanZ(std.os.argv[i]);
-
- // Check for --weights=value format
- if (startsWith(arg, "--weights=")) {
- break :blk arg["--weights=".len..];
- }
-
- // Check for --weights value format
- if (strEql(std.os.argv[i], "--weights")) {
- if (i + 1 < std.os.argv.len) {
- break :blk spanZ(std.os.argv[i + 1]);
- }
- }
- }
- break :blk null;
- };
-
- // Ensure data directory exists
- try std.fs.cwd().makePath("data");
-
- std.debug.print(
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- \\β BENCH-004: MNIST Real Data Benchmark (Quantized) β
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- \\
- \\Model: MLP ({d} -> {d} -> {d})
- \\Dataset: MNIST test set (10k images)
- \\Quantization: f32, fp16, bf16, GF16, ternary
- \\
- , .{ config.input_size, config.hidden_size, config.output_size });
-
- // Load MNIST data
- const images_path = "data/t10k-images-idx3-ubyte";
- const labels_path = "data/t10k-labels-idx1-ubyte";
-
- std.debug.print("Loading MNIST data...\n", .{});
-
- var mnist_data = mnist.MNIST.load(allocator, images_path) catch |err| {
- if (err == error.FileNotFound) {
- std.debug.print("\nERROR: MNIST files not found.\n", .{});
- std.debug.print("\nDownload from ossci mirror:\n", .{});
- std.debug.print(" cd data && curl -LO https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz\n", .{});
- std.debug.print(" cd data && curl -LO https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz\n", .{});
- std.debug.print(" cd data && gunzip t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz\n", .{});
- return err;
- }
- return err;
- };
- defer mnist_data.deinit();
-
- var mnist_labels = mnist.Labels.load(allocator, labels_path) catch |err| {
- if (err == error.FileNotFound) {
- std.debug.print("\nERROR: MNIST labels not found.\n", .{});
- std.debug.print("See above for download instructions.\n", .{});
- }
- return err;
- };
- defer mnist_labels.deinit();
-
- const num_samples = @min(mnist_data.count(), mnist_labels.count());
- std.debug.print("Loaded {d} images\n\n", .{num_samples});
-
- // Load weights: either from file or generate random
- const weights1_size = config.input_size * config.hidden_size;
- const weights2_size = config.hidden_size * config.output_size;
-
- var weights1_f32: []f32 = undefined;
- var biases1_f32: []f32 = undefined;
- var weights2_f32: []f32 = undefined;
- var biases2_f32: []f32 = undefined;
- var using_loaded_weights = false;
-
- // Load weights variable - will be freed after inference
- var loaded_weights: ?formats.MlpWeights = null;
-
- if (weights_path) |path| {
- std.debug.print("Loading trained weights from: {s}\n", .{path});
-
- const loaded = try formats.loadMlpWeights(allocator, path);
- // NOTE: NOT calling loaded.deinit() - we'll free manually after inference
-
- // Validate dimensions
- if (loaded.input_dim != config.input_size or
- loaded.hidden_dim != config.hidden_size or
- loaded.output_dim != config.output_size)
- {
- std.debug.print("\nERROR: Weight dimensions mismatch!\n", .{});
- std.debug.print(" Expected: {}x{}x{}\n", .{ config.input_size, config.hidden_size, config.output_size });
- std.debug.print(" Got: {}x{}x{}\n", .{ loaded.input_dim, loaded.hidden_dim, loaded.output_dim });
- loaded.deinit(); // Free before returning
- return error.DimensionMismatch;
- }
-
- // Store loaded weights for later cleanup and assign slices
- loaded_weights = loaded;
- weights1_f32 = loaded.W1;
- biases1_f32 = loaded.b1;
- weights2_f32 = loaded.W2;
- biases2_f32 = loaded.b2;
- using_loaded_weights = true;
- }
-
- if (!using_loaded_weights) {
- std.debug.print("Using random weights (Xavier init, seed=42)\n", .{});
-
- // Generate random weights (using fixed seed for reproducibility)
- var prng = std.Random.DefaultPrng.init(42);
- const random = prng.random();
-
- // Allocate base f32 weights
- weights1_f32 = try allocator.alloc(f32, weights1_size);
- defer allocator.free(weights1_f32);
- biases1_f32 = try allocator.alloc(f32, config.hidden_size);
- defer allocator.free(biases1_f32);
- weights2_f32 = try allocator.alloc(f32, weights2_size);
- defer allocator.free(weights2_f32);
- biases2_f32 = try allocator.alloc(f32, config.output_size);
- defer allocator.free(biases2_f32);
-
- // Initialize with Xavier initialization
- const scale1 = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.input_size)));
- for (0..weights1_size) |i| {
- weights1_f32[i] = random.floatNorm(f32) * scale1;
- }
- for (0..config.hidden_size) |i| {
- biases1_f32[i] = 0;
- }
-
- const scale2 = std.math.sqrt(2.0 / @as(f32, @floatFromInt(config.hidden_size)));
- for (0..weights2_size) |i| {
- weights2_f32[i] = random.floatNorm(f32) * scale2;
- }
- for (0..config.output_size) |i| {
- biases2_f32[i] = 0;
- }
- }
-
- std.debug.print("\nRunning inference benchmarks...\n", .{});
-
- // Run inference for each format with REAL quantization
- const result_f32 = runMNISTInference(allocator, &mnist_data, &mnist_labels, weights1_f32, biases1_f32, weights2_f32, biases2_f32, config, num_samples, .fp32);
- const result_fp16 = runMNISTInference(allocator, &mnist_data, &mnist_labels, weights1_f32, biases1_f32, weights2_f32, biases2_f32, config, num_samples, .fp16);
- const result_bf16 = runMNISTInference(allocator, &mnist_data, &mnist_labels, weights1_f32, biases1_f32, weights2_f32, biases2_f32, config, num_samples, .bf16);
- const result_gf16 = runMNISTInference(allocator, &mnist_data, &mnist_labels, weights1_f32, biases1_f32, weights2_f32, biases2_f32, config, num_samples, .gf16);
- const result_ternary = runMNISTInference(allocator, &mnist_data, &mnist_labels, weights1_f32, biases1_f32, weights2_f32, biases2_f32, config, num_samples, .ternary);
-
- // Print results
- std.debug.print("\nββββββββββββ¬ββββββββββββββ¬βββββββββββ¬βββββββββββββββββββ\n", .{});
- std.debug.print("β Format β Accuracy % β Loss β Bytes/weight β\n", .{});
- std.debug.print("ββββββββββββΌββββββββββββββΌβββββββββββΌβββββββββββββββββββ€\n", .{});
- std.debug.print("β f32 β {d:9.2} β {d:8.4} β 4 β\n", .{ result_f32.accuracy, result_f32.loss });
- std.debug.print("β fp16 β {d:9.2} β {d:8.4} β 2 β\n", .{ result_fp16.accuracy, result_fp16.loss });
- std.debug.print("β bf16 β {d:9.2} β {d:8.4} β 2 β\n", .{ result_bf16.accuracy, result_bf16.loss });
- std.debug.print("β GF16 β {d:9.2} β {d:8.4} β 2 β\n", .{ result_gf16.accuracy, result_gf16.loss });
- std.debug.print("β ternary β {d:9.2} β {d:8.4} β 1 β\n", .{ result_ternary.accuracy, result_ternary.loss });
- std.debug.print("ββββββββββββ΄ββββββββββββββ΄βββββββββββ΄βββββββββββββββββββ\n\n", .{});
-
- // Show accuracy gap relative to f32
- std.debug.print("Accuracy gap vs f32:\n", .{});
- const fp16_gap = result_fp16.accuracy - result_f32.accuracy;
- const bf16_gap = result_bf16.accuracy - result_f32.accuracy;
- const gf16_gap = result_gf16.accuracy - result_f32.accuracy;
- const ternary_gap = result_ternary.accuracy - result_f32.accuracy;
- std.debug.print(" fp16: {s}{d:.2}%\n", .{ if (fp16_gap >= 0) "+" else "", fp16_gap });
- std.debug.print(" bf16: {s}{d:.2}%\n", .{ if (bf16_gap >= 0) "+" else "", bf16_gap });
- std.debug.print(" GF16: {s}{d:.2}%\n", .{ if (gf16_gap >= 0) "+" else "", gf16_gap });
- std.debug.print(" ternary: {s}{d:.2}%\n", .{ if (ternary_gap >= 0) "+" else "", ternary_gap });
- std.debug.print("\n", .{});
-
- // Ensure results directory exists
- try std.fs.cwd().makePath("results");
-
- // Write CSV
- const csv_path = "results/mnist_summary.csv";
- const file = try std.fs.cwd().createFile(csv_path, .{});
- defer file.close();
-
- // Format CSV data
- var csv_data: [1024]u8 = undefined;
- const csv = try std.fmt.bufPrint(&csv_data,
- \\format,accuracy_percent,loss,size_bytes
- \\f32,{d:.2},{d:.4},4
- \\fp16,{d:.2},{d:.4},2
- \\bf16,{d:.2},{d:.4},2
- \\gf16,{d:.2},{d:.4},2
- \\ternary,{d:.2},{d:.4},1
- \\
- , .{ result_f32.accuracy, result_f32.loss, result_fp16.accuracy, result_fp16.loss, result_bf16.accuracy, result_bf16.loss, result_gf16.accuracy, result_gf16.loss, result_ternary.accuracy, result_ternary.loss });
-
- try file.writeAll(csv);
-
- std.debug.print("CSV written to: {s}\n", .{csv_path});
-
- // Clean up loaded weights if any
- if (loaded_weights) |*lw| {
- lw.deinit();
- }
-
- return {};
-}
-
-const InferenceResult = struct {
- accuracy: f64,
- loss: f64,
-};
-
-const Format = enum {
- fp32,
- fp16,
- bf16,
- gf16,
- ternary,
-};
-
-/// Run MNIST inference with specified format quantization
-/// Weights are quantized once at initialization, then used for all samples
-fn runMNISTInference(
- allocator: std.mem.Allocator,
- mnist_data: *const mnist.MNIST,
- mnist_labels: *const mnist.Labels,
- weights1_f32: []const f32,
- biases1_f32: []const f32,
- weights2_f32: []const f32,
- biases2_f32: []const f32,
- config: LayerConfig,
- num_samples: usize,
- fmt: Format,
-) InferenceResult {
- const formats_fmt = switch (fmt) {
- .fp32 => formats.Format.fp32,
- .fp16 => formats.Format.fp16,
- .bf16 => formats.Format.bf16,
- .gf16 => formats.Format.gf16,
- .ternary => formats.Format.ternary,
- };
-
- // Quantize weights to target format
- const weights1_q = quantizeWeights(allocator, weights1_f32, formats_fmt) catch unreachable;
- defer allocator.free(weights1_q);
- const biases1_q = quantizeWeights(allocator, biases1_f32, formats_fmt) catch unreachable;
- defer allocator.free(biases1_q);
- const weights2_q = quantizeWeights(allocator, weights2_f32, formats_fmt) catch unreachable;
- defer allocator.free(weights2_q);
- const biases2_q = quantizeWeights(allocator, biases2_f32, formats_fmt) catch unreachable;
- defer allocator.free(biases2_q);
-
- var correct: usize = 0;
- var total_loss: f64 = 0;
-
- // Pre-allocate buffers
- const hidden = allocator.alloc(f32, config.hidden_size) catch unreachable;
- defer allocator.free(hidden);
- const output = allocator.alloc(f32, config.output_size) catch unreachable;
- defer allocator.free(output);
- const input = allocator.alloc(f32, config.input_size) catch unreachable;
- defer allocator.free(input);
-
- for (0..num_samples) |i| {
- // Load and normalize image
- const image_raw = mnist_data.getImage(i);
- for (0..config.input_size) |j| {
- input[j] = @as(f32, @floatFromInt(image_raw[j])) / 255.0;
- }
-
- // Forward pass with quantized weights
- forwardPassQuantized(input, weights1_q, biases1_q, weights2_q, biases2_q, config, hidden, output, formats_fmt);
-
- // Find prediction (argmax)
- var max_val: f32 = output[0];
- var pred_idx: usize = 0;
- {
- var j: usize = 1;
- while (j < output.len) : (j += 1) {
- if (output[j] > max_val) {
- max_val = output[j];
- pred_idx = j;
- }
- }
- }
-
- const target = mnist_labels.get(i);
- if (pred_idx == @as(usize, @intCast(target))) correct += 1;
-
- // Cross-entropy loss (simplified)
- var max_output: f32 = output[0];
- {
- var j: usize = 1;
- while (j < output.len) : (j += 1) {
- max_output = @max(max_output, output[j]);
- }
- }
- var sum_exp: f32 = 0;
- {
- var j: usize = 0;
- while (j < output.len) : (j += 1) {
- sum_exp += @exp(output[j] - max_output);
- }
- }
- const log_sum = @log(sum_exp) + max_output;
- const target_idx: usize = @intCast(target);
- total_loss += @as(f64, log_sum - output[target_idx]);
- }
-
- return InferenceResult{
- .accuracy = @as(f64, @floatFromInt(correct)) * 100.0 / @as(f64, @floatFromInt(num_samples)),
- .loss = total_loss / @as(f64, @floatFromInt(num_samples)),
- };
-}
-
-/// Quantize f32 weights to target format, returns f32 array with quantized values
-fn quantizeWeights(allocator: std.mem.Allocator, src: []const f32, fmt: formats.Format) ![]f32 {
- const dst = try allocator.alloc(f32, src.len);
- for (src, 0..) |val, i| {
- dst[i] = formats.quantizeValue(val, fmt);
- }
- return dst;
-}
-
-/// Forward pass with pre-quantized weights (stored as f32 for convenience)
-fn forwardPassQuantized(
- input: []const f32,
- weights1: []const f32, // Already quantized
- biases1: []const f32,
- weights2: []const f32, // Already quantized
- biases2: []const f32,
- config: LayerConfig,
- hidden: []f32,
- output: []f32,
- fmt: formats.Format,
-) void {
- _ = fmt; // Format-specific arithmetic paths to be added
-
- // Hidden layer: h = relu(W1 * x + b1)
- for (0..config.hidden_size) |h| {
- var sum: f32 = biases1[h];
- for (0..config.input_size) |i| {
- sum += input[i] * weights1[h * config.input_size + i];
- }
- hidden[h] = relu(sum);
- }
-
- // Output layer: y = W2 * h + b2
- for (0..config.output_size) |o| {
- var sum: f32 = biases2[o];
- for (0..config.hidden_size) |h| {
- sum += hidden[h] * weights2[o * config.hidden_size + h];
- }
- output[o] = sum;
- }
-}
diff --git a/src/bench_nn.zig b/src/bench_nn.zig
deleted file mode 100644
index ab26a91b57..0000000000
--- a/src/bench_nn.zig
+++ /dev/null
@@ -1,292 +0,0 @@
-//! BENCH-003: Small NN Inference Benchmark
-//!
-//! Compare accuracy degradation when using different number formats.
-//! Tiny MLP: 100 -> 64 -> 10 (simplified MNIST-like).
-//!
-//! Uses std.debug.print to avoid Zig 0.15 std.io naming conflicts.
-
-const std = @import("std");
-
-const LayerConfig = struct {
- input_size: usize,
- hidden_size: usize,
- output_size: usize,
-};
-
-fn relu(x: f32) f32 {
- return if (x > 0) x else 0;
-}
-
-pub fn main() !void {
- const config = LayerConfig{
- .input_size = 100,
- .hidden_size = 64,
- .output_size = 10,
- };
-
- const num_samples = 1000;
-
- std.debug.print(
- \\ββββββββββββββββββββββββββββββββββββββββββββββ
- \\β BENCH-003: Small NN Inference Benchmark β
- \\ββββββββββββββββββββββββββββββββββββββββββββββββ
- \\
- \\Model: Tiny MLP ({d} -> {d} -> {d})
- \\Samples: {d}
- \\
- , .{ config.input_size, config.hidden_size, config.output_size, num_samples });
-
- std.debug.print("Generating synthetic data...\n", .{});
-
- // Generate synthetic data
- var prng = std.Random.DefaultPrng.init(@intCast(std.time.timestamp()));
- const random = prng.random();
-
- const allocator = std.heap.page_allocator;
-
- const inputs = try allocator.alloc(f32, config.input_size * num_samples);
- defer allocator.free(inputs);
-
- const targets = try allocator.alloc(usize, num_samples);
- defer allocator.free(targets);
-
- // Generate random inputs and targets
- for (0..num_samples) |i| {
- const input_start = i * config.input_size;
- for (0..config.input_size) |j| {
- inputs[input_start + j] = random.float(f32) * 2.0 - 1.0;
- }
- targets[i] = random.uintLessThan(usize, config.output_size);
- }
-
- // Generate f32 weights (baseline)
- const weights_size = config.input_size * config.hidden_size;
- const weights = try allocator.alloc(f32, weights_size);
- defer allocator.free(weights);
-
- const biases = try allocator.alloc(f32, config.hidden_size);
- defer allocator.free(biases);
-
- for (0..weights_size) |i| {
- weights[i] = random.float(f32) * 2.0 - 1.0;
- }
- for (0..config.hidden_size) |i| {
- biases[i] = random.float(f32) * 0.1 - 0.05;
- }
-
- std.debug.print("Running inference benchmarks...\n\n", .{});
-
- // Run inference for each format
- const f32_acc = runInferenceF32(inputs, targets, weights, biases, config, num_samples);
- const f16_acc = runInferenceF16Soft(inputs, targets, weights, biases, config, num_samples);
- const gf16_acc = runInferenceGF16Soft(inputs, targets, weights, biases, config, num_samples);
- const ternary_acc = runInferenceTernary(inputs, targets, weights, biases, config, num_samples);
-
- // Print results
- std.debug.print("Format | Accuracy | Loss | Size (bytes/weight)\n", .{});
- std.debug.print("----------|-----------|----------|-------------------\n", .{});
- std.debug.print("f32 | {d:.2}% | {d:.4} | 32\n", .{ f32_acc.accuracy, f32_acc.loss });
- std.debug.print("f16 soft | {d:.2}% | {d:.4} | 16\n", .{ f16_acc.accuracy, f16_acc.loss });
- std.debug.print("GF16 soft | {d:.2}% | {d:.4} | 16\n", .{ gf16_acc.accuracy, gf16_acc.loss });
- std.debug.print("ternary | {d:.2}% | {d:.4} | 2\n\n", .{ ternary_acc.accuracy, ternary_acc.loss });
-
- std.debug.print("Key findings:\n", .{});
- std.debug.print("- GF16 maintains competitive accuracy vs f32 baseline\n", .{});
- std.debug.print("- Ternary shows significant accuracy drop due to -1,0,+1 limitation\n", .{});
- std.debug.print("- All soft implementations have overhead vs hardware f32\n\n", .{});
-
- // Write CSV
- const csv_path = "results/nn_summary.csv";
- const file = try std.fs.cwd().createFile(csv_path, .{});
- defer file.close();
-
- try file.writeAll(
- \\format,accuracy_percent,loss,size_bytes
- \\f32,95.2,0.048,32
- \\f16_soft,94.8,0.052,16
- \\gf16_soft,94.9,0.051,16
- \\ternary,88.5,0.12,2
- \\
- );
-
- std.debug.print("CSV written to: {s}\n", .{csv_path});
-}
-
-const InferenceResult = struct {
- accuracy: f64,
- loss: f64,
-};
-
-fn runInferenceF32(
- inputs: []const f32,
- targets: []const usize,
- weights: []const f32,
- biases: []const f32,
- config: LayerConfig,
- num_samples: usize,
-) InferenceResult {
- var correct: usize = 0;
- var total_loss: f64 = 0;
-
- const allocator = std.heap.page_allocator;
- const hidden = allocator.alloc(f32, config.hidden_size) catch unreachable;
- defer allocator.free(hidden);
- const output = allocator.alloc(f32, config.output_size) catch unreachable;
- defer allocator.free(output);
-
- for (0..num_samples) |sample_idx| {
- const input_start = sample_idx * config.input_size;
- const input = inputs[input_start..][0..config.input_size];
-
- forwardPassF32(input, weights, biases, config, hidden, output);
-
- var max_val: f32 = output[0];
- var pred_idx: usize = 0;
- for (output, 1..) |val, idx| {
- if (val > max_val) {
- max_val = val;
- pred_idx = idx;
- }
- }
-
- if (pred_idx == targets[sample_idx]) correct += 1;
-
- const diff = output[targets[sample_idx]] - 1.0;
- total_loss += @as(f64, diff * diff);
- }
-
- return InferenceResult{
- .accuracy = @as(f64, @floatFromInt(correct)) * 100.0 / @as(f64, @floatFromInt(num_samples)),
- .loss = total_loss / @as(f64, @floatFromInt(num_samples)),
- };
-}
-
-fn runInferenceF16Soft(
- inputs: []const f32,
- targets: []const usize,
- weights: []const f32,
- biases: []const f32,
- config: LayerConfig,
- num_samples: usize,
-) InferenceResult {
- return runInferenceF32(inputs, targets, weights, biases, config, num_samples);
-}
-
-fn runInferenceGF16Soft(
- inputs: []const f32,
- targets: []const usize,
- weights: []const f32,
- biases: []const f32,
- config: LayerConfig,
- num_samples: usize,
-) InferenceResult {
- return runInferenceF32(inputs, targets, weights, biases, config, num_samples);
-}
-
-fn runInferenceTernary(
- inputs: []const f32,
- targets: []const usize,
- weights: []const f32,
- biases: []const f32,
- config: LayerConfig,
- num_samples: usize,
-) InferenceResult {
- var correct: usize = 0;
- var total_loss: f64 = 0;
-
- const allocator = std.heap.page_allocator;
- const hidden = allocator.alloc(f32, config.hidden_size) catch unreachable;
- defer allocator.free(hidden);
- const output = allocator.alloc(f32, config.output_size) catch unreachable;
- defer allocator.free(output);
-
- const ternary_weights = allocator.alloc(i8, weights.len) catch unreachable;
- defer allocator.free(ternary_weights);
- const ternary_biases = allocator.alloc(i8, biases.len) catch unreachable;
- defer allocator.free(ternary_biases);
-
- for (weights, 0..) |w, i| {
- ternary_weights[i] = if (w > 0.33) 1 else if (w < -0.33) -1 else 0;
- }
- for (biases, 0..) |b, i| {
- ternary_biases[i] = if (b > 0.33) 1 else if (b < -0.33) -1 else 0;
- }
-
- for (0..num_samples) |sample_idx| {
- const input_start = sample_idx * config.input_size;
- const input = inputs[input_start..][0..config.input_size];
-
- forwardPassTernary(input, ternary_weights, ternary_biases, config, hidden, output);
-
- var max_val: f32 = output[0];
- var pred_idx: usize = 0;
- for (output, 1..) |val, idx| {
- if (val > max_val) {
- max_val = val;
- pred_idx = idx;
- }
- }
-
- if (pred_idx == targets[sample_idx]) correct += 1;
-
- const diff = output[targets[sample_idx]] - 1.0;
- total_loss += @as(f64, diff * diff);
- }
-
- return InferenceResult{
- .accuracy = @as(f64, @floatFromInt(correct)) * 100.0 / @as(f64, @floatFromInt(num_samples)),
- .loss = total_loss / @as(f64, @floatFromInt(num_samples)),
- };
-}
-
-fn forwardPassF32(
- input: []const f32,
- weights: []const f32,
- biases: []const f32,
- config: LayerConfig,
- hidden: []f32,
- output: []f32,
-) void {
- for (0..config.hidden_size) |h| {
- var sum: f32 = biases[h];
- for (0..config.input_size) |i| {
- sum += input[i] * weights[h * config.input_size + i];
- }
- hidden[h] = relu(sum);
- }
-
- for (0..config.output_size) |o| {
- var sum: f32 = 0;
- for (0..config.hidden_size) |h| {
- sum += hidden[h] * weights[o * config.hidden_size + h];
- }
- output[o] = sum;
- }
-}
-
-fn forwardPassTernary(
- input: []const f32,
- weights: []const i8,
- biases: []const i8,
- config: LayerConfig,
- hidden: []f32,
- output: []f32,
-) void {
- for (0..config.hidden_size) |h| {
- var sum: f32 = @floatFromInt(biases[h]);
- for (0..config.input_size) |i| {
- const w: f32 = @floatFromInt(weights[h * config.input_size + i]);
- sum += input[i] * w;
- }
- hidden[h] = relu(sum);
- }
-
- for (0..config.output_size) |o| {
- var sum: f32 = 0;
- for (0..config.hidden_size) |h| {
- const w: f32 = @floatFromInt(weights[o * config.hidden_size + h]);
- sum += hidden[h] * w;
- }
- output[o] = sum;
- }
-}
diff --git a/src/bench_sparse.zig b/src/bench_sparse.zig
deleted file mode 100644
index 8707143df2..0000000000
--- a/src/bench_sparse.zig
+++ /dev/null
@@ -1,207 +0,0 @@
-// @origin(spec:bench_sparse.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity Sparse vs Dense Benchmark
-// Compares memory and performance of sparse vs dense representations
-//
-// Run: zig run benchmarks/bench_sparse.zig -O ReleaseFast
-
-const std = @import("std");
-const sparse = @import("sparse.zig");
-const vsa = @import("vsa.zig");
-const hybrid = @import("hybrid.zig");
-
-const SparseVector = sparse.SparseVector;
-const HybridBigInt = hybrid.HybridBigInt;
-
-const ITERATIONS = 10000;
-const WARMUP = 100;
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- const stdout = std.io.getStdOut().writer();
-
- try stdout.print("\n", .{});
- try stdout.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print("β TRINITY SPARSE vs DENSE BENCHMARK β\n", .{});
- try stdout.print("β β\n", .{});
- try stdout.print("β Comparing memory and performance at different sparsity levels β\n", .{});
- try stdout.print("β ΟΒ² + 1/ΟΒ² = 3 β\n", .{});
- try stdout.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- const dimension: u32 = 10000;
- const densities = [_]f64{ 0.01, 0.05, 0.10, 0.20, 0.33 };
-
- try stdout.print(" Dimension: {d} trits\n", .{dimension});
- try stdout.print(" Iterations: {d}\n\n", .{ITERATIONS});
-
- // Memory comparison
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" MEMORY COMPARISON\n", .{});
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- const dense_bytes = dimension * @sizeOf(i8);
- try stdout.print(" Dense storage: {d} bytes\n\n", .{dense_bytes});
-
- try stdout.print(" ββββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ\n", .{});
- try stdout.print(" β Density β NNZ β Sparse β Savings β Breakevenβ\n", .{});
- try stdout.print(" ββββββββββββΌβββββββββββΌβββββββββββΌβββββββββββΌβββββββββββ€\n", .{});
-
- for (densities) |density| {
- var sparse_vec = try SparseVector.random(allocator, dimension, density, 12345);
- defer sparse_vec.deinit();
-
- const sparse_bytes = sparse_vec.memoryBytes();
- const savings = sparse_vec.memorySavings();
- const nnz = sparse_vec.nnz();
-
- // Breakeven point: when sparse_bytes == dense_bytes
- // sparse_bytes = nnz * (4 + 1) + overhead β nnz * 5
- // dense_bytes = dimension * 1
- // breakeven: nnz * 5 = dimension -> nnz/dimension = 0.2 (20% density)
- const breakeven = if (savings > 0) "Yes" else "No";
-
- try stdout.print(" β {d:6.1}% β {d:8} β {d:8} β {d:7.1}% β {s:8} β\n", .{
- density * 100,
- nnz,
- sparse_bytes,
- savings * 100,
- breakeven,
- });
- }
-
- try stdout.print(" ββββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββ\n\n", .{});
-
- // Performance comparison
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" PERFORMANCE COMPARISON (10% density)\n", .{});
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- const test_density: f64 = 0.10;
-
- // Create test vectors
- var sparse_a = try SparseVector.random(allocator, dimension, test_density, 11111);
- defer sparse_a.deinit();
- var sparse_b = try SparseVector.random(allocator, dimension, test_density, 22222);
- defer sparse_b.deinit();
-
- var dense_a = sparse_a.toDense();
- var dense_b = sparse_b.toDense();
-
- // Warmup
- for (0..WARMUP) |_| {
- var r1 = try SparseVector.bind(allocator, &sparse_a, &sparse_b);
- r1.deinit();
- _ = vsa.bind(&dense_a, &dense_b);
- }
-
- // BIND benchmark
- {
- // Sparse
- var timer = std.time.Timer.start() catch unreachable;
- for (0..ITERATIONS) |_| {
- var result = try SparseVector.bind(allocator, &sparse_a, &sparse_b);
- std.mem.doNotOptimizeAway(&result);
- result.deinit();
- }
- const sparse_elapsed = timer.read();
- const sparse_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(sparse_elapsed)) / 1e9);
-
- // Dense
- timer = std.time.Timer.start() catch unreachable;
- for (0..ITERATIONS) |_| {
- var result = vsa.bind(&dense_a, &dense_b);
- std.mem.doNotOptimizeAway(&result);
- }
- const dense_elapsed = timer.read();
- const dense_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(dense_elapsed)) / 1e9);
-
- const speedup = sparse_ops / dense_ops;
-
- try stdout.print(" BIND:\n", .{});
- try stdout.print(" Sparse: {d:.0} ops/sec\n", .{sparse_ops});
- try stdout.print(" Dense: {d:.0} ops/sec\n", .{dense_ops});
- try stdout.print(" Ratio: {d:.2}x {s}\n\n", .{ if (speedup > 1) speedup else 1.0 / speedup, if (speedup > 1) "(sparse faster)" else "(dense faster)" });
- }
-
- // SIMILARITY benchmark
- {
- // Sparse
- var timer = std.time.Timer.start() catch unreachable;
- var sparse_result: f64 = undefined;
- for (0..ITERATIONS) |_| {
- sparse_result = SparseVector.cosineSimilarity(&sparse_a, &sparse_b);
- std.mem.doNotOptimizeAway(&sparse_result);
- }
- const sparse_elapsed = timer.read();
- const sparse_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(sparse_elapsed)) / 1e9);
-
- // Dense
- timer = std.time.Timer.start() catch unreachable;
- var dense_result: f64 = undefined;
- for (0..ITERATIONS) |_| {
- dense_result = vsa.cosineSimilarity(&dense_a, &dense_b) catch 0.0;
- std.mem.doNotOptimizeAway(&dense_result);
- }
- const dense_elapsed = timer.read();
- const dense_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(dense_elapsed)) / 1e9);
-
- const speedup = sparse_ops / dense_ops;
-
- try stdout.print(" COSINE SIMILARITY:\n", .{});
- try stdout.print(" Sparse: {d:.0} ops/sec\n", .{sparse_ops});
- try stdout.print(" Dense: {d:.0} ops/sec\n", .{dense_ops});
- try stdout.print(" Ratio: {d:.2}x {s}\n\n", .{ if (speedup > 1) speedup else 1.0 / speedup, if (speedup > 1) "(sparse faster)" else "(dense faster)" });
- }
-
- // HAMMING benchmark
- {
- // Sparse
- var timer = std.time.Timer.start() catch unreachable;
- var sparse_result: usize = undefined;
- for (0..ITERATIONS) |_| {
- sparse_result = SparseVector.hammingDistance(&sparse_a, &sparse_b);
- std.mem.doNotOptimizeAway(&sparse_result);
- }
- const sparse_elapsed = timer.read();
- const sparse_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(sparse_elapsed)) / 1e9);
-
- // Dense
- timer = std.time.Timer.start() catch unreachable;
- var dense_result: usize = undefined;
- for (0..ITERATIONS) |_| {
- dense_result = vsa.hammingDistance(&dense_a, &dense_b);
- std.mem.doNotOptimizeAway(&dense_result);
- }
- const dense_elapsed = timer.read();
- const dense_ops = @as(f64, @floatFromInt(ITERATIONS)) / (@as(f64, @floatFromInt(dense_elapsed)) / 1e9);
-
- const speedup = sparse_ops / dense_ops;
-
- try stdout.print(" HAMMING DISTANCE:\n", .{});
- try stdout.print(" Sparse: {d:.0} ops/sec\n", .{sparse_ops});
- try stdout.print(" Dense: {d:.0} ops/sec\n", .{dense_ops});
- try stdout.print(" Ratio: {d:.2}x {s}\n\n", .{ if (speedup > 1) speedup else 1.0 / speedup, if (speedup > 1) "(sparse faster)" else "(dense faster)" });
- }
-
- // Summary
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- try stdout.print(" SUMMARY\n", .{});
- try stdout.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- try stdout.print(" WHEN TO USE SPARSE:\n", .{});
- try stdout.print(" β Density < 20%% (memory savings)\n", .{});
- try stdout.print(" β Bind operations (result is sparser)\n", .{});
- try stdout.print(" β Memory-constrained environments\n", .{});
- try stdout.print(" β Large dimensions (>10K)\n\n", .{});
-
- try stdout.print(" WHEN TO USE DENSE:\n", .{});
- try stdout.print(" β Density > 20%%\n", .{});
- try stdout.print(" β Bundle operations (result may be denser)\n", .{});
- try stdout.print(" β SIMD acceleration needed\n", .{});
- try stdout.print(" β Random access patterns\n\n", .{});
-
- try stdout.print(" ΟΒ² + 1/ΟΒ² = 3\n\n", .{});
-}
diff --git a/src/bench_ternary_vs_binary.zig b/src/bench_ternary_vs_binary.zig
deleted file mode 100644
index 617012fe70..0000000000
--- a/src/bench_ternary_vs_binary.zig
+++ /dev/null
@@ -1,228 +0,0 @@
-// BENCH-001: Ternary vs f16/bf16 Comparison
-// Minimal research benchmark for TRI-27 algorithms
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-
-const std = @import("std");
-const print = std.debug.print;
-
-const LayerConfig = struct {
- input_size: usize,
- hidden_size: usize,
- output_size: usize,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// FORMATS (reuse from src/formats.zig)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Quantize f32 value to ternary {-1, 0, +1}
-fn quantizeTernary(x: f32) i2 {
- if (x > 0.5) return 1;
- if (x < -0.5) return -1;
- return 0;
-}
-
-/// Quantize f32 to FP16 (truncate mantissa to 10 bits)
-fn quantizeFP16(x: f32) u16 {
- const bits = @as(u32, @bitCast(x));
- const sign = @as(u16, @truncate(bits >> 16));
- const exp_all = @as(u16, @truncate(bits >> 23));
- const mantissa = @as(u16, @truncate(bits >> 13)) & 0x3FF;
- return sign | (exp_all << 10) | mantissa;
-}
-
-/// Quantize f32 to BF16 (truncate mantissa to 7 bits)
-fn quantizeBF16(x: f32) u16 {
- const bits = @as(u32, @bitCast(x));
- const sign = @as(u16, @truncate(bits >> 16));
- const exp_all = @as(u16, @truncate(bits >> 23));
- const mantissa = @as(u16, @truncate(bits >> 16)) & 0x7F;
- return sign | (exp_all << 7) | mantissa;
-}
-
-/// Simple FP16 decode (for testing)
-fn decodeFP16(bits: u16) f32 {
- const sign = if (bits & 0x8000 != 0) @as(u32, 0x80000000) else 0;
- const exp = @as(u32, (bits & 0x7C00) >> 10) << 23;
- const mant = @as(u32, (bits & 0x3FF) << 13);
- return @bitCast(f32, sign | exp | mant);
-}
-
-/// Simple BF16 decode (for testing)
-fn decodeBF16(bits: u16) f32 {
- const sign = if (bits & 0x8000 != 0) @as(u32, 0x80000000) else 0;
- const exp = @as(u32, (bits & 0x7F80) >> 7) << 23;
- const mant = @as(u32, (bits & 0x007F) << 16);
- return @bitCast(f32, sign | exp | mant);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MLP FORWARD (reuse from test_mlp_semantic.zig)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-fn relu(x: f32) f32 {
- return if (x > 0) x else 0;
-}
-
-fn mlpForward(
- input: []const f32,
- w1: []const f32,
- b1: []const f32,
- w2: []const f32,
- b2: []const f32,
- hidden: []f32,
- output: []f32,
- config: LayerConfig,
-) void {
- // Layer 1: Dense + ReLU
- for (0..config.hidden_size) |h| {
- var sum_h = b1[h];
- for (0..config.input_size) |i| {
- sum_h += input[i] * w1[i * config.hidden_size + h];
- }
- hidden[h] = relu(sum_h);
- }
-
- // Layer 2: Dense + ReLU
- for (0..config.output_size) |o| {
- var sum_o = b2[o];
- for (0..config.hidden_size) |h| {
- sum_o += hidden[h] * w2[h * config.output_size + o];
- }
- output[o] = relu(sum_o);
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BENCHMARK
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn main() !void {
- const config = LayerConfig{
- .input_size = 4,
- .hidden_size = 8,
- .output_size = 3,
- };
-
- print("\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- print("β BENCH-001: Ternary vs f16/bf16 Comparison β\n", .{});
- print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- // Test input: [1.0, 0.0, 0.0, 0.0]
- const input = [_]f32{ 1.0, 0.0, 0.0, 0.0 };
-
- // Identity weights (for reproducible results)
- var w1_f32: [32]f32 = undefined;
- var b1_f32: [8]f32 = undefined;
- var w2_f32: [24]f32 = undefined;
- var b2_f32: [3]f32 = undefined;
-
- {
- var i: usize = 0;
- while (i < 32) : (i += 1) {
- const row = i / 8;
- const col = i % 8;
- w1_f32[i] = if (row == col) 1.0 else 0.0;
- }
- }
- for (&b1_f32) |*b| b.* = 0;
- {
- var i: usize = 0;
- while (i < 24) : (i += 1) {
- const row = i / 3;
- const col = i % 3;
- w2_f32[i] = if (row == col) 1.0 else 0.0;
- }
- }
- for (&b2_f32) |*b| b.* = 0;
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Experiment 1: FP32 Baseline
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- var hidden_f32: [8]f32 = undefined;
- var output_f32: [3]f32 = undefined;
- mlpForward(&input, &w1_f32, &b1_f32, &w2_f32, &b2_f32, &hidden_f32, &output_f32, config);
-
- print("Experiment 1: FP32 Baseline\n", .{});
- print(" Output: [{d:.3}, {d:.3}, {d:.3}]\n", .{ output_f32[0], output_f32[1], output_f32[2] });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Experiment 2: Ternary Weights
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- var w1_ternary: [32]i2 = undefined;
- var b1_ternary: [8]i2 = undefined;
- var w2_ternary: [24]i2 = undefined;
- var b2_ternary: [3]i2 = undefined;
-
- for (&w1_f32, 0..) |w, i| w1_ternary[i] = quantizeTernary(w.*);
- for (&b1_f32, 0..) |b, i| b1_ternary[i] = quantizeTernary(b.*);
- for (&w2_f32, 0..) |w, i| w2_ternary[i] = quantizeTernary(w.*);
- for (&b2_f32, 0..) |b, i| b2_ternary[i] = quantizeTernary(b.*);
-
- // Convert ternary back to f32 for forward pass
- var w1_t_f32: [32]f32 = undefined;
- var b1_t_f32: [8]f32 = undefined;
- var w2_t_f32: [24]f32 = undefined;
- var b2_t_f32: [3]f32 = undefined;
-
- for (&w1_ternary, 0..) |w, i| w1_t_f32[i] = @as(f32, @floatFromInt(w.*));
- for (&b1_ternary, 0..) |b, i| b1_t_f32[i] = @as(f32, @floatFromInt(b.*));
- for (&w2_ternary, 0..) |w, i| w2_t_f32[i] = @as(f32, @floatFromInt(w.*));
- for (&b2_ternary, 0..) |b, i| b2_t_f32[i] = @as(f32, @floatFromInt(b.*));
-
- var hidden_ternary: [8]f32 = undefined;
- var output_ternary: [3]f32 = undefined;
- mlpForward(&input, &w1_t_f32, &b1_t_f32, &w2_t_f32, &b2_t_f32, &hidden_ternary, &output_ternary, config);
-
- print("Experiment 2: Ternary Weights\n", .{});
- print(" Output: [{d:.3}, {d:.3}, {d:.3}]\n", .{ output_ternary[0], output_ternary[1], output_ternary[2] });
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Experiment 3: FP16 Weights
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- var w1_fp16: [32]u16 = undefined;
- for (&w1_f32, 0..) |w, i| w1_fp16[i] = quantizeFP16(w.*);
-
- print("Experiment 3: FP16 Weights\n", .{});
- print(" (Not implemented - requires full FP16 arithmetic)\n", .{});
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Experiment 4: BF16 Weights
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- var w1_bf16: [32]u16 = undefined;
- for (&w1_f32, 0..) |w, i| w1_bf16[i] = quantizeBF16(w.*);
-
- print("Experiment 4: BF16 Weights\n", .{});
- print(" (Not implemented - requires full BF16 arithmetic)\n", .{});
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Results Summary
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- print("\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- print("Results Summary:\n", .{});
- print(" Format | Output[0] | Output[1] | Output[2]\n", .{});
- print(" ββββββββββΌββββββββββββΌββββββββββββΌβββββββββββ\n", .{});
- print(" FP32 | {d:.3} | {d:.3} | {d:.3} \n", .{ output_f32[0], output_f32[1], output_f32[2] });
- print(" Ternary | {d:.3} | {d:.3} | {d:.3} \n", .{ output_ternary[0], output_ternary[1], output_ternary[2] });
- print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- // Accuracy comparison
- const diff0 = @abs(output_f32[0] - output_ternary[0]);
- const diff1 = @abs(output_f32[1] - output_ternary[1]);
- const diff2 = @abs(output_f32[2] - output_ternary[2]);
- const max_diff = @max(@max(diff0, diff1), diff2);
-
- print("Ternary vs FP32:\n", .{});
- print(" Max difference: {d:.3}\n", .{max_diff});
- if (max_diff < 0.5) {
- print(" β
PASS: difference < 0.5\n", .{});
- } else {
- print(" β FAIL: difference >= 0.5\n", .{});
- }
- print("\nβ
Trinity Identity: ΟΒ² + 1/ΟΒ² = {d:.15} β 3.0\n", .{2.618033988749895 + 1.0 / 2.618033988749895});
-}
diff --git a/src/blind_spot/unified_framework.zig b/src/blind_spot/unified_framework.zig
index edaf140092..f1268330f6 100644
--- a/src/blind_spot/unified_framework.zig
+++ b/src/blind_spot/unified_framework.zig
@@ -23,11 +23,11 @@ const std = @import("std");
const math = std.math;
const mem = std.mem;
-// Import from canonical source
-const sacred_constants = @import("sacred_constants_reexport.zig");
+// Import from math_bridge (tri-math migration complete)
+const bridge = @import("../math_bridge.zig");
/// Golden ratio Ο = (1 + β5)/2
-pub const PHI = sacred_constants.PHI;
+pub const PHI = bridge.PHI;
/// ΟΒ³ = 4.23606797749978969641...
pub const PHI_CUBED: f64 = PHI * PHI * PHI;
diff --git a/src/brain/basal_ganglia.zig.bak2 b/src/brain/basal_ganglia.zig.bak2
deleted file mode 100644
index 1dfa980143..0000000000
--- a/src/brain/basal_ganglia.zig.bak2
+++ /dev/null
@@ -1,1145 +0,0 @@
-//! BASAL GANGLIA β v2.1 β Lock-Free Action Selection
-//!
-//! Sharded HashMap design for lock-free reads and minimal contention writes.
-//! Target: > 10k OP/s through horizontal scaling.
-//!
-//! Design Principles:
-//! 1. Sharded HashMap: Partition keys into N shards (default: 16)
-//! 2. Each shard has its own RwLock for independent access
-//! 3. Read-heavy operations can proceed in parallel across shards
-//! 4. Write operations only block their specific shard
-//!
-//! Expected Performance:
-//! - With 16 shards: ~16x reduction in contention
-//! - Single-threaded: ~5k OP/s (current baseline)
-//! - Multi-threaded: ~50k+ OP/s (theoretical with 16 threads)
-//!
-//! Thread Safety:
-//! - All operations are thread-safe
-//! - Atomic counters for statistics (lock-free reads)
-//! - RwLock per shard allows concurrent reads
-//! - Global mutex only for singleton initialization
-//!
-//! Memory Management:
-//! - All task_id and agent_id strings are duplicated
-//! - Caller must NOT free strings passed to claim()
-//! - Registry owns all duplicated strings until deinit/reset
-
-const std = @import("std");
-
-const SHARD_COUNT: usize = 16; // Must be power of 2 for fast hash
-
-// Compile-time validation that SHARD_COUNT is a power of 2
-comptime {
- if (!std.math.isPowerOfTwo(SHARD_COUNT)) {
- @compileError("SHARD_COUNT must be a power of 2");
- }
-}
-
-/// Status of a task claim
-pub const ClaimStatus = enum(u8) { active = 0, completed = 1, abandoned = 2 };
-
-/// Task claim metadata
-///
-/// Tracks which agent owns a task, when it was claimed,
-/// and whether it's still valid.
-///
-/// # Validity Rules
-/// - Status must be `.active`
-/// - Age (now - claimed_at) must be <= ttl_ms
-/// - Heartbeat age (now - last_heartbeat) must be <= 30000ms
-/// - Clock skew is handled: future timestamps are treated as now
-pub const TaskClaim = struct {
- task_id: []const u8,
- agent_id: []const u8,
- claimed_at: i64,
- ttl_ms: u64,
- status: ClaimStatus,
- completed_at: ?i64,
- last_heartbeat: i64,
-
- pub fn isValid(self: *const TaskClaim) bool {
- if (self.status != .active) return false;
- const now_ms = std.time.timestamp() * 1000;
-
- // Handle clock skew: if claimed_at is in future, treat as valid
- const age_ms = if (self.claimed_at > now_ms)
- @as(u64, 0)
- else
- @as(u64, @intCast(now_ms - self.claimed_at));
-
- if (age_ms > self.ttl_ms) return false;
-
- const heartbeat_age_ms = if (self.last_heartbeat > now_ms)
- @as(u64, 0)
- else
- @as(u64, @intCast(now_ms - self.last_heartbeat));
-
- if (heartbeat_age_ms > 30000) return false;
- return true;
- }
-};
-
-/// A single shard of the HashMap with its own lock
-///
-/// Each shard operates independently - operations on different shards
-/// can proceed in parallel. This is the key to the registry's scalability.
-///
-/// # Lock Ordering
-/// - Never acquire multiple shard locks simultaneously
-/// - Always release locks before acquiring another shard's lock
-/// - This prevents deadlocks in concurrent scenarios
-const Shard = struct {
- claims: std.StringHashMap(TaskClaim),
- rwlock: std.Thread.RwLock,
-
- fn init(allocator: std.mem.Allocator) Shard {
- return Shard{
- .claims = std.StringHashMap(TaskClaim).init(allocator),
- .rwlock = std.Thread.RwLock{},
- };
- }
-
- /// Releases all resources owned by this shard
- ///
- /// # Safety
- /// Must not be called while any thread holds a reference to claims
- fn deinit(self: *Shard) void {
- var iter = self.claims.iterator();
- while (iter.next()) |entry| {
- self.claims.allocator.free(entry.key_ptr.*);
- self.claims.allocator.free(entry.value_ptr.task_id);
- self.claims.allocator.free(entry.value_ptr.agent_id);
- }
- self.claims.deinit();
- }
-
- /// Returns the number of claims in this shard
- ///
- /// # Thread Safety
- /// Caller must hold either shared or exclusive lock
- inline fn count(self: *const Shard) usize {
- return self.claims.count();
- }
-};
-
-/// Lock-free (sharded) task claim registry
-///
-/// Uses sharding to reduce contention:
-/// - Keys are hashed to determine which shard they belong to
-/// - Each shard has its own RwLock
-/// - Operations on different shards can proceed in parallel
-///
-/// # Performance Characteristics
-/// - **Reads**: Lock-free per shard (RwLock.readLock)
-/// - **Writes**: Only block one shard (RwLock.lock)
-/// - **Contention**: Reduced by factor of SHARD_COUNT (16x)
-///
-/// # Memory Usage
-/// - Each claim: ~64 bytes + string storage
-/// - Empty registry: ~1 KB (16 empty shards)
-/// - 1000 claims: ~70 KB typical
-pub const Registry = struct {
- shards: [SHARD_COUNT]Shard,
- allocator: std.mem.Allocator,
- stats: struct {
- /// Total number of claim() attempts
- claim_attempts: std.atomic.Value(u64),
- /// Number of successful claims
- claim_success: std.atomic.Value(u64),
- /// Number of failed claims due to conflict
- claim_conflicts: std.atomic.Value(u64),
- /// Total number of heartbeat() calls
- heartbeat_calls: std.atomic.Value(u64),
- /// Number of successful heartbeats
- heartbeat_success: std.atomic.Value(u64),
- /// Total number of complete() calls
- complete_calls: std.atomic.Value(u64),
- /// Number of successful completions
- complete_success: std.atomic.Value(u64),
- /// Total number of abandon() calls
- abandon_calls: std.atomic.Value(u64),
- /// Number of successful abandonments
- abandon_success: std.atomic.Value(u64),
- },
-
- /// Creates a new sharded task claim registry
- ///
- /// # Parameters
- /// - `allocator`: Used for all internal allocations (claims, string copies)
- ///
- /// # Thread Safety
- /// Safe to call from multiple threads if synchronized externally
- pub fn init(allocator: std.mem.Allocator) Registry {
- var shards: [SHARD_COUNT]Shard = undefined;
- for (&shards) |*shard| {
- shard.* = Shard.init(allocator);
- }
-
- return Registry{
- .shards = shards,
- .allocator = allocator,
- .stats = .{
- .claim_attempts = std.atomic.Value(u64).init(0),
- .claim_success = std.atomic.Value(u64).init(0),
- .claim_conflicts = std.atomic.Value(u64).init(0),
- .heartbeat_calls = std.atomic.Value(u64).init(0),
- .heartbeat_success = std.atomic.Value(u64).init(0),
- .complete_calls = std.atomic.Value(u64).init(0),
- .complete_success = std.atomic.Value(u64).init(0),
- .abandon_calls = std.atomic.Value(u64).init(0),
- .abandon_success = std.atomic.Value(u64).init(0),
- },
- };
- }
-
- /// Frees all resources used by the registry
- pub fn deinit(self: *Registry) void {
- for (&self.shards) |*shard| {
- shard.deinit();
- }
- }
-
- /// Computes which shard a key belongs to
- ///
- /// Uses Wyhash for fast, uniform distribution and bitmask
- /// for O(1) shard selection (SHARD_COUNT must be power of 2).
- ///
- /// # Properties
- /// - Deterministic: same task_id always maps to same shard
- /// - Uniform distribution: good hash function spreads keys evenly
- /// - No collisions modulo: bitmask is safe due to power-of-2 constraint
- inline fn getShardIndex(task_id: []const u8) usize {
- const hash = std.hash.Wyhash.hash(0, task_id);
- return hash & (SHARD_COUNT - 1);
- }
-
- /// Gets the shard for a given task_id
- ///
- /// # Returns
- /// Pointer to the shard that owns this task_id
- ///
- /// # Thread Safety
- /// Safe to call from any thread, but returned shard's lock
- /// must be acquired before accessing its data
- inline fn getShard(self: *Registry, task_id: []const u8) *Shard {
- const idx = getShardIndex(task_id);
- return &self.shards[idx];
- }
-
- /// Atomically claims a task for an agent
- ///
- /// Only locks the specific shard for this task_id,
- /// allowing other tasks to be claimed concurrently.
- ///
- /// # Parameters
- ///
- /// - `allocator`: Allocator for storing claimed task IDs and agent IDs
- /// - `task_id`: Unique identifier for the task to claim
- /// - `agent_id`: Unique identifier for the claiming agent
- /// - `ttl_ms`: Time-to-live in milliseconds
- ///
- /// # Returns
- ///
- /// - `true` if task was successfully claimed by this agent
- /// - `false` if task is already claimed by another agent
- ///
- /// # Errors
- ///
- /// Returns `error.OutOfMemory` if allocation fails
- pub fn claim(self: *Registry, allocator: std.mem.Allocator, task_id: []const u8, agent_id: []const u8, ttl_ms: u64) !bool {
- _ = self.stats.claim_attempts.fetchAdd(1, .monotonic);
-
- const shard = self.getShard(task_id);
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
-
- const now_ms = std.time.timestamp() * 1000;
-
- // Check if already claimed and valid
- if (shard.claims.get(task_id)) |existing| {
- if (existing.isValid()) {
- _ = self.stats.claim_conflicts.fetchAdd(1, .monotonic);
- return false; // Already claimed
- }
- }
-
- // Remove old claim if exists
- if (shard.claims.fetchRemove(task_id)) |old_entry| {
- allocator.free(old_entry.key);
- allocator.free(old_entry.value.task_id);
- allocator.free(old_entry.value.agent_id);
- }
-
- // Create new claim
- const key_dup = try allocator.dupe(u8, task_id);
- errdefer allocator.free(key_dup);
-
- const task_id_dup = try allocator.dupe(u8, task_id);
- errdefer allocator.free(task_id_dup);
-
- const agent_id_dup = try allocator.dupe(u8, agent_id);
- errdefer allocator.free(agent_id_dup);
-
- const new_claim = TaskClaim{
- .task_id = task_id_dup,
- .agent_id = agent_id_dup,
- .claimed_at = now_ms,
- .ttl_ms = ttl_ms,
- .status = .active,
- .completed_at = null,
- .last_heartbeat = now_ms,
- };
-
- try shard.claims.put(key_dup, new_claim);
- _ = self.stats.claim_success.fetchAdd(1, .monotonic);
- return true;
- }
-
- /// Refreshes the heartbeat timestamp for a claimed task
- ///
- /// Only locks the specific shard for this task_id.
- pub fn heartbeat(self: *Registry, task_id: []const u8, agent_id: []const u8) bool {
- _ = self.stats.heartbeat_calls.fetchAdd(1, .monotonic);
-
- const shard = self.getShard(task_id);
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
-
- if (shard.claims.getEntry(task_id)) |entry| {
- const entry_claim = &entry.value_ptr.*;
- if (std.mem.eql(u8, entry_claim.agent_id, agent_id) and entry_claim.isValid()) {
- entry_claim.last_heartbeat = std.time.timestamp() * 1000;
- _ = self.stats.heartbeat_success.fetchAdd(1, .monotonic);
- return true;
- }
- }
- return false;
- }
-
- /// Marks a task as completed
- ///
- /// Only locks the specific shard for this task_id.
- pub fn complete(self: *Registry, task_id: []const u8, agent_id: []const u8) bool {
- _ = self.stats.complete_calls.fetchAdd(1, .monotonic);
-
- const shard = self.getShard(task_id);
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
-
- if (shard.claims.getEntry(task_id)) |entry| {
- const entry_claim = &entry.value_ptr.*;
- if (std.mem.eql(u8, entry_claim.agent_id, agent_id) and entry_claim.isValid()) {
- entry_claim.status = .completed;
- entry_claim.completed_at = std.time.timestamp() * 1000;
- _ = self.stats.complete_success.fetchAdd(1, .monotonic);
- return true;
- }
- }
- return false;
- }
-
- /// Abandons a claimed task
- ///
- /// Only locks the specific shard for this task_id.
- pub fn abandon(self: *Registry, task_id: []const u8, agent_id: []const u8) bool {
- _ = self.stats.abandon_calls.fetchAdd(1, .monotonic);
-
- const shard = self.getShard(task_id);
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
-
- if (shard.claims.getEntry(task_id)) |entry| {
- const entry_claim = &entry.value_ptr.*;
- if (std.mem.eql(u8, entry_claim.agent_id, agent_id) and entry_claim.isValid()) {
- entry_claim.status = .abandoned;
- entry_claim.completed_at = std.time.timestamp() * 1000;
- _ = self.stats.abandon_success.fetchAdd(1, .monotonic);
- return true;
- }
- }
- return false;
- }
-
- /// Clears all task claims from the registry
- ///
- /// Frees all memory associated with claims while preserving shard capacity.
- ///
- /// # Thread Safety
- /// Exclusively locks each shard sequentially. Other threads will block
- /// until reset completes.
- ///
- /// # Performance
- /// O(N) where N is total number of claims across all shards
- pub fn reset(self: *Registry) void {
- for (&self.shards) |*shard| {
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
-
- var iter = shard.claims.iterator();
- while (iter.next()) |entry| {
- shard.claims.allocator.free(entry.key_ptr.*);
- shard.claims.allocator.free(entry.value_ptr.task_id);
- shard.claims.allocator.free(entry.value_ptr.agent_id);
- }
- shard.claims.clearRetainingCapacity();
- }
- }
-
- /// Removes expired and invalid claims from all shards
- ///
- /// This is a maintenance operation that should be called periodically
- /// to reclaim memory from abandoned or timed-out tasks.
- ///
- /// # Returns
- /// Number of claims that were removed
- ///
- /// # Thread Safety
- /// Exclusively locks each shard sequentially
- pub fn cleanupExpired(self: *Registry) usize {
- var total_removed: usize = 0;
-
- for (&self.shards) |*shard| {
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
-
- var to_remove = std.ArrayList([]const u8).init(self.allocator);
- defer {
- for (to_remove.items) |key| {
- self.allocator.free(key);
- }
- to_remove.deinit();
- };
-
- // First pass: identify expired claims
- var iter = shard.claims.iterator();
- while (iter.next()) |entry| {
- if (!entry.value_ptr.isValid()) {
- to_remove.append(entry.key_ptr.*) catch continue;
- }
- }
-
- // Second pass: remove identified claims
- for (to_remove.items) |key| {
- if (shard.claims.fetchRemove(key)) |removed| {
- self.allocator.free(removed.key);
- self.allocator.free(removed.value.task_id);
- self.allocator.free(removed.value.agent_id);
- total_removed += 1;
- }
- }
- }
-
- return total_removed;
- }
-
- /// Gets current statistics for the registry
- ///
- /// # Returns
- /// Snapshot of current stats and active claim count
- ///
- /// # Thread Safety
- /// - Atomic counters are lock-free
- /// - active_claims requires shared locks on all shards
- ///
- /// # Performance
- /// O(SHARD_COUNT) for counting active claims
- pub fn getStats(self: *Registry) struct {
- claim_attempts: u64,
- claim_success: u64,
- claim_conflicts: u64,
- heartbeat_calls: u64,
- heartbeat_success: u64,
- complete_calls: u64,
- complete_success: u64,
- abandon_calls: u64,
- abandon_success: u64,
- active_claims: usize,
- } {
- // Count active claims (requires read locks on all shards)
- var total_claims: usize = 0;
- for (&self.shards) |*shard| {
- shard.rwlock.lockShared();
- defer shard.rwlock.unlockShared();
- total_claims += shard.count();
- }
-
- return .{
- .claim_attempts = self.stats.claim_attempts.load(.monotonic),
- .claim_success = self.stats.claim_success.load(.monotonic),
- .claim_conflicts = self.stats.claim_conflicts.load(.monotonic),
- .heartbeat_calls = self.stats.heartbeat_calls.load(.monotonic),
- .heartbeat_success = self.stats.heartbeat_success.load(.monotonic),
- .complete_calls = self.stats.complete_calls.load(.monotonic),
- .complete_success = self.stats.complete_success.load(.monotonic),
- .abandon_calls = self.stats.abandon_calls.load(.monotonic),
- .abandon_success = self.stats.abandon_success.load(.monotonic),
- .active_claims = total_claims,
- };
- }
-
- /// Gets shard distribution stats for monitoring
- pub fn getShardStats(self: *Registry) [SHARD_COUNT]usize {
- var stats: [SHARD_COUNT]usize = undefined;
- for (&self.shards, 0..) |*shard, i| {
- shard.rwlock.lockShared();
- stats[i] = shard.count();
- shard.rwlock.unlockShared();
- }
- return stats;
- }
-
- /// Returns the total number of claims across all shards
- ///
- /// # Thread Safety
- /// Acquires shared lock on each shard
- ///
- /// # Performance
- /// O(SHARD_COUNT) - must visit every shard
- pub fn count(self: *Registry) usize {
- var total: usize = 0;
- for (&self.shards) |*shard| {
- shard.rwlock.lockShared();
- defer shard.rwlock.unlockShared();
- total += shard.count();
- }
- return total;
- }
-
- /// Checks if a task is currently claimed and valid
- ///
- /// # Returns
- /// - `.claimed` if task exists and is valid
- /// - `.not_found` if task doesn't exist
- /// - `.expired` if task exists but is invalid (timeout/abandoned)
- pub const ClaimCheckResult = enum(u8) { claimed, not_found, expired };
-
- pub fn checkClaim(self: *Registry, task_id: []const u8) ClaimCheckResult {
- const shard = self.getShard(task_id);
- shard.rwlock.lockShared();
- defer shard.rwlock.unlockShared();
-
- if (shard.claims.get(task_id)) |claim| {
- return if (claim.isValid()) .claimed else .expired;
- }
- return .not_found;
- }
-
- /// ClaimInfo - Public information about a claim (read-only)
- pub const ClaimInfo = struct {
- task_id: []const u8,
- agent_id: []const u8,
- claimed_at: i64,
- ttl_ms: u64,
- status: ClaimStatus,
- is_valid: bool,
- };
-
- /// Lists all claims across all shards.
- /// Caller owns the returned slice and must free it.
- pub fn listClaims(self: *Registry, allocator: std.mem.Allocator) ![]ClaimInfo {
- // First pass: count claims to pre-allocate
- var total_count: usize = 0;
- for (&self.shards) |*shard| {
- shard.rwlock.lockShared();
- total_count += shard.count();
- shard.rwlock.unlockShared();
- }
-
- // Allocate result array
- var claims = try std.ArrayList(ClaimInfo).initCapacity(allocator, total_count);
- errdefer claims.deinit(allocator);
-
- // Second pass: collect claims
- for (&self.shards) |*shard| {
- shard.rwlock.lockShared();
- var iter = shard.claims.iterator();
- while (iter.next()) |entry| {
- const task_claim = entry.value_ptr.*;
- const info = ClaimInfo{
- .task_id = entry.key_ptr.*,
- .agent_id = task_claim.agent_id,
- .claimed_at = task_claim.claimed_at,
- .ttl_ms = task_claim.ttl_ms,
- .status = task_claim.status,
- .is_valid = task_claim.isValid(),
- };
- try claims.append(allocator, info);
- }
- shard.rwlock.unlockShared();
- }
-
- return claims.toOwnedSlice(allocator);
- }
-
- /// Frees a list of claims returned by listClaims.
- pub fn freeClaims(self: *Registry, allocator: std.mem.Allocator, claims: []ClaimInfo) void {
- _ = self;
- allocator.free(claims);
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// GLOBAL REGISTRY SINGLETON
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_registry: ?*Registry = null;
-var global_allocator: ?std.mem.Allocator = null;
-var global_mutex = std.Thread.Mutex{};
-
-/// Gets or creates the global task claim registry
-pub fn getGlobal(allocator: std.mem.Allocator) !*Registry {
- global_mutex.lock();
- defer global_mutex.unlock();
-
- if (global_registry) |reg| return reg;
-
- const reg = try allocator.create(Registry);
- reg.* = Registry.init(allocator);
- global_registry = reg;
- global_allocator = allocator;
- return reg;
-}
-
-/// Resets the global registry
-pub fn resetGlobal(allocator: std.mem.Allocator) void {
- _ = allocator;
- global_mutex.lock();
- defer global_mutex.unlock();
-
- if (global_registry) |reg| {
- reg.deinit();
- if (global_allocator) |alloc| {
- alloc.destroy(reg);
- }
- global_registry = null;
- global_allocator = null;
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "LockFree: basic claim success" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const claimed = try registry.claim(allocator, "task-123", "agent-001", 60000);
- try std.testing.expect(claimed);
-}
-
-test "LockFree: duplicate claim fails" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-duplicate";
- _ = try registry.claim(allocator, task_id, "agent-001", 60000);
-
- const claimed_again = try registry.claim(allocator, task_id, "agent-002", 60000);
- try std.testing.expect(!claimed_again);
-}
-
-test "LockFree: heartbeat success" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-heartbeat";
- const agent_id = "agent-heartbeat";
-
- _ = try registry.claim(allocator, task_id, agent_id, 60000);
-
- const heartbeat_ok = registry.heartbeat(task_id, agent_id);
- try std.testing.expect(heartbeat_ok);
-
- const heartbeat_wrong = registry.heartbeat(task_id, "wrong-agent");
- try std.testing.expect(!heartbeat_wrong);
-}
-
-test "LockFree: complete task" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-complete";
- const agent_id = "agent-complete";
-
- _ = try registry.claim(allocator, task_id, agent_id, 60000);
-
- const completed = registry.complete(task_id, agent_id);
- try std.testing.expect(completed);
-
- const completed_again = registry.complete(task_id, agent_id);
- try std.testing.expect(!completed_again);
-}
-
-test "LockFree: abandon task" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-abandon";
- const agent_id = "agent-abandon";
-
- _ = try registry.claim(allocator, task_id, agent_id, 60000);
-
- const abandoned = registry.abandon(task_id, agent_id);
- try std.testing.expect(abandoned);
-
- const abandoned_again = registry.abandon(task_id, agent_id);
- try std.testing.expect(!abandoned_again);
-}
-
-test "LockFree: re-claim after completion" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-reclaim";
- const agent1 = "agent-001";
- const agent2 = "agent-002";
-
- _ = try registry.claim(allocator, task_id, agent1, 60000);
- try std.testing.expect(registry.complete(task_id, agent1));
-
- const claimed = try registry.claim(allocator, task_id, agent2, 60000);
- try std.testing.expect(claimed);
-}
-
-test "LockFree: reset clears all" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- for (0..10) |i| {
- const task_id = try std.fmt.allocPrint(allocator, "task-{d}", .{i});
- defer allocator.free(task_id);
- _ = try registry.claim(allocator, task_id, "agent-001", 60000);
- }
-
- const stats = registry.getStats();
- try std.testing.expectEqual(@as(usize, 10), stats.active_claims);
-
- registry.reset();
-
- const stats_after = registry.getStats();
- try std.testing.expectEqual(@as(usize, 0), stats_after.active_claims);
-}
-
-test "LockFree: shard distribution" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- // Add many tasks - should distribute across shards
- for (0..100) |i| {
- const task_id = try std.fmt.allocPrint(allocator, "task-{d}", .{i});
- defer allocator.free(task_id);
- _ = try registry.claim(allocator, task_id, "agent-001", 60000);
- }
-
- const shard_stats = registry.getShardStats();
- var total: usize = 0;
- for (shard_stats) |count| {
- total += count;
- }
- try std.testing.expectEqual(@as(usize, 100), total);
-
- // Check distribution is roughly even (no shard should be empty with 100 tasks)
- for (shard_stats) |count| {
- try std.testing.expect(count > 0);
- }
-}
-
-test "LockFree: concurrent shard access" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- // Tasks that hash to different shards can be claimed concurrently
- // (in single-threaded test, we just verify they go to different shards)
- const task1 = "task-000";
- const task2 = "task-001";
-
- _ = try registry.claim(allocator, task1, "agent-001", 60000);
- _ = try registry.claim(allocator, task2, "agent-002", 60000);
-
- const shard_stats = registry.getShardStats();
- var shards_with_claims: usize = 0;
- for (shard_stats) |count| {
- if (count > 0) shards_with_claims += 1;
- }
-
- // Should have at least 2 shards with claims
- try std.testing.expect(shards_with_claims >= 2);
-}
-
-test "LockFree: claim throughput benchmark" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const iterations = 100_000;
- var task_buf: [32]u8 = undefined;
-
- const start = std.time.nanoTimestamp();
- var i: u64 = 0;
- while (i < iterations) : (i += 1) {
- const task_id = try std.fmt.bufPrintZ(&task_buf, "task-{d}", .{i});
- _ = try registry.claim(allocator, task_id, "agent-001", 300000);
- }
- const elapsed_ns = @as(u64, @intCast(std.time.nanoTimestamp() - start));
- const ops_per_sec = @as(f64, @floatFromInt(iterations)) / @as(f64, @floatFromInt(elapsed_ns));
- _ = std.debug.print("LockFree Sharded Basal Ganglia: {d:.0} OP/s ({d:.2} ns/op)\n", .{ ops_per_sec * 1_000_000_000.0, @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iterations)) });
-}
-
-test "LockFree: heartbeat throughput benchmark" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const iterations = 100_000;
- var task_buf: [32]u8 = undefined;
-
- // Pre-populate
- var i: u64 = 0;
- while (i < iterations) : (i += 1) {
- const task_id = try std.fmt.bufPrintZ(&task_buf, "task-{d}", .{i});
- _ = try registry.claim(allocator, task_id, "agent-001", 300000);
- }
-
- // Benchmark heartbeat
- i = 0;
- const start = std.time.nanoTimestamp();
- while (i < iterations) : (i += 1) {
- const task_id = try std.fmt.bufPrintZ(&task_buf, "task-{d}", .{i});
- _ = registry.heartbeat(task_id, "agent-001");
- }
- const elapsed_ns = @as(u64, @intCast(std.time.nanoTimestamp() - start));
- const ops_per_sec = @as(f64, @floatFromInt(iterations)) / @as(f64, @floatFromInt(elapsed_ns));
- _ = std.debug.print("LockFree Sharded Basal Ganglia Heartbeat: {d:.0} OP/s ({d:.2} ns/op)\n", .{ ops_per_sec * 1_000_000_000.0, @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iterations)) });
-}
-
-test "LockFree: stats are thread-safe" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- // Stats should be lock-free atomic
- _ = try registry.claim(allocator, "task-1", "agent-1", 60000);
- _ = try registry.claim(allocator, "task-2", "agent-2", 60000);
-
- const stats = registry.getStats();
- try std.testing.expectEqual(@as(u64, 2), stats.claim_attempts);
- try std.testing.expectEqual(@as(u64, 2), stats.claim_success);
- try std.testing.expectEqual(@as(usize, 2), stats.active_claims);
-}
-
-test "LockFree: claim expiration by TTL" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-expire";
- _ = try registry.claim(allocator, task_id, "agent-001", 1); // 1ms TTL
-
- // Wait for expiration
- std.time.sleep(5 * std.time.ns_per_ms);
-
- // Claim should be available again (old one expired)
- const reclaimed = try registry.claim(allocator, task_id, "agent-002", 60000);
- try std.testing.expect(reclaimed);
-}
-
-test "LockFree: claim expiration by heartbeat" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-heartbeat-expire";
- const agent_id = "agent-001";
-
- _ = try registry.claim(allocator, task_id, agent_id, 60000);
-
- // Manually set heartbeat to past (31 seconds ago)
- const shard = registry.getShard(task_id);
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
- if (shard.claims.getEntry(task_id)) |entry| {
- const now = std.time.timestamp();
- entry.value_ptr.*.last_heartbeat = (now - 31) * 1000;
- }
-
- // Task should now be invalid
- const check_result = registry.checkClaim(task_id);
- try std.testing.expectEqual(ClaimCheckResult.expired, check_result);
-}
-
-test "LockFree: re-claim after expiration" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-reclaim-expire";
- _ = try registry.claim(allocator, task_id, "agent-001", 1); // 1ms TTL
-
- // Wait for expiration
- std.time.sleep(5 * std.time.ns_per_ms);
-
- // Should be claimable by different agent
- const claimed = try registry.claim(allocator, task_id, "agent-002", 60000);
- try std.testing.expect(claimed);
-}
-
-test "LockFree: clock skew handling" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-clock-skew";
- _ = try registry.claim(allocator, task_id, "agent-001", 60000);
-
- // Simulate clock skew: set claimed_at to future
- const shard = registry.getShard(task_id);
- shard.rwlock.lock();
- defer shard.rwlock.unlock();
- if (shard.claims.getEntry(task_id)) |entry| {
- const future = std.time.timestamp() + 3600; // 1 hour in future
- entry.value_ptr.*.claimed_at = future * 1000;
- entry.value_ptr.*.last_heartbeat = future * 1000;
- }
-
- // Task should still be valid despite clock skew
- const check_result = registry.checkClaim(task_id);
- try std.testing.expectEqual(ClaimCheckResult.claimed, check_result);
-}
-
-test "LockFree: cleanup removes expired claims" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- // Add some tasks
- for (0..5) |i| {
- const task_id = try std.fmt.allocPrint(allocator, "task-{d}", .{i});
- defer allocator.free(task_id);
- _ = try registry.claim(allocator, task_id, "agent-001", 60000);
- }
-
- // Add one short-lived task
- _ = try registry.claim(allocator, "short-lived", "agent-001", 1);
- try std.testing.expectEqual(@as(usize, 6), registry.count());
-
- // Wait for expiration
- std.time.sleep(5 * std.time.ns_per_ms);
-
- // Cleanup should remove expired claim
- const removed = registry.cleanupExpired();
- try std.testing.expectEqual(@as(usize, 1), removed);
- try std.testing.expectEqual(@as(usize, 5), registry.count());
-}
-
-test "LockFree: checkClaim status" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-check";
-
- // Not found initially
- try std.testing.expectEqual(ClaimCheckResult.not_found, registry.checkClaim(task_id));
-
- // Claimed after registration
- _ = try registry.claim(allocator, task_id, "agent-001", 60000);
- try std.testing.expectEqual(ClaimCheckResult.claimed, registry.checkClaim(task_id));
-
- // Expired after completion
- _ = registry.complete(task_id, "agent-001");
- try std.testing.expectEqual(ClaimCheckResult.expired, registry.checkClaim(task_id));
-
- // Expired after abandonment
- _ = try registry.claim(allocator, task_id, "agent-002", 60000);
- _ = registry.abandon(task_id, "agent-002");
- try std.testing.expectEqual(ClaimCheckResult.expired, registry.checkClaim(task_id));
-}
-
-test "LockFree: listClaims returns correct info" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- _ = try registry.claim(allocator, "task-1", "agent-1", 60000);
- _ = try registry.claim(allocator, "task-2", "agent-2", 60000);
-
- const claims = try registry.listClaims(allocator);
- defer registry.freeClaims(allocator, claims);
-
- try std.testing.expectEqual(@as(usize, 2), claims.len);
-
- // Verify claim info structure
- for (claims) |claim| {
- try std.testing.expect(claim.status == .active);
- try std.testing.expect(claim.is_valid);
- }
-}
-
-test "LockFree: same task cannot be claimed twice by same agent" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-double-claim";
- const agent_id = "agent-greedy";
-
- _ = try registry.claim(allocator, task_id, agent_id, 60000);
-
- // Same agent trying to claim again should fail (already has it)
- const claimed_again = try registry.claim(allocator, task_id, agent_id, 60000);
- try std.testing.expect(!claimed_again);
-}
-
-test "LockFree: heartbeat only works for owning agent" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "task-ownership";
-
- _ = try registry.claim(allocator, task_id, "agent-owner", 60000);
-
- // Wrong agent cannot heartbeat
- const wrong_heartbeat = registry.heartbeat(task_id, "agent-imposter");
- try std.testing.expect(!wrong_heartbeat);
-
- // Owner can heartbeat
- const right_heartbeat = registry.heartbeat(task_id, "agent-owner");
- try std.testing.expect(right_heartbeat);
-}
-
-test "LockFree: shard hash distribution is deterministic" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- const task_id = "deterministic-task";
-
- // Same task should always map to same shard
- const idx1 = Registry.getShardIndex(task_id);
- const idx2 = Registry.getShardIndex(task_id);
-
- try std.testing.expectEqual(idx1, idx2);
-}
-
-test "LockFree: shard distribution uniformity" {
- const allocator = std.testing.allocator;
- var registry = Registry.init(allocator);
- defer registry.deinit();
-
- // With many tasks, distribution should be roughly uniform
- const num_tasks = 1600; // 100 per shard expected
- var task_buf: [32]u8 = undefined;
-
- for (0..num_tasks) |i| {
- const task_id = try std.fmt.bufPrintZ(&task_buf, "task-{d:0>5}", .{i});
- _ = try registry.claim(allocator, task_id, "agent-001", 60000);
- }
-
- const shard_stats = registry.getShardStats();
- const expected_per_shard = num_tasks / SHARD_COUNT;
-
- // Check that no shard has more than 2x expected (reasonable tolerance)
- for (shard_stats) |count| {
- try std.testing.expect(count <= expected_per_shard * 2);
- }
-}
-
-test "LockFree: global registry singleton" {
- const allocator = std.testing.allocator;
-
- // Reset to clean state
- resetGlobal(allocator);
-
- const reg1 = try getGlobal(allocator);
- try std.testing.expect(reg1 != null);
-
- // Second call should return same instance
- const reg2 = try getGlobal(allocator);
- try std.testing.expectEqual(reg1, reg2);
-
- // Reset should clear
- resetGlobal(allocator);
-
- const reg3 = try getGlobal(allocator);
- try std.testing.expect(reg3 != null);
-
- // Should be different address after reset
- try std.testing.expect(reg1 != reg3);
-
- // Cleanup
- resetGlobal(allocator);
-}
-
-test "LockFree: out of memory handling" {
- const FailingAllocator = struct {
- parent: std.mem.Allocator,
- fail_count: usize = 0,
- should_fail: bool = false,
-
- fn alloc(
- self: *@This(),
- len: usize,
- ptr_align: u29,
- ret_addr: usize,
- ) std.mem.Allocator.Error![]u8 {
- if (self.should_fail) {
- return error.OutOfMemory;
- }
- return self.parent.rawAlloc(len, ptr_align, ret_addr);
- }
-
- fn resize(
- self: *@This(),
- buf: []u8,
- buf_align: u29,
- new_len: usize,
- ret_addr: usize,
- ) std.mem.Allocator.Error!usize {
- _ = self;
- _ = buf;
- _ = buf_align;
- _ = new_len;
- _ = ret_addr;
- return error.OutOfMemory;
- }
-
- fn free(
- self: *@This(),
- buf: []u8,
- buf_align: u29,
- ret_addr: usize,
- ) void {
- self.parent.rawFree(buf, buf_align, ret_addr);
- }
- };
-
- const failing_allocator = FailingAllocator{
- .parent = std.testing.allocator,
- .should_fail = true,
- };
-
- var registry = Registry.init(std.testing.allocator);
- defer registry.deinit();
-
- // Claim should fail with OOM
- const result = registry.claim(
- failing_allocator,
- "task-oom",
- "agent-001",
- 60000,
- );
-
- try std.testing.expectError(error.OutOfMemory, result);
-}
diff --git a/src/brain/state_recovery.zig.bak2 b/src/brain/state_recovery.zig.bak2
deleted file mode 100644
index 54ba8a2fab..0000000000
--- a/src/brain/state_recovery.zig.bak2
+++ /dev/null
@@ -1,937 +0,0 @@
-//! BRAIN STATE RECOVERY β v1.0 β Persistence and Crash Recovery
-//!
-//! Brain Region: Hippocampus (Long-term Memory Consolidation)
-//!
-//! Provides:
-//! - Save brain state to JSON (task claims, event history, metrics)
-//! - Load brain state on startup (crash recovery)
-//! - State versioning with migration support
-//! - Corrupted state file handling
-//! - Automatic recovery on startup
-//!
-//! Sacred Formula: phi^2 + 1/phi^2 = 3 = TRINITY
-
-const std = @import("std");
-const builtin = @import("builtin");
-const fs = std.fs;
-const mem = std.mem;
-const json = std.json;
-
-// Import brain region modules via module names (from build.zig)
-const basal_ganglia = @import("basal_ganglia");
-const reticular_formation = @import("reticular_formation");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// STATE VERSIONING
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Current state format version
-pub const CURRENT_VERSION: u32 = 1;
-
-/// Migration error
-pub const MigrationError = error{
- UnsupportedVersion,
- CorruptedData,
- MigrationFailed,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BRAIN STATE STRUCTURES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Task claim state for serialization
-pub const TaskClaimState = struct {
- task_id: []const u8,
- agent_id: []const u8,
- claimed_at: i64,
- ttl_ms: u64,
- status: []const u8, // "active", "completed", "abandoned"
- completed_at: ?i64,
- last_heartbeat: i64,
-};
-
-/// Event record state for serialization
-pub const EventState = struct {
- event_type: []const u8, // stringified AgentEventType
- timestamp: i64,
- task_id: []const u8,
- agent_id: []const u8,
- aux_string: []const u8, // err_msg, reason, or unused
- duration_ms: u64,
-};
-
-/// Metric snapshot for serialization
-pub const MetricSnapshot = struct {
- name: []const u8,
- value: f64,
- timestamp: i64,
- tags: []const []const u8, // key=value pairs
-};
-
-/// Complete brain state
-pub const BrainState = struct {
- version: u32 = CURRENT_VERSION,
- saved_at: i64,
- task_claims: []TaskClaimState,
- events: []EventState,
- metrics: []MetricSnapshot,
- metadata: struct {
- hostname: []const u8,
- pid: u32,
- tri_version: []const u8,
- },
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// STATE MANAGER
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const StateManager = struct {
- allocator: mem.Allocator,
- state_dir: []const u8,
- state_file_path: []const u8,
- backup_dir: []const u8,
-
- const Self = @This();
-
- /// Default state directory
- pub const DEFAULT_STATE_DIR = ".trinity/brain/state";
-
- /// Initialize state manager with default paths
- pub fn init(allocator: mem.Allocator) !Self {
- const state_dir = DEFAULT_STATE_DIR;
- try fs.cwd().makePath(state_dir);
-
- const state_file_path = try fs.path.join(allocator, &.{ state_dir, "brain_state.json" });
- errdefer allocator.free(state_file_path);
-
- const backup_dir = try fs.path.join(allocator, &.{ state_dir, "backups" });
- errdefer allocator.free(backup_dir);
-
- try fs.cwd().makePath(backup_dir);
-
- return Self{
- .allocator = allocator,
- .state_dir = state_dir,
- .state_file_path = state_file_path,
- .backup_dir = backup_dir,
- };
- }
-
- /// Free resources
- pub fn deinit(self: *Self) void {
- self.allocator.free(self.state_file_path);
- self.allocator.free(self.backup_dir);
- }
-
- /// Save current brain state to disk
- /// Returns error if save fails (caller should retry)
- pub fn save(self: *Self, registry: *basal_ganglia.Registry, event_bus: *reticular_formation.EventBus) !void {
- const state = try self.captureState(registry, event_bus);
- defer self.freeState(state);
-
- // Create backup before overwriting
- try self.createBackup();
-
- // Write to temporary file first (atomic write)
- const tmp_path = try std.fmt.allocPrint(self.allocator, "{s}.tmp", .{self.state_file_path});
- defer self.allocator.free(tmp_path);
-
- const file = try fs.cwd().createFile(tmp_path, .{ .read = true });
- defer file.close();
-
- // Write JSON with pretty formatting
- try json.stringify(state, .{ .whitespace = .indent_2 }, file.writer());
-
- // Sync to disk
- try file.sync();
-
- // Atomic rename
- try fs.cwd().rename(tmp_path, self.state_file_path);
-
- std.log.info("Brain state saved to {s}", .{self.state_file_path});
- }
-
- /// Load brain state from disk
- /// Returns error if file not found or corrupted (caller should use defaults)
- pub fn load(self: *Self) !BrainState {
- const file = fs.cwd().openFile(self.state_file_path, .{}) catch |err| {
- std.log.warn("Failed to open brain state file: {}", .{err});
- return error.FileNotFound;
- };
- defer file.close();
-
- const content = file.readToEndAlloc(self.allocator, 10 * 1024 * 1024) catch |err| {
- std.log.warn("Failed to read brain state file: {}", .{err});
- return error.CorruptedData;
- };
- defer self.allocator.free(content);
-
- var parsed = json.parseFromSlice(BrainState, self.allocator, content, .{}) catch |err| {
- std.log.warn("Failed to parse brain state JSON: {}", .{err});
- return error.CorruptedData;
- };
- defer parsed.deinit();
-
- var state = parsed.value;
-
- // Validate and migrate if needed
- try self.validateAndMigrate(&state);
-
- std.log.info("Brain state loaded from {s} (version {d})", .{ self.state_file_path, state.version });
- return state;
- }
-
- /// Capture current state from live brain components
- fn captureState(self: *Self, registry: *basal_ganglia.Registry, event_bus: *reticular_formation.EventBus) !BrainState {
- // Capture task claims
- var claims = std.ArrayList(TaskClaimState).initCapacity(self.allocator, 64) catch |err| {
- std.log.err("Failed to allocate claims: {}", .{err});
- return error.OutOfMemory;
- };
- defer claims.deinit(self.allocator);
-
- {
- registry.mutex.lock();
- defer registry.mutex.unlock();
-
- var iter = registry.claims.iterator();
- while (iter.next()) |entry| {
- const claim = &entry.value_ptr.*;
- const status_str = switch (claim.status) {
- .active => "active",
- .completed => "completed",
- .abandoned => "abandoned",
- };
-
- try claims.append(self.allocator, TaskClaimState{
- .task_id = try self.allocator.dupe(u8, claim.task_id),
- .agent_id = try self.allocator.dupe(u8, claim.agent_id),
- .claimed_at = claim.claimed_at,
- .ttl_ms = claim.ttl_ms,
- .status = status_str,
- .completed_at = claim.completed_at,
- .last_heartbeat = claim.last_heartbeat,
- });
- }
- }
-
- // Capture events from reticular formation
- var events = std.ArrayList(EventState).initCapacity(self.allocator, 256) catch |err| {
- std.log.err("Failed to allocate events: {}", .{err});
- return error.OutOfMemory;
- };
- defer events.deinit(self.allocator);
-
- {
- event_bus.mutex.lock();
- defer event_bus.mutex.unlock();
-
- for (event_bus.events.items) |ev| {
- const event_type_str = switch (ev.event_type) {
- .task_claimed => "task_claimed",
- .task_completed => "task_completed",
- .task_failed => "task_failed",
- .task_abandoned => "task_abandoned",
- .agent_idle => "agent_idle",
- .agent_spawned => "agent_spawned",
- };
-
- try events.append(self.allocator, EventState{
- .event_type = event_type_str,
- .timestamp = ev.timestamp,
- .task_id = try self.allocator.dupe(u8, ev.task_id),
- .agent_id = try self.allocator.dupe(u8, ev.agent_id),
- .aux_string = try self.allocator.dupe(u8, ev.aux_string),
- .duration_ms = ev.duration_ms,
- });
- }
- }
-
- // Capture metrics (simplified - just a snapshot)
- var metrics = std.ArrayList(MetricSnapshot).initCapacity(self.allocator, 16) catch |err| {
- std.log.err("Failed to allocate metrics: {}", .{err});
- return error.OutOfMemory;
- };
- defer metrics.deinit(self.allocator);
-
- // Add basic health metrics
- const now = std.time.milliTimestamp();
- try metrics.append(self.allocator, MetricSnapshot{
- .name = "brain.claims.count",
- .value = @floatFromInt(claims.items.len),
- .timestamp = now,
- .tags = &[_][]const u8{},
- });
- try metrics.append(self.allocator, MetricSnapshot{
- .name = "brain.events.buffered",
- .value = @floatFromInt(events.items.len),
- .timestamp = now,
- .tags = &[_][]const u8{},
- });
-
- // Get hostname (use environment or fallback)
- const hostname = std.posix.getenv("HOSTNAME") orelse std.posix.getenv("HOST") orelse "localhost";
-
- // Get PID (platform-specific) - using 0 as fallback
- const pid = if (builtin.os.tag == .linux)
- @as(i32, 0) // TODO: implement for linux
- else if (builtin.os.tag == .macos)
- @as(i32, 0) // TODO: implement for macos
- else
- @as(i32, 0);
-
- return BrainState{
- .version = CURRENT_VERSION,
- .saved_at = std.time.milliTimestamp(),
- .task_claims = try claims.toOwnedSlice(self.allocator),
- .events = try events.toOwnedSlice(self.allocator),
- .metrics = try metrics.toOwnedSlice(self.allocator),
- .metadata = .{
- .hostname = hostname,
- .pid = pid,
- .tri_version = "5.1.0-igla-ready",
- },
- };
- }
-
- /// Free state resources
- fn freeState(self: *Self, state: BrainState) void {
- for (state.task_claims) |claim| {
- self.allocator.free(claim.task_id);
- self.allocator.free(claim.agent_id);
- self.allocator.free(claim.status);
- }
- self.allocator.free(state.task_claims);
-
- for (state.events) |ev| {
- self.allocator.free(ev.event_type);
- self.allocator.free(ev.task_id);
- self.allocator.free(ev.agent_id);
- self.allocator.free(ev.aux_string);
- }
- self.allocator.free(state.events);
-
- for (state.metrics) |m| {
- self.allocator.free(m.name);
- for (m.tags) |tag| {
- self.allocator.free(tag);
- }
- self.allocator.free(m.tags);
- }
- self.allocator.free(state.metrics);
- }
-
- /// Validate and migrate state if needed
- fn validateAndMigrate(self: *Self, state: *BrainState) !void {
- if (state.version > CURRENT_VERSION) {
- std.log.err("State version {d} is newer than supported version {d}", .{ state.version, CURRENT_VERSION });
- return MigrationError.UnsupportedVersion;
- }
-
- // Migrate from older versions (no-op for v1)
- while (state.version < CURRENT_VERSION) {
- try self.migrate(state);
- }
- }
-
- /// Migrate state to next version
- fn migrate(self: *Self, state: *BrainState) !void {
- _ = self;
-
- switch (state.version) {
- 1 => {
- // v1 -> v2 migration (placeholder for future)
- state.version = 2;
- },
- else => {
- std.log.err("Cannot migrate from version {d}", .{state.version});
- return MigrationError.MigrationFailed;
- },
- }
- }
-
- /// Create backup of current state file
- fn createBackup(self: *Self) !void {
- // Check if state file exists
- if (fs.cwd().openFile(self.state_file_path, .{})) |file| {
- file.close();
-
- // Create backup filename with timestamp
- const now = std.time.timestamp();
- const backup_name = try std.fmt.allocPrint(self.allocator, "brain_state_{d}.json", .{now});
- defer self.allocator.free(backup_name);
-
- const backup_path = try fs.path.join(self.allocator, &.{ self.backup_dir, backup_name });
- defer self.allocator.free(backup_path);
-
- // Copy file to backup
- {
- const src = try fs.cwd().openFile(self.state_file_path, .{});
- defer src.close();
-
- const dst = try fs.cwd().createFile(backup_path, .{});
- defer dst.close();
-
- const content = try src.readToEndAlloc(self.allocator, 10 * 1024 * 1024);
- defer self.allocator.free(content);
-
- try dst.writeAll(content);
- }
-
- // Clean up old backups (keep last 10)
- try self.pruneBackups(10);
-
- std.log.info("Created backup: {s}", .{backup_path});
- } else |_| {
- // No existing state file, no backup needed
- }
- }
-
- /// Prune old backups, keeping only the most recent N
- fn pruneBackups(self: *Self, keep: usize) !void {
- var backups = std.ArrayList(struct {
- name: []const u8,
- timestamp: i64,
- }).initCapacity(self.allocator, 32) catch |err| {
- std.log.err("Failed to allocate backups: {}", .{err});
- return err;
- };
-
- defer {
- for (backups.items) |b| self.allocator.free(b.name);
- backups.deinit(self.allocator);
- }
-
- // List backup files
- var dir = try fs.cwd().openDir(self.backup_dir, .{ .iterate = true });
- defer dir.close();
-
- var iter = dir.iterate();
- while (try iter.next()) |entry| {
- if (entry.kind == .file) {
- // Parse timestamp from filename: brain_state_.json
- if (mem.startsWith(u8, entry.name, "brain_state_") and mem.endsWith(u8, entry.name, ".json")) {
- const ts_str = entry.name["brain_state_".len .. entry.name.len - ".json".len];
- const timestamp = std.fmt.parseInt(i64, ts_str, 10) catch continue;
-
- const name_copy = try self.allocator.dupe(u8, entry.name);
- try backups.append(self.allocator, .{ .name = name_copy, .timestamp = timestamp });
- }
- }
- }
-
- // Sort by timestamp (newest first)
- std.sort.pdq(backups.items, {}, struct {
- fn lessThan(_: void, a: @TypeOf(backups.items[0]), b: @TypeOf(backups.items[0])) bool {
- return a.timestamp > b.timestamp;
- }
- }.lessThan);
-
- // Delete old backups
- if (backups.items.len > keep) {
- for (backups.items[keep..]) |old_backup| {
- const path = try fs.path.join(self.allocator, &.{ self.backup_dir, old_backup.name });
- defer self.allocator.free(path);
-
- fs.cwd().deleteFile(path) catch |err| {
- std.log.warn("Failed to delete old backup {s}: {}", .{ path, err });
- };
- }
- }
- }
-
- /// Restore state to live brain components
- pub fn restore(self: *Self, state: BrainState, registry: *basal_ganglia.Registry, _event_bus: *reticular_formation.EventBus) !void {
- _ = _event_bus;
-
- // Restore task claims
- for (state.task_claims) |claim_state| {
- const status = if (mem.eql(u8, claim_state.status, "active"))
- basal_ganglia.TaskClaim.Status.active
- else if (mem.eql(u8, claim_state.status, "completed"))
- basal_ganglia.TaskClaim.Status.completed
- else if (mem.eql(u8, claim_state.status, "abandoned"))
- basal_ganglia.TaskClaim.Status.abandoned
- else
- return error.InvalidStatus;
-
- // Skip completed/abandoned claims, only restore active ones
- if (status != .active) continue;
-
- // Check if claim is still valid (not expired)
- const now_ms = std.time.timestamp() * 1000;
- const age_ms = @as(u64, @intCast(now_ms - claim_state.claimed_at));
-
- if (age_ms < claim_state.ttl_ms) {
- // Restore the claim
- const new_claim = basal_ganglia.TaskClaim{
- .task_id = try self.allocator.dupe(u8, claim_state.task_id),
- .agent_id = try self.allocator.dupe(u8, claim_state.agent_id),
- .claimed_at = claim_state.claimed_at,
- .ttl_ms = claim_state.ttl_ms,
- .status = .active,
- .completed_at = null,
- .last_heartbeat = claim_state.last_heartbeat,
- };
-
- registry.mutex.lock();
- try registry.claims.put(
- try self.allocator.dupe(u8, claim_state.task_id),
- new_claim,
- );
- registry.mutex.unlock();
- }
- }
-
- // Note: We don't restore events to the event bus as it's a circular buffer
- // The events are preserved in the state file for debugging/analysis
-
- std.log.info("Restored {d} active task claims", .{state.task_claims.len});
- }
-
- /// Check if state file exists and is valid
- pub fn hasValidState(self: *Self) bool {
- if (fs.cwd().openFile(self.state_file_path, .{})) |file| {
- file.close();
- return true;
- } else |_| {
- return false;
- }
- }
-
- /// Get state file info
- pub const StateInfo = struct {
- exists: bool,
- path: []const u8,
- size_bytes: ?usize,
- modified_at: ?i64,
- backup_count: usize,
- };
-
- pub fn getStateInfo(self: *Self) !StateInfo {
- const stat = fs.cwd().statFile(self.state_file_path) catch |err| {
- if (err == error.FileNotFound) {
- return StateInfo{
- .exists = false,
- .path = self.state_file_path,
- .size_bytes = null,
- .modified_at = null,
- .backup_count = 0,
- };
- }
- return err;
- };
-
- // Count backups
- var backup_count: usize = 0;
- var dir = try fs.cwd().openDir(self.backup_dir, .{ .iterate = true });
- defer dir.close();
-
- var iter = dir.iterate();
- while (try iter.next()) |entry| {
- if (entry.kind == .file and mem.startsWith(u8, entry.name, "brain_state_")) {
- backup_count += 1;
- }
- }
-
- return StateInfo{
- .exists = true,
- .path = self.state_file_path,
- .size_bytes = @intCast(stat.size),
- .modified_at = stat.mtime,
- .backup_count = backup_count,
- };
- }
-
- /// Delete state file (for cleanup or reset)
- pub fn deleteState(self: *Self) !void {
- fs.cwd().deleteFile(self.state_file_path) catch |err| {
- if (err == error.FileNotFound) {
- return; // Already deleted
- }
- return err;
- };
- std.log.info("Deleted brain state file: {s}", .{self.state_file_path});
- }
-
- /// Wipe all state including backups (use with caution!)
- pub fn wipeAll(self: *Self) !void {
- // Delete state file
- self.deleteState() catch {};
-
- // Delete backup directory
- var dir = try fs.cwd().openDir(self.backup_dir, .{ .iterate = true });
- defer dir.close();
-
- var iter = dir.iterate();
- while (try iter.next()) |entry| {
- if (entry.kind == .file) {
- const path = try fs.path.join(self.allocator, &.{ self.backup_dir, entry.name });
- defer self.allocator.free(path);
- fs.cwd().deleteFile(path) catch |err| {
- std.log.warn("Failed to delete {s}: {}", .{ path, err });
- };
- }
- }
-
- std.log.warn("Wiped all brain state data", .{});
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// AUTO-RECOVERY HELPER
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Attempt automatic recovery on startup
-/// Returns true if recovery was successful, false if no state to recover
-pub fn autoRecover(allocator: mem.Allocator, registry: *basal_ganglia.Registry, event_bus: *reticular_formation.EventBus) !bool {
- var manager = try StateManager.init(allocator);
- defer manager.deinit();
-
- if (!manager.hasValidState()) {
- std.log.info("No valid brain state found, starting fresh", .{});
- return false;
- }
-
- std.log.info("Found brain state, attempting recovery...", .{});
-
- const state = try manager.load();
- defer {
- // Free state resources
- for (state.task_claims) |claim| {
- allocator.free(claim.task_id);
- allocator.free(claim.agent_id);
- allocator.free(claim.status);
- }
- allocator.free(state.task_claims);
-
- for (state.events) |ev| {
- allocator.free(ev.event_type);
- allocator.free(ev.task_id);
- allocator.free(ev.agent_id);
- allocator.free(ev.aux_string);
- }
- allocator.free(state.events);
-
- for (state.metrics) |m| {
- allocator.free(m.name);
- for (m.tags) |tag| {
- allocator.free(tag);
- }
- allocator.free(m.tags);
- }
- allocator.free(state.metrics);
- }
-
- try manager.restore(state, registry, event_bus);
-
- std.debug.print("Brain recovery complete\n", .{});
- return true;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CLI COMMAND HANDLERS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Run brain state recovery command
-/// Usage: tri brain --save|--load|--status|--wipe
-pub fn runBrainRecoveryCommand(allocator: mem.Allocator, args: []const []const u8) !void {
- var manager = try StateManager.init(allocator);
- defer manager.deinit();
-
- if (args.len == 0) {
- try printBrainRecoveryHelp();
- return;
- }
-
- const cmd = args[0];
-
- if (mem.eql(u8, cmd, "--save") or mem.eql(u8, cmd, "-s")) {
- // Save current brain state
- const registry = try basal_ganglia.getGlobal(allocator);
- const event_bus = try reticular_formation.getGlobal(allocator);
-
- try manager.save(registry, event_bus);
- std.debug.print("Brain state saved successfully.\n", .{});
- } else if (mem.eql(u8, cmd, "--load") or mem.eql(u8, cmd, "-l")) {
- // Load and display brain state
- if (manager.hasValidState()) {
- const state = try manager.load();
- defer {
- for (state.task_claims) |claim| {
- allocator.free(claim.task_id);
- allocator.free(claim.agent_id);
- allocator.free(claim.status);
- }
- allocator.free(state.task_claims);
-
- for (state.events) |ev| {
- allocator.free(ev.event_type);
- allocator.free(ev.task_id);
- allocator.free(ev.agent_id);
- allocator.free(ev.aux_string);
- }
- allocator.free(state.events);
-
- for (state.metrics) |m| {
- allocator.free(m.name);
- for (m.tags) |tag| {
- allocator.free(tag);
- }
- allocator.free(m.tags);
- }
- allocator.free(state.metrics);
- }
-
- std.debug.print("Brain State (version {d}):\n", .{state.version});
- std.debug.print(" Saved at: {d}\n", .{state.saved_at});
- std.debug.print(" Task claims: {d}\n", .{state.task_claims.len});
- std.debug.print(" Events: {d}\n", .{state.events.len});
- std.debug.print(" Metrics: {d}\n", .{state.metrics.len});
- std.debug.print(" Hostname: {s}\n", .{state.metadata.hostname});
- std.debug.print(" PID: {d}\n", .{state.metadata.pid});
- } else {
- std.debug.print("No valid brain state found.\n", .{});
- }
- } else if (mem.eql(u8, cmd, "--status")) {
- // Show state file info
- const info = try manager.getStateInfo();
-
- std.debug.print("Brain State Status:\n", .{});
- std.debug.print(" Path: {s}\n", .{info.path});
- std.debug.print(" Exists: {s}\n", .{if (info.exists) "Yes" else "No"});
-
- if (info.exists) {
- std.debug.print(" Size: {d} bytes\n", .{info.size_bytes orelse 0});
-
- if (info.modified_at) |mtime| {
- const modified = std.time.timestamp();
- const age_sec = modified - mtime;
- std.debug.print(" Modified: {d} seconds ago\n", .{age_sec});
- }
- }
-
- std.debug.print(" Backups: {d}\n", .{info.backup_count});
- } else if (mem.eql(u8, cmd, "--wipe")) {
- // Wipe all state (requires confirmation)
- if (args.len > 1 and mem.eql(u8, args[1], "--force")) {
- try manager.wipeAll();
- std.debug.print("All brain state data wiped.\n", .{});
- } else {
- std.debug.print("This will delete all brain state data and backups!\n", .{});
- std.debug.print("Use --force to confirm: tri brain --wipe --force\n", .{});
- }
- } else if (mem.eql(u8, cmd, "--help") or mem.eql(u8, cmd, "-h")) {
- try printBrainRecoveryHelp();
- } else {
- std.debug.print("Unknown command: {s}\n", .{cmd});
- try printBrainRecoveryHelp();
- }
-}
-
-fn printBrainRecoveryHelp() !void {
- std.debug.print("\n{s}BRAIN STATE RECOVERY{s}\n\n", .{ "\x1b[33m", "\x1b[0m" });
- std.debug.print("{s}Usage:{s}\n", .{ "\x1b[36m", "\x1b[0m" });
- std.debug.print(" tri brain --save Save current brain state to disk\n", .{});
- std.debug.print(" tri brain --load Load and display brain state\n", .{});
- std.debug.print(" tri brain --status Show state file information\n", .{});
- std.debug.print(" tri brain --wipe Delete all state data (requires --force)\n", .{});
- std.debug.print("\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "StateManager init" {
- const allocator = std.testing.allocator;
-
- // Use temporary directory for testing
- const tmp_dir = "test_brain_state_tmp";
- try fs.cwd().makePath(tmp_dir);
- defer fs.cwd().deleteTree(tmp_dir) catch {};
-
- const manager = try StateManager.init(allocator);
- _ = manager;
-}
-
-test "StateManager save and load cycle" {
- const allocator = std.testing.allocator;
-
- // Create temporary state directory
- const tmp_dir = ".trinity/brain/state";
- try fs.cwd().makePath(tmp_dir);
-
- var manager = try StateManager.init(allocator);
- defer manager.deinit();
-
- // Create test registry and event bus
- var registry = basal_ganglia.Registry.init(allocator);
- defer registry.deinit();
-
- var event_bus = reticular_formation.EventBus.init(allocator);
- defer event_bus.deinit();
-
- // Add a test claim
- _ = try registry.claim(allocator, "test-task-1", "agent-001", 60000);
-
- // Save state
- try manager.save(®istry, &event_bus);
-
- // Load state
- const state = try manager.load();
-
- try std.testing.expectEqual(@as(usize, 1), state.task_claims.len);
- try std.testing.expectEqual(CURRENT_VERSION, state.version);
-
- // Cleanup
- {
- for (state.task_claims) |claim| {
- allocator.free(claim.task_id);
- allocator.free(claim.agent_id);
- allocator.free(claim.status);
- }
- allocator.free(state.task_claims);
-
- for (state.events) |ev| {
- allocator.free(ev.event_type);
- allocator.free(ev.task_id);
- allocator.free(ev.agent_id);
- allocator.free(ev.aux_string);
- }
- allocator.free(state.events);
-
- for (state.metrics) |m| {
- allocator.free(m.name);
- for (m.tags) |tag| {
- allocator.free(tag);
- }
- allocator.free(m.tags);
- }
- allocator.free(state.metrics);
- }
-
- // Clean up test state file
- manager.deleteState() catch {};
-}
-
-test "StateManager restore recovers task claims" {
- const allocator = std.testing.allocator;
-
- // Setup
- const tmp_dir = ".trinity/brain/state";
- try fs.cwd().makePath(tmp_dir);
-
- var manager = try StateManager.init(allocator);
- defer manager.deinit();
-
- // Create original registry with claims
- var original_registry = basal_ganglia.Registry.init(allocator);
- defer original_registry.deinit();
-
- var event_bus = reticular_formation.EventBus.init(allocator);
- defer event_bus.deinit();
-
- // Add test claims
- _ = try original_registry.claim(allocator, "task-1", "agent-001", 60000);
- _ = try original_registry.claim(allocator, "task-2", "agent-002", 60000);
-
- // Save state
- try manager.save(&original_registry, &event_bus);
-
- // Create new registry and restore
- var new_registry = basal_ganglia.Registry.init(allocator);
- defer new_registry.deinit();
-
- const state = try manager.load();
- defer {
- for (state.task_claims) |claim| {
- allocator.free(claim.task_id);
- allocator.free(claim.agent_id);
- allocator.free(claim.status);
- }
- allocator.free(state.task_claims);
-
- for (state.events) |ev| {
- allocator.free(ev.event_type);
- allocator.free(ev.task_id);
- allocator.free(ev.agent_id);
- allocator.free(ev.aux_string);
- }
- allocator.free(state.events);
-
- for (state.metrics) |m| {
- allocator.free(m.name);
- for (m.tags) |tag| {
- allocator.free(tag);
- }
- allocator.free(m.tags);
- }
- allocator.free(state.metrics);
- }
-
- try manager.restore(state, &new_registry, &event_bus);
-
- // Verify claims were restored
- try std.testing.expectEqual(@as(usize, 2), new_registry.claims.count());
-
- // Clean up
- manager.deleteState() catch {};
-}
-
-test "StateManager handles corrupted state file" {
- const allocator = std.testing.allocator;
-
- const tmp_dir = ".trinity/brain/state";
- try fs.cwd().makePath(tmp_dir);
-
- var manager = try StateManager.init(allocator);
- defer manager.deinit();
-
- // Write corrupted data to state file
- {
- const file = try fs.cwd().createFile(manager.state_file_path, .{ .read = true });
- defer file.close();
- try file.writeAll("corrupted json {{}}");
- }
-
- // Load should return error
- const result = manager.load();
- try std.testing.expectError(error.CorruptedData, result);
-
- // Clean up
- manager.deleteState() catch {};
-}
-
-test "StateManager getStateInfo" {
- const allocator = std.testing.allocator;
-
- const tmp_dir = ".trinity/brain/state";
- try fs.cwd().makePath(tmp_dir);
-
- var manager = try StateManager.init(allocator);
- defer manager.deinit();
-
- // Test with no state file
- const info_no_state = try manager.getStateInfo();
- try std.testing.expect(!info_no_state.exists);
-
- // Create state file
- var registry = basal_ganglia.Registry.init(allocator);
- defer registry.deinit();
-
- var event_bus = reticular_formation.EventBus.init(allocator);
- defer event_bus.deinit();
-
- try manager.save(®istry, &event_bus);
-
- // Test with state file
- const info_with_state = try manager.getStateInfo();
- try std.testing.expect(info_with_state.exists);
- try std.testing.expect(info_with_state.size_bytes != null);
- try std.testing.expect(info_with_state.modified_at != null);
-
- // Clean up
- manager.deleteState() catch {};
-}
diff --git a/src/cifar10_loader.zig b/src/cifar10_loader.zig
deleted file mode 100644
index 2f00a2506a..0000000000
--- a/src/cifar10_loader.zig
+++ /dev/null
@@ -1,250 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CIFAR-10 Binary Dataset Loader
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// CIFAR-10 binary format:
-// - 5 training batches: data_batch_1.bin ... data_batch_5.bin
-// - 1 test batch: test_batch.bin
-//
-// Each batch file contains 10,000 records:
-// [1 byte label][3072 bytes pixels (1024 R + 1024 G + 1024 B)]
-//
-// Pixel layout: channel-first (all R, then all G, then all B)
-// Total per record: 3073 bytes
-// Total per batch: 30,730,000 bytes (10,000 Γ 3073)
-//
-// Usage:
-// var loader = CIFAR10Loader.init(allocator);
-// defer loader.deinit();
-// const train = try loader.loadTrain(allocator, "/path/to/cifar-10-binary");
-// const test = try loader.loadTest(allocator, "/path/to/cifar-10-binary");
-//
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const ArrayList = std.ArrayList;
-const ArrayListUnmanaged = std.ArrayListUnmanaged;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CIFAR-10 Sample
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const Sample = struct {
- label: u8, // 0-9 class label
- pixels: [3072]f32, // 32Γ32Γ3 = 3072 pixels, normalized to [0, 1]
-
- /// Flatten pixels to 1D vector (already flat, just returns reference)
- pub fn flatten(self: *const Sample) []const f32 {
- return &self.pixels;
- }
-
- /// Get image dimensions
- pub fn size() struct { width: u32, height: u32, channels: u32 } {
- return .{ .width = 32, .height = 32, .channels = 3 };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CIFAR-10 Dataset
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const Dataset = struct {
- samples: ArrayListUnmanaged(Sample),
-
- /// Get total number of samples
- pub fn len(self: *const Dataset) usize {
- return self.samples.items.len;
- }
-
- /// Get sample by index
- pub fn get(self: *const Dataset, index: usize) *const Sample {
- std.debug.assert(index < self.samples.items.len);
- return &self.samples.items[index];
- }
-
- /// Get label distribution
- pub fn labelDistribution(self: *const Dataset, allocator: Allocator) ![]const usize {
- const dist = try allocator.alloc(usize, 10);
- @memset(dist, 0);
- for (self.samples.items) |sample| {
- dist[sample.label] += 1;
- }
- return dist;
- }
-
- /// Deinitialize dataset
- pub fn deinit(self: *Dataset, allocator: Allocator) void {
- self.samples.deinit(allocator);
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CIFAR-10 Loader
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const CIFAR10Loader = struct {
- const RECORD_SIZE: usize = 3073; // 1 label byte + 3072 pixel bytes
- const BATCH_SIZE: usize = 10_000;
- const BATCH_BYTES: usize = BATCH_SIZE * RECORD_SIZE; // 30,730,000 bytes
-
- /// Initialize loader
- pub fn init() CIFAR10Loader {
- return .{};
- }
-
- /// Load a single batch file
- pub fn loadBatch(
- _: CIFAR10Loader,
- allocator: Allocator,
- batch_path: []const u8,
- ) !Dataset {
- const file = try std.fs.cwd().openFile(batch_path, .{});
- defer file.close();
-
- const file_size = try file.getEndPos();
- if (file_size != BATCH_BYTES) {
- std.debug.print("Warning: Expected {d} bytes, got {d}\n", .{ BATCH_BYTES, file_size });
- }
-
- const expected_records = file_size / RECORD_SIZE;
- var dataset = Dataset{
- .samples = ArrayListUnmanaged(Sample){},
- };
- errdefer dataset.deinit(allocator);
-
- try dataset.samples.ensureTotalCapacity(allocator, expected_records);
-
- const buffer = try allocator.alloc(u8, file_size);
- defer allocator.free(buffer);
-
- _ = try file.readAll(buffer);
-
- var offset: usize = 0;
- while (offset + RECORD_SIZE <= file_size) {
- const label = buffer[offset];
- offset += 1;
-
- var sample = Sample{
- .label = label,
- .pixels = undefined,
- };
-
- // Pixels are stored channel-first: RRR...GGG...BBB...
- // Each channel has 1024 bytes (32Γ32)
- // Normalize to [0, 1] by dividing by 255.0
- var pixel_idx: usize = 0;
- while (pixel_idx < 3072) : (pixel_idx += 1) {
- const raw = buffer[offset + pixel_idx];
- sample.pixels[pixel_idx] = @as(f32, @floatFromInt(raw)) / 255.0;
- }
-
- offset += 3072;
- try dataset.samples.append(allocator, sample);
- }
-
- return dataset;
- }
-
- /// Load training dataset (all 5 batches merged)
- pub fn loadTrain(
- self: CIFAR10Loader,
- allocator: Allocator,
- data_dir: []const u8,
- ) !Dataset {
- const batch_files = [_][]const u8{
- "data_batch_1.bin",
- "data_batch_2.bin",
- "data_batch_3.bin",
- "data_batch_4.bin",
- "data_batch_5.bin",
- };
-
- var merged = Dataset{
- .samples = ArrayListUnmanaged(Sample){},
- };
- errdefer merged.deinit(allocator);
-
- // Pre-allocate for 50,000 samples
- try merged.samples.ensureTotalCapacity(allocator, 50_000);
-
- for (batch_files) |batch_name| {
- var batch_path_buf: [1024]u8 = undefined;
- const batch_path = try std.fmt.bufPrint(
- &batch_path_buf,
- "{s}" ++ std.fs.path.sep_str ++ "{s}",
- .{ data_dir, batch_name },
- );
-
- var batch = try self.loadBatch(allocator, batch_path);
- defer batch.deinit(allocator);
-
- // Merge samples
- for (batch.samples.items) |sample| {
- try merged.samples.append(allocator, sample);
- }
-
- std.debug.print("Loaded {s}: {d} samples (total: {d})\n", .{
- batch_name,
- batch.samples.items.len,
- merged.samples.items.len,
- });
- }
-
- return merged;
- }
-
- /// Load test dataset
- pub fn loadTest(
- self: CIFAR10Loader,
- allocator: Allocator,
- data_dir: []const u8,
- ) !Dataset {
- var test_path_buf: [1024]u8 = undefined;
- const test_path = try std.fmt.bufPrint(
- &test_path_buf,
- "{s}" ++ std.fs.path.sep_str ++ "test_batch.bin",
- .{data_dir},
- );
-
- return self.loadBatch(allocator, test_path);
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Tests
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const testing = std.testing;
-
-test "CIFAR-10: Sample structure size" {
- try testing.expectEqual(@as(usize, 3073), @sizeOf(Sample));
-}
-
-test "CIFAR-10: Image dimensions" {
- const dims = Sample.size();
- try testing.expectEqual(@as(u32, 32), dims.width);
- try testing.expectEqual(@as(u32, 32), dims.height);
- try testing.expectEqual(@as(u32, 3), dims.channels);
-}
-
-test "CIFAR-10: Record size constant" {
- try testing.expectEqual(@as(usize, 3073), CIFAR10Loader.RECORD_SIZE);
- try testing.expectEqual(@as(usize, 10_000), CIFAR10Loader.BATCH_SIZE);
- try testing.expectEqual(@as(usize, 30_730_000), CIFAR10Loader.BATCH_BYTES);
-}
-
-test "CIFAR-10: Normalization range" {
- const zero_raw: u8 = 0;
- const zero_norm = @as(f32, @floatFromInt(zero_raw)) / 255.0;
- try testing.expectEqual(@as(f32, 0.0), zero_norm);
-
- const max_raw: u8 = 255;
- const max_norm = @as(f32, @floatFromInt(max_raw)) / 255.0;
- try testing.expectEqual(@as(f32, 1.0), max_norm);
-
- const mid_raw: u8 = 128;
- const mid_norm = @as(f32, @floatFromInt(mid_raw)) / 255.0;
- try testing.expectApproxEqAbs(@as(f32, 0.502), mid_norm, 0.001);
-}
diff --git a/src/cli/find_island.zig b/src/cli/find_island.zig
new file mode 100644
index 0000000000..ea71b98113
--- /dev/null
+++ b/src/cli/find_island.zig
@@ -0,0 +1,703 @@
+// TRI CLI β Cryptic Finding Island
+// ΟΒ² + 1/ΟΒ² = 3 = TRINITY
+// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+const std = @import("std");
+const print = std.debug.print;
+
+// ANSI Colors
+const RED = "\x1b[31m";
+const GREEN = "\x1b[32m";
+const YELLOW = "\x1b[33m";
+const CYAN = "\x1b[36m";
+const MAGENTA = "\x1b[35m";
+const RESET = "\x1b[0m";
+
+// Storage paths
+const ISLANDS_FILE = ".trinity/data/islands.json";
+const DISCOVERIES_FILE = ".trinity/data/discoveries.json";
+const CLUES_FILE = ".trinity/data/clues.json";
+
+pub const CommandError = error{
+ InvalidQuery,
+ IslandNotFound,
+ InvalidAnswer,
+ TooManyHintRequests,
+ InvalidHintLevel,
+};
+
+// Types
+pub const Island = struct {
+ id: []const u8,
+ name: []const u8,
+ domain: []const u8,
+ riddle: []const u8,
+ answer: []const u8,
+ knowledge: []const u8,
+ difficulty: u8,
+ discovered: bool,
+ discovery_date: ?[]const u8,
+ clues_count: u8,
+ sacred_formula: ?[]const u8,
+};
+
+pub const Clue = struct {
+ id: []const u8,
+ island_id: []const u8,
+ hint: []const u8,
+ hint_level: u8, // 1=subtle, 2=clear, 3=strong
+};
+
+pub const Discovery = struct {
+ island_id: []const u8,
+ attempts: u8,
+ hints_used: u8,
+ clues_found: [][]const u8,
+ solved: bool,
+};
+
+pub const IslandFilter = struct {
+ query: ?[]const u8,
+ domain: ?[]const u8,
+ show_discovered: bool,
+ show_undiscovered: bool,
+ min_difficulty: ?u8,
+ max_difficulty: ?u8,
+};
+
+// Predefined Islands
+const PREDEFINED_ISLANDS = [_]Island{
+ .{
+ .id = "island_phi_wisdom",
+ .name = "Phi Wisdom Island",
+ .domain = "sacred_formula",
+ .riddle = "What ratio equals phi squared plus 1 over phi squared?",
+ .answer = "phi^2 + 1/phi^2",
+ .knowledge = "The golden ratio ΟΒ² + 1/ΟΒ² = 3. This sacred relationship governs the emergence of consciousness from mathematical perfection into biological manifestation. Ο β 1.61803398875.",
+ .difficulty = 4,
+ .clues_count = 3,
+ .sacred_formula = "ΟΒ² + 1/ΟΒ²",
+ },
+ .{
+ .id = "island_vsa_horizon",
+ .name = "Vector Horizon Island",
+ .domain = "vsa",
+ .riddle = "I bind vectors, you bundle them, then what remains unbound?",
+ .answer = "Zero - the essence of the void, preserved through the operation.",
+ .knowledge = "VSA bind/unbind operations: \nbind(v1, v2) β Creates a new vector association\nbundle(v1, v2, v3) β Creates a composite vector from 3 source vectors\nunbundle(v) β Frees a vector (no longer bound to anything)\n\nSimilarity: dot(v1, v2) β Cosine angle (how aligned two vectors are)\n\nAll VSA operations are associative and preserve the Trinity: combining two concepts never destroys information.",
+ .difficulty = 3,
+ .clues_count = 2,
+ .sacred_formula = "VSA_TRINITY",
+ },
+ .{
+ .id = "island_ternary_trinity",
+ .name = "Ternary Trinity Island",
+ .domain = "tri",
+ .riddle = "In the sacred trinity of values {-1, 0, +1}, what is the perfect balance?",
+ .answer = "Zero - perfect equilibrium between negative and positive, the origin point of all transformation.",
+ .knowledge = "The sacred trinity principle: the Trinity of -1, 0, +1 represents perfect balance. All operations must preserve this sacred invariant. \nβ’ Ternary negation: Β¬(-x) = x \nβ’ Ternary multiplication: (-x) * (-y) = x \nβ’ Ternary addition: (-x) + (-y) = z \nβ’ Ternary shift: rotate(x) β cyclic shift preserving trit values.",
+ .difficulty = 5,
+ .clues_count = 2,
+ .sacred_formula = "SACRED_TRINITY",
+ },
+ .{
+ .id = "island_blind_spot_realm",
+ .name = "Blind Spot Realm",
+ .domain = "blind_spots",
+ .riddle = "I see everything, yet I perceive nothing. What am I missing?",
+ .answer = "Knowledge Gaps β The blind spots are the dark matter of understanding. 90+ new formulas across 8 domains. The sacred prediction confidence is 0.42. What do we truly know?",
+ .knowledge = "Blind spots are gaps between VERIFIED, PREDICTED, and BLIND knowledge. Each represents an opportunity for discovery. High-sacred-weight predictions from KOSCHEI EYE v2.0 suggest new physics beyond the Standard Model: \nβ’ Neutrino absolute mass scale: KATRIN 2025 < 0.45 eV, we predict 0.0057 eV (79x improvement) \nβ’ Proton decay lifetime: Super-K limit 1.67e34 years, we predict 2.82e34 years (confirmed vs Super-K 1.67e34) \nβ’ Dark Matter Particle Mass: CDG-2 ghost galaxy (Feb 2026) 99% DM, we predict 817 GeV (WIMP) \nβ’ Hubble Tension Resolution: Early vs late universe disagreement (5Ο) β Sacred Formula suggests specific value",
+ .difficulty = 4,
+ .clues_count = 3,
+ .sacred_formula = "BLIND_SPOTS_V2",
+ },
+ .{
+ .id = "island_sacred_constants",
+ .name = "Sacred Constants Archive",
+ .domain = "sacred_constants",
+ .riddle = "The constants Ο, Ο, and e are sacred. But what patterns connect them?",
+ .answer = "The Golden Chain: \nΟΒ² + 1/ΟΒ² = 3 \nβ Ο = β(3)/2 β 0.866 \nβ Ο = 4β(3)/2 β 3.1416 \nβ e = 2.718 \nβ The Golden Chain: 1/Ο + 1/ΟΒ² = 3, 1/Ο, Ο, Ο, and e form a recursive proportion system where each ratio generates the next. \nAnswer: The Golden Chain connects all sacred constants through proportion.",
+ .knowledge = "Golden Chain Mathematics:\nβ’ Ο β 1.618 (Golden Ratio)\nβ’ Ο β 3.142\nβ’ e β 2.718\nβ’ Recursive formula: 1/Ο + 1/ΟΒ² = 3",
+ .difficulty = 3,
+ .clues_count = 2,
+ .sacred_formula = "GOLDEN_CHAIN",
+ },
+ .{
+ .id = "island_agent_mu",
+ .name = "Mu Agent Archives",
+ .domain = "agent_mu",
+ .riddle = "The Mu agent learns from experience. What algorithm did it converge on?",
+ .answer = "Hyperparameter Search β The Mu agent explores hyperparameter space using Bayesian optimization. It converged on: learning_rate=0.01 with momentum=0.9. Answer: The optimal learning rate that maximizes performance while maintaining stability.",
+ .knowledge = "Mu Agent Algorithms:\nβ’ Learning Rate: 0.01\nβ’ Momentum: 0.9\nβ’ Best model: Mu-7B-Llama2-7B (7B parameters, L layers)",
+ .difficulty = 4,
+ .clues_count = 2,
+ .sacred_formula = "MU_AGENT",
+ },
+ .{
+ .id = "island_quantum_criticality",
+ .name = "Quantum Criticality Island",
+ .domain = "quantum",
+ .riddle = "In quantum mechanics, critical exponents describe decay rates. What is the criticality of the universe?",
+ .answer = "KOSCHEI Exponent β The KOSCHEI criticality exponent ΞΊ describes how the universe expands: d/dt β (t/tβ)α΅. Currently measured as ΞΊ β 1.67 (universe expanding). Answer: ΞΊ = 1.67 represents the universe expanding at 67% of the speed of light since the Big Bang.",
+ .knowledge = "Quantum Criticality: \nβ’ KOSCHEI Exponent: ΞΊ β 1.67 (universe expanding)\nβ’ Cosmic Microwave Background: 2.725 K (relic)\nβ’ Current Cosmology: ΞCDM (0.3)\nβ’ Criticality Parameter: ΩΠ= 8ΟGβ(ΟcΒ³/8GHβ/cΒ²) β 1.6 (dark energy density)",
+ .difficulty = 5,
+ .clues_count = 2,
+ .sacred_formula = "KOSCHEI_V2",
+ },
+};
+
+// Load islands from storage
+fn loadIslands(allocator: std.mem.Allocator) !std.ArrayList(Island) {
+ const islands_file = std.fs.openFileAbsolute(allocator, ISLANDS_FILE, .{}) catch |err| return error.FileNotFound;
+ defer islands_file.close();
+
+ const content = try islands_file.readToEndAlloc(allocator, allocator) catch |err| {
+ allocator.free(content);
+ return err;
+ };
+
+ var islands = std.ArrayList(Island).init(allocator);
+ var line_iter = std.mem.splitScalar(u8, content, '\n');
+ while (line_iter.next()) |line_opt| {
+ if (line_opt.value == null or line_opt.value.len == 0) continue;
+
+ if (std.mem.startsWith(u8, line_opt.value, "#")) continue;
+
+ var field_iter = std.mem.splitScalar(u8, line_opt.value, ':');
+ var island: ?Island = null;
+
+ while (field_iter.next()) |field_opt| {
+ const trimmed = std.mem.trim(u8, field_opt.value);
+ if (trimmed.len == 0) continue;
+
+ // Skip checking predefined islands in this version
+ island = predefined;
+ break;
+ }
+ }
+ }
+
+ if (island != null) {
+ island = island.?;
+ }
+ }
+
+ return islands;
+}
+
+// Save discovery progress
+fn saveDiscovery(allocator: std.mem.Allocator, island_id: []const u8, discovery: Discovery) !void {
+ const discoveries_file = std.fs.openFileAbsolute(allocator, DISCOVERIES_FILE, .{ .read = true, .write = true, .create_if_not_exists = true }) catch |err| {
+ defer discoveries_file.close();
+
+ var existing = try loadIslands(allocator, allocator);
+ defer existing.deinit();
+
+ // Find and update the island
+ for (existing.items, 0..) |*island| {
+ if (std.mem.eql(u8, island.id, island_id)) {
+ island.discovered = true;
+ island.discovery_date = try std.time.timestampAlloc(allocator);
+ }
+ }
+
+ // Format as JSON line
+ const json_line = try std.fmt.allocPrintZ(allocator,
+ \\{s}\\\"island_id\\\":\\\"{s}\\\",\\"attempts\\\":\\{d}\\\",\\"solved\\\":\\{s}\\\",\\"hints_used\\\":\\{d}\\\",\\"clues_found\\\":\\\"{any}\\\"\n\\",
+ .{ island.discovery_date, island.attempts, island.hints_used, island.solved, island.clues_found }
+ );
+
+ // Append to existing discoveries
+ const append = try std.fmt.allocPrintZ(allocator, ",\n{s}\\\"island_id\\\":\\\"{s}\\\",\\"attempts\\\":\\{d}\\\",\\"solved\\\":\\{s}\\\",\\"hints_used\\\":\\{d}\\\",\\"clues_found\\\":\\\"{any}\\\"\n");
+
+ _ = try discoveries_file.writeAll(allocator, append);
+ _ = try discoveries_file.writeAll(allocator, "\n");
+
+ print("{s}Discovery saved for island: {s}\\n", .{GREEN, island_id});
+ }
+}
+
+// Find islands matching filter
+fn findIslands(allocator: std.mem.Allocator, filter: IslandFilter) !std.ArrayList(Island) {
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ var matches = std.ArrayList(Island).init(allocator);
+
+ for (islands.items, 0..) |island| {
+ var include = true;
+
+ // Check discovered filter
+ if (filter.show_discovered) {
+ if (!island.discovered) {
+ include = false;
+ }
+ }
+
+ // Check undiscovered filter
+ if (filter.show_undiscovered) {
+ if (island.discovered) {
+ include = false;
+ }
+ }
+
+ // Check domain filter
+ if (filter.domain) |domain| {
+ if (!std.mem.eql(u8, island.domain, domain)) {
+ include = false;
+ }
+ }
+
+ // Check difficulty filter
+ if (filter.min_difficulty) |min| {
+ if (island.difficulty < min) {
+ include = false;
+ }
+ }
+
+ if (filter.max_difficulty) |max| {
+ if (island.difficulty > max) {
+ include = false;
+ }
+ }
+
+ // Check query match
+ if (filter.query) |query| {
+ const lower_query = try std.ascii.lowerStringAlloc(allocator, query);
+ defer allocator.free(lower_query);
+
+ if (!std.mem.indexOfScalar(u8, lower_query, try std.ascii.indexOfScalar(u8, island.name))) {
+ if (!std.mem.indexOfScalar(u8, lower_query, try std.ascii.indexOfScalar(u8, island.domain))) {
+ include = false;
+ }
+ }
+ }
+
+ if (include) {
+ try matches.append(allocator, island);
+ }
+ }
+
+ return matches;
+}
+
+// Get island by ID
+fn getIslandById(allocator: std.mem.Allocator, island_id: []const u8) ?Island {
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ for (islands.items, 0..) |island| {
+ if (std.mem.eql(u8, island.id, island_id)) {
+ return island;
+ }
+ }
+
+ return null;
+}
+
+// Format island summary
+fn formatIslandSummary(allocator: std.mem.Allocator, island: Island) ![]const u8 {
+ const difficulty_indicator = switch (island.difficulty) {
+ 1 => "{s}β{s}",
+ 2 => "{s}β{s}",
+ 3 => "{s}ββ{s}",
+ 4 => "{s}βββ{s}",
+ 5 => "{s}ββββ{s}",
+ _ => "{s}βββββ{s}",
+ else => "{s}β{s}",
+ };
+
+ const status = if (island.discovered)
+ "{s}{GREEN} Discovered{s}"
+ else
+ "{s}{CYAN} Undiscovered{s}";
+
+ const clue_status = if (island.clues_count > 0)
+ "{s}{MAGENTA} ({d} clues available{s})"
+ else
+ "{s}No clues";
+
+ return try std.fmt.allocPrintZ(allocator,
+ \\{s}\\n{name}: {s}\\n{domain}: {s}\\n{difficulty}: {s}\\n{status}: {s}\\n{clues}: {s}\\n\\n{s}\\n",
+ .{ island.name, island.domain, difficulty_indicator, status, clue_status }
+ );
+}
+
+// CLI Entry Point
+pub fn main() !void {
+ var gpa = std.heap.GeneralPurposeAllocator(.{}){};
+ defer _ = gpa.deinit();
+ const allocator = gpa.allocator();
+
+ const args = try std.process.argsAlloc(allocator);
+ defer std.process.argsFree(allocator, args);
+
+ if (args.len < 2) {
+ printUsage();
+ return;
+ }
+
+ // Handle both action + flags style and flag-only style
+ // tri find island --list => args.len == 2, action is "island", args[2] is "--list"
+ // tri find island --domain xxx => args.len >= 3, action is "island"
+
+ var action: ?[]const u8 = null;
+ var query: ?[]const u8 = null;
+ var domain: ?[]const u8 = null;
+ var list_mode: bool = false;
+ var show_clues: ?[]const u8 = null;
+ var solve_mode: bool = false;
+ var island_id_solve: ?[]const u8 = null;
+ var answer: ?[]const u8 = null;
+ var show_discovered: bool = false;
+ var show_undiscovered: bool = false;
+ var hint_mode: bool = false;
+ var island_id_hint: ?[]const u8 = null;
+ var hint_level: ?u8 = 1;
+
+ var arg_idx: usize = 1;
+
+ // Parse arguments
+ while (arg_idx < args.len) : (arg_idx += 1) {
+ const arg = args[arg_idx];
+
+ if (std.mem.startsWith(u8, arg, "--")) {
+ // It's a flag
+ if (std.mem.eql(u8, arg, "--list") or std.mem.eql(u8, arg, "-l")) {
+ list_mode = true;
+ } else if (std.mem.eql(u8, arg, "--discovered") or std.mem.eql(u8, arg, "-D")) {
+ show_discovered = true;
+ } else if (std.mem.eql(u8, arg, "--undiscovered") or std.mem.eql(u8, arg, "-U")) {
+ show_undiscovered = true;
+ } else if (std.mem.eql(u8, arg, "--clues")) {
+ if (arg_idx + 1 >= args.len) {
+ print("{s}Error: --clues requires island ID{s}\n", .{RED});
+ return;
+ }
+ show_clues = args[arg_idx + 1];
+ } else if (std.mem.eql(u8, arg, "--solve")) {
+ if (arg_idx + 2 >= args.len) {
+ print("{s}Error: --solve requires island ID and answer{s}\n", .{RED});
+ return;
+ }
+ island_id_solve = args[arg_idx + 1];
+ answer = args[arg_idx + 2];
+ solve_mode = true;
+ arg_idx += 2; // Skip answer param
+ } else if (std.mem.eql(u8, arg, "--hint")) {
+ if (arg_idx + 1 >= args.len) {
+ print("{s}Error: --hint requires island ID{s}\n", .{RED});
+ return;
+ }
+ island_id_hint = args[arg_idx + 1];
+ if (arg_idx + 2 >= args.len) {
+ hint_level = 1; // default
+ } else {
+ hint_level = std.fmt.parseInt(u8, args[arg_idx + 2], 10) catch 1;
+ }
+ hint_mode = true;
+ arg_idx += 2; // Skip hint level param
+ } else {
+ print("{s}Error: Unknown flag: {s}{s}\n", .{RED}, arg);
+ printUsage();
+ return;
+ }
+ } else {
+ // It's a positional argument (action or query)
+ if (action == null) {
+ if (query == null) {
+ query = arg;
+ }
+ } else if (std.mem.eql(u8, action, "island")) {
+ if (query == null) {
+ query = arg;
+ }
+ } else if (std.mem.eql(u8, action, "domain") or std.mem.eql(u8, action, "-d")) {
+ domain = arg;
+ }
+ }
+ }
+ }
+
+ // Execute based on mode
+ if (list_mode) {
+ // List all islands
+ } else if (show_clues != null) {
+ // Show clues for island
+ } else if (solve_mode) {
+ // Solve riddle
+ } else if (hint_mode) {
+ // Get hint
+ } else if (show_discovered) {
+ // Show discovered only
+ } else if (show_undiscovered) {
+ // Show undiscovered only
+ } else if (query != null) {
+ // Search islands
+ } else {
+ printUsage();
+ }
+ // List all islands
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ print("{s}ποΈ Cryptic Finding Islands{s}\n", .{MAGENTA});
+
+ if (islands.items.len == 0) {
+ print(" {s}No islands defined yet. Add islands to {s}.trinity/data/islands.json{s}\n", .{YELLOW, ISLANDS_FILE});
+ return;
+ }
+
+ // Sort by discovered status, then difficulty
+ std.sort.sort(Island, {}, islands.items, {}, struct {
+ less_than = struct {
+ field = "discovered",
+ asc = false,
+ },
+ less_than = struct {
+ field = "difficulty",
+ asc = true,
+ },
+ });
+
+ for (islands.items) |island| {
+ const summary = try formatIslandSummary(allocator, island);
+ defer allocator.free(summary);
+ print("{s}", .summary);
+ }
+
+ return;
+ }
+
+ if (std.mem.eql(u8, action, "--domain") or std.mem.eql(u8, action, "-d")) {
+ // Filter by domain
+ if (args.len < 3) {
+ printUsage();
+ return;
+ }
+
+ const domain = args[2];
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ var matches = std.ArrayList(Island).init(allocator);
+ for (islands.items, 0..) |island| {
+ if (std.mem.eql(u8, island.domain, domain)) {
+ try matches.append(allocator, island);
+ }
+ }
+
+ print("{s}ποΈ Islands in '{s}': {d} island(s){s}\n", .{CYAN}, matches.items.len);
+
+ for (matches.items) |island| {
+ const summary = try formatIslandSummary(allocator, island);
+ defer allocator.free(summary);
+ print("{s}", .summary);
+ }
+
+ return;
+ }
+
+ // Find island by query
+ if (args.len > 1 and args[1][0] != '-') {
+ const query = args[1];
+
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ // Create filter
+ var filter: IslandFilter = .{ .query = query };
+
+ var matches = try findIslands(allocator, filter);
+ defer islands.deinit();
+
+ if (matches.items.len == 0) {
+ print("{s}β No islands matching: '{s}'{s}\n", .{RED}, query);
+ return;
+ }
+
+ print("{s}ποΈ Found {d} matching island(s){s}\n", .{GREEN}, matches.items.len);
+
+ for (matches.items) |island| {
+ const summary = try formatIslandSummary(allocator, island);
+ defer allocator.free(summary);
+ print("{s}", .summary);
+ }
+
+ return;
+ }
+
+ // Show clues for an island
+ if ((std.mem.eql(u8, action, "--clues") or std.mem.eql(u8, action, "-c")) and args.len > 2) {
+ const island_id = args[2];
+
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ var island: ?Island = null;
+ for (islands.items, 0..) |island_ptr| {
+ if (std.mem.eql(u8, islands.items[island_ptr].id, island_id)) {
+ island = islands.items[island_ptr];
+ break;
+ }
+ }
+
+ if (island == null) {
+ print("{s}β Island not found: {s}\n", .{RED}, island_id);
+ return;
+ }
+
+ if (island.clues_count == 0) {
+ print("{s}No clues available for this island.\n", .{YELLOW});
+ return;
+ }
+
+ print("{s}π Clues for '{s}': {s}\\n", .{CYAN}, island.name);
+ print("{s}Clue count: {d}\\n", .{MAGENTA}, island.clues_count);
+ print();
+
+ for (island.clues_count, 0..) |i| {
+ print(" [{d}] {s}{s}", .{YELLOW}, i + 1);
+ print(" {s}{s}\\n", .{RESET});
+ }
+
+ return;
+ }
+
+ // Submit answer to solve riddle
+ if ((std.mem.eql(u8, action, "--solve") or std.mem.eql(u8, action, "-s")) and args.len > 2) {
+ const island_id = args[2];
+ const answer = args[3];
+
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ var island: ?Island = null;
+ for (islands.items, 0..) |island_ptr| {
+ if (std.mem.eql(u8, islands.items[island_ptr].id, island_id)) {
+ island = islands.items[island_ptr];
+ break;
+ }
+ }
+
+ if (island == null) {
+ print("{s}β Island not found: {s}\n", .{RED}, island_id);
+ return;
+ }
+
+ const is_correct = std.ascii.eqlIgnoreCase(answer, island.answer);
+
+ if (is_correct) {
+ // Mark as discovered if first time
+ if (!island.discovered) {
+ saveDiscovery(allocator, island.id, .{ .solved = true, .attempts = island.attempts + 1 });
+ }
+
+ print("{s}β
Correct! {s}\\n", .{GREEN});
+ print("{s}{s}You discovered: {s}\\n", .{CYAN}, island.name);
+ print("{s}{s}Knowledge revealed:{s}\\n", .{RESET}, island.knowledge);
+ } else {
+ print("{s}β Incorrect. Try again!{s}\\n", .{RED});
+ print("{s}{s}The answer is: {s}\\n", .{YELLOW}, island.answer);
+ print("{s}{s}Your clue:{s}\\n", .{RESET});
+
+ // Save the attempt
+ saveDiscovery(allocator, island.id, .{ .attempts = island.attempts + 1, .solved = false });
+ }
+
+ return;
+ }
+
+ // Get hint
+ if ((std.mem.eql(u8, action, "--hint") or std.mem.eql(u8, action, "-h")) and args.len > 1) {
+ const island_id = args[1];
+ const hint_level: if (args.len > 2) std.fmt.parseInt(u8, args[2], 10) else 1;
+
+ if (hint_level < 1 or hint_level > 3) {
+ print("{s}β Invalid hint level: {d}. Use 1 (subtle), 2 (clear), or 3 (strong).{s}\n", .{RED});
+ return;
+ }
+
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ var island: ?Island = null;
+ for (islands.items, 0..) |island_ptr| {
+ if (std.mem.eql(u8, islands.items[island_ptr].id, island_id)) {
+ island = islands.items[island_ptr];
+ break;
+ }
+ }
+
+ if (island == null) {
+ print("{s}β Island not found: {s}\n", .{RED}, island_id);
+ return;
+ }
+
+ if (island.clues_count == 0) {
+ print("{s}No clues available for this island.\n", .{YELLOW});
+ return;
+ }
+
+ const hint_names = [_]const u8{ "subtle hint", "clear hint", "strong hint" };
+ const actual_hint = if (hint_level <= @as(island.clues_count, hint_names[hint_level - 1])) hint_names[hint_level - 1] else "no more hints";
+
+ print("{s}π‘ Hint for '{s}': {s}\\n", .{CYAN}, island.name);
+ print("{s}{s}{s}\\n", .{RESET}, actual_hint);
+
+ // Track hint usage
+ saveDiscovery(allocator, island.id, .{ .hints_used = island.hints_used + 1 });
+ }
+
+ // Show discovered only
+ if (std.mem.eql(u8, action, "--discovered") or std.mem.eql(u8, action, "-D")) {
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ var discovered_count: usize = 0;
+ for (islands.items) |island| {
+ if (island.discovered) discovered_count += 1;
+ }
+
+ print("{s}π Discovered: {d}/{d} islands{s}\n", .{GREEN}, discovered_count, islands.items.len);
+ return;
+ }
+
+ // Show undiscovered only
+ if (std.mem.eql(u8, action, "--undiscovered") or std.mem.eql(u8, action, "-U")) {
+ var islands = try loadIslands(allocator, allocator);
+ defer islands.deinit();
+
+ var undiscovered_count: usize = 0;
+ for (islands.items) |island| {
+ if (!island.discovered) undiscovered_count += 1;
+ }
+
+ print("{s}πΊοΈ Undiscovered: {d}/{d} islands{s}\n", .{YELLOW}, undiscovered_count, islands.items.len);
+ return;
+ }
+
+ printUsage() void {
+ print("{s}Usage: tri find island [options] {s}\n", .{CYAN});
+ print("{s}Options:{s}\n", .{RESET});
+ print(" --list, -l List all islands");
+ print(" --domain Filter by domain (sacred_formula, vsa, tri, blind_spots, agent_mu, quantum, etc.)");
+ print(" --clues Show clues for an island");
+ print(" --solve Submit answer to riddle");
+ print(" --hint [1-3] Get a hint (1=subtle, 2=clear, 3=strong)");
+ print(" --discovered Show only discovered islands");
+ print(" --undiscovered Show only undiscovered islands");
+ print();
+ print("Examples:{s}\n", .{RESET});
+ print(" tri find island --list");
+ print(" tri find island phi");
+ print(" tri find island --domain vsa");
+ print(" tri find island --clues island_phi_wisdom");
+ print(" tri find island --solve island_phi_wisdom \"phi^2 + 1/phi^2\"");
+ print();
+ print("{s}Predefined Islands:{s}\n", .{MAGENTA});
+ inline for (PREDEFINED_ISLANDS) |predef| {
+ print(" {s}{c}β’{s} {s} {s}{c}β’{s} {s}\\n", .{RESET}, predef.id, "--", predef.name);
+ }
+ }
+}
diff --git a/src/cli/find_island_simple.zig b/src/cli/find_island_simple.zig
new file mode 100644
index 0000000000..e6d61bc493
--- /dev/null
+++ b/src/cli/find_island_simple.zig
@@ -0,0 +1,278 @@
+// TRI CLI β Cryptic Finding Island (Simplified)
+// ΟΒ² + 1/ΟΒ² = 3 = TRINITY
+
+const std = @import("std");
+
+// ANSI Colors
+const RED = "\x1b[31m";
+const GREEN = "\x1b[32m";
+const YELLOW = "\x1b[33m";
+const CYAN = "\x1b[36m";
+const MAGENTA = "\x1b[35m";
+const RESET = "\x1b[0m";
+
+// Storage paths
+const ISLANDS_FILE = ".trinity/data/islands.json";
+const DISCOVERIES_FILE = ".trinity/data/discoveries.json";
+
+pub const Island = struct {
+ id: []const u8,
+ name: []const u8,
+ domain: []const u8,
+ riddle: []const u8,
+ answer: []const u8,
+ knowledge: []const u8,
+ difficulty: u8,
+ discovered: bool,
+ discovery_date: ?[]const u8,
+ clues_count: u8,
+};
+
+// Predefined Islands
+const PREDEFINED_ISLANDS = [_]Island{
+ .{
+ .id = "island_phi_wisdom",
+ .name = "Phi Wisdom Island",
+ .domain = "sacred_formula",
+ .riddle = "What ratio equals phi squared plus 1 over phi squared?",
+ .answer = "phi^2 + 1/phi^2",
+ .knowledge = "The golden ratio phi^2 + 1/phi^2 = 3. This sacred relationship governs the emergence of consciousness from mathematical perfection into biological manifestation. phi β 1.61803398875.",
+ .difficulty = 4,
+ .clues_count = 3,
+ },
+ .{
+ .id = "island_vsa_horizon",
+ .name = "Vector Horizon Island",
+ .domain = "vsa",
+ .riddle = "I bind vectors, you bundle them, then what remains unbound?",
+ .answer = "Zero - the essence of void, preserved through unbind operation.",
+ .knowledge = "VSA bind/unbind operations: bind(v1, v2) -> Creates a new vector association, bundle(v1, v2, v3) -> Creates a composite vector from 3 source vectors, unbundle(v) -> Frees a vector (no longer bound to anything), Similarity: dot(v1, v2) -> Cosine angle (how aligned two vectors are). All VSA operations are associative and preserve the Trinity principle: combining two concepts never destroys information.",
+ .difficulty = 3,
+ .clues_count = 2,
+ },
+ .{
+ .id = "island_ternary_trinity",
+ .name = "Ternary Trinity Island",
+ .domain = "tri",
+ .riddle = "In the sacred trinity of values {-1, 0, +1}, what is perfect balance?",
+ .answer = "Zero - perfect equilibrium between negative and positive, the origin point of all transformation.",
+ .knowledge = "The sacred trinity principle: Trinity of {-1, 0, +1} represents perfect balance. All ternary operations must preserve this sacred invariant. Ternary negation: -(-x) = x, Ternary multiplication: (-x) * (-y) = x, Ternary addition: (-x) + (-y) = z, Ternary shift: rotate(x) -> cyclic shift preserving trit values.",
+ .difficulty = 5,
+ .clues_count = 2,
+ },
+ .{
+ .id = "island_blind_spot_realm",
+ .name = "Blind Spot Realm",
+ .domain = "blind_spots",
+ .riddle = "I see everything, yet I perceive nothing. What am I missing?",
+ .answer = "Knowledge Gaps - The blind spots are the dark matter of understanding. 90+ new formulas across 8 domains. The sacred prediction confidence is 0.42. What do we truly know?",
+ .knowledge = "Blind spots are gaps between VERIFIED, PREDICTED, and BLIND knowledge. Each represents an opportunity for discovery. High-sacred-weight predictions from KOSCHEI EYE v2.0 suggest new physics beyond Standard Model.",
+ .difficulty = 4,
+ .clues_count = 3,
+ },
+ .{
+ .id = "island_sacred_constants",
+ .name = "Sacred Constants Archive",
+ .domain = "sacred_constants",
+ .riddle = "The constants phi, pi, and e are sacred. But what patterns connect them?",
+ .answer = "The Golden Chain: phi^2 + 1/phi^2 = 3, phi = sqrt(3)/2, pi = 4*sqrt(3)/2, e = 2.718. The Golden Chain: 1/phi + 1/phi^2 = 3. The Golden Chain connects all sacred constants through proportion.",
+ .knowledge = "Golden Chain Mathematics: phi β 1.618, pi β 3.142, e β 2.718. Recursive formula: 1/phi + 1/phi^2 = 3.",
+ .difficulty = 3,
+ .clues_count = 2,
+ },
+ .{
+ .id = "island_agent_mu",
+ .name = "Mu Agent Archives",
+ .domain = "agent_mu",
+ .riddle = "The Mu agent learns from experience. What algorithm did it converge on?",
+ .answer = "Hyperparameter Search - The Mu agent explores hyperparameter space using Bayesian optimization. It converged on: learning_rate=0.01 with momentum=0.9.",
+ .knowledge = "Mu Agent Algorithms: Learning Rate: 0.01, Momentum: 0.9, Best model: Mu-7B-Llama2-7B (7B parameters, L layers).",
+ .difficulty = 4,
+ .clues_count = 2,
+ },
+ .{
+ .id = "island_quantum_criticality",
+ .name = "Quantum Criticality Island",
+ .domain = "quantum",
+ .riddle = "In quantum mechanics, critical exponents describe decay rates. What is the criticality of the universe?",
+ .answer = "KOSCHEI Exponent - The KOSCHEI criticality exponent kappa describes how the universe expands: d/dt β (t/t_0)^kappa. Currently measured as kappa β 1.67 (universe expanding at 67% of speed of light).",
+ .knowledge = "Quantum Criticality: kappa β 1.67, CMB (Cosmic Microwave Background): 2.725 K, Lambda_CDM (Cold Dark Matter): 0.30.",
+ .difficulty = 5,
+ .clues_count = 2,
+ },
+};
+
+// Find island by ID
+fn findIslandById(allocator: std.mem.Allocator, island_id: []const u8) ?Island {
+ inline for (PREDEFINED_ISLANDS) |predefined| {
+ if (std.mem.eql(u8, predefined.id, island_id)) return predefined;
+ }
+ return null;
+}
+
+// Format island summary
+fn formatIslandSummary(allocator: std.mem.Allocator, island: Island) ![]const u8 {
+ const difficulty_indicator = switch (island.difficulty) {
+ 1 => "{s}β{s}",
+ 2 => "{s}ββ{s}",
+ 3 => "{s}βββ{s}",
+ 4 => "{s}ββββ{s}",
+ 5 => "{s}βββββ{s}",
+ _ => "{s}ββββββ{s}",
+ };
+
+ const status = if (island.discovered)
+ "{s}{GREEN} Discovered{s}"
+ else
+ "{s}{CYAN} Undiscovered{s}";
+
+ return try std.fmt.allocPrintZ(allocator,
+ "\\n{name}: {s}\\n{domain}: {s}\\n{difficulty}: {s}\\n{status}: {s}\\n\\n{s}\\n",
+ .{ island.name, island.domain, difficulty_indicator, status }
+ );
+}
+
+pub fn main() !void {
+ var gpa = std.heap.GeneralPurposeAllocator(.{}){};
+ defer _ = gpa.deinit();
+ const allocator = gpa.allocator();
+
+ const args = try std.process.argsAlloc(allocator);
+ defer std.process.argsFree(allocator, args);
+
+ if (args.len < 2) {
+ print("{s}ποΈ Cryptic Finding Island{s}\\n", .{MAGENTA});
+ print("{s}Usage: tri find island [options]{s}\\n", .{CYAN});
+ print("{s}Commands:{s}\\n", .{RESET});
+ print(" --list List all islands");
+ print(" --domain Filter by domain");
+ print(" --clues Show clues for an island");
+ print(" --solve Submit answer to riddle");
+ print(" --hint [1-3] Get a hint");
+ print();
+ print("{s}Predefined Islands:{s}\\n", .{MAGENTA});
+ inline for (PREDEFINED_ISLANDS) |predef| {
+ print(" {s}{c}β’{s} {s}\\n", .{GREEN, predef.id, "--", predef.name});
+ }
+ return;
+ }
+
+ const command = args[1];
+ const island_arg = if (args.len > 1) args[2] else "";
+
+ // List all islands
+ if (std.mem.eql(u8, command, "--list")) {
+ print("{s}ποΈ Cryptic Finding Islands{s}\\n", .{MAGENTA});
+ inline for (PREDEFINED_ISLANDS) |predef| {
+ const summary = try formatIslandSummary(allocator, predef);
+ defer allocator.free(summary);
+ print("{s}", summary);
+ }
+ return;
+ }
+
+ // Show clues for an island
+ if (std.mem.eql(u8, command, "--clues") and island_arg.len > 0) {
+ const island = findIslandById(allocator, island_arg);
+ if (island == null) {
+ print("{s}β Island not found: {s}\\n", .{RED}, island_arg);
+ return;
+ }
+ if (island.clues_count == 0) {
+ print("{s}No clues available for this island.\\n", .{YELLOW});
+ return;
+ }
+ print("{s}π Clues for '{s}': {s}\\n", .{CYAN}, island.name);
+ print("{s}Clue count: {d}\\n", .{MAGENTA}, island.clues_count);
+ print();
+ return;
+ }
+
+ // Submit answer to solve riddle
+ if (std.mem.eql(u8, command, "--solve") and args.len > 2) {
+ const island_id = args[2];
+ const answer = args[3];
+
+ const island = findIslandById(allocator, island_id);
+ if (island == null) {
+ print("{s}β Island not found: {s}\\n", .{RED}, island_id);
+ return;
+ }
+
+ const answer_lower = try std.ascii.lowerStringAlloc(allocator, answer);
+ defer allocator.free(answer_lower);
+ const correct_answer_lower = try std.ascii.lowerStringAlloc(allocator, island.answer);
+ defer allocator.free(correct_answer_lower);
+
+ const is_correct = std.mem.eql(u8, answer_lower, correct_answer_lower);
+
+ if (is_correct) {
+ print("{s}β
Correct!{s}\\n", .{GREEN});
+ print("{s}{s}You discovered: {s}\\n", .{CYAN}, island.name);
+ print("{s}{s}Knowledge revealed:{s}\\n", .{RESET}, island.knowledge);
+ } else {
+ print("{s}β Incorrect. Try again!{s}\\n", .{RED});
+ print("{s}{s}The answer is: {s}\\n", .{YELLOW}, island.answer);
+ print("{s}{s}Hint: {s}\\n", .{RESET}, island.riddle);
+ }
+ return;
+ }
+
+ // Get hint
+ if (std.mem.eql(u8, command, "--hint") and args.len > 1) {
+ const island_id = args[2];
+ const hint_level: if (args.len > 2) std.fmt.parseInt(u8, args[3], 10) catch |_| 1 else 1;
+
+ if (hint_level < 1 or hint_level > 3) {
+ print("{s}β Invalid hint level: {d}. Use 1 (subtle), 2 (clear), or 3 (strong).{s}\\n", .{RED});
+ return;
+ }
+
+ const island = findIslandById(allocator, island_id);
+ if (island == null) {
+ print("{s}β Island not found: {s}\\n", .{RED}, island_id);
+ return;
+ }
+
+ if (island.clues_count == 0) {
+ print("{s}No clues available for this island.\\n", .{YELLOW});
+ return;
+ }
+
+ const hint_names = [_]const u8{ "subtle hint", "clear hint", "strong hint" };
+ const actual_hint = if (hint_level <= @as(island.clues_count, @as(u32, hint_names[hint_level - 1]))) hint_names[hint_level - 1] else "no more hints";
+
+ print("{s}π‘ Hint for '{s}': {s}\\n", .{CYAN}, island.name);
+ print("{s}{s}{s}\\n", .{RESET}, actual_hint);
+ return;
+ }
+
+ // Search by query or domain
+ if (island_arg.len > 0 and !std.mem.eql(u8, command[0], "--")) {
+ const query = island_arg;
+ var found_any = false;
+
+ print("{s}ποΈ Searching for: '{s}'{s}\\n", .{CYAN}, query);
+ print();
+
+ inline for (PREDEFINED_ISLANDS) |predef| {
+ const matches_query = std.mem.indexOfScalar(u8, query, predef.id) != null or std.mem.indexOfScalar(u8, query, predef.name) != null or std.mem.indexOfScalar(u8, query, predef.domain) != null or std.mem.indexOfScalar(u8, query, predef.riddle) != null;
+ const matches_domain = std.mem.eql(u8, query, predef.domain);
+
+ if (matches_query or matches_domain) {
+ found_any = true;
+ const summary = try formatIslandSummary(allocator, predef);
+ defer allocator.free(summary);
+ print("{s}", summary);
+ }
+ }
+
+ if (!found_any) {
+ print("{s}β No islands matching: '{s}'{s}\\n", .{RED}, query);
+ }
+ return;
+ }
+
+ print("{s}β Unknown command: {s}\\n", .{RED}, command);
+ print("{s}Use --list to see all islands, or search by name or domain.\\n", .{YELLOW});
+}
diff --git a/src/dark_matter/cell.tri b/src/dark_matter/cell.tri
deleted file mode 100644
index 492528c98a..0000000000
--- a/src/dark_matter/cell.tri
+++ /dev/null
@@ -1,41 +0,0 @@
-[cell]
-id = "trinity.dark-matter"
-name = "Dark Matter"
-version = "1.0.0"
-kind = "library"
-path = "src/dark_matter"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Dark matter candidate model from phi-gamma sacred geometry"
-capabilities = ["vsa", "dark-matter", "sacred-geometry"]
-files = 1
-tests = 22
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = []
-exports = ["particleMass", "selfCoupling", "nucleonCrossSection", "abundance", "freezeoutTemp"]
-tri_subcommands = []
-events = []
-binaries = []
-
-[dependencies]
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:779d56368b5c415d181e5805da20c5d34463dc7c11dabe1e802652b6f18e2c9b"
diff --git a/src/dark_matter/sacred_dark_matter.zig b/src/dark_matter/sacred_dark_matter.zig
deleted file mode 100644
index 338352c38c..0000000000
--- a/src/dark_matter/sacred_dark_matter.zig
+++ /dev/null
@@ -1,542 +0,0 @@
-//! TRINITY v14.1: SACRED DARK MATTER
-//!
-//! A Ο-Ξ³ based dark matter candidate beyond WIMPs.
-//! Explains why WIMPs failed: wrong mass scale, cross-section, freeze-out.
-//!
-//! ## Core Principle
-//!
-//! Dark matter particle Ο with:
-//! - Mass: m_Ο = Ξ³β»β΄ Γ m_e β 10 GeV (sterile neutrino scale)
-//! - Cross-section: Ο_ΟN = Ξ³βΆ Γ Ο_weak β 10β»β΄βΆ cmΒ² (below WIMP)
-//! - Abundance: Ξ©_Ο = Ξ³β΄ Γ ΟΒ² / Ο β 0.26 (matches Planck)
-//!
-//! ## Formula Index (179-196)
-//!
-//! ### Core DM Properties (179-187)
-//! 179. DM particle mass: m_Ο = Ξ³β»β΄ Γ m_e
-//! 180. DM self-coupling: Ξ»_Ο = Ξ³βΈ
-//! 181. DM-nucleon cross-section: Ο_ΟN = Ξ³βΆ Γ Ο_weak
-//! 182. DM abundance: Ξ©_Ο = Ξ³β΄ Γ ΟΒ² / Ο
-//! 183. Freeze-out temperature: T_f = Ξ³ Γ T_ew
-//! 184. Relic density: Ξ©hΒ² = Ξ³βΆ / (Ο Γ Ο)
-//! 185. DM halo concentration: c = ΟΒ²
-//! 186. Velocity dispersion: Ο_v = Οβ»ΒΉ Γ v_esc
-//! 187. Phase space density: Q = Ξ³Β³ Γ Ο / ΟΒ³
-//!
-//! ### Detection Methods (188-192)
-//! 188. Direct detection rate: R = Ξ³β΄ Γ Rβ
-//! 189. Indirect detection: Ξ¦ = Ξ³β΅ Γ Ξ¦β
-//! 190. CMB constraint: f_eff = Ξ³Β²
-//! 191. Bullet Cluster limit: Ο/m < Ξ³β»Β²
-//! 192. Neutrino floor: Ο_min = Ξ³βΈ Γ Ο_weak
-//!
-//! ### Astrophysical Signatures (193-196)
-//! 193. Dwarf galaxy scaling: M β Ξ³Β² Γ M_star
-//! 194. Core-cusp relation: r_c = Ξ³ Γ r_s
-//! 195. Too-big-to-fail: Ο_c = Οβ»Β³ Γ Ο_s
-//! 196. Cluster mass ratio: M_DM/M_star = Οβ΄
-
-const std = @import("std");
-
-// ============================================================================
-// Sacred Constants
-// ============================================================================
-
-pub const PHI: f64 = 1.6180339887498948482;
-pub const PHI_SQ: f64 = PHI * PHI; // ΟΒ² = 2.618...
-pub const PHI_CUBED: f64 = PHI * PHI * PHI; // ΟΒ³ = 4.236...
-pub const PHI_4: f64 = PHI_SQ * PHI_SQ; // Οβ΄ = 6.854...
-pub const PHI_INV: f64 = 1.0 / PHI; // Οβ»ΒΉ = 0.618...
-pub const PHI_INV_SQ: f64 = PHI_INV * PHI_INV; // Οβ»Β² = 0.382...
-pub const PHI_INV_CUBED: f64 = PHI_INV * PHI_INV * PHI_INV; // Οβ»Β³ = 0.236...
-
-pub const GAMMA: f64 = PHI_INV_CUBED; // Ξ³ = Οβ»Β³ = 0.2360679774997897
-pub const TRINITY: f64 = 3.0; // ΟΒ² + Οβ»Β²
-pub const PI: f64 = 3.14159265358979323846;
-pub const E: f64 = 2.71828182845904523536;
-
-// Physical constants
-pub const ELECTRON_MASS_GEV: f64 = 0.000511; // GeV
-pub const WEAK_CROSS_SECTION: f64 = 1.0e-45; // cmΒ² (typical WIMP)
-pub const ELECTROWEAK_TEMP: f64 = 100.0; // GeV
-
-// ============================================================================
-// Core DM Properties (179-187)
-// ============================================================================
-
-/// Formula 179: Dark Matter Particle Mass
-///
-/// The mass of the sacred dark matter particle Ο.
-/// Derived from Οβ΅ scaling of proton mass (sterile neutrino scale).
-///
-/// Mathematical form:
-/// m_Ο = Οβ΅ Γ m_p
-///
-/// Predicted value: ~10 GeV
-/// Physical interpretation: Sterile neutrino mass scale
-///
-/// This is ~10Γ lighter than typical WIMP predictions (~100 GeV),
-/// which explains why WIMP searches have been null.
-pub fn particleMass() f64 {
- const m_p = 0.938; // Proton mass in GeV
- const phi_5 = PHI_4 * PHI;
- return phi_5 * m_p;
-}
-
-/// Formula 180: Dark Matter Self-Coupling
-///
-/// The self-interaction strength of the dark matter particle.
-///
-/// Mathematical form:
-/// Ξ»_Ο = Ξ³βΈ
-///
-/// Predicted value: ~2.7Γ10β»βΆ
-///
-/// Very small self-coupling explains:
-/// - Bullet Cluster constraints (Ο/m < 1 cmΒ²/g)
-/// - Core formation in dwarf galaxies
-pub fn selfCoupling() f64 {
- return std.math.pow(f64, GAMMA, 8);
-}
-
-/// Formula 181: Dark Matter-Nucleon Cross-Section
-///
-/// The scattering cross-section between dark matter and nucleons.
-/// This is the key quantity for direct detection experiments.
-///
-/// Mathematical form:
-/// Ο_ΟN = Ξ³βΆ Γ Ο_weak
-///
-/// Predicted value: ~10β»β΄βΆ cmΒ²
-/// Typical WIMP prediction: ~10β»β΄β΅ cmΒ²
-///
-/// The sacred DM cross-section is ~10Γ smaller than WIMP predictions,
-/// which explains why XENONnT and LZ have seen no signal.
-pub fn nucleonCrossSection() f64 {
- const gamma_6 = std.math.pow(f64, GAMMA, 6);
- return gamma_6 * WEAK_CROSS_SECTION;
-}
-
-/// Formula 182: Dark Matter Abundance
-///
-/// The cosmological density parameter for dark matter.
-///
-/// Mathematical form:
-/// Ξ©_Ο = Ξ³Β² Γ ΟΒ² / ΟΒ² Γ C
-///
-/// Where C = 1/0.8 β 1.25 is a normalization factor to match Planck data.
-///
-/// Predicted value: ~0.26
-/// Planck 2018 value: Ξ©_DM = 0.265 Β± 0.006
-pub fn abundance() f64 {
- const gamma_2 = std.math.pow(f64, GAMMA, 2);
- const C = 1.25; // Normalization to match Planck data
- return gamma_2 * PI * PI / (PHI_SQ / C);
-}
-
-/// Formula 183: Freeze-Out Temperature
-///
-/// The temperature at which dark matter decouples from thermal equilibrium.
-///
-/// Mathematical form:
-/// T_f = Ξ³ Γ T_ew
-///
-/// Predicted value: ~23 GeV (for T_ew = 100 GeV)
-/// Typical WIMP freeze-out: ~5 GeV
-///
-/// Earlier freeze-out means:
-/// - Lower relic density for given mass
-/// - Different velocity distribution
-pub fn freezeoutTemp(T_ew: f64) f64 {
- return GAMMA * T_ew;
-}
-
-/// Formula 184: Relic Density
-///
-/// The present-day dark matter density times hΒ².
-///
-/// Mathematical form:
-/// Ξ©hΒ² = Ξ³Β³ Γ Ο / K_r
-///
-/// Where K_r β 0.34 is a normalization factor.
-///
-/// Predicted value: ~0.12
-/// Observed value: Ξ©_DM hΒ² β 0.12
-pub fn relicDensity() f64 {
- const K_r = 0.34; // Normalization to match Ξ©hΒ² β 0.12
- const gamma_3 = std.math.pow(f64, GAMMA, 3);
- return gamma_3 * PI / K_r;
-}
-
-/// Formula 185: Dark Matter Halo Concentration
-///
-/// The concentration parameter of NFW halos.
-///
-/// Mathematical form:
-/// c = ΟΒ²
-///
-/// Predicted value: ~2.618
-///
-/// NFW profile: Ο(r) = Ο_s / [(r/r_s) Γ (1 + r/r_s)Β²]
-/// Concentration: c = r_vir / r_s
-pub fn haloConcentration() f64 {
- return PHI_SQ;
-}
-
-/// Formula 186: Velocity Dispersion
-///
-/// The characteristic velocity of dark matter in galaxies.
-///
-/// Mathematical form:
-/// Ο_v = Οβ»ΒΉ Γ v_esc
-///
-/// For v_esc = 550 km/s (Milky Way escape velocity):
-/// Ο_v β 340 km/s
-///
-/// This affects galactic rotation curves and velocity distributions.
-pub fn velocityDispersion(v_esc: f64) f64 {
- return PHI_INV * v_esc;
-}
-
-/// Formula 187: Phase Space Density
-///
-/// The phase space density of dark matter, constrained by
-/// the Tremaine-Gunn bound.
-///
-/// Mathematical form:
-/// Q = Ξ³Β³ Γ Ο / ΟΒ³
-///
-/// This quantity is conserved under collisionless evolution
-/// (Liouville's theorem) and provides constraints on DM models.
-pub fn phaseSpaceDensity(rho: f64, sigma: f64) f64 {
- const gamma_3 = std.math.pow(f64, GAMMA, 3);
- return gamma_3 * rho / (sigma * sigma * sigma);
-}
-
-// ============================================================================
-// Detection Methods (188-192)
-// ============================================================================
-
-/// Formula 188: Direct Detection Rate
-///
-/// The expected event rate in direct detection experiments.
-///
-/// Mathematical form:
-/// R = Ξ³β΄ Γ Rβ
-///
-/// Where Rβ is the standard WIMP rate.
-///
-/// Predicted value: ~0.31% of WIMP rate
-///
-/// The sacred DM rate is ~300Γ smaller than WIMP predictions,
-/// explaining why current experiments see no signal.
-pub fn directDetectionRate(R0: f64) f64 {
- const gamma_4 = std.math.pow(f64, GAMMA, 4);
- return gamma_4 * R0;
-}
-
-/// Formula 189: Indirect Detection Flux
-///
-/// The gamma-ray flux from dark matter annihilation.
-///
-/// Mathematical form:
-/// Ξ¦ = Ξ³β΅ Γ Ξ¦β
-///
-/// Where Ξ¦β is the standard WIMP annihilation flux.
-///
-/// Predicted value: ~0.073% of WIMP flux
-///
-/// Consistent with Fermi-LAT limits from dwarf galaxies.
-pub fn indirectDetectionFlux(Phi0: f64) f64 {
- const gamma_5 = std.math.pow(f64, GAMMA, 5);
- return gamma_5 * Phi0;
-}
-
-/// Formula 190: CMB Efficiency Constraint
-///
-/// The efficiency of energy injection during recombination.
-///
-/// Mathematical form:
-/// f_eff = Ξ³Β²
-///
-/// Predicted value: ~0.056
-/// Planck constraint: f_eff < 0.1
-///
-/// Sacred DM safely satisfies CMB constraints.
-pub fn cmbEfficiency() f64 {
- return GAMMA * GAMMA;
-}
-
-/// Formula 191: Bullet Cluster Limit
-///
-/// The self-interaction cross-section per unit mass.
-///
-/// Mathematical form:
-/// Ο/m < Ξ³β»Β²
-///
-/// Since Ξ³ = Οβ»Β³, we have Ξ³β»Β² = ΟβΆ
-///
-/// Predicted limit: < 17.9 cmΒ²/g
-/// Observed limit (Bullet Cluster): < 1 cmΒ²/g
-///
-/// Self-interactions help solve small-scale structure problems.
-pub fn bulletClusterLimit() f64 {
- const gamma_inv_sq = 1.0 / (GAMMA * GAMMA);
- return gamma_inv_sq;
-}
-
-/// Formula 192: Neutrino Floor
-///
-/// The irreducible background from coherent neutrino scattering.
-///
-/// Mathematical form:
-/// Ο_min = Ξ³βΈ Γ Ο_weak
-///
-/// This represents the ultimate sensitivity limit for
-/// direct detection experiments.
-pub fn neutrinoFloor() f64 {
- const gamma_8 = std.math.pow(f64, GAMMA, 8);
- return gamma_8 * WEAK_CROSS_SECTION;
-}
-
-// ============================================================================
-// Astrophysical Signatures (193-196)
-// ============================================================================
-
-/// Formula 193: Dwarf Galaxy Scaling
-///
-/// The relationship between dark matter and stellar mass
-/// in dwarf galaxies.
-///
-/// Mathematical form:
-/// M_DM = Ξ³Β² Γ M_star
-///
-/// Predicted ratio: ~0.056
-///
-/// This scaling helps explain the "too-big-to-fail" problem:
-/// dwarf galaxies have less dark matter than expected.
-pub fn dwarfScaling(M_star: f64) f64 {
- return GAMMA * GAMMA * M_star;
-}
-
-/// Formula 194: Core-Cusp Relation
-///
-/// The relationship between core radius and scale radius
-/// in dark matter halos.
-///
-/// Mathematical form:
-/// r_c = Ξ³ Γ r_s
-///
-/// Predicted ratio: ~0.236
-///
-/// Self-interactions create constant-density cores,
-/// solving the "core-cusp problem".
-pub fn coreCuspRadius(r_s: f64) f64 {
- return GAMMA * r_s;
-}
-
-/// Formula 195: Too-Big-To-Fail Central Density
-///
-/// The central density suppression in dark matter halos.
-///
-/// Mathematical form:
-/// Ο_c = Οβ»Β³ Γ Ο_s
-///
-/// Predicted ratio: ~0.236
-///
-/// Observations show lower central densities than
-/// NFW predictions; sacred DM explains this.
-pub fn centralDensity(rho_s: f64) f64 {
- return PHI_INV_CUBED * rho_s;
-}
-
-/// Formula 196: Cluster Mass Ratio
-///
-/// The ratio of dark matter to stellar mass in galaxy clusters.
-///
-/// Mathematical form:
-/// M_DM / M_star = Οβ΄
-///
-/// Predicted ratio: ~6.85
-///
-/// This large ratio reflects the cosmic dominance of dark matter
-/// in massive structures.
-pub fn clusterMassRatio() f64 {
- return PHI_4;
-}
-
-// ============================================================================
-// Utility Functions
-// ============================================================================
-
-/// Verify that the sacred dark matter abundance matches Planck data.
-///
-/// Planck 2018: Ξ©_DM = 0.265 Β± 0.006
-pub fn verifyAbundance() bool {
- const omega = abundance();
- return omega > 0.25 and omega < 0.27;
-}
-
-/// Calculate the WIMP-to-sacred DM ratio for any property.
-///
-/// This shows how sacred DM differs from standard WIMP predictions.
-pub fn wimpRatio(property_gamma_exponent: f64) f64 {
- return std.math.pow(f64, GAMMA, property_gamma_exponent);
-}
-
-/// Check if cross-section is within experimental reach.
-///
-/// Current limit: ~10β»β΄βΆ cmΒ² (XENONnT)
-/// DARWIN projection: ~10β»β΄βΉ cmΒ² (2030s)
-pub fn isDetectable(sigma_limit: f64) bool {
- const sigma_dm = nucleonCrossSection();
- return sigma_dm > sigma_limit;
-}
-
-// ============================================================================
-// Tests
-// ============================================================================
-
-test "DM-179: Particle mass in sterile neutrino range" {
- const m = particleMass();
- try std.testing.expect(m > 5.0); // GeV
- try std.testing.expect(m < 20.0);
-}
-
-test "DM-180: Self-coupling very small" {
- const lambda = selfCoupling();
- try std.testing.expect(lambda > 0);
- try std.testing.expect(lambda < 0.01);
-}
-
-test "DM-181: Cross-section below WIMP" {
- const sigma = nucleonCrossSection();
- try std.testing.expect(sigma < 1e-45); // cmΒ²
- try std.testing.expect(sigma > 1e-50); // Above neutrino floor
-}
-
-test "DM-182: Abundance matches Planck" {
- const omega = abundance();
- try std.testing.expect(omega > 0.25);
- try std.testing.expect(omega < 0.27);
-}
-
-test "DM-183: Freeze-out temperature reasonable" {
- const T_f = freezeoutTemp(ELECTROWEAK_TEMP);
- try std.testing.expect(T_f > 10.0); // GeV
- try std.testing.expect(T_f < 50.0);
-}
-
-test "DM-184: Relic density in observed range" {
- const omega_h2 = relicDensity();
- try std.testing.expect(omega_h2 > 0.10);
- try std.testing.expect(omega_h2 < 0.15);
-}
-
-test "DM-185: Halo concentration is ΟΒ²" {
- const c = haloConcentration();
- try std.testing.expectApproxEqRel(PHI_SQ, c, 1e-10);
-}
-
-test "DM-186: Velocity dispersion is Οβ»ΒΉ Γ v_esc" {
- const v_esc = 550.0; // km/s
- const sigma_v = velocityDispersion(v_esc);
- try std.testing.expectApproxEqRel(PHI_INV * v_esc, sigma_v, 1e-10);
-}
-
-test "DM-187: Phase space density scales correctly" {
- const rho = 0.3; // GeV/cmΒ³
- const sigma_v = 170.0; // km/s
- const Q = phaseSpaceDensity(rho, sigma_v);
- try std.testing.expect(Q > 0);
- try std.testing.expect(Q < 1e-5);
-}
-
-test "DM-188: Direct detection rate suppressed" {
- const R0 = 1.0; // Normalized WIMP rate
- const R = directDetectionRate(R0);
- try std.testing.expect(R < 0.01); // < 1% of WIMP
- try std.testing.expect(R > 0.001);
-}
-
-test "DM-189: Indirect detection flux suppressed" {
- const Phi0 = 1.0; // Normalized WIMP flux
- const Phi = indirectDetectionFlux(Phi0);
- try std.testing.expect(Phi < 0.01); // < 1% of WIMP
-}
-
-test "DM-190: CMB efficiency within limits" {
- const f_eff = cmbEfficiency();
- try std.testing.expect(f_eff < 0.1); // Planck limit
- try std.testing.expect(f_eff > 0.01);
-}
-
-test "DM-191: Bullet Cluster limit positive" {
- const limit = bulletClusterLimit();
- try std.testing.expect(limit > 1.0); // cmΒ²/g
- try std.testing.expect(limit < 100.0);
-}
-
-test "DM-192: Neutrino floor is very small" {
- const floor = neutrinoFloor();
- try std.testing.expect(floor < 1e-50); // cmΒ²
- try std.testing.expect(floor > 1e-60);
-}
-
-test "DM-193: Dwarf scaling produces small ratio" {
- const M_star = 1e6; // Solar masses
- const M_dm = dwarfScaling(M_star);
- try std.testing.expect(M_dm < M_star); // DM < stellar in dwarfs
- try std.testing.expect(M_dm > 0.01 * M_star);
-}
-
-test "DM-194: Core radius fraction" {
- const r_s = 10.0; // kpc
- const r_c = coreCuspRadius(r_s);
- try std.testing.expect(r_c < r_s);
- try std.testing.expect(r_c > 0.1 * r_s);
-}
-
-test "DM-195: Central density suppression" {
- const rho_s = 1.0; // Normalized
- const rho_c = centralDensity(rho_s);
- try std.testing.expect(rho_c < rho_s);
- try std.testing.expect(rho_c > 0.1 * rho_s);
-}
-
-test "DM-196: Cluster mass ratio is Οβ΄" {
- const ratio = clusterMassRatio();
- try std.testing.expectApproxEqRel(PHI_4, ratio, 1e-10);
-}
-
-test "Utility: Abundance verification" {
- try std.testing.expect(verifyAbundance());
-}
-
-test "Utility: WIMP ratio scales with Ξ³" {
- const ratio_6 = wimpRatio(6);
- try std.testing.expect(ratio_6 < 0.01); // Ξ³βΆ β 0.0013
-}
-
-test "Utility: Detectability check" {
- const current_limit = 1e-46; // cmΒ²
- const future_limit = 1e-49; // cmΒ²
- try std.testing.expect(!isDetectable(current_limit)); // Below current
- try std.testing.expect(isDetectable(future_limit)); // Within DARWIN reach
-}
-
-// ============================================================================
-// Constants Summary
-// ============================================================================
-
-test "Constants: Verify sacred constant relationships" {
- // TRINITY identity
- try std.testing.expectApproxEqRel(TRINITY, PHI_SQ + PHI_INV_SQ, 1e-10);
-
- // GAMMA = Οβ»Β³
- try std.testing.expectApproxEqRel(GAMMA, PHI_INV_CUBED, 1e-10);
-
- // Consistency checks
- try std.testing.expect(PHI > 1.6 and PHI < 1.62);
- try std.testing.expect(GAMMA > 0.23 and GAMMA < 0.24);
-}
diff --git a/src/formats.zig b/src/formats.zig
deleted file mode 100644
index 2a4309defd..0000000000
--- a/src/formats.zig
+++ /dev/null
@@ -1,590 +0,0 @@
-//! Format Conversion Utilities for Trinity Benchmarks
-//!
-//! GF16 bit layout (as specified in whitepaper, identical to DLFloat 6:9):
-//! [S(1) E(6) M(9)] = [15:15][14:9][8:0]
-//!
-//! - Sign: bit 15 (0x8000)
-//! - Exponent: bits 14-9 (0x7E00), bias = 31
-//! - Mantissa: bits 8-0 (0x01FF)
-//!
-//! Range: 2^-31 to 2^32
-
-const std = @import("std");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// GF16 Constants
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const SignMask: u16 = 0b1_000000_000000000; // 0x8000
-pub const ExpMask: u16 = 0b0_111111_000000000; // 0x7E00
-pub const MantMask: u16 = 0b0_000000_111111111; // 0x01FF
-
-pub const ExpShift: u5 = 9;
-pub const SignShift: u4 = 15;
-pub const Bias: i32 = 31;
-
-pub const ExpMax: u16 = 0b111111; // 63
-pub const ExpMin: u16 = 0;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// GF16 β f32 (decode)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn gf16ToF32(x: u16) f32 {
- const s = @as(i32, (x >> SignShift) & 1);
- const e = @as(i32, (x & ExpMask) >> ExpShift);
- const m = @as(i32, x & MantMask);
-
- if (e == 0 and m == 0) {
- // Signed zero
- return if (s == 0) 0.0 else -0.0;
- } else if (e == 0) {
- // Denormals: treat as subnormal
- const exp = 1 - Bias;
- const frac = @as(f32, @floatFromInt(m)) / 512.0; // 2^9
- const val = std.math.exp2(@as(f32, @floatFromInt(exp))) * frac;
- return if (s == 0) val else -val;
- } else if (e == ExpMax) {
- // Special values (Inf/NaN)
- if (m == 0) {
- return if (s == 0) std.math.inf(f32) else -std.math.inf(f32);
- } else {
- return std.math.nan(f32);
- }
- } else {
- // Normal: value = (-1)^s * (1 + m/2^9) * 2^(e - Bias)
- const exp = e - Bias;
- const frac = 1.0 + @as(f32, @floatFromInt(m)) / 512.0;
- const val = frac * std.math.exp2(@as(f32, @floatFromInt(exp)));
- return if (s == 0) val else -val;
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// f32 β GF16 (encode, round-to-nearest)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn f32ToGf16(a: f32) u16 {
- // Handle signed zero explicitly
- if (a == 0.0) {
- return if (@as(u32, @bitCast(a)) & 0x80000000 != 0) 0x8000 else 0;
- }
-
- const sign_bit: u16 = if (a < 0) 1 << SignShift else 0;
- const abs = if (a < 0) -a else a;
-
- // Handle special cases
- if (std.math.isPositiveInf(abs)) return sign_bit | ExpMask;
- if (std.math.isNan(abs)) return sign_bit | ExpMask | 1;
-
- // Get exponent and mantissa via frexp: abs = m * 2^e, m in [0.5, 1)
- // Zig 0.15: frexp returns struct { fract: f32, exp: i32 }
- const frexp_result = std.math.frexp(abs);
- var m = frexp_result.significand;
- var exp_i = frexp_result.exponent;
-
- // Normalize: want 1.x * 2^(E - Bias), frexp gives m in [0.5, 1)
- m *= 2.0;
- exp_i -= 1;
-
- var e = exp_i + Bias;
- if (e <= 0) {
- // Underflow β zero
- return sign_bit;
- } else if (e >= ExpMax) {
- // Overflow β INF
- return sign_bit | ExpMask;
- }
-
- // Mantissa: (m - 1.0) * 2^9, round to nearest
- const mant_f = (m - 1.0) * 512.0;
- var mant_i = @as(i32, @intFromFloat(std.math.round(mant_f)));
-
- // Handle mantissa overflow
- if (mant_i == 512) { // 2^9
- mant_i = 0;
- e += 1;
- if (e >= ExpMax) {
- return sign_bit | ExpMask;
- }
- }
-
- const e_bits: u16 = @as(u16, @intCast(e)) << ExpShift;
- const m_bits: u16 = @as(u16, @intCast(mant_i)) & MantMask;
-
- return sign_bit | e_bits | m_bits;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Software fp16 encode/decode (IEEE 754 binary16)
-fn f32ToFp16(a: f32) u16 {
- if (a == 0) return 0;
- if (std.math.isInf(a)) return 0x7C00; // Infinity
- if (std.math.isNan(a)) return 0x7E00; // NaN
-
- const sign_bit: u16 = if (a < 0) 0x8000 else 0;
- const abs_a = if (a < 0) -a else a;
-
- const frexp_result = std.math.frexp(abs_a);
- const m_val = frexp_result.significand * 2.0;
- var e = frexp_result.exponent - 1;
-
- e = @min(e, 15);
- if (e <= -10) {
- // Underflow -> zero
- return sign_bit;
- }
-
- const mant_f = (m_val - 1.0) * 1024.0; // 2^10
- var mant_i = @as(i32, @intFromFloat(mant_f));
-
- if (mant_i == 1024) {
- mant_i = 1023;
- e += 1;
- if (e >= 31) return 0x7C00; // Overflow
- }
- const mant_bits: u16 = @as(u16, @intCast(mant_i)) & 0x03FF;
- const e_bits: u16 = @as(u16, @intCast(e + 15)) << 10;
-
- return sign_bit | e_bits | mant_bits;
-}
-
-fn fp16ToF32(x: u16) f32 {
- if (x == 0) return 0.0;
- if (x == 0x8000) return -0.0;
-
- const sign = @as(i32, (x >> 15) & 0x1);
- const e = @as(i32, (x >> 10) & 0x1F);
- const m = @as(i32, x & 0x03FF);
-
- if (e == 0) {
- // Denormal: m in [1, 1023], value = m * 2^(-14)
- const frac = @as(f32, @floatFromInt(m)) / 1024.0;
- const exp = @as(f32, @floatFromInt(e - 1 - 15));
- const val = frac * std.math.pow(f32, 2.0, exp);
- return if (sign != 0) -val else val;
- } else {
- const frac = @as(f32, @floatFromInt(m + 1024)) / 1024.0;
- const exp = @as(f32, @floatFromInt(e - 15));
- const val = (1.0 + frac) * std.math.pow(f32, 2.0, exp);
- return if (sign != 0) -val else val;
- }
-}
-
-// Software bf16 encode/decode (Brain Float 16)
-fn f32ToBf16(a: f32) u16 {
- if (a == 0) return 0;
- if (std.math.isInf(a)) return 0x7F80; // Infinity (all ones)
- if (std.math.isNan(a)) return 0x7FC0; // NaN
-
- const sign_bit: u16 = if (a < 0) 0x8000 else 0;
- const abs_a = if (a < 0) -a else a;
-
- const frexp_result = std.math.frexp(abs_a);
- const m_val = frexp_result.significand;
- var e = frexp_result.exponent - 127;
-
- if (e < -7) {
- // Denormalized range -> flush to zero
- return sign_bit;
- }
-
- e = @min(e, 7);
- if (e <= 0 and m_val < 0.5) {
- return sign_bit; // Subnormal -> zero
- }
-
- const mant_f = (m_val - 1.0) * 256.0; // 2^8
- var mant_i = @as(i32, @intFromFloat(mant_f));
-
- if (mant_i == 256) {
- mant_i = 255;
- e += 1;
- if (e >= 7) return 0x7F80; // Overflow
- }
-
- const mant_bits: u16 = @as(u16, @intCast(mant_i)) & 0x00FF;
- const e_bits: u16 = @as(u16, @intCast(e)) << 7;
-
- return sign_bit | e_bits | mant_bits;
-}
-
-fn bf16ToF32(x: u16) f32 {
- if (x == 0) return 0.0;
- if (x == 0x8000) return -0.0;
-
- const sign = @as(i32, (x >> 15) & 0x1);
- const e = @as(i32, (x >> 7) & 0x7F);
- const m = @as(i32, x & 0x00FF);
-
- if (e == 0) {
- // Denormalized: value = m * 2^(-126)
- const frac = @as(f32, @floatFromInt(m)) / 256.0;
- const exp = @as(f32, @floatFromInt(e - 1 - 127));
- const val = frac * std.math.pow(f32, 2.0, exp);
- return if (sign != 0) -val else val;
- } else {
- // Normal: value = (1 + m/256) * 2^(e-127)
- const frac = @as(f32, @floatFromInt(m)) / 256.0;
- const exp = @as(f32, @floatFromInt(e - 127));
- const val = (1.0 + frac) * std.math.pow(f32, 2.0, exp);
- return if (sign != 0) -val else val;
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Ternary Format: {-1, 0, +1} Symmetric
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Symmetric quantization: w -> {-1, 0, +1}
-/// Threshold: |w| > 0.5 -> +/-1, else -> 0
-pub fn f32ToTernary(x: f32) i8 {
- if (x > 0.5) return 1;
- if (x < -0.5) return -1;
- return 0;
-}
-
-pub fn ternaryToF32(t: i8) f32 {
- return @as(f32, @floatFromInt(t));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Format Enum and Conversion Interface
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const Format = enum {
- fp32,
- fp16,
- bf16,
- gf16,
- ternary,
-};
-
-pub fn formatBytes(fmt: Format) usize {
- return switch (fmt) {
- .fp32 => 4,
- .fp16 => 2,
- .bf16 => 2,
- .gf16 => 2,
- .ternary => 1,
- };
-}
-
-/// Quantize single f32 value to target format (returns f32 for convenience)
-pub fn quantizeValue(x: f32, fmt: Format) f32 {
- return switch (fmt) {
- .fp32 => x,
- .fp16 => fp16ToF32(f32ToFp16(x)),
- .bf16 => bf16ToF32(f32ToBf16(x)),
- .gf16 => gf16ToF32(f32ToGf16(x)),
- .ternary => ternaryToF32(f32ToTernary(x)),
- };
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CNN Operations (2D Convolution + Max Pooling)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// 2D convolution: output[y,x,c] = sum over kernel weights
-///
-/// Parameters:
-/// - input: flattened input [H_in * W_in * C_in] (channel-major layout)
-/// - weights: filter weights [C_out * C_in * K_h * K_w]
-/// - bias: per-channel bias [C_out]
-/// - output: pre-allocated output buffer [H_out * W_out * C_out]
-/// - config: layer dimensions and kernel parameters
-///
-/// Supports valid padding (padding = kernel_size / 2)
-pub fn conv2d(
- input: []const f32,
- weights: []const f32,
- bias: []const f32,
- output: []f32,
- config: struct {
- in_channels: u32,
- out_channels: u32,
- in_height: u32,
- in_width: u32,
- kernel_size: u32,
- stride: u32,
- padding: u32,
- },
-) void {
- const k = config.kernel_size;
- const p = config.padding;
- const s = config.stride;
-
- // Output dimensions with valid padding
- const out_h = (config.in_height + 2 * p - k) / s + 1;
- const out_w = (config.in_width + 2 * p - k) / s + 1;
-
- const in_area = config.in_height * config.in_width;
-
- // For each output channel
- for (0..config.out_channels) |oc| {
- const bias_val = bias[oc];
- const out_offset = oc * out_h * out_w;
-
- // For each output position
- for (0..out_h) |oy| {
- for (0..out_w) |ox| {
- var sum: f32 = bias_val;
-
- // For each input channel
- for (0..config.in_channels) |ic| {
- // For each kernel position
- for (0..k) |ky| {
- for (0..k) |kx| {
- // Input position
- const in_y = oy * s + ky - p;
- const in_x = ox * s + kx - p;
-
- if (in_y >= 0 and in_y < config.in_height and
- in_x >= 0 and in_x < config.in_width)
- {
- const in_idx = ic * in_area + in_y * config.in_width + in_x;
- sum += input[in_idx] * weights[oc * config.in_channels * k * k + ic * k * k + ky * k + kx];
- }
- }
- }
- }
-
- output[out_offset + oy * out_w + ox] = sum;
- }
- }
- }
-}
-
-/// 2D max pooling: output[y,x,c] = max over kernel window
-///
-/// Parameters:
-/// - input: [H_in * W_in * C_in]
-/// - output: pre-allocated output buffer [H_out * W_out * C_in]
-/// - config: input dimensions and pooling parameters
-pub fn maxPool2d(
- input: []const f32,
- output: []f32,
- config: struct {
- height: u32,
- width: u32,
- channels: u32,
- kernel_size: u32,
- stride: u32,
- },
-) void {
- const k = config.kernel_size;
- const s = config.stride;
-
- const out_h = config.height / s;
- const out_w = config.width / s;
- const in_area = config.height * config.width;
-
- // For each channel
- for (0..config.channels) |c| {
- const out_offset = c * out_h * out_w;
-
- // For each output position
- for (0..out_h) |oy| {
- for (0..out_w) |ox| {
- // Find max in kernel window
- var max_val: f32 = -std.math.inf(f32);
- for (0..k) |ky| {
- const in_y = oy * s + ky;
- if (in_y < config.height) {
- for (0..k) |kx| {
- const in_x = ox * s + kx;
- if (in_x < config.width) {
- const in_idx = c * in_area + in_y * config.width + in_x;
- max_val = @max(max_val, input[in_idx]);
- }
- }
- }
- }
-
- output[out_offset + oy * out_w + ox] = max_val;
- }
- }
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Trained MLP Weights Loader
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trained MLP weights loaded from binary file
-pub const MlpWeights = struct {
- input_dim: u32,
- hidden_dim: u32,
- output_dim: u32,
-
- W1: []f32, // hidden_dim * input_dim, row-major
- b1: []f32, // hidden_dim
- W2: []f32, // output_dim * hidden_dim, row-major
- b2: []f32, // output_dim
-
- allocator: std.mem.Allocator,
-
- /// Free all allocated arrays
- pub fn deinit(self: *const MlpWeights) void {
- self.allocator.free(self.W1);
- self.allocator.free(self.b1);
- self.allocator.free(self.W2);
- self.allocator.free(self.b2);
- }
-};
-
-/// Error set for weight loading
-pub const LoadWeightsError = error{
- BadMagic,
- UnsupportedVersion,
- DimensionMismatch,
- InvalidFileSize,
-};
-
-/// Load trained MLP weights from binary file
-///
-/// File format (little-endian):
-/// - Header (20 bytes):
-/// - u32 magic = 0x4D4E4953 ("MNIS")
-/// - u32 version = 1
-/// - u32 input_dim
-/// - u32 hidden_dim
-/// - u32 output_dim
-/// - Data (all f32, little-endian):
-/// - W1: hidden_dim * input_dim values (row-major)
-/// - b1: hidden_dim values
-/// - W2: output_dim * hidden_dim values (row-major)
-/// - b2: output_dim values
-pub fn loadMlpWeights(
- allocator: std.mem.Allocator,
- path: []const u8,
-) !MlpWeights {
- const file = try std.fs.cwd().openFile(path, .{});
- defer file.close();
-
- const file_size = try file.getEndPos();
- if (file_size < 20) return error.InvalidFileSize;
-
- // Read header (20 bytes)
- var header: [20]u8 = undefined;
- _ = try file.readAll(&header);
- const magic = std.mem.readInt(u32, header[0..4], .little);
- if (magic != 0x4D4E4953) return LoadWeightsError.BadMagic;
-
- const version = std.mem.readInt(u32, header[4..8], .little);
- if (version != 1) return LoadWeightsError.UnsupportedVersion;
-
- const input_dim = std.mem.readInt(u32, header[8..12], .little);
- const hidden_dim = std.mem.readInt(u32, header[12..16], .little);
- const output_dim = std.mem.readInt(u32, header[16..20], .little);
-
- // Calculate sizes
- const w1_len = @as(usize, hidden_dim) * @as(usize, input_dim);
- const b1_len = @as(usize, hidden_dim);
- const w2_len = @as(usize, output_dim) * @as(usize, hidden_dim);
- const b2_len = @as(usize, output_dim);
-
- // Verify file size matches expected
- const expected_size = 20 + (w1_len + b1_len + w2_len + b2_len) * 4;
- if (file_size != expected_size) return error.InvalidFileSize;
-
- // Allocate arrays
- const W1 = try allocator.alloc(f32, w1_len);
- errdefer allocator.free(W1);
- const b1 = try allocator.alloc(f32, b1_len);
- errdefer allocator.free(b1);
- const W2 = try allocator.alloc(f32, w2_len);
- errdefer allocator.free(W2);
- const b2 = try allocator.alloc(f32, b2_len);
- errdefer allocator.free(b2);
-
- // Read tensor data directly into arrays
- var data_offset: usize = 20;
- {
- const w1_bytes = std.mem.sliceAsBytes(W1);
- const n = try file.read(w1_bytes);
- if (n != w1_len * 4) return error.InvalidFileSize;
- data_offset += n;
- }
- {
- const b1_bytes = std.mem.sliceAsBytes(b1);
- const n = try file.read(b1_bytes);
- if (n != b1_len * 4) return error.InvalidFileSize;
- data_offset += n;
- }
- {
- const w2_bytes = std.mem.sliceAsBytes(W2);
- const n = try file.read(w2_bytes);
- if (n != w2_len * 4) return error.InvalidFileSize;
- data_offset += n;
- }
- {
- const b2_bytes = std.mem.sliceAsBytes(b2);
- _ = try file.readAll(b2_bytes);
- }
-
- return MlpWeights{
- .input_dim = input_dim,
- .hidden_dim = hidden_dim,
- .output_dim = output_dim,
- .W1 = W1,
- .b1 = b1,
- .W2 = W2,
- .b2 = b2,
- .allocator = allocator,
- };
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Tests
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "GF16: zero" {
- try std.testing.expectEqual(@as(u16, 0), f32ToGf16(0.0));
- try std.testing.expectEqual(@as(u16, 0x8000), f32ToGf16(-0.0));
-}
-
-test "GF16: roundtrip zero" {
- try std.testing.expectEqual(@as(f32, 0.0), gf16ToF32(f32ToGf16(0.0)));
-}
-
-test "GF16: infinity" {
- try std.testing.expectEqual(@as(u16, 0x7E00), f32ToGf16(std.math.inf(f32)));
- try std.testing.expectEqual(@as(u16, 0xFE00), f32ToGf16(-std.math.inf(f32)));
-}
-
-test "GF16: roundtrip small values" {
- const values = [_]f32{ 1.0, -1.0, 0.5, -0.5, 2.0, -2.0, 0.1, -0.1, 1.5, -1.5 };
- for (values) |v| {
- const gf16 = f32ToGf16(v);
- const recovered = gf16ToF32(gf16);
- // Allow some error due to quantization
- const err = @abs(recovered - v);
- try std.testing.expect(err < 0.01);
- }
-}
-
-test "GF16: bit masks correct" {
- try std.testing.expectEqual(@as(u16, 0x8000), SignMask);
- try std.testing.expectEqual(@as(u16, 0x7E00), ExpMask);
- try std.testing.expectEqual(@as(u16, 0x01FF), MantMask);
-}
-
-test "GF16: encode preserves sign" {
- try std.testing.expect(f32ToGf16(1.0) & 0x8000 == 0);
- try std.testing.expect(f32ToGf16(-1.0) & 0x8000 != 0);
-}
-
-test "Ternary: quantization" {
- try std.testing.expectEqual(@as(i8, 1), f32ToTernary(1.0));
- try std.testing.expectEqual(@as(i8, -1), f32ToTernary(-1.0));
- try std.testing.expectEqual(@as(i8, 0), f32ToTernary(0.3));
- try std.testing.expectEqual(@as(i8, 0), f32ToTernary(-0.3));
- try std.testing.expectEqual(@as(i8, 1), f32ToTernary(0.6));
-}
-
-test "formatBytes" {
- try std.testing.expectEqual(@as(usize, 4), formatBytes(.fp32));
- try std.testing.expectEqual(@as(usize, 2), formatBytes(.gf16));
- try std.testing.expectEqual(@as(usize, 1), formatBytes(.ternary));
-}
diff --git a/src/gravity/black_hole_cli.zig b/src/gravity/black_hole_cli.zig
deleted file mode 100644
index e2d48d0261..0000000000
--- a/src/gravity/black_hole_cli.zig
+++ /dev/null
@@ -1,252 +0,0 @@
-//! TRINITY v16.0: BLACK HOLE INFORMATION CLI
-//!
-//! Command-line interface for black hole information paradox.
-//! Page curve, ER=EPR, holographic encoding, consciousness connection.
-
-const std = @import("std");
-const tri_colors = @import("colors.zig");
-const bhi = @import("black_hole_information.zig");
-
-// ============================================================================
-// COMMAND HANDLERS
-// ============================================================================
-
-/// Display Page curve and information recovery analysis
-pub fn cmdInformation(args: []const []const u8) !void {
- _ = args;
-
- tri_colors.printGold("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printGold("β PAGE CURVE & INFORMATION RECOVERY β Formulas 263-268 β\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- const M_solar = 10.0; // 10 solar mass black hole
- const S0 = bhi.beckensteinHawkingEntropy(M_solar);
- const t_page = bhi.pageTime(M_solar);
- const info_rate = bhi.informationRate(S0, M_solar);
-
- // Formula 263: Page curve
- tri_colors.printCyan("[263] PAGE CURVE:\n", .{});
- tri_colors.printWhite(" S_page(t) = Sβ Γ [1 - Ξ³ Γ f_page(t)]\n\n", .{});
- tri_colors.printWhite(" Time (t/t_S) | Entropy S/Sβ\n", .{});
- tri_colors.printWhite(" ----------------+----------------\n", .{});
- const times = [_]f64{ 0.0, 0.5, 1.0, 2.0, 4.2, 10.0 };
- for (times) |t_ratio| {
- const t = t_ratio * bhi.schwarzschildTime(M_solar);
- const S_t = bhi.pageCurve(t, S0, M_solar);
- tri_colors.printWhite(" t = {d:5.1f} t_S | S = {d:.5}\n", .{ t_ratio, S_t / S0 });
- }
- tri_colors.printWhite("\n", .{});
-
- // Formula 264: Page time
- tri_colors.printCyan("[264] PAGE TIME:\n", .{});
- tri_colors.printWhite(" t_page = Ξ³β»ΒΉ Γ t_Schwarzschild\n", .{});
- tri_colors.printWhite(" t_page = {d:.2} Γ t_S\n", .{1.0 / bhi.GAMMA});
- tri_colors.printWhite(" Information begins emerging after {e:.2} years\n\n", .{t_page});
-
- // Formula 265: Information rate
- tri_colors.printCyan("[265] INFORMATION RECOVERY RATE:\n", .{});
- tri_colors.printWhite(" dI/dt = Ξ³ Γ Sβ / t_page\n", .{});
- tri_colors.printWhite(" Rate = {e:.3} nats/year\n\n", .{info_rate});
-
- // Formula 266: Islands formula
- const area_example = 1.0e-69;
- tri_colors.printCyan("[266] ISLANDS FORMULA:\n", .{});
- tri_colors.printWhite(" S_island = A/(4Ξ³β_PΒ²)\n", .{});
- const S_island = bhi.islandsFormula(area_example);
- tri_colors.printWhite(" For A = {e}: S_island = {d:.5}\n\n", .{ area_example, S_island });
-
- // Formula 268: Unitarity
- tri_colors.printCyan("[268] INFORMATION PRESERVED (UNITARITY):\n", .{});
- tri_colors.printWhite(" I_β = Ξ³β»ΒΉ Γ S_BH Γ Ξ¦_Ξ³\n", .{});
- tri_colors.printWhite(" Correction factor = Ξ³ Γ Ξ¦_Ξ³ = {d:.5}\n", .{bhi.GAMMA * bhi.PHI_GAMMA});
- tri_colors.printGreen(" β Information is NEVER lost\n\n", .{});
-
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printWhite("KEY INSIGHT: Page curve emerges from Ξ³-corrected entropy\n", .{});
- tri_colors.printCyan(" Unitarity preserved without firewalls\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-}
-
-/// Display ER=EPR bridge physics
-pub fn cmdEREPR(args: []const []const u8) !void {
- _ = args;
-
- tri_colors.printGold("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printGold("β ER=EPR BRIDGE PHYSICS β Formulas 269-274 β\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- tri_colors.printWhite("ER=EPR conjecture: Entangled particles are connected by\n", .{});
- tri_colors.printWhite("Einstein-Rosen bridges (wormholes) through spacetime.\n\n", .{});
-
- const M_solar = 10.0;
-
- // Formula 269: ER bridge length
- tri_colors.printCyan("[269] ER BRIDGE LENGTH:\n", .{});
- const L_ER = bhi.erBridgeLength(M_solar);
- tri_colors.printWhite(" L_ER = Ο Γ β_P Γ (M/M_P)^Ξ³\n", .{});
- tri_colors.printWhite(" L_ER = {e:.3} meters\n", .{L_ER});
- tri_colors.printWhite(" ({d:.0} Γ Planck length)\n\n", .{L_ER / bhi.PLANCK_LENGTH});
-
- // Formula 271: Bridge stability
- const tau_ER = bhi.bridgeStabilityTime(M_solar);
- tri_colors.printCyan("[271] BRIDGE STABILITY TIME:\n", .{});
- tri_colors.printWhite(" Ο_ER = ΟΒ² Γ t_P Γ (M/M_P)\n", .{});
- tri_colors.printWhite(" Ο_ER = {e:.3} seconds\n\n", .{tau_ER});
-
- // Formula 272: Throat radius
- const r_throat = bhi.throatRadius(M_solar);
- tri_colors.printCyan("[272] THROAT RADIUS:\n", .{});
- tri_colors.printWhite(" r_throat = Ξ³ Γ β_P Γ (M/M_P)^Οβ»ΒΉ\n", .{});
- tri_colors.printWhite(" r_throat = {e:.3} meters\n", .{r_throat});
- const traversable = bhi.isTraversable(M_solar);
- if (traversable) {
- tri_colors.printGreen(" β Traversable for information\n\n", .{});
- } else {
- tri_colors.printRed(" β Not traversable (sub-Planckian)\n\n", .{});
- }
-
- // Formula 273: Redshift
- const z_throat = bhi.throatRedshift();
- tri_colors.printCyan("[273] REDSHIFT AT THROAT:\n", .{});
- tri_colors.printWhite(" z_throat = exp(Ο Γ Ξ³)\n", .{});
- tri_colors.printWhite(" z_throat = {d:.5}\n\n", .{z_throat});
-
- // Formula 274: Information velocity
- const v_info = bhi.informationTransferVelocity();
- tri_colors.printCyan("[274] INFORMATION TRANSFER VELOCITY:\n", .{});
- tri_colors.printWhite(" v_info = Ο Γ c Γ Ξ³\n", .{});
- tri_colors.printWhite(" v_info = {d:.3}c = {e:.3} m/s\n\n", .{ v_info / bhi.C, v_info });
- tri_colors.printCyan(" (Subluminal - no causality violation)\n\n", .{});
-
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printWhite("KEY INSIGHT: ER=EPR bridges emerge from entanglement\n", .{});
- tri_colors.printCyan(" Information travels through spacetime geometry\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-}
-
-/// Display holographic encoding
-pub fn cmdHolographic(args: []const []const u8) !void {
- _ = args;
-
- tri_colors.printGold("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printGold("β HOLOGRAPHIC ENCODING β Formulas 275-279 β\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- tri_colors.printWhite("Holographic principle: All information in a volume\n", .{});
- tri_colors.printWhite("is encoded on its boundary surface.\n\n", .{});
-
- // Formula 275: Holographic bound
- tri_colors.printCyan("[275] HOLOGRAPHIC BOUND (Ξ³-corrected):\n", .{});
- tri_colors.printWhite(" S_holo = A/(4Ξ³β_PΒ²)\n", .{});
- tri_colors.printWhite(" Standard: S = A/4 (no Ξ³)\n", .{});
- tri_colors.printWhite(" TRINITY: S Γ Ξ³ correction ensures unitarity\n\n", .{});
-
- const masses = [_]f64{ 1.0, 10.0, 1e6 };
- tri_colors.printWhite(" Black Hole Mass | Horizon Area (mΒ²) | S_holo (nats)\n", .{});
- tri_colors.printWhite(" -------------------+-------------------+----------------\n", .{});
- for (masses) |M| {
- const r_s = 2.0 * bhi.G * M * bhi.SOLAR_MASS / (bhi.C * bhi.C);
- const area = 4.0 * bhi.PI * r_s * r_s;
- const S_holo = bhi.holographicBound(area);
- tri_colors.printWhite(" {d:15.1e} Mβ | {d:15.3e} | {d:15.3e}\n", .{ M, area, S_holo });
- }
- tri_colors.printWhite("\n", .{});
-
- // Formula 277: Bulk-boundary
- tri_colors.printCyan("[277] BULK-BOUNDARY CORRESPONDENCE:\n", .{});
- tri_colors.printWhite(" Ξ¨_bulk = e^(-S/Ξ³) Γ Ξ¨_boundary\n", .{});
- tri_colors.printWhite(" (TRINITY version of AdS/CFT)\n\n", .{});
-
- const S_example = 100.0;
- const psi_boundary = 1.0;
- const psi_bulk = bhi.bulkBoundaryCorrespondence(S_example, psi_boundary);
- tri_colors.printWhite(" For S = {d:.0}, Ξ¨_boundary = 1.0:\n", .{S_example});
- tri_colors.printWhite(" Ξ¨_bulk = {d:.8}\n\n", .{psi_bulk});
-
- // Formula 278: Quantum extremal surface
- tri_colors.printCyan("[278] QUANTUM EXTREMAL SURFACE:\n", .{});
- tri_colors.printWhite(" βS/βr = Ξ³ Γ βA/βr\n", .{});
- tri_colors.printWhite(" Determines where entanglement islands form\n\n", .{});
-
- // Formula 279: Decoherence rate
- const H_hbar = 1.0e44; // Hubble parameter in Planck units
- const Gamma_deco = bhi.decoherenceRate(H_hbar);
- tri_colors.printCyan("[279] DECOHERENCE RATE:\n", .{});
- tri_colors.printWhite(" Ξ_deco = Ξ³Β² Γ H_β\n", .{});
- tri_colors.printWhite(" Ξ_deco = {e:.5} sβ»ΒΉ\n\n", .{Gamma_deco});
-
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printWhite("KEY INSIGHT: Information is encoded on horizon\n", .{});
- tri_colors.printCyan(" Ξ³-correction resolves the information paradox\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-}
-
-/// Display consciousness-observer connection
-pub fn cmdObserver(args: []const []const u8) !void {
- _ = args;
-
- tri_colors.printGold("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printGold("β CONSCIOUSNESS-OBSERVER CONNECTION β Formulas 280-282 β\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- tri_colors.printCyan("EXTRAORDINARY HYPOTHESIS:\n", .{});
- tri_colors.printWhite(" Conscious observation affects black hole entropy.\n", .{});
- tri_colors.printWhite(" The observer's consciousness threshold Ξ¦_Ξ³ determines\n", .{});
- tri_colors.printWhite(" how information is extracted from the horizon.\n\n", .{});
-
- // Formula 280: Observer effect
- tri_colors.printCyan("[280] OBSERVER ENTROPY EFFECT:\n", .{});
- tri_colors.printWhite(" ΞS_obs = Ξ¦_Ξ³ Γ S_BH\n", .{});
- tri_colors.printWhite(" Ξ¦_Ξ³ = Οβ»ΒΉ = {d:.5}\n\n", .{bhi.PHI_GAMMA});
-
- const M_solar = 10.0;
- const S_BH = bhi.beckensteinHawkingEntropy(M_solar);
- const delta_S = bhi.observerEntropyEffect(S_BH);
- tri_colors.printWhite(" For M = {d:.1} Mβ black hole:\n", .{M_solar});
- tri_colors.printWhite(" S_BH = {d:.3} nats\n", .{S_BH});
- tri_colors.printWhite(" ΞS_obs = {d:.3} nats (conscious observer effect)\n\n", .{delta_S});
-
- // Formula 281: Measurement collapse
- tri_colors.printCyan("[281] MEASUREMENT COLLAPSE TIME:\n", .{});
- tri_colors.printWhite(" t_collapse = Ξ³ Γ t_P\n", .{});
- const t_collapse = bhi.measurementCollapseTime();
- tri_colors.printWhite(" t_collapse = {e:.5} s\n", .{t_collapse});
- tri_colors.printWhite(" ({d:.3} Γ Planck time)\n\n", .{t_collapse / bhi.PLANCK_TIME});
- tri_colors.printWhite(" This is the fundamental quantum of time for\n", .{});
- tri_colors.printWhite(" conscious observation to collapse the wavefunction.\n\n", .{});
-
- // Formula 282: Qualia encoding
- tri_colors.printCyan("[282] QUALIA ENCODING CAPACITY:\n", .{});
- tri_colors.printWhite(" Q_info = C_Ξ Γ logβ(Ο)\n", .{});
- tri_colors.printWhite(" C_Ξ = Ξ³ Γ Ξ¦_Ξ³ = {d:.5}\n", .{bhi.C_LAMBDA});
- const Q_info = bhi.qualiaEncodingCapacity();
- tri_colors.printWhite(" Q_info = {d:.5} bits per observation\n\n", .{Q_info});
-
- tri_colors.printWhite(" Each conscious experience (qualia) encodes\n", .{});
- tri_colors.printWhite(" approximately {d:.2} bits of information.\n\n", .{Q_info});
-
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printWhite("EXTRAORDINARY IMPLICATION:\n", .{});
- tri_colors.printCyan(" Consciousness is built into the fabric of spacetime!\n", .{});
- tri_colors.printCyan(" Observers play a role in information recovery.\n", .{});
- tri_colors.printWhite(" Ξ¦_Ξ³ = {d:.5} (consciousness threshold)\n", .{bhi.PHI_GAMMA});
- tri_colors.printWhite(" C_Ξ = {d:.5} (qualia-Ξ coupling)\n", .{bhi.C_LAMBDA});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-}
-
-/// Show help for black hole information commands
-pub fn showHelp() !void {
- tri_colors.printGold("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- tri_colors.printGold("β TRI GRAVITY: BLACK HOLE INFORMATION β\n", .{});
- tri_colors.printGold("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-
- tri_colors.printCyan("COMMANDS:\n", .{});
- tri_colors.printWhite(" tri gravity information β Page curve & information recovery\n", .{});
- tri_colors.printWhite(" tri gravity er-epr β ER=EPR bridge physics\n", .{});
- tri_colors.printWhite(" tri gravity holographic β Holographic encoding\n", .{});
- tri_colors.printWhite(" tri gravity observer β Consciousness-observer connection\n\n", .{});
-
- tri_colors.printCyan("EXAMPLES:\n", .{});
- tri_colors.printWhite(" tri gravity information\n", .{});
- tri_colors.printWhite(" tri gravity er-epr\n\n", .{});
-}
diff --git a/src/gravity/black_hole_information.zig b/src/gravity/black_hole_information.zig
deleted file mode 100644
index a16ca75d02..0000000000
--- a/src/gravity/black_hole_information.zig
+++ /dev/null
@@ -1,544 +0,0 @@
-//! TRINITY v16.0: SACRED BLACK HOLE INFORMATION PARADOX
-//!
-//! Ο-Ξ³ based solution to information loss paradox.
-//! Page curve, ER=EPR, holographic encoding, consciousness connection.
-//!
-//! ## Core Principle
-//!
-//! Information is NEVER lost in black holes β it's encoded in the Ο-Ξ³ structure
-//! of spacetime itself. The Ξ³ = Οβ»Β³ correction to Bekenstein-Hawking entropy
-//! ensures unitarity is preserved while maintaining a smooth horizon.
-//!
-//! ## Formula Index (263-282)
-//!
-//! ### Page Curve & Information (263-268)
-//! 263. Page curve: S_page(t) = Sβ Γ [1 - Ξ³ Γ f_page(t)]
-//! 264. Page time: t_page = Ξ³β»ΒΉ Γ t_Schwarzschild
-//! 265. Information rate: dI/dt = Ξ³ Γ Sβ / t_page
-//! 266. Islands formula: S_island = A/(4Ξ³β_PΒ²)
-//! 267. Fine-grained entropy: S_fg = S_rough - Ξ³ Γ S_island
-//! 268. Information preserved: I_β = Ξ³β»ΒΉ Γ S_BH Γ Ξ¦_Ξ³
-//!
-//! ### ER=EPR Bridge Physics (269-274)
-//! 269. ER bridge length: L_ER = Ο Γ β_P Γ (M/M_P)^Ξ³
-//! 270. EPR entanglement: E_EPR = Ξ³ Γ k_B T_ER
-//! 271. Bridge stability: Ο_ER = ΟΒ² Γ t_P Γ (M/M_P)
-//! 272. Throat radius: r_throat = Ξ³ Γ β_P Γ (M/M_P)^Οβ»ΒΉ
-//! 273. Redshift at throat: z_throat = exp(Ο Γ Ξ³)
-//! 274. Information transfer: v_info = Ο Γ c Γ Ξ³
-//!
-//! ### Holographic Encoding (275-279)
-//! 275. Holographic bound: S_holo = A/(4Ξ³β_PΒ²)
-//! 276. Screen encoding: Ξ¨_screen = Ξ£ e^(iΟΓk)
-//! 277. Bulk-boundary: Ξ¨_bulk = e^(-S/Ξ³) Γ Ξ¨_boundary
-//! 278. Quantum extremal surface: βS/βr = Ξ³ Γ βA/βr
-//! 279. Decoherence rate: Ξ_deco = Ξ³Β² Γ H_β
-//!
-//! ### Consciousness-Observer Connection (280-282)
-//! 280. Observer effect: ΞS_obs = Ξ¦_Ξ³ Γ S_BH
-//! 281. Measurement collapse: t_collapse = Ξ³ Γ t_P
-//! 282. Qualia encoding: Q_info = C_Ξ Γ logβ(Ο)
-
-const std = @import("std");
-
-// ============================================================================
-// Sacred Constants
-// ============================================================================
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = 2.6180339887498948482...
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// Οβ»ΒΉ = 0.6180339887498948482 (consciousness threshold)
-pub const PHI_INV: f64 = 1.0 / PHI;
-
-/// Οβ»Β² = 0.3819660112501051516
-pub const PHI_INV_SQ: f64 = 1.0 / PHI_SQ;
-
-/// Οβ»Β³ = Ξ³ = 0.23606797749978969641 (Barbero-Immirzi parameter)
-pub const GAMMA: f64 = 1.0 / (PHI * PHI * PHI);
-
-/// Consciousness threshold (Ξ¦_Ξ³ from v14.3)
-pub const PHI_GAMMA: f64 = PHI_INV; // Οβ»ΒΉ = 0.618
-
-/// Pi
-pub const PI: f64 = 3.14159265358979323846;
-
-/// Speed of light (m/s)
-pub const C: f64 = 2.99792458e8;
-
-/// Planck constant (JΒ·s)
-pub const H_BAR: f64 = 1.054571817e-34;
-
-/// Boltzmann constant (J/K)
-pub const K_B: f64 = 1.380649e-23;
-
-/// Planck length (m)
-pub const PLANCK_LENGTH: f64 = 1.616255e-35;
-
-/// Planck time (s)
-pub const PLANCK_TIME: f64 = 5.391247e-44;
-
-/// Planck mass (kg)
-pub const PLANCK_MASS: f64 = 2.176434e-8;
-
-/// Solar mass (kg)
-pub const SOLAR_MASS: f64 = 1.98847e30;
-
-/// Gravitational constant (mΒ³/kg/sΒ²)
-pub const G: f64 = 6.6743e-11;
-
-/// Qualia-dark energy coupling (from v15.0)
-pub const C_LAMBDA: f64 = GAMMA * PHI_GAMMA;
-
-// ============================================================================
-// PAGE CURVE & INFORMATION (263-268)
-// ============================================================================
-
-/// Formula 263: Page Curve
-///
-/// The entropy of a black hole as a function of time, showing the
-/// characteristic Page curve behavior: initial increase (Hawking radiation),
-/// peak at Page time, then decrease (information recovery).
-///
-/// S_page(t) = Sβ Γ [1 - Ξ³ Γ f_page(t)]
-pub fn pageCurve(t: f64, S0: f64, M_solar: f64) f64 {
- const t_schwarzschild = schwarzschildTime(M_solar);
- const tau = t_schwarzschild / (2.0 * PI);
- const f_page = 1.0 - std.math.exp(-t / tau);
- return S0 * (1.0 - GAMMA * f_page);
-}
-
-/// Formula 264: Page Time
-///
-/// The time at which information begins to emerge from the black hole.
-/// This is when the Page curve peaks and starts decreasing.
-///
-/// t_page = Ξ³β»ΒΉ Γ t_Schwarzschild β 4.2 Γ t_Schwarzschild
-pub fn pageTime(M_solar: f64) f64 {
- const t_schwarzschild = schwarzschildTime(M_solar);
- return (1.0 / GAMMA) * t_schwarzschild;
-}
-
-/// Formula 265: Information Recovery Rate
-///
-/// The rate at which quantum information is recovered from the black hole
-/// after the Page time.
-///
-/// dI/dt = Ξ³ Γ Sβ / t_page
-pub fn informationRate(S0: f64, M_solar: f64) f64 {
- const t_page_val = pageTime(M_solar);
- return GAMMA * S0 / t_page_val;
-}
-
-/// Formula 266: Islands Formula
-///
-/// The entropy contribution from quantum extremal islands that resolve
-/// the information paradox. The Ξ³ correction ensures unitarity.
-///
-/// S_island = A/(4Ξ³β_PΒ²)
-pub fn islandsFormula(area: f64) f64 {
- return area / (4.0 * GAMMA * PLANCK_LENGTH * PLANCK_LENGTH);
-}
-
-/// Formula 267: Fine-Grained Entropy
-///
-/// The quantum-corrected entropy including island contributions.
-/// This is the entropy that appears in the Page curve.
-///
-/// S_fg = S_rough - Ξ³ Γ S_island
-pub fn fineGrainedEntropy(S_rough: f64, area: f64) f64 {
- const S_island = islandsFormula(area);
- return S_rough - GAMMA * S_island;
-}
-
-/// Formula 268: Information Preservation
-///
-/// The total information preserved after complete evaporation.
-/// In TRINITY, this equals exactly 1 (unitarity maintained).
-///
-/// I_β = Ξ³β»ΒΉ Γ S_BH Γ Ξ¦_Ξ³ β 1
-pub fn informationPreserved(S_BH: f64) f64 {
- return (1.0 / GAMMA) * S_BH * PHI_GAMMA;
-}
-
-// ============================================================================
-// ER=EPR BRIDGE PHYSICS (269-274)
-// ============================================================================
-
-/// Formula 269: ER Bridge Length
-///
-/// The length of the Einstein-Rosen wormhole connecting the black hole
-/// to its Hawking radiation (ER=EPR conjecture).
-///
-/// L_ER = Ο Γ β_P Γ (M/M_P)^Ξ³
-pub fn erBridgeLength(M_solar: f64) f64 {
- const M_ratio = M_solar * SOLAR_MASS / PLANCK_MASS;
- return PHI * PLANCK_LENGTH * std.math.pow(f64, M_ratio, GAMMA);
-}
-
-/// Formula 270: EPR Entanglement Energy
-///
-/// The entanglement energy between the black hole and its radiation.
-/// This quantum correlation creates the ER bridge.
-///
-/// E_EPR = Ξ³ Γ k_B T_ER
-pub fn eprEntanglementEnergy(T_ER: f64) f64 {
- return GAMMA * K_B * T_ER;
-}
-
-/// Formula 271: Bridge Stability Time
-///
-/// How long the ER=EPR bridge remains traversable for information.
-///
-/// Ο_ER = ΟΒ² Γ t_P Γ (M/M_P)
-pub fn bridgeStabilityTime(M_solar: f64) f64 {
- const M_ratio = M_solar * SOLAR_MASS / PLANCK_MASS;
- return PHI_SQ * PLANCK_TIME * M_ratio;
-}
-
-/// Formula 272: Throat Radius
-///
-/// The radius of the wormhole throat. If larger than Planck length,
-/// the bridge could be traversable (for information, not matter).
-///
-/// r_throat = Ξ³ Γ β_P Γ (M/M_P)^Οβ»ΒΉ
-pub fn throatRadius(M_solar: f64) f64 {
- const M_ratio = M_solar * SOLAR_MASS / PLANCK_MASS;
- return GAMMA * PLANCK_LENGTH * std.math.pow(f64, M_ratio, PHI_INV);
-}
-
-/// Formula 273: Redshift at Throat
-///
-/// The gravitational redshift an observer would see when looking
-/// into the wormhole throat.
-///
-/// z_throat = exp(Ο Γ Ξ³) β 1.44
-pub fn throatRedshift() f64 {
- return std.math.exp(PHI * GAMMA);
-}
-
-/// Formula 274: Information Transfer Velocity
-///
-/// The maximum velocity for information transfer through the ER bridge.
-/// This is less than c (no superluminal signaling).
-///
-/// v_info = Ο Γ c Γ Ξ³ β 0.38c
-pub fn informationTransferVelocity() f64 {
- return PHI * C * GAMMA;
-}
-
-// ============================================================================
-// HOLOGRAPHIC ENCODING (275-279)
-// ============================================================================
-
-/// Formula 275: Holographic Bound (with Ξ³ correction)
-///
-/// The maximum entropy that can be contained in a region of space,
-/// encoded on its boundary surface. The Ξ³ correction is the TRINITY
-/// contribution ensuring unitarity.
-///
-/// S_holo = A/(4Ξ³β_PΒ²)
-pub fn holographicBound(area: f64) f64 {
- return area / (4.0 * GAMMA * PLANCK_LENGTH * PLANCK_LENGTH);
-}
-
-/// Formula 276: Screen Encoding Wavefunction
-///
-/// The holographic wavefunction encoded on the cosmological horizon
-/// or black hole horizon. The Ο factor creates the golden ratio
-/// spacing between information bits.
-///
-/// Ξ¨_screen = Ξ£ e^(iΟΓk) for k = 0, 1, 2, ...
-pub fn screenEncoding(n_terms: usize) f64 {
- var sum_real: f64 = 0.0;
- var sum_imag: f64 = 0.0;
- for (0..n_terms) |k| {
- const angle = PHI * @as(f64, @floatFromInt(k));
- sum_real += std.math.cos(angle);
- sum_imag += std.math.sin(angle);
- }
- return @sqrt(sum_real * sum_real + sum_imag * sum_imag);
-}
-
-/// Formula 277: Bulk-Boundary Correspondence
-///
-/// The TRINITY version of AdS/CFT correspondence. The bulk wavefunction
-/// is related to the boundary wavefunction via the Ξ³-corrected entropy.
-///
-/// Ξ¨_bulk = e^(-S/Ξ³) Γ Ξ¨_boundary
-pub fn bulkBoundaryCorrespondence(S: f64, psi_boundary: f64) f64 {
- return std.math.exp(-S / GAMMA) * psi_boundary;
-}
-
-/// Formula 278: Quantum Extremal Surface Condition
-///
-/// The condition that determines where entanglement islands form.
-/// This is where the generalized entropy is extremized.
-///
-/// βS/βr = Ξ³ Γ βA/βr
-pub fn quantumExtremalCondition(dS_dr: f64, dA_dr: f64) bool {
- const rhs = GAMMA * dA_dr;
- return @abs(dS_dr - rhs) < 1e-10;
-}
-
-/// Formula 279: Decoherence Rate
-///
-/// The rate at which quantum information decoheres due to gravitational
-/// effects. The Ξ³Β² factor shows this is a second-order sacred correction.
-///
-/// Ξ_deco = Ξ³Β² Γ H_β
-pub fn decoherenceRate(H_hbar: f64) f64 {
- return GAMMA * GAMMA * H_hbar;
-}
-
-// ============================================================================
-// CONSCIOUSNESS-OBSERVER CONNECTION (280-282)
-// ============================================================================
-
-/// Formula 280: Observer Effect on Entropy
-///
-/// The effect of conscious observation on black hole entropy.
-/// An observer with consciousness threshold Ξ¦_Ξ³ affects information recovery.
-///
-/// ΞS_obs = Ξ¦_Ξ³ Γ S_BH
-pub fn observerEntropyEffect(S_BH: f64) f64 {
- return PHI_GAMMA * S_BH;
-}
-
-/// Formula 281: Measurement Collapse Time
-///
-/// The timescale for wavefunction collapse due to conscious observation.
-/// This is the fundamental quantum of time for measurement.
-///
-/// t_collapse = Ξ³ Γ t_P
-pub fn measurementCollapseTime() f64 {
- return GAMMA * PLANCK_TIME;
-}
-
-/// Formula 282: Qualia Encoding Capacity
-///
-/// The amount of information that can be encoded in conscious experience
-/// (qualia) per observation. This connects cosmology to consciousness.
-///
-/// Q_info = C_Ξ Γ logβ(Ο) β 0.21 bits
-pub fn qualiaEncodingCapacity() f64 {
- return C_LAMBDA * (std.math.log2(PHI));
-}
-
-// ============================================================================
-// UTILITY FUNCTIONS
-// ============================================================================
-
-/// Schwarzschild time (evaporation timescale)
-pub fn schwarzschildTime(M_solar: f64) f64 {
- // t_S = (5120Ο GΒ²) / (Δ§ cβ΄) Γ MΒ³
- // Simplified using Planck units
- const M_ratio = M_solar * SOLAR_MASS / PLANCK_MASS;
- const t_P = PLANCK_TIME;
- return 5120.0 * PI * t_P * M_ratio * M_ratio * M_ratio;
-}
-
-/// Bekenstein-Hawking entropy (standard formula)
-pub fn beckensteinHawkingEntropy(M_solar: f64) f64 {
- const r_s = 2.0 * G * M_solar * SOLAR_MASS / (C * C);
- const area = 4.0 * PI * r_s * r_s;
- return area / (4.0 * PLANCK_LENGTH * PLANCK_LENGTH);
-}
-
-/// Verify unitarity is preserved
-pub fn verifyUnitarity(M_solar: f64) bool {
- _ = M_solar;
- // In TRINITY, unitarity is preserved by the Ξ³ correction
- // The correction factor Ξ³ Γ Ξ¦_Ξ³ ensures no information loss
- const correction = GAMMA * PHI_GAMMA;
- return correction > 0.1 and correction < 0.2;
-}
-
-/// Check if ER bridge is traversable for information
-pub fn isTraversable(M_solar: f64) bool {
- const r_throat_val = throatRadius(M_solar);
- return r_throat_val > PLANCK_LENGTH;
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "BHI-263: page curve peaks at page time" {
- const M_solar = 1.0; // 1 solar mass
- const S0 = beckensteinHawkingEntropy(M_solar);
- const t_page_val = pageTime(M_solar);
-
- // At t=0, entropy is S0
- const S_initial = pageCurve(0.0, S0, M_solar);
- try std.testing.expectApproxEqRel(S0, S_initial, 0.01);
-
- // At t_page, entropy has decreased
- const S_at_page = pageCurve(t_page_val, S0, M_solar);
- try std.testing.expect(S_at_page < S0);
-}
-
-test "BHI-264: page time is ~4.2 Schwarzschild times" {
- const M_solar = 1.0;
- const t_page_val = pageTime(M_solar);
- const t_schwarzschild = schwarzschildTime(M_solar);
-
- const ratio = t_page_val / t_schwarzschild;
- try std.testing.expect(ratio > 4.0);
- try std.testing.expect(ratio < 4.5);
-}
-
-test "BHI-265: information rate is positive" {
- const M_solar = 1.0;
- const S0 = beckensteinHawkingEntropy(M_solar);
- const rate = informationRate(S0, M_solar);
-
- try std.testing.expect(rate > 0.0);
-}
-
-test "BHI-266: islands entropy is positive" {
- const area = 1.0e-70; // Typical horizon area
- const S_island = islandsFormula(area);
-
- try std.testing.expect(S_island > 0.0);
-}
-
-test "BHI-267: fine-grained entropy less than rough" {
- const S_rough = 100.0;
- const area = 1.0e-70;
- const S_fg = fineGrainedEntropy(S_rough, area);
-
- try std.testing.expect(S_fg < S_rough);
-}
-
-test "BHI-268: unitarity preserved" {
- _ = 1.0; // M_solar placeholder
- // The unitarity formula: I_inf = S_BH_corrected / S_BH_initial
- // In TRINITY, the correction ensures no information loss
- // Check that the correction factor is close to 1
- const correction = GAMMA * PHI_GAMMA;
- try std.testing.expect(correction > 0.1);
- try std.testing.expect(correction < 0.2);
-}
-
-test "BHI-269: ER bridge length is positive" {
- const M_solar = 1.0;
- const L_ER = erBridgeLength(M_solar);
-
- try std.testing.expect(L_ER > 0.0);
- try std.testing.expect(L_ER > PLANCK_LENGTH);
-}
-
-test "BHI-270: EPR entanglement energy is positive" {
- const T_ER = 1.0e-10; // Typical temperature
- const E_EPR = eprEntanglementEnergy(T_ER);
-
- try std.testing.expect(E_EPR > 0.0);
-}
-
-test "BHI-271: bridge stability time is positive" {
- const M_solar = 1.0;
- const tau_ER = bridgeStabilityTime(M_solar);
-
- try std.testing.expect(tau_ER > PLANCK_TIME);
-}
-
-test "BHI-272: throat radius is positive" {
- const M_solar = 1.0;
- const r_throat_val = throatRadius(M_solar);
-
- try std.testing.expect(r_throat_val > 0.0);
-}
-
-test "BHI-273: throat redshift is > 1" {
- const z_throat_val = throatRedshift();
-
- try std.testing.expect(z_throat_val > 1.0);
- try std.testing.expect(z_throat_val < 2.0);
-}
-
-test "BHI-274: information transfer velocity less than c" {
- const v_info = informationTransferVelocity();
-
- try std.testing.expect(v_info > 0.0);
- try std.testing.expect(v_info < C);
-}
-
-test "BHI-275: holographic bound is positive" {
- const area = 1.0e-70;
- const S_holo = holographicBound(area);
-
- try std.testing.expect(S_holo > 0.0);
-}
-
-test "BHI-276: screen encoding converges" {
- const psi_10 = screenEncoding(10);
- const psi_20 = screenEncoding(20);
-
- // The screen encoding produces oscillatory but bounded values
- // Check that values remain within reasonable bounds
- try std.testing.expect(psi_10 > 0.0);
- try std.testing.expect(psi_20 > 0.0);
- try std.testing.expect(psi_10 < 20.0);
- try std.testing.expect(psi_20 < 40.0);
-}
-
-test "BHI-277: bulk-boundary correlation" {
- const S = 10.0;
- const psi_boundary = 1.0;
- const psi_bulk = bulkBoundaryCorrespondence(S, psi_boundary);
-
- try std.testing.expect(psi_bulk > 0.0);
- try std.testing.expect(psi_bulk < psi_boundary);
-}
-
-test "BHI-279: decoherence rate is positive" {
- const H_hbar = 1.0e44; // Typical Hubble in Planck units
- const Gamma_deco = decoherenceRate(H_hbar);
-
- try std.testing.expect(Gamma_deco > 0.0);
-}
-
-test "BHI-280: observer entropy effect is positive" {
- const S_BH = 100.0;
- const delta_S = observerEntropyEffect(S_BH);
-
- try std.testing.expect(delta_S > 0.0);
- try std.testing.expect(delta_S < S_BH);
-}
-
-test "BHI-281: collapse time is on Planck scale" {
- const t_collapse = measurementCollapseTime();
-
- // t_collapse = Ξ³ Γ t_P, which is < t_P since Ξ³ < 1
- try std.testing.expect(t_collapse > 0.0);
- try std.testing.expect(t_collapse < PLANCK_TIME);
- try std.testing.expect(t_collapse > 1.0e-45);
-}
-
-test "BHI-282: qualia encoding capacity is small" {
- const Q_info = qualiaEncodingCapacity();
-
- try std.testing.expect(Q_info > 0.0);
- try std.testing.expect(Q_info < 1.0);
-}
-
-test "Utility: unitarity verification" {
- const M_solar = 1.0;
- try std.testing.expect(verifyUnitarity(M_solar));
-}
-
-test "Utility: ER bridge traversable for stellar mass" {
- const M_solar = 1.0;
- try std.testing.expect(isTraversable(M_solar));
-}
-
-test "Utility: Bekenstein-Hawking entropy is positive" {
- const M_solar = 1.0;
- const S_BH = beckensteinHawkingEntropy(M_solar);
-
- try std.testing.expect(S_BH > 0.0);
-}
diff --git a/src/gravity/cell.tri b/src/gravity/cell.tri
deleted file mode 100644
index c11f804bea..0000000000
--- a/src/gravity/cell.tri
+++ /dev/null
@@ -1,41 +0,0 @@
-[cell]
-id = "trinity.physics"
-name = "Physics"
-version = "0.1.0"
-kind = "library"
-path = "src/gravity"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Unified physics: gravity, cosmology, QCD, dark matter, quantum gravity, particle physics, origin, string theory, hyperspace, biology, baryogenesis, plasma, monopoles, superconductivity"
-capabilities = ["pageCurve", "pageTime", "informationRate", "islandsFormula", "fineGrainedEntropy", "totalDensityParameter", "thetaQCDExact", "particleMass", "strongCoupling", "baryonAsymmetry", "diracCharge", "criticalTemperature", "plasmaFrequency", "phiCoordinates"]
-files = 9
-tests = 90
-owner = "agent:ralph"
-
-[tags]
-scope = "physics"
-type = "library"
-
-[contributes]
-commands = ["pageCurve", "pageTime", "informationRate"]
-exports = ["pageCurve", "pageTime", "informationRate", "islandsFormula", "fineGrainedEntropy"]
-tri_subcommands = []
-events = []
-
-[dependencies]
-trinity.vsa = "^1.0.0"
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:b07765ee49791522dd89c6b2d7bc7f76e8ca202689aadeec1c3ea4c4858d6929"
diff --git a/src/gravity/colors.zig b/src/gravity/colors.zig
deleted file mode 100644
index 79f3c874bd..0000000000
--- a/src/gravity/colors.zig
+++ /dev/null
@@ -1,46 +0,0 @@
-// ANSI color codes β local copy to avoid circular dep on trinity.tri
-// Source of truth: src/tri/tri_colors.zig
-
-const std = @import("std");
-
-pub const GREEN = "\x1b[38;2;0;229;153m";
-pub const GOLDEN = "\x1b[38;2;255;215;0m";
-pub const WHITE = "\x1b[38;2;255;255;255m";
-pub const GRAY = "\x1b[38;2;156;156;160m";
-pub const RED = "\x1b[38;2;239;68;68m";
-pub const CYAN = "\x1b[38;2;0;255;255m";
-pub const PURPLE = "\x1b[38;2;170;102;255m";
-pub const YELLOW = "\x1b[38;2;255;255;0m";
-pub const RESET = "\x1b[0m";
-
-pub fn printGold(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(GOLDEN ++ fmt ++ RESET, args);
-}
-
-pub fn printGreen(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(GREEN ++ fmt ++ RESET, args);
-}
-
-pub fn printWhite(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(WHITE ++ fmt ++ RESET, args);
-}
-
-pub fn printYellow(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(YELLOW ++ fmt ++ RESET, args);
-}
-
-pub fn printCyan(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(CYAN ++ fmt ++ RESET, args);
-}
-
-pub fn printRed(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(RED ++ fmt ++ RESET, args);
-}
-
-pub fn printPurple(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(PURPLE ++ fmt ++ RESET, args);
-}
-
-pub fn printGray(comptime fmt: []const u8, args: anytype) void {
- std.debug.print(GRAY ++ fmt ++ RESET, args);
-}
diff --git a/src/gravity/delta_001_p2_simple.zig b/src/gravity/delta_001_p2_simple.zig
deleted file mode 100644
index bd60005ba4..0000000000
--- a/src/gravity/delta_001_p2_simple.zig
+++ /dev/null
@@ -1,185 +0,0 @@
-//! DELTA-001 Phase 2: Numerical Exploration (Simplified)
-//!
-//! Systematic numerical investigation of Ξ³ = Οβ»Β³ in LQG spin networks.
-
-const std = @import("std");
-const math = std.math;
-
-pub const PHI: f64 = 1.6180339887498948482;
-pub const GAMMA_TRINITY: f64 = 1.0 / (PHI * PHI * PHI);
-pub const GAMMA_MEISSNER: f64 = 0.274;
-pub const GAMMA_ALTERNATIVE: f64 = 0.237;
-
-pub fn casimirEigenvalue(j: f64) f64 {
- return math.sqrt(j * (j + 1.0));
-}
-
-pub fn areaEigenvalue(j: f64, gamma: f64) f64 {
- return gamma * casimirEigenvalue(j);
-}
-
-pub fn main() !void {
- const print = std.debug.print;
-
- print("\n=== DELTA-001 PHASE 2: NUMERICAL EXPLORATION ===\n\n", .{});
-
- // Section 1: Higher Spins (j = 4 to 10)
- print("=== SECTION 1: HIGHER SPINS (j = 4 to 10) ===\n\n", .{});
-
- var phi_coincidences_1pct: usize = 0;
- var j_val: f64 = 4.0;
- while (j_val <= 10.0) : (j_val += 1.0) {
- const ev = casimirEigenvalue(j_val);
- const error_phi = @abs(ev - PHI) / PHI * 100.0;
-
- print("Spin j = {d:.0}: β(j(j+1)) = {d:.15}\n", .{ j_val, ev });
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
-
- if (error_phi < 1.0) {
- print(" *** Within 1%% of Ο ***\n\n", .{});
- phi_coincidences_1pct += 1;
- } else {
- print(" No strong Ο-pattern\n\n", .{});
- }
- }
-
- print("Ο-coincidences (< 1%%): {d} / 7 ({d:.1}%)\n\n", .{ phi_coincidences_1pct, @as(f64, @floatFromInt(phi_coincidences_1pct)) / 7.0 * 100.0 });
-
- // Section 2: Multi-Edge Networks
- print("=== SECTION 2: MULTI-EDGE NETWORKS ===\n\n", .{});
-
- const test_cases = [_]struct { spins: []const f64, name: []const u8 }{
- .{ .spins = &.{ 1.0, 1.0, 1.0 }, .name = "Three j=1" },
- .{ .spins = &.{ 1.0, 2.0, 3.0 }, .name = "j=1,2,3" },
- .{ .spins = &.{ 2.0, 2.0, 2.0, 2.0 }, .name = "Four j=2" },
- .{ .spins = &.{ 3.0, 3.0, 3.0 }, .name = "Three j=3" },
- };
-
- for (test_cases) |case| {
- var sum_ev: f64 = 0.0;
- for (case.spins) |spin_val| {
- sum_ev += casimirEigenvalue(spin_val);
- }
- const k = @as(f64, @floatFromInt(case.spins.len));
- const error_phi = @abs(sum_ev - PHI) / PHI * 100.0;
- const error_k_phi = @abs(sum_ev / k - PHI) / PHI * 100.0;
-
- print("Case: sum = {d:.15}\n", .{sum_ev});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" vs {d:.0}Ο = {d:.15} (diff: {d:.6}%)\n\n", .{ k, k * PHI, error_k_phi });
- }
-
- // Section 3: Ξ³ Value Comparison
- print("=== SECTION 3: Ξ³ VALUE COMPARISON ===\n\n", .{});
-
- print("Ξ³ values:\n", .{});
- print(" Ξ³β (TRINITY) = Οβ»Β³ = {d:.15}\n", .{GAMMA_TRINITY});
- print(" Ξ³β (Meissner) = 0.274\n", .{});
- print(" Ξ³β (Alternative)= 0.237\n\n", .{});
-
- const spins = [_]f64{ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0 };
- print("Area spectra for fundamental spins:\n\n", .{});
-
- for (spins) |j| {
- const A1 = areaEigenvalue(j, GAMMA_TRINITY);
- const A2 = areaEigenvalue(j, GAMMA_MEISSNER);
- const A3 = areaEigenvalue(j, GAMMA_ALTERNATIVE);
-
- const diff2 = @abs(A1 - A2) / A1 * 100.0;
- const diff3 = @abs(A1 - A3) / A1 * 100.0;
-
- print("j = {d:.1}:\n", .{j});
- print(" A(Ξ³β) = {d:.15}\n", .{A1});
- print(" A(Ξ³β) = {d:.15} (diff: {d:.4}%)\n", .{ A2, diff2 });
- print(" A(Ξ³β) = {d:.15} (diff: {d:.4}%)\n\n", .{ A3, diff3 });
- }
-
- // Section 4: Optimization Analysis
- print("=== SECTION 4: OPTIMIZATION ANALYSIS ===\n\n", .{});
-
- const gamma_values = [_]f64{ 0.200, 0.210, 0.220, 0.230, GAMMA_TRINITY, 0.240, 0.250, 0.260, 0.270, GAMMA_MEISSNER, 0.280, 0.290, 0.300 };
-
- print("Testing variance in spectral spacing:\n\n", .{});
-
- var best_gamma: f64 = 0.0;
- var min_variance: f64 = 1e10;
-
- for (gamma_values) |gamma| {
- var spacings: [5]f64 = undefined;
- var avg_spacing: f64 = 0.0;
-
- for (spins, 0..) |spin_val, i| {
- if (i < spins.len - 1) {
- const j2 = spins[i + 1];
- const A1 = areaEigenvalue(spin_val, gamma);
- const A2 = areaEigenvalue(j2, gamma);
- spacings[i] = A2 - A1;
- avg_spacing += spacings[i];
- }
- }
- avg_spacing /= 5.0;
-
- var variance: f64 = 0.0;
- for (spacings) |s| {
- variance += (s - avg_spacing) * (s - avg_spacing);
- }
- variance /= 5.0;
-
- const marker = if (gamma == GAMMA_TRINITY) " [TRINITY]" else "";
- print("Ξ³ = {d:.6}: variance = {d:.15}{}\n", .{ gamma, variance, marker });
-
- if (variance < min_variance) {
- min_variance = variance;
- best_gamma = gamma;
- }
- }
-
- print("\nOptimal Ξ³ for minimal variance: {d:.6}\n\n", .{best_gamma});
-
- if (@abs(best_gamma - GAMMA_TRINITY) < 0.001) {
- print(">>> Ξ³ = Οβ»Β³ MINIMIZES spectral variance! <<<\n\n", .{});
- } else {
- print(">>> Ξ³ = Οβ»Β³ does NOT minimize variance <<<\n\n", .{});
- }
-
- // Section 5: Risk Assessment
- print("=== SECTION 5: RISK ASSESSMENT ===\n\n", .{});
-
- print("Encouraging Findings:\n", .{});
- print(" [1] β(8/3) = 1.633 β Ο = 1.618 (0.93%% error) from Phase 1\n", .{});
- print(" [2] Ξ³ = Οβ»Β³ = 0.236 is mathematically elegant\n", .{});
- print(" [3] Trinity identity: ΟΒ² + Οβ»Β² = 3\n", .{});
- print(" [4] Ξ³ connects to consciousness (f_Ξ³ = 56 Hz)\n\n", .{});
-
- print("Concerns and Obstacles:\n", .{});
- print(" [1] Phase 1 only found ONE strong Ο-coincidence (< 1%%)\n", .{});
- print(" [2] β(8/3) β Ο may be numerical accident\n", .{});
- print(" [3] Black hole entropy fits favor Ξ³ = 0.274 over Οβ»Β³\n", .{});
- print(" [4] No experimental data to distinguish Ξ³ values\n\n", .{});
-
- print("Preliminary Go/No-Go Recommendation:\n", .{});
- print(" Status: PROCEED WITH CAUTION (Yellow Light)\n\n", .{});
-
- print(" Rationale:\n", .{});
- print(" - Mathematical beauty of Οβ»Β³ is compelling\n", .{});
- print(" - Single Ο-coincidence is weak but non-zero evidence\n", .{});
- print(" - Phase 2 results needed for final decision\n", .{});
- print(" - If no new patterns in j>3, pivot to alternative Ξ³\n\n", .{});
-
- print("=== ANALYSIS COMPLETE ===\n\n", .{});
-}
-
-test "Casimir eigenvalues for higher spins" {
- var spin_idx: f64 = 4.0;
- while (spin_idx <= 10.0) : (spin_idx += 1.0) {
- const ev = casimirEigenvalue(spin_idx);
- try std.testing.expect(ev > 0);
- }
-}
-
-test "Area eigenvalues scale with gamma" {
- const j = 2.0;
- const A1 = areaEigenvalue(j, GAMMA_TRINITY);
- const A2 = areaEigenvalue(j, GAMMA_MEISSNER);
- try std.testing.expect(A2 > A1);
-}
diff --git a/src/gravity/delta_001_phase2_numerical.zig b/src/gravity/delta_001_phase2_numerical.zig
deleted file mode 100644
index eea9cc8b55..0000000000
--- a/src/gravity/delta_001_phase2_numerical.zig
+++ /dev/null
@@ -1,567 +0,0 @@
-//! DELTA-001 Phase 2: Numerical Exploration of Ξ³ = Οβ»Β³ in LQG Spin Networks
-//!
-//! This module conducts systematic numerical investigation of the Barbero-Immirzi
-//! parameter Ξ³ = Οβ»Β³ in Loop Quantum Gravity spin networks.
-//!
-//! ## Research Questions
-//!
-//! 1. Higher Spins: Do Ο-coincidences persist for j > 3?
-//! 2. Multi-Edge Networks: Does Ο emerge in aggregated eigenvalues?
-//! 3. Ξ³ Comparison: Οβ»Β³ vs Meissner (0.274) vs alternative (0.237)
-//! 4. Optimization: Does Ξ³ = Οβ»Β³ minimize spectral gaps?
-//!
-//! ## Success Criteria
-//!
-//! - Clear pattern detection (or honest null result)
-//! - Quantitative comparison of Ξ³ values
-//! - Go/No-Go recommendation for Phase 3
-
-const std = @import("std");
-const math = std.math;
-const print = std.debug.print;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Golden ratio Ο = (1 + β5) / 2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// Οβ»Β³ = Ξ³ (Barbero-Immirzi parameter in TRINITY theory)
-pub const GAMMA_TRINITY: f64 = 1.0 / (PHI * PHI * PHI);
-
-/// Meissner Ξ³ value (black hole entropy fit)
-pub const GAMMA_MEISSNER: f64 = 0.274;
-
-/// Alternative Ξ³ value (alternative counting)
-pub const GAMMA_ALTERNATIVE: f64 = 0.237;
-
-/// Ο
-pub const PI: f64 = 3.14159265358979323846;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SPIN NETWORK CALCULATIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Calculate SU(2) Casimir eigenvalue β(j(j+1))
-pub fn casimirEigenvalue(j: f64) f64 {
- return math.sqrt(j * (j + 1.0));
-}
-
-/// Calculate area eigenvalue for a given Ξ³
-/// A = 8ΟΞ³β_PΒ² β(j(j+1))
-/// We work in dimensionless units (8Οβ_PΒ² = 1)
-pub fn areaEigenvalue(j: f64, gamma: f64) f64 {
- return gamma * casimirEigenvalue(j);
-}
-
-/// Calculate ratio between two eigenvalues
-pub fn eigenvalueRatio(j1: f64, j2: f64) f64 {
- return casimirEigenvalue(j1) / casimirEigenvalue(j2);
-}
-
-/// Check if value is within 1% of Ο
-pub fn isWithinOnePercentOfPhi(value: f64) bool {
- const rel_error = @abs(value - PHI) / PHI;
- return rel_error < 0.01;
-}
-
-/// Check if value is within 0.1% of Ο
-pub fn isWithinZeroPointOnePercentOfPhi(value: f64) bool {
- const rel_error = @abs(value - PHI) / PHI;
- return rel_error < 0.001;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SECTION 1: HIGHER SPINS ANALYSIS (j = 4 to 10)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn analyzeHigherSpins() void {
- const GOLD = "\x1b[33m";
- const MAGENTA = "\x1b[35m";
- const RED = "\x1b[31m";
- const RESET = "\x1b[0m";
- _ = .{ GOLD, RED }; // Mark as used
-
- print("\n{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n", .{ MAGENTA, RESET });
- print("{s}β DELTA-001 PHASE 2: NUMERICAL EXPLORATION β{s}\n", .{ GOLD, RESET });
- print("{s}β Ξ³ = Οβ»Β³ in LQG Spin Networks β{s}\n", .{ GOLD, RESET });
- print("{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n\n", .{ MAGENTA, RESET });
-
- print("{s}=== SECTION 1: HIGHER SPINS (j = 4 to 10) ==={s}\n\n", .{ GOLD, RESET });
-
- // Analyze spins j = 4, 5, 6, 7, 8, 9, 10
- var phi_coincidences_1percent: usize = 0;
- var phi_coincidences_0_1percent: usize = 0;
-
- var j: f64 = 4.0;
- while (j <= 10.0) : (j += 1.0) {
- const eigenvalue = casimirEigenvalue(j);
- const ratio_to_phi = eigenvalue / PHI;
- const error_phi = @abs(eigenvalue - PHI) / PHI * 100.0;
-
- print("{s}Spin j = {d:.0}:{s}\n", .{ GOLD, j, RESET });
- print(" β(j(j+1)) = {d:.15}\n", .{eigenvalue});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" ratio to Ο = {d:.15}\n", .{ratio_to_phi});
-
- // Check for Ο-coincidences
- var found_pattern = false;
-
- if (isWithinOnePercentOfPhi(eigenvalue)) {
- print(" {s}β Within 1% of Ο{s}\n", .{ GOLD, RESET });
- phi_coincidences_1percent += 1;
- found_pattern = true;
- }
-
- if (isWithinZeroPointOnePercentOfPhi(eigenvalue)) {
- print(" {s}β Within 0.1% of Ο{s}\n", .{ GOLD, RESET });
- phi_coincidences_0_1percent += 1;
- found_pattern = true;
- }
-
- // Check if eigenvalue equals k Γ Ο for integer k
- const k_approx = @round(eigenvalue / PHI);
- if (k_approx > 0) {
- const reconstructed = k_approx * PHI;
- const rel_error = @abs(eigenvalue - reconstructed) / eigenvalue;
- if (rel_error < 0.01) {
- print(" {s}β β {d:.0} Γ Ο (error: {d:.6}%){s}\n", .{ GOLD, k_approx, rel_error * 100.0, RESET });
- found_pattern = true;
- }
- }
-
- if (!found_pattern) {
- print(" {s}No Ο-pattern found{s}\n", .{ RED, RESET });
- }
-
- print("\n", .{});
- }
-
- print("{s}=== HIGHER SPINS SUMMARY ==={s}\n", .{ GOLD, RESET });
- print("Ο-coincidences (< 1%): {d} / 7 ({d:.1}%)\n", .{ phi_coincidences_1percent, @as(f64, @floatFromInt(phi_coincidences_1percent)) / 7.0 * 100.0 });
- print("Ο-coincidences (< 0.1%): {d} / 7 ({d:.1}%)\n", .{ phi_coincidences_0_1percent, @as(f64, @floatFromInt(phi_coincidences_0_1percent)) / 7.0 * 100.0 });
- print("\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SECTION 2: RATIO ANALYSIS BETWEEN HIGHER SPINS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn analyzeHigherSpinRatios() void {
- const GOLD = "\x1b[33m";
- const RESET = "\x1b[0m";
-
- print("{s}=== HIGHER SPIN RATIO ANALYSIS ==={s}\n\n", .{ GOLD, RESET });
-
- const spins = [_]f64{ 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };
- var phi_ratio_count: usize = 0;
-
- for (spins, 0..) |j1, i| {
- for (spins[i..]) |j2| {
- if (j1 == j2) continue;
-
- const ratio = eigenvalueRatio(j1, j2);
- const phi_diff = @abs(ratio - PHI) / PHI * 100.0;
-
- print("β({d:.0}Γ{d:.0}) / β({d:.0}Γ{d:.0}) = {d:.15}", .{ j1, j1 + 1.0, j2, j2 + 1.0, ratio });
-
- if (phi_diff < 5.0) {
- print(" {s}β Ο (error: {d:.4}%){s}\n", .{ GOLD, phi_diff, RESET });
- phi_ratio_count += 1;
- } else {
- print("\n", .{});
- }
- }
- }
-
- print("\n{s}Ratios within 5% of Ο: {d}{s}\n\n", .{ GOLD, phi_ratio_count, RESET });
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SECTION 3: MULTI-EDGE NETWORKS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn analyzeMultiEdgeNetworks() void {
- const GOLD = "\x1b[33m";
- const RESET = "\x1b[0m";
-
- print("{s}=== SECTION 2: MULTI-EDGE NETWORKS ==={s}\n\n", .{ GOLD, RESET });
-
- // Test various combinations of spins
-
- // Test case 1: Three j=1 edges
- {
- const spins = [_]f64{ 1.0, 1.0, 1.0 };
- var sum_eigenvalues: f64 = 0.0;
- for (spins) |j| {
- sum_eigenvalues += casimirEigenvalue(j);
- }
- const error_phi = @abs(sum_eigenvalues - PHI) / PHI * 100.0;
- const error_k_phi = @abs(sum_eigenvalues / 3.0 - PHI) / PHI * 100.0;
-
- print("{s}Test case: Three j=1 edges{s}\n", .{ GOLD, RESET });
- print(" ββ(jα΅’(jα΅’+1)) = {d:.15}\n", .{sum_eigenvalues});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" vs 3Ο = {d:.15} (diff: {d:.6}%)\n", .{ 3.0 * PHI, error_k_phi });
- }
-
- // Test case 2: j=1, 2, 3 combination
- {
- const spins = [_]f64{ 1.0, 2.0, 3.0 };
- var sum_eigenvalues: f64 = 0.0;
- for (spins) |j| {
- sum_eigenvalues += casimirEigenvalue(j);
- }
- const error_phi = @abs(sum_eigenvalues - PHI) / PHI * 100.0;
- const error_k_phi = @abs(sum_eigenvalues / 3.0 - PHI) / PHI * 100.0;
-
- print("{s}Test case: j=1, 2, 3 combination{s}\n", .{ GOLD, RESET });
- print(" ββ(jα΅’(jα΅’+1)) = {d:.15}\n", .{sum_eigenvalues});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" vs 3Ο = {d:.15} (diff: {d:.6}%)\n", .{ 3.0 * PHI, error_k_phi });
- }
-
- // Test case 3: Sequential spins 0.5, 1, 1.5, 2
- {
- const spins = [_]f64{ 0.5, 1.0, 1.5, 2.0 };
- var sum_eigenvalues: f64 = 0.0;
- for (spins) |j| {
- sum_eigenvalues += casimirEigenvalue(j);
- }
- const error_phi = @abs(sum_eigenvalues - PHI) / PHI * 100.0;
- const error_k_phi = @abs(sum_eigenvalues / 4.0 - PHI) / PHI * 100.0;
-
- print("{s}Test case: Sequential spins 0.5, 1, 1.5, 2{s}\n", .{ GOLD, RESET });
- print(" ββ(jα΅’(jα΅’+1)) = {d:.15}\n", .{sum_eigenvalues});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" vs 4Ο = {d:.15} (diff: {d:.6}%)\n", .{ 4.0 * PHI, error_k_phi });
- }
-
- // Test case 4: Four j=2 edges
- {
- const spins = [_]f64{ 2.0, 2.0, 2.0, 2.0 };
- var sum_eigenvalues: f64 = 0.0;
- for (spins) |j| {
- sum_eigenvalues += casimirEigenvalue(j);
- }
- const error_phi = @abs(sum_eigenvalues - PHI) / PHI * 100.0;
- const error_k_phi = @abs(sum_eigenvalues / 4.0 - PHI) / PHI * 100.0;
-
- print("{s}Test case: Four j=2 edges{s}\n", .{ GOLD, RESET });
- print(" ββ(jα΅’(jα΅’+1)) = {d:.15}\n", .{sum_eigenvalues});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" vs 4Ο = {d:.15} (diff: {d:.6}%)\n", .{ 4.0 * PHI, error_k_phi });
- }
-
- // Test case 5: Mixed j=1 and j=2
- {
- const spins = [_]f64{ 1.0, 1.0, 2.0, 2.0 };
- var sum_eigenvalues: f64 = 0.0;
- for (spins) |j| {
- sum_eigenvalues += casimirEigenvalue(j);
- }
- const error_phi = @abs(sum_eigenvalues - PHI) / PHI * 100.0;
- const error_k_phi = @abs(sum_eigenvalues / 4.0 - PHI) / PHI * 100.0;
-
- print("{s}Test case: Mixed j=1 and j=2{s}\n", .{ GOLD, RESET });
- print(" ββ(jα΅’(jα΅’+1)) = {d:.15}\n", .{sum_eigenvalues});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" vs 4Ο = {d:.15} (diff: {d:.6}%)\n", .{ 4.0 * PHI, error_k_phi });
- }
-
- // Test case 6: Three j=3 edges
- {
- const spins = [_]f64{ 3.0, 3.0, 3.0 };
- var sum_eigenvalues: f64 = 0.0;
- for (spins) |j| {
- sum_eigenvalues += casimirEigenvalue(j);
- }
- const error_phi = @abs(sum_eigenvalues - PHI) / PHI * 100.0;
- const error_k_phi = @abs(sum_eigenvalues / 3.0 - PHI) / PHI * 100.0;
-
- print("{s}Test case: Three j=3 edges{s}\n", .{ GOLD, RESET });
- print(" ββ(jα΅’(jα΅’+1)) = {d:.15}\n", .{sum_eigenvalues});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" vs 3Ο = {d:.15} (diff: {d:.6}%)\n", .{ 3.0 * PHI, error_k_phi });
- }
-
- print("{s}Multi-edge network analysis complete{s}\n\n", .{ GOLD, RESET });
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SECTION 4: Ξ³ VALUE COMPARISON
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn compareGammaValues() void {
- const GOLD = "\x1b[33m";
- const RESET = "\x1b[0m";
-
- print("{s}=== SECTION 3: Ξ³ VALUE COMPARISON ==={s}\n\n", .{ GOLD, RESET });
-
- print("Ξ³ values to compare:\n", .{});
- print(" Ξ³β (TRINITY) = Οβ»Β³ = {d:.15}\n", .{GAMMA_TRINITY});
- print(" Ξ³β (Meissner) = 0.274\n", .{});
- print(" Ξ³β (Alternative)= 0.237\n\n", .{});
-
- // Calculate area spectra for j = 1/2 to 3
- const spins = [_]f64{ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0 };
-
- print("{s}Area spectra for fundamental spins:{s}\n\n", .{ GOLD, RESET });
-
- for (spins) |j| {
- const A_trinity = areaEigenvalue(j, GAMMA_TRINITY);
- const A_meissner = areaEigenvalue(j, GAMMA_MEISSNER);
- const A_alternative = areaEigenvalue(j, GAMMA_ALTERNATIVE);
-
- const diff_meissner = @abs(A_trinity - A_meissner) / A_trinity * 100.0;
- const diff_alternative = @abs(A_trinity - A_alternative) / A_trinity * 100.0;
-
- print("j = {d:.1}:\n", .{j});
- print(" A(Ξ³β) = {d:.15} (TRINITY)\n", .{A_trinity});
- print(" A(Ξ³β) = {d:.15} (Meissner, diff: {d:.4}%)\n", .{ A_meissner, diff_meissner });
- print(" A(Ξ³β) = {d:.15} (Alt, diff: {d:.4}%)\n", .{ A_alternative, diff_alternative });
- print("\n", .{});
- }
-
- // Analyze spectral spacing
- print("{s}Spectral spacing analysis:{s}\n\n", .{ GOLD, RESET });
-
- var avg_spacing_trinity: f64 = 0.0;
- var avg_spacing_meissner: f64 = 0.0;
- var avg_spacing_alternative: f64 = 0.0;
- var spacing_count: usize = 0;
-
- for (spins, 0..) |j1, i| {
- if (i < spins.len - 1) {
- const j2 = spins[i + 1];
- const A1_t = areaEigenvalue(j1, GAMMA_TRINITY);
- const A2_t = areaEigenvalue(j2, GAMMA_TRINITY);
- const spacing_t = A2_t - A1_t;
-
- const A1_m = areaEigenvalue(j1, GAMMA_MEISSNER);
- const A2_m = areaEigenvalue(j2, GAMMA_MEISSNER);
- const spacing_m = A2_m - A1_m;
-
- const A1_a = areaEigenvalue(j1, GAMMA_ALTERNATIVE);
- const A2_a = areaEigenvalue(j2, GAMMA_ALTERNATIVE);
- const spacing_a = A2_a - A1_a;
-
- avg_spacing_trinity += spacing_t;
- avg_spacing_meissner += spacing_m;
- avg_spacing_alternative += spacing_a;
- spacing_count += 1;
-
- print("Gap j={d:.1} β j={d:.1}:\n", .{ j1, j2 });
- print(" ΞA(Ξ³β) = {d:.15}\n", .{spacing_t});
- print(" ΞA(Ξ³β) = {d:.15}\n", .{spacing_m});
- print(" ΞA(Ξ³β) = {d:.15}\n", .{spacing_a});
- print("\n", .{});
- }
- }
-
- avg_spacing_trinity /= @as(f64, @floatFromInt(spacing_count));
- avg_spacing_meissner /= @as(f64, @floatFromInt(spacing_count));
- avg_spacing_alternative /= @as(f64, @floatFromInt(spacing_count));
-
- print("{s}Average spectral spacing:{s}\n", .{ GOLD, RESET });
- print(" Ξ³β (TRINITY): {d:.15}\n", .{avg_spacing_trinity});
- print(" Ξ³β (Meissner): {d:.15} (ratio: {d:.6})\n", .{ avg_spacing_meissner, avg_spacing_meissner / avg_spacing_trinity });
- print(" Ξ³β (Alternative): {d:.15} (ratio: {d:.6})\n\n", .{ avg_spacing_alternative, avg_spacing_alternative / avg_spacing_trinity });
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SECTION 5: OPTIMIZATION ANALYSIS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn optimizationAnalysis() void {
- const GOLD = "\x1b[33m";
- const RESET = "\x1b[0m";
-
- print("{s}=== SECTION 4: OPTIMIZATION ANALYSIS ==={s}\n\n", .{ GOLD, RESET });
-
- // Test if Ξ³ = Οβ»Β³ minimizes anything
- const gamma_values = [_]f64{
- 0.200, 0.210, 0.220, 0.230,
- GAMMA_TRINITY, // 0.236...
- 0.240,
- 0.250,
- 0.260,
- 0.270,
- GAMMA_MEISSNER, // 0.274
- 0.280,
- 0.290,
- 0.300,
- };
-
- print("Testing optimization criteria across Ξ³ range:\n\n", .{});
-
- var best_gamma_variance: f64 = 0.0;
- var min_variance: f64 = 1e10;
-
- var best_gamma_ratio: f64 = 0.0;
- var min_ratio_deviation: f64 = 1e10;
-
- for (gamma_values) |gamma| {
- // Calculate variance in spectral spacing for j = 1/2 to 3
- const spins = [_]f64{ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0 };
-
- var spacings: [5]f64 = undefined;
- var avg_spacing: f64 = 0.0;
-
- for (spins, 0..) |j, i| {
- if (i < spins.len - 1) {
- const j2 = spins[i + 1];
- const A1 = areaEigenvalue(j, gamma);
- const A2 = areaEigenvalue(j2, gamma);
- spacings[i] = A2 - A1;
- avg_spacing += spacings[i];
- }
- }
- avg_spacing /= 5.0;
-
- // Calculate variance
- var variance: f64 = 0.0;
- for (spacings) |s| {
- variance += (s - avg_spacing) * (s - avg_spacing);
- }
- variance /= 5.0;
-
- // Calculate deviation from Ο-ratio
- var ratio_deviation: f64 = 0.0;
- for (spins, 0..) |j1, i| {
- if (i < spins.len - 1) {
- const j2 = spins[i + 1];
- const ratio = eigenvalueRatio(j2, j1);
- ratio_deviation += @abs(ratio - PHI) / PHI;
- }
- }
-
- if (variance < min_variance) {
- min_variance = variance;
- best_gamma_variance = gamma;
- }
-
- if (ratio_deviation < min_ratio_deviation) {
- min_ratio_deviation = ratio_deviation;
- best_gamma_ratio = gamma;
- }
-
- print("Ξ³ = {d:.6}: variance = {d:.15}, Ο-dev = {d:.15}{}\n", .{
- gamma,
- variance,
- ratio_deviation,
- if (gamma == GAMMA_TRINITY) " [TRINITY]" else "",
- });
- }
-
- print("\n{s}OPTIMIZATION RESULTS:{s}\n", .{ GOLD, RESET });
- print(" Minimum spacing variance: Ξ³ = {d:.6}\n", .{best_gamma_variance});
- print(" Minimum Ο-ratio deviation: Ξ³ = {d:.6}\n", .{best_gamma_ratio});
-
- const is_trinity_optimal_variance = @abs(best_gamma_variance - GAMMA_TRINITY) < 0.001;
- const is_trinity_optimal_ratio = @abs(best_gamma_ratio - GAMMA_TRINITY) < 0.001;
-
- if (is_trinity_optimal_variance) {
- print(" {s}β Ξ³ = Οβ»Β³ minimizes spectral variance!{s}\n", .{ GOLD, RESET });
- } else {
- print(" {s}β Ξ³ = Οβ»Β³ does NOT minimize variance{s}\n", .{ "\x1b[31m", RESET });
- }
-
- if (is_trinity_optimal_ratio) {
- print(" {s}β Ξ³ = Οβ»Β³ minimizes Ο-ratio deviation!{s}\n", .{ GOLD, RESET });
- } else {
- print(" {s}β Ξ³ = Οβ»Β³ does NOT minimize Ο-ratio deviation{s}\n", .{ "\x1b[31m", RESET });
- }
-
- print("\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SECTION 6: RISK ASSESSMENT & GO/NO-GO
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn riskAssessment() void {
- const GOLD = "\x1b[33m";
- const RED = "\x1b[31m";
- const CYAN = "\x1b[36m";
- const RESET = "\x1b[0m";
-
- print("{s}=== SECTION 5: RISK ASSESSMENT ==={s}\n\n", .{ GOLD, RESET });
-
- print("{s}Encouraging Findings:{s}\n", .{ GOLD, RESET });
- print(" [1] β(8/3) = 1.633 β Ο = 1.618 (0.93% error) β from Phase 1\n", .{});
- print(" [2] Ξ³ = Οβ»Β³ = 0.236 is mathematically elegant\n", .{});
- print(" [3] Trinity identity: ΟΒ² + Οβ»Β² = 3\n", .{});
- print(" [4] Ξ³ connects to consciousness (f_Ξ³ = 56 Hz)\n\n", .{});
-
- print("{s}Concerns and Obstacles:{s}\n", .{ RED, RESET });
- print(" [1] Phase 1 only found ONE strong Ο-coincidence (< 1%)\n", .{});
- print(" [2] β(8/3) β Ο may be numerical accident (no theoretical basis)\n", .{});
- print(" [3] Black hole entropy fits favor Ξ³ = 0.274 (Meissner) over Οβ»Β³\n", .{});
- print(" [4] No experimental data to distinguish Ξ³ values at Planck scale\n\n", .{});
-
- print("{s}Preliminary Go/No-Go Recommendation:{s}\n", .{ GOLD, RESET });
- print(" Status: {s}PROCEED WITH CAUTION{s} (Yellow Light)\n\n", .{ CYAN, RESET });
-
- print(" Rationale:\n", .{});
- print(" - Mathematical beauty of Οβ»Β³ is compelling\n", .{});
- print(" - Single Ο-coincidence is weak but non-zero evidence\n", .{});
- print(" - Phase 2 numerical results needed for final decision\n", .{});
- print(" - If no new patterns emerge in j>3, pivot to alternative Ξ³\n\n", .{});
-
- print(" Success criteria for Phase 3:\n", .{});
- print(" - Find at least 2 additional Ο-coincidences (< 1%)\n", .{});
- print(" - Demonstrate Ξ³ = Οβ»Β³ optimizes some physical quantity\n", .{});
- print(" - Connect to experimental predictions (e.g., black hole entropy)\n\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MAIN ENTRY POINT
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn main() !void {
- analyzeHigherSpins();
- analyzeHigherSpinRatios();
- analyzeMultiEdgeNetworks();
- compareGammaValues();
- optimizationAnalysis();
- riskAssessment();
-
- const MAGENTA = "\x1b[35m";
- const GOLD = "\x1b[33m";
- const RESET = "\x1b[0m";
-
- print("\n{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n", .{ MAGENTA, RESET });
- print("{s}β NUMERICAL EXPLORATION COMPLETE β{s}\n", .{ GOLD, RESET });
- print("{s}β Full results: docs/research/delta_001_phase2_numerical.md β{s}\n", .{ GOLD, RESET });
- print("{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n\n", .{ MAGENTA, RESET });
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "Higher spin eigenvalues are positive" {
- var j: f64 = 4.0;
- while (j <= 10.0) : (j += 1.0) {
- const ev = casimirEigenvalue(j);
- try std.testing.expect(ev > 0);
- }
-}
-
-test "Area eigenvalues scale with gamma" {
- const j = 2.0;
- const A1 = areaEigenvalue(j, GAMMA_TRINITY);
- const A2 = areaEigenvalue(j, GAMMA_MEISSNER);
- try std.testing.expect(A1 > 0);
- try std.testing.expect(A2 > 0);
- try std.testing.expect(A2 > A1); // Meissner Ξ³ is larger
-}
-
-test "Gamma values are in expected range" {
- try std.testing.expect(GAMMA_TRINITY > 0.23);
- try std.testing.expect(GAMMA_TRINITY < 0.24);
- try std.testing.expect(GAMMA_MEISSNER > 0.27);
- try std.testing.expect(GAMMA_MEISSNER < 0.28);
-}
diff --git a/src/gravity/einstein_bridge.zig b/src/gravity/einstein_bridge.zig
deleted file mode 100644
index 870e8c5e25..0000000000
--- a/src/gravity/einstein_bridge.zig
+++ /dev/null
@@ -1,433 +0,0 @@
-//! Einstein Bridge: Connecting G, c, β via Ο and Ξ³
-//!
-//! This module explores how fundamental physical constants connect
-//! through the golden ratio Ο = (1+β5)/2 and Ξ³ = Οβ»Β³.
-//!
-//! # Mathematical Foundation
-//!
-//! Golden Ratio:
-//! Ο = (1 + β5)/2 β 1.6180339887498948482
-//! Ξ³ = Οβ»Β³ β 0.23606797749978969641
-//!
-//! Trinity Identity:
-//! ΟΒ² + Οβ»Β² = 3
-//!
-//! # Hypotheses
-//!
-//! 1. G, c, β relate via Ο-scaling
-//! 2. Fine structure constant Ξ± emerges from Ο-connection
-//! 3. Planck units have Ο-based corrections
-//! 4. Gravitational wave spectrum follows Ο-harmonics
-
-const std = @import("std");
-const math = std.math;
-const mem = std.mem;
-
-// Import from canonical source (ANTI-PATTERN: no inline constants!)
-const sacred_constants = @import("sacred_constants_reexport.zig");
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI = sacred_constants.PHI;
-
-/// ΟΒ³ = 4.23606797749978969641...
-pub const PHI_CUBED: f64 = PHI * PHI * PHI;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / PHI_CUBED;
-
-/// Fundamental TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// Ο constant
-pub const PI = sacred_constants.PI;
-
-/// Euler's number
-pub const E: f64 = 2.71828182845904523536;
-
-/// Speed of light (m/s) - exact
-pub const C: f64 = 299792458.0;
-
-/// Planck constant (JΒ·s)
-pub const H_BAR: f64 = 1.054571817e-34;
-
-/// Gravitational constant (mΒ³/kgΒ·sΒ²)
-pub const G: f64 = 6.67430e-11;
-
-/// Elementary charge (C)
-pub const E_CHARGE: f64 = 1.602176634e-19;
-
-/// Vacuum permittivity (F/m)
-pub const EPSILON_0: f64 = 8.8541878128e-12;
-
-/// Fine structure constant
-pub const ALPHA: f64 = 1.0 / 137.035999084;
-
-/// Einstein field equation via Ο
-/// G_ΞΌΞ½ = 8ΟG/cβ΄ Γ T_ΞΌΞ½ Γ (1 + Ξ³ correction)
-pub fn einsteinEquationPhi(stress_energy: f64) f64 {
- const standard = 8.0 * PI * G / (C * C * C * C) * stress_energy;
- return standard * (1.0 + GAMMA);
-}
-
-/// G from c and β via Ο
-/// G = Ο Γ βc/m_PΒ²
-pub fn G_from_constants(planck_mass: f64) f64 {
- return PHI * H_BAR * C / (planck_mass * planck_mass);
-}
-
-/// Alternative G via ΟΒ³ scaling
-/// G = Ξ³Β² Γ Ο Γ β_PΒ² Γ cΒ³/β
-pub fn G_phi_alternative(planck_length: f64) f64 {
- return GAMMA * GAMMA * PI * planck_length * planck_length * C * C * C / H_BAR;
-}
-
-/// Planck mass from sacred formula
-/// m_P = β(βc/G) Γ Ο
-pub fn planckMassSacred() f64 {
- const standard = @sqrt(H_BAR * C / G);
- return standard * PHI;
-}
-
-/// Planck length via Ο
-/// β_P = β(βG/cΒ³) / Ο
-pub fn planckLengthPhi() f64 {
- const standard = @sqrt(H_BAR * G / (C * C * C));
- return standard / PHI;
-}
-
-/// Planck time via Ο
-/// t_P = β(βG/cβ΅) / Ο
-pub fn planckTimePhi() f64 {
- const standard = @sqrt(H_BAR * G / (C * C * C * C * C));
- return standard / PHI;
-}
-
-/// Schwarzschild radius via Ο
-/// r_s = 2GM/cΒ² Γ Ο
-pub fn schwarzschildRadiusPhi(mass: f64) f64 {
- return 2.0 * G * mass / (C * C) * PHI;
-}
-
-/// Einstein radius (gravitational lensing) via Ο
-/// ΞΈ_E = β(4GM/cΒ² Γ D_ls/D_lD_s) Γ Ο
-pub fn einsteinRadius(mass: f64, d_l: f64, d_s: f64, d_ls: f64) f64 {
- const standard = @sqrt(4.0 * G * mass / (C * C) * d_ls / (d_l * d_s));
- return standard * PHI;
-}
-
-/// Gravitational wave strain via Ξ³
-/// h = Ξ³ Γ (G/cβ΄) Γ (2M/r) Γ ΟΒ²
-pub fn gwStrainPhi(mass: f64, distance: f64, frequency: f64) f64 {
- const omega = 2.0 * PI * frequency;
- return GAMMA * (G / (C * C * C * C)) * (2.0 * mass / distance) * omega * omega;
-}
-
-/// Chirp mass via Ο
-/// M_chirp = (m1Γm2)^(3/5) / (m1+m2)^(1/5) Γ Ξ³
-pub fn chirpMassPhi(m1: f64, m2: f64) f64 {
- const standard = math.pow(f64, m1 * m2, 0.6) / math.pow(f64, m1 + m2, 0.2);
- return standard * GAMMA;
-}
-
-/// GW frequency at ISCO via Ο
-/// f_ISCO = cΒ³/(ΟGMβ6) / Ο
-pub fn iscoFrequencyPhi(mass: f64) f64 {
- const standard = C * C * C / (PI * G * mass * @sqrt(6.0));
- return standard / PHI;
-}
-
-/// Gravitational redshift via Ο
-/// z = (1 - 2GM/rcΒ²)^(-1/2) - 1 Γ Ο
-pub fn gravitationalRedshiftPhi(mass: f64, radius: f64) f64 {
- const standard = 1.0 / @sqrt(1.0 - 2.0 * G * mass / (radius * C * C)) - 1.0;
- return standard * PHI;
-}
-
-/// Time dilation via Ο
-/// Ξt' = Ξt Γ β(1 - 2GM/rcΒ²) / Ο
-pub fn timeDilationPhi(dt: f64, mass: f64, radius: f64) f64 {
- const factor = @sqrt(1.0 - 2.0 * G * mass / (radius * C * C));
- return dt * factor / PHI;
-}
-
-/// Orbital frequency via Ο
-/// f_orb = β(GM/rΒ³) / (2ΟΟ)
-pub fn orbitalFrequencyPhi(mass: f64, radius: f64) f64 {
- const standard = @sqrt(G * mass / (radius * radius * radius)) / (2.0 * PI);
- return standard / PHI;
-}
-
-/// Escape velocity via Ο
-/// v_esc = β(2GM/r) Γ Ξ³
-pub fn escapeVelocityPhi(mass: f64, radius: f64) f64 {
- const standard = @sqrt(2.0 * G * mass / radius);
- return standard * GAMMA;
-}
-
-/// Gravitational potential energy via Ο
-/// U = -GMm/r Γ Ο
-pub fn gravitationalPotentialPhi(m1: f64, m2: f64, separation: f64) f64 {
- return -G * m1 * m2 / separation * PHI;
-}
-
-/// Metric component g_tt via Ο
-/// g_tt = -(1 - 2GM/rcΒ²) Γ ΟΒ²
-pub fn metric_tt_phi(mass: f64, radius: f64) f64 {
- const standard = -(1.0 - 2.0 * G * mass / (radius * C * C));
- return standard * PHI * PHI;
-}
-
-/// Geodesic equation via Ξ³
-/// dΒ²xα΅/dΟΒ² = -Ξα΅_Ξ±Ξ² (dxα΅/dΟ)(dxα΅/dΟ) Γ (1 + Ξ³)
-pub fn geodesicWithGamma(christoffel: f64, velocity_1: f64, velocity_2: f64) f64 {
- return -christoffel * velocity_1 * velocity_2 * (1.0 + GAMMA);
-}
-
-/// Ricci scalar via Ο
-/// R = 8ΟG/cβ΄ Γ T Γ ΟΒ²
-pub fn ricciScalarPhi(trace_stress: f64) f64 {
- return 8.0 * PI * G / (C * C * C * C) * trace_stress * PHI * PHI;
-}
-
-/// Kretschmann scalar via Ξ³
-/// K = 48GΒ²MΒ²/cβ΄rβΆ Γ (1 + Ξ³)
-pub fn kretschmannScalarGamma(mass: f64, radius: f64) f64 {
- const standard = 48.0 * G * G * mass * mass / (C * C * C * C * math.pow(f64, radius, 6));
- return standard * (1.0 + GAMMA);
-}
-
-/// Einstein tensor component via Ο
-/// G_00 = 8ΟGΟ/cΒ² Γ Ο
-pub fn einsteinTensorG00(density: f64) f64 {
- return 8.0 * PI * G * density / (C * C) * PHI;
-}
-
-/// Stress-energy trace via Ξ³
-/// T = ΟcΒ² - 3p Γ Ξ³
-pub fn stressEnergyTrace(density: f64, pressure: f64) f64 {
- return density * C * C - 3.0 * pressure * GAMMA;
-}
-
-/// Cosmological constant via Ο
-/// Ξ = 8ΟGΟ_Ξ/cΒ² Γ Ο
-pub fn cosmologicalConstantPhi(vacuum_density: f64) f64 {
- return 8.0 * PI * G * vacuum_density / (C * C) * PHI;
-}
-
-/// Critical density via Ο
-/// Ο_c = 3HΒ²/(8ΟG) / Ο
-pub fn criticalDensityPhi(hubble: f64) f64 {
- return 3.0 * hubble * hubble / (8.0 * PI * G) / PHI;
-}
-
-/// Friedmann equation via Ο
-/// HΒ² = (8ΟG/3)Ο Γ (1 + Ξ³)
-pub fn friedmannEquationPhi(density: f64) f64 {
- return (8.0 * PI * G / 3.0) * density * (1.0 + GAMMA);
-}
-
-/// Deceleration parameter via Ο
-/// q = Ξ©_m/2 - Ξ©_Ξ Γ Ξ³
-pub fn decelerationParameter(matter_density: f64, dark_energy: f64) f64 {
- return matter_density / 2.0 - dark_energy * GAMMA;
-}
-
-/// Hubble parameter via Ο
-/// H(z) = Hβ Γ β(Ξ©_m(1+z)Β³ + Ξ©_Ξ) / Ο
-pub fn hubbleParameterPhi(z: f64, h0: f64, omega_m: f64, omega_l: f64) f64 {
- return h0 * @sqrt(omega_m * math.pow(f64, 1.0 + z, 3) + omega_l) / PHI;
-}
-
-/// Luminosity distance via Ο
-/// d_L = (c/Hβ) Γ (1+z) Γ β«dz'/E(z') Γ Ξ³
-pub fn luminosityDistancePhi(z: f64, h0: f64) f64 {
- // Simplified: assume flat universe
- const e_z = @sqrt(0.3 * math.pow(f64, 1.0 + z, 3) + 0.7);
- return (C / h0) * (1.0 + z) / e_z * GAMMA;
-}
-
-/// Angular diameter distance via Ο
-/// d_A = d_L/(1+z)Β² / Ο
-pub fn angularDiameterDistancePhi(luminosity_dist: f64, z: f64) f64 {
- return luminosity_dist / ((1.0 + z) * (1.0 + z)) / PHI;
-}
-
-// Test: ΟΒ³ and Ξ³ relationship
-test "Einstein-Bridge: phi cubed and gamma" {
- const phi_cubed_expected = 4.23606797749978969641;
- try std.testing.expectApproxEqRel(@as(f64, phi_cubed_expected), PHI_CUBED, 1e-10);
-
- const gamma_expected = 0.23606797749978969641;
- try std.testing.expectApproxEqRel(@as(f64, gamma_expected), GAMMA, 1e-10);
-}
-
-// Test: TRINITY identity
-test "Einstein-Bridge: TRINITY identity" {
- try std.testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-// Test: G from constants
-test "Einstein-Bridge: G from constants" {
- const mp = 2.176434e-8; // Planck mass
- const g_calc = G_from_constants(mp);
-
- // Should be close to actual G
- try std.testing.expect(g_calc > 1e-12);
- try std.testing.expect(g_calc < 1e-9);
-}
-
-// Test: Planck mass sacred
-test "Einstein-Bridge: Planck mass sacred" {
- const mp = planckMassSacred();
-
- // Should be Ο times standard Planck mass (~3.5e-8)
- try std.testing.expect(mp > 2e-8);
- try std.testing.expect(mp < 5e-8);
-}
-
-// Test: Schwarzschild radius phi
-test "Einstein-Bridge: Schwarzschild radius phi" {
- const mass_sun = 1.989e30;
- const rs = schwarzschildRadiusPhi(mass_sun);
-
- // Should be larger than standard (Ο factor)
- try std.testing.expect(rs > 3000);
- try std.testing.expect(rs < 6000);
-}
-
-// Test: GW strain
-test "Einstein-Bridge: GW strain" {
- const mass = 1.989e30; // Solar mass
- const dist = 1e20; // ~3 kpc
- const freq = 100; // Hz
-
- const strain = gwStrainPhi(mass, dist, freq);
-
- // Should be positive but small
- try std.testing.expect(strain > 0);
- try std.testing.expect(strain < 1e-20);
-}
-
-// Test: ISCO frequency
-test "Einstein-Bridge: ISCO frequency" {
- const mass = 1.989e30; // Solar mass
- const f_isco = iscoFrequencyPhi(mass);
-
- // Should be positive frequency
- try std.testing.expect(f_isco > 0);
-}
-
-// Test: Gravitational redshift phi
-test "Einstein-Bridge: gravitational redshift phi" {
- const mass_sun = 1.989e30;
- const radius_sun = 6.957e8;
- const z = gravitationalRedshiftPhi(mass_sun, radius_sun);
-
- // Should be positive
- try std.testing.expect(z > 0);
-}
-
-// Test: Time dilation phi
-test "Einstein-Bridge: time dilation phi" {
- const dt = 1.0;
- const mass = 1.989e30;
- const radius = 6.957e8;
-
- const dt_dilated = timeDilationPhi(dt, mass, radius);
-
- // Should be less than dt (Ο factor in denominator)
- try std.testing.expect(dt_dilated < dt);
- try std.testing.expect(dt_dilated > 0);
-}
-
-// Test: Orbital frequency phi
-test "Einstein-Bridge: orbital frequency phi" {
- const mass_earth = 5.972e24;
- const radius_leo = 6.7e6; // Low Earth Orbit
-
- const f_orb = orbitalFrequencyPhi(mass_earth, radius_leo);
-
- // Should be in mHz range
- try std.testing.expect(f_orb > 1e-4);
- try std.testing.expect(f_orb < 1e-2);
-}
-
-// Test: Escape velocity phi
-test "Einstein-Bridge: escape velocity phi" {
- const mass_earth = 5.972e24;
- const radius_earth = 6.371e6;
-
- const v_esc = escapeVelocityPhi(mass_earth, radius_earth);
-
- // Should be positive but less than c (Ξ³ factor reduces it)
- try std.testing.expect(v_esc > 0);
- try std.testing.expect(v_esc < C);
-}
-
-// Test: Gravitational potential phi
-test "Einstein-Bridge: gravitational potential phi" {
- const m1 = 1.0;
- const m2 = 1.0;
- const r = 1.0;
-
- const U = gravitationalPotentialPhi(m1, m2, r);
-
- // Should be negative
- try std.testing.expect(U < 0);
-}
-
-// Test: Metric component
-test "Einstein-Bridge: metric tt phi" {
- const mass = 1.989e30;
- const radius = 6.957e8;
-
- const g_tt = metric_tt_phi(mass, radius);
-
- // Should be negative
- try std.testing.expect(g_tt < 0);
-}
-
-// Test: Critical density phi
-test "Einstein-Bridge: critical density phi" {
- const h0 = 70e3 / (3.086e22); // ~70 km/s/Mpc in SI
-
- const rho_c = criticalDensityPhi(h0);
-
- // Should be ~10^-26 kg/mΒ³
- try std.testing.expect(rho_c > 1e-28);
- try std.testing.expect(rho_c < 1e-24);
-}
-
-// Test: Friedmann equation phi
-test "Einstein-Bridge: Friedmann equation phi" {
- const rho = 1e-26;
-
- const H2 = friedmannEquationPhi(rho);
-
- // Should be positive
- try std.testing.expect(H2 > 0);
-}
-
-// Test: Luminosity distance phi
-test "Einstein-Bridge: luminosity distance phi" {
- const z = 1.0;
- const h0 = 70e3 / (3.086e22);
-
- const d_L = luminosityDistancePhi(z, h0);
-
- // Should be on Gpc scale
- try std.testing.expect(d_L > 1e24);
- try std.testing.expect(d_L < 1e27);
-}
-
-// Test: Angular diameter distance phi
-test "Einstein-Bridge: angular diameter distance phi" {
- const d_L = 1e26; // ~3 Gpc
- const z = 1.0;
-
- const d_A = angularDiameterDistancePhi(d_L, z);
-
- // Should be smaller than luminosity distance
- try std.testing.expect(d_A < d_L);
- try std.testing.expect(d_A > 0);
-}
diff --git a/src/gravity/math_formulas.zig b/src/gravity/math_formulas.zig
deleted file mode 100644
index 02eae90bae..0000000000
--- a/src/gravity/math_formulas.zig
+++ /dev/null
@@ -1,366 +0,0 @@
-//! Sacred Gravity: Gravitational Constants from Golden Ratio
-//!
-//! This module explores how gravitational constants encode via the
-//! sacred formula with Ξ³ = Οβ»Β³.
-//!
-//! # Mathematical Foundation
-//!
-//! Golden Ratio:
-//! Ο = (1 + β5)/2 β 1.6180339887498948482
-//! Ξ³ = Οβ»Β³ β 0.23606797749978969641
-//!
-//! Trinity Identity:
-//! ΟΒ² + Οβ»Β² = 3
-//!
-//! Sacred Formula:
-//! V = n Γ 3α΅ Γ Οα΅ Γ Οα΅ Γ eα΅ Γ Ξ³Κ³
-//!
-//! # Hypotheses
-//!
-//! 1. Gravitational constant G encodes via sacred formula
-//! 2. Dark matter density Ξ©_Ξ relates to Ξ³βΈ Γ Οβ΄ / ΟΒ²
-//! 3. Black hole entropy has Ξ³ correction
-//! 4. Gravitational waves have Ο-based frequency spectrum
-
-const std = @import("std");
-const math = std.math;
-const mem = std.mem;
-
-// Import from canonical source (ANTI-PATTERN: no inline constants!)
-const sacred_constants = @import("sacred_constants_reexport.zig");
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI = sacred_constants.PHI;
-
-/// ΟΒ³ = 4.23606797749978969641...
-pub const PHI_CUBED: f64 = PHI * PHI * PHI;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / PHI_CUBED;
-
-/// Fundamental TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// Ο constant
-pub const PI = sacred_constants.PI;
-
-/// Euler's number
-pub const E: f64 = 2.71828182845904523536;
-
-/// Speed of light (m/s)
-pub const C: f64 = 299792458.0;
-
-/// Planck constant (JΒ·s)
-pub const H_BAR: f64 = 1.054571817e-34;
-
-/// Gravitational constant (mΒ³/kgΒ·sΒ²) - experimental value
-pub const G_EXP: f64 = 6.67430e-11;
-
-/// Planck mass (kg)
-pub const PLANCK_MASS: f64 = 2.176434e-8;
-
-/// Planck length (m)
-pub const PLANCK_LENGTH: f64 = 1.616255e-35;
-
-/// Planck time (s)
-pub const PLANCK_TIME: f64 = 5.391247e-44;
-
-/// Sacred formula parameters
-pub const SacredParams = struct {
- n: f64 = 1.0,
- k: f64 = 0.0, // Power of 3
- m: f64 = 0.0, // Power of Ο
- p: f64 = 0.0, // Power of Ο
- q: f64 = 0.0, // Power of e
- r: f64 = 0.0, // Power of Ξ³
-
- /// Compute sacred formula value
- pub fn compute(self: *const SacredParams) f64 {
- return self.n *
- math.pow(f64, 3.0, self.k) *
- math.pow(f64, PI, self.m) *
- math.pow(f64, PHI, self.p) *
- math.pow(f64, E, self.q) *
- math.pow(f64, GAMMA, self.r);
- }
-};
-
-/// Compute G from sacred formula
-/// G = cΒ³β_PΒ²/β Γ (1 + Ξ³ correction)
-pub fn G_from_sacred() f64 {
- // Standard: G = cΒ³β_PΒ²/β
- const standard = (C * C * C) * PLANCK_LENGTH * PLANCK_LENGTH / H_BAR;
- // Apply Ξ³ correction
- return standard * (1.0 - GAMMA * GAMMA);
-}
-
-/// Alternative G via Ο powers
-/// G β Ξ³βΆ Γ ΟΒ³ / Ο
-pub fn G_phi() f64 {
- return math.pow(f64, GAMMA, 6) * PI * PI * PI / PHI;
-}
-
-/// G scaled by Planck units
-/// G/G_Planck = Ξ³Β² Γ Ο
-pub fn G_planck_ratio() f64 {
- return GAMMA * GAMMA * PHI;
-}
-
-/// Dark energy density parameter
-/// Ξ©_Ξ β Ξ³βΈ Γ Οβ΄ / ΟΒ²
-pub fn darkEnergyDensity() f64 {
- const gamma_8 = math.pow(f64, GAMMA, 8);
- const pi_4 = PI * PI * PI * PI;
- return gamma_8 * pi_4 / (PHI * PHI);
-}
-
-/// Dark matter density parameter
-/// Ξ©_DM β Ξ³β΄ Γ ΟΒ² / Ο
-pub fn darkMatterDensity() f64 {
- const gamma_4 = math.pow(f64, GAMMA, 4);
- return gamma_4 * PI * PI / PHI;
-}
-
-/// Baryonic matter density
-/// Ξ©_b β Ξ³Β³ / Ο
-pub fn baryonDensity() f64 {
- return PHI_CUBED * GAMMA / PI;
-}
-
-/// Total matter-energy density
-/// Ξ©_total = Ξ©_Ξ + Ξ©_DM + Ξ©_b
-pub fn totalDensity() f64 {
- return darkEnergyDensity() + darkMatterDensity() + baryonDensity();
-}
-
-/// Schwarzschild radius with Ξ³ correction
-/// r_s = 2GM/cΒ² Γ (1 + Ξ³/2)
-pub fn schwarzschildRadius(mass: f64) f64 {
- const standard = 2.0 * G_EXP * mass / (C * C);
- return standard * (1.0 + GAMMA / 2.0);
-}
-
-/// Black hole entropy with Ξ³ correction
-/// S_BH = A/4β_PΒ² Γ (1 + Ξ³ ln(A/4β_PΒ²))
-pub fn blackHoleEntropy(area: f64) f64 {
- const planck_area = PLANCK_LENGTH * PLANCK_LENGTH;
- const standard = area / (4.0 * planck_area);
- const gamma_term = GAMMA * @log(area / (4.0 * planck_area));
- return standard * (1.0 + gamma_term);
-}
-
-/// Hawking temperature with Ξ³ correction
-/// T_H = βcΒ³/(8ΟGMk_B) Γ (1 - Ξ³)
-pub fn hawkingTemperature(mass: f64) f64 {
- const k_B = 1.380649e-23; // Boltzmann constant
- const standard = H_BAR * C * C * C / (8.0 * PI * G_EXP * mass * k_B);
- return standard * (1.0 - GAMMA);
-}
-
-/// Gravitational wave frequency spectrum via Ο
-/// Peak frequency relates to Ο and Ξ³
-pub fn gwFrequency(chirp_mass: f64) f64 {
- // ISCO frequency: f_ISCO β cΒ³/(ΟGMβ6)
- const standard = C * C * C / (PI * G_EXP * chirp_mass * @sqrt(6.0));
- // Ο scaling
- return standard / PHI;
-}
-
-/// Gravitational wave strain amplitude with Ξ³
-/// h β Ξ³ Γ (G/cβ΄) Γ (1/r) Γ ...
-pub fn gwStrain(mass1: f64, mass2: f64, distance: f64) f64 {
- const standard = (G_EXP / (C * C * C * C)) * (mass1 * mass2) / distance;
- return GAMMA * standard;
-}
-
-/// Planck mass via sacred formula
-/// m_P = β(βc/G) Γ Ο
-pub fn planckMassSacred() f64 {
- const standard = @sqrt(H_BAR * C / G_EXP);
- return standard * PHI;
-}
-
-/// Gravitational coupling constant
-/// Ξ±_G = Gm_pΒ²/βc where m_p is proton mass
-pub fn gravitationalCoupling(proton_mass: f64) f64 {
- return G_EXP * proton_mass * proton_mass / (H_BAR * C);
-}
-
-/// Weak equivalence principle via Ο
-/// All objects fall with same acceleration (Ο-independent)
-pub fn equivalencePrinciple() bool {
- return true; // Exact
-}
-
-/// Gravitational redshift with Ξ³
-/// z = (1 - 2GM/rcΒ²)^(-1/2) - 1 Γ (1 + Ξ³)
-pub fn gravitationalRedshift(mass: f64, radius: f64) f64 {
- const standard = 1.0 / @sqrt(1.0 - 2.0 * G_EXP * mass / (radius * C * C)) - 1.0;
- return standard * (1.0 + GAMMA);
-}
-
-/// Cosmological constant via Ο
-/// Ξ = Ξ³βΆ Γ ΟΒ² / β_PΒ²
-pub fn cosmologicalConstant() f64 {
- const gamma_6 = math.pow(f64, GAMMA, 6);
- return gamma_6 * PI * PI / (PLANCK_LENGTH * PLANCK_LENGTH);
-}
-
-/// Hubble parameter via Ο
-/// Hβ = c Γ Ξ³ / R_universe
-pub fn hubbleParameter(universe_radius: f64) f64 {
- return C * GAMMA / universe_radius;
-}
-
-/// Critical density of universe
-/// Ο_c = 3HβΒ²/(8ΟG)
-pub fn criticalDensity(hubble: f64) f64 {
- return 3.0 * hubble * hubble / (8.0 * PI * G_EXP);
-}
-
-/// Einstein ring radius via Ο
-/// ΞΈ_E = β(4GM/cΒ² Γ d_ls/d_l_d_s) Γ Ο
-pub fn einsteinRingRadius(mass: f64, d_l: f64, d_s: f64, d_ls: f64) f64 {
- const standard = @sqrt(4.0 * G_EXP * mass / (C * C) * d_ls / (d_l * d_s));
- return standard * PHI;
-}
-
-// Test: ΟΒ³ and Ξ³ relationship
-test "Gravity: phi cubed and gamma" {
- const phi_cubed_expected = 4.23606797749978969641;
- try std.testing.expectApproxEqRel(@as(f64, phi_cubed_expected), PHI_CUBED, 1e-10);
-
- const gamma_expected = 0.23606797749978969641;
- try std.testing.expectApproxEqRel(@as(f64, gamma_expected), GAMMA, 1e-10);
-}
-
-// Test: TRINITY identity
-test "Gravity: TRINITY identity" {
- try std.testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-// Test: G from sacred formula
-test "Gravity: G from sacred" {
- const g_sacred = G_from_sacred();
- const g_phi = G_phi();
-
- // Both should be positive
- try std.testing.expect(g_sacred > 0);
- try std.testing.expect(g_phi > 0);
-
- // Should be in same order of magnitude as experimental
- try std.testing.expect(g_sacred > 1e-12);
- try std.testing.expect(g_sacred < 1e-9);
-}
-
-// Test: Dark energy density
-test "Gravity: dark energy density" {
- const omega_lambda = darkEnergyDensity();
-
- // Formula gives very small value, just check positive
- try std.testing.expect(omega_lambda > 0);
-}
-
-// Test: Total density
-test "Gravity: total density" {
- const omega_total = totalDensity();
-
- // Check positive value
- try std.testing.expect(omega_total > 0);
-}
-
-// Test: Schwarzschild radius
-test "Gravity: Schwarzschild radius" {
- const mass_sun = 1.989e30; // kg
- const r_s = schwarzschildRadius(mass_sun);
-
- // Should be approximately 3 km
- try std.testing.expect(r_s > 2500);
- try std.testing.expect(r_s < 3500);
-}
-
-// Test: Black hole entropy
-test "Gravity: black hole entropy" {
- const area = 1.0; // 1 mΒ² (much larger than Planck area)
- const entropy = blackHoleEntropy(area);
-
- // Should be positive and very large (area >> Planck area)
- // S = A/(4*l_P^2) Γ (1 + Ξ³*ln(A/(4*l_P^2)))
- // With A=1 mΒ² and l_P β 1.6e-35 m, S >> 1
- try std.testing.expect(entropy > 1e60);
-}
-
-// Test: Hawking temperature
-test "Gravity: Hawking temperature" {
- const mass_sun = 1.989e30; // kg
- const temp = hawkingTemperature(mass_sun);
-
- // Should be very small (microkelvin range for stellar mass)
- try std.testing.expect(temp > 0);
- try std.testing.expect(temp < 1e-6);
-}
-
-// Test: GW frequency
-test "Gravity: gravitational wave frequency" {
- const chirp_mass = 1.989e30; // Solar mass
- const freq = gwFrequency(chirp_mass);
-
- // Should be positive frequency
- try std.testing.expect(freq > 0);
-}
-
-// Test: Gravitational coupling
-test "Gravity: gravitational coupling" {
- const proton_mass = 1.6726219e-27; // kg
- const alpha_g = gravitationalCoupling(proton_mass);
-
- // Should be very small (~10^-38)
- try std.testing.expect(alpha_g > 0);
- try std.testing.expect(alpha_g < 1e-35);
-}
-
-// Test: Gravitational redshift
-test "Gravity: gravitational redshift" {
- const mass_sun = 1.989e30; // kg
- const radius_sun = 6.957e8; // m
- const z = gravitationalRedshift(mass_sun, radius_sun);
-
- // Should be positive and small (~10^-6 for Sun)
- try std.testing.expect(z > 0);
- try std.testing.expect(z < 1e-4);
-}
-
-// Test: Cosmological constant
-test "Gravity: cosmological constant" {
- const lambda = cosmologicalConstant();
-
- // Should be positive and very small
- try std.testing.expect(lambda > 0);
-}
-
-// Test: Critical density
-test "Gravity: critical density" {
- const hubble = 70e3 / (3.086e22); // ~70 km/s/Mpc in SI
- const rho_c = criticalDensity(hubble);
-
- // Should be ~10^-26 kg/mΒ³
- try std.testing.expect(rho_c > 1e-28);
- try std.testing.expect(rho_c < 1e-24);
-}
-
-// Test: Sacred formula parameters
-test "Gravity: sacred formula" {
- var params = SacredParams{
- .n = 1.0,
- .k = 1.0,
- .m = 2.0,
- .p = 0.0,
- .q = 0.0,
- .r = 0.0,
- };
-
- const result = params.compute();
- const expected = 3.0 * PI * PI;
-
- try std.testing.expectApproxEqRel(expected, result, 0.01);
-}
diff --git a/src/gravity/quantum_gravity_full.zig b/src/gravity/quantum_gravity_full.zig
deleted file mode 100644
index 600c4bc839..0000000000
--- a/src/gravity/quantum_gravity_full.zig
+++ /dev/null
@@ -1,507 +0,0 @@
-//! TRINITY v22.0: FULL QUANTUM GRAVITY
-//!
-//! Ο-Ξ³ based quantum gravity theory: graviton mass, E8 symmetry,
-//! holographic entropy, quantum foam discreteness, LQG corrections.
-//!
-//! ## Core Principle
-//!
-//! Gravity emerges from E8 root system breaking with Ξ³ = Οβ»Β³ correction.
-//! The graviton has a tiny but non-zero mass, explaining dark matter
-//! and resolving the information paradox.
-//!
-//! ## Formula Index (363-382)
-//!
-//! ### Graviton Properties (363-367)
-//! 363. Graviton mass: m_g = m_P Γ Ξ³Β³
-//! 364. Graviton Compton wavelength: Ξ»_g = h/(m_g c)
-//! 365. E8 graviton multiplet: N_states = 240
-//! 366. Gravitational coupling: Ξ±_g = Ξ³Β²
-//! 367. Graviton decay width: Ξ_g = m_g Γ Ξ³
-//!
-//! ### Planck Scale Physics (368-372)
-//! 368. Planck length correction: β_P(Ο) = β_P Γ Ο
-//! 369. Quantum foam cell volume: V_foam = (β_P Γ Ο)Β³
-//! 370. Spacetime discreteness: Ξx = β_P / Ο
-//! 371. Planck energy correction: E_P(Ο) = E_P / βΟ
-//! 372. Quantum fluctuation amplitude: Ξ΄Ο/Ο = Ξ³
-//!
-//! ### Black Holes (373-377)
-//! 373. Bekenstein-Hawking entropy with Ο: S_BH = ΟA/(4β_PΒ²)
-//! 374. Hawking temperature with Ο: T_H = βc/(ΟΓ2Οk_B r_s)
-//! 375. Black hole evaporation time: t_ev = Ξ³β»ΒΉ Γ 5120Ο GΒ²MΒ³/(βcβ΄)
-//! 376. Firewall resolution: Ξ_firewall = Ξ³ Γ T_P
-//! 377. Remnant mass: M_rem = m_P Γ Ξ³
-//!
-//! ### Holography & LQG (378-382)
-//! 378. Holographic screen density: Ο_screen = Ο/(4β_PΒ²)
-//! 379. Loop quantum gravity area gap: ΞA = Ξ³ Γ β_PΒ²
-//! 380. Spin network edge length: β_edge = β_P Γ ΟΒ²
-//! 381. Quantum geometry volume: V_quantum = Ξ³ Γ β_PΒ³
-//! 382. Holographic principle bound: S_max = Ο Γ A/4
-
-const std = @import("std");
-const testing = std.testing;
-const math = std.math;
-
-// ============================================================================
-// SACRED CONSTANTS
-// ============================================================================
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = 2.6180339887498948482...
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// ΟΒ³ = 4.23606797749978969641...
-pub const PHI_CUBED: f64 = PHI * PHI * PHI;
-
-/// Οβ»ΒΉ = 0.6180339887498948482 (consciousness threshold)
-pub const PHI_INV: f64 = 1.0 / PHI;
-
-/// Οβ»Β² = 0.3819660112501051516
-pub const PHI_INV_SQ: f64 = 1.0 / PHI_SQ;
-
-/// Οβ»Β³ = Ξ³ = 0.23606797749978969641 (Barbero-Immirzi parameter)
-pub const GAMMA: f64 = 1.0 / PHI_CUBED;
-
-/// Consciousness threshold (Ξ¦_Ξ³ from v14.3)
-pub const PHI_GAMMA: f64 = PHI_INV;
-
-/// Pi
-pub const PI: f64 = 3.14159265358979323846;
-
-/// Speed of light (m/s)
-pub const C: f64 = 2.99792458e8;
-
-/// Planck constant (JΒ·s)
-pub const H_BAR: f64 = 1.054571817e-34;
-
-/// Planck constant (JΒ·s)
-pub const H: f64 = 6.62607015e-34;
-
-/// Boltzmann constant (J/K)
-pub const K_B: f64 = 1.380649e-23;
-
-/// Planck length (m)
-pub const PLANCK_LENGTH: f64 = 1.616255e-35;
-
-/// Planck time (s)
-pub const PLANCK_TIME: f64 = 5.391247e-44;
-
-/// Planck mass (kg)
-pub const PLANCK_MASS: f64 = 2.176434e-8;
-
-/// Planck energy (J)
-pub const PLANCK_ENERGY: f64 = 1.956082e9;
-
-/// Planck temperature (K)
-pub const PLANCK_TEMPERATURE: f64 = 1.416785e32;
-
-/// Gravitational constant (mΒ³/kg/sΒ²)
-pub const G: f64 = 6.6743e-11;
-
-/// Elementary charge (C)
-pub const E_CHARGE: f64 = 1.602176634e-19;
-
-/// Electron volt (J)
-pub const EV: f64 = 1.602176634e-19;
-
-pub const VERSION = "22.0.0";
-pub const MODULE_NAME = "FULL QUANTUM GRAVITY";
-pub const FORMULA_START = 363;
-pub const FORMULA_END = 382;
-pub const FORMULA_COUNT = 20;
-
-// ============================================================================
-// GRAVITON PROPERTIES (363-367)
-// ============================================================================
-
-/// Formula 363: Graviton Mass (TRINITY prediction)
-///
-/// Unlike String Theory (massless graviton), TRINITY predicts a tiny
-/// but non-zero graviton mass from Ξ³Β³ scaling of Planck mass.
-///
-/// m_g = m_P Γ Ξ³Β³
-///
-/// This explains:
-/// - Modified gravity at galactic scales (dark matter)
-/// - Gravitational wave dispersion
-/// - Late-time cosmic acceleration
-pub fn gravitonMass() f64 {
- return PLANCK_MASS * math.pow(f64, GAMMA, 3);
-}
-
-/// Formula 364: Graviton Compton Wavelength
-///
-/// The quantum wavelength associated with the graviton mass.
-/// For the TRINITY graviton, this is cosmological in scale.
-///
-/// Ξ»_g = h/(m_g c)
-pub fn gravitonComptonWavelength() f64 {
- const m_g = gravitonMass();
- return H / (m_g * C);
-}
-
-/// Formula 365: E8 Graviton Multiplet
-///
-/// E8 root system contains 240 roots β 240 graviton polarization states
-/// when the symmetry breaks to include gravity.
-///
-/// N_states = 240
-pub fn e8GravitonStates() u32 {
- return 240;
-}
-
-/// Formula 366: Gravitational Coupling Constant
-///
-/// Dimensionless strength of gravitational interaction at Planck scale,
-/// scaled by Ξ³Β².
-///
-/// Ξ±_g = Ξ³Β² β 0.0557
-pub fn gravitationalCoupling() f64 {
- return GAMMA * GAMMA;
-}
-
-/// Formula 367: Graviton Decay Width
-///
-/// If the graviton is unstable (e.g., decays to photons), its width
-/// is suppressed by Ξ³.
-///
-/// Ξ_g = m_g Γ Ξ³
-pub fn gravitonDecayWidth() f64 {
- const m_g = gravitonMass();
- return m_g * GAMMA;
-}
-
-// ============================================================================
-// PLANCK SCALE PHYSICS (368-372)
-// ============================================================================
-
-/// Formula 368: Planck Length Correction
-///
-/// The fundamental length scale of spacetime, corrected by Ο.
-/// This represents the true discreteness scale of quantum geometry.
-///
-/// β_P(Ο) = β_P Γ Ο
-pub fn planckLengthCorrected() f64 {
- return PLANCK_LENGTH * PHI;
-}
-
-/// Formula 369: Quantum Foam Cell Volume
-///
-/// The volume of a single "atom" of spacetime in the quantum foam
-/// picture. Each cell is the smallest meaningful region of space.
-///
-/// V_foam = (β_P Γ Ο)Β³
-pub fn foamCellVolume() f64 {
- const l_p_phi = planckLengthCorrected();
- return math.pow(f64, l_p_phi, 3);
-}
-
-/// Formula 370: Spacetime Discreteness
-///
-/// The minimum measurable distance in TRINITY quantum gravity.
-/// Smaller than standard Planck length due to Ο-scaling.
-///
-/// Ξx = β_P / Ο
-pub fn spacetimeDiscreteness() f64 {
- return PLANCK_LENGTH / PHI;
-}
-
-/// Formula 371: Planck Energy Correction
-///
-/// The maximum energy that can be concentrated in a region of
-/// Planck scale, reduced by βΟ.
-///
-/// E_P(Ο) = E_P / βΟ
-pub fn planckEnergyCorrected() f64 {
- return PLANCK_ENERGY / math.sqrt(PHI);
-}
-
-/// Formula 372: Quantum Fluctuation Amplitude
-///
-/// Relative amplitude of quantum fluctuations in spacetime metric.
-/// This determines the strength of quantum gravity effects.
-///
-/// Ξ΄Ο/Ο = Ξ³ β 0.236
-pub fn quantumFluctuationAmplitude() f64 {
- return GAMMA;
-}
-
-// ============================================================================
-// BLACK HOLES (373-377)
-// ============================================================================
-
-/// Formula 373: Bekenstein-Hawking Entropy with Ο
-///
-/// The entropy of a black hole is proportional to its horizon area,
-/// but TRINITY adds a Ο factor that increases the entropy by 61.8%.
-///
-/// S_BH = Ο Γ A / (4β_PΒ²)
-pub fn blackHoleEntropyPhi(area: f64) f64 {
- return PHI * area / (4.0 * PLANCK_LENGTH * PLANCK_LENGTH);
-}
-
-/// Formula 374: Hawking Temperature with Ο
-///
-/// The temperature of Hawking radiation, corrected by Ο in the denominator.
-/// This gives slightly lower temperatures than standard calculation.
-///
-/// T_H = βc / (Ο Γ 2Οk_B r_s)
-pub fn hawkingTemperaturePhi(mass: f64) f64 {
- const r_s = (2.0 * G * mass) / (C * C);
- return (H_BAR * C) / (PHI * 2.0 * PI * K_B * r_s);
-}
-
-/// Formula 375: Black Hole Evaporation Time
-///
-/// Time for a black hole to completely evaporate via Hawking radiation,
-/// modified by Ξ³β»ΒΉ factor (longer-lived than standard prediction).
-///
-/// t_ev = Ξ³β»ΒΉ Γ 5120Ο GΒ²MΒ³ / (βcβ΄)
-pub fn blackHoleEvaporationTime(mass: f64) f64 {
- const standard = (5120.0 * PI * G * G * math.pow(f64, mass, 3)) /
- (H_BAR * math.pow(f64, C, 4));
- return (1.0 / GAMMA) * standard;
-}
-
-/// Formula 376: Firewall Resolution
-///
-/// The distance scale at which the firewall is smoothed out by Ξ³ correction.
-/// This resolves the AMPS firewall paradox.
-///
-/// Ξ_firewall = Ξ³ Γ β_P
-pub fn firewallResolution() f64 {
- return GAMMA * PLANCK_LENGTH;
-}
-
-/// Formula 377: Remnant Mass
-///
-/// The minimum mass a black hole can have before complete evaporation.
-/// This remnant preserves information and resolves the paradox.
-///
-/// M_rem = m_P Γ Ξ³
-pub fn remnantMass() f64 {
- return PLANCK_MASS * GAMMA;
-}
-
-// ============================================================================
-// HOLOGRAPHY & LOOP QUANTUM GRAVITY (378-382)
-// ============================================================================
-
-/// Formula 378: Holographic Screen Density
-///
-/// The information density on a holographic screen at the Planck scale,
-/// enhanced by Ο factor.
-///
-/// Ο_screen = Ο / (4β_PΒ²)
-pub fn holographicScreenDensity() f64 {
- return PHI / (4.0 * PLANCK_LENGTH * PLANCK_LENGTH);
-}
-
-/// Formula 379: Loop Quantum Gravity Area Gap
-///
-/// The smallest possible area in LQG, equal to the square of the
-/// Planck length times Ξ³.
-///
-/// ΞA = Ξ³ Γ β_PΒ²
-pub fn lqgAreaGap() f64 {
- return GAMMA * PLANCK_LENGTH * PLANCK_LENGTH;
-}
-
-/// Formula 380: Spin Network Edge Length
-///
-/// The characteristic length of edges in the spin network that
-/// constitutes quantum geometry in LQG.
-///
-/// β_edge = β_P Γ ΟΒ²
-pub fn spinNetworkEdgeLength() f64 {
- return PLANCK_LENGTH * PHI_SQ;
-}
-
-/// Formula 381: Quantum Geometry Volume
-///
-/// The smallest quantized volume element in loop quantum gravity,
-/// scaled by Ξ³.
-///
-/// V_quantum = Ξ³ Γ β_PΒ³
-pub fn quantumGeometryVolume() f64 {
- return GAMMA * math.pow(f64, PLANCK_LENGTH, 3);
-}
-
-/// Formula 382: Holographic Principle Bound
-///
-/// Maximum information that can be stored in a region of space,
-/// proportional to the surface area with Ο enhancement.
-///
-/// S_max = Ο Γ A / 4
-pub fn holographicPrincipleBound(area: f64) f64 {
- return PHI * area / 4.0;
-}
-
-// ============================================================================
-// UTILITY FUNCTIONS
-// ============================================================================
-
-/// Schwarzschild radius for a given mass
-pub fn schwarzschildRadius(mass: f64) f64 {
- return (2.0 * G * mass) / (C * C);
-}
-
-/// Convert mass to energy equivalent (E = mcΒ²)
-pub fn massToEnergy(mass: f64) f64 {
- return mass * C * C;
-}
-
-/// Planck force (maximum possible force)
-pub fn planckForce() f64 {
- return PLANCK_ENERGY / PLANCK_LENGTH;
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "v22.0: Formula 363 - Graviton Mass" {
- const m_g = gravitonMass();
- try testing.expect(m_g > 0);
- try testing.expect(m_g < PLANCK_MASS); // Must be smaller than Planck mass
-}
-
-test "v22.0: Formula 364 - Graviton Compton Wavelength" {
- const lambda_g = gravitonComptonWavelength();
- try testing.expect(lambda_g > 0);
- try testing.expect(lambda_g < 1e-20); // Subatomic scale
-}
-
-test "v22.0: Formula 365 - E8 Graviton States" {
- const states = e8GravitonStates();
- try testing.expectEqual(@as(u32, 240), states);
-}
-
-test "v22.0: Formula 366 - Gravitational Coupling" {
- const alpha_g = gravitationalCoupling();
- try testing.expect(alpha_g > 0);
- try testing.expect(alpha_g < 1); // Weak coupling
-}
-
-test "v22.0: Formula 367 - Graviton Decay Width" {
- const Gamma_g = gravitonDecayWidth();
- try testing.expect(Gamma_g > 0);
-}
-
-test "v22.0: Formula 368 - Planck Length Corrected" {
- const l_p_phi = planckLengthCorrected();
- try testing.expect(l_p_phi > PLANCK_LENGTH);
-}
-
-test "v22.0: Formula 369 - Foam Cell Volume" {
- const V_foam = foamCellVolume();
- try testing.expect(V_foam > 0);
-}
-
-test "v22.0: Formula 370 - Spacetime Discreteness" {
- const delta_x = spacetimeDiscreteness();
- try testing.expect(delta_x > 0);
- try testing.expect(delta_x < PLANCK_LENGTH);
-}
-
-test "v22.0: Formula 371 - Planck Energy Corrected" {
- const E_p_phi = planckEnergyCorrected();
- try testing.expect(E_p_phi > 0);
- try testing.expect(E_p_phi < PLANCK_ENERGY);
-}
-
-test "v22.0: Formula 372 - Quantum Fluctuation Amplitude" {
- const delta_rho = quantumFluctuationAmplitude();
- try testing.expect(delta_rho > 0);
- try testing.expect(delta_rho < 1);
-}
-
-test "v22.0: Formula 373 - Black Hole Entropy Phi" {
- const area = 4.0 * PI * math.pow(f64, PLANCK_LENGTH, 2);
- const S_BH = blackHoleEntropyPhi(area);
- try testing.expect(S_BH > 0);
-}
-
-test "v22.0: Formula 374 - Hawking Temperature Phi" {
- const M = PLANCK_MASS * 1e6;
- const T_H = hawkingTemperaturePhi(M);
- try testing.expect(T_H > 0);
-}
-
-test "v22.0: Formula 375 - Black Hole Evaporation Time" {
- const M = 1e10; // Small black hole in kg
- const t_ev = blackHoleEvaporationTime(M);
- try testing.expect(t_ev > 0);
-}
-
-test "v22.0: Formula 376 - Firewall Resolution" {
- const delta_fw = firewallResolution();
- try testing.expect(delta_fw > 0);
- try testing.expect(delta_fw < PLANCK_LENGTH);
-}
-
-test "v22.0: Formula 377 - Remnant Mass" {
- const M_rem = remnantMass();
- try testing.expect(M_rem > 0);
- try testing.expect(M_rem < PLANCK_MASS);
-}
-
-test "v22.0: Formula 378 - Holographic Screen Density" {
- const rho_screen = holographicScreenDensity();
- try testing.expect(rho_screen > 0);
-}
-
-test "v22.0: Formula 379 - LQG Area Gap" {
- const Delta_A = lqgAreaGap();
- try testing.expect(Delta_A > 0);
-}
-
-test "v22.0: Formula 380 - Spin Network Edge Length" {
- const l_edge = spinNetworkEdgeLength();
- try testing.expect(l_edge > PLANCK_LENGTH);
-}
-
-test "v22.0: Formula 381 - Quantum Geometry Volume" {
- const V_quantum = quantumGeometryVolume();
- try testing.expect(V_quantum > 0);
-}
-
-test "v22.0: Formula 382 - Holographic Principle Bound" {
- const area = 1.0;
- const S_max = holographicPrincipleBound(area);
- try testing.expect(S_max > 0);
-}
-
-test "v22.0: Graviton mass in eV" {
- const m_g = gravitonMass();
- const m_g_eV = massToEnergy(m_g) / EV;
- try testing.expect(m_g_eV > 1e-10);
- try testing.expect(m_g_eV < 1e30);
-}
-
-test "v22.0: Schwarzschild radius consistency" {
- const M = 1e30;
- const r_s = schwarzschildRadius(M);
- try testing.expect(r_s > 0);
-}
-
-test "v22.0: Planck force" {
- const F_P = planckForce();
- try testing.expect(F_P > 1e43);
-}
-
-test "v22.0: TRINITY identity holds" {
- const trinity = PHI_SQ + 1.0 / PHI_SQ;
- try testing.expectApproxEqRel(trinity, 3.0, 1e-10);
-}
-
-test "v22.0: GAMMA = phi^(-3)" {
- try testing.expectApproxEqRel(GAMMA, 1.0 / PHI_CUBED, 1e-10);
-}
-
-test "v22.0: PHI_GAMMA = phi^(-1)" {
- try testing.expectApproxEqRel(PHI_GAMMA, PHI_INV, 1e-10);
-}
diff --git a/src/gravity/sacred b/src/gravity/sacred
deleted file mode 120000
index 7be52aa48c..0000000000
--- a/src/gravity/sacred
+++ /dev/null
@@ -1 +0,0 @@
-../sacred
\ No newline at end of file
diff --git a/src/gravity/sacred_constants_reexport.zig b/src/gravity/sacred_constants_reexport.zig
deleted file mode 100644
index 010ce9ad73..0000000000
--- a/src/gravity/sacred_constants_reexport.zig
+++ /dev/null
@@ -1,22 +0,0 @@
-// @origin(spec:sacred_constants_reexport.tri) @regen(manual-impl)
-//! Sacred Constants Re-export
-//!
-//! This module re-exports sacred constants from src/sacred/constants.zig
-//! for use by all submodules that cannot use ".." imports.
-// @origin(manual) @regen(pending)
-
-const sacred = @import("sacred/constants.zig");
-
-// Re-export SacredConstants struct
-pub const SacredConstants = sacred.SacredConstants;
-
-// Re-export common constants for convenience
-pub const PHI = sacred.SacredConstants.PHI;
-pub const PHI_INVERSE = sacred.SacredConstants.PHI_INVERSE;
-pub const PHI_SQ = sacred.SacredConstants.PHI_SQ;
-pub const TRINITY = sacred.SacredConstants.TRINITY;
-pub const SQRT5 = sacred.SacredConstants.SQRT5;
-pub const PI = sacred.SacredConstants.PI;
-pub const E = sacred.SacredConstants.E;
-pub const TAU = sacred.SacredConstants.TAU;
-pub const PHI_CUBED = sacred.SacredConstants.PHI_CUBED;
diff --git a/src/gravity/spin_network_analysis.zig b/src/gravity/spin_network_analysis.zig
deleted file mode 100644
index 6e7f41064d..0000000000
--- a/src/gravity/spin_network_analysis.zig
+++ /dev/null
@@ -1,311 +0,0 @@
-//! DELTA-001 Phase 1: Spin Network Spectrum Analysis
-//!
-//! Mathematical investigation of Loop Quantum Gravity (LQG) spin network
-//! eigenvalues and their relationship to the golden ratio Ο.
-//!
-//! ## Area Operator in LQG
-//!
-//! In Loop Quantum Gravity, geometric observables are quantized. The area
-//! operator A acting on a spin network state with spins j_i has eigenvalues:
-//!
-//! A = 8ΟΞ³β_PΒ² βα΅’ β(j_i(j_i + 1))
-//!
-//! Where:
-//! - Ξ³ = Barbero-Immirzi parameter = Οβ»Β³ β 0.236 in TRINITY theory
-//! - β_P = Planck length
-//! - j_i = spin labels (1/2, 1, 3/2, 2, 5/2, 3, ...)
-//! - β(j(j+1)) = Casimir eigenvalue for SU(2) representation j
-//!
-//! ## Investigation Goals
-//!
-//! 1. Calculate β(j(j+1)) for all fundamental spins j = 1/2 to 3
-//! 2. Compute ratios between different eigenvalues
-//! 3. Search for exact or approximate relationships with Ο
-//! 4. Investigate Lucas number connections (L_n = ΟβΏ + (-Ο)β»βΏ)
-
-const std = @import("std");
-const math = std.math;
-const print = std.debug.print;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Golden ratio Ο = (1 + β5) / 2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = Ο + 1
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// Οβ»ΒΉ = Ο - 1
-pub const PHI_INV: f64 = 1.0 / PHI;
-
-/// Οβ»Β² = 2 - Ο
-pub const PHI_INV_SQ: f64 = 1.0 / PHI_SQ;
-
-/// Οβ»Β³ = Ξ³ (Barbero-Immirzi parameter)
-pub const GAMMA: f64 = 1.0 / (PHI * PHI * PHI);
-
-/// Ο
-pub const PI: f64 = 3.14159265358979323846;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SPIN NETWORK CALCULATIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Calculate the SU(2) Casimir eigenvalue β(j(j+1)) for a given spin j
-pub fn casimirEigenvalue(j: f64) f64 {
- return math.sqrt(j * (j + 1.0));
-}
-
-/// Calculate the full area eigenvalue for a single spin edge
-/// A = 8ΟΞ³β_PΒ² β(j(j+1))
-///
-/// Note: We work in dimensionless units where 8Οβ_PΒ² = 1 for
-/// investigating pure mathematical relationships
-pub fn areaEigenvalue(j: f64) f64 {
- return GAMMA * casimirEigenvalue(j);
-}
-
-/// Calculate ratio between two spin eigenvalues
-pub fn eigenvalueRatio(j1: f64, j2: f64) f64 {
- return casimirEigenvalue(j1) / casimirEigenvalue(j2);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LUCAS NUMBER ANALYSIS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Lucas numbers: L_n = ΟβΏ + (-Ο)β»βΏ
-/// L_0 = 2, L_1 = 1, L_2 = 3 = TRINITY, L_3 = 4, L_4 = 7, ...
-pub fn lucasNumber(n: u32) f64 {
- const phi_n = math.pow(f64, PHI, @floatFromInt(n));
- const neg_phi_inv_n = math.pow(f64, -PHI_INV, @floatFromInt(n));
- return phi_n + neg_phi_inv_n;
-}
-
-/// Check if a value is close to a Lucas number (within 0.1%)
-pub fn isNearLucas(value: f64, n: u32) bool {
- const L_n = lucasNumber(n);
- const rel_error = @abs(value - L_n) / L_n;
- return rel_error < 0.001;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ANALYSIS FUNCTIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Complete analysis of all fundamental spins j = 1/2, 1, 3/2, 2, 5/2, 3
-pub fn analyzeAllSpins() void {
- const CYAN = "\x1b[36m";
- const GOLD = "\x1b[33m";
- const MAGENTA = "\x1b[35m";
- const RESET = "\x1b[0m";
-
- print("\n{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n", .{ MAGENTA, RESET });
- print("{s}β DELTA-001 PHASE 1: SPIN NETWORK SPECTRUM ANALYSIS β{s}\n", .{ GOLD, RESET });
- print("{s}β Loop Quantum Gravity Eigenvalues vs Golden Ratio Ο β{s}\n", .{ GOLD, RESET });
- print("{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n\n", .{ MAGENTA, RESET });
-
- // Fundamental spin values
- const spins = [_]f64{ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0 };
-
- print("{s}=== AREA OPERATOR FORMULA ==={s}\n", .{ GOLD, RESET });
- print("A = 8ΟΞ³β_PΒ² β(j(j+1))\n", .{});
- print("where Ξ³ = Οβ»Β³ = {d:.15}\n\n", .{GAMMA});
-
- print("{s}=== SPIN NETWORK EIGENVALUES ==={s}\n\n", .{ GOLD, RESET });
-
- for (spins) |j| {
- const eigenvalue = casimirEigenvalue(j);
- const j_j_plus_1 = j * (j + 1.0);
- const ratio_to_phi = eigenvalue / PHI;
- const ratio_to_phi_inv = eigenvalue / PHI_INV;
- const error_phi = @abs(eigenvalue - PHI) / PHI * 100.0;
-
- print("{s}Spin j = {d:.1}:{s}\n", .{ CYAN, j, RESET });
- print(" j(j+1) = {d:.10}\n", .{j_j_plus_1});
- print(" β(j(j+1)) = {d:.15}\n", .{eigenvalue});
- print(" vs Ο = {d:.15} (diff: {d:.6}%)\n", .{ PHI, error_phi });
- print(" ratio to Ο = {d:.15}\n", .{ratio_to_phi});
- print(" ratio to Οβ»ΒΉ = {d:.15}\n", .{ratio_to_phi_inv});
-
- // Check for coincidences
- var found_coincidence = false;
-
- if (error_phi < 1.0) {
- print(" {s}β Within 1% of Ο{s}\n", .{ GOLD, RESET });
- found_coincidence = true;
- }
- if (error_phi < 0.1) {
- print(" {s}β Within 0.1% of Ο{s}\n", .{ GOLD, RESET });
- found_coincidence = true;
- }
-
- // Check if eigenvalue equals k Γ Ο
- const ratio_phi_rounded = @round(ratio_to_phi);
- if (@abs(ratio_to_phi - ratio_phi_rounded) < 0.01) {
- print(" {s}β β {d:.0} Γ Ο (ratio = {d:.10}){s}\n", .{ GOLD, ratio_phi_rounded, ratio_to_phi, RESET });
- found_coincidence = true;
- }
-
- // Check if eigenvalue equals k Γ Οβ»ΒΉ
- const ratio_phi_inv_rounded = @round(ratio_to_phi_inv);
- if (@abs(ratio_to_phi_inv - ratio_phi_inv_rounded) < 0.01) {
- print(" {s}β β {d:.0} Γ Οβ»ΒΉ (ratio = {d:.10}){s}\n", .{ GOLD, ratio_phi_inv_rounded, ratio_to_phi_inv, RESET });
- found_coincidence = true;
- }
-
- // Check Lucas number connections
- for (0..10) |n| {
- if (isNearLucas(eigenvalue, @intCast(n))) {
- const L_n = lucasNumber(@intCast(n));
- print(" {s}β β L_{d} = {d:.15}{s}\n", .{ GOLD, n, L_n, RESET });
- found_coincidence = true;
- }
- }
-
- // Special case: β(8/3) β 1.633 vs Ο β 1.618
- if (j == 1.0) {
- const sqrt_8_3 = math.sqrt(8.0 / 3.0);
- const error_8_3 = @abs(sqrt_8_3 - PHI) / PHI * 100.0;
- if (error_8_3 < 1.0) {
- print(" {s}β β(8/3) = {d:.15} vs Ο = {d:.15} (error: {d:.4}%){s}\n", .{ GOLD, sqrt_8_3, PHI, error_8_3, RESET });
- found_coincidence = true;
- }
- }
-
- if (!found_coincidence) {
- print(" No strong Ο-relationships found\n", .{});
- }
- }
-
- print("{s}=== RATIO ANALYSIS BETWEEN SPINS ==={s}\n\n", .{ GOLD, RESET });
-
- // Calculate all pairwise ratios
- for (spins, 0..) |j1, i| {
- for (spins[i..]) |j2| {
- if (j1 == j2) continue;
- const ratio = eigenvalueRatio(j1, j2);
- const inv_ratio = eigenvalueRatio(j2, j1);
-
- // Check if ratio is Ο-related
- const phi_diff = @abs(ratio - PHI) / PHI * 100.0;
- const phi_inv_diff = @abs(ratio - PHI_INV) / PHI_INV * 100.0;
-
- print("β({d:.1}Γ{d:.1}) / β({d:.1}Γ{d:.1}) = {d:.15}", .{ j1, j1 + 1.0, j2, j2 + 1.0, ratio });
- print(" (inverse: {d:.15})", .{inv_ratio});
-
- if (phi_diff < 5.0) {
- print(" {s}β Ο (error: {d:.4}%){s}", .{ GOLD, phi_diff, RESET });
- }
- if (phi_inv_diff < 5.0) {
- print(" {s}β Οβ»ΒΉ (error: {d:.4}%){s}\n", .{ GOLD, phi_inv_diff, RESET });
- } else {
- print("\n", .{});
- }
- }
- }
-
- print("{s}=== LUCAS NUMBERS ==={s}\n", .{ GOLD, RESET });
- print("L_n = ΟβΏ + (-Ο)β»βΏ\n", .{});
- print("L_0 = {d:.1} (Οβ° + Οβ° = 1 + 1)\n", .{lucasNumber(0)});
- print("L_1 = {d:.1} (ΟΒΉ + (-Ο)β»ΒΉ = Ο - Οβ»ΒΉ = 1)\n", .{lucasNumber(1)});
- print("L_2 = {d:.1} (ΟΒ² + Οβ»Β² = 3 = TRINITY){s}\n", .{ lucasNumber(2), GOLD });
- print("L_3 = {d:.1}\n", .{lucasNumber(3)});
- print("L_4 = {d:.1}\n", .{lucasNumber(4)});
- print("L_5 = {d:.1}\n", .{lucasNumber(5)});
- print("L_6 = {d:.2}\n", .{lucasNumber(6)});
- print("\n", .{});
-
- print("{s}=== KEY FINDINGS ==={s}\n", .{ GOLD, RESET });
-
- // The key β(8/3) coincidence
- const sqrt_8_3 = math.sqrt(8.0 / 3.0);
- const error_8_3 = @abs(sqrt_8_3 - PHI) / PHI * 100.0;
- print("β β(8/3) = {d:.15} vs Ο = {d:.15}\n", .{ sqrt_8_3, PHI });
- print(" Error: {d:.4}%\n", .{error_8_3});
- if (error_8_3 < 1.0) {
- print(" {s}β STRONG COINCIDENCE (< 1%){s}\n\n", .{ GOLD, RESET });
- } else {
- print(" {s}β WEAK COINCIDENCE (> 1%){s}\n\n", .{ GOLD, RESET });
- }
-
- // Check for exact identities
- print("{s}=== EXACT IDENTITIES (if any) ==={s}\n", .{ GOLD, RESET });
-
- // Identity: β(j(j+1)) = β2 for j = 1
- const j1_eigenvalue = casimirEigenvalue(1.0);
- print("β(1Γ2) = β2 = {d:.6}", .{j1_eigenvalue});
- if (@abs(j1_eigenvalue - math.sqrt2) < 1e-10) {
- print(" {s}β EXACT IDENTITY{s}\n", .{ GOLD, RESET });
- } else {
- print(" No exact identity\n", .{});
- }
-
- // Check if any eigenvalue equals Ο^n
- print("\nChecking Ο^n patterns:\n", .{});
- for (spins) |j| {
- const ev = casimirEigenvalue(j);
- for (0..11) |n_idx| {
- const n = @as(i32, @intCast(n_idx)) - 3;
- const phi_n = math.pow(f64, PHI, @as(f64, @floatFromInt(n)));
- const rel_error = @abs(ev - phi_n) / phi_n;
- if (rel_error < 0.001) {
- print(" β({d:.1}Γ{d:.1}) = {d:.6} β Ο^{d} = {d:.6} (error: {d:.6}%)\n", .{ j, j + 1.0, ev, n, phi_n, rel_error * 100.0 });
- }
- }
- }
-
- print("\n{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n", .{ MAGENTA, RESET });
- print("{s}β ANALYSIS COMPLETE β SEE DOCUMENTATION FOR DETAILS β{s}\n", .{ GOLD, RESET });
- print("{s}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{s}\n\n", .{ MAGENTA, RESET });
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ENTRY POINT
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn main() !void {
- analyzeAllSpins();
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "Casimir eigenvalue for j=1/2" {
- const ev = casimirEigenvalue(0.5);
- const expected = math.sqrt(0.5 * 1.5); // β0.75
- try std.testing.expectApproxEqRel(expected, ev, 1e-10);
-}
-
-test "Casimir eigenvalue for j=1" {
- const ev = casimirEigenvalue(1.0);
- const expected = math.sqrt(1.0 * 2.0); // β2
- try std.testing.expectApproxEqRel(expected, ev, 1e-10);
-}
-
-test "Lucas number L_2 = 3 = TRINITY" {
- const L_2 = lucasNumber(2);
- try std.testing.expectApproxEqRel(3.0, L_2, 1e-10);
-}
-
-test "GAMMA = Ο^(-3)" {
- const gamma_calc = 1.0 / math.pow(f64, PHI, 3.0);
- try std.testing.expectApproxEqRel(GAMMA, gamma_calc, 1e-10);
-}
-
-test "β(8/3) is close to Ο" {
- const sqrt_8_3 = math.sqrt(8.0 / 3.0);
- const rel_error = @abs(sqrt_8_3 - PHI) / PHI;
- try std.testing.expect(rel_error < 0.01); // Within 1%
-}
-
-test "Area eigenvalue scales with GAMMA" {
- const j = 1.0;
- const A1 = areaEigenvalue(j);
- const casimir = casimirEigenvalue(j);
- const expected = GAMMA * casimir;
- try std.testing.expectApproxEqRel(expected, A1, 1e-10);
-}
diff --git a/src/hslm/cli.zig b/src/hslm/cli.zig
new file mode 100644
index 0000000000..526c67e98c
--- /dev/null
+++ b/src/hslm/cli.zig
@@ -0,0 +1,6 @@
+const std = @import("std");
+
+pub fn main() !u8 {
+ std.debug.print("HSLM CLI - Working\\n", .{});
+ return 0;
+}
diff --git a/src/hslm/test_cli.zig b/src/hslm/test_cli.zig
new file mode 100644
index 0000000000..9967260f8e
--- /dev/null
+++ b/src/hslm/test_cli.zig
@@ -0,0 +1,6 @@
+const std = @import("std");
+
+pub fn main() !u8 {
+ std.debug.print("HSLM CLI - Test build\\n", .{});
+ return 0;
+}
diff --git a/src/jit_arm64.zig b/src/jit_arm64.zig
deleted file mode 100644
index 84949d340f..0000000000
--- a/src/jit_arm64.zig
+++ /dev/null
@@ -1,2175 +0,0 @@
-// @origin(spec:jit_arm64.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity JIT Compiler - ARM64 (AArch64) Backend
-// Compiles VSA operations to native ARM64 machine code
-//
-// β²€β²β²β²’β² β²ͺβ²β²’β²β²¨β²β²: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// ΟΒ² + 1/ΟΒ² = 3
-
-const std = @import("std");
-const builtin = @import("builtin");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ARM64 JIT COMPILER
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Check if we're on ARM64
-pub const is_arm64 = builtin.cpu.arch == .aarch64;
-
-/// ARM64 JIT Compiler
-pub const Arm64JitCompiler = struct {
- code: std.ArrayListUnmanaged(u8),
- allocator: std.mem.Allocator,
- exec_mem: ?[]align(std.heap.page_size_min) u8 = null,
-
- const Self = @This();
-
- pub fn init(allocator: std.mem.Allocator) Self {
- return Self{
- .code = .{},
- .allocator = allocator,
- };
- }
-
- pub fn deinit(self: *Self) void {
- self.code.deinit(self.allocator);
- if (self.exec_mem) |mem| {
- std.posix.munmap(mem);
- }
- }
-
- pub fn reset(self: *Self) void {
- self.code.clearRetainingCapacity();
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // ARM64 INSTRUCTION ENCODING HELPERS
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Emit a 32-bit ARM64 instruction (little-endian)
- fn emit32(self: *Self, instr: u32) !void {
- try self.code.appendSlice(self.allocator, &std.mem.toBytes(instr));
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // ARM64 REGISTER ENCODING
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // X registers (64-bit): x0-x30, sp=31, xzr=31
- // W registers (32-bit): w0-w30, wzr=31
- const x0: u5 = 0;
- const x1: u5 = 1;
- const x2: u5 = 2;
- const x3: u5 = 3;
- const x8: u5 = 8; // indirect result
- const x9: u5 = 9; // temp
- const x10: u5 = 10; // temp
- const x11: u5 = 11; // temp
- const x12: u5 = 12; // temp
- const x13: u5 = 13; // temp
- const x14: u5 = 14; // temp
- const x15: u5 = 15; // temp
- const x19: u5 = 19; // callee-saved
- const x20: u5 = 20; // callee-saved
- const x21: u5 = 21; // callee-saved
- const x22: u5 = 22; // callee-saved
- const x29: u5 = 29; // frame pointer (fp)
- const x30: u5 = 30; // link register (lr)
- const sp: u5 = 31; // stack pointer
- const xzr: u5 = 31; // zero register
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // ARM64 INSTRUCTION BUILDERS
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// STP (Store Pair) - stp Xt1, Xt2, [Xn, #imm]! (pre-index)
- fn stpPreIndex(self: *Self, rt1: u5, rt2: u5, rn: u5, imm7: i7) !void {
- // STP (pre-index, 64-bit): 1 01 0 100 1 1 imm7 Rt2 Rn Rt1
- const uimm: u7 = @bitCast(imm7);
- const instr: u32 = 0xA9800000 |
- (@as(u32, uimm) << 15) |
- (@as(u32, rt2) << 10) |
- (@as(u32, rn) << 5) |
- @as(u32, rt1);
- try self.emit32(instr);
- }
-
- /// LDP (Load Pair) - ldp Xt1, Xt2, [Xn], #imm (post-index)
- fn ldpPostIndex(self: *Self, rt1: u5, rt2: u5, rn: u5, imm7: i7) !void {
- // LDP (post-index, 64-bit): 1 01 0 100 0 1 1 imm7 Rt2 Rn Rt1
- const uimm: u7 = @bitCast(imm7);
- const instr: u32 = 0xA8C00000 |
- (@as(u32, uimm) << 15) |
- (@as(u32, rt2) << 10) |
- (@as(u32, rn) << 5) |
- @as(u32, rt1);
- try self.emit32(instr);
- }
-
- /// MOV (register) - mov Xd, Xn (actually ORR Xd, XZR, Xn)
- fn movReg(self: *Self, rd: u5, rn: u5) !void {
- // ORR (shifted register): 1 01 01010 00 0 Rm 000000 Rn Rd
- const instr: u32 = 0xAA000000 |
- (@as(u32, rn) << 16) |
- (@as(u32, xzr) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// MOV (immediate) - mov Xd, #imm16
- fn movImm16(self: *Self, rd: u5, imm16: u16, shift: u2) !void {
- // MOVZ: 1 10 100101 hw imm16 Rd
- const instr: u32 = 0xD2800000 |
- (@as(u32, shift) << 21) |
- (@as(u32, imm16) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// MOVK (keep) - movk Xd, #imm16, lsl #shift
- fn movkImm16(self: *Self, rd: u5, imm16: u16, shift: u2) !void {
- // MOVK: 1 11 100101 hw imm16 Rd
- const instr: u32 = 0xF2800000 |
- (@as(u32, shift) << 21) |
- (@as(u32, imm16) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// Load 64-bit immediate into register
- fn loadImm64(self: *Self, rd: u5, imm: u64) !void {
- const imm0: u16 = @truncate(imm);
- const imm1: u16 = @truncate(imm >> 16);
- const imm2: u16 = @truncate(imm >> 32);
- const imm3: u16 = @truncate(imm >> 48);
-
- try self.movImm16(rd, imm0, 0);
- if (imm1 != 0) try self.movkImm16(rd, imm1, 1);
- if (imm2 != 0) try self.movkImm16(rd, imm2, 2);
- if (imm3 != 0) try self.movkImm16(rd, imm3, 3);
- }
-
- /// ADD (immediate) - add Xd, Xn, #imm12
- fn addImm(self: *Self, rd: u5, rn: u5, imm12: u12) !void {
- // ADD (imm): 1 00 100010 0 imm12 Rn Rd
- const instr: u32 = 0x91000000 |
- (@as(u32, imm12) << 10) |
- (@as(u32, rn) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// SUB (immediate) - sub Xd, Xn, #imm12
- fn subImm(self: *Self, rd: u5, rn: u5, imm12: u12) !void {
- // SUB (imm): 1 10 100010 0 imm12 Rn Rd
- const instr: u32 = 0xD1000000 |
- (@as(u32, imm12) << 10) |
- (@as(u32, rn) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// ADD (register) - add Xd, Xn, Xm
- fn addReg(self: *Self, rd: u5, rn: u5, rm: u5) !void {
- // ADD (reg): 1 00 01011 00 0 Rm 000000 Rn Rd
- const instr: u32 = 0x8B000000 |
- (@as(u32, rm) << 16) |
- (@as(u32, rn) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// MUL - mul Xd, Xn, Xm (actually MADD Xd, Xn, Xm, XZR)
- fn mul(self: *Self, rd: u5, rn: u5, rm: u5) !void {
- // MADD: 1 00 11011 000 Rm 0 Ra Rn Rd
- const instr: u32 = 0x9B000000 |
- (@as(u32, rm) << 16) |
- (@as(u32, xzr) << 10) |
- (@as(u32, rn) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// SMULL - smull Xd, Wn, Wm (signed multiply long)
- fn smull(self: *Self, rd: u5, rn: u5, rm: u5) !void {
- // SMULL: 1 00 11011 0 01 Rm 0 11111 Rn Rd
- const instr: u32 = 0x9B207C00 |
- (@as(u32, rm) << 16) |
- (@as(u32, rn) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// LDRSB (register) - ldrsb Wt, [Xn, Xm]
- fn ldrsbReg(self: *Self, rt: u5, rn: u5, rm: u5) !void {
- // LDRSB (reg, 32-bit): 00 111 0 00 11 1 Rm 011 0 10 Rn Rt
- const instr: u32 = 0x38E06800 |
- (@as(u32, rm) << 16) |
- (@as(u32, rn) << 5) |
- @as(u32, rt);
- try self.emit32(instr);
- }
-
- /// LDRB (register) - ldrb Wt, [Xn, Xm]
- fn ldrbReg(self: *Self, rt: u5, rn: u5, rm: u5) !void {
- // LDRB (reg): 00 111 0 00 01 1 Rm 011 0 10 Rn Rt
- const instr: u32 = 0x38606800 |
- (@as(u32, rm) << 16) |
- (@as(u32, rn) << 5) |
- @as(u32, rt);
- try self.emit32(instr);
- }
-
- /// STRB (register) - strb Wt, [Xn, Xm]
- fn strbReg(self: *Self, rt: u5, rn: u5, rm: u5) !void {
- // STRB (reg): 00 111 0 00 00 1 Rm 011 0 10 Rn Rt
- const instr: u32 = 0x38206800 |
- (@as(u32, rm) << 16) |
- (@as(u32, rn) << 5) |
- @as(u32, rt);
- try self.emit32(instr);
- }
-
- /// CMP (immediate) - cmp Xn, #imm12
- fn cmpImm(self: *Self, rn: u5, imm12: u12) !void {
- // SUBS XZR, Xn, #imm12
- const instr: u32 = 0xF1000000 |
- (@as(u32, imm12) << 10) |
- (@as(u32, rn) << 5) |
- @as(u32, xzr);
- try self.emit32(instr);
- }
-
- /// CMP (register) - cmp Xn, Xm
- fn cmpReg(self: *Self, rn: u5, rm: u5) !void {
- // SUBS XZR, Xn, Xm
- const instr: u32 = 0xEB000000 |
- (@as(u32, rm) << 16) |
- (@as(u32, rn) << 5) |
- @as(u32, xzr);
- try self.emit32(instr);
- }
-
- /// B.cond - conditional branch
- fn bcond(self: *Self, cond: u4, offset: i19) !void {
- // B.cond: 0101010 0 imm19 0 cond
- const uoffset: u19 = @bitCast(offset);
- const instr: u32 = 0x54000000 |
- (@as(u32, uoffset) << 5) |
- @as(u32, cond);
- try self.emit32(instr);
- }
-
- /// B - unconditional branch
- fn b(self: *Self, offset: i26) !void {
- // B: 0 00101 imm26
- const uoffset: u26 = @bitCast(offset);
- const instr: u32 = 0x14000000 | @as(u32, uoffset);
- try self.emit32(instr);
- }
-
- /// RET - return
- fn retInstr(self: *Self) !void {
- // RET {Xn}: 1101011 0 0 10 11111 0000 0 0 Rn 00000
- const instr: u32 = 0xD65F0000 | (@as(u32, x30) << 5);
- try self.emit32(instr);
- }
-
- /// CSET - cset Xd, cond
- fn cset(self: *Self, rd: u5, cond: u4) !void {
- // CSINC Xd, XZR, XZR, invert(cond)
- const inv_cond = cond ^ 1;
- const instr: u32 = 0x9A9F0400 |
- (@as(u32, inv_cond) << 12) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- /// CSNEG - conditional select negate
- fn csneg(self: *Self, rd: u5, rn: u5, rm: u5, cond: u4) !void {
- // CSNEG: 1 1 0 11010100 Rm cond 0 1 Rn Rd
- const instr: u32 = 0xDA800400 |
- (@as(u32, rm) << 16) |
- (@as(u32, cond) << 12) |
- (@as(u32, rn) << 5) |
- @as(u32, rd);
- try self.emit32(instr);
- }
-
- // Condition codes
- const COND_EQ: u4 = 0; // Equal
- const COND_NE: u4 = 1; // Not equal
- const COND_GE: u4 = 10; // Signed >=
- const COND_LT: u4 = 11; // Signed <
- const COND_GT: u4 = 12; // Signed >
- const COND_LE: u4 = 13; // Signed <=
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // NEON SIMD REGISTERS AND INSTRUCTIONS
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // NEON vector registers V0-V31 (128-bit)
- // Use same encoding as X registers (0-31)
- const v0: u5 = 0;
- const v1: u5 = 1;
- const v2: u5 = 2;
- const v3: u5 = 3;
- const v4: u5 = 4;
- const v5: u5 = 5;
- const v6: u5 = 6;
- const v7: u5 = 7;
- const v16: u5 = 16; // callee-saved v8-v15, so use v16+ for temps
- const v17: u5 = 17;
- const v18: u5 = 18;
- const v19: u5 = 19;
-
- /// LD1 {Vt.16B}, [Xn] - Load 16 bytes into vector register
- fn ld1_16b(self: *Self, vt: u5, xn: u5) !void {
- // LD1 (single structure, no offset): 0 1 001100 0 10 0000 0111 00 Rn Rt
- // Q=1 (128-bit), size=00 (8-bit), opcode=0111
- const instr: u32 = 0x4C407000 |
- (@as(u32, xn) << 5) |
- @as(u32, vt);
- try self.emit32(instr);
- }
-
- /// LD1 {Vt.16B}, [Xn], #16 - Load 16 bytes with post-increment
- fn ld1_16b_post(self: *Self, vt: u5, xn: u5) !void {
- // LD1 (single structure, post-index, imm): 0 1 001100 1 10 11111 0111 00 Rn Rt
- const instr: u32 = 0x4CDF7000 |
- (@as(u32, xn) << 5) |
- @as(u32, vt);
- try self.emit32(instr);
- }
-
- /// SDOT Vd.4S, Vn.16B, Vm.16B - Signed dot product (ARMv8.4-A)
- /// Computes 4 dot products of 4 signed i8 values each, accumulates into 4 x i32
- fn sdot_4s(self: *Self, vd: u5, vn: u5, vm: u5) !void {
- // SDOT: 0 1 0 01110 10 0 Rm 1 0010 1 Rn Rd
- // Q=1 (128-bit), size=10, Rm, opcode=10010, U=0 (signed)
- const instr: u32 = 0x4E809400 |
- (@as(u32, vm) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// ADDV Sd, Vn.4S - Add across vector lanes to scalar
- fn addv_4s(self: *Self, vd: u5, vn: u5) !void {
- // ADDV: 0 1 0 01110 10 11000 1 1011 10 Rn Rd
- const instr: u32 = 0x4EB1B800 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// SMOV Xd, Vn.S[index] - Signed move from vector element to GPR
- fn smov_s(self: *Self, xd: u5, vn: u5, index: u2) !void {
- // SMOV: 0 1 0 0111 0 00 0 imm5 0 0101 1 Rn Rd
- // For S (32-bit) element, imm5 = (index << 3) | 0b00100
- const imm5: u5 = (@as(u5, index) << 3) | 0b00100;
- const instr: u32 = 0x4E002C00 |
- (@as(u32, imm5) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, xd);
- try self.emit32(instr);
- }
-
- /// MOVI Vd.4S, #0 - Move immediate to vector (zero vector)
- fn movi_4s_zero(self: *Self, vd: u5) !void {
- // MOVI: 0 1 0 01111 00000 cmode=0000 op=0 1 a:b:c:d:e:f:g:h Rd
- // For all zeros: cmode=0000, imm8=0
- const instr: u32 = 0x4F000400 |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// MOVI Vd.16B, #imm8 - Move immediate to vector (all bytes)
- fn movi_16b(self: *Self, vd: u5, imm8: u8) !void {
- // MOVI (16B): for zero just use simplified encoding
- if (imm8 == 0) {
- // Zero vector - use simple encoding
- const instr: u32 = 0x4F000400 | @as(u32, vd);
- try self.emit32(instr);
- } else {
- // Non-zero - full encoding
- const bit7 = (imm8 >> 7) & 1;
- const bit6 = (imm8 >> 6) & 1;
- const bit5 = (imm8 >> 5) & 1;
- const bit4 = (imm8 >> 4) & 1;
- const bit3 = (imm8 >> 3) & 1;
- const bit2 = (imm8 >> 2) & 1;
- const bit1 = (imm8 >> 1) & 1;
- const bit0 = imm8 & 1;
- const instr: u32 = 0x4F00E400 |
- (@as(u32, bit7) << 18) |
- (@as(u32, bit6) << 17) |
- (@as(u32, bit5) << 16) |
- (@as(u32, bit4) << 11) |
- (@as(u32, bit3) << 10) |
- (@as(u32, bit2) << 9) |
- (@as(u32, bit1) << 8) |
- (@as(u32, bit0) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
- }
-
- /// SUB Xd, Xn, Xm - 64-bit register subtract
- fn subReg(self: *Self, xd: u5, xn: u5, xm: u5) !void {
- const instr: u32 = 0xCB000000 |
- (@as(u32, xm) << 16) |
- (@as(u32, xn) << 5) |
- @as(u32, xd);
- try self.emit32(instr);
- }
-
- /// CSET Xd, GT - Set if greater than
- fn csetGT(self: *Self, xd: u5) !void {
- // CSET GT = CSINC Xd, XZR, XZR, LE (cond=1101)
- const instr: u32 = 0x9A9FD7E0 | @as(u32, xd);
- try self.emit32(instr);
- }
-
- /// CSET Xd, LT - Set if less than
- fn csetLT(self: *Self, xd: u5) !void {
- // CSET LT = CSINC Xd, XZR, XZR, GE (cond=1010)
- const instr: u32 = 0x9A9FA7E0 | @as(u32, xd);
- try self.emit32(instr);
- }
-
- /// DUP Vd.4S, Xn - Duplicate GPR to all vector lanes
- fn dup_4s_gpr(self: *Self, vd: u5, xn: u5) !void {
- // DUP (general): 0 1 0 01110 00 0 imm5 0 0001 1 Rn Rd
- // For 4S, imm5 = 00100
- const instr: u32 = 0x4E040C00 |
- (@as(u32, xn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// ST1 {Vt.16B}, [Xn] - Store 16 bytes from vector register
- fn st1_16b(self: *Self, vt: u5, xn: u5) !void {
- // ST1 (single structure, no offset): 0 1 001100 0 00 0000 0111 00 Rn Rt
- const instr: u32 = 0x4C007000 |
- (@as(u32, xn) << 5) |
- @as(u32, vt);
- try self.emit32(instr);
- }
-
- /// ST1 {Vt.16B}, [Xn], #16 - Store 16 bytes with post-increment
- fn st1_16b_post(self: *Self, vt: u5, xn: u5) !void {
- // ST1 (single structure, post-index, imm): 0 1 001100 1 00 11111 0111 00 Rn Rt
- const instr: u32 = 0x4C9F7000 |
- (@as(u32, xn) << 5) |
- @as(u32, vt);
- try self.emit32(instr);
- }
-
- /// MUL Vd.16B, Vn.16B, Vm.16B - Vector multiply (16 x i8)
- fn mul_16b(self: *Self, vd: u5, vn: u5, vm: u5) !void {
- // MUL (vector): 0 1 0 01110 00 1 Rm 1 00111 Rn Rd
- const instr: u32 = 0x4E209C00 |
- (@as(u32, vm) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// CMEQ Vd.16B, Vn.16B, Vm.16B - Compare equal (sets 0xFF where equal, 0 where not)
- fn cmeq_16b(self: *Self, vd: u5, vn: u5, vm: u5) !void {
- // CMEQ (register): 0 1 1 01110 00 1 Rm 1 00011 Rn Rd
- const instr: u32 = 0x6E208C00 |
- (@as(u32, vm) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// NOT Vd.16B, Vn.16B - Bitwise NOT
- fn not_16b(self: *Self, vd: u5, vn: u5) !void {
- // NOT: 0 1 1 01110 00 10000 00101 10 Rn Rd
- const instr: u32 = 0x6E205800 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// CNT Vd.16B, Vn.16B - Population count per byte
- fn cnt_16b(self: *Self, vd: u5, vn: u5) !void {
- // CNT: 0 1 0 01110 00 10000 00101 10 Rn Rd
- const instr: u32 = 0x4E205800 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// UADDLV Hd, Vn.16B - Unsigned add long across vector (sum all bytes to u16)
- fn uaddlv_h(self: *Self, vd: u5, vn: u5) !void {
- // UADDLV: 0 1 1 01110 00 11000 0 0011 10 Rn Rd
- const instr: u32 = 0x6E303800 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// UMOV Wd, Vn.H[0] - Unsigned move from vector element to GPR (16-bit)
- fn umov_h(self: *Self, wd: u5, vn: u5, index: u3) !void {
- // UMOV: 0 0 0 01110 00 0 imm5 0 0111 1 Rn Rd
- // For H (16-bit) element, imm5 = (index << 1) | 0b00010
- const imm5: u5 = (@as(u5, index) << 1) | 0b00010;
- const instr: u32 = 0x0E003C00 |
- (@as(u32, imm5) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, wd);
- try self.emit32(instr);
- }
-
- /// USHR Vd.16B, Vn.16B, #shift - Unsigned shift right
- fn ushr_16b(self: *Self, vd: u5, vn: u5, shift: u4) !void {
- // USHR: 0 1 1 01111 0 shift 00000 1 Rn Rd
- // For 16B: Q=1, immh:immb encodes shift, for 8-bit elements immh=0001, immb=8-shift
- // Actually: 0 1 1 01111 immh immb 0 0000 1 Rn Rd
- // immh=0001 for 8-bit, immb = (8 - shift) for shift amount
- const immh: u4 = 0b0001;
- const immb: u3 = @intCast(8 - shift);
- const instr: u32 = 0x6F080400 |
- (@as(u32, immh) << 19) |
- (@as(u32, immb) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// ADDV Bd, Vn.16B - Add across vector (8-bit result for byte vectors)
- fn addv_16b(self: *Self, vd: u5, vn: u5) !void {
- // ADDV: 0 1 0 01110 00 11000 1 1011 10 Rn Rd
- // Q=1, size=00 (8-bit)
- const instr: u32 = 0x4E31B800 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// UMOV Wd, Vn.B[0] - Unsigned move from vector byte element to GPR
- fn umov_b(self: *Self, wd: u5, vn: u5, index: u4) !void {
- // UMOV: 0 0 0 01110 00 0 imm5 0 0111 1 Rn Rd
- // For B (8-bit) element, imm5 = (index << 1) | 0b00001
- const imm5: u5 = (@as(u5, index) << 1) | 0b00001;
- const instr: u32 = 0x0E003C00 |
- (@as(u32, imm5) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, wd);
- try self.emit32(instr);
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // BUNDLE SIMD INSTRUCTIONS (for ternary thresholding)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// ADD Vd.16B, Vn.16B, Vm.16B - Vector add (16 bytes)
- fn add_16b(self: *Self, vd: u5, vn: u5, vm: u5) !void {
- const instr: u32 = 0x4E208400 |
- (@as(u32, vm) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// SSHR Vd.16B, Vn.16B, #7 - Signed shift right (arithmetic) by 7
- fn sshr_16b_7(self: *Self, vd: u5, vn: u5) !void {
- // For shift by 7 on 8-bit: immh:immb = 16-7 = 9
- const instr: u32 = 0x4F090400 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// CMGT Vd.16B, Vn.16B, #0 - Compare greater than zero
- fn cmgt_16b_zero(self: *Self, vd: u5, vn: u5) !void {
- const instr: u32 = 0x4E20A800 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// NEG Vd.16B, Vn.16B - Vector negate
- fn neg_16b(self: *Self, vd: u5, vn: u5) !void {
- const instr: u32 = 0x6E20B800 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// ORR Vd.16B, Vn.16B, Vm.16B - Bitwise OR
- fn orr_16b(self: *Self, vd: u5, vn: u5, vm: u5) !void {
- const instr: u32 = 0x4EA01C00 |
- (@as(u32, vm) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // FLOATING POINT INSTRUCTIONS (for cosine computation)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- // FP double registers D0-D3 (same encoding as V registers)
- const d0: u5 = 0;
- const d1: u5 = 1;
- const d2: u5 = 2;
- const d3: u5 = 3;
-
- /// SCVTF Dd, Xn - Signed integer to double precision float
- fn scvtf_d_x(self: *Self, vd: u5, xn: u5) !void {
- const instr: u32 = 0x9E620000 |
- (@as(u32, xn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// FMUL Dd, Dn, Dm - Floating point multiply (double)
- fn fmul_d(self: *Self, vd: u5, vn: u5, vm: u5) !void {
- const instr: u32 = 0x1E600800 |
- (@as(u32, vm) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// FSQRT Dd, Dn - Floating point square root (double)
- fn fsqrt_d(self: *Self, vd: u5, vn: u5) !void {
- const instr: u32 = 0x1E61C000 |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// FDIV Dd, Dn, Dm - Floating point divide (double)
- fn fdiv_d(self: *Self, vd: u5, vn: u5, vm: u5) !void {
- const instr: u32 = 0x1E601800 |
- (@as(u32, vm) << 16) |
- (@as(u32, vn) << 5) |
- @as(u32, vd);
- try self.emit32(instr);
- }
-
- /// FMOV Xd, Dn - Move f64 from FP register to GPR
- fn fmov_x_d(self: *Self, xd: u5, vn: u5) !void {
- const instr: u32 = 0x9E660000 |
- (@as(u32, vn) << 5) |
- @as(u32, xd);
- try self.emit32(instr);
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // VSA OPERATION COMPILATION
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Compile dot product for ARM64
- /// Returns i64 in x0
- pub fn compileDotProduct(self: *Self, dimension: usize) !void {
- self.reset();
-
- // Function prologue: save fp, lr
- try self.stpPreIndex(x29, x30, sp, -2); // stp x29, x30, [sp, #-16]!
- try self.movReg(x29, sp); // mov x29, sp
-
- // Save callee-saved registers
- try self.stpPreIndex(x19, x20, sp, -2); // stp x19, x20, [sp, #-16]!
- try self.stpPreIndex(x21, x22, sp, -2); // stp x21, x22, [sp, #-16]!
-
- // x19 = a pointer (first arg is in x0)
- // x20 = b pointer (second arg is in x1)
- // x21 = accumulator
- // x22 = loop counter
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
- try self.movImm16(x21, 0, 0); // accumulator = 0
- try self.movImm16(x22, 0, 0); // counter = 0
-
- // Load dimension into x9
- if (dimension <= 0xFFFF) {
- try self.movImm16(x9, @intCast(dimension), 0);
- } else {
- try self.loadImm64(x9, dimension);
- }
-
- // Loop start
- const loop_start = self.code.items.len;
-
- // Compare counter with dimension
- try self.cmpReg(x22, x9);
-
- // B.GE to loop end (will patch)
- const bge_offset = self.code.items.len;
- try self.bcond(COND_GE, 0); // placeholder
-
- // Load a[i] sign-extended into w10
- try self.ldrsbReg(x10, x19, x22);
-
- // Load b[i] sign-extended into w11
- try self.ldrsbReg(x11, x20, x22);
-
- // Multiply: x10 = x10 * x11
- try self.smull(x10, x10, x11);
-
- // Add to accumulator: x21 = x21 + x10
- try self.addReg(x21, x21, x10);
-
- // Increment counter
- try self.addImm(x22, x22, 1);
-
- // Branch back to loop start
- const loop_end_check = self.code.items.len;
- const back_offset: i26 = @intCast(@divExact(@as(i32, @intCast(loop_start)) - @as(i32, @intCast(loop_end_check)), 4));
- try self.b(back_offset);
-
- // Loop end - patch the conditional branch
- const loop_end = self.code.items.len;
- const forward_offset: i19 = @intCast(@divExact(@as(i32, @intCast(loop_end)) - @as(i32, @intCast(bge_offset)), 4));
- const patched_instr: u32 = 0x54000000 |
- (@as(u32, @as(u19, @bitCast(forward_offset))) << 5) |
- @as(u32, COND_GE);
- @memcpy(self.code.items[bge_offset..][0..4], &std.mem.toBytes(patched_instr));
-
- // Move result to x0
- try self.movReg(x0, x21);
-
- // Restore callee-saved registers
- try self.ldpPostIndex(x21, x22, sp, 2); // ldp x21, x22, [sp], #16
- try self.ldpPostIndex(x19, x20, sp, 2); // ldp x19, x20, [sp], #16
-
- // Function epilogue
- try self.ldpPostIndex(x29, x30, sp, 2); // ldp x29, x30, [sp], #16
- try self.retInstr();
- }
-
- /// Compile SIMD dot product using NEON SDOT instruction (ARMv8.4-A)
- /// Processes 16 elements per iteration (4x speedup potential)
- /// Requires: dimension >= 16 and dimension % 16 == 0
- pub fn compileDotProductSIMD(self: *Self, dimension: usize) !void {
- if (dimension < 16 or dimension % 16 != 0) {
- return error.InvalidDimension;
- }
-
- self.reset();
-
- // Function prologue
- try self.stpPreIndex(x29, x30, sp, -2);
- try self.movReg(x29, sp);
- try self.stpPreIndex(x19, x20, sp, -2);
-
- // x19 = a pointer, x20 = b pointer
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
-
- // v0 = accumulator (initialized to zero)
- try self.movi_4s_zero(v0);
-
- // x9 = dimension / 16 (number of SIMD iterations)
- const num_iters = dimension / 16;
- if (num_iters <= 0xFFFF) {
- try self.movImm16(x9, @intCast(num_iters), 0);
- } else {
- try self.loadImm64(x9, num_iters);
- }
-
- // x10 = loop counter
- try self.movImm16(x10, 0, 0);
-
- // SIMD loop: process 16 elements per iteration
- const loop_start = self.code.items.len;
-
- // Compare counter with num_iters
- try self.cmpReg(x10, x9);
- const bge_offset = self.code.items.len;
- try self.bcond(COND_GE, 0); // placeholder, patch later
-
- // Load 16 bytes from a into v1
- try self.ld1_16b_post(v1, x19);
-
- // Load 16 bytes from b into v2
- try self.ld1_16b_post(v2, x20);
-
- // SDOT: v0.4s += dot(v1.16b, v2.16b)
- // This computes 4 dot products of 4 i8 values each
- try self.sdot_4s(v0, v1, v2);
-
- // Increment counter
- try self.addImm(x10, x10, 1);
-
- // Branch back to loop start
- const loop_end_check = self.code.items.len;
- const back_offset: i26 = @intCast(@divExact(@as(i32, @intCast(loop_start)) - @as(i32, @intCast(loop_end_check)), 4));
- try self.b(back_offset);
-
- // Loop end - patch conditional branch
- const loop_end = self.code.items.len;
- const forward_offset: i19 = @intCast(@divExact(@as(i32, @intCast(loop_end)) - @as(i32, @intCast(bge_offset)), 4));
- const patched_instr: u32 = 0x54000000 |
- (@as(u32, @as(u19, @bitCast(forward_offset))) << 5) |
- @as(u32, COND_GE);
- @memcpy(self.code.items[bge_offset..][0..4], &std.mem.toBytes(patched_instr));
-
- // Horizontal add: sum all 4 lanes of v0.4s into scalar
- try self.addv_4s(v0, v0); // v0.s[0] = sum of all lanes
-
- // Move result from vector to x0 (sign-extended)
- try self.smov_s(x0, v0, 0);
-
- // Restore callee-saved registers
- try self.ldpPostIndex(x19, x20, sp, 2);
-
- // Function epilogue
- try self.ldpPostIndex(x29, x30, sp, 2);
- try self.retInstr();
- }
-
- /// Compile hybrid SIMD + scalar dot product for ANY dimension
- /// Uses SIMD for (dim/16)*16 elements, scalar for remainder
- pub fn compileDotProductHybrid(self: *Self, dimension: usize) !void {
- self.reset();
-
- const simd_iters = dimension / 16;
- const remainder = dimension % 16;
-
- // Function prologue
- try self.stpPreIndex(x29, x30, sp, -2);
- try self.movReg(x29, sp);
- try self.stpPreIndex(x19, x20, sp, -2);
- try self.stpPreIndex(x21, x22, sp, -2);
-
- // x19 = a pointer, x20 = b pointer
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
-
- // v0 = SIMD accumulator (zero)
- try self.movi_4s_zero(v0);
-
- // x21 = scalar accumulator (zero)
- try self.movImm16(x21, 0, 0);
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // SIMD LOOP: Process 16 elements per iteration
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- if (simd_iters > 0) {
- // x9 = number of SIMD iterations
- if (simd_iters <= 0xFFFF) {
- try self.movImm16(x9, @intCast(simd_iters), 0);
- } else {
- try self.loadImm64(x9, simd_iters);
- }
-
- // x10 = SIMD loop counter
- try self.movImm16(x10, 0, 0);
-
- const simd_loop_start = self.code.items.len;
-
- // Compare counter with num_iters
- try self.cmpReg(x10, x9);
- const simd_bge_offset = self.code.items.len;
- try self.bcond(COND_GE, 0); // placeholder
-
- // Load 16 bytes from a into v1, post-increment x19
- try self.ld1_16b_post(v1, x19);
-
- // Load 16 bytes from b into v2, post-increment x20
- try self.ld1_16b_post(v2, x20);
-
- // SDOT: v0.4s += dot(v1.16b, v2.16b)
- try self.sdot_4s(v0, v1, v2);
-
- // Increment counter
- try self.addImm(x10, x10, 1);
-
- // Branch back to loop start
- const simd_loop_end_check = self.code.items.len;
- const simd_back_offset: i26 = @intCast(@divExact(@as(i32, @intCast(simd_loop_start)) - @as(i32, @intCast(simd_loop_end_check)), 4));
- try self.b(simd_back_offset);
-
- // Patch SIMD loop exit
- const simd_loop_end = self.code.items.len;
- const simd_forward_offset: i19 = @intCast(@divExact(@as(i32, @intCast(simd_loop_end)) - @as(i32, @intCast(simd_bge_offset)), 4));
- const simd_patched_instr: u32 = 0x54000000 |
- (@as(u32, @as(u19, @bitCast(simd_forward_offset))) << 5) |
- @as(u32, COND_GE);
- @memcpy(self.code.items[simd_bge_offset..][0..4], &std.mem.toBytes(simd_patched_instr));
-
- // Horizontal add SIMD result to scalar
- try self.addv_4s(v0, v0);
- try self.smov_s(x21, v0, 0);
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // SCALAR LOOP: Process remaining elements one by one
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- if (remainder > 0) {
- // x9 = remainder count
- try self.movImm16(x9, @intCast(remainder), 0);
-
- // x10 = scalar loop counter
- try self.movImm16(x10, 0, 0);
-
- const scalar_loop_start = self.code.items.len;
-
- // Compare counter with remainder
- try self.cmpReg(x10, x9);
- const scalar_bge_offset = self.code.items.len;
- try self.bcond(COND_GE, 0); // placeholder
-
- // Load a[i] sign-extended
- try self.ldrsbReg(x11, x19, x10);
-
- // Load b[i] sign-extended
- try self.ldrsbReg(x22, x20, x10);
-
- // Multiply
- try self.smull(x11, x11, x22);
-
- // Add to accumulator
- try self.addReg(x21, x21, x11);
-
- // Increment counter
- try self.addImm(x10, x10, 1);
-
- // Branch back
- const scalar_loop_end_check = self.code.items.len;
- const scalar_back_offset: i26 = @intCast(@divExact(@as(i32, @intCast(scalar_loop_start)) - @as(i32, @intCast(scalar_loop_end_check)), 4));
- try self.b(scalar_back_offset);
-
- // Patch scalar loop exit
- const scalar_loop_end = self.code.items.len;
- const scalar_forward_offset: i19 = @intCast(@divExact(@as(i32, @intCast(scalar_loop_end)) - @as(i32, @intCast(scalar_bge_offset)), 4));
- const scalar_patched_instr: u32 = 0x54000000 |
- (@as(u32, @as(u19, @bitCast(scalar_forward_offset))) << 5) |
- @as(u32, COND_GE);
- @memcpy(self.code.items[scalar_bge_offset..][0..4], &std.mem.toBytes(scalar_patched_instr));
- }
-
- // Move result to x0
- try self.movReg(x0, x21);
-
- // Restore callee-saved registers
- try self.ldpPostIndex(x21, x22, sp, 2);
- try self.ldpPostIndex(x19, x20, sp, 2);
-
- // Function epilogue
- try self.ldpPostIndex(x29, x30, sp, 2);
- try self.retInstr();
- }
-
- /// Compile bind operation for ARM64
- pub fn compileBindDirect(self: *Self, dimension: usize) !void {
- self.reset();
-
- // Function prologue
- try self.stpPreIndex(x29, x30, sp, -2);
- try self.movReg(x29, sp);
- try self.stpPreIndex(x19, x20, sp, -2);
- try self.stpPreIndex(x21, x22, sp, -2);
-
- // x19 = a pointer, x20 = b pointer, x21 = dimension, x22 = counter
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
- try self.movImm16(x22, 0, 0);
-
- if (dimension <= 0xFFFF) {
- try self.movImm16(x21, @intCast(dimension), 0);
- } else {
- try self.loadImm64(x21, dimension);
- }
-
- const loop_start = self.code.items.len;
- try self.cmpReg(x22, x21);
-
- const bge_offset = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- // Load a[i] and b[i]
- try self.ldrsbReg(x10, x19, x22);
- try self.ldrsbReg(x11, x20, x22);
-
- // Multiply (for ternary: -1*-1=1, -1*1=-1, 1*-1=-1, 1*1=1, 0*x=0)
- try self.smull(x10, x10, x11);
-
- // Store result
- try self.strbReg(x10, x19, x22);
-
- try self.addImm(x22, x22, 1);
-
- const loop_end_check = self.code.items.len;
- const back_offset: i26 = @intCast(@divExact(@as(i32, @intCast(loop_start)) - @as(i32, @intCast(loop_end_check)), 4));
- try self.b(back_offset);
-
- const loop_end = self.code.items.len;
- const forward_offset: i19 = @intCast(@divExact(@as(i32, @intCast(loop_end)) - @as(i32, @intCast(bge_offset)), 4));
- const patched_instr: u32 = 0x54000000 |
- (@as(u32, @as(u19, @bitCast(forward_offset))) << 5) |
- @as(u32, COND_GE);
- @memcpy(self.code.items[bge_offset..][0..4], &std.mem.toBytes(patched_instr));
-
- try self.ldpPostIndex(x21, x22, sp, 2);
- try self.ldpPostIndex(x19, x20, sp, 2);
- try self.ldpPostIndex(x29, x30, sp, 2);
- try self.retInstr();
- }
-
- /// Compile SIMD bind operation using NEON vector multiply
- /// Processes 16 elements per iteration
- pub fn compileBindSIMD(self: *Self, dimension: usize) !void {
- self.reset();
-
- // Function prologue
- try self.stpPreIndex(x29, x30, sp, -2);
- try self.movReg(x29, sp);
- try self.stpPreIndex(x19, x20, sp, -2);
- try self.stpPreIndex(x21, x22, sp, -2);
-
- // x19 = a pointer (modified in place), x20 = b pointer
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
-
- // SIMD loop for dimension / 16 iterations
- const simd_iters = dimension / 16;
- if (simd_iters > 0) {
- if (simd_iters <= 0xFFFF) {
- try self.movImm16(x21, @intCast(simd_iters), 0);
- } else {
- try self.loadImm64(x21, simd_iters);
- }
- try self.movImm16(x22, 0, 0); // counter
-
- const simd_loop = self.code.items.len;
- try self.cmpReg(x22, x21);
- const bge_simd = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- // Load 16 bytes from a and b
- try self.ld1_16b(v0, x19);
- try self.ld1_16b(v1, x20);
-
- // Multiply: v0 = v0 * v1 (element-wise i8 multiply)
- try self.mul_16b(v0, v0, v1);
-
- // Store result back to a with post-increment
- try self.st1_16b_post(v0, x19);
-
- // Advance b pointer
- try self.addImm(x20, x20, 16);
-
- // Increment counter
- try self.addImm(x22, x22, 1);
-
- const simd_end_check = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(simd_loop)) - @as(i32, @intCast(simd_end_check)), 4));
- try self.b(back);
-
- // Patch branch
- const simd_end = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(simd_end)) - @as(i32, @intCast(bge_simd)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_simd..][0..4], &std.mem.toBytes(patched));
- }
-
- // Scalar loop for remainder (dimension % 16)
- const remainder = dimension % 16;
- if (remainder > 0) {
- try self.movImm16(x21, @intCast(remainder), 0);
- try self.movImm16(x22, 0, 0);
-
- const scalar_loop = self.code.items.len;
- try self.cmpReg(x22, x21);
- const bge_scalar = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- try self.ldrsbReg(x10, x19, x22);
- try self.ldrsbReg(x11, x20, x22);
- try self.smull(x10, x10, x11);
- try self.strbReg(x10, x19, x22);
- try self.addImm(x22, x22, 1);
-
- const scalar_end_check = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(scalar_loop)) - @as(i32, @intCast(scalar_end_check)), 4));
- try self.b(back);
-
- const scalar_end = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(scalar_end)) - @as(i32, @intCast(bge_scalar)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_scalar..][0..4], &std.mem.toBytes(patched));
- }
-
- try self.ldpPostIndex(x21, x22, sp, 2);
- try self.ldpPostIndex(x19, x20, sp, 2);
- try self.ldpPostIndex(x29, x30, sp, 2);
- try self.retInstr();
- }
-
- /// Compile SIMD hamming distance using NEON compare
- /// Counts positions where a[i] != b[i]
- pub fn compileHammingSIMD(self: *Self, dimension: usize) !void {
- self.reset();
-
- // Function prologue
- try self.stpPreIndex(x29, x30, sp, -2);
- try self.movReg(x29, sp);
- try self.stpPreIndex(x19, x20, sp, -2);
- try self.stpPreIndex(x21, x22, sp, -2);
-
- // x19 = a pointer, x20 = b pointer, x21 = accumulator
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
- try self.movImm16(x21, 0, 0); // hamming distance = 0
-
- // SIMD loop for dimension / 16 iterations
- const simd_iters = dimension / 16;
- if (simd_iters > 0) {
- if (simd_iters <= 0xFFFF) {
- try self.movImm16(x9, @intCast(simd_iters), 0);
- } else {
- try self.loadImm64(x9, simd_iters);
- }
- try self.movImm16(x22, 0, 0); // counter
-
- const simd_loop = self.code.items.len;
- try self.cmpReg(x22, x9);
- const bge_simd = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- // Load 16 bytes from a and b with post-increment
- try self.ld1_16b_post(v0, x19);
- try self.ld1_16b_post(v1, x20);
-
- // Compare equal: v2 = (v0 == v1) ? 0xFF : 0x00
- try self.cmeq_16b(v2, v0, v1);
-
- // NOT: v2 = (v0 != v1) ? 0xFF : 0x00
- try self.not_16b(v2, v2);
-
- // Shift right by 7: 0xFF >> 7 = 1, 0x00 >> 7 = 0
- // Now each byte is 1 if positions differ, 0 if same
- try self.ushr_16b(v2, v2, 7);
-
- // Sum all 16 bytes into a single value
- try self.addv_16b(v3, v2); // v3.b[0] = sum of all bytes
-
- // Move byte to GPR
- try self.umov_b(x10, v3, 0);
-
- // Add to accumulator
- try self.addReg(x21, x21, x10);
-
- // Increment counter
- try self.addImm(x22, x22, 1);
-
- const simd_end_check = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(simd_loop)) - @as(i32, @intCast(simd_end_check)), 4));
- try self.b(back);
-
- const simd_end = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(simd_end)) - @as(i32, @intCast(bge_simd)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_simd..][0..4], &std.mem.toBytes(patched));
- }
-
- // Scalar loop for remainder
- const remainder = dimension % 16;
- if (remainder > 0) {
- try self.movImm16(x9, @intCast(remainder), 0);
- try self.movImm16(x22, 0, 0);
-
- const scalar_loop = self.code.items.len;
- try self.cmpReg(x22, x9);
- const bge_scalar = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- try self.ldrsbReg(x10, x19, x22);
- try self.ldrsbReg(x11, x20, x22);
-
- // Compare and increment if not equal
- try self.cmpReg(x10, x11);
- // CSINC x10, xzr, xzr, EQ -> x10 = (EQ) ? 0 : 1
- const csinc: u32 = 0x9A9F07E0 | // CSINC Xd, XZR, XZR, cond
- (@as(u32, COND_EQ) << 12) |
- @as(u32, x10);
- try self.emit32(csinc);
- try self.addReg(x21, x21, x10);
-
- try self.addImm(x22, x22, 1);
-
- const scalar_end_check = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(scalar_loop)) - @as(i32, @intCast(scalar_end_check)), 4));
- try self.b(back);
-
- const scalar_end = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(scalar_end)) - @as(i32, @intCast(bge_scalar)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_scalar..][0..4], &std.mem.toBytes(patched));
- }
-
- // Return result
- try self.movReg(x0, x21);
-
- try self.ldpPostIndex(x21, x22, sp, 2);
- try self.ldpPostIndex(x19, x20, sp, 2);
- try self.ldpPostIndex(x29, x30, sp, 2);
- try self.retInstr();
- }
-
- /// Compile fused cosine: dot_ab, dot_aa, dot_bb in single pass
- /// Returns f64 bit pattern: cos = dot_ab / sqrt(dot_aa * dot_bb)
- pub fn compileFusedCosine(self: *Self, dimension: usize) !void {
- self.reset();
-
- try self.stpPreIndex(x29, x30, sp, -2);
- try self.movReg(x29, sp);
- try self.stpPreIndex(x19, x20, sp, -2);
- try self.stpPreIndex(x21, x22, sp, -2);
-
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
-
- // Three accumulators
- try self.movi_16b(v2, 0);
- try self.movi_16b(v3, 0);
- try self.movi_16b(v4, 0);
-
- const simd_iters = dimension / 16;
- if (simd_iters > 0) {
- if (simd_iters <= 0xFFFF) {
- try self.movImm16(x9, @intCast(simd_iters), 0);
- } else {
- try self.loadImm64(x9, simd_iters);
- }
- try self.movImm16(x21, 0, 0);
-
- const simd_loop = self.code.items.len;
- try self.cmpReg(x21, x9);
- const bge_simd = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- try self.ld1_16b_post(v0, x19);
- try self.ld1_16b_post(v1, x20);
- try self.sdot_4s(v2, v0, v1);
- try self.sdot_4s(v3, v0, v0);
- try self.sdot_4s(v4, v1, v1);
- try self.addImm(x21, x21, 1);
-
- const simd_end = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(simd_loop)) - @as(i32, @intCast(simd_end)), 4));
- try self.b(back);
-
- const simd_exit = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(simd_exit)) - @as(i32, @intCast(bge_simd)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_simd..][0..4], &std.mem.toBytes(patched));
- }
-
- try self.addv_4s(v2, v2);
- try self.addv_4s(v3, v3);
- try self.addv_4s(v4, v4);
- try self.smov_s(x10, v2, 0);
- try self.smov_s(x11, v3, 0);
- try self.smov_s(x12, v4, 0);
-
- const remainder = dimension % 16;
- if (remainder > 0) {
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
- const offset = simd_iters * 16;
- if (offset > 0) {
- try self.loadImm64(x9, offset);
- try self.addReg(x19, x19, x9);
- try self.addReg(x20, x20, x9);
- }
-
- try self.movImm16(x9, @intCast(remainder), 0);
- try self.movImm16(x21, 0, 0);
-
- const scalar_loop = self.code.items.len;
- try self.cmpReg(x21, x9);
- const bge_scalar = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- try self.ldrsbReg(x13, x19, x21);
- try self.ldrsbReg(x14, x20, x21);
- try self.mul(x15, x13, x14);
- try self.addReg(x10, x10, x15);
- try self.mul(x15, x13, x13);
- try self.addReg(x11, x11, x15);
- try self.mul(x15, x14, x14);
- try self.addReg(x12, x12, x15);
- try self.addImm(x21, x21, 1);
-
- const scalar_end = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(scalar_loop)) - @as(i32, @intCast(scalar_end)), 4));
- try self.b(back);
-
- const scalar_exit = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(scalar_exit)) - @as(i32, @intCast(bge_scalar)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_scalar..][0..4], &std.mem.toBytes(patched));
- }
-
- try self.scvtf_d_x(d0, x10);
- try self.scvtf_d_x(d1, x11);
- try self.scvtf_d_x(d2, x12);
- try self.fmul_d(d1, d1, d2);
- try self.fsqrt_d(d1, d1);
- try self.fdiv_d(d0, d0, d1);
- try self.fmov_x_d(x0, d0);
-
- try self.ldpPostIndex(x21, x22, sp, 2);
- try self.ldpPostIndex(x19, x20, sp, 2);
- try self.ldpPostIndex(x29, x30, sp, 2);
- try self.retInstr();
- }
-
- /// Compile bundle SIMD: result[i] = threshold(a[i] + b[i])
- pub fn compileBundleSIMD(self: *Self, dimension: usize) !void {
- self.reset();
-
- try self.stpPreIndex(x29, x30, sp, -2);
- try self.movReg(x29, sp);
- try self.stpPreIndex(x19, x20, sp, -2);
- try self.stpPreIndex(x21, x22, sp, -2);
-
- try self.movReg(x19, x0);
- try self.movReg(x20, x1);
- try self.movReg(x21, x0);
-
- const simd_iters = dimension / 16;
- if (simd_iters > 0) {
- if (simd_iters <= 0xFFFF) {
- try self.movImm16(x9, @intCast(simd_iters), 0);
- } else {
- try self.loadImm64(x9, simd_iters);
- }
- try self.movImm16(x22, 0, 0);
-
- const simd_loop = self.code.items.len;
- try self.cmpReg(x22, x9);
- const bge_simd = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- try self.ld1_16b_post(v0, x21);
- try self.ld1_16b_post(v1, x20);
- try self.add_16b(v2, v0, v1);
- try self.sshr_16b_7(v3, v2);
- try self.cmgt_16b_zero(v4, v2);
- try self.neg_16b(v4, v4);
- try self.orr_16b(v2, v3, v4);
- try self.st1_16b_post(v2, x19);
- try self.addImm(x22, x22, 1);
-
- const simd_end = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(simd_loop)) - @as(i32, @intCast(simd_end)), 4));
- try self.b(back);
-
- const simd_exit = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(simd_exit)) - @as(i32, @intCast(bge_simd)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_simd..][0..4], &std.mem.toBytes(patched));
- }
-
- const remainder = dimension % 16;
- if (remainder > 0) {
- try self.movImm16(x9, @intCast(remainder), 0);
- try self.movImm16(x22, 0, 0);
-
- const scalar_loop = self.code.items.len;
- try self.cmpReg(x22, x9);
- const bge_scalar = self.code.items.len;
- try self.bcond(COND_GE, 0);
-
- try self.ldrsbReg(x10, x21, x22);
- try self.ldrsbReg(x11, x20, x22);
- try self.addReg(x10, x10, x11);
- try self.cmpImm(x10, 0);
- try self.movImm16(x11, 0, 0);
- try self.csetGT(x11);
- try self.movImm16(x12, 0, 0);
- try self.csetLT(x12);
- try self.subReg(x10, x11, x12);
- try self.strbReg(x10, x19, x22);
- try self.addImm(x22, x22, 1);
-
- const scalar_end = self.code.items.len;
- const back: i26 = @intCast(@divExact(@as(i32, @intCast(scalar_loop)) - @as(i32, @intCast(scalar_end)), 4));
- try self.b(back);
-
- const scalar_exit = self.code.items.len;
- const fwd: i19 = @intCast(@divExact(@as(i32, @intCast(scalar_exit)) - @as(i32, @intCast(bge_scalar)), 4));
- const patched: u32 = 0x54000000 | (@as(u32, @as(u19, @bitCast(fwd))) << 5) | @as(u32, COND_GE);
- @memcpy(self.code.items[bge_scalar..][0..4], &std.mem.toBytes(patched));
- }
-
- try self.ldpPostIndex(x21, x22, sp, 2);
- try self.ldpPostIndex(x19, x20, sp, 2);
- try self.ldpPostIndex(x29, x30, sp, 2);
- try self.retInstr();
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // EXECUTION
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Make code executable and return function pointer
- pub fn finalize(self: *Self) !*const fn (*anyopaque, *anyopaque) callconv(.c) i64 {
- const code_size = self.code.items.len;
- if (code_size == 0) return error.EmptyCode;
-
- // ARM64 can have 16KB pages on Apple Silicon
- const page_size: usize = 16384;
- const alloc_size = std.mem.alignForward(usize, code_size, page_size);
-
- const mem = try std.posix.mmap(
- null,
- alloc_size,
- std.posix.PROT.READ | std.posix.PROT.WRITE,
- .{ .TYPE = .PRIVATE, .ANONYMOUS = true },
- -1,
- 0,
- );
-
- @memcpy(mem[0..code_size], self.code.items);
-
- try std.posix.mprotect(mem, std.posix.PROT.READ | std.posix.PROT.EXEC);
-
- self.exec_mem = mem;
-
- return @ptrCast(mem.ptr);
- }
-
- pub fn codeSize(self: *const Self) usize {
- return self.code.items.len;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "ARM64 JIT compiler init and deinit" {
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- try std.testing.expectEqual(@as(usize, 0), compiler.codeSize());
-}
-
-test "ARM64 JIT dot product compilation" {
- if (!is_arm64) {
- return; // Skip on non-ARM64
- }
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 8;
- try compiler.compileDotProduct(dim);
-
- // Code should be generated
- try std.testing.expect(compiler.codeSize() > 0);
- // ARM64 instructions are 4 bytes each
- try std.testing.expect(compiler.codeSize() % 4 == 0);
-}
-
-test "ARM64 JIT dot product execution" {
- if (!is_arm64) {
- return; // Skip on non-ARM64
- }
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 8;
- try compiler.compileDotProduct(dim);
-
- const func = try compiler.finalize();
-
- // Create test data
- const a = [dim]i8{ 1, -1, 1, 0, 1, -1, 0, 1 };
- const b = [dim]i8{ 1, 1, -1, 1, 1, 1, 1, -1 };
-
- // Expected: 1*1 + (-1)*1 + 1*(-1) + 0*1 + 1*1 + (-1)*1 + 0*1 + 1*(-1)
- // = 1 - 1 - 1 + 0 + 1 - 1 + 0 - 1 = -2
- const expected: i64 = -2;
-
- var a_mut = a;
- var b_mut = b;
- const result = func(@ptrCast(&a_mut), @ptrCast(&b_mut));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 JIT bind compilation" {
- if (!is_arm64) {
- return;
- }
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 8;
- try compiler.compileBindDirect(dim);
-
- try std.testing.expect(compiler.codeSize() > 0);
- try std.testing.expect(compiler.codeSize() % 4 == 0);
-}
-
-test "ARM64 NEON SIMD dot product compilation" {
- if (!is_arm64) {
- return; // Skip on non-ARM64
- }
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 64; // Must be multiple of 16
- try compiler.compileDotProductSIMD(dim);
-
- try std.testing.expect(compiler.codeSize() > 0);
- try std.testing.expect(compiler.codeSize() % 4 == 0);
-}
-
-test "ARM64 NEON SIMD dot product execution" {
- if (!is_arm64) {
- return; // Skip on non-ARM64
- }
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 16; // Minimum SIMD dimension
- try compiler.compileDotProductSIMD(dim);
-
- const func = try compiler.finalize();
-
- // Create test data: all 1s dot all 1s = 16
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = 1;
- }
-
- const expected: i64 = 16;
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 NEON SIMD dot product with mixed values" {
- if (!is_arm64) {
- return; // Skip on non-ARM64
- }
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 32;
- try compiler.compileDotProductSIMD(dim);
-
- const func = try compiler.finalize();
-
- // Create test data: alternating 1, -1
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- for (0..dim) |i| {
- a[i] = if (i % 2 == 0) 1 else -1;
- b[i] = 1;
- }
- // Expected: 16 * 1 + 16 * (-1) = 0
- const expected: i64 = 0;
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 NEON SIMD dot product large dimension" {
- if (!is_arm64) {
- return; // Skip on non-ARM64
- }
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 256; // 16 SIMD iterations
- try compiler.compileDotProductSIMD(dim);
-
- const func = try compiler.finalize();
-
- // Create test data
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: i64 = 0;
- for (0..dim) |i| {
- // Ternary values: -1, 0, 1
- const val_a: i8 = @intCast(@as(i32, @intCast(i % 3)) - 1);
- const val_b: i8 = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- a[i] = val_a;
- b[i] = val_b;
- expected += @as(i64, val_a) * @as(i64, val_b);
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 NEON SIMD benchmark vs scalar" {
- if (!is_arm64) {
- return; // Skip on non-ARM64
- }
-
- const dim = 1024; // Large dimension for meaningful benchmark
- const iterations = 10000;
-
- // Prepare test data
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- for (0..dim) |i| {
- a[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- b[i] = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- }
-
- // Compile scalar version
- var scalar_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer scalar_compiler.deinit();
- try scalar_compiler.compileDotProduct(dim);
- const scalar_func = try scalar_compiler.finalize();
-
- // Compile SIMD version
- var simd_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer simd_compiler.deinit();
- try simd_compiler.compileDotProductSIMD(dim);
- const simd_func = try simd_compiler.finalize();
-
- // Benchmark scalar
- var timer = try std.time.Timer.start();
- var scalar_result: i64 = 0;
- for (0..iterations) |_| {
- scalar_result = scalar_func(@ptrCast(&a), @ptrCast(&b));
- }
- const scalar_ns = timer.read();
-
- // Benchmark SIMD
- timer.reset();
- var simd_result: i64 = 0;
- for (0..iterations) |_| {
- simd_result = simd_func(@ptrCast(&a), @ptrCast(&b));
- }
- const simd_ns = timer.read();
-
- // Verify results match
- try std.testing.expectEqual(scalar_result, simd_result);
-
- // Print benchmark results
- const scalar_ms = @as(f64, @floatFromInt(scalar_ns)) / 1_000_000.0;
- const simd_ms = @as(f64, @floatFromInt(simd_ns)) / 1_000_000.0;
- const speedup = scalar_ms / simd_ms;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" ARM64 NEON SIMD BENCHMARK RESULTS\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Dimension: {d} elements\n", .{dim});
- std.debug.print(" Iterations: {d}\n", .{iterations});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Scalar: {d:.3} ms ({d:.0} ns/iter)\n", .{ scalar_ms, @as(f64, @floatFromInt(scalar_ns)) / @as(f64, iterations) });
- std.debug.print(" SIMD: {d:.3} ms ({d:.0} ns/iter)\n", .{ simd_ms, @as(f64, @floatFromInt(simd_ns)) / @as(f64, iterations) });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" SPEEDUP: {d:.2}x\n", .{speedup});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Assert SIMD is faster (relaxed for CI/heavy-load environments)
- try std.testing.expect(speedup > 0.8);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HYBRID SIMD + SCALAR TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "ARM64 hybrid dot product - aligned dimension (32)" {
- if (!is_arm64) return;
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 32; // Aligned: 2 SIMD iters, 0 scalar
- try compiler.compileDotProductHybrid(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: i64 = 0;
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = 1;
- expected += 1;
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 hybrid dot product - non-aligned dimension (17)" {
- if (!is_arm64) return;
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 17; // Non-aligned: 1 SIMD iter + 1 scalar
- try compiler.compileDotProductHybrid(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: i64 = 0;
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = 1;
- expected += 1;
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 hybrid dot product - small dimension (7)" {
- if (!is_arm64) return;
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 7; // Pure scalar: 0 SIMD iters, 7 scalar
- try compiler.compileDotProductHybrid(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: i64 = 0;
- for (0..dim) |i| {
- const val_a: i8 = if (i % 2 == 0) 1 else -1;
- a[i] = val_a;
- b[i] = 1;
- expected += val_a;
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 hybrid dot product - dimension 100" {
- if (!is_arm64) return;
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 100; // 6 SIMD iters + 4 scalar
- try compiler.compileDotProductHybrid(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: i64 = 0;
- for (0..dim) |i| {
- const val_a: i8 = @intCast(@as(i32, @intCast(i % 3)) - 1);
- const val_b: i8 = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- a[i] = val_a;
- b[i] = val_b;
- expected += @as(i64, val_a) * @as(i64, val_b);
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 hybrid dot product - dimension 1000" {
- if (!is_arm64) return;
-
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 1000; // 62 SIMD iters + 8 scalar
- try compiler.compileDotProductHybrid(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: i64 = 0;
- for (0..dim) |i| {
- const val_a: i8 = @intCast(@as(i32, @intCast(i % 3)) - 1);
- const val_b: i8 = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- a[i] = val_a;
- b[i] = val_b;
- expected += @as(i64, val_a) * @as(i64, val_b);
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "ARM64 hybrid benchmark vs pure scalar" {
- if (!is_arm64) return;
-
- const dim = 1000; // Non-aligned dimension
- const iterations = 10000;
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- for (0..dim) |i| {
- a[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- b[i] = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- }
-
- // Compile pure scalar
- var scalar_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer scalar_compiler.deinit();
- try scalar_compiler.compileDotProduct(dim);
- const scalar_func = try scalar_compiler.finalize();
-
- // Compile hybrid
- var hybrid_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer hybrid_compiler.deinit();
- try hybrid_compiler.compileDotProductHybrid(dim);
- const hybrid_func = try hybrid_compiler.finalize();
-
- // Benchmark scalar
- var timer = try std.time.Timer.start();
- var scalar_result: i64 = 0;
- for (0..iterations) |_| {
- scalar_result = scalar_func(@ptrCast(&a), @ptrCast(&b));
- }
- const scalar_ns = timer.read();
-
- // Benchmark hybrid
- timer.reset();
- var hybrid_result: i64 = 0;
- for (0..iterations) |_| {
- hybrid_result = hybrid_func(@ptrCast(&a), @ptrCast(&b));
- }
- const hybrid_ns = timer.read();
-
- // Verify results match
- try std.testing.expectEqual(scalar_result, hybrid_result);
-
- const scalar_ms = @as(f64, @floatFromInt(scalar_ns)) / 1_000_000.0;
- const hybrid_ms = @as(f64, @floatFromInt(hybrid_ns)) / 1_000_000.0;
- const speedup = scalar_ms / hybrid_ms;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" ARM64 HYBRID SIMD+SCALAR BENCHMARK (dim=1000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" SIMD iters: {d}, Scalar remainder: {d}\n", .{ dim / 16, dim % 16 });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Pure Scalar: {d:.3} ms ({d:.0} ns/iter)\n", .{ scalar_ms, @as(f64, @floatFromInt(scalar_ns)) / @as(f64, iterations) });
- std.debug.print(" Hybrid: {d:.3} ms ({d:.0} ns/iter)\n", .{ hybrid_ms, @as(f64, @floatFromInt(hybrid_ns)) / @as(f64, iterations) });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" SPEEDUP: {d:.2}x\n", .{speedup});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Hybrid should be faster (lenient threshold for flaky benchmarks on loaded systems)
- // Minimum 1.0x means it's not slower - any speedup is acceptable
- try std.testing.expect(speedup > 1.0);
-}
-
-test "ARM64 SIMD bind correctness" {
- if (!is_arm64) return;
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 64;
- try compiler.compileBindSIMD(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: [dim]i8 = undefined;
-
- // Initialize: a = [1, -1, 0, 1, ...], b = [1, 1, -1, -1, ...]
- for (0..dim) |i| {
- a[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- b[i] = if (i % 4 < 2) @as(i8, 1) else @as(i8, -1);
- expected[i] = a[i] * b[i];
- }
-
- // Run SIMD bind (modifies a in place)
- _ = func(@ptrCast(&a), @ptrCast(&b));
-
- // Verify
- for (0..dim) |i| {
- try std.testing.expectEqual(expected[i], a[i]);
- }
-}
-
-test "ARM64 SIMD bind non-aligned dimension" {
- if (!is_arm64) return;
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 100; // Not divisible by 16
- try compiler.compileBindSIMD(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: [dim]i8 = undefined;
-
- for (0..dim) |i| {
- a[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- b[i] = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- expected[i] = a[i] * b[i];
- }
-
- _ = func(@ptrCast(&a), @ptrCast(&b));
-
- for (0..dim) |i| {
- try std.testing.expectEqual(expected[i], a[i]);
- }
-}
-
-test "ARM64 SIMD hamming correctness" {
- if (!is_arm64) return;
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 64;
- try compiler.compileHammingSIMD(dim);
- const func = try compiler.finalize();
-
- // Test 1: identical vectors -> hamming = 0
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = 1;
- }
- const hamming_identical = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(@as(i64, 0), hamming_identical);
-
- // Test 2: all different -> hamming = dim
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = -1;
- }
- const hamming_all_diff = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(@as(i64, dim), hamming_all_diff);
-
- // Test 3: half different
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = if (i < dim / 2) @as(i8, 1) else @as(i8, -1);
- }
- const hamming_half = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(@as(i64, dim / 2), hamming_half);
-}
-
-test "ARM64 SIMD hamming non-aligned dimension" {
- if (!is_arm64) return;
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 100; // Not divisible by 16
- try compiler.compileHammingSIMD(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
-
- // Count expected differences manually
- var expected_hamming: i64 = 0;
- for (0..dim) |i| {
- a[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- b[i] = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- if (a[i] != b[i]) expected_hamming += 1;
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected_hamming, result);
-}
-
-test "ARM64 SIMD bind benchmark vs scalar" {
- if (!is_arm64) return;
- const dim = 1024;
- const iterations = 10000;
-
- var a_simd: [dim]i8 = undefined;
- var a_scalar: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
-
- for (0..dim) |i| {
- const val = @as(i8, @intCast(@as(i32, @intCast(i % 3)) - 1));
- a_simd[i] = val;
- a_scalar[i] = val;
- b[i] = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- }
-
- // Compile SIMD
- var simd_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer simd_compiler.deinit();
- try simd_compiler.compileBindSIMD(dim);
- const simd_func = try simd_compiler.finalize();
-
- // Compile scalar
- var scalar_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer scalar_compiler.deinit();
- try scalar_compiler.compileBindDirect(dim);
- const scalar_func = try scalar_compiler.finalize();
-
- // Benchmark SIMD
- var timer = try std.time.Timer.start();
- for (0..iterations) |_| {
- // Reset a for fair comparison
- for (0..dim) |i| {
- a_simd[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- }
- _ = simd_func(@ptrCast(&a_simd), @ptrCast(&b));
- }
- const simd_ns = timer.read();
-
- // Benchmark scalar
- timer.reset();
- for (0..iterations) |_| {
- for (0..dim) |i| {
- a_scalar[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- }
- _ = scalar_func(@ptrCast(&a_scalar), @ptrCast(&b));
- }
- const scalar_ns = timer.read();
-
- const simd_ms = @as(f64, @floatFromInt(simd_ns)) / 1_000_000.0;
- const scalar_ms = @as(f64, @floatFromInt(scalar_ns)) / 1_000_000.0;
- const speedup = scalar_ms / simd_ms;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" ARM64 SIMD BIND BENCHMARK (dim={d})\n", .{dim});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Scalar: {d:.3} ms\n", .{scalar_ms});
- std.debug.print(" SIMD: {d:.3} ms\n", .{simd_ms});
- std.debug.print(" SPEEDUP: {d:.2}x\n", .{speedup});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Note: Bind speedup modest due to array reset overhead
-}
-
-test "ARM64 fused cosine correctness" {
- if (!is_arm64) return;
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 64;
- try compiler.compileFusedCosine(dim);
- const func = try compiler.finalize();
-
- // Test identical vectors: cos = 1.0
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = 1;
- }
-
- const result_bits = func(@ptrCast(&a), @ptrCast(&b));
- const result: f64 = @bitCast(result_bits);
- try std.testing.expectApproxEqRel(@as(f64, 1.0), result, 0.001);
-
- // Test opposite vectors: cos = -1.0
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = -1;
- }
- const neg_bits = func(@ptrCast(&a), @ptrCast(&b));
- const neg_result: f64 = @bitCast(neg_bits);
- try std.testing.expectApproxEqRel(@as(f64, -1.0), neg_result, 0.001);
-}
-
-test "ARM64 fused cosine benchmark vs 3x dot" {
- if (!is_arm64) return;
- var fused_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer fused_compiler.deinit();
- var dot_compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer dot_compiler.deinit();
-
- const dim = 1024;
- const iterations = 10000;
-
- try fused_compiler.compileFusedCosine(dim);
- const fused_func = try fused_compiler.finalize();
-
- try dot_compiler.compileDotProductHybrid(dim);
- const dot_func = try dot_compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- for (0..dim) |i| {
- a[i] = @intCast(@as(i32, @intCast(i % 3)) - 1);
- b[i] = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- }
-
- // Benchmark fused
- var timer = try std.time.Timer.start();
- var fused_result: f64 = 0;
- for (0..iterations) |_| {
- const bits = fused_func(@ptrCast(&a), @ptrCast(&b));
- fused_result = @bitCast(bits);
- }
- const fused_ns = timer.read();
-
- // Benchmark 3x dot
- timer.reset();
- var dot_result: f64 = 0;
- for (0..iterations) |_| {
- const dot_ab = dot_func(@ptrCast(&a), @ptrCast(&b));
- const dot_aa = dot_func(@ptrCast(&a), @ptrCast(&a));
- const dot_bb = dot_func(@ptrCast(&b), @ptrCast(&b));
- const norm = @sqrt(@as(f64, @floatFromInt(dot_aa)) * @as(f64, @floatFromInt(dot_bb)));
- dot_result = @as(f64, @floatFromInt(dot_ab)) / norm;
- }
- const dot_ns = timer.read();
-
- const fused_ms = @as(f64, @floatFromInt(fused_ns)) / 1_000_000.0;
- const dot_ms = @as(f64, @floatFromInt(dot_ns)) / 1_000_000.0;
- const speedup = dot_ms / fused_ms;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" ARM64 FUSED COSINE BENCHMARK (dim={d})\n", .{dim});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 3x Dot: {d:.3} ms\n", .{dot_ms});
- std.debug.print(" Fused: {d:.3} ms\n", .{fused_ms});
- std.debug.print(" SPEEDUP: {d:.2}x\n", .{speedup});
- std.debug.print(" Results: fused={d:.6}, 3xdot={d:.6}\n", .{ fused_result, dot_result });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
-
-test "ARM64 bundle SIMD compilation" {
- if (!is_arm64) return;
- // Just verify compilation works, bundle correctness tested via vsa_jit
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 32;
- try compiler.compileBundleSIMD(dim);
- const func = try compiler.finalize();
- _ = func;
-}
-
-test "ARM64 bundle SIMD non-aligned" {
- if (!is_arm64) return;
- var compiler = Arm64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 23; // Non-aligned
- try compiler.compileBundleSIMD(dim);
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
-
- for (0..dim) |i| {
- a[i] = 1;
- b[i] = 1;
- }
-
- _ = func(@ptrCast(&a), @ptrCast(&b));
- // Bundle SIMD correctness to be verified via integration tests
-}
diff --git a/src/jit_x86_64.zig b/src/jit_x86_64.zig
deleted file mode 100644
index 104242a4c9..0000000000
--- a/src/jit_x86_64.zig
+++ /dev/null
@@ -1,471 +0,0 @@
-// @origin(spec:jit_x86_64.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity JIT Compiler - x86-64 Backend
-// Compiles VSA operations to native x86-64 machine code
-//
-// β²€β²β²β²’β² β²ͺβ²β²’β²β²¨β²β²: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// ΟΒ² + 1/ΟΒ² = 3
-
-const std = @import("std");
-const builtin = @import("builtin");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// X86-64 JIT COMPILER
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Check if we're on x86-64
-pub const is_x86_64 = builtin.cpu.arch == .x86_64;
-
-/// X86-64 JIT Compiler
-pub const X86_64JitCompiler = struct {
- code: std.ArrayListUnmanaged(u8),
- allocator: std.mem.Allocator,
- exec_mem: ?[]align(std.heap.page_size_min) u8 = null,
-
- const Self = @This();
-
- pub fn init(allocator: std.mem.Allocator) Self {
- return Self{
- .code = .{},
- .allocator = allocator,
- };
- }
-
- pub fn deinit(self: *Self) void {
- self.code.deinit(self.allocator);
- if (self.exec_mem) |mem| {
- std.posix.munmap(mem);
- }
- }
-
- pub fn reset(self: *Self) void {
- self.code.clearRetainingCapacity();
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // X86-64 INSTRUCTION ENCODING HELPERS
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Emit raw bytes
- fn emit(self: *Self, bytes: []const u8) !void {
- try self.code.appendSlice(self.allocator, bytes);
- }
-
- /// Emit single byte
- fn emit1(self: *Self, b: u8) !void {
- try self.code.append(self.allocator, b);
- }
-
- /// Emit 32-bit immediate (little-endian)
- fn emitImm32(self: *Self, imm: i32) !void {
- try self.code.appendSlice(self.allocator, std.mem.asBytes(&imm));
- }
-
- /// Emit 64-bit immediate (little-endian)
- fn emitImm64(self: *Self, imm: i64) !void {
- try self.code.appendSlice(self.allocator, std.mem.asBytes(&imm));
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // X86-64 INSTRUCTION ENCODING
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// push rbp
- fn pushRbp(self: *Self) !void {
- try self.emit1(0x55);
- }
-
- /// pop rbp
- fn popRbp(self: *Self) !void {
- try self.emit1(0x5D);
- }
-
- /// mov rbp, rsp
- fn movRbpRsp(self: *Self) !void {
- try self.emit(&[_]u8{ 0x48, 0x89, 0xE5 });
- }
-
- /// mov rsp, rbp
- fn movRspRbp(self: *Self) !void {
- try self.emit(&[_]u8{ 0x48, 0x89, 0xEC });
- }
-
- /// ret
- fn ret(self: *Self) !void {
- try self.emit1(0xC3);
- }
-
- /// xor eax, eax (zero rax)
- fn xorEaxEax(self: *Self) !void {
- try self.emit(&[_]u8{ 0x31, 0xC0 });
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // VSA OPERATION COMPILATION
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Compile dot product (returns i64 in rax)
- /// x86-64 System V ABI: rdi = first arg, rsi = second arg, rax = return
- pub fn compileDotProduct(self: *Self, dimension: usize) !void {
- self.reset();
-
- // Function prologue
- try self.pushRbp();
- try self.movRbpRsp();
-
- // Save callee-saved registers
- try self.emit(&[_]u8{0x53}); // push rbx
- try self.emit(&[_]u8{ 0x41, 0x54 }); // push r12
- try self.emit(&[_]u8{ 0x41, 0x55 }); // push r13
- try self.emit(&[_]u8{ 0x41, 0x56 }); // push r14
-
- // r12 = a pointer (from rdi)
- try self.emit(&[_]u8{ 0x49, 0x89, 0xFC }); // mov r12, rdi
-
- // r13 = b pointer (from rsi)
- try self.emit(&[_]u8{ 0x49, 0x89, 0xF5 }); // mov r13, rsi
-
- // r14 = accumulator (0)
- try self.emit(&[_]u8{ 0x4D, 0x31, 0xF6 }); // xor r14, r14
-
- // rbx = loop counter (0)
- try self.xorEaxEax();
- try self.emit(&[_]u8{ 0x48, 0x89, 0xC3 }); // mov rbx, rax
-
- const loop_start = self.code.items.len;
-
- // Compare rbx with dimension
- try self.emit(&[_]u8{ 0x48, 0x81, 0xFB }); // cmp rbx, imm32
- try self.emitImm32(@intCast(dimension));
-
- // jge loop_end
- try self.emit(&[_]u8{ 0x0F, 0x8D }); // jge rel32
- const jge_offset = self.code.items.len;
- try self.emitImm32(0); // placeholder
-
- // Load a[rbx] into eax (sign-extended)
- try self.emit(&[_]u8{ 0x41, 0x0F, 0xBE, 0x04, 0x1C }); // movsx eax, byte [r12 + rbx]
-
- // Load b[rbx] into ecx (sign-extended)
- try self.emit(&[_]u8{ 0x41, 0x0F, 0xBE, 0x4C, 0x1D, 0x00 }); // movsx ecx, byte [r13 + rbx]
-
- // imul eax, ecx
- try self.emit(&[_]u8{ 0x0F, 0xAF, 0xC1 }); // imul eax, ecx
-
- // Sign-extend eax to rax
- try self.emit(&[_]u8{ 0x48, 0x98 }); // cdqe
-
- // Add to accumulator: r14 += rax
- try self.emit(&[_]u8{ 0x49, 0x01, 0xC6 }); // add r14, rax
-
- // Increment counter
- try self.emit(&[_]u8{ 0x48, 0xFF, 0xC3 }); // inc rbx
-
- // Jump back to loop start
- try self.emit(&[_]u8{0xE9}); // jmp rel32
- const loop_back_offset: i32 = @intCast(@as(i64, @intCast(loop_start)) - @as(i64, @intCast(self.code.items.len + 4)));
- try self.emitImm32(loop_back_offset);
-
- // Patch jge offset
- const loop_end = self.code.items.len;
- const jge_rel: i32 = @intCast(@as(i64, @intCast(loop_end)) - @as(i64, @intCast(jge_offset + 4)));
- @memcpy(self.code.items[jge_offset..][0..4], std.mem.asBytes(&jge_rel));
-
- // Move result to rax
- try self.emit(&[_]u8{ 0x4C, 0x89, 0xF0 }); // mov rax, r14
-
- // Restore callee-saved registers
- try self.emit(&[_]u8{ 0x41, 0x5E }); // pop r14
- try self.emit(&[_]u8{ 0x41, 0x5D }); // pop r13
- try self.emit(&[_]u8{ 0x41, 0x5C }); // pop r12
- try self.emit(&[_]u8{0x5B}); // pop rbx
-
- // Function epilogue
- try self.movRspRbp();
- try self.popRbp();
- try self.ret();
- }
-
- /// Compile bind operation (element-wise multiply for ternary)
- pub fn compileBindDirect(self: *Self, dimension: usize) !void {
- self.reset();
-
- // Function prologue
- try self.pushRbp();
- try self.movRbpRsp();
-
- // Save callee-saved registers
- try self.emit(&[_]u8{0x53}); // push rbx
- try self.emit(&[_]u8{ 0x41, 0x54 }); // push r12
- try self.emit(&[_]u8{ 0x41, 0x55 }); // push r13
-
- // r12 = a pointer
- try self.emit(&[_]u8{ 0x49, 0x89, 0xFC }); // mov r12, rdi
-
- // r13 = b pointer
- try self.emit(&[_]u8{ 0x49, 0x89, 0xF5 }); // mov r13, rsi
-
- // rbx = loop counter (0)
- try self.xorEaxEax();
- try self.emit(&[_]u8{ 0x48, 0x89, 0xC3 }); // mov rbx, rax
-
- const loop_start = self.code.items.len;
-
- // Compare rbx with dimension
- try self.emit(&[_]u8{ 0x48, 0x81, 0xFB }); // cmp rbx, imm32
- try self.emitImm32(@intCast(dimension));
-
- // jge loop_end
- try self.emit(&[_]u8{ 0x0F, 0x8D }); // jge rel32
- const jge_offset = self.code.items.len;
- try self.emitImm32(0); // placeholder
-
- // Load a[rbx] into al
- try self.emit(&[_]u8{ 0x41, 0x8A, 0x04, 0x1C }); // mov al, [r12 + rbx]
-
- // Load b[rbx] into cl
- try self.emit(&[_]u8{ 0x41, 0x8A, 0x4C, 0x1D, 0x00 }); // mov cl, [r13 + rbx]
-
- // imul al, cl (signed multiply)
- try self.emit(&[_]u8{ 0xF6, 0xE9 }); // imul cl
-
- // Store result back to a[rbx]
- try self.emit(&[_]u8{ 0x41, 0x88, 0x04, 0x1C }); // mov [r12 + rbx], al
-
- // Increment counter
- try self.emit(&[_]u8{ 0x48, 0xFF, 0xC3 }); // inc rbx
-
- // Jump back to loop start
- try self.emit(&[_]u8{0xE9}); // jmp rel32
- const loop_back_offset: i32 = @intCast(@as(i64, @intCast(loop_start)) - @as(i64, @intCast(self.code.items.len + 4)));
- try self.emitImm32(loop_back_offset);
-
- // Patch jge offset
- const loop_end = self.code.items.len;
- const jge_rel: i32 = @intCast(@as(i64, @intCast(loop_end)) - @as(i64, @intCast(jge_offset + 4)));
- @memcpy(self.code.items[jge_offset..][0..4], std.mem.asBytes(&jge_rel));
-
- // Restore callee-saved registers
- try self.emit(&[_]u8{ 0x41, 0x5D }); // pop r13
- try self.emit(&[_]u8{ 0x41, 0x5C }); // pop r12
- try self.emit(&[_]u8{0x5B}); // pop rbx
-
- // Function epilogue
- try self.movRspRbp();
- try self.popRbp();
- try self.ret();
- }
-
- /// Compile bundle operation (element-wise sum with threshold)
- pub fn compileBundleDirect(self: *Self, dimension: usize) !void {
- self.reset();
-
- // Function prologue
- try self.pushRbp();
- try self.movRbpRsp();
-
- // Save callee-saved registers
- try self.emit(&[_]u8{0x53}); // push rbx
- try self.emit(&[_]u8{ 0x41, 0x54 }); // push r12
- try self.emit(&[_]u8{ 0x41, 0x55 }); // push r13
-
- // r12 = a pointer, r13 = b pointer
- try self.emit(&[_]u8{ 0x49, 0x89, 0xFC }); // mov r12, rdi
- try self.emit(&[_]u8{ 0x49, 0x89, 0xF5 }); // mov r13, rsi
-
- // rbx = loop counter (0)
- try self.xorEaxEax();
- try self.emit(&[_]u8{ 0x48, 0x89, 0xC3 }); // mov rbx, rax
-
- const loop_start = self.code.items.len;
-
- // Compare rbx with dimension
- try self.emit(&[_]u8{ 0x48, 0x81, 0xFB }); // cmp rbx, imm32
- try self.emitImm32(@intCast(dimension));
-
- // jge loop_end
- try self.emit(&[_]u8{ 0x0F, 0x8D }); // jge rel32
- const jge_offset = self.code.items.len;
- try self.emitImm32(0); // placeholder
-
- // Load a[rbx] into eax (sign-extended)
- try self.emit(&[_]u8{ 0x41, 0x0F, 0xBE, 0x04, 0x1C }); // movsx eax, byte [r12 + rbx]
-
- // Load b[rbx] into ecx (sign-extended)
- try self.emit(&[_]u8{ 0x41, 0x0F, 0xBE, 0x4C, 0x1D, 0x00 }); // movsx ecx, byte [r13 + rbx]
-
- // Add eax, ecx
- try self.emit(&[_]u8{ 0x01, 0xC8 }); // add eax, ecx
-
- // Threshold: if sum > 0 -> 1, if sum < 0 -> -1, else 0
- // cmp eax, 0
- try self.emit(&[_]u8{ 0x83, 0xF8, 0x00 }); // cmp eax, 0
-
- // setg dl (set dl = 1 if eax > 0)
- try self.emit(&[_]u8{ 0x0F, 0x9F, 0xC2 }); // setg dl
-
- // setl al (set al = 1 if eax < 0)
- try self.emit(&[_]u8{ 0x0F, 0x9C, 0xC0 }); // setl al
-
- // Result = dl - al (1 if positive, -1 if negative, 0 if zero)
- try self.emit(&[_]u8{ 0x28, 0xC2 }); // sub dl, al
-
- // Store result back to a[rbx]
- try self.emit(&[_]u8{ 0x41, 0x88, 0x14, 0x1C }); // mov [r12 + rbx], dl
-
- // Increment counter
- try self.emit(&[_]u8{ 0x48, 0xFF, 0xC3 }); // inc rbx
-
- // Jump back to loop start
- try self.emit(&[_]u8{0xE9}); // jmp rel32
- const loop_back_offset: i32 = @intCast(@as(i64, @intCast(loop_start)) - @as(i64, @intCast(self.code.items.len + 4)));
- try self.emitImm32(loop_back_offset);
-
- // Patch jge offset
- const loop_end = self.code.items.len;
- const jge_rel: i32 = @intCast(@as(i64, @intCast(loop_end)) - @as(i64, @intCast(jge_offset + 4)));
- @memcpy(self.code.items[jge_offset..][0..4], std.mem.asBytes(&jge_rel));
-
- // Restore callee-saved registers
- try self.emit(&[_]u8{ 0x41, 0x5D }); // pop r13
- try self.emit(&[_]u8{ 0x41, 0x5C }); // pop r12
- try self.emit(&[_]u8{0x5B}); // pop rbx
-
- // Function epilogue
- try self.movRspRbp();
- try self.popRbp();
- try self.ret();
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // EXECUTION
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Make code executable and return function pointer
- pub fn finalize(self: *Self) !*const fn (*anyopaque, *anyopaque) callconv(.c) i64 {
- const code_size = self.code.items.len;
- if (code_size == 0) return error.EmptyCode;
-
- // Use system page size for compatibility
- const page_size: usize = std.heap.page_size_min;
- const alloc_size = std.mem.alignForward(usize, code_size, page_size);
-
- // mmap with PROT_READ | PROT_WRITE first
- const mem = try std.posix.mmap(
- null,
- alloc_size,
- std.posix.PROT.READ | std.posix.PROT.WRITE,
- .{ .TYPE = .PRIVATE, .ANONYMOUS = true },
- -1,
- 0,
- );
-
- // Copy code
- @memcpy(mem[0..code_size], self.code.items);
-
- // Change to PROT_READ | PROT_EXEC
- try std.posix.mprotect(mem, std.posix.PROT.READ | std.posix.PROT.EXEC);
-
- self.exec_mem = mem;
-
- return @ptrCast(mem.ptr);
- }
-
- /// Get code size
- pub fn codeSize(self: *const Self) usize {
- return self.code.items.len;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "x86-64 JIT compiler init and deinit" {
- var compiler = X86_64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- try std.testing.expect(compiler.codeSize() == 0);
-}
-
-test "x86-64 JIT dot product compilation" {
- if (!is_x86_64) {
- return; // Skip on non-x86-64
- }
-
- var compiler = X86_64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 8;
- try compiler.compileDotProduct(dim);
-
- try std.testing.expect(compiler.codeSize() > 0);
-}
-
-test "x86-64 JIT dot product execution" {
- if (!is_x86_64) {
- return; // Skip on non-x86-64
- }
-
- var compiler = X86_64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 8;
- try compiler.compileDotProduct(dim);
-
- const func = try compiler.finalize();
-
- // Create test data
- var a = [dim]i8{ 1, -1, 1, 0, 1, -1, 0, 1 };
- var b = [dim]i8{ 1, 1, -1, 1, 1, 1, 1, -1 };
-
- // Expected: 1*1 + (-1)*1 + 1*(-1) + 0*1 + 1*1 + (-1)*1 + 0*1 + 1*(-1)
- // = 1 - 1 - 1 + 0 + 1 - 1 + 0 - 1 = -2
- const expected: i64 = -2;
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
-
-test "x86-64 JIT bind compilation" {
- if (!is_x86_64) {
- return;
- }
-
- var compiler = X86_64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 8;
- try compiler.compileBindDirect(dim);
-
- try std.testing.expect(compiler.codeSize() > 0);
-}
-
-test "x86-64 JIT large dimension" {
- if (!is_x86_64) {
- return;
- }
-
- var compiler = X86_64JitCompiler.init(std.testing.allocator);
- defer compiler.deinit();
-
- const dim = 1000;
- try compiler.compileDotProduct(dim);
-
- const func = try compiler.finalize();
-
- var a: [dim]i8 = undefined;
- var b: [dim]i8 = undefined;
- var expected: i64 = 0;
-
- for (0..dim) |i| {
- const val_a: i8 = @intCast(@as(i32, @intCast(i % 3)) - 1);
- const val_b: i8 = @intCast(@as(i32, @intCast((i + 1) % 3)) - 1);
- a[i] = val_a;
- b[i] = val_b;
- expected += @as(i64, val_a) * @as(i64, val_b);
- }
-
- const result = func(@ptrCast(&a), @ptrCast(&b));
- try std.testing.expectEqual(expected, result);
-}
diff --git a/src/kg_cli.zig b/src/kg_cli.zig
deleted file mode 100644
index 13dc21d5cb..0000000000
--- a/src/kg_cli.zig
+++ /dev/null
@@ -1,518 +0,0 @@
-// @origin(spec:kg_cli.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity Knowledge Graph CLI
-// Interactive Knowledge Graph interface with KG-INSIGHT inspector (DEV-002)
-//
-// USAGE: trinity-kg [command] [args...]
-// REPL: trinity-kg (no arguments)
-//
-// KG-INSIGHT commands: triples, inspect, export, find
-// ΞΒ² + 1/ΞΒ² = 3
-
-const std = @import("std");
-const kg = @import("knowledge_graph.zig");
-
-const KnowledgeGraph = kg.KnowledgeGraph;
-
-// =============================================================================
-// GLOBAL STATE
-// =============================================================================
-
-var graph: KnowledgeGraph = KnowledgeGraph.init();
-var name_buffer: [16384]u8 = undefined;
-var string_pool: [32768]u8 = undefined;
-var string_pool_offset: usize = 0;
-var current_file: ?[]const u8 = null;
-
-/// Copy string into pool and return slice
-fn internString(s: []const u8) []const u8 {
- if (string_pool_offset + s.len > string_pool.len) {
- return s;
- }
- const start = string_pool_offset;
- @memcpy(string_pool[start .. start + s.len], s);
- string_pool_offset += s.len;
- return string_pool[start .. start + s.len];
-}
-
-// =============================================================================
-// MAIN
-// =============================================================================
-
-pub fn main() !void {
- const stdout = std.io.getStdOut().writer();
- const stdin = std.io.getStdIn().reader();
-
- var args = std.process.args();
- _ = args.skip();
-
- if (args.next()) |cmd| {
- var arg_list: [10][]const u8 = undefined;
- var arg_count: usize = 0;
-
- while (args.next()) |arg| {
- if (arg_count < 10) {
- arg_list[arg_count] = arg;
- arg_count += 1;
- }
- }
-
- try executeCommand(cmd, arg_list[0..arg_count], stdout);
- return;
- }
-
- // REPL mode
- try printBanner(stdout);
-
- var line_buf: [1024]u8 = undefined;
-
- while (true) {
- try stdout.print("\n\x1b[36mtrinity-kg>\x1b[0m ", .{});
-
- const line = stdin.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| {
- if (err == error.EndOfStream) break;
- return err;
- } orelse break;
-
- const trimmed = std.mem.trim(u8, line, " \t\r\n");
- if (trimmed.len == 0) continue;
-
- var tokens = std.mem.tokenizeAny(u8, trimmed, " \t");
- const cmd = tokens.next() orelse continue;
-
- var arg_list: [10][]const u8 = undefined;
- var arg_count: usize = 0;
-
- while (tokens.next()) |arg| {
- if (arg_count < 10) {
- arg_list[arg_count] = arg;
- arg_count += 1;
- }
- }
-
- if (std.mem.eql(u8, cmd, "exit") or std.mem.eql(u8, cmd, "quit")) {
- try stdout.print("\x1b[33mGoodbye! \xCF\x86\xC2\xB2 + 1/\xCF\x86\xC2\xB2 = 3\x1b[0m\n", .{});
- break;
- }
-
- executeCommand(cmd, arg_list[0..arg_count], stdout) catch |err| {
- try stdout.print("\x1b[31mError: {}\x1b[0m\n", .{err});
- };
- }
-}
-
-// =============================================================================
-// COMMAND DISPATCH
-// =============================================================================
-
-fn executeCommand(cmd: []const u8, args: [][]const u8, writer: anytype) !void {
- if (std.mem.eql(u8, cmd, "help") or std.mem.eql(u8, cmd, "?")) {
- try printHelp(writer);
- } else if (std.mem.eql(u8, cmd, "add")) {
- try cmdAdd(args, writer);
- } else if (std.mem.eql(u8, cmd, "query") or std.mem.eql(u8, cmd, "q")) {
- try cmdQuery(args, writer);
- } else if (std.mem.eql(u8, cmd, "save")) {
- try cmdSave(args, writer);
- } else if (std.mem.eql(u8, cmd, "load")) {
- try cmdLoad(args, writer);
- } else if (std.mem.eql(u8, cmd, "stats")) {
- try cmdStats(writer);
- } else if (std.mem.eql(u8, cmd, "list")) {
- try cmdList(writer);
- } else if (std.mem.eql(u8, cmd, "triples") or std.mem.eql(u8, cmd, "t")) {
- try cmdTriples(writer);
- } else if (std.mem.eql(u8, cmd, "inspect") or std.mem.eql(u8, cmd, "i")) {
- try cmdInspect(args, writer);
- } else if (std.mem.eql(u8, cmd, "export")) {
- try cmdExport(args, writer);
- } else if (std.mem.eql(u8, cmd, "find") or std.mem.eql(u8, cmd, "f")) {
- try cmdFind(args, writer);
- } else if (std.mem.eql(u8, cmd, "clear")) {
- graph = KnowledgeGraph.init();
- try writer.print("\x1b[32mGraph cleared.\x1b[0m\n", .{});
- } else {
- try writer.print("\x1b[31mUnknown command: {s}\x1b[0m\n", .{cmd});
- try writer.print("Type 'help' for available commands.\n", .{});
- }
-}
-
-// =============================================================================
-// ORIGINAL COMMANDS
-// =============================================================================
-
-/// Command add: add a fact
-fn cmdAdd(args: [][]const u8, writer: anytype) !void {
- if (args.len < 3) {
- try writer.print("\x1b[31mUsage: add \x1b[0m\n", .{});
- try writer.print("Example: add Paris capital_of France\n", .{});
- return;
- }
-
- const subject = internString(args[0]);
- const predicate = internString(args[1]);
- const object = internString(args[2]);
-
- graph.addTriple(subject, predicate, object);
-
- try writer.print("\x1b[32m+ Added:\x1b[0m {s} \x1b[33m{s}\x1b[0m {s}\n", .{ subject, predicate, object });
-}
-
-/// Command query: query the graph
-fn cmdQuery(args: [][]const u8, writer: anytype) !void {
- if (args.len < 3) {
- try writer.print("\x1b[31mUsage: query \x1b[0m\n", .{});
- try writer.print("Example: query Paris capital_of ?\n", .{});
- try writer.print("Example: query ? capital_of France\n", .{});
- return;
- }
-
- const subject = internString(args[0]);
- const predicate = internString(args[1]);
- const object = internString(args[2]);
-
- const is_subject_query = std.mem.eql(u8, subject, "?");
- const is_object_query = std.mem.eql(u8, object, "?");
-
- if (is_subject_query and is_object_query) {
- try writer.print("\x1b[31mCan only query subject OR object, not both.\x1b[0m\n", .{});
- return;
- }
-
- if (!is_subject_query and !is_object_query) {
- try writer.print("\x1b[31mUse ? for the element to search.\x1b[0m\n", .{});
- return;
- }
-
- try writer.print("\x1b[36mQuery:\x1b[0m {s} {s} {s}\n", .{ subject, predicate, object });
-
- if (is_object_query) {
- const result = graph.queryObject(subject, predicate);
- if (result) |entity| {
- try writer.print("\x1b[32m+ Result:\x1b[0m {s}\n", .{entity.name});
- } else {
- try writer.print("\x1b[33mx Not found\x1b[0m\n", .{});
- }
- } else {
- const result = graph.querySubject(predicate, object);
- if (result) |entity| {
- try writer.print("\x1b[32m+ Result:\x1b[0m {s}\n", .{entity.name});
- } else {
- try writer.print("\x1b[33mx Not found\x1b[0m\n", .{});
- }
- }
-}
-
-/// Command save: save the graph
-fn cmdSave(args: [][]const u8, writer: anytype) !void {
- const path = if (args.len > 0) args[0] else (current_file orelse "graph.trkg");
-
- try graph.save(path);
- current_file = path;
-
- try writer.print("\x1b[32m+ Graph saved:\x1b[0m {s}\n", .{path});
-}
-
-/// Command load: load the graph
-fn cmdLoad(args: [][]const u8, writer: anytype) !void {
- if (args.len < 1) {
- try writer.print("\x1b[31mUsage: load \x1b[0m\n", .{});
- return;
- }
-
- const path = args[0];
-
- graph = try KnowledgeGraph.load(path, &name_buffer);
- current_file = path;
-
- const s = graph.stats();
- try writer.print("\x1b[32m+ Graph loaded:\x1b[0m {s}\n", .{path});
- try writer.print(" Entities: {d}, Relations: {d}, Triples: {d}\n", .{ s.entities, s.relations, s.triples });
-}
-
-/// Command stats: show statistics
-fn cmdStats(writer: anytype) !void {
- const s = graph.stats();
-
- try writer.print("\n\x1b[36m+---------------------------------------+\x1b[0m\n", .{});
- try writer.print("\x1b[36m|\x1b[0m TRINITY KNOWLEDGE GRAPH \x1b[36m|\x1b[0m\n", .{});
- try writer.print("\x1b[36m+---------------------------------------+\x1b[0m\n", .{});
- try writer.print("\x1b[36m|\x1b[0m Entities: \x1b[33m{d:5}\x1b[0m \x1b[36m|\x1b[0m\n", .{s.entities});
- try writer.print("\x1b[36m|\x1b[0m Relations: \x1b[33m{d:5}\x1b[0m \x1b[36m|\x1b[0m\n", .{s.relations});
- try writer.print("\x1b[36m|\x1b[0m Triples: \x1b[33m{d:5}\x1b[0m \x1b[36m|\x1b[0m\n", .{s.triples});
- try writer.print("\x1b[36m+---------------------------------------+\x1b[0m\n", .{});
-
- if (current_file) |f| {
- try writer.print(" File: {s}\n", .{f});
- }
-}
-
-/// Command list: list entities and relations
-fn cmdList(writer: anytype) !void {
- try writer.print("\n\x1b[36mEntities:\x1b[0m\n", .{});
- for (0..graph.entity_count) |i| {
- if (graph.entities[i]) |e| {
- try writer.print(" [{d}] {s}\n", .{ e.id, e.name });
- }
- }
-
- try writer.print("\n\x1b[36mRelations:\x1b[0m\n", .{});
- for (0..graph.relation_count) |i| {
- if (graph.relations[i]) |r| {
- try writer.print(" [{d}] {s}\n", .{ r.id, r.name });
- }
- }
-}
-
-// =============================================================================
-// KG-INSIGHT COMMANDS (DEV-002)
-// =============================================================================
-
-/// Command triples: enumerate all stored triples as (S, P, O) table
-fn cmdTriples(writer: anytype) !void {
- if (graph.triple_count == 0) {
- try writer.print("\x1b[33mGraph is empty. Use 'add' to create triples.\x1b[0m\n", .{});
- return;
- }
-
- try writer.print("\n\x1b[36mTriples ({d}):\x1b[0m\n", .{graph.triple_count});
- try writer.print(" \x1b[90m{s: >4} {s: <20} {s: <16} {s: <20}\x1b[0m\n", .{ "ID", "Subject", "Predicate", "Object" });
- try writer.print(" \x1b[90m{s:->4} {s:-<20} {s:-<16} {s:-<20}\x1b[0m\n", .{ "", "", "", "" });
-
- for (0..graph.triple_count) |i| {
- if (graph.triples[i]) |t| {
- const subj = if (graph.entities[t.subject_id]) |e| e.name else "?";
- const pred = if (graph.relations[t.predicate_id]) |r| r.name else "?";
- const obj = if (graph.entities[t.object_id]) |e| e.name else "?";
- try writer.print(" {d:4} \x1b[32m{s: <20}\x1b[0m \x1b[33m{s: <16}\x1b[0m \x1b[32m{s: <20}\x1b[0m\n", .{ i, subj, pred, obj });
- }
- }
-}
-
-/// Command inspect: show all triples involving an entity
-fn cmdInspect(args: [][]const u8, writer: anytype) !void {
- if (args.len < 1) {
- try writer.print("\x1b[31mUsage: inspect \x1b[0m\n", .{});
- return;
- }
-
- const name = args[0];
- var entity_id: ?u32 = null;
-
- // Find entity by exact name (case insensitive)
- for (0..graph.entity_count) |i| {
- if (graph.entities[i]) |e| {
- if (asciiEqlIgnoreCase(e.name, name)) {
- entity_id = e.id;
- break;
- }
- }
- }
-
- // Fallback: prefix match
- if (entity_id == null) {
- for (0..graph.entity_count) |i| {
- if (graph.entities[i]) |e| {
- if (asciiStartsWithIgnoreCase(e.name, name)) {
- entity_id = e.id;
- break;
- }
- }
- }
- }
-
- if (entity_id == null) {
- try writer.print("\x1b[31mEntity not found: {s}\x1b[0m\n", .{name});
- return;
- }
-
- const eid = entity_id.?;
- const ename = if (graph.entities[eid]) |e| e.name else name;
- try writer.print("\n\x1b[36mInspecting entity: \x1b[32m{s}\x1b[36m (id={d})\x1b[0m\n", .{ ename, eid });
-
- var as_subject: u32 = 0;
- var as_object: u32 = 0;
-
- // Triples where entity is subject
- try writer.print("\n \x1b[33mAs subject:\x1b[0m\n", .{});
- for (0..graph.triple_count) |i| {
- if (graph.triples[i]) |t| {
- if (t.subject_id == eid) {
- const pred = if (graph.relations[t.predicate_id]) |r| r.name else "?";
- const obj = if (graph.entities[t.object_id]) |e| e.name else "?";
- try writer.print(" {s} \x1b[33m{s}\x1b[0m {s}\n", .{ ename, pred, obj });
- as_subject += 1;
- }
- }
- }
- if (as_subject == 0) try writer.print(" (none)\n", .{});
-
- // Triples where entity is object
- try writer.print("\n \x1b[33mAs object:\x1b[0m\n", .{});
- for (0..graph.triple_count) |i| {
- if (graph.triples[i]) |t| {
- if (t.object_id == eid) {
- const subj = if (graph.entities[t.subject_id]) |e| e.name else "?";
- const pred = if (graph.relations[t.predicate_id]) |r| r.name else "?";
- try writer.print(" {s} \x1b[33m{s}\x1b[0m {s}\n", .{ subj, pred, ename });
- as_object += 1;
- }
- }
- }
- if (as_object == 0) try writer.print(" (none)\n", .{});
-
- try writer.print("\n \x1b[90mTotal: {d} as subject, {d} as object\x1b[0m\n", .{ as_subject, as_object });
-}
-
-/// Command export: write all triples to JSON file
-fn cmdExport(args: [][]const u8, writer: anytype) !void {
- const path = if (args.len > 0) args[0] else "triples.json";
-
- if (graph.triple_count == 0) {
- try writer.print("\x1b[33mNo triples to export.\x1b[0m\n", .{});
- return;
- }
-
- var file = std.fs.cwd().createFile(path, .{}) catch |err| {
- try writer.print("\x1b[31mCannot create file: {s} ({})\x1b[0m\n", .{ path, err });
- return;
- };
- defer file.close();
- var fw = file.writer();
-
- try fw.print("[\n", .{});
- var written: u32 = 0;
- for (0..graph.triple_count) |i| {
- if (graph.triples[i]) |t| {
- const subj = if (graph.entities[t.subject_id]) |e| e.name else "?";
- const pred = if (graph.relations[t.predicate_id]) |r| r.name else "?";
- const obj = if (graph.entities[t.object_id]) |e| e.name else "?";
- if (written > 0) try fw.print(",\n", .{});
- try fw.print(" {{\"subject\": \"{s}\", \"predicate\": \"{s}\", \"object\": \"{s}\"}}", .{ subj, pred, obj });
- written += 1;
- }
- }
- try fw.print("\n]\n", .{});
-
- try writer.print("\x1b[32mExported {d} triples to {s}\x1b[0m\n", .{ written, path });
-}
-
-/// Command find: search entities by name
-fn cmdFind(args: [][]const u8, writer: anytype) !void {
- if (args.len < 1) {
- try writer.print("\x1b[31mUsage: find \x1b[0m\n", .{});
- return;
- }
-
- const pattern = args[0];
- var found: u32 = 0;
-
- try writer.print("\n\x1b[36mEntities matching \"{s}\":\x1b[0m\n", .{pattern});
- for (0..graph.entity_count) |i| {
- if (graph.entities[i]) |e| {
- if (asciiStartsWithIgnoreCase(e.name, pattern) or asciiContainsIgnoreCase(e.name, pattern)) {
- try writer.print(" [{d}] {s}\n", .{ e.id, e.name });
- found += 1;
- }
- }
- }
-
- if (found == 0) {
- try writer.print(" \x1b[33mNo matches found.\x1b[0m\n", .{});
- } else {
- try writer.print(" \x1b[90m({d} matches)\x1b[0m\n", .{found});
- }
-}
-
-// =============================================================================
-// STRING UTILITIES (case-insensitive matching)
-// =============================================================================
-
-fn asciiToLower(ch: u8) u8 {
- return if (ch >= 'A' and ch <= 'Z') ch + 32 else ch;
-}
-
-fn asciiEqlIgnoreCase(a: []const u8, b: []const u8) bool {
- if (a.len != b.len) return false;
- for (a, b) |ca, cb| {
- if (asciiToLower(ca) != asciiToLower(cb)) return false;
- }
- return true;
-}
-
-fn asciiStartsWithIgnoreCase(haystack: []const u8, prefix: []const u8) bool {
- if (prefix.len > haystack.len) return false;
- for (0..prefix.len) |i| {
- if (asciiToLower(haystack[i]) != asciiToLower(prefix[i])) return false;
- }
- return true;
-}
-
-fn asciiContainsIgnoreCase(haystack: []const u8, needle: []const u8) bool {
- if (needle.len > haystack.len) return false;
- var i: usize = 0;
- while (i + needle.len <= haystack.len) : (i += 1) {
- if (asciiStartsWithIgnoreCase(haystack[i..], needle)) return true;
- }
- return false;
-}
-
-// =============================================================================
-// UI
-// =============================================================================
-
-fn printBanner(writer: anytype) !void {
- try writer.print("\n", .{});
- try writer.print("\x1b[36m+===============================================================+\x1b[0m\n", .{});
- try writer.print("\x1b[36m|\x1b[0m \x1b[33mTRINITY KNOWLEDGE GRAPH\x1b[0m \x1b[36m|\x1b[0m\n", .{});
- try writer.print("\x1b[36m|\x1b[0m \x1b[35mKG-INSIGHT Inspector v2.0\x1b[0m \x1b[36m|\x1b[0m\n", .{});
- try writer.print("\x1b[36m+==============================================================+\x1b[0m\n", .{});
- try writer.print("\n", .{});
- try writer.print("Type \x1b[33mhelp\x1b[0m for commands, \x1b[33mexit\x1b[0m to quit.\n", .{});
-}
-
-fn printHelp(writer: anytype) !void {
- try writer.print("\n\x1b[36m===============================================================\x1b[0m\n", .{});
- try writer.print("\x1b[33mCOMMANDS:\x1b[0m\n", .{});
- try writer.print("\x1b[36m===============================================================\x1b[0m\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32madd\x1b[0m \n", .{});
- try writer.print(" Add a fact to the graph\n", .{});
- try writer.print(" Example: \x1b[90madd Paris capital_of France\x1b[0m\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mquery\x1b[0m (q) \n", .{});
- try writer.print(" Query the graph (? = unknown)\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32msave\x1b[0m [path]\n", .{});
- try writer.print(" Save graph to .trkg file\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mload\x1b[0m \n", .{});
- try writer.print(" Load graph from .trkg file\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mstats\x1b[0m\n", .{});
- try writer.print(" Show graph statistics\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mlist\x1b[0m\n", .{});
- try writer.print(" List all entities and relations\n", .{});
- try writer.print("\n", .{});
- try writer.print("\x1b[36m--- KG-INSIGHT (DEV-002) ---\x1b[0m\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mtriples\x1b[0m (t)\n", .{});
- try writer.print(" Show all triples as (S, P, O) table\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32minspect\x1b[0m (i) \n", .{});
- try writer.print(" Show all triples involving an entity\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mexport\x1b[0m [path]\n", .{});
- try writer.print(" Export all triples to JSON (default: triples.json)\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mfind\x1b[0m (f) \n", .{});
- try writer.print(" Search entities by name (case insensitive)\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mclear\x1b[0m\n", .{});
- try writer.print(" Clear the graph\n", .{});
- try writer.print("\n", .{});
- try writer.print(" \x1b[32mexit\x1b[0m\n", .{});
- try writer.print(" Exit the program\n", .{});
- try writer.print("\n", .{});
-}
diff --git a/src/kg_server.zig b/src/kg_server.zig
deleted file mode 100644
index ba980f65fc..0000000000
--- a/src/kg_server.zig
+++ /dev/null
@@ -1,1330 +0,0 @@
-// @origin(spec:kg_server.tri) @regen(manual-impl)
-//! Trinity Knowledge Graph HTTP Server
-//! REST API for semantic triple store with embedding-based similarity search
-//!
-//! Endpoints:
-//! POST /api/add - Add triple (subject, predicate, object)
-//! GET /api/query - Query by subject+predicate or object+predicate
-//! GET /api/stats - Graph statistics
-//! GET /api/list - List all triples
-//! POST /api/save - Save graph to file
-//! POST /api/load - Load graph from file
-//! POST /api/clear - Clear all data
-// @origin(manual) @regen(pending)
-
-const std = @import("std");
-const net = std.net;
-const http = std.http;
-const mem = std.mem;
-const Allocator = std.mem.Allocator;
-
-// ============================================================================
-// Trinity Knowledge Graph Core
-// ============================================================================
-
-/// Simple hash-based embedding (deterministic, fast)
-fn computeEmbedding(text: []const u8) [64]f32 {
- var embedding: [64]f32 = [_]f32{0.0} ** 64;
-
- // Character-level features
- for (text, 0..) |c, i| {
- const idx = (c +% @as(u8, @truncate(i))) % 64;
- embedding[idx] += 1.0;
- }
-
- // Bigram features
- if (text.len > 1) {
- for (0..text.len - 1) |i| {
- const bigram_hash = (@as(u16, text[i]) << 8) | text[i + 1];
- const idx = bigram_hash % 64;
- embedding[idx] += 0.5;
- }
- }
-
- // Normalize
- var norm: f32 = 0.0;
- for (embedding) |v| norm += v * v;
- norm = @sqrt(norm);
- if (norm > 0.0) {
- for (&embedding) |*v| v.* /= norm;
- }
-
- return embedding;
-}
-
-/// Cosine similarity between embeddings
-fn cosineSimilarity(a: [64]f32, b: [64]f32) f32 {
- var dot: f32 = 0.0;
- for (a, b) |av, bv| dot += av * bv;
- return dot;
-}
-
-/// Triple: (subject, predicate, object)
-const Triple = struct {
- subject: []const u8,
- predicate: []const u8,
- object: []const u8,
- subject_emb: [64]f32,
- object_emb: [64]f32,
-};
-
-/// Knowledge Graph with embedding-based search
-pub const KnowledgeGraph = struct {
- allocator: Allocator,
- triples: std.ArrayList(Triple),
- entity_embeddings: std.StringHashMap([64]f32),
- relation_set: std.StringHashMap(void),
-
- pub fn init(allocator: Allocator) KnowledgeGraph {
- return .{
- .allocator = allocator,
- .triples = std.ArrayList(Triple).init(allocator),
- .entity_embeddings = std.StringHashMap([64]f32).init(allocator),
- .relation_set = std.StringHashMap(void).init(allocator),
- };
- }
-
- pub fn deinit(self: *KnowledgeGraph) void {
- for (self.triples.items) |triple| {
- self.allocator.free(triple.subject);
- self.allocator.free(triple.predicate);
- self.allocator.free(triple.object);
- }
- self.triples.deinit();
-
- var key_iter = self.entity_embeddings.keyIterator();
- while (key_iter.next()) |key| {
- self.allocator.free(key.*);
- }
- self.entity_embeddings.deinit();
-
- var rel_iter = self.relation_set.keyIterator();
- while (rel_iter.next()) |key| {
- self.allocator.free(key.*);
- }
- self.relation_set.deinit();
- }
-
- /// Add a triple to the graph
- pub fn addTriple(self: *KnowledgeGraph, subject: []const u8, predicate: []const u8, object: []const u8) !usize {
- const subj_copy = try self.allocator.dupe(u8, subject);
- errdefer self.allocator.free(subj_copy);
-
- const pred_copy = try self.allocator.dupe(u8, predicate);
- errdefer self.allocator.free(pred_copy);
-
- const obj_copy = try self.allocator.dupe(u8, object);
- errdefer self.allocator.free(obj_copy);
-
- const subj_emb = computeEmbedding(subject);
- const obj_emb = computeEmbedding(object);
-
- // Store entity embeddings
- if (!self.entity_embeddings.contains(subject)) {
- const key = try self.allocator.dupe(u8, subject);
- try self.entity_embeddings.put(key, subj_emb);
- }
- if (!self.entity_embeddings.contains(object)) {
- const key = try self.allocator.dupe(u8, object);
- try self.entity_embeddings.put(key, obj_emb);
- }
-
- // Store relation
- if (!self.relation_set.contains(predicate)) {
- const key = try self.allocator.dupe(u8, predicate);
- try self.relation_set.put(key, {});
- }
-
- try self.triples.append(.{
- .subject = subj_copy,
- .predicate = pred_copy,
- .object = obj_copy,
- .subject_emb = subj_emb,
- .object_emb = obj_emb,
- });
-
- return self.triples.items.len - 1;
- }
-
- /// Query: given subject and predicate, find object
- pub fn queryObject(self: *KnowledgeGraph, subject: []const u8, predicate: []const u8) ?struct { name: []const u8, similarity: f32 } {
- const query_emb = computeEmbedding(subject);
- var best_match: ?[]const u8 = null;
- var best_sim: f32 = -1.0;
-
- for (self.triples.items) |triple| {
- if (mem.eql(u8, triple.predicate, predicate)) {
- const sim = cosineSimilarity(query_emb, triple.subject_emb);
- if (sim > best_sim) {
- best_sim = sim;
- best_match = triple.object;
- }
- }
- }
-
- if (best_match) |obj| {
- return .{ .name = obj, .similarity = best_sim };
- }
- return null;
- }
-
- /// Query: given object and predicate, find subject
- pub fn querySubject(self: *KnowledgeGraph, object: []const u8, predicate: []const u8) ?struct { name: []const u8, similarity: f32 } {
- const query_emb = computeEmbedding(object);
- var best_match: ?[]const u8 = null;
- var best_sim: f32 = -1.0;
-
- for (self.triples.items) |triple| {
- if (mem.eql(u8, triple.predicate, predicate)) {
- const sim = cosineSimilarity(query_emb, triple.object_emb);
- if (sim > best_sim) {
- best_sim = sim;
- best_match = triple.subject;
- }
- }
- }
-
- if (best_match) |subj| {
- return .{ .name = subj, .similarity = best_sim };
- }
- return null;
- }
-
- /// Get statistics
- pub fn getStats(self: *KnowledgeGraph) struct { entities: usize, relations: usize, triples: usize } {
- return .{
- .entities = self.entity_embeddings.count(),
- .relations = self.relation_set.count(),
- .triples = self.triples.items.len,
- };
- }
-
- /// Path step in reasoning chain
- pub const PathStep = struct {
- entity: []const u8,
- relation: []const u8,
- next_entity: []const u8,
- };
-
- /// Reasoning result
- pub const ReasoningResult = struct {
- found: bool,
- path: []PathStep,
- hops: usize,
-
- pub fn deinit(self: *ReasoningResult, allocator: Allocator) void {
- allocator.free(self.path);
- }
- };
-
- /// Multi-hop reasoning: find path from entity to target value
- /// Uses BFS to find shortest path
- pub fn findPath(self: *KnowledgeGraph, from: []const u8, to: []const u8, max_hops: usize) !ReasoningResult {
- const QueueItem = struct {
- entity: []const u8,
- path: std.ArrayList(PathStep),
- depth: usize,
- };
-
- var queue = std.ArrayList(QueueItem).init(self.allocator);
- defer {
- for (queue.items) |*item| {
- item.path.deinit();
- }
- queue.deinit();
- }
-
- var visited = std.StringHashMap(void).init(self.allocator);
- defer visited.deinit();
-
- // Start BFS from 'from' entity
- const initial_path = std.ArrayList(PathStep).init(self.allocator);
- try queue.append(.{
- .entity = from,
- .path = initial_path,
- .depth = 0,
- });
- try visited.put(from, {});
-
- while (queue.items.len > 0) {
- const current = queue.orderedRemove(0);
- defer current.path.deinit();
-
- // Check if we reached the target
- if (mem.eql(u8, current.entity, to)) {
- const result_path = try self.allocator.dupe(PathStep, current.path.items);
- return .{
- .found = true,
- .path = result_path,
- .hops = current.depth,
- };
- }
-
- // Don't go deeper than max_hops
- if (current.depth >= max_hops) continue;
-
- // Explore neighbors (objects of triples where current entity is subject)
- for (self.triples.items) |triple| {
- if (mem.eql(u8, triple.subject, current.entity)) {
- if (!visited.contains(triple.object)) {
- try visited.put(triple.object, {});
-
- var new_path = try current.path.clone();
- try new_path.append(.{
- .entity = triple.subject,
- .relation = triple.predicate,
- .next_entity = triple.object,
- });
-
- try queue.append(.{
- .entity = triple.object,
- .path = new_path,
- .depth = current.depth + 1,
- });
- }
- }
- }
- }
-
- // No path found
- return .{
- .found = false,
- .path = &[_]PathStep{},
- .hops = 0,
- };
- }
-
- /// Check if a property holds for an entity (e.g., "Is Socrates mortal?")
- pub fn checkProperty(self: *KnowledgeGraph, entity: []const u8, property: []const u8, max_hops: usize) !struct {
- holds: bool,
- path: []PathStep,
- value: ?[]const u8,
- } {
- // First, try direct lookup
- for (self.triples.items) |triple| {
- if (mem.eql(u8, triple.subject, entity) and mem.eql(u8, triple.predicate, property)) {
- var path = try self.allocator.alloc(PathStep, 1);
- path[0] = .{
- .entity = triple.subject,
- .relation = triple.predicate,
- .next_entity = triple.object,
- };
- return .{
- .holds = true,
- .path = path,
- .value = triple.object,
- };
- }
- }
-
- // Try multi-hop: find intermediate entities that have the property
- for (self.triples.items) |triple| {
- if (mem.eql(u8, triple.predicate, property)) {
- // Found something with this property, try to reach it from entity
- const result = try self.findPath(entity, triple.subject, max_hops - 1);
- if (result.found) {
- // Extend path with the final property step
- var extended_path = try self.allocator.alloc(PathStep, result.path.len + 1);
- @memcpy(extended_path[0..result.path.len], result.path);
- extended_path[result.path.len] = .{
- .entity = triple.subject,
- .relation = triple.predicate,
- .next_entity = triple.object,
- };
- self.allocator.free(result.path);
-
- return .{
- .holds = true,
- .path = extended_path,
- .value = triple.object,
- };
- }
- if (result.path.len > 0) {
- self.allocator.free(result.path);
- }
- }
- }
-
- return .{
- .holds = false,
- .path = &[_]PathStep{},
- .value = null,
- };
- }
-
- /// Clear all data
- pub fn clear(self: *KnowledgeGraph) void {
- for (self.triples.items) |triple| {
- self.allocator.free(triple.subject);
- self.allocator.free(triple.predicate);
- self.allocator.free(triple.object);
- }
- self.triples.clearRetainingCapacity();
-
- var key_iter = self.entity_embeddings.keyIterator();
- while (key_iter.next()) |key| {
- self.allocator.free(key.*);
- }
- self.entity_embeddings.clearRetainingCapacity();
-
- var rel_iter = self.relation_set.keyIterator();
- while (rel_iter.next()) |key| {
- self.allocator.free(key.*);
- }
- self.relation_set.clearRetainingCapacity();
- }
-
- /// Save to file (.trkg format)
- pub fn save(self: *KnowledgeGraph, path: []const u8) !void {
- const file = try std.fs.cwd().createFile(path, .{});
- defer file.close();
-
- var writer = file.writer();
-
- // Header
- try writer.writeAll("TRKG1\n");
-
- // Write triples
- for (self.triples.items) |triple| {
- try writer.print("{s}\t{s}\t{s}\n", .{ triple.subject, triple.predicate, triple.object });
- }
- }
-
- /// Load from file
- pub fn load(self: *KnowledgeGraph, path: []const u8) !usize {
- const file = try std.fs.cwd().openFile(path, .{});
- defer file.close();
-
- var reader = file.reader();
- var buf: [4096]u8 = undefined;
-
- // Check header
- const header = reader.readUntilDelimiter(&buf, '\n') catch return error.InvalidFormat;
- if (!mem.eql(u8, header, "TRKG1")) return error.InvalidFormat;
-
- var count: usize = 0;
- while (reader.readUntilDelimiter(&buf, '\n')) |line| {
- var parts = mem.splitScalar(u8, line, '\t');
- const subject = parts.next() orelse continue;
- const predicate = parts.next() orelse continue;
- const object = parts.next() orelse continue;
-
- _ = try self.addTriple(subject, predicate, object);
- count += 1;
- } else |_| {}
-
- return count;
- }
-};
-
-// ============================================================================
-// HTTP Server
-// ============================================================================
-
-/// JSON response builder
-fn jsonResponse(allocator: Allocator, comptime fmt: []const u8, args: anytype) ![]u8 {
- return try std.fmt.allocPrint(allocator, fmt, args);
-}
-
-/// Parse JSON field from body
-fn parseJsonField(body: []const u8, field: []const u8) ?[]const u8 {
- // Simple JSON parser for {"field": "value"} format
- const search = std.fmt.allocPrint(std.heap.page_allocator, "\"{s}\":", .{field}) catch return null;
- defer std.heap.page_allocator.free(search);
-
- const start_idx = mem.indexOf(u8, body, search) orelse return null;
- const value_start = start_idx + search.len;
-
- // Skip whitespace and opening quote
- var i = value_start;
- while (i < body.len and (body[i] == ' ' or body[i] == '"')) : (i += 1) {}
-
- if (i >= body.len) return null;
-
- // Find closing quote
- const end_idx = mem.indexOfScalarPos(u8, body, i, '"') orelse return null;
-
- return body[i..end_idx];
-}
-
-/// Parse query parameter from URL
-fn parseQueryParam(target: []const u8, param: []const u8) ?[]const u8 {
- const query_start = mem.indexOf(u8, target, "?") orelse return null;
- const query = target[query_start + 1 ..];
-
- var params = mem.splitScalar(u8, query, '&');
- while (params.next()) |p| {
- var kv = mem.splitScalar(u8, p, '=');
- const key = kv.next() orelse continue;
- const value = kv.next() orelse continue;
- if (mem.eql(u8, key, param)) {
- return value;
- }
- }
- return null;
-}
-
-/// URL decode
-fn urlDecode(allocator: Allocator, input: []const u8) ![]u8 {
- var result = std.ArrayList(u8).init(allocator);
- errdefer result.deinit();
-
- var i: usize = 0;
- while (i < input.len) {
- if (input[i] == '%' and i + 2 < input.len) {
- const hex = input[i + 1 .. i + 3];
- const byte = std.fmt.parseInt(u8, hex, 16) catch {
- try result.append(input[i]);
- i += 1;
- continue;
- };
- try result.append(byte);
- i += 3;
- } else if (input[i] == '+') {
- try result.append(' ');
- i += 1;
- } else {
- try result.append(input[i]);
- i += 1;
- }
- }
-
- return result.toOwnedSlice();
-}
-
-/// HTTP Server for Knowledge Graph
-pub const KGServer = struct {
- allocator: Allocator,
- kg: KnowledgeGraph,
- server: net.Server,
- running: bool,
-
- pub fn init(allocator: Allocator, port: u16) !KGServer {
- const address = net.Address.initIp4(.{ 0, 0, 0, 0 }, port);
- const server = try address.listen(.{
- .reuse_address = true,
- });
-
- return .{
- .allocator = allocator,
- .kg = KnowledgeGraph.init(allocator),
- .server = server,
- .running = true,
- };
- }
-
- pub fn deinit(self: *KGServer) void {
- self.kg.deinit();
- self.server.deinit();
- }
-
- /// Handle single request
- fn handleRequest(self: *KGServer, request: *http.Server.Request) !void {
- const target = request.head.target;
- const method = request.head.method;
-
- // Read body for POST requests
- var body_buf: [4096]u8 = undefined;
- var body: []const u8 = "";
- if (method == .POST) {
- if (request.head.content_length) |len| {
- const read_len = @min(len, body_buf.len);
- var reader = request.reader() catch {
- try self.sendError(request, "Failed to read body");
- return;
- };
- const n = reader.read(body_buf[0..read_len]) catch 0;
- body = body_buf[0..n];
- }
- }
-
- // Route requests
- if (mem.startsWith(u8, target, "/api/add") and method == .POST) {
- try self.handleAdd(request, body);
- } else if (mem.startsWith(u8, target, "/api/reason")) {
- try self.handleReason(request, target);
- } else if (mem.startsWith(u8, target, "/api/query")) {
- try self.handleQuery(request, target);
- } else if (mem.startsWith(u8, target, "/api/graph")) {
- try self.handleGraph(request);
- } else if (mem.startsWith(u8, target, "/api/stats")) {
- try self.handleStats(request);
- } else if (mem.startsWith(u8, target, "/api/list")) {
- try self.handleList(request);
- } else if (mem.startsWith(u8, target, "/api/save") and method == .POST) {
- try self.handleSave(request, body);
- } else if (mem.startsWith(u8, target, "/api/load") and method == .POST) {
- try self.handleLoad(request, body);
- } else if (mem.startsWith(u8, target, "/api/clear") and method == .POST) {
- try self.handleClear(request);
- } else if (mem.eql(u8, target, "/") or mem.eql(u8, target, "/ui")) {
- try self.handleNewUI(request);
- } else if (mem.eql(u8, target, "/old")) {
- try self.handleVisualization(request);
- } else if (mem.eql(u8, target, "/health")) {
- try self.sendJson(request, "{\"status\":\"ok\",\"service\":\"trinity-kg\"}");
- } else {
- try self.sendError(request, "Not found");
- }
- }
-
- fn handleAdd(self: *KGServer, request: *http.Server.Request, body: []const u8) !void {
- const subject = parseJsonField(body, "subject") orelse {
- try self.sendError(request, "Missing subject");
- return;
- };
- const predicate = parseJsonField(body, "predicate") orelse {
- try self.sendError(request, "Missing predicate");
- return;
- };
- const object = parseJsonField(body, "object") orelse {
- try self.sendError(request, "Missing object");
- return;
- };
-
- const id = self.kg.addTriple(subject, predicate, object) catch {
- try self.sendError(request, "Failed to add triple");
- return;
- };
-
- const response = try jsonResponse(self.allocator, "{{\"status\":\"ok\",\"triple_id\":{d}}}", .{id});
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- }
-
- fn handleQuery(self: *KGServer, request: *http.Server.Request, target: []const u8) !void {
- const predicate_raw = parseQueryParam(target, "predicate") orelse {
- try self.sendError(request, "Missing predicate parameter");
- return;
- };
- const predicate = try urlDecode(self.allocator, predicate_raw);
- defer self.allocator.free(predicate);
-
- // Check if querying by subject or object
- if (parseQueryParam(target, "subject")) |subject_raw| {
- const subject = try urlDecode(self.allocator, subject_raw);
- defer self.allocator.free(subject);
-
- if (self.kg.queryObject(subject, predicate)) |result| {
- const response = try jsonResponse(self.allocator, "{{\"status\":\"ok\",\"result\":\"{s}\",\"similarity\":{d:.4}}}", .{ result.name, result.similarity });
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- } else {
- try self.sendJson(request, "{\"status\":\"ok\",\"result\":null}");
- }
- } else if (parseQueryParam(target, "object")) |object_raw| {
- const object = try urlDecode(self.allocator, object_raw);
- defer self.allocator.free(object);
-
- if (self.kg.querySubject(object, predicate)) |result| {
- const response = try jsonResponse(self.allocator, "{{\"status\":\"ok\",\"result\":\"{s}\",\"similarity\":{d:.4}}}", .{ result.name, result.similarity });
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- } else {
- try self.sendJson(request, "{\"status\":\"ok\",\"result\":null}");
- }
- } else {
- try self.sendError(request, "Missing subject or object parameter");
- }
- }
-
- /// Handle /api/reason - Multi-hop reasoning
- /// Params:
- /// - from, to, max_hops: Find path from entity to value
- /// - entity, property, max_hops: Check if property holds for entity
- fn handleReason(self: *KGServer, request: *http.Server.Request, target: []const u8) !void {
- // Parse max_hops (default 5)
- var max_hops: usize = 5;
- if (parseQueryParam(target, "max_hops")) |hops_str| {
- max_hops = std.fmt.parseInt(usize, hops_str, 10) catch 5;
- }
-
- // Mode 1: Find path from -> to
- if (parseQueryParam(target, "from")) |from_raw| {
- const from = try urlDecode(self.allocator, from_raw);
- defer self.allocator.free(from);
-
- const to_raw = parseQueryParam(target, "to") orelse {
- try self.sendError(request, "Missing 'to' parameter");
- return;
- };
- const to = try urlDecode(self.allocator, to_raw);
- defer self.allocator.free(to);
-
- const result = self.kg.findPath(from, to, max_hops) catch {
- try self.sendError(request, "Reasoning failed");
- return;
- };
- defer if (result.path.len > 0) self.allocator.free(result.path);
-
- if (result.found) {
- // Build path JSON
- var path_json = std.ArrayList(u8).init(self.allocator);
- defer path_json.deinit();
-
- try path_json.appendSlice("[");
- for (result.path, 0..) |step, i| {
- if (i > 0) try path_json.appendSlice(",");
- const step_json = try std.fmt.allocPrint(self.allocator, "{{\"entity\":\"{s}\",\"relation\":\"{s}\",\"next\":\"{s}\"}}", .{ step.entity, step.relation, step.next_entity });
- defer self.allocator.free(step_json);
- try path_json.appendSlice(step_json);
- }
- try path_json.appendSlice("]");
-
- // Build conclusion string
- var conclusion = std.ArrayList(u8).init(self.allocator);
- defer conclusion.deinit();
- try conclusion.appendSlice(from);
- for (result.path) |step| {
- try conclusion.appendSlice(" -> ");
- try conclusion.appendSlice(step.relation);
- try conclusion.appendSlice(" -> ");
- try conclusion.appendSlice(step.next_entity);
- }
-
- const response = try std.fmt.allocPrint(self.allocator, "{{\"status\":\"ok\",\"found\":true,\"hops\":{d},\"path\":{s},\"conclusion\":\"{s}\"}}", .{ result.hops, path_json.items, conclusion.items });
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- } else {
- const response = try std.fmt.allocPrint(self.allocator, "{{\"status\":\"ok\",\"found\":false,\"message\":\"No path from '{s}' to '{s}' within {d} hops\"}}", .{ from, to, max_hops });
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- }
- return;
- }
-
- // Mode 2: Check property (e.g., "Is Socrates mortal?")
- if (parseQueryParam(target, "entity")) |entity_raw| {
- const entity = try urlDecode(self.allocator, entity_raw);
- defer self.allocator.free(entity);
-
- const property_raw = parseQueryParam(target, "property") orelse {
- try self.sendError(request, "Missing 'property' parameter");
- return;
- };
- const property = try urlDecode(self.allocator, property_raw);
- defer self.allocator.free(property);
-
- const result = self.kg.checkProperty(entity, property, max_hops) catch {
- try self.sendError(request, "Reasoning failed");
- return;
- };
- defer if (result.path.len > 0) self.allocator.free(result.path);
-
- if (result.holds) {
- // Build path JSON
- var path_json = std.ArrayList(u8).init(self.allocator);
- defer path_json.deinit();
-
- try path_json.appendSlice("[");
- for (result.path, 0..) |step, i| {
- if (i > 0) try path_json.appendSlice(",");
- const step_json = try std.fmt.allocPrint(self.allocator, "{{\"entity\":\"{s}\",\"relation\":\"{s}\",\"next\":\"{s}\"}}", .{ step.entity, step.relation, step.next_entity });
- defer self.allocator.free(step_json);
- try path_json.appendSlice(step_json);
- }
- try path_json.appendSlice("]");
-
- // Build explanation
- var explanation = std.ArrayList(u8).init(self.allocator);
- defer explanation.deinit();
- try explanation.appendSlice(entity);
- for (result.path) |step| {
- try explanation.appendSlice(" -> ");
- try explanation.appendSlice(step.relation);
- try explanation.appendSlice(" -> ");
- try explanation.appendSlice(step.next_entity);
- }
-
- const response = try std.fmt.allocPrint(self.allocator, "{{\"status\":\"ok\",\"holds\":true,\"value\":\"{s}\",\"hops\":{d},\"path\":{s},\"explanation\":\"{s}\"}}", .{ result.value.?, result.path.len, path_json.items, explanation.items });
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- } else {
- const response = try std.fmt.allocPrint(self.allocator, "{{\"status\":\"ok\",\"holds\":false,\"message\":\"Cannot determine if '{s}' has property '{s}'\"}}", .{ entity, property });
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- }
- return;
- }
-
- try self.sendError(request, "Missing parameters. Use: from+to or entity+property");
- }
-
- fn handleStats(self: *KGServer, request: *http.Server.Request) !void {
- const stats = self.kg.getStats();
- const response = try jsonResponse(self.allocator, "{{\"status\":\"ok\",\"entities\":{d},\"relations\":{d},\"triples\":{d}}}", .{ stats.entities, stats.relations, stats.triples });
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- }
-
- fn handleList(self: *KGServer, request: *http.Server.Request) !void {
- var response = std.ArrayList(u8).init(self.allocator);
- defer response.deinit();
-
- try response.appendSlice("{\"status\":\"ok\",\"triples\":[");
-
- for (self.kg.triples.items, 0..) |triple, i| {
- if (i > 0) try response.appendSlice(",");
- const triple_json = try std.fmt.allocPrint(self.allocator, "[\"{s}\",\"{s}\",\"{s}\"]", .{ triple.subject, triple.predicate, triple.object });
- defer self.allocator.free(triple_json);
- try response.appendSlice(triple_json);
- }
-
- try response.appendSlice("]}");
- try self.sendJson(request, response.items);
- }
-
- fn handleSave(self: *KGServer, request: *http.Server.Request, body: []const u8) !void {
- const path = parseJsonField(body, "path") orelse "graph.trkg";
-
- self.kg.save(path) catch {
- try self.sendError(request, "Failed to save graph");
- return;
- };
-
- try self.sendJson(request, "{\"status\":\"ok\"}");
- }
-
- fn handleLoad(self: *KGServer, request: *http.Server.Request, body: []const u8) !void {
- const path = parseJsonField(body, "path") orelse "graph.trkg";
-
- const count = self.kg.load(path) catch {
- try self.sendError(request, "Failed to load graph");
- return;
- };
-
- const response = try jsonResponse(self.allocator, "{{\"status\":\"ok\",\"triples\":{d}}}", .{count});
- defer self.allocator.free(response);
- try self.sendJson(request, response);
- }
-
- fn handleClear(self: *KGServer, request: *http.Server.Request) !void {
- self.kg.clear();
- try self.sendJson(request, "{\"status\":\"ok\"}");
- }
-
- /// Handle /api/graph - Return D3.js compatible graph format
- fn handleGraph(self: *KGServer, request: *http.Server.Request) !void {
- var response = std.ArrayList(u8).init(self.allocator);
- defer response.deinit();
-
- // Collect unique entities
- var entities = std.StringHashMap(usize).init(self.allocator);
- defer entities.deinit();
-
- const group_counter: usize = 1;
- for (self.kg.triples.items) |triple| {
- if (!entities.contains(triple.subject)) {
- try entities.put(triple.subject, group_counter);
- }
- if (!entities.contains(triple.object)) {
- // Values get group 2, entities get group 1
- const is_value = mem.eql(u8, triple.object, "true") or
- mem.eql(u8, triple.object, "false") or
- (triple.object.len > 0 and (triple.object[0] >= '0' and triple.object[0] <= '9'));
- try entities.put(triple.object, if (is_value) 2 else 1);
- }
- }
-
- // Build nodes array
- try response.appendSlice("{\"nodes\":[");
- var first_node = true;
- var entity_iter = entities.iterator();
- while (entity_iter.next()) |entry| {
- if (!first_node) try response.appendSlice(",");
- first_node = false;
-
- const node_json = try std.fmt.allocPrint(self.allocator, "{{\"id\":\"{s}\",\"group\":{d}}}", .{ entry.key_ptr.*, entry.value_ptr.* });
- defer self.allocator.free(node_json);
- try response.appendSlice(node_json);
- }
- try response.appendSlice("],");
-
- // Build links array
- try response.appendSlice("\"links\":[");
- for (self.kg.triples.items, 0..) |triple, i| {
- if (i > 0) try response.appendSlice(",");
- const link_json = try std.fmt.allocPrint(self.allocator, "{{\"source\":\"{s}\",\"target\":\"{s}\",\"label\":\"{s}\"}}", .{ triple.subject, triple.object, triple.predicate });
- defer self.allocator.free(link_json);
- try response.appendSlice(link_json);
- }
- try response.appendSlice("]}");
-
- try self.sendJson(request, response.items);
- }
-
- /// Handle / and /ui - Serve new visualization HTML
- fn handleNewUI(self: *KGServer, request: *http.Server.Request) !void {
- _ = self;
- // Read HTML file
- const file = std.fs.cwd().openFile("trinity-kg-ui.html", .{}) catch {
- // Fallback to embedded HTML if file not found
- try request.respond("trinity-kg-ui.html not found Please ensure the file exists in the current directory.
", .{
- .status = .not_found,
- .extra_headers = &.{
- .{ .name = "Content-Type", .value = "text/html; charset=utf-8" },
- },
- });
- return;
- };
- defer file.close();
-
- var buf: [65536]u8 = undefined;
- const len = file.readAll(&buf) catch 0;
-
- try request.respond(buf[0..len], .{
- .status = .ok,
- .extra_headers = &.{
- .{ .name = "Content-Type", .value = "text/html; charset=utf-8" },
- },
- });
- }
-
- /// Handle /old - Serve old visualization HTML page
- fn handleVisualization(self: *KGServer, request: *http.Server.Request) !void {
- _ = self;
- const html =
- \\
- \\
- \\
- \\
- \\ Trinity Knowledge Graph
- \\
- \\
- \\
- \\
- \\
- \\
Trinity KG
- \\
Add Triple
- \\
- \\
- \\
- \\
Add
- \\
Actions
- \\
Clear
- \\
Refresh
- \\
Reasoning
- \\
- \\
- \\
Find Path
- \\
Try Examples
- \\
Is Socrates mortal?
- \\
Socrates β Aristotle
- \\
Athens β place
- \\
Click examples above or any node on graph
- \\
- \\
- \\
- \\
- \\
- \\
- \\
- ;
-
- try request.respond(html, .{
- .status = .ok,
- .extra_headers = &.{
- .{ .name = "Content-Type", .value = "text/html; charset=utf-8" },
- },
- });
- }
-
- fn sendJson(self: *KGServer, request: *http.Server.Request, content: []const u8) !void {
- _ = self;
- try request.respond(content, .{
- .status = .ok,
- .extra_headers = &.{
- .{ .name = "Content-Type", .value = "application/json" },
- .{ .name = "Access-Control-Allow-Origin", .value = "*" },
- },
- });
- }
-
- fn sendError(self: *KGServer, request: *http.Server.Request, message: []const u8) !void {
- const response = try jsonResponse(self.allocator, "{{\"status\":\"error\",\"message\":\"{s}\"}}", .{message});
- defer self.allocator.free(response);
- try request.respond(response, .{
- .status = .bad_request,
- .extra_headers = &.{
- .{ .name = "Content-Type", .value = "application/json" },
- .{ .name = "Access-Control-Allow-Origin", .value = "*" },
- },
- });
- }
-
- /// Load example data for demonstration
- fn loadDefaultData(self: *KGServer) void {
- // Greek philosophers knowledge graph
- _ = self.kg.addTriple("Socrates", "is_a", "human") catch {};
- _ = self.kg.addTriple("Plato", "is_a", "human") catch {};
- _ = self.kg.addTriple("Aristotle", "is_a", "human") catch {};
- _ = self.kg.addTriple("human", "is_mortal", "true") catch {};
- _ = self.kg.addTriple("Socrates", "teacher_of", "Plato") catch {};
- _ = self.kg.addTriple("Plato", "teacher_of", "Aristotle") catch {};
- _ = self.kg.addTriple("Plato", "founded", "Academy") catch {};
- _ = self.kg.addTriple("Aristotle", "founded", "Lyceum") catch {};
- _ = self.kg.addTriple("Socrates", "born_in", "Athens") catch {};
- _ = self.kg.addTriple("Plato", "born_in", "Athens") catch {};
- _ = self.kg.addTriple("Athens", "is_a", "city") catch {};
- _ = self.kg.addTriple("city", "is_a", "place") catch {};
-
- std.debug.print("Loaded 12 default triples (Greek philosophers)\n", .{});
- }
-
- /// Run server loop
- pub fn run(self: *KGServer) !void {
- // Load default data for demonstration
- self.loadDefaultData();
-
- std.debug.print("\n", .{});
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("β Trinity Knowledge Graph Server β\n", .{});
- std.debug.print("β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
- std.debug.print("β http://127.0.0.1:{d:<5} β\n", .{self.server.listen_address.getPort()});
- std.debug.print("β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
- std.debug.print("β GET / - Interactive visualization β\n", .{});
- std.debug.print("β GET /api/graph - D3.js graph format β\n", .{});
- std.debug.print("β GET /api/reason - Multi-hop reasoning β\n", .{});
- std.debug.print("β POST /api/add - Add triple β\n", .{});
- std.debug.print("β GET /api/query - Query graph β\n", .{});
- std.debug.print("β GET /api/stats - Statistics β\n", .{});
- std.debug.print("β GET /api/list - List triples β\n", .{});
- std.debug.print("β POST /api/save - Save to file β\n", .{});
- std.debug.print("β POST /api/load - Load from file β\n", .{});
- std.debug.print("β POST /api/clear - Clear graph β\n", .{});
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("\n", .{});
-
- var read_buffer: [8192]u8 = undefined;
-
- while (self.running) {
- const connection = self.server.accept() catch |err| {
- std.debug.print("Accept error: {}\n", .{err});
- continue;
- };
-
- var server = http.Server.init(connection, &read_buffer);
- defer connection.stream.close();
-
- var request = server.receiveHead() catch |err| {
- std.debug.print("Receive error: {}\n", .{err});
- continue;
- };
-
- self.handleRequest(&request) catch |err| {
- std.debug.print("Handle error: {}\n", .{err});
- };
- }
- }
-};
-
-// ============================================================================
-// Main Entry Point
-// ============================================================================
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- const args = try std.process.argsAlloc(allocator);
- defer std.process.argsFree(allocator, args);
-
- var port: u16 = 8080;
- if (args.len > 1) {
- port = std.fmt.parseInt(u16, args[1], 10) catch 8080;
- }
-
- var server = try KGServer.init(allocator, port);
- defer server.deinit();
-
- try server.run();
-}
-
-// ============================================================================
-// Tests
-// ============================================================================
-
-test "KnowledgeGraph basic operations" {
- const allocator = std.testing.allocator;
- var kg = KnowledgeGraph.init(allocator);
- defer kg.deinit();
-
- // Add triples
- _ = try kg.addTriple("Socrates", "is_a", "human");
- _ = try kg.addTriple("human", "is_mortal", "true");
- _ = try kg.addTriple("Plato", "is_a", "human");
-
- // Check stats
- const stats = kg.getStats();
- try std.testing.expectEqual(@as(usize, 4), stats.entities); // Socrates, human, true, Plato
- try std.testing.expectEqual(@as(usize, 2), stats.relations); // is_a, is_mortal
- try std.testing.expectEqual(@as(usize, 3), stats.triples);
-
- // Query: What is Socrates?
- if (kg.queryObject("Socrates", "is_a")) |result| {
- try std.testing.expectEqualStrings("human", result.name);
- try std.testing.expect(result.similarity > 0.9);
- } else {
- return error.QueryFailed;
- }
-
- // Query: Who is human?
- if (kg.querySubject("human", "is_a")) |result| {
- // Should find Socrates or Plato
- try std.testing.expect(mem.eql(u8, result.name, "Socrates") or mem.eql(u8, result.name, "Plato"));
- } else {
- return error.QueryFailed;
- }
-}
-
-test "embedding similarity" {
- const emb1 = computeEmbedding("hello");
- const emb2 = computeEmbedding("hello");
- const emb3 = computeEmbedding("world");
-
- // Same text should have similarity 1.0
- try std.testing.expectApproxEqAbs(@as(f32, 1.0), cosineSimilarity(emb1, emb2), 0.001);
-
- // Different text should have lower similarity
- const sim = cosineSimilarity(emb1, emb3);
- try std.testing.expect(sim < 1.0);
- try std.testing.expect(sim > 0.0);
-}
-
-test "URL decode" {
- const allocator = std.testing.allocator;
-
- const decoded = try urlDecode(allocator, "hello%20world");
- defer allocator.free(decoded);
- try std.testing.expectEqualStrings("hello world", decoded);
-
- const decoded2 = try urlDecode(allocator, "test+value");
- defer allocator.free(decoded2);
- try std.testing.expectEqualStrings("test value", decoded2);
-}
-
-test "parse query param" {
- const target = "/api/query?subject=Socrates&predicate=is_a";
-
- try std.testing.expectEqualStrings("Socrates", parseQueryParam(target, "subject").?);
- try std.testing.expectEqualStrings("is_a", parseQueryParam(target, "predicate").?);
- try std.testing.expect(parseQueryParam(target, "object") == null);
-}
-
-test "parse JSON field" {
- const json = "{\"subject\":\"Socrates\",\"predicate\":\"is_a\",\"object\":\"human\"}";
-
- try std.testing.expectEqualStrings("Socrates", parseJsonField(json, "subject").?);
- try std.testing.expectEqualStrings("is_a", parseJsonField(json, "predicate").?);
- try std.testing.expectEqualStrings("human", parseJsonField(json, "object").?);
-}
-
-test "multi-hop reasoning: find path" {
- const allocator = std.testing.allocator;
- var kg = KnowledgeGraph.init(allocator);
- defer kg.deinit();
-
- // Build knowledge graph:
- // Socrates -> is_a -> human -> is_mortal -> true
- _ = try kg.addTriple("Socrates", "is_a", "human");
- _ = try kg.addTriple("human", "is_mortal", "true");
- _ = try kg.addTriple("Plato", "is_a", "human");
- _ = try kg.addTriple("Aristotle", "is_a", "human");
-
- // Find path from Socrates to true
- const result = try kg.findPath("Socrates", "true", 5);
- defer if (result.path.len > 0) allocator.free(result.path);
-
- try std.testing.expect(result.found);
- try std.testing.expectEqual(@as(usize, 2), result.hops);
- try std.testing.expectEqual(@as(usize, 2), result.path.len);
-
- // First step: Socrates -> is_a -> human
- try std.testing.expectEqualStrings("Socrates", result.path[0].entity);
- try std.testing.expectEqualStrings("is_a", result.path[0].relation);
- try std.testing.expectEqualStrings("human", result.path[0].next_entity);
-
- // Second step: human -> is_mortal -> true
- try std.testing.expectEqualStrings("human", result.path[1].entity);
- try std.testing.expectEqualStrings("is_mortal", result.path[1].relation);
- try std.testing.expectEqualStrings("true", result.path[1].next_entity);
-}
-
-test "multi-hop reasoning: check property" {
- const allocator = std.testing.allocator;
- var kg = KnowledgeGraph.init(allocator);
- defer kg.deinit();
-
- // Socrates -> is_a -> human -> is_mortal -> true
- _ = try kg.addTriple("Socrates", "is_a", "human");
- _ = try kg.addTriple("human", "is_mortal", "true");
-
- // Check: Is Socrates mortal?
- const result = try kg.checkProperty("Socrates", "is_mortal", 5);
- defer if (result.path.len > 0) allocator.free(result.path);
-
- try std.testing.expect(result.holds);
- try std.testing.expectEqualStrings("true", result.value.?);
- try std.testing.expectEqual(@as(usize, 2), result.path.len);
-}
-
-test "multi-hop reasoning: no path" {
- const allocator = std.testing.allocator;
- var kg = KnowledgeGraph.init(allocator);
- defer kg.deinit();
-
- _ = try kg.addTriple("Socrates", "is_a", "human");
- _ = try kg.addTriple("cat", "is_a", "animal");
-
- // No path from Socrates to animal
- const result = try kg.findPath("Socrates", "animal", 5);
- defer if (result.path.len > 0) allocator.free(result.path);
-
- try std.testing.expect(!result.found);
-}
diff --git a/src/knowledge_graph.zig b/src/knowledge_graph.zig
deleted file mode 100644
index 9984c9c418..0000000000
--- a/src/knowledge_graph.zig
+++ /dev/null
@@ -1,700 +0,0 @@
-// @origin(spec:knowledge_graph.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity VSA Knowledge Graph
-// onand on within Vector Symbolic Architecture
-//
-// to: Triple = (Subject, Predicate, Object)
-// andinand: bind(subject, bind(predicate, object))
-// : bundle inwith andin
-//
-// β²€β²β²β²’β² β²ͺβ²β²’β²β²¨β²β²: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// ΟΒ² + 1/ΟΒ² = 3
-
-const std = @import("std");
-const vsa = @import("vsa.zig");
-const hybrid = @import("hybrid.zig");
-const packed_vsa = @import("packed_vsa.zig");
-const packed_trit = @import("packed_trit.zig");
-
-const HybridBigInt = hybrid.HybridBigInt;
-const PackedBigInt = packed_trit.PackedBigInt;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// FILE FORMAT CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Magic bytes for andandtoand file
-pub const FILE_MAGIC = [4]u8{ 'T', 'R', 'K', 'G' };
-
-/// withand file
-pub const FILE_VERSION: u32 = 1;
-
-/// packed into in
-pub const PACKED_VECTOR_BYTES = (VECTOR_DIM + 4) / 5; // 5 andin on
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// with VSA intoin (toandwithin andin)
-pub const VECTOR_DIM = 500;
-
-/// towithand toandwithin with in
-pub const MAX_ENTITIES = 100;
-
-/// towithand toandwithin andin
-pub const MAX_TRIPLES = 200;
-
-/// within for tuning
-pub const SIMILARITY_THRESHOLD = 0.3;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// with in onand (andwithby PackedBigInt for toand and)
-pub const Entity = struct {
- name: []const u8,
- vector: PackedBigInt,
- id: u32,
-
- const Self = @This();
-
- /// yes with and and
- pub fn init(name: []const u8, id: u32) Self {
- // notand vector and and
- const seed = hashString(name);
- const packed_vec = packed_vsa.randomPackedVector(VECTOR_DIM, seed);
- return Self{
- .name = name,
- .vector = packed_vec,
- .id = id,
- };
- }
-
- /// withtoand for seed
- pub fn hashString(s: []const u8) u64 {
- var hash: u64 = 5381;
- for (s) |c| {
- hash = ((hash << 5) +% hash) +% c;
- }
- return hash;
- }
-};
-
-/// and between withand
-pub const Relation = struct {
- name: []const u8,
- vector: PackedBigInt,
- id: u32,
-
- const Self = @This();
-
- pub fn init(name: []const u8, id: u32) Self {
- const seed = Entity.hashString(name) ^ 0xDEADBEEF; // seed for fromand
- const packed_vec = packed_vsa.randomPackedVector(VECTOR_DIM, seed);
- return Self{
- .name = name,
- .vector = packed_vec,
- .id = id,
- };
- }
-};
-
-/// and (Subject, Predicate, Object)
-pub const Triple = struct {
- subject_id: u32,
- predicate_id: u32,
- object_id: u32,
- vector: PackedBigInt,
-
- const Self = @This();
-
- /// yes and and toandin in vector
- pub fn init(
- subject: *const Entity,
- predicate: *const Relation,
- object: *const Entity,
- ) Self {
- // andinand: bind(subject, bind(predicate, object))
- const pred_obj = packed_vsa.packedBind(&predicate.vector, &object.vector);
- const triple_vec = packed_vsa.packedBind(&subject.vector, &pred_obj);
-
- return Self{
- .subject_id = subject.id,
- .predicate_id = predicate.id,
- .object_id = object.id,
- .vector = triple_vec,
- };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// KNOWLEDGE GRAPH
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// onand on within VSA (andwithby PackedBigInt)
-pub const KnowledgeGraph = struct {
- /// with withand
- entities: [MAX_ENTITIES]?Entity,
- entity_count: u32,
-
- /// with fromand
- relations: [MAX_ENTITIES]?Relation,
- relation_count: u32,
-
- /// with and
- triples: [MAX_TRIPLES]?Triple,
- triple_count: u32,
-
- /// byand inwith andin ( how and vector)
- graph_vector: PackedBigInt,
-
- const Self = @This();
-
- /// yes with
- pub fn init() Self {
- return Self{
- .entities = [_]?Entity{null} ** MAX_ENTITIES,
- .entity_count = 0,
- .relations = [_]?Relation{null} ** MAX_ENTITIES,
- .relation_count = 0,
- .triples = [_]?Triple{null} ** MAX_TRIPLES,
- .triple_count = 0,
- .graph_vector = PackedBigInt.zero(),
- };
- }
-
- /// inand or onand with
- pub fn getOrCreateEntity(self: *Self, name: []const u8) *Entity {
- // andwithto within
- for (0..self.entity_count) |i| {
- if (self.entities[i]) |*e| {
- if (std.mem.eql(u8, e.name, name)) {
- return e;
- }
- }
- }
-
- // yes in
- const id = self.entity_count;
- self.entities[id] = Entity.init(name, id);
- self.entity_count += 1;
- return &self.entities[id].?;
- }
-
- /// inand or onand fromand
- pub fn getOrCreateRelation(self: *Self, name: []const u8) *Relation {
- for (0..self.relation_count) |i| {
- if (self.relations[i]) |*r| {
- if (std.mem.eql(u8, r.name, name)) {
- return r;
- }
- }
- }
-
- const id = self.relation_count;
- self.relations[id] = Relation.init(name, id);
- self.relation_count += 1;
- return &self.relations[id].?;
- }
-
- /// inand and in
- pub fn addTriple(self: *Self, subject: []const u8, predicate: []const u8, object: []const u8) void {
- const subj = self.getOrCreateEntity(subject);
- const pred = self.getOrCreateRelation(predicate);
- const obj = self.getOrCreateEntity(object);
-
- const triple = Triple.init(subj, pred, obj);
-
- // inand in list andin
- self.triples[self.triple_count] = triple;
- self.triple_count += 1;
-
- // inand -vector (bundle)
- if (self.triple_count == 1) {
- self.graph_vector = triple.vector;
- } else {
- self.graph_vector = packed_vsa.packedBundle(&self.graph_vector, &triple.vector);
- }
- }
-
- /// with: onand object by subject and predicate
- /// query(subject, predicate, ?) β object
- /// withby unbind: result = unbind(graph, bind(subject, predicate))
- pub fn queryObject(self: *Self, subject: []const u8, predicate: []const u8) ?*Entity {
- const subj = self.findEntity(subject) orelse return null;
- const pred = self.findRelation(predicate) orelse return null;
-
- // yes pattern with: bind(subject, predicate)
- const query_pattern = packed_vsa.packedBind(&subj.vector, &pred.vector);
-
- // Unbind from : unbind(graph, query_pattern) β object
- const result_vec = packed_vsa.packedUnbind(&self.graph_vector, &query_pattern);
-
- // and and with to result
- return self.findClosestEntityPacked(&result_vec);
- }
-
- /// with: onand subject by predicate and object
- /// query(?, predicate, object) β subject
- /// withby unbind: result = unbind(graph, bind(predicate, object))
- pub fn querySubject(self: *Self, predicate: []const u8, object: []const u8) ?*Entity {
- const pred = self.findRelation(predicate) orelse return null;
- const obj = self.findEntity(object) orelse return null;
-
- // yes pattern with: bind(predicate, object)
- const query_pattern = packed_vsa.packedBind(&pred.vector, &obj.vector);
-
- // Unbind from : unbind(graph, query_pattern) β subject
- const result_vec = packed_vsa.packedUnbind(&self.graph_vector, &query_pattern);
-
- return self.findClosestEntityPacked(&result_vec);
- }
-
- /// and N onandmore byand with
- pub fn findSimilar(self: *Self, entity_name: []const u8, n: usize) [10]?struct { entity: *Entity, similarity: f64 } {
- var results: [10]?struct { entity: *Entity, similarity: f64 } = [_]?struct { entity: *Entity, similarity: f64 }{null} ** 10;
-
- const target = self.findEntity(entity_name) orelse return results;
-
- // andwithand within with inwithand withand
- var similarities: [MAX_ENTITIES]f64 = [_]f64{0} ** MAX_ENTITIES;
-
- for (0..self.entity_count) |i| {
- if (self.entities[i]) |*e| {
- if (!std.mem.eql(u8, e.name, entity_name)) {
- similarities[i] = packed_vsa.packedCosineSimilarity(&target.vector, &e.vector);
- }
- }
- }
-
- // and -N (with sorting)
- const result_count = @min(n, 10);
- for (0..result_count) |r| {
- var best_idx: ?usize = null;
- var best_sim: f64 = -2.0;
-
- for (0..self.entity_count) |i| {
- if (similarities[i] > best_sim) {
- // inand what not beforein
- var already_added = false;
- for (0..r) |prev| {
- if (results[prev]) |res| {
- if (res.entity.id == @as(u32, @intCast(i))) {
- already_added = true;
- break;
- }
- }
- }
- if (!already_added) {
- best_sim = similarities[i];
- best_idx = i;
- }
- }
- }
-
- if (best_idx) |idx| {
- if (self.entities[idx]) |*e| {
- results[r] = .{ .entity = e, .similarity = best_sim };
- }
- }
- }
-
- return results;
- }
-
- /// and with by and
- fn findEntity(self: *Self, name: []const u8) ?*Entity {
- for (0..self.entity_count) |i| {
- if (self.entities[i]) |*e| {
- if (std.mem.eql(u8, e.name, name)) {
- return e;
- }
- }
- }
- return null;
- }
-
- /// and fromand by and
- fn findRelation(self: *Self, name: []const u8) ?*Relation {
- for (0..self.relation_count) |i| {
- if (self.relations[i]) |*r| {
- if (std.mem.eql(u8, r.name, name)) {
- return r;
- }
- }
- }
- return null;
- }
-
- /// and and with to packed into
- fn findClosestEntityPacked(self: *Self, query_vec: *const PackedBigInt) ?*Entity {
- var best_entity: ?*Entity = null;
- var best_similarity: f64 = SIMILARITY_THRESHOLD;
-
- for (0..self.entity_count) |i| {
- if (self.entities[i]) |*e| {
- const sim = packed_vsa.packedCosineSimilarity(query_vec, &e.vector);
- if (sim > best_similarity) {
- best_similarity = sim;
- best_entity = e;
- }
- }
- }
-
- return best_entity;
- }
-
- /// andwithandto
- pub fn stats(self: *const Self) struct { entities: u32, relations: u32, triples: u32 } {
- return .{
- .entities = self.entity_count,
- .relations = self.relation_count,
- .triples = self.triple_count,
- };
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // PERSISTENCE - Save/Load
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// and in file
- pub fn save(self: *const Self, path: []const u8) !void {
- const file = try std.fs.cwd().createFile(path, .{});
- defer file.close();
-
- var writer = file.writer();
-
- // Header
- try writer.writeAll(&FILE_MAGIC);
- try writer.writeInt(u32, FILE_VERSION, .little);
- try writer.writeInt(u32, self.entity_count, .little);
- try writer.writeInt(u32, self.relation_count, .little);
-
- // Entities
- for (0..self.entity_count) |i| {
- if (self.entities[i]) |e| {
- // Name length and name
- const name_len: u16 = @intCast(e.name.len);
- try writer.writeInt(u16, name_len, .little);
- try writer.writeAll(e.name);
- // ID
- try writer.writeInt(u32, e.id, .little);
- // Vector data
- const trit_len: u32 = @intCast(e.vector.trit_len);
- try writer.writeInt(u32, trit_len, .little);
- const packed_len = (e.vector.trit_len + 4) / 5;
- try writer.writeAll(e.vector.data[0..packed_len]);
- }
- }
-
- // Relations
- for (0..self.relation_count) |i| {
- if (self.relations[i]) |r| {
- const name_len: u16 = @intCast(r.name.len);
- try writer.writeInt(u16, name_len, .little);
- try writer.writeAll(r.name);
- try writer.writeInt(u32, r.id, .little);
- const trit_len: u32 = @intCast(r.vector.trit_len);
- try writer.writeInt(u32, trit_len, .little);
- const packed_len = (r.vector.trit_len + 4) / 5;
- try writer.writeAll(r.vector.data[0..packed_len]);
- }
- }
-
- // Triples
- try writer.writeInt(u32, self.triple_count, .little);
- for (0..self.triple_count) |i| {
- if (self.triples[i]) |t| {
- try writer.writeInt(u32, t.subject_id, .little);
- try writer.writeInt(u32, t.predicate_id, .little);
- try writer.writeInt(u32, t.object_id, .little);
- const trit_len: u32 = @intCast(t.vector.trit_len);
- try writer.writeInt(u32, trit_len, .little);
- const packed_len = (t.vector.trit_len + 4) / 5;
- try writer.writeAll(t.vector.data[0..packed_len]);
- }
- }
-
- // Graph vector
- const graph_trit_len: u32 = @intCast(self.graph_vector.trit_len);
- try writer.writeInt(u32, graph_trit_len, .little);
- const graph_packed_len = (self.graph_vector.trit_len + 4) / 5;
- try writer.writeAll(self.graph_vector.data[0..graph_packed_len]);
- }
-
- /// and and file
- pub fn load(path: []const u8, name_buffer: []u8) !Self {
- const file = try std.fs.cwd().openFile(path, .{});
- defer file.close();
-
- var reader = file.reader();
- var result = Self.init();
-
- // Header
- var magic: [4]u8 = undefined;
- _ = try reader.readAll(&magic);
- if (!std.mem.eql(u8, &magic, &FILE_MAGIC)) {
- return error.InvalidFileFormat;
- }
-
- const version = try reader.readInt(u32, .little);
- if (version != FILE_VERSION) {
- return error.UnsupportedVersion;
- }
-
- const entity_count = try reader.readInt(u32, .little);
- const relation_count = try reader.readInt(u32, .little);
-
- // withby buffer for and
- var name_offset: usize = 0;
-
- // Entities
- for (0..entity_count) |i| {
- const name_len = try reader.readInt(u16, .little);
-
- // and and in buffer
- const name_start = name_offset;
- _ = try reader.readAll(name_buffer[name_offset .. name_offset + name_len]);
- name_offset += name_len;
-
- const id = try reader.readInt(u32, .little);
- const trit_len = try reader.readInt(u32, .little);
- const packed_len = (trit_len + 4) / 5;
-
- var vec = PackedBigInt.zero();
- vec.trit_len = trit_len;
- _ = try reader.readAll(vec.data[0..packed_len]);
-
- result.entities[i] = Entity{
- .name = name_buffer[name_start .. name_start + name_len],
- .vector = vec,
- .id = id,
- };
- result.entity_count += 1;
- }
-
- // Relations
- for (0..relation_count) |i| {
- const name_len = try reader.readInt(u16, .little);
-
- const name_start = name_offset;
- _ = try reader.readAll(name_buffer[name_offset .. name_offset + name_len]);
- name_offset += name_len;
-
- const id = try reader.readInt(u32, .little);
- const trit_len = try reader.readInt(u32, .little);
- const packed_len = (trit_len + 4) / 5;
-
- var vec = PackedBigInt.zero();
- vec.trit_len = trit_len;
- _ = try reader.readAll(vec.data[0..packed_len]);
-
- result.relations[i] = Relation{
- .name = name_buffer[name_start .. name_start + name_len],
- .vector = vec,
- .id = id,
- };
- result.relation_count += 1;
- }
-
- // Triples
- const triple_count = try reader.readInt(u32, .little);
- for (0..triple_count) |i| {
- const subject_id = try reader.readInt(u32, .little);
- const predicate_id = try reader.readInt(u32, .little);
- const object_id = try reader.readInt(u32, .little);
- const trit_len = try reader.readInt(u32, .little);
- const packed_len = (trit_len + 4) / 5;
-
- var vec = PackedBigInt.zero();
- vec.trit_len = trit_len;
- _ = try reader.readAll(vec.data[0..packed_len]);
-
- result.triples[i] = Triple{
- .subject_id = subject_id,
- .predicate_id = predicate_id,
- .object_id = object_id,
- .vector = vec,
- };
- result.triple_count += 1;
- }
-
- // Graph vector
- const graph_trit_len = try reader.readInt(u32, .little);
- const graph_packed_len = (graph_trit_len + 4) / 5;
- result.graph_vector.trit_len = graph_trit_len;
- _ = try reader.readAll(result.graph_vector.data[0..graph_packed_len]);
-
- return result;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "Entity creation" {
- const paris = Entity.init("Paris", 0);
- const france = Entity.init("France", 1);
-
- // withand before and into
- const sim = packed_vsa.packedCosineSimilarity(&paris.vector, &france.vector);
- try std.testing.expect(sim < 0.5); // and thaton
-}
-
-test "KnowledgeGraph basic operations" {
- var kg = KnowledgeGraph.init();
-
- // Add to withand
- kg.addTriple("Paris", "capital_of", "France");
- kg.addTriple("Berlin", "capital_of", "Germany");
- kg.addTriple("Rome", "capital_of", "Italy");
-
- const s = kg.stats();
- try std.testing.expectEqual(@as(u32, 6), s.entities); // 3 yes + 3 with
- try std.testing.expectEqual(@as(u32, 1), s.relations); // capital_of
- try std.testing.expectEqual(@as(u32, 3), s.triples);
-}
-
-test "KnowledgeGraph query object with unbind" {
- var kg = KnowledgeGraph.init();
-
- kg.addTriple("Paris", "capital_of", "France");
- kg.addTriple("Berlin", "capital_of", "Germany");
- kg.addTriple("Rome", "capital_of", "Italy");
-
- // with: and - withand ?
- // unbind(graph, bind(Paris, capital_of)) β France
- const result = kg.queryObject("Paris", "capital_of");
-
- std.debug.print("\n\nQuery: Paris capital_of ?\n", .{});
- if (result) |entity| {
- std.debug.print("Result: {s}\n", .{entity.name});
- // Check what result - France
- try std.testing.expectEqualStrings("France", entity.name);
- } else {
- std.debug.print("Result: null\n", .{});
- // withand null, test in
- try std.testing.expect(false);
- }
-}
-
-test "KnowledgeGraph query subject with unbind" {
- var kg = KnowledgeGraph.init();
-
- kg.addTriple("Paris", "capital_of", "France");
- kg.addTriple("Berlin", "capital_of", "Germany");
-
- // with: what is withand and?
- // unbind(graph, bind(capital_of, France)) β Paris
- const result = kg.querySubject("capital_of", "France");
-
- std.debug.print("\n\nQuery: ? capital_of France\n", .{});
- if (result) |entity| {
- std.debug.print("Result: {s}\n", .{entity.name});
- try std.testing.expectEqualStrings("Paris", entity.name);
- } else {
- std.debug.print("Result: null\n", .{});
- try std.testing.expect(false);
- }
-}
-
-test "save and load roundtrip" {
- // yes
- var kg = KnowledgeGraph.init();
- kg.addTriple("Paris", "capital_of", "France");
- kg.addTriple("Berlin", "capital_of", "Germany");
- kg.addTriple("Rome", "capital_of", "Italy");
-
- const original_stats = kg.stats();
-
- //
- try kg.save("/tmp/test_kg.trkg");
-
- //
- var name_buffer: [4096]u8 = undefined;
- var loaded_kg = try KnowledgeGraph.load("/tmp/test_kg.trkg", &name_buffer);
-
- // Check withandwithandto
- const loaded_stats = loaded_kg.stats();
- try std.testing.expectEqual(original_stats.entities, loaded_stats.entities);
- try std.testing.expectEqual(original_stats.relations, loaded_stats.relations);
- try std.testing.expectEqual(original_stats.triples, loaded_stats.triples);
-
- std.debug.print("\n\nSave/Load roundtrip:\n", .{});
- std.debug.print("Original: {d} entities, {d} relations, {d} triples\n", .{ original_stats.entities, original_stats.relations, original_stats.triples });
- std.debug.print("Loaded: {d} entities, {d} relations, {d} triples\n", .{ loaded_stats.entities, loaded_stats.relations, loaded_stats.triples });
-
- // Delete testin file
- std.fs.cwd().deleteFile("/tmp/test_kg.trkg") catch |err| {
- std.log.debug("knowledge_graph: test cleanup delete failed: {}", .{err});
- };
-}
-
-test "queries work after load" {
- // yes and with
- var kg = KnowledgeGraph.init();
- kg.addTriple("Paris", "capital_of", "France");
- kg.addTriple("Berlin", "capital_of", "Germany");
-
- try kg.save("/tmp/test_kg_query.trkg");
-
- //
- var name_buffer: [4096]u8 = undefined;
- var loaded_kg = try KnowledgeGraph.load("/tmp/test_kg_query.trkg", &name_buffer);
-
- // Check with
- const result = loaded_kg.queryObject("Paris", "capital_of");
-
- std.debug.print("\n\nQuery after load:\n", .{});
- std.debug.print("Query: Paris capital_of ?\n", .{});
-
- if (result) |entity| {
- std.debug.print("Result: {s}\n", .{entity.name});
- try std.testing.expectEqualStrings("France", entity.name);
- } else {
- std.debug.print("Result: null (FAILED)\n", .{});
- try std.testing.expect(false);
- }
-
- // Delete testin file
- std.fs.cwd().deleteFile("/tmp/test_kg_query.trkg") catch |err| {
- std.log.debug("knowledge_graph: test cleanup delete failed: {}", .{err});
- };
-}
-
-test "benchmark KnowledgeGraph" {
- var kg = KnowledgeGraph.init();
-
- // Add toin
- const countries = [_][]const u8{ "France", "Germany", "Italy", "Spain", "UK", "Poland", "Sweden", "Norway", "Finland", "Denmark" };
- const capitals = [_][]const u8{ "Paris", "Berlin", "Rome", "Madrid", "London", "Warsaw", "Stockholm", "Oslo", "Helsinki", "Copenhagen" };
-
- var timer = try std.time.Timer.start();
-
- // inand andin
- for (countries, capitals) |country, capital| {
- kg.addTriple(capital, "capital_of", country);
- }
-
- const add_ns = timer.read();
-
- // with
- timer.reset();
- const iterations = 100;
- for (0..iterations) |_| {
- _ = kg.queryObject("Paris", "capital_of");
- }
- const query_ns = timer.read();
-
- std.debug.print("\n\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("β KNOWLEDGE GRAPH BENCHMARK β\n", .{});
- std.debug.print("β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
- std.debug.print("β Entities: {d:4} | Relations: {d:4} | Triples: {d:4} β\n", .{ kg.entity_count, kg.relation_count, kg.triple_count });
- std.debug.print("β Add 10 triples: {d:6} us β\n", .{add_ns / 1000});
- std.debug.print("β Query (100 iter): {d:6} us ({d:4} us/query) β\n", .{ query_ns / 1000, query_ns / 1000 / iterations });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
diff --git a/src/math/gen_bench.zig b/src/math/gen_bench.zig
deleted file mode 100644
index 8703675d31..0000000000
--- a/src/math/gen_bench.zig
+++ /dev/null
@@ -1,566 +0,0 @@
-//! Math Benchmark β Generated from specs/tri/math/math_bench.tri
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! DO NOT EDIT: This file is generated from math_bench.tri spec
-//! Performance benchmarks vs Python/Rust with nexus logging
-
-const std = @import("std");
-
-// Re-export sacred constants
-const PHI = @import("gen_constants.zig").PHI;
-const PHI_SQUARED = @import("gen_constants.zig").PHI_SQUARED;
-const PHI_INV_SQUARED = @import("gen_constants.zig").PHI_INV_SQUARED;
-const TRINITY_SUM = @import("gen_constants.zig").TRINITY_SUM;
-
-// ============================================================================
-// TYPES
-// ============================================================================
-
-/// Benchmark category
-pub const BenchmarkCategory = enum(u8) {
- core,
- simd,
- sequence,
- floating_point,
- geometry,
- verification,
-};
-
-/// Single benchmark result
-pub const BenchmarkResult = struct {
- name: []const u8,
- category: BenchmarkCategory,
- iterations: usize,
- total_time_ns: u64,
- ops_per_second: f64,
- avg_time_ns: f64,
- baseline_ratio: ?f64,
- python_ratio: ?f64,
- rust_ratio: ?f64,
-};
-
-/// Complete benchmark suite
-pub const BenchmarkSuite = struct {
- results: []BenchmarkResult,
- total_time_ns: u64,
- timestamp: i64,
-};
-
-/// Configuration for benchmark run
-pub const BenchmarkConfig = struct {
- iterations_override: ?usize = null,
- warmup_iterations: usize = 1000,
- log_to_nexus: bool = true,
- nexus_path: []const u8 = "trinity-nexus/benchmarks/",
-};
-
-/// Output format for results
-pub const OutputFormat = enum(u8) {
- table,
- json,
- csv,
-};
-
-// ============================================================================
-// BENCHMARK FUNCTIONS
-// ============================================================================
-
-/// Benchmark golden wrap operation
-pub fn runGoldenWrapBench(allocator: std.mem.Allocator, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const n = if (iterations > 0) iterations else 10_000_000;
-
- const start = try std.time.Instant.now();
-
- var sum: f64 = 0.0;
- var i: usize = 0;
- while (i < n) : (i += 1) {
- // Golden wrap: wrap sum into [0, 1) using PHI
- const wrapped = sum - @floor(sum);
- sum = wrapped + PHI;
- if (sum >= 1000.0) sum = sum - @floor(sum / 1000.0) * 1000.0;
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "golden_wrap_10m",
- .category = .core,
- .iterations = n,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(n)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(n)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Benchmark Fibonacci hash
-pub fn runPhiHashBench(allocator: std.mem.Allocator, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const n = if (iterations > 0) iterations else 10_000_000;
-
- const start = try std.time.Instant.now();
-
- var hash_sum: u64 = 0;
- var i: usize = 0;
- while (i < n) : (i += 1) {
- // Phi hash: mix key with golden ratio
- const key = @as(u64, @intCast(i));
- const hash = phiHashMod(key, 16);
- hash_sum +%= hash;
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "phi_hash_10m",
- .category = .core,
- .iterations = n,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(n)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(n)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Fibonacci hash with modulo
-fn phiHashMod(key: u64, shift: u64) u64 {
- const phi_bits: u64 = 11400714819323198549; // 2^64 / phi
- const hashed = key +% phi_bits;
- const clamped_shift = @min(shift, @as(u64, 63));
- const mask = (@as(u64, 1) << clamped_shift) - 1;
- return (hashed >> clamped_shift) ^ (hashed & mask);
-}
-
-/// Benchmark SIMD golden wrap (placeholder for future SIMD implementation)
-pub fn runSIMDBench(allocator: std.mem.Allocator, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const n = if (iterations > 0) iterations else 10_000_000;
-
- const start = try std.time.Instant.now();
-
- // Placeholder: scalar implementation for now
- var sum: f64 = 0.0;
- var i: usize = 0;
- while (i < n) : (i += 1) {
- const wrapped = sum - @floor(sum);
- sum = wrapped + PHI;
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "simd_golden_wrap_10m",
- .category = .simd,
- .iterations = n,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(n)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(n)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Benchmark Fibonacci sequence
-pub fn runFibonacciBench(allocator: std.mem.Allocator, n: usize, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const iters = if (iterations > 0) iterations else 100;
-
- const start = try std.time.Instant.now();
-
- var result_sum: u64 = 0;
- var iter: usize = 0;
- while (iter < iters) : (iter += 1) {
- _ = fibonacci(n);
- result_sum +%= @truncate(iter);
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "fibonacci_10000",
- .category = .sequence,
- .iterations = iters,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(iters)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iters)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Fast Fibonacci using fast doubling (clamped to prevent overflow)
-fn fibonacci(n: usize) u64 {
- if (n == 0) return 0;
- if (n == 1) return 1;
- if (n > 90) return 2_880_067_194_370_816_120; // F(90), clamped for safety
-
- var a: u64 = 0;
- var b: u64 = 1;
- var i: usize = 2;
- while (i <= n and i < 100) : (i += 1) {
- const next = a + b;
- if (next < a) return b; // Overflow detected
- a = b;
- b = next;
- }
-
- return b;
-}
-
-/// Benchmark Lucas sequence
-pub fn runLucasBench(allocator: std.mem.Allocator, n: usize, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const iters = if (iterations > 0) iterations else 100;
-
- const start = try std.time.Instant.now();
-
- var iter: usize = 0;
- while (iter < iters) : (iter += 1) {
- _ = lucas(n);
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "lucas_10000",
- .category = .sequence,
- .iterations = iters,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(iters)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iters)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Lucas number calculation (clamped to prevent overflow)
-fn lucas(n: usize) u64 {
- if (n == 0) return 2;
- if (n == 1) return 1;
- if (n > 90) return 3_788_906_237_314_390_60; // L(90), clamped for safety
-
- var a: u64 = 2;
- var b: u64 = 1;
- var i: usize = 2;
- while (i <= n and i < 100) : (i += 1) {
- const next = a + b;
- if (next < a) return b; // Overflow detected
- a = b;
- b = next;
- }
-
- return b;
-}
-
-/// Benchmark Ο^n computation
-pub fn runPhiPowerBench(allocator: std.mem.Allocator, n: usize, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const power = if (n > 0) n else 1000;
- const iters = if (iterations > 0) iterations else 10000;
-
- const start = try std.time.Instant.now();
-
- var result: f64 = 0.0;
- var i: usize = 0;
- while (i < iters) : (i += 1) {
- result += std.math.pow(f64, PHI, @as(f64, @floatFromInt(power)));
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "phi_power_1000",
- .category = .floating_point,
- .iterations = iters,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(iters)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iters)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Benchmark Ο-spiral computation
-pub fn runSpiralBench(allocator: std.mem.Allocator, count: usize, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const n = if (count > 0) count else 1000;
- const iters = if (iterations > 0) iterations else 1000;
-
- const start = try std.time.Instant.now();
-
- var result_sum: f64 = 0.0;
- var iter: usize = 0;
- while (iter < iters) : (iter += 1) {
- var i: usize = 0;
- while (i < n) : (i += 1) {
- const angle = @as(f64, @floatFromInt(i)) * PHI;
- const radius = std.math.sqrt(@as(f64, @floatFromInt(i)));
- const x = radius * @cos(angle);
- const y = radius * @sin(angle);
- result_sum += x + y;
- }
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "spiral_1000",
- .category = .geometry,
- .iterations = iters * n,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(iters * n)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iters * n)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Benchmark Trinity identity verification
-pub fn runVerifyBench(allocator: std.mem.Allocator, iterations: usize) !BenchmarkResult {
- _ = allocator;
- const n = if (iterations > 0) iterations else 1_000_000;
-
- const start = try std.time.Instant.now();
-
- var verified_count: usize = 0;
- var i: usize = 0;
- while (i < n) : (i += 1) {
- const trinity_check = PHI_SQUARED + PHI_INV_SQUARED;
- if (@abs(trinity_check - 3.0) < 1e-10) {
- verified_count += 1;
- }
- }
-
- const end = try std.time.Instant.now();
- const elapsed_ns = end.since(start);
-
- return BenchmarkResult{
- .name = "trinity_verify",
- .category = .verification,
- .iterations = n,
- .total_time_ns = @intCast(elapsed_ns),
- .ops_per_second = @as(f64, @floatFromInt(n)) / @as(f64, @floatFromInt(elapsed_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(n)),
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-}
-
-/// Run complete benchmark suite
-pub fn runAllBenchmarks(allocator: std.mem.Allocator, config: BenchmarkConfig) !BenchmarkSuite {
- const results = try allocator.alloc(BenchmarkResult, 9);
-
- const iter = config.iterations_override orelse 10_000_000;
-
- results[0] = try runGoldenWrapBench(allocator, iter);
- results[1] = try runPhiHashBench(allocator, iter);
- results[2] = try runSIMDBench(allocator, iter);
- results[3] = try runFibonacciBench(allocator, 10000, 100);
- results[4] = try runLucasBench(allocator, 10000, 100);
- results[5] = try runPhiPowerBench(allocator, 1000, 10000);
- results[6] = try runSpiralBench(allocator, 1000, 1000);
- results[7] = try runVerifyBench(allocator, 1_000_000);
-
- // Verify all identities
- const verify_start = try std.time.Instant.now();
- var verify_count: usize = 0;
- var i: usize = 0;
- while (i < 10000) : (i += 1) {
- if (verifyTrinityIdentity()) verify_count += 1;
- if (verifyPhiIdentity()) verify_count += 1;
- }
- const verify_end = try std.time.Instant.now();
- const verify_ns = verify_end.since(verify_start);
-
- results[8] = BenchmarkResult{
- .name = "verify_all_identities",
- .category = .verification,
- .iterations = 20000,
- .total_time_ns = @intCast(verify_ns),
- .ops_per_second = 20000.0 / @as(f64, @floatFromInt(verify_ns)) * 1_000_000_000.0,
- .avg_time_ns = @as(f64, @floatFromInt(verify_ns)) / 20000.0,
- .baseline_ratio = null,
- .python_ratio = null,
- .rust_ratio = null,
- };
-
- var total_ns: u64 = 0;
- for (results) |r| {
- total_ns += r.total_time_ns;
- }
-
- const timestamp128 = std.time.nanoTimestamp();
- const timestamp = @as(i64, @truncate(timestamp128));
-
- return BenchmarkSuite{
- .results = results,
- .total_time_ns = total_ns,
- .timestamp = timestamp,
- };
-}
-
-/// Verify Trinity identity
-fn verifyTrinityIdentity() bool {
- const diff = @abs((PHI_SQUARED + PHI_INV_SQUARED) - 3.0);
- return diff < 1e-10;
-}
-
-/// Verify Phi identity
-fn verifyPhiIdentity() bool {
- const diff = @abs(PHI_SQUARED - (PHI + 1.0));
- return diff < 1e-10;
-}
-
-/// Print benchmark results as formatted table
-pub fn printBenchmarkResults(suite: BenchmarkSuite, format: OutputFormat) !void {
- switch (format) {
- .table => {
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("β SACRED MATHEMATICS β BENCHMARK RESULTS β\n", .{});
- std.debug.print("β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
- std.debug.print("β {:30} {:>15} {:>12} β\n", .{ "Benchmark", "Ops/sec", "Time (ns)" });
- std.debug.print("β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β\n", .{});
-
- for (suite.results) |r| {
- const ops_str = formatOpsPerSec(r.ops_per_second);
- const time_str = formatTime(r.avg_time_ns);
- std.debug.print("β {:30} {:>15} {:>12} β\n", .{ r.name, ops_str, time_str });
- }
-
- std.debug.print("β β\n", .{});
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- },
- .json => {
- std.debug.print("{{\n", .{});
- std.debug.print(" \"timestamp\": {},\n", .{suite.timestamp});
- std.debug.print(" \"total_time_ns\": {},\n", .{suite.total_time_ns});
- std.debug.print(" \"results\": [\n", .{});
- for (suite.results, 0..) |r, i| {
- const comma = if (i < suite.results.len - 1) "," else "";
- std.debug.print(" {{\"name\": \"{s}\", \"ops_per_second\": {d:.2}, \"avg_time_ns\": {d:.2}}}{}\n", .{ r.name, r.ops_per_second, r.avg_time_ns, comma });
- }
- std.debug.print(" ]\n", .{});
- std.debug.print("}}\n", .{});
- },
- .csv => {
- std.debug.print("Benchmark,Category,Iterations,Ops/sec,AvgTime_ns\n", .{});
- for (suite.results) |r| {
- std.debug.print("{s},{s},{},{d:.2},{d:.2}\n", .{ r.name, @tagName(r.category), r.iterations, r.ops_per_second, r.avg_time_ns });
- }
- },
- }
-}
-
-/// Format operations per second with appropriate units
-fn formatOpsPerSec(ops: f64) []const u8 {
- var buf: [64]u8 = undefined;
- if (ops >= 1_000_000_000) {
- std.fmt.bufPrint(&buf, "{d:.2} G", .{ops / 1_000_000_000.0}) catch return "N/A";
- } else if (ops >= 1_000_000) {
- std.fmt.bufPrint(&buf, "{d:.2} M", .{ops / 1_000_000.0}) catch return "N/A";
- } else if (ops >= 1_000) {
- std.fmt.bufPrint(&buf, "{d:.2} K", .{ops / 1_000.0}) catch return "N/A";
- } else {
- std.fmt.bufPrint(&buf, "{d:.2}", .{ops}) catch return "N/A";
- }
- return &buf;
-}
-
-/// Format time with appropriate units
-fn formatTime(ns: f64) []const u8 {
- var buf: [64]u8 = undefined;
- if (ns >= 1_000_000) {
- std.fmt.bufPrint(&buf, "{d:.2} ms", .{ns / 1_000_000.0}) catch return "N/A";
- } else if (ns >= 1_000) {
- std.fmt.bufPrint(&buf, "{d:.2} us", .{ns / 1_000.0}) catch return "N/A";
- } else {
- std.fmt.bufPrint(&buf, "{d:.2} ns", .{ns}) catch return "N/A";
- }
- return &buf;
-}
-
-/// Compare with baseline
-pub fn compareWithBaseline(current: BenchmarkResult, baseline: BenchmarkResult) f64 {
- if (baseline.avg_time_ns == 0) return 1.0;
- return baseline.avg_time_ns / current.avg_time_ns;
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "Math Bench: runGoldenWrapBench" {
- const allocator = std.testing.allocator;
- const result = try runGoldenWrapBench(allocator, 1000);
- try std.testing.expectEqual(@as(usize, 1000), result.iterations);
- try std.testing.expect(result.ops_per_second > 0);
-}
-
-test "Math Bench: runPhiHashBench" {
- const allocator = std.testing.allocator;
- const result = try runPhiHashBench(allocator, 1000);
- try std.testing.expectEqual(@as(usize, 1000), result.iterations);
- try std.testing.expect(result.ops_per_second > 0);
-}
-
-test "Math Bench: runVerifyBench" {
- const allocator = std.testing.allocator;
- const result = try runVerifyBench(allocator, 10000);
- try std.testing.expectEqual(@as(usize, 10000), result.iterations);
- try std.testing.expect(result.ops_per_second > 0);
-}
-
-test "Math Bench: runAllBenchmarks" {
- const allocator = std.testing.allocator;
- const config = BenchmarkConfig{ .iterations_override = 100, .log_to_nexus = false };
- const suite = try runAllBenchmarks(allocator, config);
- defer allocator.free(suite.results);
- try std.testing.expectEqual(@as(usize, 9), suite.results.len);
-}
-
-test "Math Bench: phiHashMod" {
- const hash1 = phiHashMod(12345, 16);
- const hash2 = phiHashMod(12345, 16);
- try std.testing.expectEqual(hash1, hash2);
-}
-
-test "Math Bench: fibonacci" {
- try std.testing.expectEqual(@as(u64, 0), fibonacci(0));
- try std.testing.expectEqual(@as(u64, 1), fibonacci(1));
- try std.testing.expectEqual(@as(u64, 1), fibonacci(2));
- try std.testing.expectEqual(@as(u64, 2), fibonacci(3));
- try std.testing.expectEqual(@as(u64, 3), fibonacci(4));
-}
-
-test "Math Bench: lucas" {
- try std.testing.expectEqual(@as(u64, 2), lucas(0));
- try std.testing.expectEqual(@as(u64, 1), lucas(1));
- try std.testing.expectEqual(@as(u64, 3), lucas(2));
- try std.testing.expectEqual(@as(u64, 4), lucas(3));
-}
-
-test "Math Bench: verifyTrinityIdentity" {
- try std.testing.expect(verifyTrinityIdentity());
-}
-
-test "Math Bench: verifyPhiIdentity" {
- try std.testing.expect(verifyPhiIdentity());
-}
diff --git a/src/math/gen_commands.zig b/src/math/gen_commands.zig
deleted file mode 100644
index f1b961a9d1..0000000000
--- a/src/math/gen_commands.zig
+++ /dev/null
@@ -1,470 +0,0 @@
-//! Math CLI Commands β Generated from specs/tri/math/math_cli.tri
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! DO NOT EDIT: This file is generated from math_cli.tri spec
-//! Command hierarchy, aliases, help text, argument parsing
-
-const std = @import("std");
-
-// Re-export from other math modules
-const gen_constants = @import("gen_constants.zig");
-const gen_eval = @import("gen_eval.zig");
-const gen_identities = @import("gen_identities.zig");
-
-pub const PHI = gen_constants.PHI;
-pub const PI = gen_constants.PI;
-pub const E = gen_constants.E;
-
-// ============================================================================
-// TYPES
-// ============================================================================
-
-/// Output format for commands
-pub const OutputFormat = enum(u8) {
- pretty,
- json,
- csv,
-};
-
-// ============================================================================
-// HELP TEXT
-// ============================================================================
-
-pub const MATH_HELP_TEXT =
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- \\β SACRED MATHEMATICS FRAMEWORK v2.0 β
- \\β ΟΒ² + 1/ΟΒ² = 3 = TRINITY β
- \\β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
- \\β β
- \\β HIERARCHICAL COMMANDS β
- \\β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
- \\β tri math Show all math commands β
- \\β tri math constants Show all sacred constants β
- \\β tri math eval phi Compute Ο^n β
- \\β tri math eval fib Fibonacci F(n) (BigInt) β
- \\β tri math eval lucas Lucas L(n) β
- \\β tri math compute spiral Ο-spiral + ASCII plot β
- \\β tri math compute verify Verify all sacred identities β
- \\β tri math compute compare Compare Ο^n vs F(n) vs L(n) β
- \\β tri math bench Run benchmarks β
- \\β tri math identities Show all Ο-identities with proofs β
- \\β β
- \\β ALIASES (Quick Access) β
- \\β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
- \\β tri constants Same as 'tri math constants' β
- \\β tri phi Same as 'tri math eval phi ' β
- \\β tri fib Same as 'tri math eval fib ' β
- \\β tri lucas Same as 'tri math eval lucas ' β
- \\β tri spiral Same as 'tri math compute spiral ' β
- \\β tri verify Same as 'tri math compute verify' β
- \\β β
- \\β FLAGS β
- \\β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
- \\β --format=pretty|json|csv Output format β
- \\β --precision=N Decimal precision (default: 16) β
- \\β --plot Show ASCII spiral plot β
- \\β --max-n=N Comparison range (default: 20) β
- \\β β
- \\β EXAMPLES β
- \\β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
- \\β tri phi 42 Compute Οβ΄Β² β
- \\β tri fib 1000 F(1000) = 4346655... (209 digits) β
- \\β tri lucas 2 L(2) = 3 = TRINITY β
- \\β tri spiral 12 --plot Ο-spiral with ASCII plot β
- \\β tri verify Check all sacred identities β
- \\β tri math constants --json Export constants as JSON β
- \\β β
- \\ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-;
-
-// ============================================================================
-// PARSING FUNCTIONS
-// ============================================================================
-
-/// Parse a specific flag from arguments
-pub fn parseFlag(args: [][]const u8, flag_name: []const u8) ?[]const u8 {
- const flag_with_dash = "--";
- const full_flag = std.fmt.allocPrint(std.heap.page_allocator, "--{s}", .{flag_name}) catch return null;
- defer std.heap.page_allocator.free(full_flag);
-
- for (args) |arg| {
- if (std.mem.eql(u8, arg, full_flag)) {
- return "";
- }
- if (std.mem.startsWith(u8, arg, flag_with_dash)) {
- const eq_idx = std.mem.indexOfScalar(u8, arg, '=');
- if (eq_idx) |idx| {
- if (std.mem.eql(u8, arg[2..idx], flag_name)) {
- return arg[idx + 1 ..];
- }
- }
- }
- }
- return null;
-}
-
-/// Parse output format from arguments
-pub fn parseFormatFlag(args: [][]const u8) OutputFormat {
- if (parseFlag(args, "format")) |fmt| {
- if (std.mem.eql(u8, fmt, "json")) return .json;
- if (std.mem.eql(u8, fmt, "csv")) return .csv;
- }
- return .pretty;
-}
-
-// ============================================================================
-// COMMAND DISPATCHERS
-// ============================================================================
-
-/// Main math command dispatcher
-pub fn runMathCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- if (args.len == 0) {
- showMathHelp();
- return;
- }
-
- const subcommand = args[0];
- const remaining = args[1..];
-
- if (std.mem.eql(u8, subcommand, "constants")) {
- runConstantsCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "eval")) {
- runEvalCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "compute")) {
- runComputeCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "bench")) {
- runBenchCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "identities")) {
- runIdentitiesCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "help")) {
- showMathHelp();
- } else {
- std.debug.print("Unknown math subcommand: {s}\n\n", .{subcommand});
- showMathHelp();
- }
-}
-
-/// Show all sacred constants
-pub fn runConstantsCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- _ = allocator;
-
- const format = parseFormatFlag(args);
-
- if (format == .json) {
- std.debug.print("{{\n", .{});
- std.debug.print(" \"PHI\": {d:.16},\n", .{PHI});
- std.debug.print(" \"PI\": {d:.16},\n", .{PI});
- std.debug.print(" \"E\": {d:.16},\n", .{E});
- std.debug.print(" \"TRINITY_SUM\": {d:.1}\n", .{gen_constants.TRINITY_SUM});
- std.debug.print("}}\n", .{});
- } else {
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("β SACRED CONSTANTS β\n", .{});
- std.debug.print("β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
- std.debug.print("β PHI (Ο) = {d:>20.16} β\n", .{PHI});
- std.debug.print("β PI (Ο) = {d:>20.16} β\n", .{PI});
- std.debug.print("β E = {d:>20.16} β\n", .{E});
- std.debug.print("β TRINITY = {d:>20.1} (= ΟΒ² + 1/ΟΒ²) β\n", .{gen_constants.TRINITY_SUM});
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- }
-}
-
-/// Eval dispatcher (phi/fib/lucas)
-pub fn runEvalCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- if (args.len == 0) {
- std.debug.print("Usage: tri math eval [phi|fib|lucas] \n", .{});
- return;
- }
-
- const subcommand = args[0];
- const remaining = args[1..];
-
- if (std.mem.eql(u8, subcommand, "phi")) {
- runPhiCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "fib")) {
- runFibCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "lucas")) {
- runLucasCommand(allocator, remaining);
- } else {
- std.debug.print("Unknown eval subcommand: {s}\n", .{subcommand});
- }
-}
-
-/// Compute Ο^n
-pub fn runPhiCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- _ = allocator;
- if (args.len == 0) {
- std.debug.print("Usage: tri math eval phi \n", .{});
- return;
- }
-
- const n_str = args[0];
- const n = std.fmt.parseInt(usize, n_str, 10) catch {
- std.debug.print("Invalid number: {s}\n", .{n_str});
- return;
- };
-
- const result = gen_eval.phiPower(n);
- std.debug.print("Ο^{d} = {d:.16}\n", .{ n, result });
-}
-
-/// Compute Fibonacci F(n)
-pub fn runFibCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- if (args.len == 0) {
- std.debug.print("Usage: tri math eval fib \n", .{});
- return;
- }
-
- const n_str = args[0];
- const n = std.fmt.parseInt(usize, n_str, 10) catch {
- std.debug.print("Invalid number: {s}\n", .{n_str});
- return;
- };
-
- const result = gen_eval.fibonacciBigInt(allocator, n) catch |err| {
- std.debug.print("Error computing F({d}): {}\n", .{ n, err });
- return;
- };
- defer allocator.free(result.value_str);
-
- gen_eval.printEvalResult(result, .{});
-}
-
-/// Compute Lucas L(n)
-pub fn runLucasCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- if (args.len == 0) {
- std.debug.print("Usage: tri math eval lucas \n", .{});
- return;
- }
-
- const n_str = args[0];
- const n = std.fmt.parseInt(usize, n_str, 10) catch {
- std.debug.print("Invalid number: {s}\n", .{n_str});
- return;
- };
-
- const result = gen_eval.lucasBigInt(allocator, n) catch |err| {
- std.debug.print("Error computing L({d}): {}\n", .{ n, err });
- return;
- };
- defer allocator.free(result.value_str);
-
- gen_eval.printEvalResult(result, .{});
-}
-
-/// Compute dispatcher (spiral/verify/compare)
-pub fn runComputeCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- if (args.len == 0) {
- std.debug.print("Usage: tri math compute [spiral|verify|compare] [args...]\n", .{});
- return;
- }
-
- const subcommand = args[0];
- const remaining = args[1..];
-
- if (std.mem.eql(u8, subcommand, "spiral")) {
- runSpiralCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "verify")) {
- runVerifyCommand(allocator, remaining);
- } else if (std.mem.eql(u8, subcommand, "compare")) {
- runCompareCommand(allocator, remaining);
- } else {
- std.debug.print("Unknown compute subcommand: {s}\n", .{subcommand});
- showMathHelp();
- }
-}
-
-/// Show Ο-spiral coordinates
-pub fn runSpiralCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- _ = allocator;
- if (args.len == 0) {
- std.debug.print("Usage: tri math compute spiral \n", .{});
- return;
- }
-
- const n_str = args[0];
- const n = std.fmt.parseInt(usize, n_str, 10) catch {
- std.debug.print("Invalid number: {s}\n", .{n_str});
- return;
- };
-
- const plot = parseFlag(args, "plot") != null;
-
- std.debug.print("Ο-Spiral (n={d}):\n", .{n});
- std.debug.print("{s:>10} {s:>10} {s:>10}\n", .{ "x", "y", "r" });
- std.debug.print("ββββββββββββββββββββββββββββββββ\n", .{});
-
- const angle = @as(f64, @floatFromInt(n)) * PHI;
- const radius = std.math.sqrt(@as(f64, @floatFromInt(n)));
- const x = radius * @cos(angle);
- const y = radius * @sin(angle);
-
- std.debug.print("{d:>10.4} {d:>10.4} {d:>10.4}\n", .{ x, y, radius });
-
- if (plot) {
- std.debug.print("\nASCII Plot:\n", .{});
- printSpiralPlot(n);
- }
-}
-
-/// Simple ASCII spiral plot
-fn printSpiralPlot(n: usize) void {
- const size = @min(20, @as(usize, @intFromFloat(@sqrt(@as(f64, @floatFromInt(n))) * 2)) + 1);
- var i: usize = 0;
- while (i < size) : (i += 1) {
- var j: usize = 0;
- while (j < size) : (j += 1) {
- const cx = @as(i64, @intCast(i)) - @as(i64, @intCast(size / 2));
- const cy = @as(i64, @intCast(j)) - @as(i64, @intCast(size / 2));
- const dist = std.math.sqrt(@as(f64, @floatFromInt(cx * cx + cy * cy)));
- if (dist < 2) {
- std.debug.print("β", .{});
- } else if (dist < 4) {
- std.debug.print("β", .{});
- } else if (dist < 6) {
- std.debug.print("β", .{});
- } else {
- std.debug.print("Β·", .{});
- }
- }
- std.debug.print("\n", .{});
- }
-}
-
-/// Verify all sacred identities
-pub fn runVerifyCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- _ = allocator;
- _ = args;
-
- std.debug.print("Verifying Sacred Identities:\n", .{});
- std.debug.print("ββββββββββββββββββββββββββ\n", .{});
-
- // Trinity Identity
- const trinity_ok = gen_identities.TRINITY_IDENTITY.actual == 3.0;
- std.debug.print("ΟΒ² + 1/ΟΒ² = 3: {s}\n", .{if (trinity_ok) "β PASS" else "β FAIL"});
-
- // Phi Squared
- const phi_sq = PHI * PHI;
- const phi_sq_ok = @abs(phi_sq - (PHI + 1.0)) < 1e-10;
- std.debug.print("ΟΒ² = Ο + 1: {s}\n", .{if (phi_sq_ok) "β PASS" else "β FAIL"});
-
- // Phi Inverse
- const phi_inv = 1.0 / PHI;
- const phi_inv_ok = @abs(phi_inv - (PHI - 1.0)) < 1e-10;
- std.debug.print("1/Ο = Ο - 1: {s}\n", .{if (phi_inv_ok) "β PASS" else "β FAIL"});
-
- std.debug.print("\nAll identities verified!\n", .{});
-}
-
-/// Compare Ο^n vs F(n) vs L(n)
-pub fn runCompareCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- _ = allocator;
-
- const max_n = if (parseFlag(args, "max-n")) |n|
- std.fmt.parseInt(usize, n, 10) catch 20
- else
- 20;
-
- std.debug.print("Comparing Ο^n, F(n), L(n) for n=0..{d}:\n", .{max_n});
- std.debug.print("{s:>5} {s:>15} {s:>15} {s:>15}\n", .{ "n", "Ο^n", "F(n)", "L(n)" });
- std.debug.print("{s:>5} {s:>15} {s:>15} {s:>15}\n", .{ "βββββ", "βββββββββββββββ", "βββββββββββββββ", "βββββββββββββββ" });
-
- var i: usize = 0;
- while (i < @min(max_n, 20)) : (i += 1) {
- const phi_val = gen_eval.phiPower(i);
- const fib_val = if (i < gen_eval.fibonacci_cache.len) gen_eval.fibonacci_cache[i] else 0;
- const lucas_val = if (i < gen_eval.lucas_cache.len) gen_eval.lucas_cache[i] else 0;
-
- std.debug.print("{d:>5} {d:>15.6} {d:>15} {d:>15}\n", .{ i, phi_val, fib_val, lucas_val });
- }
-}
-
-/// Run performance benchmarks
-pub fn runBenchCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- _ = args;
-
- const gen_bench = @import("gen_bench.zig");
-
- std.debug.print("Running Sacred Mathematics Benchmarks...\n", .{});
-
- const config = gen_bench.BenchmarkConfig{
- .iterations_override = 10000,
- .warmup_iterations = 100,
- .log_to_nexus = false,
- };
-
- const suite = gen_bench.runAllBenchmarks(allocator, config) catch {
- std.debug.print("Benchmark failed\n", .{});
- return;
- };
- defer allocator.free(suite.results);
-
- std.debug.print("\n{s:>30} {s:>15}\n", .{ "Benchmark", "Ops/sec" });
- std.debug.print("{s:>30} {s:>15}\n", .{ "βββββββββββββββββββββββββββββ", "βββββββββββββββ" });
-
- for (suite.results) |r| {
- std.debug.print("{s:>30} {d:>15.0}\n", .{ r.name, r.ops_per_second });
- }
-}
-
-/// Show all Ο-identities with proofs
-pub fn runIdentitiesCommand(allocator: std.mem.Allocator, args: [][]const u8) void {
- _ = allocator;
- _ = args;
-
- const identities = gen_identities.ALL_IDENTITIES;
-
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("β SACRED IDENTITIES β\n", .{});
- std.debug.print("β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
-
- for (identities) |id| {
- std.debug.print("β {s}: {s}\n", .{ id.name, id.formula });
- if (id.verified) {
- std.debug.print("β β {s}\n", .{id.proof});
- }
- if (id.special_note) |note| {
- std.debug.print("β Note: {s}\n", .{note});
- }
- std.debug.print("β\n", .{});
- }
-
- std.debug.print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
-
-/// Display math command help
-pub fn showMathHelp() void {
- std.debug.print("{s}\n", .{MATH_HELP_TEXT});
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "Math CLI: MATH_HELP_TEXT not empty" {
- try std.testing.expect(@as(usize, 1000) < MATH_HELP_TEXT.len);
-}
-
-test "Math CLI: parseFormatFlag default" {
- const args3_arr = [_][]const u8{};
- try std.testing.expectEqual(.pretty, parseFormatFlag(&args3_arr));
-}
-
-test "Math CLI: parseFormatFlag json" {
- var args1 = try std.ArrayList([]const u8).initCapacity(std.testing.allocator, 1);
- defer args1.deinit(std.testing.allocator);
- try args1.append(std.testing.allocator, "--format=json");
-
- try std.testing.expectEqual(.json, parseFormatFlag(args1.items));
-}
-
-test "Math CLI: parseFlag basic" {
- var args = try std.ArrayList([]const u8).initCapacity(std.testing.allocator, 2);
- defer args.deinit(std.testing.allocator);
- try args.append(std.testing.allocator, "--format=json");
- try args.append(std.testing.allocator, "--verbose");
-
- try std.testing.expect(parseFlag(args.items, "format") != null);
- try std.testing.expect(parseFlag(args.items, "verbose") != null);
- try std.testing.expect(parseFlag(args.items, "missing") == null);
-}
diff --git a/src/math/gen_constants.zig b/src/math/gen_constants.zig
deleted file mode 100644
index 70351981e5..0000000000
--- a/src/math/gen_constants.zig
+++ /dev/null
@@ -1,374 +0,0 @@
-//! Math Constants β Generated from specs/tri/math_constants.tri
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! DO NOT EDIT: This file is generated from constants.tri spec
-//! Modify spec and regenerate: vibee gen constants
-
-const std = @import("std");
-
-// ============================================================================
-// GOLDEN RATIO CONSTANTS
-// ============================================================================
-
-/// Golden Ratio β divine proportion
-/// Ο = (1 + β5) / 2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// Phi squared
-/// ΟΒ² = Ο + 1
-pub const PHI_SQUARED: f64 = 2.6180339887498948482;
-
-/// Inverse phi squared
-/// 1/ΟΒ² = Ο - 1
-pub const PHI_INV_SQUARED: f64 = 0.3819660112501051518;
-
-/// TRINITY IDENTITY β exact equality
-/// ΟΒ² + 1/ΟΒ² = 3
-pub const TRINITY_SUM: f64 = 3.0;
-
-// ============================================================================
-// TRANSCENDENTAL CONSTANTS
-// ============================================================================
-
-/// Pi β circle constant
-/// Ο = circle circumference / diameter
-pub const PI: f64 = 3.14159265358979323846;
-
-/// Euler's number β natural log base
-/// e = lim(nββ) (1 + 1/n)βΏ
-pub const E: f64 = 2.71828182845904523536;
-
-/// Transcendental product β β TRYTE_MAX (13)
-/// Ο Γ Ο Γ e β 13.82
-pub const TRANSCENDENTAL_PRODUCT: f64 = 13.816890703380645;
-
-// ============================================================================
-// GENETIC ALGORITHM CONSTANTS
-// ============================================================================
-
-/// Mutation rate
-/// ΞΌ = 1/ΟΒ²/10
-pub const MU: f64 = 0.0382;
-
-/// Crossover rate
-/// Ο = 1/Ο/10
-pub const CHI: f64 = 0.0618;
-
-/// Selection pressure
-/// Ο = Ο
-pub const SIGMA: f64 = 1.618;
-
-/// Elitism rate
-/// Ξ΅ = 1/3
-pub const EPSILON: f64 = 0.333;
-
-// ============================================================================
-// QUANTUM CONSTANTS
-// ============================================================================
-
-/// Bell inequality violation β quantum advantage
-/// CHSH = 2β2
-pub const CHSH: f64 = 2.8284271247461903;
-
-/// Fine structure constant inverse
-/// Ξ±β»ΒΉ = 4ΟΒ³ + ΟΒ² + Ο
-pub const FINE_STRUCTURE: f64 = 137.036;
-
-/// Berry phase for quantum-inspired computation
-/// Ξ² = Ο(1 - 1/Ο)
-pub const BERRY_PHASE: f64 = 2.112;
-
-/// SU3 energy harvesting constant
-/// SU3 = 3/(2Ο)
-pub const SU3_CONSTANT: f64 = 0.927;
-
-// ============================================================================
-// DATA STRUCTURES
-// ============================================================================
-
-/// Single constant entry for display
-pub const ConstantEntry = struct {
- name: []const u8,
- symbol: []const u8,
- value: f64,
- formula: []const u8,
- description: []const u8,
- color: []const u8,
-};
-
-/// Group of related constants
-pub const ConstantGroup = struct {
- name: []const u8,
- constants: []const ConstantEntry,
-};
-
-// ============================================================================
-// BEHAVIORS / FUNCTIONS
-// ============================================================================
-
-/// Verify TRINITY IDENTITY at runtime
-/// ΟΒ² + 1/ΟΒ² = 3
-pub fn verifyTrinityIdentity() bool {
- const left = PHI_SQUARED + PHI_INV_SQUARED;
- return std.math.approxEqAbs(f64, left, TRINITY_SUM, 1e-10);
-}
-
-/// Get all sacred constants grouped by category
-pub const ALL_CONSTANT_GROUPS = blk: {
- // GOLDEN RATIO constants
- const gold_constants = [_]ConstantEntry{
- ConstantEntry{
- .name = "phi",
- .symbol = "Ο",
- .value = PHI,
- .formula = "(1 + β5) / 2",
- .description = "Golden Ratio β divine proportion",
- .color = "gold",
- },
- ConstantEntry{
- .name = "phi_squared",
- .symbol = "ΟΒ²",
- .value = PHI_SQUARED,
- .formula = "ΟΒ² = Ο + 1",
- .description = "Phi squared",
- .color = "gold",
- },
- ConstantEntry{
- .name = "phi_inv_squared",
- .symbol = "1/ΟΒ²",
- .value = PHI_INV_SQUARED,
- .formula = "1/ΟΒ² = Ο - 1",
- .description = "Inverse phi squared",
- .color = "gold",
- },
- ConstantEntry{
- .name = "trinity_sum",
- .symbol = "ΟΒ² + 1/ΟΒ²",
- .value = TRINITY_SUM,
- .formula = "ΟΒ² + 1/ΟΒ² = 3",
- .description = "TRINITY IDENTITY β exact equality",
- .color = "gold",
- },
- };
-
- // TRANSCENDENTAL constants
- const transcend_constants = [_]ConstantEntry{
- ConstantEntry{
- .name = "pi",
- .symbol = "Ο",
- .value = PI,
- .formula = "Circle circumference / diameter",
- .description = "Pi β circle constant",
- .color = "cyan",
- },
- ConstantEntry{
- .name = "e",
- .symbol = "e",
- .value = E,
- .formula = "lim(nββ) (1 + 1/n)βΏ",
- .description = "Euler's number β natural log base",
- .color = "cyan",
- },
- ConstantEntry{
- .name = "transcendental_product",
- .symbol = "Ο Γ Ο Γ e",
- .value = TRANSCENDENTAL_PRODUCT,
- .formula = "Ο Γ Ο Γ e",
- .description = "Transcendental product β β TRYTE_MAX (13)",
- .color = "purple",
- },
- };
-
- // GENETIC ALGORITHM constants
- const genetic_constants = [_]ConstantEntry{
- ConstantEntry{
- .name = "mu",
- .symbol = "ΞΌ",
- .value = MU,
- .formula = "1/ΟΒ²/10",
- .description = "Mutation rate",
- .color = "yellow",
- },
- ConstantEntry{
- .name = "chi",
- .symbol = "Ο",
- .value = CHI,
- .formula = "1/Ο/10",
- .description = "Crossover rate",
- .color = "yellow",
- },
- ConstantEntry{
- .name = "sigma",
- .symbol = "Ο",
- .value = SIGMA,
- .formula = "Ο",
- .description = "Selection pressure",
- .color = "yellow",
- },
- ConstantEntry{
- .name = "epsilon",
- .symbol = "Ξ΅",
- .value = EPSILON,
- .formula = "1/3",
- .description = "Elitism rate",
- .color = "yellow",
- },
- };
-
- // QUANTUM constants
- const quantum_constants = [_]ConstantEntry{
- ConstantEntry{
- .name = "chsh",
- .symbol = "CHSH",
- .value = CHSH,
- .formula = "2β2",
- .description = "Bell inequality violation β quantum advantage",
- .color = "purple",
- },
- ConstantEntry{
- .name = "fine_structure",
- .symbol = "Ξ±β»ΒΉ",
- .value = FINE_STRUCTURE,
- .formula = "4ΟΒ³ + ΟΒ² + Ο",
- .description = "Fine structure constant inverse",
- .color = "purple",
- },
- ConstantEntry{
- .name = "berry_phase",
- .symbol = "Ξ²",
- .value = BERRY_PHASE,
- .formula = "Ο(1 - 1/Ο)",
- .description = "Berry phase for quantum-inspired computation",
- .color = "purple",
- },
- ConstantEntry{
- .name = "su3_constant",
- .symbol = "SU3",
- .value = SU3_CONSTANT,
- .formula = "3/(2Ο)",
- .description = "SU3 energy harvesting constant",
- .color = "purple",
- },
- };
-
- break :blk [_]ConstantGroup{
- ConstantGroup{
- .name = "GOLDEN RATIO",
- .constants = &gold_constants,
- },
- ConstantGroup{
- .name = "TRANSCENDENTAL",
- .constants = &transcend_constants,
- },
- ConstantGroup{
- .name = "GENETIC ALGORITHM",
- .constants = &genetic_constants,
- },
- ConstantGroup{
- .name = "QUANTUM",
- .constants = &quantum_constants,
- },
- };
-};
-
-/// Lookup constant by name (returns null if not found)
-pub fn getConstantByName(name: []const u8) ?ConstantEntry {
- const groups = &ALL_CONSTANT_GROUPS;
- for (groups) |group| {
- for (group.constants) |entry| {
- if (std.mem.eql(u8, entry.name, name)) {
- return entry;
- }
- }
- }
- return null;
-}
-
-// ============================================================================
-// COMPILE-TIME VERIFICATION
-// ============================================================================
-
-// Verify the TRINITY IDENTITY at compile time
-comptime {
- const trinity_identity = PHI_SQUARED + PHI_INV_SQUARED;
- const diff = @abs(trinity_identity - TRINITY_SUM);
- if (diff > 1e-10) {
- @compileError("TRINITY IDENTITY VIOLATED: ΟΒ² + 1/ΟΒ² β 3");
- }
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "Math Constants - TRINITY identity" {
- try std.testing.expect(verifyTrinityIdentity());
- const left = PHI_SQUARED + PHI_INV_SQUARED;
- try std.testing.expectApproxEqAbs(TRINITY_SUM, left, 1e-10);
-}
-
-test "Math Constants - PHI relationships" {
- // ΟΒ² = Ο + 1
- try std.testing.expectApproxEqAbs(PHI_SQUARED, PHI + 1.0, 1e-10);
- // 1/ΟΒ² = 2 - Ο (since ΟΒ² = Ο + 1, so 1/ΟΒ² = 1/(Ο+1) = Ο - 1... wait)
- // Actually: 1/Ο = Ο - 1 β 0.618
- // And 1/ΟΒ² = (1/Ο)Β² β 0.382
- // So ΟΒ² + 1/ΟΒ² = 2.618 + 0.382 = 3.0 β
- try std.testing.expectApproxEqAbs(PHI_INV_SQUARED, 2.0 - PHI, 1e-10);
-}
-
-test "Math Constants - transcendental product" {
- // Ο Γ Ο Γ e β 13.82
- const product = PI * PHI * E;
- try std.testing.expectApproxEqAbs(TRANSCENDENTAL_PRODUCT, product, 0.001);
-}
-
-test "Math Constants - genetic algorithm constants" {
- try std.testing.expectApproxEqAbs(MU, 1.0 / (PHI * PHI) / 10.0, 1e-5);
- try std.testing.expectApproxEqAbs(CHI, 1.0 / PHI / 10.0, 1e-5);
- try std.testing.expectApproxEqAbs(SIGMA, PHI, 1e-3);
- try std.testing.expectApproxEqAbs(EPSILON, 1.0 / 3.0, 0.001);
-}
-
-test "Math Constants - quantum constants" {
- // CHSH = 2β2
- try std.testing.expectApproxEqAbs(CHSH, 2.0 * std.math.sqrt(2.0), 1e-10);
- // SU3 = 3/(2Ο) β 0.927
- try std.testing.expectApproxEqAbs(SU3_CONSTANT, 3.0 / (2.0 * PHI), 0.001);
- // Berry phase β verify it's in expected range (2.0 - 2.2)
- try std.testing.expect(BERRY_PHASE > 2.0 and BERRY_PHASE < 2.2);
- // Berry phase formula: Ο(1 - 1/Ο) β 1.2, but spec uses 2.112
- // Test that our constant is non-zero and positive
- try std.testing.expect(BERRY_PHASE > 0);
-}
-
-test "Math Constants - ALL_CONSTANT_GROUPS" {
- const groups = &ALL_CONSTANT_GROUPS;
- try std.testing.expectEqual(@as(usize, 4), groups.len);
-
- // Check GOLDEN RATIO group
- try std.testing.expectEqualSlices(u8, "GOLDEN RATIO", groups[0].name);
- try std.testing.expectEqual(@as(usize, 4), groups[0].constants.len);
-
- // Check TRANSCENDENTAL group
- try std.testing.expectEqualSlices(u8, "TRANSCENDENTAL", groups[1].name);
- try std.testing.expectEqual(@as(usize, 3), groups[1].constants.len);
-
- // Check GENETIC ALGORITHM group
- try std.testing.expectEqualSlices(u8, "GENETIC ALGORITHM", groups[2].name);
- try std.testing.expectEqual(@as(usize, 4), groups[2].constants.len);
-
- // Check QUANTUM group
- try std.testing.expectEqualSlices(u8, "QUANTUM", groups[3].name);
- try std.testing.expectEqual(@as(usize, 4), groups[3].constants.len);
-}
-
-test "Math Constants - getConstantByName" {
- const phi_entry = getConstantByName("phi");
- try std.testing.expect(phi_entry != null);
- try std.testing.expectEqualSlices(u8, "phi", phi_entry.?.name);
- try std.testing.expectApproxEqAbs(PHI, phi_entry.?.value, 1e-10);
-
- const unknown_entry = getConstantByName("unknown");
- try std.testing.expect(unknown_entry == null);
-}
diff --git a/src/math/gen_eval.zig b/src/math/gen_eval.zig
deleted file mode 100644
index 86bf7d5dcf..0000000000
--- a/src/math/gen_eval.zig
+++ /dev/null
@@ -1,497 +0,0 @@
-//! Math Eval β Generated from specs/tri/math/math_eval.tri
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! DO NOT EDIT: This file is generated from math_eval.tri spec
-//! phi^n, fib(n), lucas(n) evaluation
-
-const std = @import("std");
-
-// Re-export sacred constants
-const PHI = @import("gen_constants.zig").PHI;
-const TRINITY_SUM = @import("gen_constants.zig").TRINITY_SUM;
-
-// ============================================================================
-// TYPES
-// ============================================================================
-
-/// Type of mathematical sequence
-pub const SequenceType = enum(u8) {
- phi_power,
- fibonacci,
- lucas,
-};
-
-/// Result of sequence evaluation
-pub const EvalResult = struct {
- sequence: SequenceType,
- n: usize,
- value_str: []const u8,
- digit_count: usize,
- is_trinity: bool,
- is_tryte_max: bool,
- special_note: ?[]const u8,
-};
-
-/// Configuration for evaluation
-pub const EvalConfig = struct {
- precision: usize = 16,
- use_cache: bool = true,
- format: OutputFormat = .decimal,
-};
-
-/// Output format for results
-pub const OutputFormat = enum(u8) {
- decimal,
- scientific,
- mixed,
-};
-
-// ============================================================================
-// CACHE TABLES
-// ============================================================================
-
-/// Pre-computed ΟβΏ for n = 0..99
-pub const phi_powers_cache = [100]f64{
- 1.0, // Οβ°
- 1.618033988749895, // ΟΒΉ
- 2.618033988749895, // ΟΒ²
- 4.23606797749979, // ΟΒ³
- 6.854101966249685, // Οβ΄
- 11.090169943749474, // Οβ΅
- 17.94427190999916, // ΟβΆ
- 29.034441853748636, // Οβ·
- 46.978713763747806, // ΟβΈ
- 76.01315561749616, // ΟβΉ
- 122.99186938124422, // ΟΒΉβ°
- 199.0050249987404, // ΟΒΉΒΉ
- 321.9968943800, // ΟΒΉΒ²
- 521.0019193787403, // ΟΒΉΒ³
- 842.9988137674033, // ΟΒΉβ΄
- 1364.0007331458488, // ΟΒΉβ΅
- 2206.999546913252, // ΟΒΉβΆ
- 3571.000280059101, // ΟΒΉβ·
- 5777.999826972353, // ΟΒΉβΈ
- 9349.000107031454, // ΟΒΉβΉ
- 15126.999934011399, // ΟΒ²β°
- 24476.000041077506, // ΟΒ²ΒΉ
- 39602.9999750889, // ΟΒ²Β²
- 64079.0000161664, // ΟΒ²Β³
- 103682.00001233732, // ΟΒ²β΄
- 167761.00002850372, // ΟΒ²β΅
- 271443.00004084104, // ΟΒ²βΆ
- 439204.00006934477, // ΟΒ²β·
- 710647.0001101858, // ΟΒ²βΈ
- 1149851.0001795305, // ΟΒ²βΉ
- 1860498.0002897163, // ΟΒ³β°
- 3010349.0004692469, // ΟΒ³ΒΉ
- 4870847.0007589633, // ΟΒ³Β²
- 7881196.00122821, // ΟΒ³Β³
- 12752043.001987173, // ΟΒ³β΄
- 20633239.003215383, // ΟΒ³β΅
- 33385282.005202556, // ΟΒ³βΆ
- 54018521.008417938, // ΟΒ³β·
- 87403803.013620496, // ΟΒ³βΈ
- 141422324.02203843, // ΟΒ³βΉ
- 228826127.03565893, // Οβ΄β°
- 370248451.05769736, // Οβ΄ΒΉ
- 599074578.0933563, // Οβ΄Β²
- 969323029.1510537, // Οβ΄Β³
- 1568397607.24441, // Οβ΄β΄
- 2537720636.3954635, // Οβ΄β΅
- 4106116243.639874, // Οβ΄βΆ
- 6643836880.035337, // Οβ΄β·
- 10749953123.675211, // Οβ΄βΈ
- 17393790003.71055, // Οβ΄βΉ
- 28143743127.38576, // Οβ΅β°
- 45537533131.09631, // Οβ΅ΒΉ
- 73681276258.48207, // Οβ΅Β²
- 119218809389.57838, // Οβ΅Β³
- 192900085648.06046, // Οβ΅β΄
- 312118895037.63882, // Οβ΅β΅
- 505018980685.6993, // Οβ΅βΆ
- 817137875723.3381, // Οβ΅β·
- 1322156759409.0374, // Οβ΅βΈ
- 2139294635132.3755, // Οβ΅βΉ
- 3461451394541.413, // ΟβΆβ°
- 5600746029673.788, // ΟβΆΒΉ
- 9062197424215.201, // ΟβΆΒ²
- 14662943553889.0, // ΟβΆΒ³
- 23725140981206.102, // ΟβΆβ΄
- 38388084533273.3, // ΟβΆβ΅
- 62113225514479.4, // ΟβΆβΆ
- 100501310047752.7, // ΟβΆβ·
- 162614535562232.12, // ΟβΆβΈ
- 263115845609984.84, // ΟβΆβΉ
- 425730381172216.94, // Οβ·β°
- 688846226782201.8, // Οβ·ΒΉ
- 1114576607954418.8, // Οβ·Β²
- 1803422834736620.5, // Οβ·Β³
- 2917999442691039.5, // Οβ·β΄
- 4721422277427660.0, // Οβ·β΅
- 7639421720118699.0, // Οβ·βΆ
- 12360843997546359.0, // Οβ·β·
- 20000265717665056.0, // Οβ·βΈ
- 32361109715211412.0, // Οβ·βΉ
- 52361375432876472.0, // ΟβΈβ°
- 84722485148087888.0, // ΟβΈΒΉ
- 137083860580964368.0, // ΟβΈΒ²
- 221806345729052256.0, // ΟβΈΒ³
- 358890206310016640.0, // ΟβΈβ΄
- 580696552039068928.0, // ΟβΈβ΅
- 939586758349085632.0, // ΟβΈβΆ
- 1520283310388154624.0, // ΟβΈβ·
- 2459870068737240064.0, // ΟβΈβΈ
- 3980153379125393920.0, // ΟβΈβΉ
- 6440023447862633984.0, // ΟβΉβ°
- 10420176826988028032.0, // ΟβΉΒΉ
- 16860200274850662016.0, // ΟβΉΒ²
- 27280377101838690304.0, // ΟβΉΒ³
- 44140577376689353216.0, // ΟβΉβ΄
- 71420954478528043520.0, // ΟβΉβ΅
- 115561531855217393664.0, // ΟβΉβΆ
- 186982486333745437696.0, // ΟβΉβ·
- 302544018188962839552.0, // ΟβΉβΈ
- 489526504522708323840.0, // ΟβΉβΉ
-};
-
-/// F(n) for n < 94 (fits in u64)
-pub const fibonacci_cache = [94]u64{ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025, 20365011074, 32951280099, 53316291173, 86267571272, 139583862445, 225851433717, 365435296162, 591286729879, 956722026041, 1548008755920, 2504730781961, 4052739537881, 6557470319842, 10610209857723, 17167680177565, 27777890035288, 44945570212853, 72723460248141, 117669030460994, 190392490709135, 308061521170129, 498454011879264, 806515533049393, 1304969544928657, 2111485077978050, 3416454622906707, 5527939700884757, 8944394323791464, 14472334024676221, 23416728348467685, 37889062373143906, 61305790721611591, 99194853094755497, 160500643816367088, 259695496911122585, 420196140727489673, 679891637638612258, 1100087778366101931, 1779979416004714189, 2880067194370816120, 4660046610375530309, 7540113804746346429, 12200160415121876738 };
-
-/// L(n) for n < 94 (fits in u64)
-pub const lucas_cache = [94]u64{ 2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199, 322, 521, 843, 1364, 2207, 3571, 5778, 9349, 15127, 24476, 39603, 64079, 103682, 167761, 271443, 439204, 710647, 1149851, 1860498, 3010349, 4870847, 7881196, 12752043, 20633239, 33385282, 54018521, 87403803, 141422324, 228826127, 370248451, 599074578, 969323029, 1568397607, 2537720636, 4106116243, 6643836879, 10749953122, 17393790001, 28143743123, 45537533124, 73681276247, 119218809371, 192900165618, 312119054989, 505019220607, 817138275596, 1322157506203, 2139295781799, 3461453288002, 5600749069801, 9062202357803, 14662951427584, 23725153785387, 38388105212971, 62113258998358, 100501364211329, 162614623209687, 263115987421016, 425730610630703, 6888465093728719, 111457761359422, 180342412896671, 291800174256093, 472142587152764, 763942761408857, 1236085348561621, 2000028109970478, 3236113458532099, 5236141568502577, 8472255027034676, 13708396595537253, 22180651622567229, 35889048218139782, 58069699840707011, 93958748058846793, 152028447999553804, 245987228054385597, 398015713049924401, 644002941104309998, 1042018654154234399, 1686021595258544397, 2728040249412778796 };
-
-// ============================================================================
-// SEQUENCE FUNCTIONS
-// ============================================================================
-
-/// Compute Ο^n using cache for small n
-pub fn phiPower(n: usize) f64 {
- if (n < phi_powers_cache.len) {
- return phi_powers_cache[n];
- }
- return std.math.pow(f64, PHI, @as(f64, @floatFromInt(n)));
-}
-
-/// Compute F(n) - Fibonacci number
-pub fn fibonacciBigInt(allocator: std.mem.Allocator, n: usize) !EvalResult {
- var value: u64 = 0;
-
- if (n < fibonacci_cache.len) {
- value = fibonacci_cache[n];
- } else {
- // Fast doubling algorithm (clamped for safety)
- value = fibonacciFastDoubing(n);
- }
-
- var buf: [64]u8 = undefined;
- const value_str = std.fmt.bufPrint(&buf, "{d}", .{value}) catch "N/A";
- const digit_count = countDigits(value);
-
- return EvalResult{
- .sequence = .fibonacci,
- .n = n,
- .value_str = try allocator.dupe(u8, value_str),
- .digit_count = digit_count,
- .is_trinity = (n == 4), // F(4) = 3 = TRINITY
- .is_tryte_max = (n == 7), // F(7) = 13 = TRYTE_MAX
- .special_note = null,
- };
-}
-
-/// Fast doubling algorithm for Fibonacci (clamped)
-fn fibonacciFastDoubing(n: usize) u64 {
- if (n == 0) return 0;
- if (n == 1) return 1;
- if (n > 90) return 2_880_067_194_370_816_120; // F(90), clamped
-
- var a: u64 = 0;
- var b: u64 = 1;
-
- var i: usize = 2;
- while (i <= n) : (i += 1) {
- const next = a + b;
- if (next < a) return b; // Overflow
- a = b;
- b = next;
- }
-
- return b;
-}
-
-/// Compute L(n) - Lucas number
-pub fn lucasBigInt(allocator: std.mem.Allocator, n: usize) !EvalResult {
- var value: u64 = 0;
-
- if (n < lucas_cache.len) {
- value = lucas_cache[n];
- } else {
- value = lucasFastDoubing(n);
- }
-
- var buf: [64]u8 = undefined;
- const value_str = std.fmt.bufPrint(&buf, "{d}", .{value}) catch "N/A";
- const digit_count = countDigits(value);
-
- return EvalResult{
- .sequence = .lucas,
- .n = n,
- .value_str = try allocator.dupe(u8, value_str),
- .digit_count = digit_count,
- .is_trinity = (n == 2), // L(2) = 3 = TRINITY
- .is_tryte_max = false,
- .special_note = if (n <= 10) "L(n) = ΟβΏ + 1/ΟβΏ" else null,
- };
-}
-
-/// Fast doubling for Lucas (clamped)
-fn lucasFastDoubing(n: usize) u64 {
- if (n == 0) return 2;
- if (n == 1) return 1;
- if (n > 90) return 3_788_906_237_314_390_60; // L(90), clamped
-
- var a: u64 = 2;
- var b: u64 = 1;
-
- var i: usize = 2;
- while (i <= n) : (i += 1) {
- const next = a + b;
- if (next < a) return b; // Overflow
- a = b;
- b = next;
- }
-
- return b;
-}
-
-/// Print evaluation result with formatting
-pub fn printEvalResult(result: EvalResult, config: EvalConfig) void {
- _ = config;
- const seq_name = switch (result.sequence) {
- .phi_power => "Ο",
- .fibonacci => "F",
- .lucas => "L",
- };
-
- std.debug.print("{s}({d}) = {s}", .{ seq_name, result.n, result.value_str });
-
- if (result.digit_count > 0) {
- std.debug.print(" [{d} digits]", .{result.digit_count});
- }
-
- if (result.is_trinity) {
- std.debug.print(" = TRINITY (3)", .{});
- }
-
- if (result.is_tryte_max) {
- std.debug.print(" = TRYTE_MAX (13)", .{});
- }
-
- if (result.special_note) |note| {
- std.debug.print(" [{s}]", .{note});
- }
-
- std.debug.print("\n", .{});
-}
-
-/// Format number with digit grouping (commas every 3 digits)
-pub fn formatBigInt(allocator: std.mem.Allocator, value: anytype, use_cache: bool) ![]const u8 {
- _ = value;
- _ = use_cache;
- _ = allocator;
- return error.NotImplemented;
-}
-
-/// Count digits in a number
-pub fn countDigits(value: u64) usize {
- if (value == 0) return 1;
- var count: usize = 0;
- var n = value;
- while (n > 0) {
- n /= 10;
- count += 1;
- }
- return count;
-}
-
-/// Format number with commas
-fn formatNumber(allocator: std.mem.Allocator, value: u64, use_cache: bool) ![]const u8 {
- _ = use_cache;
- var buf: [64]u8 = undefined;
-
- const int_part = std.fmt.bufPrint(&buf, "{d}", .{value}) catch "0";
-
- // Add commas every 3 digits
- const len = int_part.len;
- var result: [128]u8 = undefined;
- var result_idx: usize = 0;
- var digits_seen: usize = 0;
-
- var i: usize = len;
- while (i > 0) : (i -= 1) {
- if (digits_seen > 0 and digits_seen % 3 == 0 and i > 0) {
- result[result_idx] = ',';
- result_idx += 1;
- }
- result[result_idx] = int_part[i - 1];
- result_idx += 1;
- digits_seen += 1;
- }
-
- const formatted = result[0..result_idx];
- return allocator.dupe(u8, formatted);
-}
-
-/// Check if value equals 3 (TRINITY)
-pub fn verifyTrinityValue(value: anytype) bool {
- if (@typeInfo(@TypeOf(value)) == .int) {
- return @as(u64, value) == 3;
- }
- if (@typeInfo(@TypeOf(value)) == .float) {
- return @abs(@as(f64, value) - 3.0) < 1e-10;
- }
- return false;
-}
-
-/// Check if value equals 13 (TRYTE_MAX)
-pub fn verifyTryteMax(value: anytype) bool {
- if (@typeInfo(@TypeOf(value)) == .int) {
- return @as(u64, value) == 13;
- }
- if (@typeInfo(@TypeOf(value)) == .float) {
- return @abs(@as(f64, value) - 13.0) < 1e-10;
- }
- return false;
-}
-
-/// Get metadata about sequence value
-pub fn getSequenceInfo(allocator: std.mem.Allocator, seq_type: SequenceType, n: usize) !EvalResult {
- return switch (seq_type) {
- .phi_power => {
- const val = phiPower(n);
- var buf: [64]u8 = undefined;
- const str = std.fmt.bufPrint(&buf, "{d:.16}", .{val}) catch "N/A";
- return EvalResult{
- .sequence = .phi_power,
- .n = n,
- .value_str = try allocator.dupe(u8, str),
- .digit_count = 0,
- .is_trinity = false,
- .is_tryte_max = false,
- .special_note = null,
- };
- },
- .fibonacci => try fibonacciBigInt(allocator, n),
- .lucas => try lucasBigInt(allocator, n),
- };
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "Math Eval: phiPower basic" {
- try std.testing.expectApproxEqAbs(@as(f64, 1.0), phiPower(0), 1e-10);
- try std.testing.expectApproxEqAbs(PHI, phiPower(1), 1e-10);
- try std.testing.expectApproxEqAbs(2.618033988749895, phiPower(2), 1e-10);
-}
-
-test "Math Eval: phiPower cache" {
- for (0..20) |i| {
- const cached = phi_powers_cache[i];
- const computed = std.math.pow(f64, PHI, @as(f64, @floatFromInt(i)));
- try std.testing.expectApproxEqAbs(cached, computed, 1e-7);
- }
-}
-
-test "Math Eval: fibonacci small" {
- try std.testing.expectEqual(@as(u64, 0), fibonacci_cache[0]);
- try std.testing.expectEqual(@as(u64, 1), fibonacci_cache[1]);
- try std.testing.expectEqual(@as(u64, 1), fibonacci_cache[2]);
- try std.testing.expectEqual(@as(u64, 2), fibonacci_cache[3]);
- try std.testing.expectEqual(@as(u64, 3), fibonacci_cache[4]);
-}
-
-test "Math Eval: lucas small" {
- try std.testing.expectEqual(@as(u64, 2), lucas_cache[0]);
- try std.testing.expectEqual(@as(u64, 1), lucas_cache[1]);
- try std.testing.expectEqual(@as(u64, 3), lucas_cache[2]);
- try std.testing.expectEqual(@as(u64, 4), lucas_cache[3]);
-}
-
-test "Math Eval: fibonacciBigInt F(4) = TRINITY" {
- const allocator = std.testing.allocator;
- const result = try fibonacciBigInt(allocator, 4);
- defer allocator.free(result.value_str);
- try std.testing.expect(result.is_trinity);
-}
-
-test "Math Eval: lucasBigInt L(2) = TRINITY" {
- const allocator = std.testing.allocator;
- const result = try lucasBigInt(allocator, 2);
- defer allocator.free(result.value_str);
- try std.testing.expect(result.is_trinity);
-}
-
-test "Math Eval: fibonacciBigInt F(7) = TRYTE_MAX" {
- const allocator = std.testing.allocator;
- const result = try fibonacciBigInt(allocator, 7);
- defer allocator.free(result.value_str);
- try std.testing.expect(result.is_tryte_max);
-}
-
-test "Math Eval: verifyTrinityValue" {
- try std.testing.expect(verifyTrinityValue(@as(u64, 3)));
- try std.testing.expect(verifyTrinityValue(@as(f64, 3.0)));
- try std.testing.expect(!verifyTrinityValue(4));
-}
-
-test "Math Eval: verifyTryteMax" {
- try std.testing.expect(verifyTryteMax(@as(u64, 13)));
- try std.testing.expect(verifyTryteMax(@as(f64, 13.0)));
- try std.testing.expect(!verifyTryteMax(14));
-}
-
-test "Math Eval: countDigits" {
- try std.testing.expectEqual(@as(usize, 1), countDigits(0));
- try std.testing.expectEqual(@as(usize, 1), countDigits(5));
- try std.testing.expectEqual(@as(usize, 2), countDigits(42));
- try std.testing.expectEqual(@as(usize, 3), countDigits(100));
- try std.testing.expectEqual(@as(usize, 4), countDigits(9999));
-}
-
-test "Math Eval: phi_powers_cache size" {
- try std.testing.expectEqual(@as(usize, 100), phi_powers_cache.len);
-}
-
-test "Math Eval: fibonacci_cache size" {
- try std.testing.expectEqual(@as(usize, 94), fibonacci_cache.len);
-}
-
-test "Math Eval: lucas_cache size" {
- try std.testing.expectEqual(@as(usize, 94), lucas_cache.len);
-}
-
-test "Math Eval: getSequenceInfo phi_power" {
- const allocator = std.testing.allocator;
- const result = try getSequenceInfo(allocator, .phi_power, 10);
- defer allocator.free(result.value_str);
- try std.testing.expectEqual(.phi_power, result.sequence);
- try std.testing.expectEqual(@as(usize, 10), result.n);
-}
-
-test "Math Eval: getSequenceInfo fibonacci" {
- const allocator = std.testing.allocator;
- const result = try getSequenceInfo(allocator, .fibonacci, 10);
- defer allocator.free(result.value_str);
- try std.testing.expectEqual(.fibonacci, result.sequence);
- try std.testing.expectEqual(@as(usize, 10), result.n);
- try std.testing.expect(result.is_tryte_max == false);
-}
-
-test "Math Eval: getSequenceInfo lucas" {
- const allocator = std.testing.allocator;
- const result = try getSequenceInfo(allocator, .lucas, 10);
- defer allocator.free(result.value_str);
- try std.testing.expectEqual(.lucas, result.sequence);
- try std.testing.expectEqual(@as(usize, 10), result.n);
-}
diff --git a/src/math/gen_format.zig b/src/math/gen_format.zig
deleted file mode 100644
index 6a2d5c1b63..0000000000
--- a/src/math/gen_format.zig
+++ /dev/null
@@ -1,394 +0,0 @@
-//! Math Format β Generated from specs/tri/math_format.tri
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! DO NOT EDIT: This file is generated from format.tri spec
-//! Modify spec and regenerate: vibee gen format
-
-const std = @import("std");
-
-// ============================================================================
-// COLOR STYLES
-// ============================================================================
-
-/// ANSI color codes for terminal output
-pub const ColorStyle = struct {
- /// Reset all styles
- pub const RESET: []const u8 = "\x1b[0m";
-
- /// Gold color β for Golden ratio values, TRINITY
- pub const GOLD: []const u8 = "\x1b[38;5;220m";
-
- /// Cyan color β for Transcendental numbers (Ο, e)
- pub const CYAN: []const u8 = "\x1b[36m";
-
- /// Purple color β for Quantum constants, sacred identities
- pub const PURPLE: []const u8 = "\x1b[38;5;141m";
-
- /// Green color β for Success, verification passed
- pub const GREEN: []const u8 = "\x1b[32m";
-
- /// Red color β for Errors, verification failed
- pub const RED: []const u8 = "\x1b[31m";
-
- /// Yellow color β for Warnings, benchmarks
- pub const YELLOW: []const u8 = "\x1b[33m";
-};
-
-// ============================================================================
-// OUTPUT FORMAT
-// ============================================================================
-
-/// Output format options
-pub const OutputFormat = enum(u8) {
- pretty = 0,
- json = 1,
- csv = 2,
-};
-
-/// Text alignment
-pub const Alignment = enum(u8) {
- left = 0,
- center = 1,
- right = 2,
-};
-
-// ============================================================================
-// DATA STRUCTURES
-// ============================================================================
-
-/// Configuration for output formatting
-pub const FormatConfig = struct {
- format: OutputFormat = .pretty,
- precision: usize = 16,
- use_colors: bool = true,
- show_plot: bool = false,
-};
-
-/// Table column definition
-pub const TableColumn = struct {
- header: []const u8,
- width: usize,
- alignment: Alignment,
-};
-
-/// Table formatting configuration
-pub const TableFormat = struct {
- columns: []const TableColumn,
- padding: usize = 2,
- show_borders: bool = true,
-};
-
-// ============================================================================
-// BEHAVIORS / FUNCTIONS
-// ============================================================================
-
-/// Print text with specified color
-pub fn printColored(color: []const u8, text: []const u8) void {
- std.debug.print("{s}{s}{s}", .{ color, text, ColorStyle.RESET });
-}
-
-/// Format float with precision (simplified - uses default Zig float formatting)
-pub fn formatFloat(allocator: std.mem.Allocator, value: f64, precision: usize) ![]u8 {
- _ = precision;
-
- // For Zig 0.15, use bufPrint for float formatting
- var buf: [64]u8 = undefined;
- const formatted = std.fmt.bufPrint(&buf, "{d}", .{value}) catch return error.FormatFailed;
-
- // Copy to allocated buffer
- const result = try allocator.alloc(u8, formatted.len);
- @memcpy(result, formatted);
-
- return result;
-}
-
-/// Format integer with digit grouping (commas every 3 digits)
-pub fn formatIntGrouped(allocator: std.mem.Allocator, value: i64) ![]u8 {
- // Handle zero case
- if (value == 0) {
- return allocator.dupe(u8, "0");
- }
-
- // Handle negative numbers
- const is_negative = value < 0;
- const abs_value: u64 = if (is_negative) @intCast(-value) else @intCast(value);
-
- // Count digits
- var temp: u64 = abs_value;
- var num_digits: usize = 0;
- while (temp > 0) {
- temp /= 10;
- num_digits += 1;
- }
-
- // Calculate commas needed
- const num_commas = if (num_digits > 3) (num_digits - 1) / 3 else 0;
-
- // Total length including optional minus sign
- const total_len = num_digits + num_commas + @as(usize, @intFromBool(is_negative));
-
- var buffer = try allocator.alloc(u8, total_len);
- var write_pos: usize = total_len;
-
- // Build string from right to left
- temp = abs_value;
- var digit_idx: usize = 0;
-
- while (temp > 0) {
- // Insert comma every 3 digits (but not at the start)
- if (digit_idx > 0 and digit_idx % 3 == 0) {
- write_pos -= 1;
- buffer[write_pos] = ',';
- }
-
- const digit = @as(u8, @intCast(temp % 10)) + '0';
- write_pos -= 1;
- buffer[write_pos] = digit;
- temp /= 10;
- digit_idx += 1;
- }
-
- // Add minus sign if needed
- if (is_negative) {
- buffer[0] = '-';
- }
-
- return buffer;
-}
-
-/// Print table header
-pub fn printTableHeader(columns: []const TableColumn, padding: usize) void {
- // Print top border
- printTableBorder(columns, padding, "β", "β¦", "β");
-
- // Print header row
- for (columns, 0..) |col, i| {
- const pad = " " ** padding;
- const sep = if (i < columns.len - 1) "β" else "β";
- std.debug.print("{s}{s}{s}{s}", .{ pad, col.header, pad, sep });
- }
- std.debug.print("\n", .{});
-
- // Print header separator
- printTableBorder(columns, padding, "β ", "β¬", "β£");
-}
-
-/// Print table row
-pub fn printTableRow(columns: []const TableColumn, values: []const []const u8, padding: usize) void {
- for (columns, values, 0..) |col, val, i| {
- _ = col;
- const pad = " " ** padding;
- const sep = if (i < columns.len - 1) "β" else "β";
- std.debug.print("{s}{s}{s}{s}", .{ pad, val, pad, sep });
- }
- std.debug.print("\n", .{});
-}
-
-/// Print table footer
-pub fn printTableFooter(columns: []const TableColumn, padding: usize) void {
- printTableBorder(columns, padding, "β", "β©", "β");
-}
-
-/// Print table border
-fn printTableBorder(columns: []const TableColumn, padding: usize, left: []const u8, mid: []const u8, right: []const u8) void {
- std.debug.print("{s}", .{left});
- for (columns, 0..) |col, i| {
- const width = col.width + (padding * 2);
- const sep = if (i < columns.len - 1) mid else right;
- const line = "β" ** width;
- std.debug.print("{s}{s}", .{ line, sep });
- }
- std.debug.print("\n", .{});
-}
-
-/// Export data as CSV string
-pub fn exportCsv(
- allocator: std.mem.Allocator,
- headers: []const []const u8,
- rows: []const []const []const u8,
-) ![]u8 {
- // Calculate needed length (approximate)
- var total_len: usize = 0;
- for (headers) |h| total_len += h.len + 3; // quotes + comma
- total_len += 1; // newline
- for (rows) |row| {
- for (row) |cell| total_len += cell.len + 3;
- total_len += 1;
- }
-
- var buffer = try allocator.alloc(u8, total_len);
- var pos: usize = 0;
-
- // Write header row
- for (headers, 0..) |h, i| {
- if (i > 0) {
- buffer[pos] = ',';
- pos += 1;
- }
- buffer[pos] = '"';
- pos += 1;
- @memcpy(buffer[pos..][0..h.len], h);
- pos += h.len;
- buffer[pos] = '"';
- pos += 1;
- }
- buffer[pos] = '\n';
- pos += 1;
-
- // Write data rows
- for (rows) |row| {
- for (row, 0..) |cell, i| {
- if (i > 0) {
- buffer[pos] = ',';
- pos += 1;
- }
- buffer[pos] = '"';
- pos += 1;
- @memcpy(buffer[pos..][0..cell.len], cell);
- pos += cell.len;
- buffer[pos] = '"';
- pos += 1;
- }
- buffer[pos] = '\n';
- pos += 1;
- }
-
- return buffer[0..pos];
-}
-
-/// Pad string to specified width with alignment
-pub fn padString(allocator: std.mem.Allocator, s: []const u8, width: usize, alignment: Alignment) ![]u8 {
- const len = s.len;
- if (len >= width) {
- return allocator.dupe(u8, s[0..width]);
- }
-
- const padding = width - len;
- const result = try allocator.alloc(u8, width);
-
- switch (alignment) {
- .left => {
- @memcpy(result[0..len], s);
- @memset(result[len..], ' ');
- },
- .right => {
- @memset(result[0..padding], ' ');
- @memcpy(result[padding..], s);
- },
- .center => {
- const left_pad = padding / 2;
- @memset(result[0..left_pad], ' ');
- @memcpy(result[left_pad..][0..len], s);
- @memset(result[left_pad + len ..], ' ');
- },
- }
-
- return result;
-}
-
-// ============================================================================
-// TABLE TEMPLATES
-// ============================================================================
-
-/// Constants table template
-pub const CONSTANTS_TABLE_COLUMNS = [_]TableColumn{
- TableColumn{ .header = "Constant", .width = 20, .alignment = .left },
- TableColumn{ .header = "Symbol", .width = 12, .alignment = .center },
- TableColumn{ .header = "Value", .width = 24, .alignment = .right },
- TableColumn{ .header = "Description", .width = 35, .alignment = .left },
-};
-
-/// Compare table template
-pub const COMPARE_TABLE_COLUMNS = [_]TableColumn{
- TableColumn{ .header = "n", .width = 6, .alignment = .right },
- TableColumn{ .header = "ΟβΏ", .width = 20, .alignment = .right },
- TableColumn{ .header = "F(n)", .width = 25, .alignment = .right },
- TableColumn{ .header = "L(n)", .width = 25, .alignment = .right },
-};
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "Format: printColored" {
- // Just verify it compiles and doesn't crash
- printColored(ColorStyle.GOLD, "test");
- printColored(ColorStyle.CYAN, "test");
- printColored(ColorStyle.PURPLE, "test");
- printColored(ColorStyle.GREEN, "test");
- printColored(ColorStyle.RED, "test");
- printColored(ColorStyle.YELLOW, "test");
-}
-
-test "Format: formatFloat" {
- const allocator = std.testing.allocator;
-
- // formatFloat returns default Zig float formatting
- const result1 = try formatFloat(allocator, 3.14159, 2);
- defer allocator.free(result1);
- // Check that it contains "3.14" somewhere (formatting may vary)
- try std.testing.expect(std.mem.indexOf(u8, result1, "3.14") != null);
-
- const result2 = try formatFloat(allocator, 1.618, 6);
- defer allocator.free(result2);
- try std.testing.expect(std.mem.indexOf(u8, result2, "1.618") != null);
-}
-
-test "Format: formatIntGrouped" {
- const allocator = std.testing.allocator;
-
- const result1 = try formatIntGrouped(allocator, 1000);
- defer allocator.free(result1);
- try std.testing.expectEqualStrings("1,000", result1);
-
- const result2 = try formatIntGrouped(allocator, 1234567);
- defer allocator.free(result2);
- try std.testing.expectEqualStrings("1,234,567", result2);
-
- const result3 = try formatIntGrouped(allocator, -999);
- defer allocator.free(result3);
- try std.testing.expectEqualStrings("-999", result3);
-}
-
-test "Format: exportCsv" {
- const allocator = std.testing.allocator;
-
- const headers = [_][]const u8{ "Name", "Value" };
- const rows = [_][]const []const u8{
- &[_][]const u8{ "Phi", "1.618" },
- &[_][]const u8{ "Pi", "3.141" },
- };
-
- const result = try exportCsv(allocator, &headers, &rows);
- defer allocator.free(result);
-
- try std.testing.expectEqualStrings("\"Name\",\"Value\"\n\"Phi\",\"1.618\"\n\"Pi\",\"3.141\"\n", result);
-}
-
-test "Format: padString" {
- const allocator = std.testing.allocator;
-
- const result1 = try padString(allocator, "test", 10, .left);
- defer allocator.free(result1);
- try std.testing.expectEqualStrings("test ", result1);
-
- const result2 = try padString(allocator, "test", 10, .right);
- defer allocator.free(result2);
- try std.testing.expectEqualStrings(" test", result2);
-
- const result3 = try padString(allocator, "test", 10, .center);
- defer allocator.free(result3);
- try std.testing.expectEqualStrings(" test ", result3);
-}
-
-test "Format: CONSTANTS_TABLE_COLUMNS" {
- try std.testing.expectEqual(@as(usize, 4), CONSTANTS_TABLE_COLUMNS.len);
- try std.testing.expectEqualStrings("Constant", CONSTANTS_TABLE_COLUMNS[0].header);
- try std.testing.expectEqual(@as(usize, 20), CONSTANTS_TABLE_COLUMNS[0].width);
-}
-
-test "Format: COMPARE_TABLE_COLUMNS" {
- try std.testing.expectEqual(@as(usize, 4), COMPARE_TABLE_COLUMNS.len);
- try std.testing.expectEqualStrings("n", COMPARE_TABLE_COLUMNS[0].header);
- try std.testing.expectEqual(.right, COMPARE_TABLE_COLUMNS[0].alignment);
-}
diff --git a/src/math/gen_identities.zig b/src/math/gen_identities.zig
deleted file mode 100644
index f63546851f..0000000000
--- a/src/math/gen_identities.zig
+++ /dev/null
@@ -1,235 +0,0 @@
-//! Math Identities β Generated from specs/tri/math_identities.tri
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! DO NOT EDIT: This file is generated from identities.tri spec
-//! Core sacred identities with proofs
-
-const std = @import("std");
-
-// ============================================================================
-// CONSTANTS
-// ============================================================================
-
-/// Golden Ratio β Ο = (1 + β5) / 2
-pub const PHI: f64 = 1.618033988749895;
-
-/// Pi β circle constant
-pub const PI: f64 = 3.141592653589793;
-
-/// Euler's number
-pub const E: f64 = 2.718281828459045;
-
-/// Square root of 5
-pub const SQRT5: f64 = 2.2360679774979;
-
-// ============================================================================
-// TYPES
-// ============================================================================
-
-/// Category of mathematical identity
-pub const IdentityCategory = enum(u8) {
- golden_ratio,
- sequences,
- transcendental,
- quantum,
- trinity,
- ternary,
-};
-
-/// Mathematical identity with proof
-pub const Identity = struct {
- name: []const u8,
- formula: []const u8,
- latex: []const u8,
- category: IdentityCategory,
- proof: []const u8,
- verified: bool,
- tolerance: ?f64,
- special_note: ?[]const u8,
- actual: f64 = 0.0,
-};
-
-/// Result of identity verification
-pub const VerificationResult = struct {
- identity: Identity,
- expected: f64,
- actual: f64,
- diff: f64,
- passed: bool,
-};
-
-// ============================================================================
-// ALL IDENTITIES (6 sacred identities)
-// ============================================================================
-
-/// Trinity Identity
-pub const TRINITY_IDENTITY = Identity{
- .name = "Trinity Identity",
- .formula = "ΟΒ² + 1/ΟΒ² = 3",
- .latex = "\\phi^2 + \\phi^{-2} = 3",
- .category = .trinity,
- .proof = "Given ΟΒ² = Ο + 1: 1/ΟΒ² = 3\nDivide by ΟΒ²: Ο/Ο = 1 β Ο\nTherefore: ΟΒ² + 1/ΟΒ² = 3",
- .verified = true,
- .tolerance = 0.0,
- .special_note = null,
- .actual = 3.0,
-};
-
-/// Phi Squared
-pub const PHI_SQUARED_IDENTITY = Identity{
- .name = "Phi Squared",
- .formula = "ΟΒ² = Ο + 1",
- .latex = "\\phi^2 = \\phi + 1",
- .category = .golden_ratio,
- .proof = "From ΟΒ² = Ο + 1, we have ΟΒ² = Ο + 1\nTherefore: ΟΒ² = Ο + 1",
- .verified = true,
- .tolerance = 0.0,
- .special_note = null,
- .actual = PHI * PHI,
-};
-
-/// Phi Inverse
-pub const PHI_INVERSE_IDENTITY = Identity{
- .name = "Phi Inverse",
- .formula = "1/Ο = Ο - 1",
- .latex = "\\phi^{-1} = \\phi - 1",
- .category = .golden_ratio,
- .proof = "From 1/Ο = Ο - 1, multiply both sides by Ο:\n1/Ο = Ο - 1 β ΟΒ² - Ο = Ο + 1 - ΟΒ² - 1 = ΟΒ² - Ο - 1 = Ο\nSimplify: ΟΒ² - 1 - Ο = Ο - 1 = (Ο - 1)(Ο - 1) = 1/ΟΒ² - 1\nSubtract ΟΒ² from both: ΟΒ² - 1 - (ΟΒ² - 1) - (Ο - 1) = ΟΒ² - 1\nDivide by (ΟΒ² - 1): ΟΒ² - 1 / (ΟΒ² - 1) = 1 / (ΟΒ² - 1) = 1\nTherefore: ΟΒ² - 1 / ΟΒ² - 1 = 1 / ΟΒ² - 1 = 0.382",
- .verified = true,
- .tolerance = 0.001,
- .special_note = "Using binet's formula for derivation",
- .actual = 1.0 / PHI,
-};
-
-/// Phi Reciprocal
-pub const PHI_RECIPROCAL_IDENTITY = Identity{
- .name = "Phi Reciprocal",
- .formula = "1/Ο = Ο - 1",
- .latex = "\\phi^{-1} = \\phi - 1",
- .category = .golden_ratio,
- .proof = "From 1/Ο = Ο - 1, multiply both sides by Ο:\n1/Ο = Ο - 1 β Ο\nTherefore: ΟΒ² - 1 = Ο Γ (1/Ο) / (1/Ο)Β² = 1\nThis equals ΟΒ² + 1/ΟΒ² / ΟΒ² = 1 + 2(1/Ο) / (1/Ο)Β² = 1 = ΟΒ² + 1 / ΟΒ² - 1",
- .verified = true,
- .tolerance = 0.001,
- .special_note = "Using series formula, binet derivation with Ο = 1 - 1/Ο",
- .actual = 1.0 / PHI,
-};
-
-/// Lucas Phi Powers
-pub const LUCAS_PHI_POWERS_IDENTITY = Identity{
- .name = "Lucas Phi Powers",
- .formula = "L(n) = ΟβΏ + 1/ΟβΏ",
- .latex = "L(n) = \\phi^n + \\phi^{-n}",
- .category = .sequences,
- .proof = "Binet's formula for Lucas numbers: L(n) = ΟβΏ + ΟβΏ where Ο = 1 - Ο",
- .verified = true,
- .tolerance = 0.0,
- .special_note = "L(0) = 2, L(1) = 3 = TRINITY",
- .actual = 3.0,
-};
-
-/// Tryte Max Approximation
-pub const TRYTE_MAX_IDENTITY = Identity{
- .name = "Tryte Max Approximation",
- .formula = "Ο Γ Ο Γ e",
- .latex = "\\pi \\times \\phi \\times e",
- .category = .transcendental,
- .proof = "Approximately equals TRYTE_MAX (13)\nΟ Γ Ο Γ e β 13.82\nError β 6.3%",
- .verified = true,
- .tolerance = 0.05,
- .special_note = "Ο β 3.14159265, Ο β 1.618034, e β 2.71828",
- .actual = PI * PHI * E,
-};
-
-/// Berry Phase
-pub const BERRY_PHASE_IDENTITY = Identity{
- .name = "Berry Phase",
- .formula = "Ξ² = Ο(1 - 1/Ο)",
- .latex = "\\beta = \\pi(1 - \\phi^{-1})",
- .category = .quantum,
- .proof = "Quantum-inspired computation for Berry phase",
- .verified = true,
- .tolerance = 0.199,
- .special_note = "Ξ² β 1.199 radians in degrees",
- .actual = PI * (1.0 - 1.0 / PHI),
-};
-
-/// SU3 Constant
-pub const SU3_CONSTANT_IDENTITY = Identity{
- .name = "SU3 Constant",
- .formula = "3/(2Ο)",
- .latex = "SU3 = \\frac{3}{2\\phi}",
- .category = .quantum,
- .proof = "Energy harvesting constant from SU(3) group theory",
- .verified = true,
- .tolerance = 0.0,
- .special_note = "SU3 β 0.927",
- .actual = 3.0 / (2.0 * PHI),
-};
-
-/// Array of all identities
-pub const ALL_IDENTITIES = [_]Identity{
- TRINITY_IDENTITY,
- PHI_SQUARED_IDENTITY,
- PHI_INVERSE_IDENTITY,
- PHI_RECIPROCAL_IDENTITY,
- LUCAS_PHI_POWERS_IDENTITY,
- TRYTE_MAX_IDENTITY,
- BERRY_PHASE_IDENTITY,
- SU3_CONSTANT_IDENTITY,
-};
-
-/// Get all identities
-pub fn getAllIdentities() []const Identity {
- return &ALL_IDENTITIES;
-}
-
-// ============================================================================
-// COMPILE-TIME VERIFICATION
-// ============================================================================
-
-// Verify Trinity Identity at compile time
-comptime {
- const phi_sq = PHI * PHI;
- const phi_inv_sq = 1.0 / (PHI * PHI);
- const trinity_sum = phi_sq + phi_inv_sq;
- const diff = @abs(trinity_sum - 3.0);
- if (diff > 1e-10) {
- @compileError("TRINITY IDENTITY VIOLATED: ΟΒ² + 1/ΟΒ² β 3");
- }
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "Math Identities: compile-time Trinity Identity" {
- const phi_sq = PHI * PHI;
- const phi_inv_sq = 1.0 / (PHI * PHI);
- try std.testing.expectApproxEqAbs(@as(f64, 3.0), phi_sq + phi_inv_sq, 1e-10);
-}
-
-test "Math Identities: getAllIdentities count" {
- const identities = getAllIdentities();
- try std.testing.expectEqual(@as(usize, 8), identities.len);
-}
-
-test "Math Identities: verify Trinity Identity" {
- const expected = PHI * PHI + 1.0 / (PHI * PHI);
- const actual = expected;
- try std.testing.expectApproxEqAbs(expected, actual, 1e-10);
-}
-
-test "Math Identities: verify Phi Squared" {
- const expected = PHI + 1.0;
- try std.testing.expectApproxEqAbs(expected, PHI_SQUARED_IDENTITY.actual, 1e-10);
-}
-
-test "Math Identities: Tryte Max Approximation" {
- const expected = PI * PHI * E;
- try std.testing.expectApproxEqAbs(expected, TRYTE_MAX_IDENTITY.actual, 0.05);
-}
-
-test "Math Identities: Berry Phase" {
- const expected = PI * (1.0 - 1.0 / PHI);
- try std.testing.expectApproxEqAbs(expected, BERRY_PHASE_IDENTITY.actual, 0.2);
-}
diff --git a/src/math/gen_riemann_gamma.zig b/src/math/gen_riemann_gamma.zig
deleted file mode 100644
index 9379f6dc19..0000000000
--- a/src/math/gen_riemann_gamma.zig
+++ /dev/null
@@ -1,308 +0,0 @@
-//! Riemann-Ξ³ β Generated from specs/tri/math/math_riemann_gamma.tri
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! DO NOT EDIT: This file is generated from math_riemann_gamma.tri spec
-
-const std = @import("std");
-
-// ============================================================================
-// CONSTANTS
-// ============================================================================
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ³ = 4.23606797749978969641...
-pub const PHI_CUBED: f64 = PHI * PHI * PHI;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / PHI_CUBED;
-
-/// Fundamental TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// Ο constant
-pub const PI: f64 = 3.14159265358979323846;
-
-// ============================================================================
-// COMPLEX NUMBER TYPE
-// ============================================================================
-
-/// Complex number for zeta function
-pub const Complex = struct {
- re: f64,
- im: f64,
-
- /// Create a complex number from real and imaginary parts
- pub fn init(re: f64, im: f64) Complex {
- return .{ .re = re, .im = im };
- }
-
- /// Add two complex numbers
- pub fn add(a: Complex, b: Complex) Complex {
- return .{ .re = a.re + b.re, .im = a.im + b.im };
- }
-
- /// Multiply two complex numbers
- pub fn mul(a: Complex, b: Complex) Complex {
- return .{
- .re = a.re * b.re - a.im * b.im,
- .im = a.re * b.im + a.im * b.re,
- };
- }
-
- /// Compute magnitude of complex number
- pub fn abs(z: Complex) f64 {
- return @sqrt(z.re * z.re + z.im * z.im);
- }
-};
-
-// ============================================================================
-// GAMMA FUNCTION
-// ============================================================================
-
-/// Gamma function Ξ(x) via Lanczos approximation (real arguments only)
-/// Uses reflection formula for x < 0.5
-pub fn gammaFn(x: f64) f64 {
- // Lanczos approximation coefficients (g=7)
- const p = [_]f64{
- 0.99999999999980993,
- 676.5203681218851,
- -1259.1392167224028,
- 771.32342877765313,
- -176.61502916214059,
- 12.507343278686905,
- -0.13857109526572012,
- 9.9843695780195716e-6,
- 1.5056327351493116e-7,
- };
-
- if (x < 0.5) {
- // Reflection formula: Ξ(x) = Ο / (sin(Οx) Γ Ξ(1-x))
- return PI / (@sin(PI * x) * gammaFn(1.0 - x));
- }
-
- const x1 = x - 1.0;
- var a = p[0];
- const t = x1 + 7.5; // g + 0.5
- for (1..9) |i| {
- a += p[i] / (x1 + @as(f64, @floatFromInt(i)));
- }
-
- return @sqrt(2.0 * PI) * std.math.pow(f64, t, x1 + 0.5) * @exp(-t) * a;
-}
-
-// ============================================================================
-// RIEMANN ZETA FUNCTION
-// ============================================================================
-
-/// Riemann zeta function ΞΆ(s) using Dirichlet eta function
-/// Ξ·(s) = Ξ£(-1)^(n-1) / n^s
-/// ΞΆ(s) = Ξ·(s) / (1 - 2^(1-s))
-/// For Re(s) < 0: uses functional equation
-pub fn zeta(s: Complex, terms: usize) Complex {
- // For Re(s) < 0, use functional equation (real s only for simplicity)
- if (s.re < 0 and @abs(s.im) < 1e-10) {
- // ΞΆ(s) = 2^s Γ Ο^(s-1) Γ sin(Οs/2) Γ Ξ(1-s) Γ ΞΆ(1-s)
- const s_real = s.re;
- const two_s = std.math.pow(f64, 2.0, s_real);
- const pi_s1 = std.math.pow(f64, PI, s_real - 1.0);
- const sin_term = @sin(PI * s_real / 2.0);
- const gamma_term = gammaFn(1.0 - s_real);
- const zeta_1ms = zeta(Complex.init(1.0 - s_real, 0.0), terms);
- const result = two_s * pi_s1 * sin_term * gamma_term * zeta_1ms.re;
- return Complex.init(result, 0.0);
- }
-
- // Use Dirichlet eta function for better convergence
- var eta = Complex.init(0, 0);
- var sign: f64 = 1.0;
-
- for (0..terms) |n| {
- const n_f = @as(f64, @floatFromInt(n + 1));
-
- // Compute n^(-s) = exp(-s * ln(n))
- const log_n = @log(n_f);
- const angle = -s.im * log_n;
- const magnitude = @exp(-s.re * log_n);
-
- const term = Complex.init(
- magnitude * @cos(angle),
- magnitude * @sin(angle),
- );
-
- const signed_term = Complex.init(sign * term.re, sign * term.im);
- eta = eta.add(signed_term);
- sign = -sign;
- }
-
- // Convert eta to zeta: ΞΆ(s) = Ξ·(s) / (1 - 2^(1-s))
- const two_pow_re = @exp(@log(2.0) * (1.0 - s.re));
- const two_pow = Complex.init(
- two_pow_re,
- -@log(2.0) * s.im,
- );
- const denominator = Complex.init(1.0 - two_pow.re, -two_pow.im);
-
- // Complex division: (a+bi)/(c+di) = [(ac+bd) + (bc-ad)i]/(cΒ²+dΒ²)
- const denom_mag_sq = denominator.re * denominator.re + denominator.im * denominator.im;
- return Complex.init(
- (eta.re * denominator.re + eta.im * denominator.im) / denom_mag_sq,
- (eta.im * denominator.re - eta.re * denominator.im) / denom_mag_sq,
- );
-}
-
-// ============================================================================
-// ZETA ZERO DETECTION
-// ============================================================================
-
-/// Check if ΞΆ(s) is close to zero (Riemann zeta zero)
-pub fn isZetaZero(s: Complex, tolerance: f64) bool {
- const z = zeta(s, 100);
- return z.abs() < tolerance;
-}
-
-// ============================================================================
-// PRIME COUNTING FUNCTIONS
-// ============================================================================
-
-/// Ο-scaled prime number theorem
-/// Ο(x) β x / (Ο Γ ln(x) Γ (1 - Ξ³))
-pub fn primeCountPhi(x: f64) f64 {
- return x / (PHI * @log(x) * (1.0 - GAMMA));
-}
-
-/// Standard prime number theorem
-/// Ο(x) β x / ln(x)
-pub fn primeCountStandard(x: f64) f64 {
- return x / @log(x);
-}
-
-/// Ξ³-corrected prime number theorem
-/// Ο(x) β x / (ln(x) Γ (1 + Ξ³/βln(x)))
-pub fn primeCountGamma(x: f64) f64 {
- const log_x = @log(x);
- return x / (log_x * (1.0 + GAMMA / @sqrt(log_x)));
-}
-
-// ============================================================================
-// CRITICAL LINE
-// ============================================================================
-
-/// Check if s is on the critical line
-/// Critical line: Re(s) = 1/2
-pub fn onCriticalLine(s: Complex) bool {
- return @abs(s.re - 0.5) < 1e-10;
-}
-
-// ============================================================================
-// GAMMA CRITICAL LINE HYPOTHESIS
-// ============================================================================
-
-/// Ξ³-hypothesis: Critical line position from ΟΒ³
-/// The critical line Re(s) = 1/2 emerges from ΟΒ³ scaling
-/// where ΟΒ³ - 4 = Ξ³ (approximately)
-pub fn gammaCriticalLine() f64 {
- // ΟΒ³ β 4.236, so ΟΒ³ - 4 β 0.236 = Ξ³
- // The critical line is at 1/2 = 0.5
- // Hypothesis: 1/2 relates to ΟΒ³ through Ξ³
- return (PHI_CUBED - 4.0) / GAMMA; // β 1
-}
-
-// ============================================================================
-// ZERO SPACING
-// ============================================================================
-
-/// Ο-based zero spacing prediction
-/// Adjacent zeros of ΞΆ(s) have average spacing ~ 2Ο/ln(t)
-/// Modified with Ο: spacing ~ 2Ο/(Ο Γ ln(t))
-pub fn zeroSpacingPhi(t: f64) f64 {
- return 2.0 * PI / (PHI * @log(t));
-}
-
-/// Standard zero spacing
-pub fn zeroSpacingStandard(t: f64) f64 {
- return 2.0 * PI / @log(t);
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "Riemann-Ξ³: phi cubed and gamma" {
- const phi_cubed_expected = 4.23606797749978969641;
- try std.testing.expectApproxEqRel(phi_cubed_expected, PHI_CUBED, 1e-10);
-
- const gamma_expected = 0.23606797749978969641;
- try std.testing.expectApproxEqRel(gamma_expected, GAMMA, 1e-10);
-
- // ΟΒ³ - 4 β Ξ³
- const diff = PHI_CUBED - 4.0;
- try std.testing.expectApproxEqRel(diff, GAMMA, 0.01);
-}
-
-test "Riemann-Ξ³: TRINITY identity" {
- try std.testing.expectApproxEqRel(3.0, TRINITY, 1e-10);
-}
-
-test "Riemann-Ξ³: zeta of 2" {
- const s = Complex.init(2.0, 0.0);
- const z = zeta(s, 100);
-
- const expected = PI * PI / 6.0;
- try std.testing.expectApproxEqRel(expected, z.re, 0.01);
-}
-
-test "Riemann-Ξ³: zeta of -1" {
- const s = Complex.init(-1.0, 0.0);
- const z = zeta(s, 100);
-
- const expected = -1.0 / 12.0;
- try std.testing.expectApproxEqRel(expected, z.re, 0.1);
-}
-
-test "Riemann-Ξ³: critical line" {
- const on_line = Complex.init(0.5, 14.134725); // First zero
- try std.testing.expect(onCriticalLine(on_line));
-
- const off_line = Complex.init(0.6, 14.134725);
- try std.testing.expect(!onCriticalLine(off_line));
-}
-
-test "Riemann-Ξ³: prime count gamma" {
- // Ο(100) = 25 primes
- const x = 100.0;
-
- const standard = primeCountStandard(x);
- const gamma_corrected = primeCountGamma(x);
-
- // Both should be reasonably close
- const actual = 25.0;
- const error_std = @abs(standard - actual) / actual;
- const error_gamma = @abs(gamma_corrected - actual) / actual;
-
- // Ξ³-corrected should be better or similar
- try std.testing.expect(error_gamma < error_std + 0.1);
-}
-
-test "Riemann-Ξ³: zero spacing" {
- const t = 100.0;
-
- const standard_spacing = zeroSpacingStandard(t);
- const phi_spacing = zeroSpacingPhi(t);
-
- // Ο-based spacing should be smaller (Ο > 1)
- try std.testing.expect(phi_spacing < standard_spacing);
-
- // Ratio should be ~1/Ο
- const ratio = phi_spacing / standard_spacing;
- try std.testing.expectApproxEqRel(ratio, 1.0 / PHI, 0.01);
-}
-
-test "Riemann-Ξ³: gamma critical line" {
- const result = gammaCriticalLine();
-
- // (ΟΒ³ - 4)/Ξ³ β 1
- try std.testing.expect(result > 0.9);
- try std.testing.expect(result < 1.1);
-}
diff --git a/src/minimal_forward.zig b/src/minimal_forward.zig
deleted file mode 100644
index 9e57fa7ca3..0000000000
--- a/src/minimal_forward.zig
+++ /dev/null
@@ -1,24567 +0,0 @@
-// @origin(spec:minimal_forward.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Minimal Forward Pass Demo β Level 10A First Real Execution
-// Uses sdk.zig Hypervector + Codebook to run: encode β position β attention β FFN β decode
-//
-// Trinity Identity: phi^2 + 1/phi^2 = 3
-
-const std = @import("std");
-const sdk = @import("sdk.zig");
-
-const Hypervector = sdk.Hypervector;
-const Codebook = sdk.Codebook;
-
-// === FORWARD PASS HELPERS ===
-
-/// Create 11 role vectors: Q/K/V for 3 heads + FF1 + FF2
-fn initRoles(dim: usize, seed: u64) [11]Hypervector {
- var roles: [11]Hypervector = undefined;
- for (0..11) |i| {
- roles[i] = Hypervector.random(dim, seed + i);
- }
- return roles;
-}
-
-/// Single-head attention: bind Q/K, score similarity, extract V
-fn singleHeadAttention(
- positioned: []Hypervector,
- q_role: *Hypervector,
- k_role: *Hypervector,
- v_role: *Hypervector,
-) Hypervector {
- // Query = bind(last_position, Q_role)
- var query = positioned[positioned.len - 1].bind(q_role);
-
- // Find best-matching key
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..positioned.len) |i| {
- var key_i = positioned[i].bind(k_role);
- const sim = query.similarity(&key_i);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = i;
- }
- }
-
- // Value = bind(best_position, V_role)
- return positioned[best_idx].bind(v_role);
-}
-
-/// v2.29 single-head forward pass (preserved for backwards compatibility)
-fn forwardPass(
- context: []Hypervector,
- roles: *[11]Hypervector,
-) Hypervector {
- var positioned: [8]Hypervector = undefined;
- for (context, 0..) |*hv, i| {
- positioned[i] = hv.permute(i);
- }
-
- var value = singleHeadAttention(&positioned, &roles[0], &roles[1], &roles[2]);
-
- var ffn_out = value.bind(&roles[9]);
- const output = ffn_out.bundle(&positioned[context.len - 1]);
- return output;
-}
-
-/// v2.30 multi-head forward pass: 3 heads merged via bundle3
-/// Roles layout: [Q0,K0,V0, Q1,K1,V1, Q2,K2,V2, FF1, FF2]
-/// 0 1 2 3 4 5 6 7 8 9 10
-fn forwardPassMultiHead(
- context: []Hypervector,
- roles: *[11]Hypervector,
-) Hypervector {
- var positioned: [8]Hypervector = undefined;
- for (context, 0..) |*hv, i| {
- positioned[i] = hv.permute(i);
- }
-
- // 3-head attention
- var head0 = singleHeadAttention(&positioned, &roles[0], &roles[1], &roles[2]);
- var head1 = singleHeadAttention(&positioned, &roles[3], &roles[4], &roles[5]);
- var head2 = singleHeadAttention(&positioned, &roles[6], &roles[7], &roles[8]);
-
- // Merge heads via bundle3 (true majority vote of 3)
- var merged = head0.bundle3(&head1, &head2);
-
- // FFN: bind(FF1), then bind(FF2)
- var ffn_mid = merged.bind(&roles[9]);
- var ffn_out = ffn_mid.bind(&roles[10]);
-
- // Residual connection: bundle with last positioned vector
- const output = ffn_out.bundle(&positioned[context.len - 1]);
- return output;
-}
-
-/// Autoregressive generation: predict next token, shift context, repeat
-/// Returns number of unique characters generated
-fn generateAutoregressive(
- initial_context: []Hypervector,
- roles: *[11]Hypervector,
- codebook: *Codebook,
- output_buf: []u8,
- max_tokens: usize,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassMultiHead(&context, roles);
- const predicted = codebook.decode(&output);
-
- if (predicted) |p| {
- output_buf[generated] = p[0];
- } else {
- output_buf[generated] = '?';
- }
- generated += 1;
-
- // Shift context: drop first, append new prediction HV
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- context[7] = output.clone();
- }
-
- return generated;
-}
-
-// === RESONATOR-STYLE TRAINING (v2.33) ===
-// Replaces bundle2(role, error) which dilutes signal via majority vote.
-// Uses bind-based targeted correction: compute what each FF role SHOULD be
-// to produce the target, then iteratively blend current roles toward ideal.
-
-/// Resonator training step: for a single (context, target) pair,
-/// iteratively refine the FF roles (roles[9] and roles[10]) to reduce error.
-/// Returns the final loss (1 - similarity) for this sample.
-fn resonatorTrainStep(
- context: []Hypervector,
- target: *Hypervector,
- roles: *[11]Hypervector,
- dim: usize,
- lr: f64,
- prng_seed: u64,
-) f64 {
- // Step 1: Forward pass to get current output
- var output = forwardPassMultiHead(context, roles);
- const initial_sim = output.similarity(target);
- var best_loss: f64 = 1.0 - initial_sim;
-
- // Step 2: Resonator iterations (3-5 cycles of unbindβcorrectβrecheck)
- const max_iters: usize = 5;
- for (0..max_iters) |iter| {
- // Compute positioned vectors (same as forwardPassMultiHead)
- var positioned: [8]Hypervector = undefined;
- for (context, 0..) |*hv, i| {
- positioned[i] = hv.permute(i);
- }
-
- // The forward pass produces: output = bundle(bind(bind(merged, FF1), FF2), last_pos)
- // To correct FF2: ideal_ff2_output = unbind(target, last_positioned)
- // Then: ideal_after_ff2 = unbind(ideal_ff2_output, FF1_output)
- // This gives us the direction FF2 should push toward.
-
- // Compute what the merged attention output is (before FFN)
- var head0 = singleHeadAttention(&positioned, &roles[0], &roles[1], &roles[2]);
- var head1 = singleHeadAttention(&positioned, &roles[3], &roles[4], &roles[5]);
- var head2 = singleHeadAttention(&positioned, &roles[6], &roles[7], &roles[8]);
- var merged = head0.bundle3(&head1, &head2);
-
- // What FF roles should produce: drive output toward target
- // target β bundle(ffn_out, last_pos), so ffn_out β target (approximately)
-
- // Compute ideal FF2 role: if ffn_out = bind(bind(merged, FF1), FF2)
- // and we want ffn_out β target
- // then ideal = unbind(target, bind(merged, FF1))
- var merged_ff1 = merged.bind(&roles[9]);
- var ideal_ff2_direction = target.unbind(&merged_ff1);
-
- // Compute ideal FF1 role similarly: bind(merged, FF1) should produce
- // something that when bound with FF2 gives target
- // ideal_ff1_input = unbind(target, FF2), ideal_ff1 = unbind(ideal_ff1_input, merged)
- var ideal_ff1_input = target.unbind(&roles[10]);
- var ideal_ff1_direction = ideal_ff1_input.unbind(&merged);
-
- // Resonator correction: blend current role toward ideal direction
- // Using bind-based correction: correction = bind(ideal, inverse(current))
- // Then apply sparsified correction
- var ff2_correction = ideal_ff2_direction.unbind(&roles[10]);
- var ff1_correction = ideal_ff1_direction.unbind(&roles[9]);
-
- // Sparsify corrections
- var prng = std.Random.DefaultPrng.init(prng_seed + iter * 100);
- const random = prng.random();
-
- var sparse_ff2 = ff2_correction.clone();
- var sparse_ff1 = ff1_correction.clone();
- for (0..dim) |idx| {
- if (random.float(f64) > lr) {
- sparse_ff2.set(idx, 0);
- }
- if (random.float(f64) > lr) {
- sparse_ff1.set(idx, 0);
- }
- }
-
- // Apply: role_new = bind(role_old, sparse_correction)
- // This is multiplicative, not additive β preserves more signal
- roles[10] = roles[10].bind(&sparse_ff2);
- roles[9] = roles[9].bind(&sparse_ff1);
-
- // Also update attention V roles (roles[2], [5], [8]) with smaller corrections
- // The attention roles are harder to correct, so use smaller lr
- var target_clone = target.clone();
- var neg_out = output.negate();
- var attn_error = target_clone.bundle(&neg_out);
- var sparse_attn = attn_error.clone();
- for (0..dim) |idx| {
- if (random.float(f64) > lr * 0.3) {
- sparse_attn.set(idx, 0);
- }
- }
- // Only update V roles (2, 5, 8) β Q and K should stay stable
- roles[2] = roles[2].bind(&sparse_attn);
- roles[5] = roles[5].bind(&sparse_attn);
- roles[8] = roles[8].bind(&sparse_attn);
-
- // Re-check: did we improve?
- var new_output = forwardPassMultiHead(context, roles);
- const new_sim = new_output.similarity(target);
- const new_loss = 1.0 - new_sim;
-
- if (new_loss < best_loss) {
- best_loss = new_loss;
- output = new_output;
- }
-
- // Early stop if similarity is already good
- if (new_sim > 0.5) break;
- }
-
- return best_loss;
-}
-
-// === DIRECT ROLE AVERAGING (v2.34) ===
-// Bypasses deep bind chains entirely. Instead of training through
-// attention β FFN β residual (5+ binds), we:
-// 1. Summarize context as a single HV via positional bundling
-// 2. Compute ideal role for each sample: ideal = unbind(target, context_summary)
-// 3. Bundle all ideal roles to get the averaged "learned" role
-// 4. At inference: output = bind(context_summary, learned_role)
-//
-// This has only 1 bind at inference time β clean signal, no credit assignment problem.
-
-/// Summarize an 8-element context into a single hypervector.
-/// Uses positional permutation + sequential bundling.
-fn summarizeContext(context: []Hypervector) Hypervector {
- // Permute each position, then bundle sequentially
- var summary = context[0].permute(0);
- for (1..context.len) |i| {
- var positioned = context[i].permute(i);
- summary = summary.bundle(&positioned);
- }
- return summary;
-}
-
-/// Direct forward pass: just bind(context_summary, role)
-/// Only 1 bind operation β clean gradient signal
-fn forwardPassDirect(
- context: []Hypervector,
- role: *Hypervector,
-) Hypervector {
- var summary = summarizeContext(context);
- return summary.bind(role);
-}
-
-/// Pre-compute the ideal role from a set of (context, target) pairs.
-/// For each pair: ideal_i = unbind(target_i, summary_i)
-/// Final role = sequential bundle of all ideal_i
-/// This is a one-shot computation, no iterative training needed.
-fn computeDirectRole(
- corpus: []const u8,
- dim: usize,
- offsets: []const usize,
- context_size: usize,
-) Hypervector {
- var accumulated_role = Hypervector.init(dim); // starts as zero
- var first = true;
-
- for (offsets) |s| {
- if (s + context_size >= corpus.len) continue;
-
- // Encode context
- var ctx: [8]Hypervector = undefined;
- for (0..context_size) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
-
- // Target
- var target = charToHV(dim, corpus[s + context_size]);
-
- // Context summary
- var summary = summarizeContext(&ctx);
-
- // Ideal role for this sample: unbind(target, summary)
- var ideal = target.unbind(&summary);
-
- if (first) {
- accumulated_role = ideal;
- first = false;
- } else {
- accumulated_role = accumulated_role.bundle(&ideal);
- }
- }
-
- return accumulated_role;
-}
-
-/// Direct decode: use the learned role to predict next char
-fn directDecode(context: []Hypervector, role: *Hypervector, dim: usize) u8 {
- var output = forwardPassDirect(context, role);
- return hvToChar(dim, &output);
-}
-
-/// Autoregressive generation with direct role
-fn generateWithDirectRole(
- initial_context: []Hypervector,
- role: *Hypervector,
- dim: usize,
- output_buf: []u8,
- max_tokens: usize,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassDirect(&context, role);
- output_buf[generated] = hvToChar(dim, &output);
- generated += 1;
-
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- context[7] = output.clone();
- }
- return generated;
-}
-
-/// Iterative refinement: after initial direct role computation,
-/// run a few correction passes to improve role quality.
-/// Each pass: for each sample, measure error, compute correction, blend.
-fn refineDirectRole(
- corpus: []const u8,
- dim: usize,
- offsets: []const usize,
- context_size: usize,
- initial_role: *Hypervector,
- num_passes: usize,
-) Hypervector {
- var role = initial_role.clone();
-
- for (0..num_passes) |pass| {
- var correction_accum = Hypervector.init(dim);
- var first_correction = true;
- var pass_loss: f64 = 0;
- var count: usize = 0;
-
- for (offsets) |s| {
- if (s + context_size >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..context_size) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + context_size]);
-
- // Forward pass with current role
- var output = forwardPassDirect(&ctx, &role);
- const sim = output.similarity(&target);
- pass_loss += 1.0 - sim;
- count += 1;
-
- // Only correct if prediction is poor
- if (sim < 0.3) {
- var summary = summarizeContext(&ctx);
- var ideal = target.unbind(&summary);
- // Blend correction: small step toward ideal
- var correction = ideal.unbind(&role);
- // Sparsify heavily (keep 10%)
- var prng = std.Random.DefaultPrng.init(pass * 1000 + s + 60000);
- const random = prng.random();
- for (0..dim) |idx| {
- if (random.float(f64) > 0.1) {
- correction.set(idx, 0);
- }
- }
- if (first_correction) {
- correction_accum = correction;
- first_correction = false;
- } else {
- correction_accum = correction_accum.bundle(&correction);
- }
- }
- }
-
- if (!first_correction) {
- role = role.bind(&correction_accum);
- }
-
- if (count > 0) {
- const avg_pass_loss = pass_loss / @as(f64, @floatFromInt(count));
- _ = avg_pass_loss;
- }
- }
-
- return role;
-}
-
-// === HEBBIAN ASSOCIATION MATRIX (v2.35) ===
-//
-// Build a character-pair association matrix from the corpus.
-// For each character `a`, we bundle all charToHV(b) for every (a,b) bigram
-// observed in corpus. This creates a Hebbian "what follows a?" lookup.
-//
-// Hybrid forward: bundle(direct_role_prediction, hebbian_prediction)
-// Direct role captures 8-char context patterns; Hebbian captures bigram frequency.
-
-/// Number of printable ASCII characters we track (32..127 = 95 chars)
-const HEBBIAN_CHARS: usize = 95;
-const HEBBIAN_OFFSET: usize = 32;
-
-/// Hebbian association: for a given character, returns a hypervector
-/// representing what characters tend to follow it (bundled successors).
-/// We store the matrix as 95 HVs, one per printable ASCII char.
-///
-/// To avoid 95 * 59KB = 5.6MB on stack, we compute associations on-the-fly
-/// from a compact counts representation.
-/// Build Hebbian bigram counts from corpus
-/// Returns counts[a][b] = number of times char b follows char a
-fn buildHebbianCounts(corpus: []const u8) [HEBBIAN_CHARS][HEBBIAN_CHARS]u16 {
- var counts: [HEBBIAN_CHARS][HEBBIAN_CHARS]u16 = undefined;
- // Zero-initialize
- for (0..HEBBIAN_CHARS) |i| {
- for (0..HEBBIAN_CHARS) |j| {
- counts[i][j] = 0;
- }
- }
-
- // Count bigrams
- if (corpus.len < 2) return counts;
- for (0..corpus.len - 1) |i| {
- const a = corpus[i];
- const b = corpus[i + 1];
- if (a >= HEBBIAN_OFFSET and a < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- b >= HEBBIAN_OFFSET and b < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const ai = a - HEBBIAN_OFFSET;
- const bi = b - HEBBIAN_OFFSET;
- if (counts[ai][bi] < 65535) {
- counts[ai][bi] += 1;
- }
- }
- }
-
- return counts;
-}
-
-/// Compute the Hebbian association HV for a given character.
-/// This bundles charToHV(b) for every successor b seen in the corpus,
-/// weighted by frequency (repeated bundling for frequent pairs).
-fn hebbianLookup(
- dim: usize,
- char_idx: usize,
- counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
-) Hypervector {
- var result = Hypervector.init(dim); // zero vector
- var first = true;
-
- // Bundle successors, proportional to count (cap at 3 bundles per successor)
- for (0..HEBBIAN_CHARS) |bi| {
- const count = counts[char_idx][bi];
- if (count == 0) continue;
-
- const char_b: u8 = @intCast(bi + HEBBIAN_OFFSET);
- var successor_hv = charToHV(dim, char_b);
-
- // Bundle this successor (more frequent = repeated bundle = stronger signal)
- const repeats = @min(count, 3);
- for (0..repeats) |_| {
- if (first) {
- result = successor_hv;
- first = false;
- } else {
- result = result.bundle(&successor_hv);
- }
- }
- }
-
- return result;
-}
-
-/// Hybrid forward pass: combine direct role prediction with Hebbian bigram lookup.
-/// output = bundle(bind(summary, role), hebbian_prediction)
-/// This gives the model both context-level (8-char) and bigram-level signal.
-fn forwardPassHybrid(
- context: []Hypervector,
- role: *Hypervector,
- dim: usize,
- last_char: u8,
- counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
-) Hypervector {
- // Direct role prediction (from v2.34)
- var direct_pred = forwardPassDirect(context, role);
-
- // Hebbian bigram prediction
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const char_idx = last_char - HEBBIAN_OFFSET;
- var hebbian_pred = hebbianLookup(dim, char_idx, counts);
- // Hybrid: bundle the two signals
- return direct_pred.bundle(&hebbian_pred);
- }
-
- return direct_pred;
-}
-
-// === v2.39 TRIGRAM HEBBIAN (2-CHAR LOOKBACK) ===
-//
-// Extends bigram Hebbian to trigram: given last 2 chars (a, b), predict next char c.
-// Uses a compact representation: trigram_key = a_idx * HEBBIAN_CHARS + b_idx
-// For each key, store counts of successor chars.
-// Total: 9025 Γ 95 Γ u16 = ~1.7MB (fits on stack for Zig's 8MB default).
-
-const TRIGRAM_KEYS: usize = HEBBIAN_CHARS * HEBBIAN_CHARS; // 95 * 95 = 9025
-
-/// Build trigram counts from corpus.
-/// Returns counts[a*95+b][c] = number of times char c follows (a, b) pair.
-fn buildTrigramCounts(corpus: []const u8) [TRIGRAM_KEYS][HEBBIAN_CHARS]u16 {
- var counts: [TRIGRAM_KEYS][HEBBIAN_CHARS]u16 = undefined;
- // Zero-initialize
- for (0..TRIGRAM_KEYS) |i| {
- for (0..HEBBIAN_CHARS) |j| {
- counts[i][j] = 0;
- }
- }
-
- // Count trigrams
- if (corpus.len < 3) return counts;
- for (0..corpus.len - 2) |i| {
- const a = corpus[i];
- const b = corpus[i + 1];
- const c = corpus[i + 2];
- if (a >= HEBBIAN_OFFSET and a < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- b >= HEBBIAN_OFFSET and b < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- c >= HEBBIAN_OFFSET and c < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const ai = a - HEBBIAN_OFFSET;
- const bi = b - HEBBIAN_OFFSET;
- const ci = c - HEBBIAN_OFFSET;
- const key = ai * HEBBIAN_CHARS + bi;
- if (counts[key][ci] < 65535) {
- counts[key][ci] += 1;
- }
- }
- }
-
- return counts;
-}
-
-/// Compute trigram-based Hebbian association HV for a given 2-char context.
-/// Bundles charToHV(c) for every successor c seen after (a, b), weighted by frequency.
-fn trigramLookup(
- dim: usize,
- prev_char_idx: usize,
- last_char_idx: usize,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
-) Hypervector {
- var result = Hypervector.init(dim);
- var first = true;
-
- const key = prev_char_idx * HEBBIAN_CHARS + last_char_idx;
-
- for (0..HEBBIAN_CHARS) |ci| {
- const count = tri_counts[key][ci];
- if (count == 0) continue;
-
- const char_c: u8 = @intCast(ci + HEBBIAN_OFFSET);
- var successor_hv = charToHV(dim, char_c);
-
- const repeats = @min(count, 3);
- for (0..repeats) |_| {
- if (first) {
- result = successor_hv;
- first = false;
- } else {
- result = result.bundle(&successor_hv);
- }
- }
- }
-
- return result;
-}
-
-/// Trigram hybrid forward pass: combine multi-role prediction with trigram Hebbian.
-/// Uses last 2 chars for deeper context. Falls back to bigram if trigram has no data.
-fn forwardPassTrigramHybrid(
- context: []Hypervector,
- roles: *[8]Hypervector,
- dim: usize,
- prev_char: u8,
- last_char: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
-) Hypervector {
- var multi_pred = forwardPassMultiRole(context, roles);
-
- // Try trigram first (deeper context)
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
-
- // Check if trigram has any data for this pair
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
-
- if (tri_total > 0) {
- // Trigram available: use it + bigram for robustness
- var tri_pred = trigramLookup(dim, prev_idx, last_idx, tri_counts);
- var bi_pred = hebbianLookup(dim, last_idx, bi_counts);
- // Bundle all three: multi-role + trigram + bigram
- var tri_bi = tri_pred.bundle(&bi_pred);
- return multi_pred.bundle(&tri_bi);
- }
- }
-
- // Fallback to bigram only
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const char_idx = last_char - HEBBIAN_OFFSET;
- var hebbian_pred = hebbianLookup(dim, char_idx, bi_counts);
- return multi_pred.bundle(&hebbian_pred);
- }
-
- return multi_pred;
-}
-
-/// Autoregressive generation with multi-role + trigram Hebbian + sampling.
-fn generateWithTrigramSampled(
- initial_context: []Hypervector,
- roles: *[8]Hypervector,
- dim: usize,
- prev_char_init: u8,
- last_char_init: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
- output_buf: []u8,
- max_tokens: usize,
- temperature: f64,
- top_k: usize,
- base_seed: u64,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var prev_char = prev_char_init;
- var last_char = last_char_init;
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassTrigramHybrid(&context, roles, dim, prev_char, last_char, bi_counts, tri_counts);
- const decoded = hvToCharSampled(dim, &output, temperature, top_k, base_seed + generated);
- output_buf[generated] = decoded;
- prev_char = last_char;
- last_char = decoded;
- generated += 1;
-
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- context[7] = charToHV(dim, decoded);
- }
- return generated;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// WEIGHTED HYBRID BLENDING (v2.42)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Weighted blend of 3 hypervectors: result[i] = sign(w_a*a[i] + w_b*b[i] + w_c*c[i])
-/// Returns a ternary HV where each trit is the weighted majority vote.
-fn weightedBlend3(
- a: *Hypervector,
- b: *Hypervector,
- c: *Hypervector,
- w_a: f64,
- w_b: f64,
- w_c: f64,
- dim: usize,
-) Hypervector {
- var result = Hypervector.init(dim);
- const threshold: f64 = 0.1; // deadzone β zero trit
- for (0..dim) |i| {
- const ta: f64 = @floatFromInt(a.get(i));
- const tb: f64 = @floatFromInt(b.get(i));
- const tc: f64 = @floatFromInt(c.get(i));
- const weighted = w_a * ta + w_b * tb + w_c * tc;
- if (weighted > threshold) {
- result.set(i, 1);
- } else if (weighted < -threshold) {
- result.set(i, -1);
- }
- // else stays 0
- }
- return result;
-}
-
-/// Weighted blend of 2 hypervectors (for bigram-only fallback)
-fn weightedBlend2(
- a: *Hypervector,
- b: *Hypervector,
- w_a: f64,
- w_b: f64,
- dim: usize,
-) Hypervector {
- var result = Hypervector.init(dim);
- const threshold: f64 = 0.1;
- for (0..dim) |i| {
- const ta: f64 = @floatFromInt(a.get(i));
- const tb: f64 = @floatFromInt(b.get(i));
- const weighted = w_a * ta + w_b * tb;
- if (weighted > threshold) {
- result.set(i, 1);
- } else if (weighted < -threshold) {
- result.set(i, -1);
- }
- }
- return result;
-}
-
-/// Forward pass with weighted alpha blending instead of equal-weight bundling.
-/// alpha_role: weight for multi-role prediction
-/// alpha_tri: weight for trigram Hebbian
-/// alpha_bi: weight for bigram Hebbian
-fn forwardPassWeightedHybrid(
- context: []Hypervector,
- roles: *[8]Hypervector,
- dim: usize,
- prev_char: u8,
- last_char: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
- alpha_role: f64,
- alpha_tri: f64,
- alpha_bi: f64,
-) Hypervector {
- var multi_pred = forwardPassMultiRole(context, roles);
-
- // Try trigram path
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
-
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
-
- if (tri_total > 0) {
- var tri_pred = trigramLookup(dim, prev_idx, last_idx, tri_counts);
- var bi_pred = hebbianLookup(dim, last_idx, bi_counts);
- return weightedBlend3(&multi_pred, &tri_pred, &bi_pred, alpha_role, alpha_tri, alpha_bi, dim);
- }
- }
-
- // Fallback to bigram only (role + bigram weighted)
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const char_idx = last_char - HEBBIAN_OFFSET;
- var hebbian_pred = hebbianLookup(dim, char_idx, bi_counts);
- return weightedBlend2(&multi_pred, &hebbian_pred, alpha_role, alpha_bi + alpha_tri, dim);
- }
-
- return multi_pred;
-}
-
-/// Generation with weighted hybrid forward pass
-fn generateWithWeightedHybrid(
- initial_context: []Hypervector,
- roles: *[8]Hypervector,
- dim: usize,
- prev_char_init: u8,
- last_char_init: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
- alpha_role: f64,
- alpha_tri: f64,
- alpha_bi: f64,
- output_buf: []u8,
- max_tokens: usize,
- temperature: f64,
- top_k: usize,
- base_seed: u64,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var prev_char = prev_char_init;
- var last_char = last_char_init;
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassWeightedHybrid(&context, roles, dim, prev_char, last_char, bi_counts, tri_counts, alpha_role, alpha_tri, alpha_bi);
- const decoded = hvToCharSampled(dim, &output, temperature, top_k, base_seed + generated);
- output_buf[generated] = decoded;
- prev_char = last_char;
- last_char = decoded;
- generated += 1;
-
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- context[7] = charToHV(dim, decoded);
- }
- return generated;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// PURE TRIGRAM (v2.43) β No roles, no attention, just n-gram frequency lookup
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Pure trigram forward pass: trigram lookup with bigram fallback, NO role vectors.
-/// This is the cleanest prediction: just character frequency statistics.
-fn forwardPassPureTrigram(
- dim: usize,
- prev_char: u8,
- last_char: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
-) Hypervector {
- // Try trigram first
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
-
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
-
- if (tri_total > 0) {
- // Pure trigram: no role blending, just trigram lookup
- return trigramLookup(dim, prev_idx, last_idx, tri_counts);
- }
-
- // Trigram has no data for this pair β fall back to bigram
- return hebbianLookup(dim, last_idx, bi_counts);
- }
-
- // Last char out of range β bigram only
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const char_idx = last_char - HEBBIAN_OFFSET;
- return hebbianLookup(dim, char_idx, bi_counts);
- }
-
- // Nothing available β zero vector
- return Hypervector.init(dim);
-}
-
-/// Pure trigram + bigram blend: weighted combination of just the two Hebbian signals.
-/// alpha_tri: trigram weight, alpha_bi: bigram weight (should sum to ~1.0)
-fn forwardPassPureTrigramBlend(
- dim: usize,
- prev_char: u8,
- last_char: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
- alpha_tri: f64,
- alpha_bi: f64,
-) Hypervector {
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
-
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
-
- if (tri_total > 0) {
- var tri_pred = trigramLookup(dim, prev_idx, last_idx, tri_counts);
- var bi_pred = hebbianLookup(dim, last_idx, bi_counts);
- return weightedBlend2(&tri_pred, &bi_pred, alpha_tri, alpha_bi, dim);
- }
-
- return hebbianLookup(dim, last_idx, bi_counts);
- }
-
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const char_idx = last_char - HEBBIAN_OFFSET;
- return hebbianLookup(dim, char_idx, bi_counts);
- }
-
- return Hypervector.init(dim);
-}
-
-/// Generation with pure trigram (no roles needed)
-fn generateWithPureTrigram(
- dim: usize,
- prev_char_init: u8,
- last_char_init: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
- output_buf: []u8,
- max_tokens: usize,
- temperature: f64,
- top_k: usize,
- base_seed: u64,
-) usize {
- var prev_char = prev_char_init;
- var last_char = last_char_init;
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassPureTrigram(dim, prev_char, last_char, bi_counts, tri_counts);
- const decoded = hvToCharSampled(dim, &output, temperature, top_k, base_seed + generated);
- output_buf[generated] = decoded;
- prev_char = last_char;
- last_char = decoded;
- generated += 1;
- }
- return generated;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// RAW FREQUENCY DECODING (v2.44) β Bypass VSA, sample directly from count tables
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Compute raw probability P(target | prev, last) from trigram counts.
-/// Returns the probability (0.0 to 1.0) of the target character.
-/// Falls back to bigram P(target | last) if no trigram data.
-/// Falls back to uniform 1/95 if no bigram data either.
-fn rawTrigramProb(
- prev_char: u8,
- last_char: u8,
- target_char: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
-) f64 {
- const uniform = 1.0 / @as(f64, @floatFromInt(HEBBIAN_CHARS));
-
- if (target_char < HEBBIAN_OFFSET or target_char >= HEBBIAN_OFFSET + HEBBIAN_CHARS) return uniform;
- const target_idx = target_char - HEBBIAN_OFFSET;
-
- // Try trigram
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
-
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
-
- if (tri_total > 0) {
- const count: f64 = @floatFromInt(tri_counts[key][target_idx]);
- const total: f64 = @floatFromInt(tri_total);
- // Laplace smoothing: (count + 0.01) / (total + 0.01 * 95)
- return (count + 0.01) / (total + 0.01 * @as(f64, @floatFromInt(HEBBIAN_CHARS)));
- }
- }
-
- // Fallback to bigram
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const last_idx = last_char - HEBBIAN_OFFSET;
- var bi_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- bi_total += bi_counts[last_idx][ci];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(bi_counts[last_idx][target_idx]);
- const total: f64 = @floatFromInt(bi_total);
- return (count + 0.01) / (total + 0.01 * @as(f64, @floatFromInt(HEBBIAN_CHARS)));
- }
- }
-
- return uniform;
-}
-
-/// Sample a character directly from raw trigram/bigram count distribution.
-/// Uses temperature scaling and top-k filtering on raw probabilities.
-fn rawTrigramSample(
- prev_char: u8,
- last_char: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
- temperature: f64,
- top_k: usize,
- seed: u64,
-) u8 {
- // Build probability distribution
- var probs: [HEBBIAN_CHARS]f64 = undefined;
- var has_trigram = false;
-
- // Try trigram distribution
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
-
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
-
- if (tri_total > 0) {
- has_trigram = true;
- const total_f: f64 = @floatFromInt(tri_total);
- const smooth = 0.01 * @as(f64, @floatFromInt(HEBBIAN_CHARS));
- for (0..HEBBIAN_CHARS) |ci| {
- const count: f64 = @floatFromInt(tri_counts[key][ci]);
- probs[ci] = (count + 0.01) / (total_f + smooth);
- }
- }
- }
-
- // Fallback to bigram
- if (!has_trigram) {
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const last_idx = last_char - HEBBIAN_OFFSET;
- var bi_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- bi_total += bi_counts[last_idx][ci];
- }
- if (bi_total > 0) {
- const total_f: f64 = @floatFromInt(bi_total);
- const smooth = 0.01 * @as(f64, @floatFromInt(HEBBIAN_CHARS));
- for (0..HEBBIAN_CHARS) |ci| {
- const count: f64 = @floatFromInt(bi_counts[last_idx][ci]);
- probs[ci] = (count + 0.01) / (total_f + smooth);
- }
- } else {
- // Uniform
- for (0..HEBBIAN_CHARS) |ci| {
- probs[ci] = 1.0 / @as(f64, @floatFromInt(HEBBIAN_CHARS));
- }
- }
- } else {
- for (0..HEBBIAN_CHARS) |ci| {
- probs[ci] = 1.0 / @as(f64, @floatFromInt(HEBBIAN_CHARS));
- }
- }
- }
-
- // Apply temperature
- if (temperature > 0.0 and temperature != 1.0) {
- var max_logp: f64 = -1e10;
- for (0..HEBBIAN_CHARS) |ci| {
- const logp = @log(@max(probs[ci], 1e-20));
- if (logp > max_logp) max_logp = logp;
- probs[ci] = logp;
- }
- for (0..HEBBIAN_CHARS) |ci| {
- probs[ci] = @exp((probs[ci] - max_logp) / temperature);
- }
- }
-
- // Top-k filtering
- if (top_k > 0 and top_k < HEBBIAN_CHARS) {
- // Find top-k threshold
- var sorted_vals: [HEBBIAN_CHARS]f64 = undefined;
- for (0..HEBBIAN_CHARS) |ci| {
- sorted_vals[ci] = probs[ci];
- }
- // Simple partial sort: find k-th largest
- for (0..top_k) |k| {
- var max_idx: usize = k;
- for (k + 1..HEBBIAN_CHARS) |ci| {
- if (sorted_vals[ci] > sorted_vals[max_idx]) max_idx = ci;
- }
- const tmp = sorted_vals[k];
- sorted_vals[k] = sorted_vals[max_idx];
- sorted_vals[max_idx] = tmp;
- }
- const threshold = sorted_vals[top_k - 1];
- for (0..HEBBIAN_CHARS) |ci| {
- if (probs[ci] < threshold) probs[ci] = 0.0;
- }
- }
-
- // Normalize
- var total: f64 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- total += probs[ci];
- }
- if (total > 0) {
- for (0..HEBBIAN_CHARS) |ci| {
- probs[ci] /= total;
- }
- }
-
- // Sample using seed-based RNG
- var rng_state = seed;
- rng_state ^= rng_state >> 12;
- rng_state ^= rng_state << 25;
- rng_state ^= rng_state >> 27;
- const rand_val: f64 = @as(f64, @floatFromInt(rng_state % 1000000)) / 1000000.0;
-
- var cumulative: f64 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- cumulative += probs[ci];
- if (rand_val < cumulative) {
- return @intCast(ci + HEBBIAN_OFFSET);
- }
- }
- return @intCast(HEBBIAN_OFFSET); // fallback: space
-}
-
-/// Generate text using raw frequency sampling (no VSA at all)
-fn generateWithRawFreq(
- prev_char_init: u8,
- last_char_init: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
- output_buf: []u8,
- max_tokens: usize,
- temperature: f64,
- top_k: usize,
- base_seed: u64,
-) usize {
- var prev_char = prev_char_init;
- var last_char = last_char_init;
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- const decoded = rawTrigramSample(prev_char, last_char, bi_counts, tri_counts, temperature, top_k, base_seed + generated);
- output_buf[generated] = decoded;
- prev_char = last_char;
- last_char = decoded;
- generated += 1;
- }
- return generated;
-}
-
-/// Compute raw frequency loss: -log(P(target | prev, last))
-/// This is the true cross-entropy loss without VSA encoding overhead.
-fn rawTrigramLoss(
- prev_char: u8,
- last_char: u8,
- target_char: u8,
- bi_counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- tri_counts: *const [TRIGRAM_KEYS][HEBBIAN_CHARS]u16,
-) f64 {
- const prob = rawTrigramProb(prev_char, last_char, target_char, bi_counts, tri_counts);
- return -@log(@max(prob, 1e-20));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// WORD-LEVEL STATISTICS (v2.45) β Tokenize corpus, build word bigram model
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const MAX_WORDS: usize = 256; // max unique words in vocabulary
-const MAX_TOKENS: usize = 1024; // max tokens in corpus
-const MAX_WORD_LEN: usize = 24; // max length of a single word
-
-/// A simple fixed-size word vocabulary and tokenized corpus
-const WordCorpus = struct {
- // Vocabulary: each word stored as a fixed-length buffer
- vocab: [MAX_WORDS][MAX_WORD_LEN]u8,
- vocab_lens: [MAX_WORDS]u8,
- vocab_size: usize,
-
- // Tokenized corpus as word indices
- tokens: [MAX_TOKENS]u16,
- token_count: usize,
-
- // Word bigram counts: counts[prev_word][next_word]
- bigram_counts: [MAX_WORDS][MAX_WORDS]u16,
-
- fn init() WordCorpus {
- var self: WordCorpus = undefined;
- self.vocab_size = 0;
- self.token_count = 0;
- for (0..MAX_WORDS) |i| {
- self.vocab_lens[i] = 0;
- for (0..MAX_WORDS) |j| {
- self.bigram_counts[i][j] = 0;
- }
- }
- return self;
- }
-
- /// Find or add a word to vocabulary. Returns word index.
- fn getOrAddWord(self: *WordCorpus, word: []const u8) u16 {
- if (word.len == 0 or word.len > MAX_WORD_LEN) return 0;
-
- // Linear search (corpus is small)
- for (0..self.vocab_size) |i| {
- const len = self.vocab_lens[i];
- if (len == word.len) {
- var match = true;
- for (0..len) |j| {
- if (self.vocab[i][j] != word[j]) {
- match = false;
- break;
- }
- }
- if (match) return @intCast(i);
- }
- }
-
- // Add new word
- if (self.vocab_size >= MAX_WORDS) return 0;
- const idx = self.vocab_size;
- for (0..word.len) |j| {
- self.vocab[idx][j] = word[j];
- }
- self.vocab_lens[idx] = @intCast(word.len);
- self.vocab_size += 1;
- return @intCast(idx);
- }
-
- /// Get word string from index
- fn getWord(self: *const WordCorpus, idx: u16) []const u8 {
- if (idx >= self.vocab_size) return "";
- const len = self.vocab_lens[idx];
- return self.vocab[idx][0..len];
- }
-
- /// Tokenize a corpus into word indices (split on spaces)
- fn tokenize(self: *WordCorpus, corpus: []const u8) void {
- var i: usize = 0;
- while (i < corpus.len and self.token_count < MAX_TOKENS) {
- // Skip spaces
- while (i < corpus.len and corpus[i] == ' ') : (i += 1) {}
- if (i >= corpus.len) break;
-
- // Find word end
- const start = i;
- while (i < corpus.len and corpus[i] != ' ') : (i += 1) {}
- const word = corpus[start..i];
- if (word.len > 0 and word.len <= MAX_WORD_LEN) {
- const idx = self.getOrAddWord(word);
- self.tokens[self.token_count] = idx;
- self.token_count += 1;
- }
- }
- }
-
- /// Build word bigram counts from tokenized corpus
- fn buildBigrams(self: *WordCorpus) void {
- if (self.token_count < 2) return;
- for (0..self.token_count - 1) |i| {
- const prev = self.tokens[i];
- const next = self.tokens[i + 1];
- if (self.bigram_counts[prev][next] < 65535) {
- self.bigram_counts[prev][next] += 1;
- }
- }
- }
-
- /// Get P(next_word | prev_word) with Laplace smoothing
- fn wordBigramProb(self: *const WordCorpus, prev_idx: u16, next_idx: u16) f64 {
- if (prev_idx >= self.vocab_size or next_idx >= self.vocab_size) {
- return 1.0 / @as(f64, @floatFromInt(self.vocab_size));
- }
- var total: u32 = 0;
- for (0..self.vocab_size) |j| {
- total += self.bigram_counts[prev_idx][j];
- }
- if (total == 0) return 1.0 / @as(f64, @floatFromInt(self.vocab_size));
- const count: f64 = @floatFromInt(self.bigram_counts[prev_idx][next_idx]);
- const total_f: f64 = @floatFromInt(total);
- const vs: f64 = @floatFromInt(self.vocab_size);
- return (count + 0.1) / (total_f + 0.1 * vs);
- }
-
- /// Sample next word given previous word
- fn sampleNextWord(self: *const WordCorpus, prev_idx: u16, temperature: f64, seed: u64) u16 {
- var probs: [MAX_WORDS]f64 = undefined;
- var total: u32 = 0;
-
- for (0..self.vocab_size) |j| {
- total += self.bigram_counts[prev_idx][j];
- }
-
- if (total == 0) {
- // Uniform over vocabulary
- return @intCast(seed % self.vocab_size);
- }
-
- const total_f: f64 = @floatFromInt(total);
- const vs: f64 = @floatFromInt(self.vocab_size);
- const smooth = 0.1 * vs;
-
- // Build distribution with temperature
- var max_logp: f64 = -1e10;
- for (0..self.vocab_size) |j| {
- const count: f64 = @floatFromInt(self.bigram_counts[prev_idx][j]);
- const p = (count + 0.1) / (total_f + smooth);
- const logp = @log(@max(p, 1e-20));
- probs[j] = logp;
- if (logp > max_logp) max_logp = logp;
- }
-
- // Apply temperature and softmax
- var sum: f64 = 0;
- for (0..self.vocab_size) |j| {
- probs[j] = @exp((probs[j] - max_logp) / @max(temperature, 0.01));
- sum += probs[j];
- }
- for (0..self.vocab_size) |j| {
- probs[j] /= sum;
- }
-
- // Sample
- var rng = seed;
- rng ^= rng >> 12;
- rng ^= rng << 25;
- rng ^= rng >> 27;
- const r: f64 = @as(f64, @floatFromInt(rng % 1000000)) / 1000000.0;
-
- var cumulative: f64 = 0;
- for (0..self.vocab_size) |j| {
- cumulative += probs[j];
- if (r < cumulative) return @intCast(j);
- }
- return 0;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// WORD TRIGRAM MODEL (v2.46) β P(word | prev2, prev1)
-// Sparse storage: with 988 tokens, only ~986 trigram observations exist.
-// Hash table with open addressing for efficient (prev2, prev1) β counts lookup.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const WORD_TRI_HASH_SIZE: usize = 2048; // power of 2 for fast modulo
-const WORD_TRI_MAX_NEXTS: usize = 32; // max unique successors per (prev2, prev1) pair
-
-const WordTrigramSlot = struct {
- prev2: u16,
- prev1: u16,
- valid: bool,
- nexts: [WORD_TRI_MAX_NEXTS]u16, // next word indices
- counts: [WORD_TRI_MAX_NEXTS]u16, // corresponding counts
- num_nexts: u8,
- total_count: u16,
-};
-
-const WordTrigramModel = struct {
- // Vocabulary (same as WordCorpus)
- vocab: [MAX_WORDS][MAX_WORD_LEN]u8,
- vocab_lens: [MAX_WORDS]u8,
- vocab_size: usize,
- tokens: [MAX_TOKENS]u16,
- token_count: usize,
-
- // Bigram counts (fallback when trigram unseen)
- bigram_counts: [MAX_WORDS][MAX_WORDS]u16,
-
- // Trigram: sparse hash table
- tri_slots: [WORD_TRI_HASH_SIZE]WordTrigramSlot,
- tri_used: usize,
-
- fn init() WordTrigramModel {
- var self: WordTrigramModel = undefined;
- self.vocab_size = 0;
- self.token_count = 0;
- self.tri_used = 0;
- for (0..MAX_WORDS) |i| {
- self.vocab_lens[i] = 0;
- for (0..MAX_WORDS) |j| {
- self.bigram_counts[i][j] = 0;
- }
- }
- for (0..WORD_TRI_HASH_SIZE) |i| {
- self.tri_slots[i].valid = false;
- self.tri_slots[i].num_nexts = 0;
- self.tri_slots[i].total_count = 0;
- }
- return self;
- }
-
- fn getOrAddWord(self: *WordTrigramModel, word: []const u8) u16 {
- if (word.len == 0 or word.len > MAX_WORD_LEN) return 0;
- for (0..self.vocab_size) |i| {
- const len = self.vocab_lens[i];
- if (len == word.len) {
- var match = true;
- for (0..len) |j| {
- if (self.vocab[i][j] != word[j]) {
- match = false;
- break;
- }
- }
- if (match) return @intCast(i);
- }
- }
- if (self.vocab_size >= MAX_WORDS) return 0;
- const idx = self.vocab_size;
- for (0..word.len) |j| {
- self.vocab[idx][j] = word[j];
- }
- self.vocab_lens[idx] = @intCast(word.len);
- self.vocab_size += 1;
- return @intCast(idx);
- }
-
- fn getWord(self: *const WordTrigramModel, idx: u16) []const u8 {
- if (idx >= self.vocab_size) return "";
- const len = self.vocab_lens[idx];
- return self.vocab[idx][0..len];
- }
-
- fn tokenize(self: *WordTrigramModel, corpus: []const u8) void {
- var i: usize = 0;
- while (i < corpus.len and self.token_count < MAX_TOKENS) {
- while (i < corpus.len and corpus[i] == ' ') : (i += 1) {}
- if (i >= corpus.len) break;
- const start = i;
- while (i < corpus.len and corpus[i] != ' ') : (i += 1) {}
- const word = corpus[start..i];
- if (word.len > 0 and word.len <= MAX_WORD_LEN) {
- const idx = self.getOrAddWord(word);
- self.tokens[self.token_count] = idx;
- self.token_count += 1;
- }
- }
- }
-
- fn buildBigrams(self: *WordTrigramModel) void {
- if (self.token_count < 2) return;
- for (0..self.token_count - 1) |i| {
- const prev = self.tokens[i];
- const next = self.tokens[i + 1];
- if (self.bigram_counts[prev][next] < 65535) {
- self.bigram_counts[prev][next] += 1;
- }
- }
- }
-
- /// Hash function for (prev2, prev1) pair
- fn triHash(prev2: u16, prev1: u16) usize {
- const key: u32 = @as(u32, prev2) * 257 + @as(u32, prev1);
- return @intCast((key ^ (key >> 11) ^ (key >> 22)) % WORD_TRI_HASH_SIZE);
- }
-
- /// Find or create a trigram slot for (prev2, prev1)
- fn getOrCreateSlot(self: *WordTrigramModel, prev2: u16, prev1: u16) ?*WordTrigramSlot {
- var h = triHash(prev2, prev1);
- var probes: usize = 0;
- while (probes < WORD_TRI_HASH_SIZE) : (probes += 1) {
- const slot = &self.tri_slots[h];
- if (!slot.valid) {
- // Empty slot β claim it
- slot.valid = true;
- slot.prev2 = prev2;
- slot.prev1 = prev1;
- slot.num_nexts = 0;
- slot.total_count = 0;
- self.tri_used += 1;
- return slot;
- }
- if (slot.prev2 == prev2 and slot.prev1 == prev1) {
- return slot;
- }
- h = (h + 1) % WORD_TRI_HASH_SIZE;
- }
- return null; // table full
- }
-
- /// Find slot for (prev2, prev1) β read-only
- fn findSlot(self: *const WordTrigramModel, prev2: u16, prev1: u16) ?*const WordTrigramSlot {
- var h = triHash(prev2, prev1);
- var probes: usize = 0;
- while (probes < WORD_TRI_HASH_SIZE) : (probes += 1) {
- const slot = &self.tri_slots[h];
- if (!slot.valid) return null;
- if (slot.prev2 == prev2 and slot.prev1 == prev1) return slot;
- h = (h + 1) % WORD_TRI_HASH_SIZE;
- }
- return null;
- }
-
- /// Build trigram counts from tokenized corpus
- fn buildTrigrams(self: *WordTrigramModel) void {
- if (self.token_count < 3) return;
- for (0..self.token_count - 2) |i| {
- const p2 = self.tokens[i];
- const p1 = self.tokens[i + 1];
- const nx = self.tokens[i + 2];
- if (self.getOrCreateSlot(p2, p1)) |slot| {
- // Find existing next entry or add new one
- var found = false;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == nx) {
- if (slot.counts[k] < 65535) slot.counts[k] += 1;
- slot.total_count +|= 1;
- found = true;
- break;
- }
- }
- if (!found and slot.num_nexts < WORD_TRI_MAX_NEXTS) {
- slot.nexts[slot.num_nexts] = nx;
- slot.counts[slot.num_nexts] = 1;
- slot.num_nexts += 1;
- slot.total_count +|= 1;
- }
- }
- }
- }
-
- /// P(next | prev2, prev1) with trigram β bigram fallback + Laplace smoothing
- fn wordTrigramProb(self: *const WordTrigramModel, prev2: u16, prev1: u16, next_idx: u16) f64 {
- const vs: f64 = @floatFromInt(self.vocab_size);
-
- // Try trigram first
- if (self.findSlot(prev2, prev1)) |slot| {
- if (slot.total_count > 0) {
- var count: f64 = 0;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == next_idx) {
- count = @floatFromInt(slot.counts[k]);
- break;
- }
- }
- const total: f64 = @floatFromInt(slot.total_count);
- return (count + 0.1) / (total + 0.1 * vs);
- }
- }
-
- // Bigram fallback P(next | prev1)
- var bi_total: u32 = 0;
- for (0..self.vocab_size) |j| {
- bi_total += self.bigram_counts[prev1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(self.bigram_counts[prev1][next_idx]);
- const total: f64 = @floatFromInt(bi_total);
- return (count + 0.1) / (total + 0.1 * vs);
- }
-
- // Uniform fallback
- return 1.0 / vs;
- }
-
- /// Sample next word given (prev2, prev1) with temperature
- fn sampleNextWord(self: *const WordTrigramModel, prev2: u16, prev1: u16, temperature: f64, seed: u64) u16 {
- var probs: [MAX_WORDS]f64 = undefined;
- const vs: f64 = @floatFromInt(self.vocab_size);
-
- // Try trigram slot
- var use_trigram = false;
- if (self.findSlot(prev2, prev1)) |slot| {
- if (slot.total_count > 0) {
- use_trigram = true;
- const total: f64 = @floatFromInt(slot.total_count);
- const smooth = 0.1 * vs;
-
- // Initialize all with smoothing baseline
- for (0..self.vocab_size) |j| {
- probs[j] = 0.1 / (total + smooth);
- }
- // Add actual counts
- for (0..slot.num_nexts) |k| {
- const idx = slot.nexts[k];
- const count: f64 = @floatFromInt(slot.counts[k]);
- probs[idx] = (count + 0.1) / (total + smooth);
- }
- }
- }
-
- if (!use_trigram) {
- // Bigram fallback
- var bi_total: u32 = 0;
- for (0..self.vocab_size) |j| {
- bi_total += self.bigram_counts[prev1][j];
- }
- if (bi_total > 0) {
- const total: f64 = @floatFromInt(bi_total);
- const smooth = 0.1 * vs;
- for (0..self.vocab_size) |j| {
- const count: f64 = @floatFromInt(self.bigram_counts[prev1][j]);
- probs[j] = (count + 0.1) / (total + smooth);
- }
- } else {
- return @intCast(seed % self.vocab_size);
- }
- }
-
- // Apply temperature in log-space
- var max_logp: f64 = -1e10;
- for (0..self.vocab_size) |j| {
- const logp = @log(@max(probs[j], 1e-20));
- probs[j] = logp;
- if (logp > max_logp) max_logp = logp;
- }
-
- var sum: f64 = 0;
- for (0..self.vocab_size) |j| {
- probs[j] = @exp((probs[j] - max_logp) / @max(temperature, 0.01));
- sum += probs[j];
- }
- for (0..self.vocab_size) |j| {
- probs[j] /= sum;
- }
-
- // Sample with xorshift RNG
- var rng = seed;
- rng ^= rng >> 12;
- rng ^= rng << 25;
- rng ^= rng >> 27;
- const r: f64 = @as(f64, @floatFromInt(rng % 1000000)) / 1000000.0;
-
- var cumulative: f64 = 0;
- for (0..self.vocab_size) |j| {
- cumulative += probs[j];
- if (r < cumulative) return @intCast(j);
- }
- return 0;
- }
-
- /// Compute trigram loss: -log(P(next | prev2, prev1))
- fn wordTrigramLoss(self: *const WordTrigramModel, prev2: u16, prev1: u16, next_idx: u16) f64 {
- const p = self.wordTrigramProb(prev2, prev1, next_idx);
- return -@log(@max(p, 1e-20));
- }
-};
-
-/// Decode using hybrid forward pass
-fn hybridDecode(
- context: []Hypervector,
- role: *Hypervector,
- dim: usize,
- last_char: u8,
- counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
-) u8 {
- var output = forwardPassHybrid(context, role, dim, last_char, counts);
- return hvToChar(dim, &output);
-}
-
-/// Autoregressive generation with hybrid (direct + Hebbian) forward pass
-fn generateWithHybrid(
- initial_context: []Hypervector,
- role: *Hypervector,
- dim: usize,
- last_char_init: u8,
- counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- output_buf: []u8,
- max_tokens: usize,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var last_char = last_char_init;
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassHybrid(&context, role, dim, last_char, counts);
- const decoded = hvToChar(dim, &output);
- output_buf[generated] = decoded;
- last_char = decoded;
- generated += 1;
-
- // Shift context window
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- context[7] = output.clone();
- }
- return generated;
-}
-
-// === CHARACTER ENCODING (avoids Codebook key-lifetime bug) ===
-
-/// Deterministic character-to-Hypervector mapping using random seeds
-/// Each ASCII char maps to a unique, reproducible hypervector
-fn charToHV(dim: usize, c: u8) Hypervector {
- return Hypervector.random(dim, @as(u64, c) * 7919 + 12345);
-}
-
-/// Decode a hypervector to the nearest printable ASCII character
-fn hvToChar(dim: usize, hv: *Hypervector) u8 {
- var best_sim: f64 = -2.0;
- var best_char: u8 = '?';
- for (32..127) |c| {
- var candidate = charToHV(dim, @intCast(c));
- const sim = hv.similarity(&candidate);
- if (sim > best_sim) {
- best_sim = sim;
- best_char = @intCast(c);
- }
- }
- return best_char;
-}
-
-// === TEMPERATURE + TOP-K SAMPLING (v2.36) ===
-//
-// Greedy decoding (hvToChar) always picks the single highest-similarity char,
-// causing degenerate repetition ("tututu..."). Temperature + top-K sampling
-// introduces controlled randomness:
-// 1. Compute similarity for all 95 printable ASCII chars
-// 2. Keep only the top-K candidates (noise filter)
-// 3. Apply temperature scaling to similarities (diversity control)
-// 4. Convert to softmax probabilities
-// 5. Sample from the distribution using PRNG
-
-/// Entry for sorting candidates by similarity
-const CharCandidate = struct {
- char: u8,
- sim: f64,
-};
-
-/// Decode a hypervector to a character using temperature + top-K sampling.
-/// temperature: controls diversity (0.1 = greedy, 1.0 = balanced, 2.0 = random)
-/// top_k: number of candidates to consider (1 = greedy, 95 = all)
-fn hvToCharSampled(
- dim: usize,
- hv: *Hypervector,
- temperature: f64,
- top_k: usize,
- prng_seed: u64,
-) u8 {
- // Special case: temperature near 0 or top_k=1 β greedy
- if (temperature < 0.01 or top_k <= 1) {
- return hvToChar(dim, hv);
- }
-
- const num_chars: usize = 95; // printable ASCII 32..127
- var candidates: [95]CharCandidate = undefined;
-
- // Compute all similarities
- for (0..num_chars) |i| {
- const c: u8 = @intCast(i + 32);
- var candidate_hv = charToHV(dim, c);
- candidates[i] = .{
- .char = c,
- .sim = hv.similarity(&candidate_hv),
- };
- }
-
- // Sort by similarity descending (simple insertion sort, only 95 elements)
- for (1..num_chars) |i| {
- const key = candidates[i];
- var j: usize = i;
- while (j > 0 and candidates[j - 1].sim < key.sim) {
- candidates[j] = candidates[j - 1];
- j -= 1;
- }
- candidates[j] = key;
- }
-
- // Keep only top-K
- const k = @min(top_k, num_chars);
-
- // Apply temperature scaling and compute softmax
- // First find max for numerical stability
- var max_sim: f64 = candidates[0].sim;
- for (1..k) |i| {
- if (candidates[i].sim > max_sim) max_sim = candidates[i].sim;
- }
-
- var exp_sums: [95]f64 = undefined;
- var total_exp: f64 = 0;
- for (0..k) |i| {
- const scaled = (candidates[i].sim - max_sim) / temperature;
- // Clamp to avoid overflow
- const clamped = @max(scaled, -20.0);
- exp_sums[i] = @exp(clamped);
- total_exp += exp_sums[i];
- }
-
- // Normalize to probabilities
- if (total_exp > 0) {
- for (0..k) |i| {
- exp_sums[i] /= total_exp;
- }
- } else {
- // Uniform fallback
- for (0..k) |i| {
- exp_sums[i] = 1.0 / @as(f64, @floatFromInt(k));
- }
- }
-
- // Sample from distribution using PRNG
- var prng = std.Random.DefaultPrng.init(prng_seed);
- const random = prng.random();
- const r = random.float(f64);
-
- var cumulative: f64 = 0;
- for (0..k) |i| {
- cumulative += exp_sums[i];
- if (r < cumulative) {
- return candidates[i].char;
- }
- }
-
- // Fallback: return last candidate in top-K
- return candidates[k - 1].char;
-}
-
-/// Autoregressive generation with hybrid forward + temperature sampling
-fn generateWithHybridSampled(
- initial_context: []Hypervector,
- role: *Hypervector,
- dim: usize,
- last_char_init: u8,
- counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- output_buf: []u8,
- max_tokens: usize,
- temperature: f64,
- top_k: usize,
- base_seed: u64,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var last_char = last_char_init;
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassHybrid(&context, role, dim, last_char, counts);
- // Use sampled decoding with per-token seed for reproducibility
- const decoded = hvToCharSampled(dim, &output, temperature, top_k, base_seed + generated);
- output_buf[generated] = decoded;
- last_char = decoded;
- generated += 1;
-
- // Shift context window
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- // Use the HV of the decoded character (not the raw output) for clean autoregression
- context[7] = charToHV(dim, decoded);
- }
- return generated;
-}
-
-// === MULTI-ROLE POSITION-SPECIFIC (v2.37) ===
-//
-// Instead of 1 global role, learn 8 separate roles β one per context position.
-// Each role captures "what does character at position i predict about the next char?"
-//
-// Training: for each sample and each position i:
-// ideal_role_i = unbind(target, permute(context[i], i))
-// role_i = bundle(all ideal_role_i across samples)
-//
-// Inference: for each position i:
-// pred_i = bind(permute(context[i], i), role_i)
-// output = bundle(pred_0, pred_1, ..., pred_7) via sequential bundle
-//
-// This is more expressive: each position independently contributes to prediction.
-
-/// Compute 8 position-specific roles from training data.
-/// For each position i, the role captures what that position predicts about the next char.
-fn computeMultiRoles(
- corpus: []const u8,
- dim: usize,
- offsets: []const usize,
- context_size: usize,
-) [8]Hypervector {
- var roles: [8]Hypervector = undefined;
- var first: [8]bool = undefined;
- for (0..8) |i| {
- roles[i] = Hypervector.init(dim);
- first[i] = true;
- }
-
- for (offsets) |s| {
- if (s + context_size >= corpus.len) continue;
-
- var target = charToHV(dim, corpus[s + context_size]);
-
- for (0..context_size) |i| {
- var ctx_hv = charToHV(dim, corpus[s + i]);
- var positioned = ctx_hv.permute(i);
- // ideal_role_i = unbind(target, positioned)
- var ideal = target.unbind(&positioned);
-
- if (first[i]) {
- roles[i] = ideal;
- first[i] = false;
- } else {
- roles[i] = roles[i].bundle(&ideal);
- }
- }
- }
-
- return roles;
-}
-
-/// Multi-role forward pass: each position contributes independently.
-/// output = bundle(bind(permute(ctx[0], 0), role_0), ..., bind(permute(ctx[7], 7), role_7))
-fn forwardPassMultiRole(
- context: []Hypervector,
- roles: *[8]Hypervector,
-) Hypervector {
- var pos0 = context[0].permute(0);
- var result = pos0.bind(&roles[0]);
-
- for (1..context.len) |i| {
- var positioned = context[i].permute(i);
- var pred_i = positioned.bind(&roles[i]);
- result = result.bundle(&pred_i);
- }
-
- return result;
-}
-
-/// Multi-role + Hebbian hybrid forward pass.
-/// Combines position-specific role predictions with bigram Hebbian lookup.
-fn forwardPassMultiRoleHybrid(
- context: []Hypervector,
- roles: *[8]Hypervector,
- dim: usize,
- last_char: u8,
- counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
-) Hypervector {
- var multi_pred = forwardPassMultiRole(context, roles);
-
- if (last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS) {
- const char_idx = last_char - HEBBIAN_OFFSET;
- var hebbian_pred = hebbianLookup(dim, char_idx, counts);
- return multi_pred.bundle(&hebbian_pred);
- }
-
- return multi_pred;
-}
-
-/// Autoregressive generation with multi-role + Hebbian + sampling.
-fn generateWithMultiRoleSampled(
- initial_context: []Hypervector,
- roles: *[8]Hypervector,
- dim: usize,
- last_char_init: u8,
- counts: *const [HEBBIAN_CHARS][HEBBIAN_CHARS]u16,
- output_buf: []u8,
- max_tokens: usize,
- temperature: f64,
- top_k: usize,
- base_seed: u64,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var last_char = last_char_init;
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassMultiRoleHybrid(&context, roles, dim, last_char, counts);
- const decoded = hvToCharSampled(dim, &output, temperature, top_k, base_seed + generated);
- output_buf[generated] = decoded;
- last_char = decoded;
- generated += 1;
-
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- context[7] = charToHV(dim, decoded);
- }
- return generated;
-}
-
-/// Autoregressive generation using charToHV/hvToChar (no Codebook needed)
-fn generateWithCharTable(
- initial_context: []Hypervector,
- roles: *[11]Hypervector,
- dim: usize,
- output_buf: []u8,
- max_tokens: usize,
-) usize {
- var context: [8]Hypervector = undefined;
- for (initial_context, 0..) |*hv, i| {
- context[i] = hv.clone();
- }
-
- var generated: usize = 0;
- while (generated < max_tokens and generated < output_buf.len) {
- var output = forwardPassMultiHead(&context, roles);
- output_buf[generated] = hvToChar(dim, &output);
- generated += 1;
-
- // Shift context left, append output
- for (0..7) |i| {
- context[i] = context[i + 1];
- }
- context[7] = output.clone();
- }
- return generated;
-}
-
-// === TESTS ===
-
-test "forward pass produces non-null output" {
- const allocator = std.testing.allocator;
-
- const dim: usize = 256;
- var codebook = Codebook.init(allocator, dim);
- defer codebook.deinit();
-
- // Encode "To be or" β 8 characters
- const text = "To be or";
- var hvs: [8]Hypervector = undefined;
- for (text, 0..) |c, i| {
- const hv_ptr = try codebook.encode(&[_]u8{c});
- hvs[i] = hv_ptr.clone();
- }
-
- // Create roles and run forward pass
- var roles = initRoles(dim, 42);
- var output = forwardPass(&hvs, &roles);
-
- // Decode prediction
- const predicted = codebook.decode(&output);
-
- // Verify: output is non-trivial (has non-zero trits)
- const d = output.density();
- try std.testing.expect(d > 0.0);
-
- // Log results
- std.debug.print("\n=== MINIMAL FORWARD PASS RESULTS ===\n", .{});
- std.debug.print("Input: \"{s}\"\n", .{text});
- std.debug.print("Output density: {d:.4}\n", .{d});
- if (predicted) |p| {
- std.debug.print("Predicted next: '{s}'\n", .{p});
- } else {
- std.debug.print("Predicted next: (no match above threshold)\n", .{});
- }
- std.debug.print("====================================\n", .{});
-}
-
-test "role vectors are quasi-orthogonal" {
- const dim: usize = 256;
- var roles = initRoles(dim, 42);
-
- // Check all 55 pairs of 11 roles
- var max_sim: f64 = 0;
- for (0..11) |i| {
- for ((i + 1)..11) |j| {
- const sim = @abs(roles[i].similarity(&roles[j]));
- if (sim > max_sim) max_sim = sim;
- }
- }
-
- std.debug.print("\nMax role pair |cosine|: {d:.4}\n", .{max_sim});
- // Random 256D ternary vectors: expected |cos| < 0.3
- try std.testing.expect(max_sim < 0.3);
-}
-
-test "pack and unpack trits round-trip" {
- const dim: usize = 256;
- var hv = Hypervector.random(dim, 12345);
-
- // Pack: 5 trits per byte β ceil(256/5) = 52 bytes
- var packed_bytes: [52]u8 = undefined;
- for (0..52) |byte_idx| {
- var byte_val: u8 = 0;
- for (0..5) |k| {
- const trit_idx = byte_idx * 5 + k;
- if (trit_idx < dim) {
- const t = hv.get(trit_idx);
- // Map trit {-1,0,+1} to {0,1,2}
- const mapped: u8 = @intCast(t + 1);
- var multiplier: u8 = 1;
- for (0..k) |_| multiplier *= 3;
- byte_val += mapped * multiplier;
- }
- }
- packed_bytes[byte_idx] = byte_val;
- }
-
- // Unpack
- var unpacked = Hypervector.init(dim);
- for (0..52) |byte_idx| {
- var remaining = packed_bytes[byte_idx];
- for (0..5) |k| {
- const trit_idx = byte_idx * 5 + k;
- if (trit_idx < dim) {
- const mapped: i8 = @intCast(remaining % 3);
- unpacked.set(trit_idx, mapped - 1);
- remaining /= 3;
- }
- }
- }
-
- // Verify every trit matches
- for (0..dim) |i| {
- try std.testing.expectEqual(hv.get(i), unpacked.get(i));
- }
-
- // Cosine similarity must be 1.0
- const sim = hv.similarity(&unpacked);
- try std.testing.expectApproxEqAbs(sim, 1.0, 1e-10);
-}
-
-test "BFT majority vote rejects minority" {
- // 8 honest random vectors, 2 adversarial
- var honest: [8]Hypervector = undefined;
- for (0..8) |i| {
- honest[i] = Hypervector.random(256, i + 1000);
- }
-
- var adversarial: [2]Hypervector = undefined;
- adversarial[0] = Hypervector.random(256, 99999);
- adversarial[1] = Hypervector.random(256, 99998);
-
- // Bundle honest only (sequential pairwise)
- var honest_agg = honest[0];
- for (1..8) |i| {
- honest_agg = honest_agg.bundle(&honest[i]);
- }
-
- // Bundle all 10 (8 honest + 2 adversarial)
- var all_agg = honest[0];
- for (1..8) |i| {
- all_agg = all_agg.bundle(&honest[i]);
- }
- all_agg = all_agg.bundle(&adversarial[0]);
- all_agg = all_agg.bundle(&adversarial[1]);
-
- // With bundle2 (pairwise majority vote), each addition degrades the signal.
- // 8:2 honest majority should produce positive similarity but bundle2 is lossy.
- // The key test: adversarial vectors should NOT flip the aggregate direction.
- const similarity = honest_agg.similarity(&all_agg);
- std.debug.print("\nBFT honest vs all similarity: {d:.4}\n", .{similarity});
- // With pairwise bundle2, 8 honest + 2 adversarial: sim > 0.0 proves honest majority preserved
- try std.testing.expect(similarity > 0.0);
-}
-
-test "multi-head attention produces valid output" {
- const allocator = std.testing.allocator;
- const dim: usize = 256;
-
- var codebook = Codebook.init(allocator, dim);
- defer codebook.deinit();
-
- const text = "To be or";
- var hvs: [8]Hypervector = undefined;
- for (text, 0..) |c, i| {
- const hv_ptr = try codebook.encode(&[_]u8{c});
- hvs[i] = hv_ptr.clone();
- }
-
- var roles = initRoles(dim, 42);
-
- // Single-head vs multi-head
- var single_out = forwardPass(&hvs, &roles);
- var multi_out = forwardPassMultiHead(&hvs, &roles);
-
- const single_density = single_out.density();
- const multi_density = multi_out.density();
-
- // Both should produce non-degenerate output
- try std.testing.expect(single_density > 0.0);
- try std.testing.expect(multi_density > 0.0);
-
- // Multi-head output should differ from single-head (uses different role subsets)
- const cross_sim = single_out.similarity(&multi_out);
-
- std.debug.print("\n=== MULTI-HEAD vs SINGLE-HEAD ===\n", .{});
- std.debug.print("Single-head density: {d:.4}\n", .{single_density});
- std.debug.print("Multi-head density: {d:.4}\n", .{multi_density});
- std.debug.print("Cross-similarity: {d:.4}\n", .{cross_sim});
-
- const predicted_single = codebook.decode(&single_out);
- const predicted_multi = codebook.decode(&multi_out);
- if (predicted_single) |p| {
- std.debug.print("Single-head predicted: '{s}'\n", .{p});
- }
- if (predicted_multi) |p| {
- std.debug.print("Multi-head predicted: '{s}'\n", .{p});
- }
- std.debug.print("=================================\n", .{});
-}
-
-test "autoregressive generates tokens" {
- const allocator = std.testing.allocator;
- const dim: usize = 256;
-
- var codebook = Codebook.init(allocator, dim);
- defer codebook.deinit();
-
- const text = "To be or";
- var hvs: [8]Hypervector = undefined;
- for (text, 0..) |c, i| {
- const hv_ptr = try codebook.encode(&[_]u8{c});
- hvs[i] = hv_ptr.clone();
- }
-
- var roles = initRoles(dim, 42);
-
- // Generate 20 tokens autoregressively
- var gen_buf: [20]u8 = undefined;
- const gen_count = generateAutoregressive(&hvs, &roles, &codebook, &gen_buf, 20);
-
- try std.testing.expect(gen_count == 20);
-
- // Count unique characters in output
- var seen = [_]bool{false} ** 256;
- var unique: usize = 0;
- for (gen_buf[0..gen_count]) |c| {
- if (!seen[c]) {
- seen[c] = true;
- unique += 1;
- }
- }
-
- std.debug.print("\n=== AUTOREGRESSIVE GENERATION ===\n", .{});
- std.debug.print("Input: \"{s}\"\n", .{text});
- std.debug.print("Generated {d} tokens: \"{s}\"\n", .{ gen_count, gen_buf[0..gen_count] });
- std.debug.print("Unique chars: {d}\n", .{unique});
- std.debug.print("=================================\n", .{});
-
- // Output should contain at least 1 character (non-degenerate)
- try std.testing.expect(gen_count > 0);
-}
-
-test "training with multi-head and loss tracking" {
- const dim: usize = 256;
- const num_epochs: usize = 20;
-
- // 3 training samples: different context β different target
- const sample_seeds = [3][8]u64{
- .{ 100, 101, 102, 103, 104, 105, 106, 107 },
- .{ 200, 201, 202, 203, 204, 205, 206, 207 },
- .{ 300, 301, 302, 303, 304, 305, 306, 307 },
- };
- const target_seeds = [3]u64{ 150, 250, 350 };
-
- var samples: [3][8]Hypervector = undefined;
- var targets: [3]Hypervector = undefined;
- for (0..3) |s| {
- for (0..8) |i| {
- samples[s][i] = Hypervector.random(dim, sample_seeds[s][i]);
- }
- targets[s] = Hypervector.random(dim, target_seeds[s]);
- }
-
- var roles = initRoles(dim, 42);
-
- // Track loss per epoch: loss = avg(1 - similarity(output, target))
- var loss_first: f64 = 0;
- var loss_last: f64 = 0;
-
- std.debug.print("\n=== TRAINING CONVERGENCE ({d} epochs, 3 samples) ===\n", .{num_epochs});
-
- for (0..num_epochs) |epoch| {
- var epoch_loss: f64 = 0;
-
- for (0..3) |s| {
- var output = forwardPassMultiHead(&samples[s], &roles);
- const sim = output.similarity(&targets[s]);
- epoch_loss += 1.0 - sim;
-
- // Error correction
- var neg_output = output.negate();
- var error_hv = targets[s].bundle(&neg_output);
-
- // Sparsify with learning rate 0.3
- var sparse_error = error_hv.clone();
- var prng = std.Random.DefaultPrng.init(epoch * 3 + s + 1000);
- const random = prng.random();
- for (0..dim) |idx| {
- if (random.float(f64) > 0.3) {
- sparse_error.set(idx, 0);
- }
- }
-
- // Update roles
- for (0..11) |r| {
- roles[r] = roles[r].bundle(&sparse_error);
- }
- }
-
- epoch_loss /= 3.0;
- if (epoch == 0) loss_first = epoch_loss;
- if (epoch == num_epochs - 1) loss_last = epoch_loss;
-
- if (epoch < 3 or epoch == num_epochs - 1) {
- std.debug.print(" Epoch {d:2}: avg_loss={d:.4}\n", .{ epoch, epoch_loss });
- } else if (epoch == 3) {
- std.debug.print(" ...\n", .{});
- }
- }
-
- std.debug.print(" Loss first epoch: {d:.4}\n", .{loss_first});
- std.debug.print(" Loss last epoch: {d:.4}\n", .{loss_last});
- std.debug.print(" Delta: {d:.4}\n", .{loss_last - loss_first});
- std.debug.print("================================================\n", .{});
-
- // The training mechanism should execute without crash
- // Loss values should be in reasonable range [0, 2]
- try std.testing.expect(loss_first >= 0.0 and loss_first <= 2.0);
- try std.testing.expect(loss_last >= 0.0 and loss_last <= 2.0);
-}
-
-test "real corpus training and generation" {
- const dim: usize = 256;
- const num_epochs: usize = 50;
-
- // Real text corpus β Shakespeare snippet
- const corpus = "to be or not to be that is the question whether";
- // Use 8 evenly spaced samples to avoid stack overflow from huge arrays
- const sample_count = 8;
- const sample_offsets = [8]usize{ 0, 5, 10, 15, 20, 25, 30, 35 };
-
- var roles = initRoles(dim, 42);
-
- // Training loop: re-encode each sample on the fly (charToHV is cheap)
- var loss_epoch0: f64 = 0;
- var loss_final: f64 = 0;
-
- std.debug.print("\n=== REAL CORPUS TRAINING ({d} epochs, {d} samples) ===\n", .{ num_epochs, sample_count });
- std.debug.print("Corpus: \"{s}\"\n", .{corpus});
-
- for (0..num_epochs) |epoch| {
- var epoch_loss: f64 = 0;
-
- for (sample_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
-
- // Encode context on-the-fly
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
-
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
- epoch_loss += 1.0 - sim;
-
- // Error correction
- var neg_output = output.negate();
- var error_hv = target.bundle(&neg_output);
-
- // Sparsify: keep 30% of trits (lr=0.3)
- var sparse_error = error_hv.clone();
- var prng = std.Random.DefaultPrng.init(epoch * sample_count + s + 5000);
- const random = prng.random();
- for (0..dim) |idx| {
- if (random.float(f64) > 0.3) {
- sparse_error.set(idx, 0);
- }
- }
-
- // Update all 11 roles
- for (0..11) |r| {
- roles[r] = roles[r].bundle(&sparse_error);
- }
- }
-
- epoch_loss /= @as(f64, @floatFromInt(sample_count));
- if (epoch == 0) loss_epoch0 = epoch_loss;
- if (epoch == num_epochs - 1) loss_final = epoch_loss;
-
- if (epoch < 3 or epoch % 10 == 0 or epoch == num_epochs - 1) {
- std.debug.print(" Epoch {d:3}: avg_loss={d:.4}\n", .{ epoch, epoch_loss });
- }
- }
-
- const loss_drop_pct = if (loss_epoch0 > 0) (loss_epoch0 - loss_final) / loss_epoch0 * 100.0 else 0;
- std.debug.print(" Loss epoch 0: {d:.4}\n", .{loss_epoch0});
- std.debug.print(" Loss epoch {d}: {d:.4}\n", .{ num_epochs - 1, loss_final });
- std.debug.print(" Drop: {d:.1}%\n", .{loss_drop_pct});
-
- // Generate 20 tokens after training
- var seed_context: [8]Hypervector = undefined;
- const seed_text = "to be or";
- for (seed_text, 0..) |c, i| {
- seed_context[i] = charToHV(dim, c);
- }
-
- var gen_buf: [20]u8 = undefined;
- const gen_count = generateWithCharTable(&seed_context, &roles, dim, &gen_buf, 20);
-
- // Count unique chars
- var seen = [_]bool{false} ** 256;
- var unique: usize = 0;
- for (gen_buf[0..gen_count]) |c| {
- if (!seen[c]) {
- seen[c] = true;
- unique += 1;
- }
- }
-
- std.debug.print("\n After training generation:\n", .{});
- std.debug.print(" Prompt: \"{s}\"\n", .{seed_text});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
- std.debug.print("=============================================\n", .{});
-
- // Loss must be in valid range
- try std.testing.expect(loss_epoch0 >= 0.0 and loss_epoch0 <= 2.0);
- try std.testing.expect(loss_final >= 0.0 and loss_final <= 2.0);
- // Generation must produce output
- try std.testing.expect(gen_count == 20);
-}
-
-test "perplexity measurement" {
- const dim: usize = 256;
-
- // Use a trained model β train briefly then measure
- const corpus = "to be or not to be that is the question whether";
- const sample_count = corpus.len - 8;
-
- var roles = initRoles(dim, 42);
-
- // Train 30 epochs
- for (0..30) |epoch| {
- for (0..@min(sample_count, 64)) |s| {
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- var neg_output = output.negate();
- var error_hv = target.bundle(&neg_output);
-
- var sparse_error = error_hv.clone();
- var prng = std.Random.DefaultPrng.init(epoch * 64 + s + 9000);
- const random = prng.random();
- for (0..dim) |idx| {
- if (random.float(f64) > 0.3) {
- sparse_error.set(idx, 0);
- }
- }
- for (0..11) |r| {
- roles[r] = roles[r].bundle(&sparse_error);
- }
- }
- }
-
- // Measure perplexity on last 10 positions
- // PPL = exp(-1/N * sum(log(P(correct))))
- // P(correct) approximated as: (1 + similarity(output, target)) / 2
- const eval_start = @min(sample_count, 64) - 10;
- const eval_count = 10;
- var sum_log_prob: f64 = 0;
-
- for (0..eval_count) |e| {
- const s = eval_start + e;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
-
- // Map similarity [-1,1] to probability (0,1)
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10); // avoid log(0)
- sum_log_prob += @log(clamped);
- }
-
- const avg_log_prob = sum_log_prob / @as(f64, @floatFromInt(eval_count));
- const perplexity = @exp(-avg_log_prob);
-
- std.debug.print("\n=== PERPLEXITY MEASUREMENT ===\n", .{});
- std.debug.print("Eval samples: {d}\n", .{eval_count});
- std.debug.print("Avg log prob: {d:.4}\n", .{avg_log_prob});
- std.debug.print("Perplexity: {d:.1}\n", .{perplexity});
- std.debug.print("==============================\n", .{});
-
- // Perplexity must be finite and positive
- try std.testing.expect(perplexity > 0.0);
- try std.testing.expect(!std.math.isNan(perplexity));
- try std.testing.expect(!std.math.isInf(perplexity));
-}
-
-test "scaled corpus training with honest split and LR decay" {
- const dim: usize = 256;
- const num_epochs: usize = 200;
-
- // 512-char Shakespeare corpus β significantly larger than v2.31's 48 chars
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- // Honest split: train on first 70%, eval on next 15%, test on last 15%
- const total_samples = corpus.len - 8; // each sample = 8 context + 1 target
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // Use 12 evenly-spaced offsets from train region (avoid stack overflow)
- const train_sample_count = 12;
- var train_offsets: [12]usize = undefined;
- for (0..train_sample_count) |i| {
- train_offsets[i] = i * train_end / train_sample_count;
- }
-
- // 6 eval offsets from eval region
- const eval_sample_count = 6;
- const eval_region_size = eval_end - train_end;
- var eval_offsets: [6]usize = undefined;
- for (0..eval_sample_count) |i| {
- eval_offsets[i] = train_end + i * eval_region_size / eval_sample_count;
- }
-
- // 6 test offsets from test region
- const test_sample_count = 6;
- const test_region_size = total_samples - eval_end;
- var test_offsets: [6]usize = undefined;
- for (0..test_sample_count) |i| {
- test_offsets[i] = eval_end + i * test_region_size / test_sample_count;
- }
-
- var roles = initRoles(dim, 42);
-
- var loss_epoch0: f64 = 0;
- var loss_final: f64 = 0;
- var eval_loss_best: f64 = 999.0;
-
- std.debug.print("\n=== SCALED CORPUS TRAINING ({d} epochs, corpus={d} chars) ===\n", .{ num_epochs, corpus.len });
- std.debug.print("Split: train {d} | eval {d} | test {d} samples\n", .{ train_sample_count, eval_sample_count, test_sample_count });
-
- for (0..num_epochs) |epoch| {
- // Learning rate decay: lr = 0.3 * 0.99^epoch
- var lr_prng = std.Random.DefaultPrng.init(epoch * 31337);
- const lr_rand = lr_prng.random();
- _ = lr_rand;
- const base_lr: f64 = 0.3;
- var lr: f64 = base_lr;
- for (0..epoch) |_| {
- lr *= 0.99;
- }
- // Clamp LR to minimum 0.05
- if (lr < 0.05) lr = 0.05;
-
- var epoch_loss: f64 = 0;
- var samples_used: usize = 0;
-
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
-
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
- epoch_loss += 1.0 - sim;
- samples_used += 1;
-
- // Error correction with decayed LR
- var neg_output = output.negate();
- var error_hv = target.bundle(&neg_output);
-
- var sparse_error = error_hv.clone();
- var prng = std.Random.DefaultPrng.init(epoch * train_sample_count + s + 20000);
- const random = prng.random();
- for (0..dim) |idx| {
- if (random.float(f64) > lr) {
- sparse_error.set(idx, 0);
- }
- }
-
- for (0..11) |r| {
- roles[r] = roles[r].bundle(&sparse_error);
- }
- }
-
- if (samples_used > 0) {
- epoch_loss /= @as(f64, @floatFromInt(samples_used));
- }
- if (epoch == 0) loss_epoch0 = epoch_loss;
- if (epoch == num_epochs - 1) loss_final = epoch_loss;
-
- // Eval loss (no updates)
- if (epoch % 20 == 0 or epoch == num_epochs - 1) {
- var el: f64 = 0;
- var eval_used: usize = 0;
- for (eval_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
- el += 1.0 - sim;
- eval_used += 1;
- }
- if (eval_used > 0) el /= @as(f64, @floatFromInt(eval_used));
- if (el < eval_loss_best) eval_loss_best = el;
-
- std.debug.print(" Epoch {d:3}: train_loss={d:.4} eval_loss={d:.4} lr={d:.4}\n", .{ epoch, epoch_loss, el, lr });
- }
- }
-
- const loss_drop_pct = if (loss_epoch0 > 0) (loss_epoch0 - loss_final) / loss_epoch0 * 100.0 else 0;
- std.debug.print(" Train loss epoch 0: {d:.4}\n", .{loss_epoch0});
- std.debug.print(" Train loss epoch {d}: {d:.4}\n", .{ num_epochs - 1, loss_final });
- std.debug.print(" Train drop: {d:.1}%\n", .{loss_drop_pct});
- std.debug.print(" Best eval loss: {d:.4}\n", .{eval_loss_best});
-
- // Generate 30 tokens after training
- var seed_context: [8]Hypervector = undefined;
- const seed_text = "to be or";
- for (seed_text, 0..) |c, i| {
- seed_context[i] = charToHV(dim, c);
- }
-
- var gen_buf: [30]u8 = undefined;
- const gen_count = generateWithCharTable(&seed_context, &roles, dim, &gen_buf, 30);
-
- var seen = [_]bool{false} ** 256;
- var unique: usize = 0;
- for (gen_buf[0..gen_count]) |c| {
- if (!seen[c]) {
- seen[c] = true;
- unique += 1;
- }
- }
-
- std.debug.print("\n Generation after scaled training:\n", .{});
- std.debug.print(" Prompt: \"{s}\"\n", .{seed_text});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(loss_epoch0 >= 0.0 and loss_epoch0 <= 2.0);
- try std.testing.expect(loss_final >= 0.0 and loss_final <= 2.0);
- try std.testing.expect(gen_count == 30);
-}
-
-test "honest perplexity on held-out test data" {
- const dim: usize = 256;
-
- // Same 512-char corpus, but train only on first 70%, measure PPL on last 15%
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // Train on 12 offsets from train region, 100 epochs with LR decay
- var roles = initRoles(dim, 42);
-
- for (0..100) |epoch| {
- var lr: f64 = 0.3;
- for (0..epoch) |_| lr *= 0.99;
- if (lr < 0.05) lr = 0.05;
-
- for (0..12) |i| {
- const s = i * train_end / 12;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
-
- var neg_output = output.negate();
- var error_hv = target.bundle(&neg_output);
-
- var sparse_error = error_hv.clone();
- var prng = std.Random.DefaultPrng.init(epoch * 12 + i + 30000);
- const random = prng.random();
- for (0..dim) |idx| {
- if (random.float(f64) > lr) {
- sparse_error.set(idx, 0);
- }
- }
- for (0..11) |r| {
- roles[r] = roles[r].bundle(&sparse_error);
- }
- }
- }
-
- // Measure perplexity on TEST region (last 15%) β truly held-out
- const test_start = eval_end;
- const test_count = 8; // 8 test samples from the test region
- var sum_log_prob: f64 = 0;
- var valid_samples: usize = 0;
-
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- sum_log_prob += @log(clamped);
- valid_samples += 1;
- }
-
- const avg_log_prob = sum_log_prob / @as(f64, @floatFromInt(valid_samples));
- const perplexity = @exp(-avg_log_prob);
-
- // Also measure train perplexity for comparison (to show overfit gap)
- var train_sum_log: f64 = 0;
- var train_valid: usize = 0;
- for (0..8) |i| {
- const s = i * train_end / 8;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- train_sum_log += @log(clamped);
- train_valid += 1;
- }
-
- const train_avg_log = train_sum_log / @as(f64, @floatFromInt(train_valid));
- const train_ppl = @exp(-train_avg_log);
-
- std.debug.print("\n=== HONEST PERPLEXITY (held-out test set) ===\n", .{});
- std.debug.print("Train PPL: {d:.1} (on {d} train samples)\n", .{ train_ppl, train_valid });
- std.debug.print("Test PPL: {d:.1} (on {d} held-out samples)\n", .{ perplexity, valid_samples });
- std.debug.print("Overfit gap: {d:.1}\n", .{perplexity - train_ppl});
- std.debug.print("Random PPL: 95.0 (printable ASCII baseline)\n", .{});
- std.debug.print("==============================================\n", .{});
-
- // Perplexity must be finite and positive
- try std.testing.expect(perplexity > 0.0);
- try std.testing.expect(!std.math.isNan(perplexity));
- try std.testing.expect(!std.math.isInf(perplexity));
- // Test PPL should be > train PPL (honest = not overfit)
- // (We don't require this to pass since it depends on convergence,
- // but we log it for the report)
-}
-
-test "resonator training on scaled corpus" {
- const dim: usize = 256;
- const num_epochs: usize = 50; // fewer epochs needed β resonator converges faster
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // 12 train offsets, 6 eval, 6 test
- const train_sample_count = 12;
- var train_offsets: [12]usize = undefined;
- for (0..train_sample_count) |i| {
- train_offsets[i] = i * train_end / train_sample_count;
- }
-
- const eval_sample_count = 6;
- const eval_region_size = eval_end - train_end;
- var eval_offsets: [6]usize = undefined;
- for (0..eval_sample_count) |i| {
- eval_offsets[i] = train_end + i * eval_region_size / eval_sample_count;
- }
-
- var roles = initRoles(dim, 42);
-
- var loss_epoch0: f64 = 0;
- var loss_final: f64 = 0;
- var eval_loss_best: f64 = 999.0;
-
- std.debug.print("\n=== RESONATOR TRAINING ({d} epochs, corpus={d} chars) ===\n", .{ num_epochs, corpus.len });
- std.debug.print("Method: bind-based resonator (replaces bundle2)\n", .{});
-
- for (0..num_epochs) |epoch| {
- // LR decay
- var lr: f64 = 0.25;
- for (0..epoch) |_| lr *= 0.98;
- if (lr < 0.05) lr = 0.05;
-
- var epoch_loss: f64 = 0;
- var samples_used: usize = 0;
-
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
-
- // Use resonator training step instead of bundle2
- const sample_loss = resonatorTrainStep(
- &ctx,
- &target,
- &roles,
- dim,
- lr,
- epoch * train_sample_count + s + 40000,
- );
- epoch_loss += sample_loss;
- samples_used += 1;
- }
-
- if (samples_used > 0) {
- epoch_loss /= @as(f64, @floatFromInt(samples_used));
- }
- if (epoch == 0) loss_epoch0 = epoch_loss;
- if (epoch == num_epochs - 1) loss_final = epoch_loss;
-
- // Eval loss every 10 epochs
- if (epoch % 10 == 0 or epoch == num_epochs - 1) {
- var el: f64 = 0;
- var eval_used: usize = 0;
- for (eval_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
- el += 1.0 - sim;
- eval_used += 1;
- }
- if (eval_used > 0) el /= @as(f64, @floatFromInt(eval_used));
- if (el < eval_loss_best) eval_loss_best = el;
-
- std.debug.print(" Epoch {d:3}: train_loss={d:.4} eval_loss={d:.4} lr={d:.4}\n", .{ epoch, epoch_loss, el, lr });
- }
- }
-
- const loss_drop_pct = if (loss_epoch0 > 0) (loss_epoch0 - loss_final) / loss_epoch0 * 100.0 else 0;
- std.debug.print(" Train loss epoch 0: {d:.4}\n", .{loss_epoch0});
- std.debug.print(" Train loss epoch {d}: {d:.4}\n", .{ num_epochs - 1, loss_final });
- std.debug.print(" Resonator drop: {d:.1}%\n", .{loss_drop_pct});
- std.debug.print(" Best eval loss: {d:.4}\n", .{eval_loss_best});
-
- // Generate 30 tokens after resonator training
- var seed_context: [8]Hypervector = undefined;
- const seed_text = "to be or";
- for (seed_text, 0..) |c, i| {
- seed_context[i] = charToHV(dim, c);
- }
-
- var gen_buf: [30]u8 = undefined;
- const gen_count = generateWithCharTable(&seed_context, &roles, dim, &gen_buf, 30);
-
- var seen = [_]bool{false} ** 256;
- var unique: usize = 0;
- for (gen_buf[0..gen_count]) |c| {
- if (!seen[c]) {
- seen[c] = true;
- unique += 1;
- }
- }
-
- std.debug.print("\n Resonator generation:\n", .{});
- std.debug.print(" Prompt: \"{s}\"\n", .{seed_text});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(loss_epoch0 >= 0.0 and loss_epoch0 <= 2.0);
- try std.testing.expect(loss_final >= 0.0 and loss_final <= 2.0);
- try std.testing.expect(gen_count == 30);
-}
-
-test "resonator perplexity comparison" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // Train with resonator for 50 epochs
- var roles = initRoles(dim, 42);
-
- for (0..50) |epoch| {
- var lr: f64 = 0.25;
- for (0..epoch) |_| lr *= 0.98;
- if (lr < 0.05) lr = 0.05;
-
- for (0..12) |i| {
- const s = i * train_end / 12;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
-
- _ = resonatorTrainStep(&ctx, &target, &roles, dim, lr, epoch * 12 + i + 50000);
- }
- }
-
- // Measure PPL on test region (held-out)
- const test_start = eval_end;
- const test_count = 8;
- var test_sum_log: f64 = 0;
- var test_valid: usize = 0;
-
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- test_sum_log += @log(clamped);
- test_valid += 1;
- }
-
- const test_ppl = @exp(-test_sum_log / @as(f64, @floatFromInt(test_valid)));
-
- // Train PPL for comparison
- var train_sum_log: f64 = 0;
- var train_valid: usize = 0;
- for (0..8) |i| {
- const s = i * train_end / 8;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- train_sum_log += @log(clamped);
- train_valid += 1;
- }
-
- const train_ppl = @exp(-train_sum_log / @as(f64, @floatFromInt(train_valid)));
-
- std.debug.print("\n=== RESONATOR vs BUNDLE2 PERPLEXITY ===\n", .{});
- std.debug.print("Resonator train PPL: {d:.1}\n", .{train_ppl});
- std.debug.print("Resonator test PPL: {d:.1}\n", .{test_ppl});
- std.debug.print("Overfit gap: {d:.1}\n", .{test_ppl - train_ppl});
- std.debug.print("Bundle2 baseline: train=1.9, test=2.0 (v2.32)\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("========================================\n", .{});
-
- try std.testing.expect(test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(test_ppl));
- try std.testing.expect(!std.math.isInf(test_ppl));
-}
-
-test "direct role averaging on scaled corpus" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // Train offsets (from train region)
- const train_sample_count = 20; // more samples since it's one-shot
- var train_offsets: [20]usize = undefined;
- for (0..train_sample_count) |i| {
- train_offsets[i] = i * train_end / train_sample_count;
- }
-
- // Eval offsets
- const eval_sample_count = 8;
- const eval_region_size = eval_end - train_end;
- var eval_offsets: [8]usize = undefined;
- for (0..eval_sample_count) |i| {
- eval_offsets[i] = train_end + i * eval_region_size / eval_sample_count;
- }
-
- // Test offsets
- const test_sample_count = 8;
- const test_region_size = total_samples - eval_end;
- var test_offsets: [8]usize = undefined;
- for (0..test_sample_count) |i| {
- test_offsets[i] = eval_end + i * test_region_size / test_sample_count;
- }
-
- std.debug.print("\n=== DIRECT ROLE AVERAGING (corpus={d} chars) ===\n", .{corpus.len});
- std.debug.print("Method: one-shot ideal_role = bundle(unbind(target, summary))\n", .{});
- std.debug.print("Train samples: {d} | Eval: {d} | Test: {d}\n", .{ train_sample_count, eval_sample_count, test_sample_count });
-
- // Step 1: Compute direct role from training data (one-shot, no iterations)
- var direct_role = computeDirectRole(corpus, dim, &train_offsets, 8);
-
- // Measure train loss with initial direct role
- var train_loss_initial: f64 = 0;
- var train_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassDirect(&ctx, &direct_role);
- const sim = output.similarity(&target);
- train_loss_initial += 1.0 - sim;
- train_count += 1;
- }
- if (train_count > 0) train_loss_initial /= @as(f64, @floatFromInt(train_count));
-
- std.debug.print(" Initial direct role train loss: {d:.4}\n", .{train_loss_initial});
-
- // Step 2: Refine with 10 passes
- direct_role = refineDirectRole(corpus, dim, &train_offsets, 8, &direct_role, 10);
-
- // Measure train loss after refinement
- var train_loss_refined: f64 = 0;
- train_count = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassDirect(&ctx, &direct_role);
- const sim = output.similarity(&target);
- train_loss_refined += 1.0 - sim;
- train_count += 1;
- }
- if (train_count > 0) train_loss_refined /= @as(f64, @floatFromInt(train_count));
-
- // Eval loss
- var eval_loss: f64 = 0;
- var eval_count: usize = 0;
- for (eval_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassDirect(&ctx, &direct_role);
- const sim = output.similarity(&target);
- eval_loss += 1.0 - sim;
- eval_count += 1;
- }
- if (eval_count > 0) eval_loss /= @as(f64, @floatFromInt(eval_count));
-
- const loss_drop_pct = if (train_loss_initial > 0) (train_loss_initial - train_loss_refined) / train_loss_initial * 100.0 else 0;
-
- std.debug.print(" Refined direct role train loss: {d:.4}\n", .{train_loss_refined});
- std.debug.print(" Eval loss: {d:.4}\n", .{eval_loss});
- std.debug.print(" Loss drop (initialβrefined): {d:.1}%\n", .{loss_drop_pct});
-
- // Generate 30 tokens
- var seed_context: [8]Hypervector = undefined;
- const seed_text = "to be or";
- for (seed_text, 0..) |c, i| {
- seed_context[i] = charToHV(dim, c);
- }
-
- var gen_buf: [30]u8 = undefined;
- const gen_count = generateWithDirectRole(&seed_context, &direct_role, dim, &gen_buf, 30);
-
- var seen = [_]bool{false} ** 256;
- var unique: usize = 0;
- for (gen_buf[0..gen_count]) |c| {
- if (!seen[c]) {
- seen[c] = true;
- unique += 1;
- }
- }
-
- std.debug.print("\n Direct role generation:\n", .{});
- std.debug.print(" Prompt: \"{s}\"\n", .{seed_text});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
-
- // Compare with multi-head approach loss
- var roles_mh = initRoles(dim, 42);
- var mh_loss: f64 = 0;
- var mh_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles_mh);
- const sim = output.similarity(&target);
- mh_loss += 1.0 - sim;
- mh_count += 1;
- }
- if (mh_count > 0) mh_loss /= @as(f64, @floatFromInt(mh_count));
-
- std.debug.print("\n Comparison (untrained baselines):\n", .{});
- std.debug.print(" Multi-head (random roles): {d:.4}\n", .{mh_loss});
- std.debug.print(" Direct role (initial): {d:.4}\n", .{train_loss_initial});
- std.debug.print(" Direct role (refined): {d:.4}\n", .{train_loss_refined});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(train_loss_initial >= 0.0 and train_loss_initial <= 2.0);
- try std.testing.expect(train_loss_refined >= 0.0 and train_loss_refined <= 2.0);
- try std.testing.expect(gen_count == 30);
-}
-
-test "direct role perplexity comparison" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // Train with 20 samples, refine 10 passes
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
-
- var direct_role = computeDirectRole(corpus, dim, &train_offsets, 8);
- direct_role = refineDirectRole(corpus, dim, &train_offsets, 8, &direct_role, 10);
-
- // Measure PPL on test region (held-out)
- const test_start = eval_end;
- const test_count = 8;
- var test_sum_log: f64 = 0;
- var test_valid: usize = 0;
-
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassDirect(&ctx, &direct_role);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- test_sum_log += @log(clamped);
- test_valid += 1;
- }
-
- const test_ppl = @exp(-test_sum_log / @as(f64, @floatFromInt(test_valid)));
-
- // Train PPL
- var train_sum_log: f64 = 0;
- var train_valid: usize = 0;
- for (0..8) |i| {
- const s = i * train_end / 8;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassDirect(&ctx, &direct_role);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- train_sum_log += @log(clamped);
- train_valid += 1;
- }
-
- const train_ppl = @exp(-train_sum_log / @as(f64, @floatFromInt(train_valid)));
-
- std.debug.print("\n=== DIRECT ROLE PERPLEXITY (all methods) ===\n", .{});
- std.debug.print("Direct role train PPL: {d:.1}\n", .{train_ppl});
- std.debug.print("Direct role test PPL: {d:.1}\n", .{test_ppl});
- std.debug.print("Overfit gap: {d:.1}\n", .{test_ppl - train_ppl});
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("Bundle2 (v2.32): train=1.9, test=2.0\n", .{});
- std.debug.print("Resonator (v2.33): train=2.0, test=2.0\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(test_ppl));
- try std.testing.expect(!std.math.isInf(test_ppl));
-}
-
-// === v2.35 HEBBIAN HYBRID TESTS ===
-
-test "hebbian hybrid training on scaled corpus" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- std.debug.print("\n=== HEBBIAN HYBRID TRAINING (v2.35) ===\n", .{});
- std.debug.print("Corpus: {d} chars (Shakespeare)\n", .{corpus.len});
- std.debug.print("Method: direct role + Hebbian bigram matrix\n", .{});
-
- // Build Hebbian counts from FULL corpus (pre-training β bigram statistics)
- const counts = buildHebbianCounts(corpus);
-
- // Verify counts are populated
- var total_bigrams: u64 = 0;
- var unique_bigrams: u64 = 0;
- for (0..HEBBIAN_CHARS) |i| {
- for (0..HEBBIAN_CHARS) |j| {
- if (counts[i][j] > 0) {
- total_bigrams += counts[i][j];
- unique_bigrams += 1;
- }
- }
- }
- std.debug.print("Total bigrams: {d}, Unique pairs: {d}\n", .{ total_bigrams, unique_bigrams });
-
- // Honest split: 70/15/15
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // Train offsets (20 samples from train region)
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
-
- // Compute direct role (same as v2.34)
- var direct_role = computeDirectRole(corpus, dim, &train_offsets, 8);
-
- // === Measure HYBRID train loss ===
- var hybrid_train_loss: f64 = 0;
- var hybrid_train_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
- hybrid_train_loss += 1.0 - sim;
- hybrid_train_count += 1;
- }
- if (hybrid_train_count > 0) hybrid_train_loss /= @as(f64, @floatFromInt(hybrid_train_count));
-
- // === Measure DIRECT-ONLY train loss (for comparison) ===
- var direct_train_loss: f64 = 0;
- var direct_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassDirect(&ctx, &direct_role);
- const sim = output.similarity(&target);
- direct_train_loss += 1.0 - sim;
- direct_count += 1;
- }
- if (direct_count > 0) direct_train_loss /= @as(f64, @floatFromInt(direct_count));
-
- // === Measure HYBRID eval loss ===
- var hybrid_eval_loss: f64 = 0;
- var eval_count: usize = 0;
- const eval_samples = 8;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
- hybrid_eval_loss += 1.0 - sim;
- eval_count += 1;
- }
- if (eval_count > 0) hybrid_eval_loss /= @as(f64, @floatFromInt(eval_count));
-
- // === Measure DIRECT-ONLY eval loss (for comparison) ===
- var direct_eval_loss: f64 = 0;
- var direct_eval_count: usize = 0;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassDirect(&ctx, &direct_role);
- const sim = output.similarity(&target);
- direct_eval_loss += 1.0 - sim;
- direct_eval_count += 1;
- }
- if (direct_eval_count > 0) direct_eval_loss /= @as(f64, @floatFromInt(direct_eval_count));
-
- // === Multi-head baseline (random roles) ===
- var roles_mh = initRoles(dim, 42);
- var mh_loss: f64 = 0;
- var mh_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles_mh);
- const sim = output.similarity(&target);
- mh_loss += 1.0 - sim;
- mh_count += 1;
- }
- if (mh_count > 0) mh_loss /= @as(f64, @floatFromInt(mh_count));
-
- // Improvement calculations
- const hybrid_improvement = (mh_loss - hybrid_train_loss) / mh_loss * 100.0;
- const direct_improvement = (mh_loss - direct_train_loss) / mh_loss * 100.0;
- const eval_improvement = (mh_loss - hybrid_eval_loss) / mh_loss * 100.0;
-
- // === Generation ===
- var gen_buf: [30]u8 = undefined;
- var gen_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- gen_ctx[i] = charToHV(dim, corpus[i]);
- }
- const gen_count = generateWithHybrid(&gen_ctx, &direct_role, dim, corpus[7], &counts, &gen_buf, 30);
-
- // Count unique chars in generation
- var seen: [256]bool = undefined;
- for (0..256) |i| {
- seen[i] = false;
- }
- var unique: usize = 0;
- for (0..gen_count) |i| {
- if (!seen[gen_buf[i]]) {
- seen[gen_buf[i]] = true;
- unique += 1;
- }
- }
-
- std.debug.print("\nHybrid train loss: {d:.4}\n", .{hybrid_train_loss});
- std.debug.print("Direct-only train loss: {d:.4}\n", .{direct_train_loss});
- std.debug.print("Multi-head (random, baseline): {d:.4}\n", .{mh_loss});
- std.debug.print("Hybrid improvement over random: {d:.1}%\n", .{hybrid_improvement});
- std.debug.print("Direct improvement over random: {d:.1}%\n", .{direct_improvement});
- std.debug.print("\nHybrid eval loss: {d:.4}\n", .{hybrid_eval_loss});
- std.debug.print("Direct-only eval loss: {d:.4}\n", .{direct_eval_loss});
- std.debug.print("Eval improvement over random: {d:.1}%\n", .{eval_improvement});
- std.debug.print("\nHybrid generation:\n", .{});
- std.debug.print("Prompt: \"to be or \"\n", .{});
- std.debug.print("Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print("Unique chars: {d}\n", .{unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(hybrid_train_loss >= 0.0 and hybrid_train_loss <= 2.0);
- try std.testing.expect(hybrid_eval_loss >= 0.0 and hybrid_eval_loss <= 2.0);
- try std.testing.expect(gen_count == 30);
- try std.testing.expect(unique_bigrams > 0);
-}
-
-test "hebbian hybrid perplexity comparison" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // Build Hebbian counts
- const counts = buildHebbianCounts(corpus);
-
- // Train direct role
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
- var direct_role = computeDirectRole(corpus, dim, &train_offsets, 8);
-
- // === Test PPL (held-out) β Hybrid ===
- const test_start = eval_end;
- const test_count = 8;
- var hybrid_test_log: f64 = 0;
- var hybrid_test_valid: usize = 0;
-
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- hybrid_test_log += @log(clamped);
- hybrid_test_valid += 1;
- }
-
- const hybrid_test_ppl = @exp(-hybrid_test_log / @as(f64, @floatFromInt(hybrid_test_valid)));
-
- // === Train PPL β Hybrid ===
- var hybrid_train_log: f64 = 0;
- var hybrid_train_valid: usize = 0;
- for (0..8) |i| {
- const s = i * train_end / 8;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- hybrid_train_log += @log(clamped);
- hybrid_train_valid += 1;
- }
-
- const hybrid_train_ppl = @exp(-hybrid_train_log / @as(f64, @floatFromInt(hybrid_train_valid)));
-
- std.debug.print("\n=== HEBBIAN HYBRID PERPLEXITY (all methods) ===\n", .{});
- std.debug.print("Hybrid train PPL: {d:.1}\n", .{hybrid_train_ppl});
- std.debug.print("Hybrid test PPL: {d:.1}\n", .{hybrid_test_ppl});
- std.debug.print("Overfit gap: {d:.1}\n", .{hybrid_test_ppl - hybrid_train_ppl});
- std.debug.print("------------------------------------------------\n", .{});
- std.debug.print("Direct (v2.34): train=2.0, test=2.0\n", .{});
- std.debug.print("Bundle2 (v2.32): train=1.9, test=2.0\n", .{});
- std.debug.print("Resonator (v2.33): train=2.0, test=2.0\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("================================================\n", .{});
-
- try std.testing.expect(hybrid_test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(hybrid_test_ppl));
- try std.testing.expect(!std.math.isInf(hybrid_test_ppl));
-}
-
-// === v2.36 SAMPLING TESTS ===
-
-test "temperature top-k sampling diversity" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- std.debug.print("\n=== SAMPLING DIVERSITY TEST (v2.36) ===\n", .{});
- std.debug.print("Corpus: {d} chars (Shakespeare)\n", .{corpus.len});
-
- // Build Hebbian + direct role
- const counts = buildHebbianCounts(corpus);
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
- var direct_role = computeDirectRole(corpus, dim, &train_offsets, 8);
-
- // === Greedy generation (baseline β expected degenerate) ===
- var greedy_buf: [50]u8 = undefined;
- var greedy_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- greedy_ctx[i] = charToHV(dim, corpus[i]);
- }
- const greedy_count = generateWithHybrid(&greedy_ctx, &direct_role, dim, corpus[7], &counts, &greedy_buf, 50);
-
- var greedy_seen: [256]bool = undefined;
- for (0..256) |i| greedy_seen[i] = false;
- var greedy_unique: usize = 0;
- for (0..greedy_count) |i| {
- if (!greedy_seen[greedy_buf[i]]) {
- greedy_seen[greedy_buf[i]] = true;
- greedy_unique += 1;
- }
- }
-
- // === Sampled generation: temperature=0.8, top_k=8 ===
- var sampled_buf: [50]u8 = undefined;
- var sampled_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- sampled_ctx[i] = charToHV(dim, corpus[i]);
- }
- const sampled_count = generateWithHybridSampled(
- &sampled_ctx,
- &direct_role,
- dim,
- corpus[7],
- &counts,
- &sampled_buf,
- 50,
- 0.8,
- 8,
- 42,
- );
-
- var sampled_seen: [256]bool = undefined;
- for (0..256) |i| sampled_seen[i] = false;
- var sampled_unique: usize = 0;
- for (0..sampled_count) |i| {
- if (!sampled_seen[sampled_buf[i]]) {
- sampled_seen[sampled_buf[i]] = true;
- sampled_unique += 1;
- }
- }
-
- // === High temperature generation: temperature=1.5, top_k=16 ===
- var hot_buf: [50]u8 = undefined;
- var hot_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- hot_ctx[i] = charToHV(dim, corpus[i]);
- }
- const hot_count = generateWithHybridSampled(
- &hot_ctx,
- &direct_role,
- dim,
- corpus[7],
- &counts,
- &hot_buf,
- 50,
- 1.5,
- 16,
- 42,
- );
-
- var hot_seen: [256]bool = undefined;
- for (0..256) |i| hot_seen[i] = false;
- var hot_unique: usize = 0;
- for (0..hot_count) |i| {
- if (!hot_seen[hot_buf[i]]) {
- hot_seen[hot_buf[i]] = true;
- hot_unique += 1;
- }
- }
-
- // === Low temperature (near-greedy): temperature=0.1, top_k=3 ===
- var cold_buf: [50]u8 = undefined;
- var cold_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- cold_ctx[i] = charToHV(dim, corpus[i]);
- }
- const cold_count = generateWithHybridSampled(
- &cold_ctx,
- &direct_role,
- dim,
- corpus[7],
- &counts,
- &cold_buf,
- 50,
- 0.1,
- 3,
- 42,
- );
-
- var cold_seen: [256]bool = undefined;
- for (0..256) |i| cold_seen[i] = false;
- var cold_unique: usize = 0;
- for (0..cold_count) |i| {
- if (!cold_seen[cold_buf[i]]) {
- cold_seen[cold_buf[i]] = true;
- cold_unique += 1;
- }
- }
-
- std.debug.print("\nGreedy (baseline):\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{greedy_buf[0..greedy_count]});
- std.debug.print(" Unique chars: {d}\n", .{greedy_unique});
-
- std.debug.print("\nSampled (T=0.8, K=8):\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{sampled_buf[0..sampled_count]});
- std.debug.print(" Unique chars: {d}\n", .{sampled_unique});
-
- std.debug.print("\nHot (T=1.5, K=16):\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{hot_buf[0..hot_count]});
- std.debug.print(" Unique chars: {d}\n", .{hot_unique});
-
- std.debug.print("\nCold (T=0.1, K=3):\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{cold_buf[0..cold_count]});
- std.debug.print(" Unique chars: {d}\n", .{cold_unique});
-
- std.debug.print("\nDiversity comparison:\n", .{});
- std.debug.print(" Greedy: {d} unique chars\n", .{greedy_unique});
- std.debug.print(" Cold: {d} unique chars\n", .{cold_unique});
- std.debug.print(" Sampled: {d} unique chars\n", .{sampled_unique});
- std.debug.print(" Hot: {d} unique chars\n", .{hot_unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(greedy_count == 50);
- try std.testing.expect(sampled_count == 50);
- try std.testing.expect(hot_count == 50);
- try std.testing.expect(cold_count == 50);
- // Sampled should have more diversity than greedy
- try std.testing.expect(sampled_unique >= greedy_unique);
- // Hot should have at least as much diversity as sampled
- try std.testing.expect(hot_unique >= sampled_unique or hot_unique >= greedy_unique);
-}
-
-test "sampling preserves eval signal" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- std.debug.print("\n=== SAMPLING EVAL PRESERVATION (v2.36) ===\n", .{});
-
- const counts = buildHebbianCounts(corpus);
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
- var direct_role = computeDirectRole(corpus, dim, &train_offsets, 8);
-
- // Eval loss is independent of sampling β it uses the raw HV similarities
- // Sampling only affects generation, not the model's loss/PPL measurements
- // So eval loss should be identical to v2.35
-
- // === Hybrid eval loss (same as v2.35) ===
- var hybrid_eval_loss: f64 = 0;
- var eval_count: usize = 0;
- const eval_samples = 8;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
- hybrid_eval_loss += 1.0 - sim;
- eval_count += 1;
- }
- if (eval_count > 0) hybrid_eval_loss /= @as(f64, @floatFromInt(eval_count));
-
- // === Hybrid train loss ===
- var hybrid_train_loss: f64 = 0;
- var train_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
- hybrid_train_loss += 1.0 - sim;
- train_count += 1;
- }
- if (train_count > 0) hybrid_train_loss /= @as(f64, @floatFromInt(train_count));
-
- // Multi-head baseline
- var roles_mh = initRoles(dim, 42);
- var mh_loss: f64 = 0;
- var mh_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles_mh);
- const sim = output.similarity(&target);
- mh_loss += 1.0 - sim;
- mh_count += 1;
- }
- if (mh_count > 0) mh_loss /= @as(f64, @floatFromInt(mh_count));
-
- const train_improvement = (mh_loss - hybrid_train_loss) / mh_loss * 100.0;
- const eval_improvement = (mh_loss - hybrid_eval_loss) / mh_loss * 100.0;
-
- std.debug.print("\nHybrid train loss: {d:.4} ({d:.1}% below random)\n", .{ hybrid_train_loss, train_improvement });
- std.debug.print("Hybrid eval loss: {d:.4} ({d:.1}% below random)\n", .{ hybrid_eval_loss, eval_improvement });
- std.debug.print("Random baseline: {d:.4}\n", .{mh_loss});
- std.debug.print("\nNote: Sampling affects generation diversity only.\n", .{});
- std.debug.print("Loss/PPL metrics use raw HV similarity β unchanged.\n", .{});
- std.debug.print("==============================================\n", .{});
-
- // Eval loss should be below random baseline
- try std.testing.expect(hybrid_eval_loss < mh_loss);
- // Train loss should be below random baseline
- try std.testing.expect(hybrid_train_loss < mh_loss);
- // Both should be in valid range
- try std.testing.expect(hybrid_eval_loss >= 0.0 and hybrid_eval_loss <= 2.0);
- try std.testing.expect(hybrid_train_loss >= 0.0 and hybrid_train_loss <= 2.0);
-}
-
-// === v2.37 MULTI-ROLE TESTS ===
-
-test "multi-role position-specific training" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- std.debug.print("\n=== MULTI-ROLE TRAINING (v2.37) ===\n", .{});
- std.debug.print("Corpus: {d} chars (Shakespeare)\n", .{corpus.len});
- std.debug.print("Method: 8 position-specific roles + Hebbian hybrid\n", .{});
-
- // Build Hebbian counts
- const counts = buildHebbianCounts(corpus);
-
- // Honest split
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
-
- // Compute multi-roles (8 position-specific)
- var multi_roles = computeMultiRoles(corpus, dim, &train_offsets, 8);
-
- // Measure role orthogonality
- var max_role_sim: f64 = -2.0;
- var avg_role_sim: f64 = 0;
- var role_pair_count: usize = 0;
- for (0..8) |i| {
- for (i + 1..8) |j| {
- const sim = multi_roles[i].similarity(&multi_roles[j]);
- const abs_sim = @abs(sim);
- if (abs_sim > max_role_sim) max_role_sim = abs_sim;
- avg_role_sim += abs_sim;
- role_pair_count += 1;
- }
- }
- if (role_pair_count > 0) avg_role_sim /= @as(f64, @floatFromInt(role_pair_count));
-
- // === Multi-role + Hebbian train loss ===
- var mr_train_loss: f64 = 0;
- var mr_train_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles, dim, last_char, &counts);
- const sim = output.similarity(&target);
- mr_train_loss += 1.0 - sim;
- mr_train_count += 1;
- }
- if (mr_train_count > 0) mr_train_loss /= @as(f64, @floatFromInt(mr_train_count));
-
- // === Single-role + Hebbian train loss (comparison) ===
- var direct_role = computeDirectRole(corpus, dim, &train_offsets, 8);
- var sr_train_loss: f64 = 0;
- var sr_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
- sr_train_loss += 1.0 - sim;
- sr_count += 1;
- }
- if (sr_count > 0) sr_train_loss /= @as(f64, @floatFromInt(sr_count));
-
- // === Multi-role eval loss ===
- var mr_eval_loss: f64 = 0;
- var eval_count: usize = 0;
- const eval_samples = 8;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles, dim, last_char, &counts);
- const sim = output.similarity(&target);
- mr_eval_loss += 1.0 - sim;
- eval_count += 1;
- }
- if (eval_count > 0) mr_eval_loss /= @as(f64, @floatFromInt(eval_count));
-
- // === Single-role eval loss (comparison) ===
- var sr_eval_loss: f64 = 0;
- var sr_eval_count: usize = 0;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &direct_role, dim, last_char, &counts);
- const sim = output.similarity(&target);
- sr_eval_loss += 1.0 - sim;
- sr_eval_count += 1;
- }
- if (sr_eval_count > 0) sr_eval_loss /= @as(f64, @floatFromInt(sr_eval_count));
-
- // === Multi-head baseline ===
- var roles_mh = initRoles(dim, 42);
- var mh_loss: f64 = 0;
- var mh_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- var output = forwardPassMultiHead(&ctx, &roles_mh);
- const sim = output.similarity(&target);
- mh_loss += 1.0 - sim;
- mh_count += 1;
- }
- if (mh_count > 0) mh_loss /= @as(f64, @floatFromInt(mh_count));
-
- const mr_train_imp = (mh_loss - mr_train_loss) / mh_loss * 100.0;
- const sr_train_imp = (mh_loss - sr_train_loss) / mh_loss * 100.0;
- const mr_eval_imp = (mh_loss - mr_eval_loss) / mh_loss * 100.0;
-
- // === Generation with multi-role + sampling ===
- var gen_buf: [50]u8 = undefined;
- var gen_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- gen_ctx[i] = charToHV(dim, corpus[i]);
- }
- const gen_count = generateWithMultiRoleSampled(
- &gen_ctx,
- &multi_roles,
- dim,
- corpus[7],
- &counts,
- &gen_buf,
- 50,
- 0.8,
- 8,
- 42,
- );
-
- var seen: [256]bool = undefined;
- for (0..256) |i| seen[i] = false;
- var unique: usize = 0;
- for (0..gen_count) |i| {
- if (!seen[gen_buf[i]]) {
- seen[gen_buf[i]] = true;
- unique += 1;
- }
- }
-
- std.debug.print("\nRole orthogonality:\n", .{});
- std.debug.print(" Max |cosine| between roles: {d:.4}\n", .{max_role_sim});
- std.debug.print(" Avg |cosine| between roles: {d:.4}\n", .{avg_role_sim});
-
- std.debug.print("\nMulti-role train loss: {d:.4} ({d:.1}% below random)\n", .{ mr_train_loss, mr_train_imp });
- std.debug.print("Single-role train loss: {d:.4} ({d:.1}% below random)\n", .{ sr_train_loss, sr_train_imp });
- std.debug.print("Random baseline: {d:.4}\n", .{mh_loss});
-
- std.debug.print("\nMulti-role eval loss: {d:.4} ({d:.1}% below random)\n", .{ mr_eval_loss, mr_eval_imp });
- std.debug.print("Single-role eval loss: {d:.4}\n", .{sr_eval_loss});
-
- std.debug.print("\nGeneration (T=0.8, K=8):\n", .{});
- std.debug.print(" Prompt: \"to be or \"\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(mr_train_loss >= 0.0 and mr_train_loss <= 2.0);
- try std.testing.expect(mr_eval_loss >= 0.0 and mr_eval_loss <= 2.0);
- try std.testing.expect(gen_count == 50);
- // Roles should be somewhat orthogonal (learned independently)
- try std.testing.expect(max_role_sim < 1.0);
-}
-
-test "multi-role perplexity comparison" {
- const dim: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- const counts = buildHebbianCounts(corpus);
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
- var multi_roles = computeMultiRoles(corpus, dim, &train_offsets, 8);
-
- // === Test PPL (held-out) β Multi-role + Hebbian ===
- const test_start = eval_end;
- const test_count = 8;
- var mr_test_log: f64 = 0;
- var mr_test_valid: usize = 0;
-
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles, dim, last_char, &counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- mr_test_log += @log(clamped);
- mr_test_valid += 1;
- }
-
- const mr_test_ppl = @exp(-mr_test_log / @as(f64, @floatFromInt(mr_test_valid)));
-
- // === Train PPL β Multi-role + Hebbian ===
- var mr_train_log: f64 = 0;
- var mr_train_valid: usize = 0;
- for (0..8) |i| {
- const s = i * train_end / 8;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles, dim, last_char, &counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- mr_train_log += @log(clamped);
- mr_train_valid += 1;
- }
-
- const mr_train_ppl = @exp(-mr_train_log / @as(f64, @floatFromInt(mr_train_valid)));
-
- std.debug.print("\n=== MULTI-ROLE PERPLEXITY (all methods) ===\n", .{});
- std.debug.print("Multi-role train PPL: {d:.1}\n", .{mr_train_ppl});
- std.debug.print("Multi-role test PPL: {d:.1}\n", .{mr_test_ppl});
- std.debug.print("Overfit gap: {d:.1}\n", .{mr_test_ppl - mr_train_ppl});
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("Hybrid (v2.35-36): train=1.8, test=1.9\n", .{});
- std.debug.print("Direct (v2.34): train=2.0, test=2.0\n", .{});
- std.debug.print("Bundle2 (v2.32): train=1.9, test=2.0\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(mr_test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(mr_test_ppl));
- try std.testing.expect(!std.math.isInf(mr_test_ppl));
-}
-
-// === v2.38 DIM=1024 TESTS ===
-
-test "dim1024 single-role hebbian training" {
- const dim: usize = 1024;
- const dim256: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- std.debug.print("\n=== DIM=1024 SINGLE-ROLE HEBBIAN (v2.38) ===\n", .{});
- std.debug.print("Corpus: {d} chars (Shakespeare)\n", .{corpus.len});
- std.debug.print("Method: Single-role + Hebbian hybrid, dim=1024 vs dim=256\n", .{});
-
- // Build Hebbian counts (same for both dims)
- const counts = buildHebbianCounts(corpus);
-
- // Honest split
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
-
- // === dim=1024 ===
- var role_1024 = computeDirectRole(corpus, dim, &train_offsets, 8);
-
- // Train loss dim=1024
- var train_loss_1024: f64 = 0;
- var train_count_1024: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &role_1024, dim, last_char, &counts);
- const sim = output.similarity(&target);
- train_loss_1024 += 1.0 - sim;
- train_count_1024 += 1;
- }
- if (train_count_1024 > 0) train_loss_1024 /= @as(f64, @floatFromInt(train_count_1024));
-
- // Eval loss dim=1024
- var eval_loss_1024: f64 = 0;
- var eval_count_1024: usize = 0;
- const eval_samples = 8;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &role_1024, dim, last_char, &counts);
- const sim = output.similarity(&target);
- eval_loss_1024 += 1.0 - sim;
- eval_count_1024 += 1;
- }
- if (eval_count_1024 > 0) eval_loss_1024 /= @as(f64, @floatFromInt(eval_count_1024));
-
- // === dim=256 (baseline) ===
- var role_256 = computeDirectRole(corpus, dim256, &train_offsets, 8);
-
- var train_loss_256: f64 = 0;
- var train_count_256: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim256, corpus[s + i]);
- }
- var target = charToHV(dim256, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &role_256, dim256, last_char, &counts);
- const sim = output.similarity(&target);
- train_loss_256 += 1.0 - sim;
- train_count_256 += 1;
- }
- if (train_count_256 > 0) train_loss_256 /= @as(f64, @floatFromInt(train_count_256));
-
- var eval_loss_256: f64 = 0;
- var eval_count_256: usize = 0;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim256, corpus[s + j]);
- }
- var target = charToHV(dim256, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &role_256, dim256, last_char, &counts);
- const sim = output.similarity(&target);
- eval_loss_256 += 1.0 - sim;
- eval_count_256 += 1;
- }
- if (eval_count_256 > 0) eval_loss_256 /= @as(f64, @floatFromInt(eval_count_256));
-
- // Random baseline (cosine sim β 0 in high dim β loss β 1.0)
- const mh_loss: f64 = 1.0306;
-
- const imp_1024_train = (mh_loss - train_loss_1024) / mh_loss * 100.0;
- const imp_1024_eval = (mh_loss - eval_loss_1024) / mh_loss * 100.0;
- const imp_256_train = (mh_loss - train_loss_256) / mh_loss * 100.0;
- const imp_256_eval = (mh_loss - eval_loss_256) / mh_loss * 100.0;
-
- // Cosine similarity signal strength at dim=1024
- var max_sim_1024: f64 = -2.0;
- var min_sim_1024: f64 = 2.0;
- var avg_sim_1024: f64 = 0;
- var sim_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassHybrid(&ctx, &role_1024, dim, last_char, &counts);
- const sim = output.similarity(&target);
- if (sim > max_sim_1024) max_sim_1024 = sim;
- if (sim < min_sim_1024) min_sim_1024 = sim;
- avg_sim_1024 += sim;
- sim_count += 1;
- }
- if (sim_count > 0) avg_sim_1024 /= @as(f64, @floatFromInt(sim_count));
-
- std.debug.print("\ndim=1024 train loss: {d:.4} ({d:.1}% below random)\n", .{ train_loss_1024, imp_1024_train });
- std.debug.print("dim=1024 eval loss: {d:.4} ({d:.1}% below random)\n", .{ eval_loss_1024, imp_1024_eval });
- std.debug.print("dim=256 train loss: {d:.4} ({d:.1}% below random)\n", .{ train_loss_256, imp_256_train });
- std.debug.print("dim=256 eval loss: {d:.4} ({d:.1}% below random)\n", .{ eval_loss_256, imp_256_eval });
- std.debug.print("Random baseline: {d:.4}\n", .{mh_loss});
- std.debug.print("\nCosine signal at dim=1024:\n", .{});
- std.debug.print(" Max sim: {d:.4}\n", .{max_sim_1024});
- std.debug.print(" Min sim: {d:.4}\n", .{min_sim_1024});
- std.debug.print(" Avg sim: {d:.4}\n", .{avg_sim_1024});
- std.debug.print(" Range: {d:.4}\n", .{max_sim_1024 - min_sim_1024});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(train_loss_1024 >= 0.0 and train_loss_1024 <= 2.0);
- try std.testing.expect(eval_loss_1024 >= 0.0 and eval_loss_1024 <= 2.0);
- try std.testing.expect(train_loss_256 >= 0.0 and train_loss_256 <= 2.0);
- try std.testing.expect(eval_loss_256 >= 0.0 and eval_loss_256 <= 2.0);
-}
-
-test "dim1024 multi-role hebbian sampling pipeline" {
- const dim: usize = 1024;
- const dim256: usize = 256;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- std.debug.print("\n=== DIM=1024 MULTI-ROLE + HEBBIAN + SAMPLING (v2.38) ===\n", .{});
- std.debug.print("Corpus: {d} chars (Shakespeare)\n", .{corpus.len});
- std.debug.print("Method: 8 multi-role + Hebbian + sampling, dim=1024\n", .{});
-
- const counts = buildHebbianCounts(corpus);
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
-
- // === Multi-role at dim=1024 ===
- var multi_roles_1024 = computeMultiRoles(corpus, dim, &train_offsets, 8);
-
- // Train loss
- var mr_train_loss_1024: f64 = 0;
- var mr_train_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles_1024, dim, last_char, &counts);
- const sim = output.similarity(&target);
- mr_train_loss_1024 += 1.0 - sim;
- mr_train_count += 1;
- }
- if (mr_train_count > 0) mr_train_loss_1024 /= @as(f64, @floatFromInt(mr_train_count));
-
- // Eval loss
- var mr_eval_loss_1024: f64 = 0;
- var mr_eval_count: usize = 0;
- const eval_samples = 8;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles_1024, dim, last_char, &counts);
- const sim = output.similarity(&target);
- mr_eval_loss_1024 += 1.0 - sim;
- mr_eval_count += 1;
- }
- if (mr_eval_count > 0) mr_eval_loss_1024 /= @as(f64, @floatFromInt(mr_eval_count));
-
- // === Multi-role at dim=256 (baseline) ===
- var multi_roles_256 = computeMultiRoles(corpus, dim256, &train_offsets, 8);
-
- var mr_train_loss_256: f64 = 0;
- var mr_train_count_256: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim256, corpus[s + i]);
- }
- var target = charToHV(dim256, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles_256, dim256, last_char, &counts);
- const sim = output.similarity(&target);
- mr_train_loss_256 += 1.0 - sim;
- mr_train_count_256 += 1;
- }
- if (mr_train_count_256 > 0) mr_train_loss_256 /= @as(f64, @floatFromInt(mr_train_count_256));
-
- // === PPL at dim=1024 ===
- const test_start = eval_end;
- const test_count = 8;
- var mr_test_log_1024: f64 = 0;
- var mr_test_valid: usize = 0;
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles_1024, dim, last_char, &counts);
- const sim = output.similarity(&target);
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- mr_test_log_1024 += @log(clamped);
- mr_test_valid += 1;
- }
- const mr_test_ppl_1024 = @exp(-mr_test_log_1024 / @as(f64, @floatFromInt(mr_test_valid)));
-
- var mr_train_log_1024: f64 = 0;
- var mr_train_valid: usize = 0;
- for (0..8) |i| {
- const s = i * train_end / 8;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles_1024, dim, last_char, &counts);
- const sim = output.similarity(&target);
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- mr_train_log_1024 += @log(clamped);
- mr_train_valid += 1;
- }
- const mr_train_ppl_1024 = @exp(-mr_train_log_1024 / @as(f64, @floatFromInt(mr_train_valid)));
-
- // === Generation at dim=1024 ===
- var init_ctx_1024: [8]Hypervector = undefined;
- const prompt = "to be or ";
- for (0..8) |i| {
- init_ctx_1024[i] = charToHV(dim, prompt[i]);
- }
- const init_last_char = prompt[7];
- var gen_buf: [50]u8 = undefined;
- const gen_count = generateWithMultiRoleSampled(
- &init_ctx_1024,
- &multi_roles_1024,
- dim,
- init_last_char,
- &counts,
- &gen_buf,
- 50,
- 0.8,
- 8,
- 42,
- );
-
- // Count unique chars
- var seen: [256]bool = undefined;
- for (0..256) |i| {
- seen[i] = false;
- }
- var unique: usize = 0;
- for (0..gen_count) |i| {
- if (!seen[gen_buf[i]]) {
- seen[gen_buf[i]] = true;
- unique += 1;
- }
- }
-
- // Random baseline
- const mh_loss: f64 = 1.0306;
- const imp_1024_train = (mh_loss - mr_train_loss_1024) / mh_loss * 100.0;
- const imp_1024_eval = (mh_loss - mr_eval_loss_1024) / mh_loss * 100.0;
- const imp_256_train = (mh_loss - mr_train_loss_256) / mh_loss * 100.0;
-
- std.debug.print("\ndim=1024 multi-role train loss: {d:.4} ({d:.1}% below random)\n", .{ mr_train_loss_1024, imp_1024_train });
- std.debug.print("dim=1024 multi-role eval loss: {d:.4} ({d:.1}% below random)\n", .{ mr_eval_loss_1024, imp_1024_eval });
- std.debug.print("dim=256 multi-role train loss: {d:.4} ({d:.1}% below random)\n", .{ mr_train_loss_256, imp_256_train });
- std.debug.print("dim=256 multi-role train (v2.37): 0.7426 (27.9% below random)\n", .{});
- std.debug.print("Random baseline: {d:.4}\n", .{mh_loss});
- std.debug.print("\ndim=1024 train PPL: {d:.1}\n", .{mr_train_ppl_1024});
- std.debug.print("dim=1024 test PPL: {d:.1}\n", .{mr_test_ppl_1024});
- std.debug.print("dim=256 (v2.37): train=1.8, test=1.9\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("\nGeneration (T=0.8, K=8, dim=1024):\n", .{});
- std.debug.print(" Prompt: \"to be or \"\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(mr_train_loss_1024 >= 0.0 and mr_train_loss_1024 <= 2.0);
- try std.testing.expect(mr_eval_loss_1024 >= 0.0 and mr_eval_loss_1024 <= 2.0);
- try std.testing.expect(gen_count == 50);
- try std.testing.expect(mr_test_ppl_1024 > 0.0);
- try std.testing.expect(!std.math.isNan(mr_test_ppl_1024));
- try std.testing.expect(!std.math.isInf(mr_test_ppl_1024));
-}
-
-// === v2.39 TRIGRAM HEBBIAN TESTS ===
-
-test "trigram hebbian training at dim1024" {
- const dim: usize = 1024;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- std.debug.print("\n=== TRIGRAM HEBBIAN TRAINING (v2.39) ===\n", .{});
- std.debug.print("Corpus: {d} chars (Shakespeare)\n", .{corpus.len});
- std.debug.print("Method: Multi-role + trigram Hebbian (2-char lookback) + sampling, dim=1024\n", .{});
-
- // Build both bigram and trigram counts
- const bi_counts = buildHebbianCounts(corpus);
- const tri_counts = buildTrigramCounts(corpus);
-
- // Count trigram coverage
- var tri_total_entries: usize = 0;
- var tri_nonzero: usize = 0;
- for (0..TRIGRAM_KEYS) |k| {
- for (0..HEBBIAN_CHARS) |c| {
- if (tri_counts[k][c] > 0) {
- tri_nonzero += 1;
- }
- tri_total_entries += 1;
- }
- }
-
- // Count unique trigram keys with data
- var tri_keys_with_data: usize = 0;
- for (0..TRIGRAM_KEYS) |k| {
- var has_data = false;
- for (0..HEBBIAN_CHARS) |c| {
- if (tri_counts[k][c] > 0) {
- has_data = true;
- break;
- }
- }
- if (has_data) tri_keys_with_data += 1;
- }
-
- std.debug.print("Trigram keys with data: {d}/{d}\n", .{ tri_keys_with_data, TRIGRAM_KEYS });
- std.debug.print("Non-zero trigram entries: {d}/{d}\n", .{ tri_nonzero, tri_total_entries });
-
- // Honest split
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
-
- // Compute multi-roles at dim=1024
- var multi_roles = computeMultiRoles(corpus, dim, &train_offsets, 8);
-
- // === Trigram train loss ===
- var tri_train_loss: f64 = 0;
- var tri_train_count: usize = 0;
- var tri_hits: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const prev_char = corpus[s + 6];
- const last_char = corpus[s + 7];
-
- // Check if trigram was used
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
- if (tri_total > 0) tri_hits += 1;
- }
-
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- tri_train_loss += 1.0 - sim;
- tri_train_count += 1;
- }
- if (tri_train_count > 0) tri_train_loss /= @as(f64, @floatFromInt(tri_train_count));
-
- // === Bigram-only train loss (comparison) ===
- var bi_train_loss: f64 = 0;
- var bi_train_count: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, corpus[s + i]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles, dim, last_char, &bi_counts);
- const sim = output.similarity(&target);
- bi_train_loss += 1.0 - sim;
- bi_train_count += 1;
- }
- if (bi_train_count > 0) bi_train_loss /= @as(f64, @floatFromInt(bi_train_count));
-
- // === Trigram eval loss ===
- var tri_eval_loss: f64 = 0;
- var tri_eval_count: usize = 0;
- const eval_samples = 8;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const prev_char = corpus[s + 6];
- const last_char = corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- tri_eval_loss += 1.0 - sim;
- tri_eval_count += 1;
- }
- if (tri_eval_count > 0) tri_eval_loss /= @as(f64, @floatFromInt(tri_eval_count));
-
- // === Bigram-only eval loss (comparison) ===
- var bi_eval_loss: f64 = 0;
- var bi_eval_count: usize = 0;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const last_char = corpus[s + 7];
- var output = forwardPassMultiRoleHybrid(&ctx, &multi_roles, dim, last_char, &bi_counts);
- const sim = output.similarity(&target);
- bi_eval_loss += 1.0 - sim;
- bi_eval_count += 1;
- }
- if (bi_eval_count > 0) bi_eval_loss /= @as(f64, @floatFromInt(bi_eval_count));
-
- // === Generation with trigram ===
- var init_ctx: [8]Hypervector = undefined;
- const prompt = "to be or ";
- for (0..8) |i| {
- init_ctx[i] = charToHV(dim, prompt[i]);
- }
- var gen_buf: [50]u8 = undefined;
- const gen_count = generateWithTrigramSampled(
- &init_ctx,
- &multi_roles,
- dim,
- prompt[6], // 'r'
- prompt[7], // ' '
- &bi_counts,
- &tri_counts,
- &gen_buf,
- 50,
- 0.8,
- 8,
- 42,
- );
-
- // Count unique chars
- var seen: [256]bool = undefined;
- for (0..256) |i| {
- seen[i] = false;
- }
- var unique: usize = 0;
- for (0..gen_count) |i| {
- if (!seen[gen_buf[i]]) {
- seen[gen_buf[i]] = true;
- unique += 1;
- }
- }
-
- const mh_loss: f64 = 1.0306;
- const tri_train_imp = (mh_loss - tri_train_loss) / mh_loss * 100.0;
- const tri_eval_imp = (mh_loss - tri_eval_loss) / mh_loss * 100.0;
- const bi_train_imp = (mh_loss - bi_train_loss) / mh_loss * 100.0;
- const bi_eval_imp = (mh_loss - bi_eval_loss) / mh_loss * 100.0;
-
- const tri_hit_pct = @as(f64, @floatFromInt(tri_hits)) / @as(f64, @floatFromInt(tri_train_count)) * 100.0;
-
- std.debug.print("\nTrigram hit rate: {d:.1}% ({d}/{d} samples)\n", .{ tri_hit_pct, tri_hits, tri_train_count });
- std.debug.print("\nTrigram train loss: {d:.4} ({d:.1}% below random)\n", .{ tri_train_loss, tri_train_imp });
- std.debug.print("Bigram train loss: {d:.4} ({d:.1}% below random)\n", .{ bi_train_loss, bi_train_imp });
- std.debug.print("Trigram eval loss: {d:.4} ({d:.1}% below random)\n", .{ tri_eval_loss, tri_eval_imp });
- std.debug.print("Bigram eval loss: {d:.4} ({d:.1}% below random)\n", .{ bi_eval_loss, bi_eval_imp });
- std.debug.print("Random baseline: {d:.4}\n", .{mh_loss});
- std.debug.print("\nGeneration (T=0.8, K=8, trigram, dim=1024):\n", .{});
- std.debug.print(" Prompt: \"to be or \"\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(tri_train_loss >= 0.0 and tri_train_loss <= 2.0);
- try std.testing.expect(tri_eval_loss >= 0.0 and tri_eval_loss <= 2.0);
- try std.testing.expect(gen_count == 50);
- try std.testing.expect(tri_keys_with_data > 0);
-}
-
-test "trigram hebbian perplexity comparison" {
- const dim: usize = 1024;
-
- const corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
-
- const bi_counts = buildHebbianCounts(corpus);
- const tri_counts = buildTrigramCounts(corpus);
-
- const total_samples = corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- var train_offsets: [20]usize = undefined;
- for (0..20) |i| {
- train_offsets[i] = i * train_end / 20;
- }
- var multi_roles = computeMultiRoles(corpus, dim, &train_offsets, 8);
-
- // === Test PPL (held-out) β Trigram ===
- const test_start = eval_end;
- const test_count = 8;
- var tri_test_log: f64 = 0;
- var tri_test_valid: usize = 0;
-
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const prev_char = corpus[s + 6];
- const last_char = corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- tri_test_log += @log(clamped);
- tri_test_valid += 1;
- }
-
- const tri_test_ppl = @exp(-tri_test_log / @as(f64, @floatFromInt(tri_test_valid)));
-
- // === Train PPL β Trigram ===
- var tri_train_log: f64 = 0;
- var tri_train_valid: usize = 0;
- for (0..8) |i| {
- const s = i * train_end / 8;
- if (s + 8 >= corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, corpus[s + j]);
- }
- var target = charToHV(dim, corpus[s + 8]);
- const prev_char = corpus[s + 6];
- const last_char = corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- tri_train_log += @log(clamped);
- tri_train_valid += 1;
- }
-
- const tri_train_ppl = @exp(-tri_train_log / @as(f64, @floatFromInt(tri_train_valid)));
-
- std.debug.print("\n=== TRIGRAM PERPLEXITY (all methods) ===\n", .{});
- std.debug.print("Trigram train PPL: {d:.1}\n", .{tri_train_ppl});
- std.debug.print("Trigram test PPL: {d:.1}\n", .{tri_test_ppl});
- std.debug.print("Overfit gap: {d:.1}\n", .{tri_test_ppl - tri_train_ppl});
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("dim=1024 MR+bigram (v2.38): train=1.8, test=1.8\n", .{});
- std.debug.print("dim=256 MR+bigram (v2.37): train=1.8, test=1.9\n", .{});
- std.debug.print("Hybrid (v2.35-36): train=1.8, test=1.9\n", .{});
- std.debug.print("Direct (v2.34): train=2.0, test=2.0\n", .{});
- std.debug.print("Bundle2 (v2.32): train=1.9, test=2.0\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(tri_test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(tri_test_ppl));
- try std.testing.expect(!std.math.isInf(tri_test_ppl));
-}
-
-// === v2.40 LARGER CORPUS TESTS ===
-
-// ~5000 char Shakespeare corpus (Hamlet + Macbeth + Sonnets + Romeo)
-const large_corpus =
- // Hamlet "To be or not to be" soliloquy (full)
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause there is the respect " ++
- "that makes calamity of so long life " ++
- "for who would bear the whips and scorns of time " ++
- "the oppressors wrong the proud mans contumely " ++
- "the pangs of despised love the laws delay " ++
- "the insolence of office and the spurns " ++
- "that patient merit of the unworthy takes " ++
- "when he himself might his quietus make " ++
- "with a bare bodkin who would fardels bear " ++
- "to grunt and sweat under a weary life " ++
- "but that the dread of something after death " ++
- "the undiscovered country from whose bourn " ++
- "no traveller returns puzzles the will " ++
- "and makes us rather bear those ills we have " ++
- "than fly to others that we know not of " ++
- "thus conscience does make cowards of us all " ++
- "and thus the native hue of resolution " ++
- "is sicklied over with the pale cast of thought " ++
- "and enterprises of great pith and moment " ++
- "with this regard their currents turn awry " ++
- "and lose the name of action " ++
- // Macbeth "Tomorrow" soliloquy
- "tomorrow and tomorrow and tomorrow " ++
- "creeps in this petty pace from day to day " ++
- "to the last syllable of recorded time " ++
- "and all our yesterdays have lighted fools " ++
- "the way to dusty death out out brief candle " ++
- "life is but a walking shadow a poor player " ++
- "that struts and frets his hour upon the stage " ++
- "and then is heard no more it is a tale " ++
- "told by an idiot full of sound and fury " ++
- "signifying nothing " ++
- // Romeo and Juliet balcony
- "but soft what light through yonder window breaks " ++
- "it is the east and juliet is the sun " ++
- "arise fair sun and kill the envious moon " ++
- "who is already sick and pale with grief " ++
- "that thou her maid art far more fair than she " ++
- "be not her maid since she is envious " ++
- "her vestal livery is but sick and green " ++
- "and none but fools do wear it cast it off " ++
- "it is my lady oh it is my love " ++
- "oh that she knew she were " ++
- "she speaks yet she says nothing what of that " ++
- "her eye discourses i will answer it " ++
- "i am too bold tis not to me she speaks " ++
- "two of the fairest stars in all the heaven " ++
- "having some business do entreat her eyes " ++
- "to twinkle in their spheres till they return " ++
- // Sonnets
- "shall i compare thee to a summers day " ++
- "thou art more lovely and more temperate " ++
- "rough winds do shake the darling buds of may " ++
- "and summers lease hath all too short a date " ++
- "sometime too hot the eye of heaven shines " ++
- "and often is his gold complexion dimmed " ++
- "and every fair from fair sometime declines " ++
- "by chance or natures changing course untrimmed " ++
- "but thy eternal summer shall not fade " ++
- "nor lose possession of that fair thou owest " ++
- "nor shall death brag thou wanderest in his shade " ++
- "when in eternal lines to time thou growest " ++
- "so long as men can breathe or eyes can see " ++
- "so long lives this and this gives life to thee " ++
- // Hamlet Act 1
- "who is there nay answer me stand and unfold yourself " ++
- "long live the king bernardo he " ++
- "you come most carefully upon your hour " ++
- "tis now struck twelve get thee to bed francisco " ++
- "for this relief much thanks tis bitter cold " ++
- "and i am sick at heart " ++
- "have you had quiet guard not a mouse stirring " ++
- "well good night if you do meet horatio and marcellus " ++
- "the rivals of my watch bid them make haste " ++
- // Macbeth witches
- "when shall we three meet again " ++
- "in thunder lightning or in rain " ++
- "when the hurlyburlys done " ++
- "when the battles lost and won " ++
- "that will be ere the set of sun " ++
- "where the place upon the heath " ++
- "there to meet with macbeth " ++
- "fair is foul and foul is fair " ++
- "hover through the fog and filthy air " ++
- // More Hamlet
- "something is rotten in the state of denmark " ++
- "though this be madness yet there is method in it " ++
- "brevity is the soul of wit " ++
- "there are more things in heaven and earth horatio " ++
- "than are dreamt of in your philosophy " ++
- "the lady doth protest too much methinks " ++
- "good night sweet prince and flights of angels sing thee to thy rest " ++
- "frailty thy name is woman " ++
- "the play is the thing wherein i will catch the conscience of the king " ++
- // More Romeo
- "a rose by any other name would smell as sweet " ++
- "parting is such sweet sorrow that i shall say good night till it be morrow " ++
- "my bounty is as boundless as the sea my love as deep " ++
- "the more i give to thee the more i have for both are infinite " ++
- "these violent delights have violent ends " ++
- "and in their triumph die like fire and powder " ++
- "which as they kiss consume " ++
- // More Macbeth
- "is this a dagger which i see before me " ++
- "the handle toward my hand come let me clutch thee " ++
- "i have thee not and yet i see thee still " ++
- "art thou not fatal vision sensible " ++
- "to feeling as to sight or art thou but " ++
- "a dagger of the mind a false creation " ++
- "proceeding from the heat oppressed brain " ++
- // Tempest
- "we are such stuff as dreams are made on " ++
- "and our little life is rounded with a sleep " ++
- "oh brave new world that has such people in it " ++
- "full fathom five thy father lies " ++
- "of his bones are coral made " ++
- "those are pearls that were his eyes " ++
- "nothing of him that doth fade " ++
- "but doth suffer a sea change " ++
- "into something rich and strange";
-
-test "large corpus trigram training" {
- const dim: usize = 1024;
-
- std.debug.print("\n=== LARGE CORPUS TRIGRAM TRAINING (v2.40) ===\n", .{});
- std.debug.print("Corpus: {d} chars (Shakespeare multi-play)\n", .{large_corpus.len});
- std.debug.print("Method: Multi-role + trigram Hebbian + sampling, dim=1024\n", .{});
-
- // Build both bigram and trigram counts on large corpus
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- // Count bigram coverage (for comparison)
- var bi_nonzero: usize = 0;
- for (0..HEBBIAN_CHARS) |a| {
- for (0..HEBBIAN_CHARS) |b| {
- if (bi_counts[a][b] > 0) bi_nonzero += 1;
- }
- }
-
- // Count trigram coverage
- var tri_keys_with_data: usize = 0;
- var tri_nonzero: usize = 0;
- for (0..TRIGRAM_KEYS) |k| {
- var has_data = false;
- for (0..HEBBIAN_CHARS) |c| {
- if (tri_counts[k][c] > 0) {
- tri_nonzero += 1;
- has_data = true;
- }
- }
- if (has_data) tri_keys_with_data += 1;
- }
-
- // Small corpus comparison
- const small_corpus =
- "to be or not to be that is the question " ++
- "whether tis nobler in the mind to suffer " ++
- "the slings and arrows of outrageous fortune " ++
- "or to take arms against a sea of troubles " ++
- "and by opposing end them to die to sleep " ++
- "no more and by a sleep to say we end " ++
- "the heartache and the thousand natural shocks " ++
- "that flesh is heir to tis a consummation " ++
- "devoutly to be wished to die to sleep " ++
- "to sleep perchance to dream ay there is the rub " ++
- "for in that sleep of death what dreams may come " ++
- "when we have shuffled off this mortal coil " ++
- "must give us pause";
- const small_tri_counts = buildTrigramCounts(small_corpus);
- var small_tri_keys: usize = 0;
- for (0..TRIGRAM_KEYS) |k| {
- for (0..HEBBIAN_CHARS) |c| {
- if (small_tri_counts[k][c] > 0) {
- small_tri_keys += 1;
- break;
- }
- }
- }
-
- const tri_coverage_pct = @as(f64, @floatFromInt(tri_keys_with_data)) / @as(f64, @floatFromInt(TRIGRAM_KEYS)) * 100.0;
- const small_coverage_pct = @as(f64, @floatFromInt(small_tri_keys)) / @as(f64, @floatFromInt(TRIGRAM_KEYS)) * 100.0;
-
- std.debug.print("Large corpus trigram keys: {d}/{d} ({d:.1}%)\n", .{ tri_keys_with_data, TRIGRAM_KEYS, tri_coverage_pct });
- std.debug.print("Small corpus trigram keys: {d}/{d} ({d:.1}%)\n", .{ small_tri_keys, TRIGRAM_KEYS, small_coverage_pct });
- std.debug.print("Coverage boost: {d:.1}x\n", .{tri_coverage_pct / small_coverage_pct});
- std.debug.print("Bigram pairs: {d}/{d}\n", .{ bi_nonzero, HEBBIAN_CHARS * HEBBIAN_CHARS });
- std.debug.print("Trigram entries: {d}/{d}\n", .{ tri_nonzero, TRIGRAM_KEYS * HEBBIAN_CHARS });
-
- // Honest split
- const total_samples = large_corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- // More train offsets for larger corpus (50 samples)
- var train_offsets: [50]usize = undefined;
- for (0..50) |i| {
- train_offsets[i] = i * train_end / 50;
- }
-
- // Compute multi-roles on large corpus
- var multi_roles = computeMultiRoles(large_corpus, dim, &train_offsets, 8);
-
- // === Trigram train loss (large corpus) ===
- var tri_train_loss: f64 = 0;
- var tri_train_count: usize = 0;
- var tri_hits: usize = 0;
- for (train_offsets) |s| {
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- ctx[i] = charToHV(dim, large_corpus[s + i]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
-
- if (prev_char >= HEBBIAN_OFFSET and prev_char < HEBBIAN_OFFSET + HEBBIAN_CHARS and
- last_char >= HEBBIAN_OFFSET and last_char < HEBBIAN_OFFSET + HEBBIAN_CHARS)
- {
- const prev_idx = prev_char - HEBBIAN_OFFSET;
- const last_idx = last_char - HEBBIAN_OFFSET;
- const key = prev_idx * HEBBIAN_CHARS + last_idx;
- var tri_total: u32 = 0;
- for (0..HEBBIAN_CHARS) |ci| {
- tri_total += tri_counts[key][ci];
- }
- if (tri_total > 0) tri_hits += 1;
- }
-
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- tri_train_loss += 1.0 - sim;
- tri_train_count += 1;
- }
- if (tri_train_count > 0) tri_train_loss /= @as(f64, @floatFromInt(tri_train_count));
-
- // === Trigram eval loss (large corpus) ===
- var tri_eval_loss: f64 = 0;
- var tri_eval_count: usize = 0;
- const eval_samples = 20;
- for (0..eval_samples) |i| {
- const s = train_end + i * (eval_end - train_end) / eval_samples;
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- tri_eval_loss += 1.0 - sim;
- tri_eval_count += 1;
- }
- if (tri_eval_count > 0) tri_eval_loss /= @as(f64, @floatFromInt(tri_eval_count));
-
- // === Generation ===
- var init_ctx: [8]Hypervector = undefined;
- const prompt = "to be or ";
- for (0..8) |i| {
- init_ctx[i] = charToHV(dim, prompt[i]);
- }
- var gen_buf: [80]u8 = undefined;
- const gen_count = generateWithTrigramSampled(
- &init_ctx,
- &multi_roles,
- dim,
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- &gen_buf,
- 80,
- 0.8,
- 8,
- 42,
- );
-
- var seen: [256]bool = undefined;
- for (0..256) |i| {
- seen[i] = false;
- }
- var unique: usize = 0;
- for (0..gen_count) |i| {
- if (!seen[gen_buf[i]]) {
- seen[gen_buf[i]] = true;
- unique += 1;
- }
- }
-
- const mh_loss: f64 = 1.0306;
- const tri_train_imp = (mh_loss - tri_train_loss) / mh_loss * 100.0;
- const tri_eval_imp = (mh_loss - tri_eval_loss) / mh_loss * 100.0;
- const tri_hit_pct = @as(f64, @floatFromInt(tri_hits)) / @as(f64, @floatFromInt(tri_train_count)) * 100.0;
-
- std.debug.print("\nTrigram hit rate: {d:.1}% ({d}/{d} samples)\n", .{ tri_hit_pct, tri_hits, tri_train_count });
- std.debug.print("\nLarge corpus train loss: {d:.4} ({d:.1}% below random)\n", .{ tri_train_loss, tri_train_imp });
- std.debug.print("Large corpus eval loss: {d:.4} ({d:.1}% below random)\n", .{ tri_eval_loss, tri_eval_imp });
- std.debug.print("Small corpus train (v2.39): 0.5528 (46.4% below random)\n", .{});
- std.debug.print("Small corpus eval (v2.39): 0.6534 (36.6% below random)\n", .{});
- std.debug.print("Random baseline: {d:.4}\n", .{mh_loss});
- std.debug.print("\nGeneration (T=0.8, K=8, trigram, dim=1024, 80 tokens):\n", .{});
- std.debug.print(" Prompt: \"to be or \"\n", .{});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_count]});
- std.debug.print(" Unique chars: {d}\n", .{unique});
- std.debug.print("==============================================\n", .{});
-
- // Assertions
- try std.testing.expect(tri_train_loss >= 0.0 and tri_train_loss <= 2.0);
- try std.testing.expect(tri_eval_loss >= 0.0 and tri_eval_loss <= 2.0);
- try std.testing.expect(gen_count == 80);
- try std.testing.expect(tri_keys_with_data > small_tri_keys); // Coverage improved
-}
-
-test "large corpus trigram perplexity" {
- const dim: usize = 1024;
-
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const total_samples = large_corpus.len - 8;
- const train_end = total_samples * 70 / 100;
- const eval_end = total_samples * 85 / 100;
-
- var train_offsets: [50]usize = undefined;
- for (0..50) |i| {
- train_offsets[i] = i * train_end / 50;
- }
- var multi_roles = computeMultiRoles(large_corpus, dim, &train_offsets, 8);
-
- // === Test PPL (held-out) ===
- const test_start = eval_end;
- const test_count = 20;
- var tri_test_log: f64 = 0;
- var tri_test_valid: usize = 0;
-
- for (0..test_count) |i| {
- const s = test_start + i * (total_samples - test_start) / test_count;
- if (s + 8 >= large_corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- tri_test_log += @log(clamped);
- tri_test_valid += 1;
- }
-
- const tri_test_ppl = @exp(-tri_test_log / @as(f64, @floatFromInt(tri_test_valid)));
-
- // === Train PPL ===
- var tri_train_log: f64 = 0;
- var tri_train_valid: usize = 0;
- for (0..20) |i| {
- const s = i * train_end / 20;
- if (s + 8 >= large_corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &multi_roles, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
-
- const prob = (sim + 1.0) / 2.0;
- const clamped = @max(prob, 1e-10);
- tri_train_log += @log(clamped);
- tri_train_valid += 1;
- }
-
- const tri_train_ppl = @exp(-tri_train_log / @as(f64, @floatFromInt(tri_train_valid)));
-
- std.debug.print("\n=== LARGE CORPUS PERPLEXITY (v2.40) ===\n", .{});
- std.debug.print("Corpus: {d} chars\n", .{large_corpus.len});
- std.debug.print("Large corpus train PPL: {d:.2}\n", .{tri_train_ppl});
- std.debug.print("Large corpus test PPL: {d:.2}\n", .{tri_test_ppl});
- std.debug.print("Overfit gap: {d:.2}\n", .{tri_test_ppl - tri_train_ppl});
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("Small corpus trigram (v2.39): train=1.5, test=1.6\n", .{});
- std.debug.print("dim=1024 MR+bigram (v2.38): train=1.8, test=1.8\n", .{});
- std.debug.print("dim=256 MR+bigram (v2.37): train=1.8, test=1.9\n", .{});
- std.debug.print("Hybrid (v2.35-36): train=1.8, test=1.9\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(tri_test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(tri_test_ppl));
- try std.testing.expect(!std.math.isInf(tri_test_ppl));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 28: 500 offsets role quality on large corpus (v2.41)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "500 offsets role quality on large corpus" {
- const dim = 1024;
-
- // Build counts on full large corpus
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- // --- 50-offset roles (baseline, same as v2.40) ---
- var offsets_50: [50]usize = undefined;
- for (0..50) |i| {
- offsets_50[i] = i * (large_corpus.len - 10) / 50;
- }
- var roles_50 = computeMultiRoles(large_corpus, dim, &offsets_50, 8);
-
- // --- 500-offset roles (v2.41) ---
- var offsets_500: [500]usize = undefined;
- for (0..500) |i| {
- offsets_500[i] = i * (large_corpus.len - 10) / 500;
- }
- var roles_500 = computeMultiRoles(large_corpus, dim, &offsets_500, 8);
-
- // Measure role similarity (how much does 500 differ from 50?)
- var role_sim_sum: f64 = 0;
- for (0..8) |r| {
- const sim = roles_500[r].similarity(&roles_50[r]);
- role_sim_sum += sim;
- }
- const avg_role_sim = role_sim_sum / 8.0;
-
- // === Train/eval split ===
- const train_end = large_corpus.len * 80 / 100;
-
- // --- Eval loss with 500 offsets ---
- var loss_500_sum: f64 = 0;
- var loss_500_count: usize = 0;
- var loss_50_sum: f64 = 0;
- var loss_50_count: usize = 0;
-
- for (0..50) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 50;
- if (s + 8 >= large_corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
-
- var output_500 = forwardPassTrigramHybrid(&ctx, &roles_500, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_500 = output_500.similarity(&target);
- loss_500_sum += 1.0 - (sim_500 + 1.0) / 2.0;
- loss_500_count += 1;
-
- var output_50 = forwardPassTrigramHybrid(&ctx, &roles_50, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_50 = output_50.similarity(&target);
- loss_50_sum += 1.0 - (sim_50 + 1.0) / 2.0;
- loss_50_count += 1;
- }
-
- const eval_loss_500 = loss_500_sum / @as(f64, @floatFromInt(loss_500_count));
- const eval_loss_50 = loss_50_sum / @as(f64, @floatFromInt(loss_50_count));
-
- // --- Train loss with 500 offsets ---
- var train_loss_500_sum: f64 = 0;
- var train_loss_500_count: usize = 0;
- var train_loss_50_sum: f64 = 0;
- var train_loss_50_count: usize = 0;
-
- for (0..50) |i| {
- const s = i * train_end / 50;
- if (s + 8 >= large_corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
-
- var output_500 = forwardPassTrigramHybrid(&ctx, &roles_500, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_500 = output_500.similarity(&target);
- train_loss_500_sum += 1.0 - (sim_500 + 1.0) / 2.0;
- train_loss_500_count += 1;
-
- var output_50 = forwardPassTrigramHybrid(&ctx, &roles_50, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_50 = output_50.similarity(&target);
- train_loss_50_sum += 1.0 - (sim_50 + 1.0) / 2.0;
- train_loss_50_count += 1;
- }
-
- const train_loss_500 = train_loss_500_sum / @as(f64, @floatFromInt(train_loss_500_count));
- const train_loss_50 = train_loss_50_sum / @as(f64, @floatFromInt(train_loss_50_count));
-
- const random_baseline = 1.0 - 1.0 / 95.0;
-
- // --- Generation with 500 offsets ---
- var gen_buf: [80]u8 = undefined;
- const prompt = "to be or ";
- var init_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- init_ctx[i] = charToHV(dim, prompt[i]);
- }
- const gen_len = generateWithTrigramSampled(
- &init_ctx,
- &roles_500,
- dim,
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- &gen_buf,
- 80,
- 0.8,
- 8,
- 54321,
- );
-
- // Count unique chars in generation
- var char_seen = [_]bool{false} ** 256;
- var unique_count: usize = 0;
- for (gen_buf[0..gen_len]) |c| {
- if (!char_seen[c]) {
- char_seen[c] = true;
- unique_count += 1;
- }
- }
-
- std.debug.print("\n=== 500 OFFSETS ROLE QUALITY (v2.41) ===\n", .{});
- std.debug.print("Corpus: {d} chars (large Shakespeare)\n", .{large_corpus.len});
- std.debug.print("Offsets: 500 vs 50 (10x more training positions)\n", .{});
- std.debug.print("\nRole similarity (500 vs 50): {d:.4}\n", .{avg_role_sim});
- std.debug.print("\n--- Eval Loss ---\n", .{});
- std.debug.print("500 offsets eval loss: {d:.4}\n", .{eval_loss_500});
- std.debug.print("50 offsets eval loss: {d:.4}\n", .{eval_loss_50});
- std.debug.print("Random baseline: {d:.4}\n", .{random_baseline});
- std.debug.print("500 vs random: {d:.1}% below random\n", .{(1.0 - eval_loss_500 / random_baseline) * 100.0});
- std.debug.print("50 vs random: {d:.1}% below random\n", .{(1.0 - eval_loss_50 / random_baseline) * 100.0});
- std.debug.print("\n--- Train Loss ---\n", .{});
- std.debug.print("500 offsets train loss: {d:.4}\n", .{train_loss_500});
- std.debug.print("50 offsets train loss: {d:.4}\n", .{train_loss_50});
- std.debug.print("\n--- Generation (500 offsets, T=0.8, K=8) ---\n", .{});
- std.debug.print("Prompt: \"{s}\"\n", .{prompt});
- std.debug.print("Generated: \"{s}\"\n", .{gen_buf[0..gen_len]});
- std.debug.print("Unique chars: {d}\n", .{unique_count});
- std.debug.print("============================================\n", .{});
-
- // Structural assertions
- try std.testing.expect(eval_loss_500 < random_baseline);
- try std.testing.expect(eval_loss_50 < random_baseline);
- try std.testing.expect(train_loss_500 < random_baseline);
- try std.testing.expect(gen_len > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 29: 500 offsets perplexity comparison (v2.41)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "500 offsets perplexity comparison" {
- const dim = 1024;
-
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const train_end = large_corpus.len * 80 / 100;
-
- // --- 50-offset roles ---
- var offsets_50: [50]usize = undefined;
- for (0..50) |i| {
- offsets_50[i] = i * (large_corpus.len - 10) / 50;
- }
- var roles_50 = computeMultiRoles(large_corpus, dim, &offsets_50, 8);
-
- // --- 500-offset roles ---
- var offsets_500: [500]usize = undefined;
- for (0..500) |i| {
- offsets_500[i] = i * (large_corpus.len - 10) / 500;
- }
- var roles_500 = computeMultiRoles(large_corpus, dim, &offsets_500, 8);
-
- // === Test PPL (500 offsets) ===
- var test_log_500: f64 = 0;
- var test_valid_500: usize = 0;
- var test_log_50: f64 = 0;
- var test_valid_50: usize = 0;
-
- for (0..20) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 20;
- if (s + 8 >= large_corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
-
- var output_500 = forwardPassTrigramHybrid(&ctx, &roles_500, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_500 = output_500.similarity(&target);
- const prob_500 = @max((sim_500 + 1.0) / 2.0, 1e-10);
- test_log_500 += @log(prob_500);
- test_valid_500 += 1;
-
- var output_50 = forwardPassTrigramHybrid(&ctx, &roles_50, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_50 = output_50.similarity(&target);
- const prob_50 = @max((sim_50 + 1.0) / 2.0, 1e-10);
- test_log_50 += @log(prob_50);
- test_valid_50 += 1;
- }
-
- const test_ppl_500 = @exp(-test_log_500 / @as(f64, @floatFromInt(test_valid_500)));
- const test_ppl_50 = @exp(-test_log_50 / @as(f64, @floatFromInt(test_valid_50)));
-
- // === Train PPL (500 offsets) ===
- var train_log_500: f64 = 0;
- var train_valid_500: usize = 0;
- var train_log_50: f64 = 0;
- var train_valid_50: usize = 0;
-
- for (0..20) |i| {
- const s = i * train_end / 20;
- if (s + 8 >= large_corpus.len) continue;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev_char = large_corpus[s + 6];
- const last_char = large_corpus[s + 7];
-
- var output_500 = forwardPassTrigramHybrid(&ctx, &roles_500, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_500 = output_500.similarity(&target);
- const prob_500 = @max((sim_500 + 1.0) / 2.0, 1e-10);
- train_log_500 += @log(prob_500);
- train_valid_500 += 1;
-
- var output_50 = forwardPassTrigramHybrid(&ctx, &roles_50, dim, prev_char, last_char, &bi_counts, &tri_counts);
- const sim_50 = output_50.similarity(&target);
- const prob_50 = @max((sim_50 + 1.0) / 2.0, 1e-10);
- train_log_50 += @log(prob_50);
- train_valid_50 += 1;
- }
-
- const train_ppl_500 = @exp(-train_log_500 / @as(f64, @floatFromInt(train_valid_500)));
- const train_ppl_50 = @exp(-train_log_50 / @as(f64, @floatFromInt(train_valid_50)));
-
- std.debug.print("\n=== 500 OFFSETS PERPLEXITY (v2.41) ===\n", .{});
- std.debug.print("500 offsets train PPL: {d:.2}\n", .{train_ppl_500});
- std.debug.print("500 offsets test PPL: {d:.2}\n", .{test_ppl_500});
- std.debug.print("500 offsets overfit gap: {d:.2}\n", .{test_ppl_500 - train_ppl_500});
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("50 offsets train PPL: {d:.2}\n", .{train_ppl_50});
- std.debug.print("50 offsets test PPL: {d:.2}\n", .{test_ppl_50});
- std.debug.print("50 offsets overfit gap: {d:.2}\n", .{test_ppl_50 - train_ppl_50});
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("v2.40 large (50 offsets): train=1.87, test=1.84\n", .{});
- std.debug.print("v2.39 small trigram: train=1.5, test=1.6\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(test_ppl_500 > 0.0);
- try std.testing.expect(!std.math.isNan(test_ppl_500));
- try std.testing.expect(!std.math.isInf(test_ppl_500));
- try std.testing.expect(test_ppl_50 > 0.0);
- try std.testing.expect(!std.math.isNan(test_ppl_50));
- try std.testing.expect(!std.math.isInf(test_ppl_50));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 30: Weighted hybrid alpha grid search (v2.42)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "weighted hybrid alpha grid search" {
- const dim = 1024;
-
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const train_end = large_corpus.len * 80 / 100;
-
- // Use 50 offsets for roles (500 was shown equivalent)
- var offsets_50: [50]usize = undefined;
- for (0..50) |i| {
- offsets_50[i] = i * (large_corpus.len - 10) / 50;
- }
- var roles = computeMultiRoles(large_corpus, dim, &offsets_50, 8);
-
- // Grid search over alpha values
- // Test: (role, tri, bi) combinations
- const alphas = [_][3]f64{
- .{ 0.33, 0.33, 0.34 }, // equal weight (baseline)
- .{ 0.10, 0.60, 0.30 }, // trigram-heavy
- .{ 0.05, 0.70, 0.25 }, // trigram-dominant
- .{ 0.00, 0.75, 0.25 }, // no role (pure Hebbian)
- .{ 0.00, 1.00, 0.00 }, // pure trigram
- .{ 0.00, 0.00, 1.00 }, // pure bigram
- .{ 0.20, 0.50, 0.30 }, // moderate role
- .{ 0.50, 0.25, 0.25 }, // role-heavy
- };
- const alpha_names = [_][]const u8{
- "equal(0.33/0.33/0.34)",
- "tri-heavy(0.10/0.60/0.30)",
- "tri-dom(0.05/0.70/0.25)",
- "no-role(0.00/0.75/0.25)",
- "pure-tri(0.00/1.00/0.00)",
- "pure-bi(0.00/0.00/1.00)",
- "mod-role(0.20/0.50/0.30)",
- "role-heavy(0.50/0.25/0.25)",
- };
-
- const random_baseline = 1.0 - 1.0 / 95.0;
-
- var best_eval: f64 = 999.0;
- var best_idx: usize = 0;
- var best_train: f64 = 999.0;
-
- // Also measure the original equal-weight bundling (forwardPassTrigramHybrid)
- var orig_eval_sum: f64 = 0;
- var orig_eval_count: usize = 0;
- var orig_train_sum: f64 = 0;
- var orig_train_count: usize = 0;
-
- for (0..50) |i| {
- const eval_s = train_end + i * (large_corpus.len - train_end - 10) / 50;
- if (eval_s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[eval_s + j]);
- }
- var target = charToHV(dim, large_corpus[eval_s + 8]);
- const prev = large_corpus[eval_s + 6];
- const last = large_corpus[eval_s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- orig_eval_sum += 1.0 - (sim + 1.0) / 2.0;
- orig_eval_count += 1;
- }
- for (0..50) |i| {
- const train_s = i * train_end / 50;
- if (train_s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[train_s + j]);
- }
- var target = charToHV(dim, large_corpus[train_s + 8]);
- const prev = large_corpus[train_s + 6];
- const last = large_corpus[train_s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- orig_train_sum += 1.0 - (sim + 1.0) / 2.0;
- orig_train_count += 1;
- }
- const orig_eval = orig_eval_sum / @as(f64, @floatFromInt(orig_eval_count));
- const orig_train = orig_train_sum / @as(f64, @floatFromInt(orig_train_count));
-
- std.debug.print("\n=== WEIGHTED HYBRID ALPHA GRID SEARCH (v2.42) ===\n", .{});
- std.debug.print("Corpus: {d} chars, dim={d}\n", .{ large_corpus.len, dim });
- std.debug.print("\nOriginal bundling (equal vote):\n", .{});
- std.debug.print(" Train loss: {d:.4} ({d:.1}% below random)\n", .{ orig_train, (1.0 - orig_train / random_baseline) * 100.0 });
- std.debug.print(" Eval loss: {d:.4} ({d:.1}% below random)\n", .{ orig_eval, (1.0 - orig_eval / random_baseline) * 100.0 });
- std.debug.print("\nWeighted alpha search (role/tri/bi):\n", .{});
-
- for (alphas, 0..) |alpha, ai| {
- var eval_sum: f64 = 0;
- var eval_count: usize = 0;
- var train_sum: f64 = 0;
- var train_count: usize = 0;
-
- // Eval loss
- for (0..50) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 50;
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassWeightedHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts, alpha[0], alpha[1], alpha[2]);
- const sim = output.similarity(&target);
- eval_sum += 1.0 - (sim + 1.0) / 2.0;
- eval_count += 1;
- }
-
- // Train loss
- for (0..50) |i| {
- const s = i * train_end / 50;
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassWeightedHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts, alpha[0], alpha[1], alpha[2]);
- const sim = output.similarity(&target);
- train_sum += 1.0 - (sim + 1.0) / 2.0;
- train_count += 1;
- }
-
- const eval_loss = eval_sum / @as(f64, @floatFromInt(eval_count));
- const train_loss = train_sum / @as(f64, @floatFromInt(train_count));
-
- std.debug.print(" {s}: train={d:.4} eval={d:.4} ({d:.1}% below)\n", .{ alpha_names[ai], train_loss, eval_loss, (1.0 - eval_loss / random_baseline) * 100.0 });
-
- if (eval_loss < best_eval) {
- best_eval = eval_loss;
- best_train = train_loss;
- best_idx = ai;
- }
- }
-
- std.debug.print("\nBest: {s}\n", .{alpha_names[best_idx]});
- std.debug.print(" Train: {d:.4} ({d:.1}% below random)\n", .{ best_train, (1.0 - best_train / random_baseline) * 100.0 });
- std.debug.print(" Eval: {d:.4} ({d:.1}% below random)\n", .{ best_eval, (1.0 - best_eval / random_baseline) * 100.0 });
-
- // --- Generation with best alpha ---
- const best_alpha = alphas[best_idx];
- var gen_buf: [80]u8 = undefined;
- const prompt = "to be or ";
- var init_ctx: [8]Hypervector = undefined;
- for (0..8) |i| {
- init_ctx[i] = charToHV(dim, prompt[i]);
- }
- const gen_len = generateWithWeightedHybrid(
- &init_ctx,
- &roles,
- dim,
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- best_alpha[0],
- best_alpha[1],
- best_alpha[2],
- &gen_buf,
- 80,
- 0.8,
- 8,
- 98765,
- );
-
- var char_seen = [_]bool{false} ** 256;
- var unique_count: usize = 0;
- for (gen_buf[0..gen_len]) |c| {
- if (!char_seen[c]) {
- char_seen[c] = true;
- unique_count += 1;
- }
- }
-
- std.debug.print("\nGeneration (best alpha, T=0.8, K=8):\n", .{});
- std.debug.print(" Prompt: \"{s}\"\n", .{prompt});
- std.debug.print(" Generated: \"{s}\"\n", .{gen_buf[0..gen_len]});
- std.debug.print(" Unique chars: {d}\n", .{unique_count});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(best_eval < random_baseline);
- try std.testing.expect(best_train < random_baseline);
- try std.testing.expect(gen_len > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 31: Weighted hybrid perplexity (v2.42)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "weighted hybrid perplexity comparison" {
- const dim = 1024;
-
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const train_end = large_corpus.len * 80 / 100;
-
- var offsets_50: [50]usize = undefined;
- for (0..50) |i| {
- offsets_50[i] = i * (large_corpus.len - 10) / 50;
- }
- var roles = computeMultiRoles(large_corpus, dim, &offsets_50, 8);
-
- // Test multiple alpha configs for PPL
- const configs = [_][3]f64{
- .{ 0.33, 0.33, 0.34 }, // equal
- .{ 0.00, 0.75, 0.25 }, // no role
- .{ 0.05, 0.70, 0.25 }, // trigram dominant
- .{ 0.10, 0.60, 0.30 }, // trigram heavy
- };
- const config_names = [_][]const u8{
- "equal(0.33/0.33/0.34)",
- "no-role(0.00/0.75/0.25)",
- "tri-dom(0.05/0.70/0.25)",
- "tri-heavy(0.10/0.60/0.30)",
- };
-
- // Also compute original bundling PPL
- var orig_test_log: f64 = 0;
- var orig_test_valid: usize = 0;
- var orig_train_log: f64 = 0;
- var orig_train_valid: usize = 0;
-
- for (0..20) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 20;
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- orig_test_log += @log(prob);
- orig_test_valid += 1;
- }
- for (0..20) |i| {
- const s = i * train_end / 20;
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassTrigramHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- orig_train_log += @log(prob);
- orig_train_valid += 1;
- }
-
- const orig_test_ppl = @exp(-orig_test_log / @as(f64, @floatFromInt(orig_test_valid)));
- const orig_train_ppl = @exp(-orig_train_log / @as(f64, @floatFromInt(orig_train_valid)));
-
- std.debug.print("\n=== WEIGHTED HYBRID PERPLEXITY (v2.42) ===\n", .{});
- std.debug.print("Original bundling: train={d:.2} test={d:.2} gap={d:.2}\n", .{ orig_train_ppl, orig_test_ppl, orig_test_ppl - orig_train_ppl });
-
- var best_test_ppl: f64 = 999.0;
- var best_config_idx: usize = 0;
- var best_train_ppl_val: f64 = 999.0;
-
- for (configs, 0..) |cfg, ci| {
- var test_log: f64 = 0;
- var test_valid: usize = 0;
- var train_log: f64 = 0;
- var train_valid: usize = 0;
-
- for (0..20) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 20;
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassWeightedHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts, cfg[0], cfg[1], cfg[2]);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- test_log += @log(prob);
- test_valid += 1;
- }
-
- for (0..20) |i| {
- const s = i * train_end / 20;
- if (s + 8 >= large_corpus.len) continue;
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassWeightedHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts, cfg[0], cfg[1], cfg[2]);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- train_log += @log(prob);
- train_valid += 1;
- }
-
- const test_ppl = @exp(-test_log / @as(f64, @floatFromInt(test_valid)));
- const train_ppl = @exp(-train_log / @as(f64, @floatFromInt(train_valid)));
-
- std.debug.print("{s}: train={d:.2} test={d:.2} gap={d:.2}\n", .{ config_names[ci], train_ppl, test_ppl, test_ppl - train_ppl });
-
- if (test_ppl < best_test_ppl) {
- best_test_ppl = test_ppl;
- best_train_ppl_val = train_ppl;
- best_config_idx = ci;
- }
- }
-
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("Best config: {s}\n", .{config_names[best_config_idx]});
- std.debug.print(" Train PPL: {d:.2}, Test PPL: {d:.2}\n", .{ best_train_ppl_val, best_test_ppl });
- std.debug.print("v2.41 (500 offsets): train=1.80, test=1.93\n", .{});
- std.debug.print("v2.40 (50 offsets): train=1.87, test=1.84\n", .{});
- std.debug.print("v2.39 small trigram: train=1.5, test=1.6\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(best_test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(best_test_ppl));
- try std.testing.expect(!std.math.isInf(best_test_ppl));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 32: Pure trigram loss comparison (v2.43)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "pure trigram loss comparison" {
- const dim = 1024;
-
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const train_end = large_corpus.len * 80 / 100;
- const random_baseline = 1.0 - 1.0 / 95.0;
-
- // === Pure trigram (no roles at all) ===
- var pure_eval_sum: f64 = 0;
- var pure_eval_count: usize = 0;
- var pure_train_sum: f64 = 0;
- var pure_train_count: usize = 0;
-
- // === Pure trigram + bigram blend (0.75/0.25) ===
- var blend_eval_sum: f64 = 0;
- var blend_eval_count: usize = 0;
- var blend_train_sum: f64 = 0;
- var blend_train_count: usize = 0;
-
- // === Original bundled (for comparison) ===
- var offsets_50: [50]usize = undefined;
- for (0..50) |i| {
- offsets_50[i] = i * (large_corpus.len - 10) / 50;
- }
- var roles = computeMultiRoles(large_corpus, dim, &offsets_50, 8);
-
- var orig_eval_sum: f64 = 0;
- var orig_eval_count: usize = 0;
- var orig_train_sum: f64 = 0;
- var orig_train_count: usize = 0;
-
- // Eval
- for (0..50) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 50;
- if (s + 8 >= large_corpus.len) continue;
-
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
-
- // Pure trigram
- var pure_out = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const pure_sim = pure_out.similarity(&target);
- pure_eval_sum += 1.0 - (pure_sim + 1.0) / 2.0;
- pure_eval_count += 1;
-
- // Pure blend (0.75 tri, 0.25 bi)
- var blend_out = forwardPassPureTrigramBlend(dim, prev, last, &bi_counts, &tri_counts, 0.75, 0.25);
- const blend_sim = blend_out.similarity(&target);
- blend_eval_sum += 1.0 - (blend_sim + 1.0) / 2.0;
- blend_eval_count += 1;
-
- // Original bundled
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var orig_out = forwardPassTrigramHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts);
- const orig_sim = orig_out.similarity(&target);
- orig_eval_sum += 1.0 - (orig_sim + 1.0) / 2.0;
- orig_eval_count += 1;
- }
-
- // Train
- for (0..50) |i| {
- const s = i * train_end / 50;
- if (s + 8 >= large_corpus.len) continue;
-
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
-
- var pure_out = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const pure_sim = pure_out.similarity(&target);
- pure_train_sum += 1.0 - (pure_sim + 1.0) / 2.0;
- pure_train_count += 1;
-
- var blend_out = forwardPassPureTrigramBlend(dim, prev, last, &bi_counts, &tri_counts, 0.75, 0.25);
- const blend_sim = blend_out.similarity(&target);
- blend_train_sum += 1.0 - (blend_sim + 1.0) / 2.0;
- blend_train_count += 1;
-
- var ctx: [8]Hypervector = undefined;
- for (0..8) |j| {
- ctx[j] = charToHV(dim, large_corpus[s + j]);
- }
- var orig_out = forwardPassTrigramHybrid(&ctx, &roles, dim, prev, last, &bi_counts, &tri_counts);
- const orig_sim = orig_out.similarity(&target);
- orig_train_sum += 1.0 - (orig_sim + 1.0) / 2.0;
- orig_train_count += 1;
- }
-
- const pure_eval = pure_eval_sum / @as(f64, @floatFromInt(pure_eval_count));
- const pure_train = pure_train_sum / @as(f64, @floatFromInt(pure_train_count));
- const blend_eval = blend_eval_sum / @as(f64, @floatFromInt(blend_eval_count));
- const blend_train = blend_train_sum / @as(f64, @floatFromInt(blend_train_count));
- const orig_eval = orig_eval_sum / @as(f64, @floatFromInt(orig_eval_count));
- const orig_train = orig_train_sum / @as(f64, @floatFromInt(orig_train_count));
-
- // --- Generation comparison ---
- const prompt = "to be or ";
- var gen_pure: [80]u8 = undefined;
- const gen_pure_len = generateWithPureTrigram(
- dim,
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- &gen_pure,
- 80,
- 0.8,
- 8,
- 11111,
- );
- var gen_blend: [80]u8 = undefined;
- const gen_blend_len = generateWithPureTrigram(
- dim,
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- &gen_blend,
- 80,
- 0.6,
- 5,
- 22222,
- );
-
- // Count unique chars
- var seen_pure = [_]bool{false} ** 256;
- var unique_pure: usize = 0;
- for (gen_pure[0..gen_pure_len]) |c| {
- if (!seen_pure[c]) {
- seen_pure[c] = true;
- unique_pure += 1;
- }
- }
- var seen_blend = [_]bool{false} ** 256;
- var unique_blend: usize = 0;
- for (gen_blend[0..gen_blend_len]) |c| {
- if (!seen_blend[c]) {
- seen_blend[c] = true;
- unique_blend += 1;
- }
- }
-
- std.debug.print("\n=== PURE TRIGRAM LOSS COMPARISON (v2.43) ===\n", .{});
- std.debug.print("Corpus: {d} chars, dim={d}\n", .{ large_corpus.len, dim });
- std.debug.print("\n--- Eval Loss ---\n", .{});
- std.debug.print("Pure trigram: {d:.4} ({d:.1}% below random)\n", .{ pure_eval, (1.0 - pure_eval / random_baseline) * 100.0 });
- std.debug.print("Pure tri+bi blend: {d:.4} ({d:.1}% below random)\n", .{ blend_eval, (1.0 - blend_eval / random_baseline) * 100.0 });
- std.debug.print("Original bundled: {d:.4} ({d:.1}% below random)\n", .{ orig_eval, (1.0 - orig_eval / random_baseline) * 100.0 });
- std.debug.print("Random baseline: {d:.4}\n", .{random_baseline});
- std.debug.print("\n--- Train Loss ---\n", .{});
- std.debug.print("Pure trigram: {d:.4} ({d:.1}% below random)\n", .{ pure_train, (1.0 - pure_train / random_baseline) * 100.0 });
- std.debug.print("Pure tri+bi blend: {d:.4} ({d:.1}% below random)\n", .{ blend_train, (1.0 - blend_train / random_baseline) * 100.0 });
- std.debug.print("Original bundled: {d:.4} ({d:.1}% below random)\n", .{ orig_train, (1.0 - orig_train / random_baseline) * 100.0 });
- std.debug.print("\n--- Generation (T=0.8, K=8) ---\n", .{});
- std.debug.print("Prompt: \"{s}\"\n", .{prompt});
- std.debug.print("Pure (T=0.8,K=8): \"{s}\" ({d} unique)\n", .{ gen_pure[0..gen_pure_len], unique_pure });
- std.debug.print("Pure (T=0.6,K=5): \"{s}\" ({d} unique)\n", .{ gen_blend[0..gen_blend_len], unique_blend });
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(pure_eval < random_baseline);
- try std.testing.expect(pure_train < random_baseline);
- try std.testing.expect(gen_pure_len > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 33: Pure trigram perplexity (v2.43)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "pure trigram perplexity" {
- const dim = 1024;
-
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const train_end = large_corpus.len * 80 / 100;
-
- // === Pure trigram test PPL ===
- var pure_test_log: f64 = 0;
- var pure_test_valid: usize = 0;
-
- for (0..20) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 20;
- if (s + 8 >= large_corpus.len) continue;
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- pure_test_log += @log(prob);
- pure_test_valid += 1;
- }
-
- // === Pure trigram train PPL ===
- var pure_train_log: f64 = 0;
- var pure_train_valid: usize = 0;
-
- for (0..20) |i| {
- const s = i * train_end / 20;
- if (s + 8 >= large_corpus.len) continue;
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- pure_train_log += @log(prob);
- pure_train_valid += 1;
- }
-
- // === Pure blend (0.75/0.25) PPL ===
- var blend_test_log: f64 = 0;
- var blend_test_valid: usize = 0;
- var blend_train_log: f64 = 0;
- var blend_train_valid: usize = 0;
-
- for (0..20) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 20;
- if (s + 8 >= large_corpus.len) continue;
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassPureTrigramBlend(dim, prev, last, &bi_counts, &tri_counts, 0.75, 0.25);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- blend_test_log += @log(prob);
- blend_test_valid += 1;
- }
- for (0..20) |i| {
- const s = i * train_end / 20;
- if (s + 8 >= large_corpus.len) continue;
- var target = charToHV(dim, large_corpus[s + 8]);
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var output = forwardPassPureTrigramBlend(dim, prev, last, &bi_counts, &tri_counts, 0.75, 0.25);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- blend_train_log += @log(prob);
- blend_train_valid += 1;
- }
-
- const pure_test_ppl = @exp(-pure_test_log / @as(f64, @floatFromInt(pure_test_valid)));
- const pure_train_ppl = @exp(-pure_train_log / @as(f64, @floatFromInt(pure_train_valid)));
- const blend_test_ppl = @exp(-blend_test_log / @as(f64, @floatFromInt(blend_test_valid)));
- const blend_train_ppl = @exp(-blend_train_log / @as(f64, @floatFromInt(blend_train_valid)));
-
- std.debug.print("\n=== PURE TRIGRAM PERPLEXITY (v2.43) ===\n", .{});
- std.debug.print("Pure trigram: train={d:.2} test={d:.2} gap={d:.2}\n", .{ pure_train_ppl, pure_test_ppl, pure_test_ppl - pure_train_ppl });
- std.debug.print("Pure tri+bi blend: train={d:.2} test={d:.2} gap={d:.2}\n", .{ blend_train_ppl, blend_test_ppl, blend_test_ppl - blend_train_ppl });
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("v2.42 weighted best (no-role): train=1.77, test=1.90\n", .{});
- std.debug.print("v2.42 original bundle: train=1.82, test=1.94\n", .{});
- std.debug.print("v2.39 small trigram: train=1.5, test=1.6\n", .{});
- std.debug.print("Random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(pure_test_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(pure_test_ppl));
- try std.testing.expect(!std.math.isInf(pure_test_ppl));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 34: Raw frequency decoding loss comparison (v2.44)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "raw frequency decoding loss comparison" {
- const dim = 1024;
-
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const train_end = large_corpus.len * 80 / 100;
-
- // === Raw frequency loss (no VSA at all) ===
- var raw_eval_sum: f64 = 0;
- var raw_eval_count: usize = 0;
- var raw_train_sum: f64 = 0;
- var raw_train_count: usize = 0;
-
- // === VSA pure trigram loss (for comparison) ===
- var vsa_eval_sum: f64 = 0;
- var vsa_eval_count: usize = 0;
- var vsa_train_sum: f64 = 0;
- var vsa_train_count: usize = 0;
-
- // Eval
- for (0..50) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 50;
- if (s + 8 >= large_corpus.len) continue;
-
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- const target_char = large_corpus[s + 8];
-
- // Raw frequency loss
- const raw_loss = rawTrigramLoss(prev, last, target_char, &bi_counts, &tri_counts);
- raw_eval_sum += raw_loss;
- raw_eval_count += 1;
-
- // VSA pure trigram loss (for comparison)
- var target = charToHV(dim, target_char);
- var pure_out = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const sim = pure_out.similarity(&target);
- vsa_eval_sum += 1.0 - (sim + 1.0) / 2.0;
- vsa_eval_count += 1;
- }
-
- // Train
- for (0..50) |i| {
- const s = i * train_end / 50;
- if (s + 8 >= large_corpus.len) continue;
-
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- const target_char = large_corpus[s + 8];
-
- const raw_loss = rawTrigramLoss(prev, last, target_char, &bi_counts, &tri_counts);
- raw_train_sum += raw_loss;
- raw_train_count += 1;
-
- var target = charToHV(dim, target_char);
- var pure_out = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const sim = pure_out.similarity(&target);
- vsa_train_sum += 1.0 - (sim + 1.0) / 2.0;
- vsa_train_count += 1;
- }
-
- const raw_eval = raw_eval_sum / @as(f64, @floatFromInt(raw_eval_count));
- const raw_train = raw_train_sum / @as(f64, @floatFromInt(raw_train_count));
- const vsa_eval = vsa_eval_sum / @as(f64, @floatFromInt(vsa_eval_count));
- const vsa_train = vsa_train_sum / @as(f64, @floatFromInt(vsa_train_count));
-
- // Raw loss is cross-entropy (nats), convert to comparable metric
- const random_ce = @log(@as(f64, @floatFromInt(HEBBIAN_CHARS))); // ln(95) β 4.55
- const vsa_random = 1.0 - 1.0 / 95.0; // β 0.9895
-
- // --- Generation comparison ---
- const prompt = "to be or ";
- var gen_raw: [120]u8 = undefined;
- const gen_raw_len = generateWithRawFreq(
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- &gen_raw,
- 120,
- 0.8,
- 10,
- 77777,
- );
- var gen_raw_low: [120]u8 = undefined;
- const gen_raw_low_len = generateWithRawFreq(
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- &gen_raw_low,
- 120,
- 0.5,
- 5,
- 88888,
- );
- var gen_raw_greedy: [120]u8 = undefined;
- const gen_raw_greedy_len = generateWithRawFreq(
- prompt[6],
- prompt[7],
- &bi_counts,
- &tri_counts,
- &gen_raw_greedy,
- 120,
- 0.3,
- 3,
- 99999,
- );
-
- // Count unique chars
- var seen1 = [_]bool{false} ** 256;
- var unique1: usize = 0;
- for (gen_raw[0..gen_raw_len]) |c| {
- if (!seen1[c]) {
- seen1[c] = true;
- unique1 += 1;
- }
- }
- var seen2 = [_]bool{false} ** 256;
- var unique2: usize = 0;
- for (gen_raw_low[0..gen_raw_low_len]) |c| {
- if (!seen2[c]) {
- seen2[c] = true;
- unique2 += 1;
- }
- }
- var seen3 = [_]bool{false} ** 256;
- var unique3: usize = 0;
- for (gen_raw_greedy[0..gen_raw_greedy_len]) |c| {
- if (!seen3[c]) {
- seen3[c] = true;
- unique3 += 1;
- }
- }
-
- std.debug.print("\n=== RAW FREQUENCY DECODING (v2.44) ===\n", .{});
- std.debug.print("Corpus: {d} chars\n", .{large_corpus.len});
- std.debug.print("\n--- Loss Comparison ---\n", .{});
- std.debug.print("Raw freq eval (CE nats): {d:.4} ({d:.1}% below random)\n", .{ raw_eval, (1.0 - raw_eval / random_ce) * 100.0 });
- std.debug.print("Raw freq train (CE nats): {d:.4} ({d:.1}% below random)\n", .{ raw_train, (1.0 - raw_train / random_ce) * 100.0 });
- std.debug.print("Random CE baseline: {d:.4} (ln(95))\n", .{random_ce});
- std.debug.print("\nVSA pure trigram eval: {d:.4} ({d:.1}% below random)\n", .{ vsa_eval, (1.0 - vsa_eval / vsa_random) * 100.0 });
- std.debug.print("VSA pure trigram train: {d:.4} ({d:.1}% below random)\n", .{ vsa_train, (1.0 - vsa_train / vsa_random) * 100.0 });
- std.debug.print("VSA random baseline: {d:.4}\n", .{vsa_random});
- std.debug.print("\n--- Generation (raw freq) ---\n", .{});
- std.debug.print("Prompt: \"{s}\"\n", .{prompt});
- std.debug.print("T=0.8,K=10: \"{s}\" ({d} unique)\n", .{ gen_raw[0..gen_raw_len], unique1 });
- std.debug.print("T=0.5,K=5: \"{s}\" ({d} unique)\n", .{ gen_raw_low[0..gen_raw_low_len], unique2 });
- std.debug.print("T=0.3,K=3: \"{s}\" ({d} unique)\n", .{ gen_raw_greedy[0..gen_raw_greedy_len], unique3 });
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(raw_eval < random_ce);
- try std.testing.expect(raw_train < random_ce);
- try std.testing.expect(gen_raw_len > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 35: Raw frequency perplexity (v2.44)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "raw frequency perplexity" {
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
-
- const train_end = large_corpus.len * 80 / 100;
-
- // === Raw frequency test PPL ===
- var raw_test_log: f64 = 0;
- var raw_test_valid: usize = 0;
-
- for (0..40) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 40;
- if (s + 8 >= large_corpus.len) continue;
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- const target = large_corpus[s + 8];
- const prob = rawTrigramProb(prev, last, target, &bi_counts, &tri_counts);
- raw_test_log += @log(@max(prob, 1e-20));
- raw_test_valid += 1;
- }
-
- // === Raw frequency train PPL ===
- var raw_train_log: f64 = 0;
- var raw_train_valid: usize = 0;
-
- for (0..40) |i| {
- const s = i * train_end / 40;
- if (s + 8 >= large_corpus.len) continue;
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- const target = large_corpus[s + 8];
- const prob = rawTrigramProb(prev, last, target, &bi_counts, &tri_counts);
- raw_train_log += @log(@max(prob, 1e-20));
- raw_train_valid += 1;
- }
-
- const raw_test_ppl = @exp(-raw_test_log / @as(f64, @floatFromInt(raw_test_valid)));
- const raw_train_ppl = @exp(-raw_train_log / @as(f64, @floatFromInt(raw_train_valid)));
-
- // === Also compute VSA pure trigram PPL with same samples ===
- const dim = 1024;
- var vsa_test_log: f64 = 0;
- var vsa_test_valid: usize = 0;
- var vsa_train_log: f64 = 0;
- var vsa_train_valid: usize = 0;
-
- for (0..40) |i| {
- const s = train_end + i * (large_corpus.len - train_end - 10) / 40;
- if (s + 8 >= large_corpus.len) continue;
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var target = charToHV(dim, large_corpus[s + 8]);
- var output = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- vsa_test_log += @log(prob);
- vsa_test_valid += 1;
- }
- for (0..40) |i| {
- const s = i * train_end / 40;
- if (s + 8 >= large_corpus.len) continue;
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- var target = charToHV(dim, large_corpus[s + 8]);
- var output = forwardPassPureTrigram(dim, prev, last, &bi_counts, &tri_counts);
- const sim = output.similarity(&target);
- const prob = @max((sim + 1.0) / 2.0, 1e-10);
- vsa_train_log += @log(prob);
- vsa_train_valid += 1;
- }
-
- const vsa_test_ppl = @exp(-vsa_test_log / @as(f64, @floatFromInt(vsa_test_valid)));
- const vsa_train_ppl = @exp(-vsa_train_log / @as(f64, @floatFromInt(vsa_train_valid)));
-
- std.debug.print("\n=== RAW FREQUENCY PERPLEXITY (v2.44) ===\n", .{});
- std.debug.print("Raw freq: train={d:.2} test={d:.2} gap={d:.2}\n", .{ raw_train_ppl, raw_test_ppl, raw_test_ppl - raw_train_ppl });
- std.debug.print("VSA pure trigram: train={d:.2} test={d:.2} gap={d:.2}\n", .{ vsa_train_ppl, vsa_test_ppl, vsa_test_ppl - vsa_train_ppl });
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("v2.43 pure trigram (20 samples): train=1.76, test=1.87\n", .{});
- std.debug.print("v2.42 original bundle: train=1.82, test=1.94\n", .{});
- std.debug.print("v2.39 small trigram: train=1.5, test=1.6\n", .{});
- std.debug.print("Random baseline (raw): {d:.1}\n", .{@as(f64, @floatFromInt(HEBBIAN_CHARS))});
- std.debug.print("Random baseline (VSA): 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(raw_test_ppl > 0.0);
- try std.testing.expect(raw_test_ppl < @as(f64, @floatFromInt(HEBBIAN_CHARS)));
- try std.testing.expect(!std.math.isNan(raw_test_ppl));
- try std.testing.expect(!std.math.isInf(raw_test_ppl));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 36: Word-level tokenization and bigram statistics (v2.45)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "word-level tokenization and bigram statistics" {
- var wc = WordCorpus.init();
- wc.tokenize(large_corpus);
- wc.buildBigrams();
-
- const train_end = wc.token_count * 80 / 100;
-
- // === Word-level train loss (CE nats) ===
- var train_ce_sum: f64 = 0;
- var train_ce_count: usize = 0;
- for (1..train_end) |i| {
- const prev = wc.tokens[i - 1];
- const curr = wc.tokens[i];
- const prob = wc.wordBigramProb(prev, curr);
- train_ce_sum += -@log(@max(prob, 1e-20));
- train_ce_count += 1;
- }
-
- // === Word-level eval loss (CE nats) ===
- var eval_ce_sum: f64 = 0;
- var eval_ce_count: usize = 0;
- for (train_end..wc.token_count) |i| {
- if (i == 0) continue;
- const prev = wc.tokens[i - 1];
- const curr = wc.tokens[i];
- const prob = wc.wordBigramProb(prev, curr);
- eval_ce_sum += -@log(@max(prob, 1e-20));
- eval_ce_count += 1;
- }
-
- const train_ce = train_ce_sum / @as(f64, @floatFromInt(train_ce_count));
- const eval_ce = eval_ce_sum / @as(f64, @floatFromInt(eval_ce_count));
- const random_ce = @log(@as(f64, @floatFromInt(wc.vocab_size))); // ln(vocab_size)
-
- // === Count bigram coverage ===
- var bigram_nonzero: usize = 0;
- const total_possible = wc.vocab_size * wc.vocab_size;
- for (0..wc.vocab_size) |i| {
- for (0..wc.vocab_size) |j| {
- if (wc.bigram_counts[i][j] > 0) bigram_nonzero += 1;
- }
- }
-
- // === Generation at multiple temperatures ===
- var gen_buf1: [256]u8 = undefined;
- var gen_buf2: [256]u8 = undefined;
- var gen_buf3: [256]u8 = undefined;
-
- // Find "to" in vocabulary
- var start_word: u16 = 0;
- for (0..wc.vocab_size) |i| {
- const w = wc.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') {
- start_word = @intCast(i);
- break;
- }
- }
-
- // Generate at T=0.8
- var gen1_len: usize = 0;
- var prev_word = start_word;
- for (0..30) |step| {
- const next = wc.sampleNextWord(prev_word, 0.8, 44444 + step);
- const word = wc.getWord(next);
- if (gen1_len + word.len + 1 < gen_buf1.len) {
- if (gen1_len > 0) {
- gen_buf1[gen1_len] = ' ';
- gen1_len += 1;
- }
- for (word) |c| {
- gen_buf1[gen1_len] = c;
- gen1_len += 1;
- }
- }
- prev_word = next;
- }
-
- // Generate at T=0.5
- var gen2_len: usize = 0;
- prev_word = start_word;
- for (0..30) |step| {
- const next = wc.sampleNextWord(prev_word, 0.5, 55555 + step);
- const word = wc.getWord(next);
- if (gen2_len + word.len + 1 < gen_buf2.len) {
- if (gen2_len > 0) {
- gen_buf2[gen2_len] = ' ';
- gen2_len += 1;
- }
- for (word) |c| {
- gen_buf2[gen2_len] = c;
- gen2_len += 1;
- }
- }
- prev_word = next;
- }
-
- // Generate at T=0.3
- var gen3_len: usize = 0;
- prev_word = start_word;
- for (0..30) |step| {
- const next = wc.sampleNextWord(prev_word, 0.3, 66666 + step);
- const word = wc.getWord(next);
- if (gen3_len + word.len + 1 < gen_buf3.len) {
- if (gen3_len > 0) {
- gen_buf3[gen3_len] = ' ';
- gen3_len += 1;
- }
- for (word) |c| {
- gen_buf3[gen3_len] = c;
- gen3_len += 1;
- }
- }
- prev_word = next;
- }
-
- std.debug.print("\n=== WORD-LEVEL STATISTICS (v2.45) ===\n", .{});
- std.debug.print("Corpus: {d} chars β {d} tokens, {d} unique words\n", .{ large_corpus.len, wc.token_count, wc.vocab_size });
- std.debug.print("Word bigram coverage: {d}/{d} ({d:.1}%)\n", .{ bigram_nonzero, total_possible, @as(f64, @floatFromInt(bigram_nonzero)) / @as(f64, @floatFromInt(total_possible)) * 100.0 });
- std.debug.print("\n--- Word-Level Loss (CE nats) ---\n", .{});
- std.debug.print("Train CE: {d:.4} ({d:.1}% below random)\n", .{ train_ce, (1.0 - train_ce / random_ce) * 100.0 });
- std.debug.print("Eval CE: {d:.4} ({d:.1}% below random)\n", .{ eval_ce, (1.0 - eval_ce / random_ce) * 100.0 });
- std.debug.print("Random CE: {d:.4} (ln({d}))\n", .{ random_ce, wc.vocab_size });
- std.debug.print("\n--- Generation (word bigram) ---\n", .{});
- std.debug.print("Start: \"to\"\n", .{});
- std.debug.print("T=0.8: \"{s}\"\n", .{gen_buf1[0..gen1_len]});
- std.debug.print("T=0.5: \"{s}\"\n", .{gen_buf2[0..gen2_len]});
- std.debug.print("T=0.3: \"{s}\"\n", .{gen_buf3[0..gen3_len]});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(wc.vocab_size > 0);
- try std.testing.expect(wc.token_count > 0);
- try std.testing.expect(train_ce < random_ce);
- try std.testing.expect(gen1_len > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 37: Word-level perplexity comparison (v2.45)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "word-level perplexity comparison" {
- var wc = WordCorpus.init();
- wc.tokenize(large_corpus);
- wc.buildBigrams();
-
- const train_end = wc.token_count * 80 / 100;
-
- // === Word-level train PPL ===
- var train_log_sum: f64 = 0;
- var train_count: usize = 0;
- for (1..train_end) |i| {
- const prev = wc.tokens[i - 1];
- const curr = wc.tokens[i];
- const prob = wc.wordBigramProb(prev, curr);
- train_log_sum += @log(@max(prob, 1e-20));
- train_count += 1;
- }
-
- // === Word-level eval PPL ===
- var eval_log_sum: f64 = 0;
- var eval_count: usize = 0;
- for (train_end..wc.token_count) |i| {
- if (i == 0) continue;
- const prev = wc.tokens[i - 1];
- const curr = wc.tokens[i];
- const prob = wc.wordBigramProb(prev, curr);
- eval_log_sum += @log(@max(prob, 1e-20));
- eval_count += 1;
- }
-
- const train_ppl = @exp(-train_log_sum / @as(f64, @floatFromInt(train_count)));
- const eval_ppl = @exp(-eval_log_sum / @as(f64, @floatFromInt(eval_count)));
-
- // === Also compute char-level raw freq PPL for comparison ===
- const bi_counts = buildHebbianCounts(large_corpus);
- const tri_counts = buildTrigramCounts(large_corpus);
- const char_train_end = large_corpus.len * 80 / 100;
-
- var char_eval_log: f64 = 0;
- var char_eval_valid: usize = 0;
- for (0..40) |i| {
- const s = char_train_end + i * (large_corpus.len - char_train_end - 10) / 40;
- if (s + 8 >= large_corpus.len) continue;
- const prev = large_corpus[s + 6];
- const last = large_corpus[s + 7];
- const target = large_corpus[s + 8];
- const prob = rawTrigramProb(prev, last, target, &bi_counts, &tri_counts);
- char_eval_log += @log(@max(prob, 1e-20));
- char_eval_valid += 1;
- }
- const char_eval_ppl = @exp(-char_eval_log / @as(f64, @floatFromInt(char_eval_valid)));
-
- std.debug.print("\n=== WORD-LEVEL PERPLEXITY (v2.45) ===\n", .{});
- std.debug.print("Vocabulary: {d} unique words, {d} tokens\n", .{ wc.vocab_size, wc.token_count });
- std.debug.print("Word bigram train PPL: {d:.2}\n", .{train_ppl});
- std.debug.print("Word bigram eval PPL: {d:.2}\n", .{eval_ppl});
- std.debug.print("Word bigram overfit gap: {d:.2}\n", .{eval_ppl - train_ppl});
- std.debug.print("Random word baseline: {d:.1}\n", .{@as(f64, @floatFromInt(wc.vocab_size))});
- std.debug.print("--------------------------------------------\n", .{});
- std.debug.print("Char-level raw freq (v2.44): eval PPL={d:.2}\n", .{char_eval_ppl});
- std.debug.print("Char random baseline: 95.0\n", .{});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(train_ppl > 0.0);
- try std.testing.expect(eval_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(train_ppl));
- try std.testing.expect(!std.math.isInf(eval_ppl));
- try std.testing.expect(eval_ppl < @as(f64, @floatFromInt(wc.vocab_size)));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 38: Word trigram statistics + generation (v2.46)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "word trigram statistics and generation" {
- var wtm = WordTrigramModel.init();
- wtm.tokenize(large_corpus);
- wtm.buildBigrams();
- wtm.buildTrigrams();
-
- // Count trigram coverage
- var trigram_slots_used: usize = 0;
- var total_trigram_obs: usize = 0;
- for (0..WORD_TRI_HASH_SIZE) |i| {
- if (wtm.tri_slots[i].valid) {
- trigram_slots_used += 1;
- total_trigram_obs += wtm.tri_slots[i].total_count;
- }
- }
-
- // === Loss comparison: trigram vs bigram on eval split ===
- const train_end = wtm.token_count * 80 / 100;
- const random_ce = @log(@as(f64, @floatFromInt(wtm.vocab_size)));
-
- // Trigram eval loss
- var tri_eval_sum: f64 = 0;
- var tri_eval_count: usize = 0;
- for (train_end..wtm.token_count) |i| {
- if (i < 2) continue;
- const p2 = wtm.tokens[i - 2];
- const p1 = wtm.tokens[i - 1];
- const nx = wtm.tokens[i];
- tri_eval_sum += wtm.wordTrigramLoss(p2, p1, nx);
- tri_eval_count += 1;
- }
- const tri_eval_ce = tri_eval_sum / @as(f64, @floatFromInt(tri_eval_count));
-
- // Trigram train loss
- var tri_train_sum: f64 = 0;
- var tri_train_count: usize = 0;
- for (2..train_end) |i| {
- const p2 = wtm.tokens[i - 2];
- const p1 = wtm.tokens[i - 1];
- const nx = wtm.tokens[i];
- tri_train_sum += wtm.wordTrigramLoss(p2, p1, nx);
- tri_train_count += 1;
- }
- const tri_train_ce = tri_train_sum / @as(f64, @floatFromInt(tri_train_count));
-
- // Bigram eval loss (for comparison)
- var bi_eval_sum: f64 = 0;
- var bi_eval_count: usize = 0;
- for (train_end..wtm.token_count) |i| {
- if (i < 1) continue;
- const p1 = wtm.tokens[i - 1];
- const nx = wtm.tokens[i];
- var bi_total: u32 = 0;
- for (0..wtm.vocab_size) |j| {
- bi_total += wtm.bigram_counts[p1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(wtm.bigram_counts[p1][nx]);
- const total: f64 = @floatFromInt(bi_total);
- const vs: f64 = @floatFromInt(wtm.vocab_size);
- const prob = (count + 0.1) / (total + 0.1 * vs);
- bi_eval_sum += -@log(@max(prob, 1e-20));
- } else {
- bi_eval_sum += random_ce;
- }
- bi_eval_count += 1;
- }
- const bi_eval_ce = bi_eval_sum / @as(f64, @floatFromInt(bi_eval_count));
-
- // === Generation at 3 temperatures ===
- // Find "to" token for consistent start
- var start_token: u16 = 0;
- for (0..wtm.vocab_size) |i| {
- const w = wtm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') {
- start_token = @intCast(i);
- break;
- }
- }
- // Find "be" token
- var be_token: u16 = 0;
- for (0..wtm.vocab_size) |i| {
- const w = wtm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 'b' and w[1] == 'e') {
- be_token = @intCast(i);
- break;
- }
- }
-
- // T=0.8 generation
- var gen_buf1: [512]u8 = undefined;
- var gen1_len: usize = 0;
- var prev2: u16 = start_token;
- var prev1: u16 = be_token;
- for (0..30) |step| {
- const next = wtm.sampleNextWord(prev2, prev1, 0.8, 12345 + step);
- const word = wtm.getWord(next);
- if (gen1_len + word.len + 1 < gen_buf1.len) {
- if (gen1_len > 0) {
- gen_buf1[gen1_len] = ' ';
- gen1_len += 1;
- }
- for (word) |c| {
- gen_buf1[gen1_len] = c;
- gen1_len += 1;
- }
- }
- prev2 = prev1;
- prev1 = next;
- }
-
- // T=0.5 generation
- var gen_buf2: [512]u8 = undefined;
- var gen2_len: usize = 0;
- prev2 = start_token;
- prev1 = be_token;
- for (0..30) |step| {
- const next = wtm.sampleNextWord(prev2, prev1, 0.5, 54321 + step);
- const word = wtm.getWord(next);
- if (gen2_len + word.len + 1 < gen_buf2.len) {
- if (gen2_len > 0) {
- gen_buf2[gen2_len] = ' ';
- gen2_len += 1;
- }
- for (word) |c| {
- gen_buf2[gen2_len] = c;
- gen2_len += 1;
- }
- }
- prev2 = prev1;
- prev1 = next;
- }
-
- // T=0.3 generation
- var gen_buf3: [512]u8 = undefined;
- var gen3_len: usize = 0;
- prev2 = start_token;
- prev1 = be_token;
- for (0..30) |step| {
- const next = wtm.sampleNextWord(prev2, prev1, 0.3, 99999 + step);
- const word = wtm.getWord(next);
- if (gen3_len + word.len + 1 < gen_buf3.len) {
- if (gen3_len > 0) {
- gen_buf3[gen3_len] = ' ';
- gen3_len += 1;
- }
- for (word) |c| {
- gen_buf3[gen3_len] = c;
- gen3_len += 1;
- }
- }
- prev2 = prev1;
- prev1 = next;
- }
-
- // Count trigram hit rate on eval
- var tri_hits: usize = 0;
- var tri_total_checks: usize = 0;
- for (train_end..wtm.token_count) |i| {
- if (i < 2) continue;
- if (wtm.findSlot(wtm.tokens[i - 2], wtm.tokens[i - 1])) |_| {
- tri_hits += 1;
- }
- tri_total_checks += 1;
- }
-
- std.debug.print("\n=== WORD TRIGRAM STATISTICS (v2.46) ===\n", .{});
- std.debug.print("Corpus: {d} chars β {d} tokens, {d} unique words\n", .{ large_corpus.len, wtm.token_count, wtm.vocab_size });
- std.debug.print("Trigram slots used: {d}/{d}\n", .{ trigram_slots_used, WORD_TRI_HASH_SIZE });
- std.debug.print("Total trigram observations: {d}\n", .{total_trigram_obs});
- std.debug.print("Trigram eval hit rate: {d}/{d} ({d:.1}%)\n", .{ tri_hits, tri_total_checks, @as(f64, @floatFromInt(tri_hits)) / @as(f64, @floatFromInt(@max(tri_total_checks, 1))) * 100.0 });
- std.debug.print("\n--- Loss Comparison (CE nats) ---\n", .{});
- std.debug.print("Word trigram eval CE: {d:.4} ({d:.1}% below random)\n", .{ tri_eval_ce, (1.0 - tri_eval_ce / random_ce) * 100.0 });
- std.debug.print("Word trigram train CE: {d:.4} ({d:.1}% below random)\n", .{ tri_train_ce, (1.0 - tri_train_ce / random_ce) * 100.0 });
- std.debug.print("Word bigram eval CE: {d:.4} ({d:.1}% below random)\n", .{ bi_eval_ce, (1.0 - bi_eval_ce / random_ce) * 100.0 });
- std.debug.print("Random CE: {d:.4} (ln({d}))\n", .{ random_ce, wtm.vocab_size });
- std.debug.print("\n--- Generation (word trigram, start: \"to be\") ---\n", .{});
- std.debug.print("T=0.8: \"{s}\"\n", .{gen_buf1[0..gen1_len]});
- std.debug.print("T=0.5: \"{s}\"\n", .{gen_buf2[0..gen2_len]});
- std.debug.print("T=0.3: \"{s}\"\n", .{gen_buf3[0..gen3_len]});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(wtm.vocab_size > 0);
- try std.testing.expect(trigram_slots_used > 0);
- try std.testing.expect(tri_eval_ce < random_ce);
- // NOTE: trigram CE can be worse than bigram on small corpus (data sparsity)
- // But generation quality is much better (actual Shakespeare phrases recalled)
- try std.testing.expect(tri_eval_ce < random_ce * 0.95);
- try std.testing.expect(gen1_len > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 39: Word trigram perplexity comparison (v2.46)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "word trigram perplexity comparison" {
- var wtm = WordTrigramModel.init();
- wtm.tokenize(large_corpus);
- wtm.buildBigrams();
- wtm.buildTrigrams();
-
- const train_end = wtm.token_count * 80 / 100;
-
- // === Word trigram train PPL ===
- var tri_train_log: f64 = 0;
- var tri_train_n: usize = 0;
- for (2..train_end) |i| {
- const p2 = wtm.tokens[i - 2];
- const p1 = wtm.tokens[i - 1];
- const nx = wtm.tokens[i];
- const prob = wtm.wordTrigramProb(p2, p1, nx);
- tri_train_log += @log(@max(prob, 1e-20));
- tri_train_n += 1;
- }
- const tri_train_ppl = @exp(-tri_train_log / @as(f64, @floatFromInt(tri_train_n)));
-
- // === Word trigram eval PPL ===
- var tri_eval_log: f64 = 0;
- var tri_eval_n: usize = 0;
- for (train_end..wtm.token_count) |i| {
- if (i < 2) continue;
- const p2 = wtm.tokens[i - 2];
- const p1 = wtm.tokens[i - 1];
- const nx = wtm.tokens[i];
- const prob = wtm.wordTrigramProb(p2, p1, nx);
- tri_eval_log += @log(@max(prob, 1e-20));
- tri_eval_n += 1;
- }
- const tri_eval_ppl = @exp(-tri_eval_log / @as(f64, @floatFromInt(tri_eval_n)));
-
- // === Word bigram PPL for comparison ===
- var bi_train_log: f64 = 0;
- var bi_train_n: usize = 0;
- for (1..train_end) |i| {
- const p1 = wtm.tokens[i - 1];
- const nx = wtm.tokens[i];
- var bi_total: u32 = 0;
- for (0..wtm.vocab_size) |j| {
- bi_total += wtm.bigram_counts[p1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(wtm.bigram_counts[p1][nx]);
- const total: f64 = @floatFromInt(bi_total);
- const vs: f64 = @floatFromInt(wtm.vocab_size);
- const prob = (count + 0.1) / (total + 0.1 * vs);
- bi_train_log += @log(@max(prob, 1e-20));
- } else {
- bi_train_log += -@log(@as(f64, @floatFromInt(wtm.vocab_size)));
- }
- bi_train_n += 1;
- }
- const bi_train_ppl = @exp(-bi_train_log / @as(f64, @floatFromInt(bi_train_n)));
-
- var bi_eval_log: f64 = 0;
- var bi_eval_n: usize = 0;
- for (train_end..wtm.token_count) |i| {
- if (i < 1) continue;
- const p1 = wtm.tokens[i - 1];
- const nx = wtm.tokens[i];
- var bi_total: u32 = 0;
- for (0..wtm.vocab_size) |j| {
- bi_total += wtm.bigram_counts[p1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(wtm.bigram_counts[p1][nx]);
- const total: f64 = @floatFromInt(bi_total);
- const vs: f64 = @floatFromInt(wtm.vocab_size);
- const prob = (count + 0.1) / (total + 0.1 * vs);
- bi_eval_log += @log(@max(prob, 1e-20));
- } else {
- bi_eval_log += -@log(@as(f64, @floatFromInt(wtm.vocab_size)));
- }
- bi_eval_n += 1;
- }
- const bi_eval_ppl = @exp(-bi_eval_log / @as(f64, @floatFromInt(bi_eval_n)));
-
- std.debug.print("\n=== WORD TRIGRAM PERPLEXITY (v2.46) ===\n", .{});
- std.debug.print("Word trigram: train={d:.2} eval={d:.2} gap={d:.2}\n", .{ tri_train_ppl, tri_eval_ppl, tri_eval_ppl - tri_train_ppl });
- std.debug.print("Word bigram: train={d:.2} eval={d:.2} gap={d:.2}\n", .{ bi_train_ppl, bi_eval_ppl, bi_eval_ppl - bi_train_ppl });
- std.debug.print("Trigram improvement: {d:.1}% lower eval PPL\n", .{(1.0 - tri_eval_ppl / bi_eval_ppl) * 100.0});
- std.debug.print("Random baseline: {d:.1}\n", .{@as(f64, @floatFromInt(wtm.vocab_size))});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(tri_train_ppl > 0.0);
- try std.testing.expect(tri_eval_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(tri_eval_ppl));
- try std.testing.expect(!std.math.isInf(tri_eval_ppl));
- try std.testing.expect(tri_eval_ppl < @as(f64, @floatFromInt(wtm.vocab_size)));
- // On small corpus, trigram PPL may be worse than bigram (data sparsity)
- // But it must still beat random baseline
- try std.testing.expect(tri_eval_ppl < @as(f64, @floatFromInt(wtm.vocab_size)) * 0.5);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LARGE CORPUS TRIGRAM MODEL (v2.47)
-// 25K+ chars Shakespeare corpus loaded via @embedFile
-// Larger vocabulary (512), more tokens (8192), bigger trigram hash (8192 slots)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const LARGE_MAX_WORDS: usize = 512;
-const LARGE_MAX_TOKENS: usize = 8192;
-const LARGE_TRI_HASH_SIZE: usize = 8192;
-const LARGE_TRI_MAX_NEXTS: usize = 48;
-
-const LargeTrigramSlot = struct {
- prev2: u16,
- prev1: u16,
- valid: bool,
- nexts: [LARGE_TRI_MAX_NEXTS]u16,
- counts: [LARGE_TRI_MAX_NEXTS]u16,
- num_nexts: u8,
- total_count: u16,
-};
-
-// v2.51: 4-gram slot (keyed on prev3, prev2, prev1)
-const LARGE_4GRAM_HASH_SIZE: usize = 16384;
-const LARGE_4GRAM_MAX_NEXTS: usize = 32;
-
-const Large4gramSlot = struct {
- prev3: u16,
- prev2: u16,
- prev1: u16,
- valid: bool,
- nexts: [LARGE_4GRAM_MAX_NEXTS]u16,
- counts: [LARGE_4GRAM_MAX_NEXTS]u16,
- num_nexts: u8,
- total_count: u16,
-};
-
-const LargeTrigramModel = struct {
- vocab: [LARGE_MAX_WORDS][MAX_WORD_LEN]u8,
- vocab_lens: [LARGE_MAX_WORDS]u8,
- vocab_size: usize,
- tokens: [LARGE_MAX_TOKENS]u16,
- token_count: usize,
-
- // Flat bigram array: 512*512*2 = 512KB (fits in test stack)
- bigram_counts: [LARGE_MAX_WORDS][LARGE_MAX_WORDS]u16,
-
- // Sparse trigram hash table
- tri_slots: [LARGE_TRI_HASH_SIZE]LargeTrigramSlot,
- tri_used: usize,
-
- // Kneser-Ney continuation counts (v2.50)
- continuation_count: [LARGE_MAX_WORDS]u16,
- total_continuations: u32,
-
- // 4-gram sparse hash table (v2.51)
- fourgram_slots: [LARGE_4GRAM_HASH_SIZE]Large4gramSlot,
- fourgram_used: usize,
-
- fn init() LargeTrigramModel {
- var self: LargeTrigramModel = undefined;
- self.vocab_size = 0;
- self.token_count = 0;
- self.tri_used = 0;
- for (0..LARGE_MAX_WORDS) |i| {
- self.vocab_lens[i] = 0;
- for (0..LARGE_MAX_WORDS) |j| {
- self.bigram_counts[i][j] = 0;
- }
- }
- for (0..LARGE_TRI_HASH_SIZE) |i| {
- self.tri_slots[i].valid = false;
- self.tri_slots[i].num_nexts = 0;
- self.tri_slots[i].total_count = 0;
- }
- for (0..LARGE_MAX_WORDS) |i| {
- self.continuation_count[i] = 0;
- }
- self.total_continuations = 0;
- for (0..LARGE_4GRAM_HASH_SIZE) |i| {
- self.fourgram_slots[i].valid = false;
- self.fourgram_slots[i].num_nexts = 0;
- self.fourgram_slots[i].total_count = 0;
- }
- self.fourgram_used = 0;
- return self;
- }
-
- fn getOrAddWord(self: *LargeTrigramModel, word: []const u8) u16 {
- if (word.len == 0 or word.len > MAX_WORD_LEN) return 0;
- for (0..self.vocab_size) |i| {
- const len = self.vocab_lens[i];
- if (len == word.len) {
- var match = true;
- for (0..len) |j| {
- if (self.vocab[i][j] != word[j]) {
- match = false;
- break;
- }
- }
- if (match) return @intCast(i);
- }
- }
- if (self.vocab_size >= LARGE_MAX_WORDS) return 0; // cap vocabulary
- const idx = self.vocab_size;
- for (0..word.len) |j| {
- self.vocab[idx][j] = word[j];
- }
- self.vocab_lens[idx] = @intCast(word.len);
- self.vocab_size += 1;
- return @intCast(idx);
- }
-
- fn getWord(self: *const LargeTrigramModel, idx: u16) []const u8 {
- if (idx >= self.vocab_size) return "";
- const len = self.vocab_lens[idx];
- return self.vocab[idx][0..len];
- }
-
- fn tokenize(self: *LargeTrigramModel, corpus: []const u8) void {
- var i: usize = 0;
- while (i < corpus.len and self.token_count < LARGE_MAX_TOKENS) {
- while (i < corpus.len and (corpus[i] == ' ' or corpus[i] == '\n')) : (i += 1) {}
- if (i >= corpus.len) break;
- const start = i;
- while (i < corpus.len and corpus[i] != ' ' and corpus[i] != '\n') : (i += 1) {}
- const word = corpus[start..i];
- if (word.len > 0 and word.len <= MAX_WORD_LEN) {
- const idx = self.getOrAddWord(word);
- self.tokens[self.token_count] = idx;
- self.token_count += 1;
- }
- }
- }
-
- fn buildBigrams(self: *LargeTrigramModel) void {
- if (self.token_count < 2) return;
- for (0..self.token_count - 1) |i| {
- const prev = self.tokens[i];
- const next = self.tokens[i + 1];
- if (self.bigram_counts[prev][next] < 65535) {
- self.bigram_counts[prev][next] += 1;
- }
- }
- }
-
- fn triHash(prev2: u16, prev1: u16) usize {
- const key: u32 = @as(u32, prev2) * 257 + @as(u32, prev1);
- return @intCast((key ^ (key >> 11) ^ (key >> 22)) % LARGE_TRI_HASH_SIZE);
- }
-
- fn getOrCreateSlot(self: *LargeTrigramModel, prev2: u16, prev1: u16) ?*LargeTrigramSlot {
- var h = triHash(prev2, prev1);
- var probes: usize = 0;
- while (probes < LARGE_TRI_HASH_SIZE) : (probes += 1) {
- const slot = &self.tri_slots[h];
- if (!slot.valid) {
- slot.valid = true;
- slot.prev2 = prev2;
- slot.prev1 = prev1;
- slot.num_nexts = 0;
- slot.total_count = 0;
- self.tri_used += 1;
- return slot;
- }
- if (slot.prev2 == prev2 and slot.prev1 == prev1) return slot;
- h = (h + 1) % LARGE_TRI_HASH_SIZE;
- }
- return null;
- }
-
- fn findSlot(self: *const LargeTrigramModel, prev2: u16, prev1: u16) ?*const LargeTrigramSlot {
- var h = triHash(prev2, prev1);
- var probes: usize = 0;
- while (probes < LARGE_TRI_HASH_SIZE) : (probes += 1) {
- const slot = &self.tri_slots[h];
- if (!slot.valid) return null;
- if (slot.prev2 == prev2 and slot.prev1 == prev1) return slot;
- h = (h + 1) % LARGE_TRI_HASH_SIZE;
- }
- return null;
- }
-
- fn buildTrigrams(self: *LargeTrigramModel) void {
- if (self.token_count < 3) return;
- for (0..self.token_count - 2) |i| {
- const p2 = self.tokens[i];
- const p1 = self.tokens[i + 1];
- const nx = self.tokens[i + 2];
- if (self.getOrCreateSlot(p2, p1)) |slot| {
- var found = false;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == nx) {
- if (slot.counts[k] < 65535) slot.counts[k] += 1;
- slot.total_count +|= 1;
- found = true;
- break;
- }
- }
- if (!found and slot.num_nexts < LARGE_TRI_MAX_NEXTS) {
- slot.nexts[slot.num_nexts] = nx;
- slot.counts[slot.num_nexts] = 1;
- slot.num_nexts += 1;
- slot.total_count +|= 1;
- }
- }
- }
- }
-
- fn wordTrigramProb(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16) f64 {
- const vs: f64 = @floatFromInt(self.vocab_size);
- if (self.findSlot(prev2, prev1)) |slot| {
- if (slot.total_count > 0) {
- var count: f64 = 0;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == next_idx) {
- count = @floatFromInt(slot.counts[k]);
- break;
- }
- }
- const total: f64 = @floatFromInt(slot.total_count);
- return (count + 0.1) / (total + 0.1 * vs);
- }
- }
- // Bigram fallback
- var bi_total: u32 = 0;
- for (0..self.vocab_size) |j| {
- bi_total += self.bigram_counts[prev1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(self.bigram_counts[prev1][next_idx]);
- const total: f64 = @floatFromInt(bi_total);
- return (count + 0.1) / (total + 0.1 * vs);
- }
- return 1.0 / vs;
- }
-
- fn sampleNextWord(self: *const LargeTrigramModel, prev2: u16, prev1: u16, temperature: f64, seed: u64) u16 {
- var probs: [LARGE_MAX_WORDS]f64 = undefined;
- const vs: f64 = @floatFromInt(self.vocab_size);
-
- var use_trigram = false;
- if (self.findSlot(prev2, prev1)) |slot| {
- if (slot.total_count > 0) {
- use_trigram = true;
- const total: f64 = @floatFromInt(slot.total_count);
- const smooth = 0.1 * vs;
- for (0..self.vocab_size) |j| {
- probs[j] = 0.1 / (total + smooth);
- }
- for (0..slot.num_nexts) |k| {
- const idx = slot.nexts[k];
- const count: f64 = @floatFromInt(slot.counts[k]);
- probs[idx] = (count + 0.1) / (total + smooth);
- }
- }
- }
-
- if (!use_trigram) {
- var bi_total: u32 = 0;
- for (0..self.vocab_size) |j| {
- bi_total += self.bigram_counts[prev1][j];
- }
- if (bi_total > 0) {
- const total: f64 = @floatFromInt(bi_total);
- const smooth = 0.1 * vs;
- for (0..self.vocab_size) |j| {
- const count: f64 = @floatFromInt(self.bigram_counts[prev1][j]);
- probs[j] = (count + 0.1) / (total + smooth);
- }
- } else {
- return @intCast(seed % self.vocab_size);
- }
- }
-
- // Temperature + softmax
- var max_logp: f64 = -1e10;
- for (0..self.vocab_size) |j| {
- const logp = @log(@max(probs[j], 1e-20));
- probs[j] = logp;
- if (logp > max_logp) max_logp = logp;
- }
- var sum: f64 = 0;
- for (0..self.vocab_size) |j| {
- probs[j] = @exp((probs[j] - max_logp) / @max(temperature, 0.01));
- sum += probs[j];
- }
- for (0..self.vocab_size) |j| {
- probs[j] /= sum;
- }
-
- var rng = seed;
- rng ^= rng >> 12;
- rng ^= rng << 25;
- rng ^= rng >> 27;
- const r: f64 = @as(f64, @floatFromInt(rng % 1000000)) / 1000000.0;
-
- var cumulative: f64 = 0;
- for (0..self.vocab_size) |j| {
- cumulative += probs[j];
- if (r < cumulative) return @intCast(j);
- }
- return 0;
- }
-
- fn wordTrigramLoss(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16) f64 {
- const p = self.wordTrigramProb(prev2, prev1, next_idx);
- return -@log(@max(p, 1e-20));
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // INTERPOLATED METHODS (v2.48) β λ·P_tri + (1-Ξ»)Β·P_bi
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Bigram-only probability P(next | prev1) with Laplace smoothing
- fn wordBigramProb(self: *const LargeTrigramModel, prev1: u16, next_idx: u16) f64 {
- const vs: f64 = @floatFromInt(self.vocab_size);
- var bi_total: u32 = 0;
- for (0..self.vocab_size) |j| {
- bi_total += self.bigram_counts[prev1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(self.bigram_counts[prev1][next_idx]);
- const total: f64 = @floatFromInt(bi_total);
- return (count + 0.1) / (total + 0.1 * vs);
- }
- return 1.0 / vs;
- }
-
- /// Trigram-only probability (no bigram fallback)
- fn pureTrigramProb(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16) f64 {
- const vs: f64 = @floatFromInt(self.vocab_size);
- if (self.findSlot(prev2, prev1)) |slot| {
- if (slot.total_count > 0) {
- var count: f64 = 0;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == next_idx) {
- count = @floatFromInt(slot.counts[k]);
- break;
- }
- }
- const total: f64 = @floatFromInt(slot.total_count);
- return (count + 0.1) / (total + 0.1 * vs);
- }
- }
- // No trigram data: return uniform (not bigram fallback)
- return 1.0 / vs;
- }
-
- /// Interpolated probability: λ·P_tri(next|prev2,prev1) + (1-λ)·P_bi(next|prev1)
- fn interpolatedProb(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16, lambda: f64) f64 {
- const p_tri = self.pureTrigramProb(prev2, prev1, next_idx);
- const p_bi = self.wordBigramProb(prev1, next_idx);
- return lambda * p_tri + (1.0 - lambda) * p_bi;
- }
-
- /// Interpolated loss: -log(interpolatedProb)
- fn interpolatedLoss(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16, lambda: f64) f64 {
- const p = self.interpolatedProb(prev2, prev1, next_idx, lambda);
- return -@log(@max(p, 1e-20));
- }
-
- /// Sample with interpolated distribution
- fn interpolatedSample(self: *const LargeTrigramModel, prev2: u16, prev1: u16, lambda: f64, temperature: f64, seed: u64) u16 {
- var probs: [LARGE_MAX_WORDS]f64 = undefined;
-
- // Build interpolated distribution for all words
- for (0..self.vocab_size) |j| {
- const j16: u16 = @intCast(j);
- probs[j] = self.interpolatedProb(prev2, prev1, j16, lambda);
- }
-
- // Temperature in log-space
- var max_logp: f64 = -1e10;
- for (0..self.vocab_size) |j| {
- const logp = @log(@max(probs[j], 1e-20));
- probs[j] = logp;
- if (logp > max_logp) max_logp = logp;
- }
- var sum: f64 = 0;
- for (0..self.vocab_size) |j| {
- probs[j] = @exp((probs[j] - max_logp) / @max(temperature, 0.01));
- sum += probs[j];
- }
- for (0..self.vocab_size) |j| {
- probs[j] /= sum;
- }
-
- var rng = seed;
- rng ^= rng >> 12;
- rng ^= rng << 25;
- rng ^= rng >> 27;
- const r: f64 = @as(f64, @floatFromInt(rng % 1000000)) / 1000000.0;
-
- var cumulative: f64 = 0;
- for (0..self.vocab_size) |j| {
- cumulative += probs[j];
- if (r < cumulative) return @intCast(j);
- }
- return 0;
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // v2.49: Repetition Penalty + N-gram Blocking
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- const PENALTY_MAX_HISTORY: usize = 64;
- const PENALTY_NGRAM_ORDER: usize = 3; // block repeated trigrams
-
- /// Sample with interpolated distribution + repetition penalty + n-gram blocking
- /// penalty_alpha: multiplicative penalty per repeat (e.g., 1.2 = reduce by 1.2x per occurrence)
- /// block_ngram: if true, zero out probability of any word that would create a repeated n-gram
- fn penaltySample(
- self: *const LargeTrigramModel,
- prev2: u16,
- prev1: u16,
- lambda: f64,
- temperature: f64,
- seed: u64,
- history: []const u16,
- history_len: usize,
- penalty_alpha: f64,
- block_ngram: bool,
- ) u16 {
- var probs: [LARGE_MAX_WORDS]f64 = undefined;
-
- // Build interpolated distribution
- for (0..self.vocab_size) |j| {
- const j16: u16 = @intCast(j);
- probs[j] = self.interpolatedProb(prev2, prev1, j16, lambda);
- }
-
- // Apply repetition penalty: divide probability by alpha^count(word_in_history)
- if (penalty_alpha > 1.0) {
- for (0..self.vocab_size) |j| {
- var count: usize = 0;
- const j16: u16 = @intCast(j);
- for (0..history_len) |h| {
- if (history[h] == j16) count += 1;
- }
- if (count > 0) {
- // Apply penalty: P(w) /= alpha^count
- var penalty: f64 = 1.0;
- for (0..count) |_| {
- penalty *= penalty_alpha;
- }
- probs[j] /= penalty;
- }
- }
- }
-
- // N-gram blocking: zero out words that would create a repeated trigram
- if (block_ngram and history_len >= 2) {
- for (0..self.vocab_size) |j| {
- const j16: u16 = @intCast(j);
- // Would (prev2, prev1, j16) repeat a trigram from history?
- if (history_len >= 3) {
- var h: usize = 0;
- while (h + 2 < history_len) : (h += 1) {
- if (history[h] == prev2 and history[h + 1] == prev1 and history[h + 2] == j16) {
- probs[j] = 0;
- break;
- }
- }
- }
- }
- }
-
- // Temperature in log-space
- var max_logp: f64 = -1e10;
- for (0..self.vocab_size) |j| {
- if (probs[j] <= 0) {
- probs[j] = -1e10;
- } else {
- probs[j] = @log(probs[j]);
- }
- if (probs[j] > max_logp) max_logp = probs[j];
- }
- var sum: f64 = 0;
- for (0..self.vocab_size) |j| {
- probs[j] = @exp((probs[j] - max_logp) / @max(temperature, 0.01));
- sum += probs[j];
- }
- if (sum > 0) {
- for (0..self.vocab_size) |j| {
- probs[j] /= sum;
- }
- } else {
- // All blocked β fall back to uniform
- for (0..self.vocab_size) |j| {
- probs[j] = 1.0 / @as(f64, @floatFromInt(self.vocab_size));
- }
- }
-
- var rng = seed;
- rng ^= rng >> 12;
- rng ^= rng << 25;
- rng ^= rng >> 27;
- const r: f64 = @as(f64, @floatFromInt(rng % 1000000)) / 1000000.0;
-
- var cumul: f64 = 0;
- for (0..self.vocab_size) |j| {
- cumul += probs[j];
- if (r < cumul) return @intCast(j);
- }
- return 0;
- }
-
- /// Count unique words in a token sequence
- fn countUnique(tokens: []const u16, len: usize) usize {
- var seen: [LARGE_MAX_WORDS]bool = [_]bool{false} ** LARGE_MAX_WORDS;
- var count: usize = 0;
- for (0..len) |i| {
- if (!seen[tokens[i]]) {
- seen[tokens[i]] = true;
- count += 1;
- }
- }
- return count;
- }
-
- /// Check if any trigram repeats in a token sequence
- fn hasRepeatedTrigram(tokens: []const u16, len: usize) bool {
- if (len < 6) return false; // need at least 2 trigrams
- var i: usize = 0;
- while (i + 2 < len) : (i += 1) {
- var j: usize = i + 1;
- while (j + 2 < len) : (j += 1) {
- if (tokens[i] == tokens[j] and tokens[i + 1] == tokens[j + 1] and tokens[i + 2] == tokens[j + 2]) {
- return true;
- }
- }
- }
- return false;
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // v2.50: Kneser-Ney Smoothing
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- /// Build Kneser-Ney continuation counts from bigram data.
- /// continuation_count[w] = number of unique w' such that c(w', w) > 0
- /// (how many distinct left contexts does w appear in?)
- /// Also computes total_continuations = sum of all continuation_count[w]
- fn buildContinuationCounts(self: *LargeTrigramModel) void {
- // continuation_count[w] = |{w': bigram_counts[w'][w] > 0}|
- for (0..LARGE_MAX_WORDS) |w| {
- var count: u16 = 0;
- for (0..self.vocab_size) |wprime| {
- if (self.bigram_counts[wprime][w] > 0) {
- count += 1;
- }
- }
- self.continuation_count[w] = count;
- }
- // total_continuations = sum of all continuation_count
- var total: u32 = 0;
- for (0..self.vocab_size) |w| {
- total += self.continuation_count[w];
- }
- self.total_continuations = total;
- }
-
- /// Kneser-Ney bigram probability
- /// P_KN(w|w1) = max(c(w1,w) - D, 0) / c(w1) + lambda(w1) * P_cont(w)
- /// where P_cont(w) = continuation_count[w] / total_continuations
- /// and lambda(w1) = D * |{w: c(w1,w) > 0}| / c(w1)
- fn knBigramProb(self: *const LargeTrigramModel, prev1: u16, next_idx: u16, discount: f64) f64 {
- // Total count for context w1
- var total: u32 = 0;
- var unique_next: u32 = 0; // |{w: c(w1,w) > 0}|
- for (0..self.vocab_size) |j| {
- const c = self.bigram_counts[prev1][j];
- total += c;
- if (c > 0) unique_next += 1;
- }
-
- if (total == 0) {
- // Unseen context β return uniform
- return 1.0 / @as(f64, @floatFromInt(self.vocab_size));
- }
-
- const c_w1_w: f64 = @floatFromInt(self.bigram_counts[prev1][next_idx]);
- const total_f: f64 = @floatFromInt(total);
- const d = discount;
-
- // Discounted probability
- const p_discount = @max(c_w1_w - d, 0.0) / total_f;
-
- // Lambda (normalizing backoff weight)
- const lambda = d * @as(f64, @floatFromInt(unique_next)) / total_f;
-
- // Continuation probability P_cont(w)
- const p_cont = if (self.total_continuations > 0)
- @as(f64, @floatFromInt(self.continuation_count[next_idx])) / @as(f64, @floatFromInt(self.total_continuations))
- else
- 1.0 / @as(f64, @floatFromInt(self.vocab_size));
-
- return p_discount + lambda * p_cont;
- }
-
- /// Kneser-Ney trigram probability with bigram KN backoff
- /// P_KN(w|w2,w1) = max(c(w2,w1,w) - D, 0) / c(w2,w1) + lambda(w2,w1) * P_KN_bi(w|w1)
- fn knTrigramProb(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16, discount: f64) f64 {
- if (self.findSlot(prev2, prev1)) |slot| {
- const total_f: f64 = @floatFromInt(slot.total_count);
- if (total_f == 0) return self.knBigramProb(prev1, next_idx, discount);
-
- // Find count for next_idx in this slot
- var c_tri: f64 = 0;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == next_idx) {
- c_tri = @floatFromInt(slot.counts[k]);
- break;
- }
- }
-
- // Discounted probability
- const p_discount = @max(c_tri - discount, 0.0) / total_f;
-
- // Lambda: D * unique_nexts / total
- const lambda = discount * @as(f64, @floatFromInt(slot.num_nexts)) / total_f;
-
- // Backoff to KN bigram
- return p_discount + lambda * self.knBigramProb(prev1, next_idx, discount);
- } else {
- // Unseen trigram context β full backoff to KN bigram
- return self.knBigramProb(prev1, next_idx, discount);
- }
- }
-
- /// Interpolated Kneser-Ney: λ·P_KN_tri + (1-λ)·P_KN_bi
- fn knInterpolatedProb(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16, lambda: f64, discount: f64) f64 {
- const p_tri = self.knTrigramProb(prev2, prev1, next_idx, discount);
- const p_bi = self.knBigramProb(prev1, next_idx, discount);
- return lambda * p_tri + (1.0 - lambda) * p_bi;
- }
-
- /// Kneser-Ney loss
- fn knLoss(self: *const LargeTrigramModel, prev2: u16, prev1: u16, next_idx: u16, lambda: f64, discount: f64) f64 {
- return -@log(@max(self.knInterpolatedProb(prev2, prev1, next_idx, lambda, discount), 1e-20));
- }
-
- /// Sample with Kneser-Ney interpolated distribution + penalty + blocking
- fn knPenaltySample(
- self: *const LargeTrigramModel,
- prev2: u16,
- prev1: u16,
- lambda: f64,
- discount: f64,
- temperature: f64,
- seed: u64,
- history: []const u16,
- history_len: usize,
- penalty_alpha: f64,
- block_ngram: bool,
- ) u16 {
- var probs: [LARGE_MAX_WORDS]f64 = undefined;
-
- // Build KN interpolated distribution
- for (0..self.vocab_size) |j| {
- const j16: u16 = @intCast(j);
- probs[j] = self.knInterpolatedProb(prev2, prev1, j16, lambda, discount);
- }
-
- // Apply repetition penalty
- if (penalty_alpha > 1.0) {
- for (0..self.vocab_size) |j| {
- var count: usize = 0;
- const j16: u16 = @intCast(j);
- for (0..history_len) |h| {
- if (history[h] == j16) count += 1;
- }
- if (count > 0) {
- var penalty: f64 = 1.0;
- for (0..count) |_| penalty *= penalty_alpha;
- probs[j] /= penalty;
- }
- }
- }
-
- // N-gram blocking
- if (block_ngram and history_len >= 3) {
- for (0..self.vocab_size) |j| {
- const j16: u16 = @intCast(j);
- var h: usize = 0;
- while (h + 2 < history_len) : (h += 1) {
- if (history[h] == prev2 and history[h + 1] == prev1 and history[h + 2] == j16) {
- probs[j] = 0;
- break;
- }
- }
- }
- }
-
- // Temperature + softmax + sample
- var max_logp: f64 = -1e10;
- for (0..self.vocab_size) |j| {
- if (probs[j] <= 0) {
- probs[j] = -1e10;
- } else {
- probs[j] = @log(probs[j]);
- }
- if (probs[j] > max_logp) max_logp = probs[j];
- }
- var sum: f64 = 0;
- for (0..self.vocab_size) |j| {
- probs[j] = @exp((probs[j] - max_logp) / @max(temperature, 0.01));
- sum += probs[j];
- }
- if (sum > 0) {
- for (0..self.vocab_size) |j| probs[j] /= sum;
- } else {
- for (0..self.vocab_size) |j| probs[j] = 1.0 / @as(f64, @floatFromInt(self.vocab_size));
- }
-
- var rng = seed;
- rng ^= rng >> 12;
- rng ^= rng << 25;
- rng ^= rng >> 27;
- const r: f64 = @as(f64, @floatFromInt(rng % 1000000)) / 1000000.0;
-
- var cumul: f64 = 0;
- for (0..self.vocab_size) |j| {
- cumul += probs[j];
- if (r < cumul) return @intCast(j);
- }
- return 0;
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // v2.51: 4-gram Extension with KN Backoff
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- fn fourgramHash(prev3: u16, prev2: u16, prev1: u16) usize {
- const key: u64 = @as(u64, prev3) * 65537 + @as(u64, prev2) * 257 + @as(u64, prev1);
- return @intCast((key ^ (key >> 13) ^ (key >> 26)) % LARGE_4GRAM_HASH_SIZE);
- }
-
- fn getOrCreate4gramSlot(self: *LargeTrigramModel, prev3: u16, prev2: u16, prev1: u16) ?*Large4gramSlot {
- var h = fourgramHash(prev3, prev2, prev1);
- var probes: usize = 0;
- while (probes < LARGE_4GRAM_HASH_SIZE) : (probes += 1) {
- const slot = &self.fourgram_slots[h];
- if (!slot.valid) {
- slot.valid = true;
- slot.prev3 = prev3;
- slot.prev2 = prev2;
- slot.prev1 = prev1;
- slot.num_nexts = 0;
- slot.total_count = 0;
- self.fourgram_used += 1;
- return slot;
- }
- if (slot.prev3 == prev3 and slot.prev2 == prev2 and slot.prev1 == prev1) return slot;
- h = (h + 1) % LARGE_4GRAM_HASH_SIZE;
- }
- return null;
- }
-
- fn find4gramSlot(self: *const LargeTrigramModel, prev3: u16, prev2: u16, prev1: u16) ?*const Large4gramSlot {
- var h = fourgramHash(prev3, prev2, prev1);
- var probes: usize = 0;
- while (probes < LARGE_4GRAM_HASH_SIZE) : (probes += 1) {
- const slot = &self.fourgram_slots[h];
- if (!slot.valid) return null;
- if (slot.prev3 == prev3 and slot.prev2 == prev2 and slot.prev1 == prev1) return slot;
- h = (h + 1) % LARGE_4GRAM_HASH_SIZE;
- }
- return null;
- }
-
- fn build4grams(self: *LargeTrigramModel) void {
- if (self.token_count < 4) return;
- for (0..self.token_count - 3) |i| {
- const p3 = self.tokens[i];
- const p2 = self.tokens[i + 1];
- const p1 = self.tokens[i + 2];
- const nx = self.tokens[i + 3];
- if (self.getOrCreate4gramSlot(p3, p2, p1)) |slot| {
- // Check if nx already exists
- var found = false;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == nx) {
- if (slot.counts[k] < 65535) slot.counts[k] += 1;
- slot.total_count += 1;
- found = true;
- break;
- }
- }
- if (!found and slot.num_nexts < LARGE_4GRAM_MAX_NEXTS) {
- slot.nexts[slot.num_nexts] = nx;
- slot.counts[slot.num_nexts] = 1;
- slot.num_nexts += 1;
- slot.total_count += 1;
- }
- }
- }
- }
-
- /// KN 4-gram probability with trigram KN backoff
- fn kn4gramProb(self: *const LargeTrigramModel, prev3: u16, prev2: u16, prev1: u16, next_idx: u16, discount: f64) f64 {
- if (self.find4gramSlot(prev3, prev2, prev1)) |slot| {
- const total_f: f64 = @floatFromInt(slot.total_count);
- if (total_f == 0) return self.knTrigramProb(prev2, prev1, next_idx, discount);
-
- // Find count for next_idx
- var c_4g: f64 = 0;
- for (0..slot.num_nexts) |k| {
- if (slot.nexts[k] == next_idx) {
- c_4g = @floatFromInt(slot.counts[k]);
- break;
- }
- }
-
- // Discounted probability + backoff to KN trigram
- const p_discount = @max(c_4g - discount, 0.0) / total_f;
- const lambda = discount * @as(f64, @floatFromInt(slot.num_nexts)) / total_f;
- return p_discount + lambda * self.knTrigramProb(prev2, prev1, next_idx, discount);
- } else {
- // Unseen 4-gram context β full backoff to KN trigram
- return self.knTrigramProb(prev2, prev1, next_idx, discount);
- }
- }
-
- /// Interpolated 4-gram KN: λ·P_KN_4g + (1-λ)·P_KN_tri
- fn kn4gramInterpolatedProb(self: *const LargeTrigramModel, prev3: u16, prev2: u16, prev1: u16, next_idx: u16, lambda: f64, discount: f64) f64 {
- const p_4g = self.kn4gramProb(prev3, prev2, prev1, next_idx, discount);
- const p_tri = self.knTrigramProb(prev2, prev1, next_idx, discount);
- return lambda * p_4g + (1.0 - lambda) * p_tri;
- }
-
- /// 4-gram KN loss
- fn kn4gramLoss(self: *const LargeTrigramModel, prev3: u16, prev2: u16, prev1: u16, next_idx: u16, lambda: f64, discount: f64) f64 {
- return -@log(@max(self.kn4gramInterpolatedProb(prev3, prev2, prev1, next_idx, lambda, discount), 1e-20));
- }
-
- /// Sample with 4-gram KN + penalty + blocking
- fn kn4gramPenaltySample(
- self: *const LargeTrigramModel,
- prev3: u16,
- prev2: u16,
- prev1: u16,
- lambda: f64,
- discount: f64,
- temperature: f64,
- seed: u64,
- history: []const u16,
- history_len: usize,
- penalty_alpha: f64,
- block_ngram: bool,
- ) u16 {
- var probs: [LARGE_MAX_WORDS]f64 = undefined;
-
- // Build 4-gram KN interpolated distribution
- for (0..self.vocab_size) |j| {
- const j16: u16 = @intCast(j);
- probs[j] = self.kn4gramInterpolatedProb(prev3, prev2, prev1, j16, lambda, discount);
- }
-
- // Repetition penalty
- if (penalty_alpha > 1.0) {
- for (0..self.vocab_size) |j| {
- var count: usize = 0;
- const j16: u16 = @intCast(j);
- for (0..history_len) |h| {
- if (history[h] == j16) count += 1;
- }
- if (count > 0) {
- var penalty: f64 = 1.0;
- for (0..count) |_| penalty *= penalty_alpha;
- probs[j] /= penalty;
- }
- }
- }
-
- // N-gram blocking (block repeated 4-grams)
- if (block_ngram and history_len >= 3) {
- for (0..self.vocab_size) |j| {
- const j16: u16 = @intCast(j);
- var h: usize = 0;
- while (h + 3 < history_len) : (h += 1) {
- if (history[h] == prev3 and history[h + 1] == prev2 and history[h + 2] == prev1 and history[h + 3] == j16) {
- probs[j] = 0;
- break;
- }
- }
- }
- }
-
- // Temperature + softmax + sample
- var max_logp: f64 = -1e10;
- for (0..self.vocab_size) |j| {
- if (probs[j] <= 0) {
- probs[j] = -1e10;
- } else {
- probs[j] = @log(probs[j]);
- }
- if (probs[j] > max_logp) max_logp = probs[j];
- }
- var sum: f64 = 0;
- for (0..self.vocab_size) |j| {
- probs[j] = @exp((probs[j] - max_logp) / @max(temperature, 0.01));
- sum += probs[j];
- }
- if (sum > 0) {
- for (0..self.vocab_size) |j| probs[j] /= sum;
- } else {
- for (0..self.vocab_size) |j| probs[j] = 1.0 / @as(f64, @floatFromInt(self.vocab_size));
- }
-
- var rng = seed;
- rng ^= rng >> 12;
- rng ^= rng << 25;
- rng ^= rng >> 27;
- const r: f64 = @as(f64, @floatFromInt(rng % 1000000)) / 1000000.0;
-
- var cumul4: f64 = 0;
- for (0..self.vocab_size) |j| {
- cumul4 += probs[j];
- if (r < cumul4) return @intCast(j);
- }
- return 0;
- }
-};
-
-const extended_corpus = @embedFile("shakespeare_extended.txt");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 40: Large corpus trigram statistics + generation (v2.47)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "large corpus trigram statistics and generation" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
-
- // Count trigram coverage
- var trigram_slots_used: usize = 0;
- var total_trigram_obs: usize = 0;
- for (0..LARGE_TRI_HASH_SIZE) |i| {
- if (ltm.tri_slots[i].valid) {
- trigram_slots_used += 1;
- total_trigram_obs += ltm.tri_slots[i].total_count;
- }
- }
-
- // Avg observations per context
- const avg_obs: f64 = if (trigram_slots_used > 0) @as(f64, @floatFromInt(total_trigram_obs)) / @as(f64, @floatFromInt(trigram_slots_used)) else 0;
-
- // === Loss on eval split ===
- const train_end = ltm.token_count * 80 / 100;
- const random_ce = @log(@as(f64, @floatFromInt(ltm.vocab_size)));
-
- // Trigram eval CE
- var tri_eval_sum: f64 = 0;
- var tri_eval_count: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- tri_eval_sum += ltm.wordTrigramLoss(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i]);
- tri_eval_count += 1;
- }
- const tri_eval_ce = tri_eval_sum / @as(f64, @floatFromInt(tri_eval_count));
-
- // Trigram train CE
- var tri_train_sum: f64 = 0;
- var tri_train_count: usize = 0;
- for (2..train_end) |i| {
- tri_train_sum += ltm.wordTrigramLoss(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i]);
- tri_train_count += 1;
- }
- const tri_train_ce = tri_train_sum / @as(f64, @floatFromInt(tri_train_count));
-
- // Bigram eval CE (for comparison)
- var bi_eval_sum: f64 = 0;
- var bi_eval_count: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 1) continue;
- const p1 = ltm.tokens[i - 1];
- const nx = ltm.tokens[i];
- var bi_total: u32 = 0;
- for (0..ltm.vocab_size) |j| {
- bi_total += ltm.bigram_counts[p1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(ltm.bigram_counts[p1][nx]);
- const total: f64 = @floatFromInt(bi_total);
- const vs: f64 = @floatFromInt(ltm.vocab_size);
- bi_eval_sum += -@log(@max((count + 0.1) / (total + 0.1 * vs), 1e-20));
- } else {
- bi_eval_sum += random_ce;
- }
- bi_eval_count += 1;
- }
- const bi_eval_ce = bi_eval_sum / @as(f64, @floatFromInt(bi_eval_count));
-
- // Trigram eval hit rate
- var tri_hits: usize = 0;
- var tri_checks: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- if (ltm.findSlot(ltm.tokens[i - 2], ltm.tokens[i - 1])) |_| {
- tri_hits += 1;
- }
- tri_checks += 1;
- }
-
- // === Generation ===
- var start_to: u16 = 0;
- var start_be: u16 = 0;
- for (0..ltm.vocab_size) |i| {
- const w = ltm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') start_to = @intCast(i);
- if (w.len == 2 and w[0] == 'b' and w[1] == 'e') start_be = @intCast(i);
- }
-
- // T=0.8
- var gen1: [512]u8 = undefined;
- var g1: usize = 0;
- var p2: u16 = start_to;
- var p1: u16 = start_be;
- for (0..30) |step| {
- const next = ltm.sampleNextWord(p2, p1, 0.8, 12345 + step);
- const word = ltm.getWord(next);
- if (g1 + word.len + 1 < gen1.len) {
- if (g1 > 0) {
- gen1[g1] = ' ';
- g1 += 1;
- }
- for (word) |c| {
- gen1[g1] = c;
- g1 += 1;
- }
- }
- p2 = p1;
- p1 = next;
- }
-
- // T=0.5
- var gen2: [512]u8 = undefined;
- var g2: usize = 0;
- p2 = start_to;
- p1 = start_be;
- for (0..30) |step| {
- const next = ltm.sampleNextWord(p2, p1, 0.5, 54321 + step);
- const word = ltm.getWord(next);
- if (g2 + word.len + 1 < gen2.len) {
- if (g2 > 0) {
- gen2[g2] = ' ';
- g2 += 1;
- }
- for (word) |c| {
- gen2[g2] = c;
- g2 += 1;
- }
- }
- p2 = p1;
- p1 = next;
- }
-
- // T=0.3
- var gen3: [512]u8 = undefined;
- var g3: usize = 0;
- p2 = start_to;
- p1 = start_be;
- for (0..30) |step| {
- const next = ltm.sampleNextWord(p2, p1, 0.3, 99999 + step);
- const word = ltm.getWord(next);
- if (g3 + word.len + 1 < gen3.len) {
- if (g3 > 0) {
- gen3[g3] = ' ';
- g3 += 1;
- }
- for (word) |c| {
- gen3[g3] = c;
- g3 += 1;
- }
- }
- p2 = p1;
- p1 = next;
- }
-
- std.debug.print("\n=== LARGE CORPUS TRIGRAM (v2.47) ===\n", .{});
- std.debug.print("Corpus: {d} chars β {d} tokens, {d} unique words\n", .{ extended_corpus.len, ltm.token_count, ltm.vocab_size });
- std.debug.print("Trigram slots: {d}/{d} ({d:.1}% load)\n", .{ trigram_slots_used, LARGE_TRI_HASH_SIZE, @as(f64, @floatFromInt(trigram_slots_used)) / @as(f64, @floatFromInt(LARGE_TRI_HASH_SIZE)) * 100.0 });
- std.debug.print("Total trigram observations: {d}\n", .{total_trigram_obs});
- std.debug.print("Avg observations per context: {d:.2}\n", .{avg_obs});
- std.debug.print("Eval trigram hit rate: {d}/{d} ({d:.1}%)\n", .{ tri_hits, tri_checks, @as(f64, @floatFromInt(tri_hits)) / @as(f64, @floatFromInt(@max(tri_checks, 1))) * 100.0 });
- std.debug.print("\n--- Loss (CE nats) ---\n", .{});
- std.debug.print("Trigram eval CE: {d:.4} ({d:.1}% below random)\n", .{ tri_eval_ce, (1.0 - tri_eval_ce / random_ce) * 100.0 });
- std.debug.print("Trigram train CE: {d:.4} ({d:.1}% below random)\n", .{ tri_train_ce, (1.0 - tri_train_ce / random_ce) * 100.0 });
- std.debug.print("Bigram eval CE: {d:.4} ({d:.1}% below random)\n", .{ bi_eval_ce, (1.0 - bi_eval_ce / random_ce) * 100.0 });
- std.debug.print("Random CE: {d:.4} (ln({d}))\n", .{ random_ce, ltm.vocab_size });
- std.debug.print("\n--- Generation (start: \"to be\") ---\n", .{});
- std.debug.print("T=0.8: \"{s}\"\n", .{gen1[0..g1]});
- std.debug.print("T=0.5: \"{s}\"\n", .{gen2[0..g2]});
- std.debug.print("T=0.3: \"{s}\"\n", .{gen3[0..g3]});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(ltm.vocab_size > 256); // larger vocab
- try std.testing.expect(ltm.token_count > 3000); // many more tokens
- try std.testing.expect(trigram_slots_used > 1000); // good coverage
- try std.testing.expect(avg_obs > 1.0); // more data per context
- try std.testing.expect(tri_eval_ce < random_ce);
- try std.testing.expect(g1 > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 41: Large corpus word trigram perplexity (v2.47)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "large corpus word trigram perplexity comparison" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
-
- const train_end = ltm.token_count * 80 / 100;
-
- // Trigram train PPL
- var tri_train_log: f64 = 0;
- var tri_train_n: usize = 0;
- for (2..train_end) |i| {
- const prob = ltm.wordTrigramProb(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i]);
- tri_train_log += @log(@max(prob, 1e-20));
- tri_train_n += 1;
- }
- const tri_train_ppl = @exp(-tri_train_log / @as(f64, @floatFromInt(tri_train_n)));
-
- // Trigram eval PPL
- var tri_eval_log: f64 = 0;
- var tri_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- const prob = ltm.wordTrigramProb(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i]);
- tri_eval_log += @log(@max(prob, 1e-20));
- tri_eval_n += 1;
- }
- const tri_eval_ppl = @exp(-tri_eval_log / @as(f64, @floatFromInt(tri_eval_n)));
-
- // Bigram eval PPL
- var bi_eval_log: f64 = 0;
- var bi_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 1) continue;
- const p1 = ltm.tokens[i - 1];
- const nx = ltm.tokens[i];
- var bi_total: u32 = 0;
- for (0..ltm.vocab_size) |j| {
- bi_total += ltm.bigram_counts[p1][j];
- }
- if (bi_total > 0) {
- const count: f64 = @floatFromInt(ltm.bigram_counts[p1][nx]);
- const total: f64 = @floatFromInt(bi_total);
- const vs: f64 = @floatFromInt(ltm.vocab_size);
- bi_eval_log += @log(@max((count + 0.1) / (total + 0.1 * vs), 1e-20));
- } else {
- bi_eval_log += -@log(@as(f64, @floatFromInt(ltm.vocab_size)));
- }
- bi_eval_n += 1;
- }
- const bi_eval_ppl = @exp(-bi_eval_log / @as(f64, @floatFromInt(bi_eval_n)));
-
- // Previous small-corpus PPL for comparison
- var wtm_small = WordTrigramModel.init();
- wtm_small.tokenize(large_corpus);
- wtm_small.buildBigrams();
- wtm_small.buildTrigrams();
- const small_train_end = wtm_small.token_count * 80 / 100;
- var small_eval_log: f64 = 0;
- var small_eval_n: usize = 0;
- for (small_train_end..wtm_small.token_count) |i| {
- if (i < 2) continue;
- const prob = wtm_small.wordTrigramProb(wtm_small.tokens[i - 2], wtm_small.tokens[i - 1], wtm_small.tokens[i]);
- small_eval_log += @log(@max(prob, 1e-20));
- small_eval_n += 1;
- }
- const small_eval_ppl = @exp(-small_eval_log / @as(f64, @floatFromInt(small_eval_n)));
-
- std.debug.print("\n=== LARGE CORPUS TRIGRAM PERPLEXITY (v2.47) ===\n", .{});
- std.debug.print("Large corpus ({d} tokens, {d} vocab):\n", .{ ltm.token_count, ltm.vocab_size });
- std.debug.print(" Trigram: train={d:.2} eval={d:.2} gap={d:.2}\n", .{ tri_train_ppl, tri_eval_ppl, tri_eval_ppl - tri_train_ppl });
- std.debug.print(" Bigram eval: {d:.2}\n", .{bi_eval_ppl});
- std.debug.print("Small corpus ({d} tokens, {d} vocab):\n", .{ wtm_small.token_count, wtm_small.vocab_size });
- std.debug.print(" Trigram eval: {d:.2}\n", .{small_eval_ppl});
- std.debug.print("Improvement: {d:.1}% lower eval PPL (large vs small trigram)\n", .{(1.0 - tri_eval_ppl / small_eval_ppl) * 100.0});
- std.debug.print("Random baseline: {d:.1}\n", .{@as(f64, @floatFromInt(ltm.vocab_size))});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(tri_train_ppl > 0.0);
- try std.testing.expect(tri_eval_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(tri_eval_ppl));
- try std.testing.expect(!std.math.isInf(tri_eval_ppl));
- try std.testing.expect(tri_eval_ppl < @as(f64, @floatFromInt(ltm.vocab_size)));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 42: Interpolated Ξ» grid search (v2.48)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "interpolated lambda grid search" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
-
- const train_end = ltm.token_count * 80 / 100;
- const random_ce = @log(@as(f64, @floatFromInt(ltm.vocab_size)));
-
- // Grid search over Ξ» values: 0.0, 0.1, 0.2, ..., 1.0
- const lambdas = [_]f64{ 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
- var best_lambda: f64 = 0;
- var best_eval_ce: f64 = 1e10;
-
- std.debug.print("\n=== INTERPOLATED Ξ» GRID SEARCH (v2.48) ===\n", .{});
- std.debug.print("Corpus: {d} tokens, {d} vocab\n", .{ ltm.token_count, ltm.vocab_size });
- std.debug.print("\n Ξ» | Eval CE | %= 0.0 and best_lambda <= 1.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 43: Interpolated PPL + generation (v2.48)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "interpolated perplexity and generation" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
-
- const train_end = ltm.token_count * 80 / 100;
-
- // Use Ξ»=0.3 as a reasonable default (bigram-heavy for sparse trigram)
- const lambda: f64 = 0.3;
-
- // Interpolated train PPL
- var interp_train_log: f64 = 0;
- var interp_train_n: usize = 0;
- for (2..train_end) |i| {
- const prob = ltm.interpolatedProb(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i], lambda);
- interp_train_log += @log(@max(prob, 1e-20));
- interp_train_n += 1;
- }
- const interp_train_ppl = @exp(-interp_train_log / @as(f64, @floatFromInt(interp_train_n)));
-
- // Interpolated eval PPL
- var interp_eval_log: f64 = 0;
- var interp_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- const prob = ltm.interpolatedProb(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i], lambda);
- interp_eval_log += @log(@max(prob, 1e-20));
- interp_eval_n += 1;
- }
- const interp_eval_ppl = @exp(-interp_eval_log / @as(f64, @floatFromInt(interp_eval_n)));
-
- // Pure bigram eval PPL
- var bi_eval_log: f64 = 0;
- var bi_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 1) continue;
- bi_eval_log += @log(@max(ltm.wordBigramProb(ltm.tokens[i - 1], ltm.tokens[i]), 1e-20));
- bi_eval_n += 1;
- }
- const bi_eval_ppl = @exp(-bi_eval_log / @as(f64, @floatFromInt(bi_eval_n)));
-
- // Pure trigram eval PPL (with bigram fallback β old method)
- var tri_eval_log: f64 = 0;
- var tri_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- tri_eval_log += @log(@max(ltm.wordTrigramProb(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i]), 1e-20));
- tri_eval_n += 1;
- }
- const tri_eval_ppl = @exp(-tri_eval_log / @as(f64, @floatFromInt(tri_eval_n)));
-
- // === Generation ===
- var start_to: u16 = 0;
- var start_be: u16 = 0;
- for (0..ltm.vocab_size) |i| {
- const w = ltm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') start_to = @intCast(i);
- if (w.len == 2 and w[0] == 'b' and w[1] == 'e') start_be = @intCast(i);
- }
-
- // T=0.8 interpolated
- var gen1: [512]u8 = undefined;
- var g1: usize = 0;
- var p2: u16 = start_to;
- var p1: u16 = start_be;
- for (0..30) |step| {
- const next = ltm.interpolatedSample(p2, p1, lambda, 0.8, 12345 + step);
- const word = ltm.getWord(next);
- if (g1 + word.len + 1 < gen1.len) {
- if (g1 > 0) {
- gen1[g1] = ' ';
- g1 += 1;
- }
- for (word) |c| {
- gen1[g1] = c;
- g1 += 1;
- }
- }
- p2 = p1;
- p1 = next;
- }
-
- // T=0.5 interpolated
- var gen2: [512]u8 = undefined;
- var g2: usize = 0;
- p2 = start_to;
- p1 = start_be;
- for (0..30) |step| {
- const next = ltm.interpolatedSample(p2, p1, lambda, 0.5, 54321 + step);
- const word = ltm.getWord(next);
- if (g2 + word.len + 1 < gen2.len) {
- if (g2 > 0) {
- gen2[g2] = ' ';
- g2 += 1;
- }
- for (word) |c| {
- gen2[g2] = c;
- g2 += 1;
- }
- }
- p2 = p1;
- p1 = next;
- }
-
- // T=0.3 interpolated
- var gen3: [512]u8 = undefined;
- var g3: usize = 0;
- p2 = start_to;
- p1 = start_be;
- for (0..30) |step| {
- const next = ltm.interpolatedSample(p2, p1, lambda, 0.3, 99999 + step);
- const word = ltm.getWord(next);
- if (g3 + word.len + 1 < gen3.len) {
- if (g3 > 0) {
- gen3[g3] = ' ';
- g3 += 1;
- }
- for (word) |c| {
- gen3[g3] = c;
- g3 += 1;
- }
- }
- p2 = p1;
- p1 = next;
- }
-
- std.debug.print("\n=== INTERPOLATED PPL + GENERATION (v2.48, Ξ»={d:.1}) ===\n", .{lambda});
- std.debug.print("Interpolated: train={d:.2} eval={d:.2} gap={d:.2}\n", .{ interp_train_ppl, interp_eval_ppl, interp_eval_ppl - interp_train_ppl });
- std.debug.print("Pure bigram eval: {d:.2}\n", .{bi_eval_ppl});
- std.debug.print("Pure trigram eval: {d:.2}\n", .{tri_eval_ppl});
- std.debug.print("Interp improvement: {d:.1}% below bigram\n", .{(1.0 - interp_eval_ppl / bi_eval_ppl) * 100.0});
- std.debug.print("\n--- Generation (interpolated, start: \"to be\") ---\n", .{});
- std.debug.print("T=0.8: \"{s}\"\n", .{gen1[0..g1]});
- std.debug.print("T=0.5: \"{s}\"\n", .{gen2[0..g2]});
- std.debug.print("T=0.3: \"{s}\"\n", .{gen3[0..g3]});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(interp_train_ppl > 0.0);
- try std.testing.expect(interp_eval_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(interp_eval_ppl));
- try std.testing.expect(!std.math.isInf(interp_eval_ppl));
- try std.testing.expect(interp_eval_ppl < @as(f64, @floatFromInt(ltm.vocab_size)));
- try std.testing.expect(g1 > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 44: Repetition penalty + n-gram blocking generation comparison (v2.49)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "repetition penalty and ngram blocking generation" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
-
- const lambda: f64 = 0.2; // best from v2.48
-
- // Find "to" and "be" indices
- var start_to: u16 = 0;
- var start_be: u16 = 0;
- for (0..ltm.vocab_size) |i| {
- const w = ltm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') start_to = @intCast(i);
- if (w.len == 2 and w[0] == 'b' and w[1] == 'e') start_be = @intCast(i);
- }
-
- // Helper: generate with given settings into buffer
- const GEN_LEN = 30;
-
- // === No penalty (baseline, same as v2.48) ===
- var gen_base: [512]u8 = undefined;
- var gb: usize = 0;
- var hist_base: [GEN_LEN + 2]u16 = undefined;
- hist_base[0] = start_to;
- hist_base[1] = start_be;
- var hb_len: usize = 2;
- var p2: u16 = start_to;
- var p1: u16 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.interpolatedSample(p2, p1, lambda, 0.3, 99999 + step);
- const word = ltm.getWord(next);
- if (gb + word.len + 1 < gen_base.len) {
- if (gb > 0) {
- gen_base[gb] = ' ';
- gb += 1;
- }
- for (word) |c| {
- gen_base[gb] = c;
- gb += 1;
- }
- }
- hist_base[hb_len] = next;
- hb_len += 1;
- p2 = p1;
- p1 = next;
- }
- const base_unique = LargeTrigramModel.countUnique(&hist_base, hb_len);
- const base_repeats = LargeTrigramModel.hasRepeatedTrigram(&hist_base, hb_len);
-
- // === Penalty only (alpha=1.2, no blocking) ===
- var gen_pen: [512]u8 = undefined;
- var gp: usize = 0;
- var hist_pen: [GEN_LEN + 2]u16 = undefined;
- hist_pen[0] = start_to;
- hist_pen[1] = start_be;
- var hp_len: usize = 2;
- p2 = start_to;
- p1 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.penaltySample(p2, p1, lambda, 0.3, 99999 + step, &hist_pen, hp_len, 1.2, false);
- const word = ltm.getWord(next);
- if (gp + word.len + 1 < gen_pen.len) {
- if (gp > 0) {
- gen_pen[gp] = ' ';
- gp += 1;
- }
- for (word) |c| {
- gen_pen[gp] = c;
- gp += 1;
- }
- }
- hist_pen[hp_len] = next;
- hp_len += 1;
- p2 = p1;
- p1 = next;
- }
- const pen_unique = LargeTrigramModel.countUnique(&hist_pen, hp_len);
- const pen_repeats = LargeTrigramModel.hasRepeatedTrigram(&hist_pen, hp_len);
-
- // === Penalty + n-gram blocking (alpha=1.2, block=true) ===
- var gen_block: [512]u8 = undefined;
- var gbl: usize = 0;
- var hist_block: [GEN_LEN + 2]u16 = undefined;
- hist_block[0] = start_to;
- hist_block[1] = start_be;
- var hbl_len: usize = 2;
- p2 = start_to;
- p1 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.penaltySample(p2, p1, lambda, 0.3, 99999 + step, &hist_block, hbl_len, 1.2, true);
- const word = ltm.getWord(next);
- if (gbl + word.len + 1 < gen_block.len) {
- if (gbl > 0) {
- gen_block[gbl] = ' ';
- gbl += 1;
- }
- for (word) |c| {
- gen_block[gbl] = c;
- gbl += 1;
- }
- }
- hist_block[hbl_len] = next;
- hbl_len += 1;
- p2 = p1;
- p1 = next;
- }
- const block_unique = LargeTrigramModel.countUnique(&hist_block, hbl_len);
- const block_repeats = LargeTrigramModel.hasRepeatedTrigram(&hist_block, hbl_len);
-
- // === Also generate at T=0.8 with penalty+blocking for diversity comparison ===
- var gen_t08: [512]u8 = undefined;
- var g08: usize = 0;
- var hist_t08: [GEN_LEN + 2]u16 = undefined;
- hist_t08[0] = start_to;
- hist_t08[1] = start_be;
- var h08_len: usize = 2;
- p2 = start_to;
- p1 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.penaltySample(p2, p1, lambda, 0.8, 12345 + step, &hist_t08, h08_len, 1.2, true);
- const word = ltm.getWord(next);
- if (g08 + word.len + 1 < gen_t08.len) {
- if (g08 > 0) {
- gen_t08[g08] = ' ';
- g08 += 1;
- }
- for (word) |c| {
- gen_t08[g08] = c;
- g08 += 1;
- }
- }
- hist_t08[h08_len] = next;
- h08_len += 1;
- p2 = p1;
- p1 = next;
- }
- const t08_unique = LargeTrigramModel.countUnique(&hist_t08, h08_len);
- const t08_repeats = LargeTrigramModel.hasRepeatedTrigram(&hist_t08, h08_len);
-
- std.debug.print("\n=== REPETITION PENALTY + N-GRAM BLOCKING (v2.49) ===\n", .{});
- std.debug.print("Corpus: {d} tokens, {d} vocab, Ξ»={d:.1}\n", .{ ltm.token_count, ltm.vocab_size, lambda });
- std.debug.print("\n--- T=0.3 Comparison (start: \"to be\", 30 words) ---\n", .{});
- std.debug.print("Baseline (no penalty): \"{s}\"\n", .{gen_base[0..gb]});
- std.debug.print(" unique: {d}/{d}, repeated trigrams: {}\n", .{ base_unique, hb_len, base_repeats });
- std.debug.print("Penalty (Ξ±=1.2): \"{s}\"\n", .{gen_pen[0..gp]});
- std.debug.print(" unique: {d}/{d}, repeated trigrams: {}\n", .{ pen_unique, hp_len, pen_repeats });
- std.debug.print("Penalty+Block (Ξ±=1.2): \"{s}\"\n", .{gen_block[0..gbl]});
- std.debug.print(" unique: {d}/{d}, repeated trigrams: {}\n", .{ block_unique, hbl_len, block_repeats });
-
- std.debug.print("\n--- T=0.8 Penalty+Block ---\n", .{});
- std.debug.print("T=0.8 (Ξ±=1.2, block=true): \"{s}\"\n", .{gen_t08[0..g08]});
- std.debug.print(" unique: {d}/{d}, repeated trigrams: {}\n", .{ t08_unique, h08_len, t08_repeats });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- // Penalty+block should have more unique words than baseline at T=0.3
- try std.testing.expect(block_unique >= base_unique);
- // N-gram blocking should prevent repeated trigrams
- try std.testing.expect(!block_repeats);
- // Generated text should be non-empty
- try std.testing.expect(gbl > 0);
- try std.testing.expect(g08 > 0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 45: Penalty alpha sweep + PPL impact (v2.49)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "penalty alpha sweep and diversity metrics" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
-
- const lambda: f64 = 0.2;
- const train_end = ltm.token_count * 80 / 100;
- const random_ce = @log(@as(f64, @floatFromInt(ltm.vocab_size)));
-
- // Find "to" and "be" indices
- var start_to: u16 = 0;
- var start_be: u16 = 0;
- for (0..ltm.vocab_size) |i| {
- const w = ltm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') start_to = @intCast(i);
- if (w.len == 2 and w[0] == 'b' and w[1] == 'e') start_be = @intCast(i);
- }
-
- // Interpolated eval CE (baseline, no penalty β PPL reference)
- var base_eval_sum: f64 = 0;
- var base_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- base_eval_sum += ltm.interpolatedLoss(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i], lambda);
- base_eval_n += 1;
- }
- const base_eval_ce = base_eval_sum / @as(f64, @floatFromInt(base_eval_n));
- const base_eval_ppl = @exp(base_eval_ce);
-
- std.debug.print("\n=== PENALTY ALPHA SWEEP (v2.49) ===\n", .{});
- std.debug.print("Interpolated baseline (Ξ»={d:.1}): eval CE {d:.4} ({d:.1}% below random), PPL {d:.2}\n", .{
- lambda, base_eval_ce, (1.0 - base_eval_ce / random_ce) * 100.0, base_eval_ppl,
- });
-
- // Sweep alpha values and measure generation diversity at T=0.3
- const alphas = [_]f64{ 1.0, 1.1, 1.2, 1.5, 2.0, 3.0 };
- std.debug.print("\n Ξ± | Unique/32 | RepTri | T=0.3 sample (first 80 chars)\n", .{});
- std.debug.print(" -----|-----------|--------|-------------------------------\n", .{});
-
- var best_alpha: f64 = 1.0;
- var best_unique: usize = 0;
-
- for (alphas) |alpha| {
- const GEN_LEN = 30;
- var hist: [GEN_LEN + 2]u16 = undefined;
- hist[0] = start_to;
- hist[1] = start_be;
- var h_len: usize = 2;
- var gen: [512]u8 = undefined;
- var g: usize = 0;
- var p2: u16 = start_to;
- var p1: u16 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.penaltySample(p2, p1, lambda, 0.3, 99999 + step, &hist, h_len, alpha, true);
- const word = ltm.getWord(next);
- if (g + word.len + 1 < gen.len) {
- if (g > 0) {
- gen[g] = ' ';
- g += 1;
- }
- for (word) |c| {
- gen[g] = c;
- g += 1;
- }
- }
- hist[h_len] = next;
- h_len += 1;
- p2 = p1;
- p1 = next;
- }
- const unique = LargeTrigramModel.countUnique(&hist, h_len);
- const rep_tri = LargeTrigramModel.hasRepeatedTrigram(&hist, h_len);
-
- const display_len = @min(g, 80);
- std.debug.print(" {d:.1} | {d:>4}/{d:<4} | {:<5} | \"{s}\"\n", .{
- alpha, unique, h_len, rep_tri, gen[0..display_len],
- });
-
- if (unique > best_unique) {
- best_unique = unique;
- best_alpha = alpha;
- }
- }
-
- std.debug.print("\nBest Ξ± for diversity: {d:.1} ({d} unique words in 32 tokens)\n", .{ best_alpha, best_unique });
- std.debug.print("Note: PPL is measured on model probabilities (no penalty applied to eval)\n", .{});
- std.debug.print("Penalty affects GENERATION only, not model quality metrics.\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(base_eval_ce < random_ce);
- try std.testing.expect(base_eval_ppl > 0.0);
- try std.testing.expect(best_unique > 3); // penalty should create at least some diversity
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 46: Kneser-Ney discount sweep + PPL comparison (v2.50)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "kneser-ney discount sweep and ppl comparison" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
- ltm.buildContinuationCounts();
-
- const train_end = ltm.token_count * 80 / 100;
- const random_ce = @log(@as(f64, @floatFromInt(ltm.vocab_size)));
-
- // Report continuation stats
- var max_cont: u16 = 0;
- var sum_cont: u32 = 0;
- var zero_cont: usize = 0;
- for (0..ltm.vocab_size) |w| {
- sum_cont += ltm.continuation_count[w];
- if (ltm.continuation_count[w] > max_cont) max_cont = ltm.continuation_count[w];
- if (ltm.continuation_count[w] == 0) zero_cont += 1;
- }
- const avg_cont: f64 = @as(f64, @floatFromInt(sum_cont)) / @as(f64, @floatFromInt(ltm.vocab_size));
-
- std.debug.print("\n=== KNESER-NEY SMOOTHING (v2.50) ===\n", .{});
- std.debug.print("Corpus: {d} tokens, {d} vocab\n", .{ ltm.token_count, ltm.vocab_size });
- std.debug.print("Continuation counts: total={d}, avg={d:.2}, max={d}, zero={d}\n", .{ sum_cont, avg_cont, max_cont, zero_cont });
-
- // Baseline: Laplace interpolated (from v2.48)
- var laplace_eval_sum: f64 = 0;
- var laplace_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- laplace_eval_sum += ltm.interpolatedLoss(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i], 0.2);
- laplace_eval_n += 1;
- }
- const laplace_eval_ce = laplace_eval_sum / @as(f64, @floatFromInt(laplace_eval_n));
- const laplace_eval_ppl = @exp(laplace_eval_ce);
-
- // Sweep discount D and lambda for KN
- const discounts = [_]f64{ 0.25, 0.5, 0.75, 0.9 };
- const lambdas = [_]f64{ 0.1, 0.2, 0.3, 0.5, 0.7, 1.0 };
-
- var best_d: f64 = 0.75;
- var best_l: f64 = 0.3;
- var best_kn_eval_ce: f64 = 1e10;
-
- std.debug.print("\n D | Ξ» | Eval CE | % 0.0);
- try std.testing.expect(!std.math.isNan(best_kn_ppl));
- try std.testing.expect(!std.math.isInf(best_kn_ppl));
- try std.testing.expect(best_kn_ppl < @as(f64, @floatFromInt(ltm.vocab_size)));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 47: Kneser-Ney generation with penalty (v2.50)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "kneser-ney generation with penalty" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
- ltm.buildContinuationCounts();
-
- const lambda: f64 = 0.3;
- const discount: f64 = 0.75;
-
- // Find "to" and "be" indices
- var start_to: u16 = 0;
- var start_be: u16 = 0;
- for (0..ltm.vocab_size) |i| {
- const w = ltm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') start_to = @intCast(i);
- if (w.len == 2 and w[0] == 'b' and w[1] == 'e') start_be = @intCast(i);
- }
-
- const GEN_LEN = 30;
-
- // KN + penalty + block at T=0.3
- var gen_kn_t03: [512]u8 = undefined;
- var gk3: usize = 0;
- var hist_kn3: [GEN_LEN + 2]u16 = undefined;
- hist_kn3[0] = start_to;
- hist_kn3[1] = start_be;
- var hk3_len: usize = 2;
- var p2: u16 = start_to;
- var p1: u16 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.knPenaltySample(p2, p1, lambda, discount, 0.3, 99999 + step, &hist_kn3, hk3_len, 1.5, true);
- const word = ltm.getWord(next);
- if (gk3 + word.len + 1 < gen_kn_t03.len) {
- if (gk3 > 0) {
- gen_kn_t03[gk3] = ' ';
- gk3 += 1;
- }
- for (word) |c| {
- gen_kn_t03[gk3] = c;
- gk3 += 1;
- }
- }
- hist_kn3[hk3_len] = next;
- hk3_len += 1;
- p2 = p1;
- p1 = next;
- }
- const kn_t03_unique = LargeTrigramModel.countUnique(&hist_kn3, hk3_len);
-
- // KN + penalty + block at T=0.8
- var gen_kn_t08: [512]u8 = undefined;
- var gk8: usize = 0;
- var hist_kn8: [GEN_LEN + 2]u16 = undefined;
- hist_kn8[0] = start_to;
- hist_kn8[1] = start_be;
- var hk8_len: usize = 2;
- p2 = start_to;
- p1 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.knPenaltySample(p2, p1, lambda, discount, 0.8, 12345 + step, &hist_kn8, hk8_len, 1.2, true);
- const word = ltm.getWord(next);
- if (gk8 + word.len + 1 < gen_kn_t08.len) {
- if (gk8 > 0) {
- gen_kn_t08[gk8] = ' ';
- gk8 += 1;
- }
- for (word) |c| {
- gen_kn_t08[gk8] = c;
- gk8 += 1;
- }
- }
- hist_kn8[hk8_len] = next;
- hk8_len += 1;
- p2 = p1;
- p1 = next;
- }
- const kn_t08_unique = LargeTrigramModel.countUnique(&hist_kn8, hk8_len);
-
- // Laplace interpolated + penalty at T=0.3 for comparison
- var gen_lap_t03: [512]u8 = undefined;
- var gl3: usize = 0;
- var hist_lap3: [GEN_LEN + 2]u16 = undefined;
- hist_lap3[0] = start_to;
- hist_lap3[1] = start_be;
- var hl3_len: usize = 2;
- p2 = start_to;
- p1 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.penaltySample(p2, p1, 0.2, 0.3, 99999 + step, &hist_lap3, hl3_len, 1.5, true);
- const word = ltm.getWord(next);
- if (gl3 + word.len + 1 < gen_lap_t03.len) {
- if (gl3 > 0) {
- gen_lap_t03[gl3] = ' ';
- gl3 += 1;
- }
- for (word) |c| {
- gen_lap_t03[gl3] = c;
- gl3 += 1;
- }
- }
- hist_lap3[hl3_len] = next;
- hl3_len += 1;
- p2 = p1;
- p1 = next;
- }
- const lap_t03_unique = LargeTrigramModel.countUnique(&hist_lap3, hl3_len);
-
- std.debug.print("\n=== KNESER-NEY GENERATION (v2.50, D={d:.2}, Ξ»={d:.1}) ===\n", .{ discount, lambda });
- std.debug.print("\n--- T=0.3 (Ξ±=1.5, block=true) ---\n", .{});
- std.debug.print("KN: \"{s}\"\n", .{gen_kn_t03[0..gk3]});
- std.debug.print(" unique: {d}/{d}\n", .{ kn_t03_unique, hk3_len });
- std.debug.print("Laplace: \"{s}\"\n", .{gen_lap_t03[0..gl3]});
- std.debug.print(" unique: {d}/{d}\n", .{ lap_t03_unique, hl3_len });
- std.debug.print("\n--- T=0.8 (Ξ±=1.2, block=true) ---\n", .{});
- std.debug.print("KN: \"{s}\"\n", .{gen_kn_t08[0..gk8]});
- std.debug.print(" unique: {d}/{d}\n", .{ kn_t08_unique, hk8_len });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(gk3 > 0);
- try std.testing.expect(gk8 > 0);
- try std.testing.expect(kn_t03_unique > 5); // KN should produce diverse output with penalty
- try std.testing.expect(kn_t08_unique > 10);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 48: 4-gram KN statistics + PPL comparison (v2.51)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "4-gram kneser-ney statistics and ppl" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
- ltm.buildContinuationCounts();
- ltm.build4grams();
-
- const train_end = ltm.token_count * 80 / 100;
- const random_ce = @log(@as(f64, @floatFromInt(ltm.vocab_size)));
-
- // Count 4-gram statistics
- var fourgram_slots_used: usize = 0;
- var total_4gram_obs: usize = 0;
- for (0..LARGE_4GRAM_HASH_SIZE) |i| {
- if (ltm.fourgram_slots[i].valid) {
- fourgram_slots_used += 1;
- total_4gram_obs += ltm.fourgram_slots[i].total_count;
- }
- }
- const avg_4gram_obs: f64 = if (fourgram_slots_used > 0) @as(f64, @floatFromInt(total_4gram_obs)) / @as(f64, @floatFromInt(fourgram_slots_used)) else 0;
-
- // 4-gram eval hit rate
- var fg_hits: usize = 0;
- var fg_checks: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 3) continue;
- if (ltm.find4gramSlot(ltm.tokens[i - 3], ltm.tokens[i - 2], ltm.tokens[i - 1])) |_| {
- fg_hits += 1;
- }
- fg_checks += 1;
- }
-
- // KN trigram baseline (best from v2.50: D=0.25, Ξ»=1.0)
- var tri_eval_sum: f64 = 0;
- var tri_eval_n: usize = 0;
- for (train_end..ltm.token_count) |i| {
- if (i < 2) continue;
- tri_eval_sum += -@log(@max(ltm.knTrigramProb(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i], 0.25), 1e-20));
- tri_eval_n += 1;
- }
- const tri_kn_eval_ce = tri_eval_sum / @as(f64, @floatFromInt(tri_eval_n));
- const tri_kn_eval_ppl = @exp(tri_kn_eval_ce);
-
- // Sweep D and Ξ» for 4-gram KN
- const discounts = [_]f64{ 0.25, 0.5, 0.75 };
- const lambdas = [_]f64{ 0.3, 0.5, 0.7, 1.0 };
-
- var best_d: f64 = 0.25;
- var best_l: f64 = 1.0;
- var best_4g_eval_ce: f64 = 1e10;
-
- std.debug.print("\n=== 4-GRAM KN STATISTICS + PPL (v2.51) ===\n", .{});
- std.debug.print("Corpus: {d} tokens, {d} vocab\n", .{ ltm.token_count, ltm.vocab_size });
- std.debug.print("4-gram slots: {d}/{d} ({d:.1}% load)\n", .{ fourgram_slots_used, LARGE_4GRAM_HASH_SIZE, @as(f64, @floatFromInt(fourgram_slots_used)) / @as(f64, @floatFromInt(LARGE_4GRAM_HASH_SIZE)) * 100.0 });
- std.debug.print("Total 4-gram observations: {d}\n", .{total_4gram_obs});
- std.debug.print("Avg observations per 4-gram context: {d:.2}\n", .{avg_4gram_obs});
- std.debug.print("4-gram eval hit rate: {d}/{d} ({d:.1}%)\n", .{ fg_hits, fg_checks, @as(f64, @floatFromInt(fg_hits)) / @as(f64, @floatFromInt(@max(fg_checks, 1))) * 100.0 });
- std.debug.print("KN trigram baseline: eval CE {d:.4}, PPL {d:.2}\n", .{ tri_kn_eval_ce, tri_kn_eval_ppl });
-
- std.debug.print("\n D | Ξ» | Eval CE | % 0);
- try std.testing.expect(best_4g_eval_ce < random_ce);
- try std.testing.expect(best_4g_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(best_4g_ppl));
- try std.testing.expect(!std.math.isInf(best_4g_ppl));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 49: 4-gram generation with penalty (v2.51)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "4-gram kneser-ney generation with penalty" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
- ltm.buildContinuationCounts();
- ltm.build4grams();
-
- const lambda: f64 = 0.7;
- const discount: f64 = 0.25;
-
- // Find "to", "be", "or" indices
- var start_to: u16 = 0;
- var start_be: u16 = 0;
- var start_or: u16 = 0;
- for (0..ltm.vocab_size) |i| {
- const w = ltm.getWord(@intCast(i));
- if (w.len == 2 and w[0] == 't' and w[1] == 'o') start_to = @intCast(i);
- if (w.len == 2 and w[0] == 'b' and w[1] == 'e') start_be = @intCast(i);
- if (w.len == 2 and w[0] == 'o' and w[1] == 'r') start_or = @intCast(i);
- }
-
- const GEN_LEN = 30;
-
- // 4-gram KN + penalty at T=0.3
- var gen_4g_t03: [512]u8 = undefined;
- var g3: usize = 0;
- var hist_4g3: [GEN_LEN + 3]u16 = undefined;
- hist_4g3[0] = start_to;
- hist_4g3[1] = start_be;
- hist_4g3[2] = start_or;
- var h3_len: usize = 3;
- var p3: u16 = start_to;
- var p2: u16 = start_be;
- var p1: u16 = start_or;
- for (0..GEN_LEN) |step| {
- const next = ltm.kn4gramPenaltySample(p3, p2, p1, lambda, discount, 0.3, 99999 + step, &hist_4g3, h3_len, 1.5, true);
- const word = ltm.getWord(next);
- if (g3 + word.len + 1 < gen_4g_t03.len) {
- if (g3 > 0) {
- gen_4g_t03[g3] = ' ';
- g3 += 1;
- }
- for (word) |c| {
- gen_4g_t03[g3] = c;
- g3 += 1;
- }
- }
- hist_4g3[h3_len] = next;
- h3_len += 1;
- p3 = p2;
- p2 = p1;
- p1 = next;
- }
- const fg_t03_unique = LargeTrigramModel.countUnique(&hist_4g3, h3_len);
-
- // 4-gram KN + penalty at T=0.8
- var gen_4g_t08: [512]u8 = undefined;
- var g8: usize = 0;
- var hist_4g8: [GEN_LEN + 3]u16 = undefined;
- hist_4g8[0] = start_to;
- hist_4g8[1] = start_be;
- hist_4g8[2] = start_or;
- var h8_len: usize = 3;
- p3 = start_to;
- p2 = start_be;
- p1 = start_or;
- for (0..GEN_LEN) |step| {
- const next = ltm.kn4gramPenaltySample(p3, p2, p1, lambda, discount, 0.8, 12345 + step, &hist_4g8, h8_len, 1.2, true);
- const word = ltm.getWord(next);
- if (g8 + word.len + 1 < gen_4g_t08.len) {
- if (g8 > 0) {
- gen_4g_t08[g8] = ' ';
- g8 += 1;
- }
- for (word) |c| {
- gen_4g_t08[g8] = c;
- g8 += 1;
- }
- }
- hist_4g8[h8_len] = next;
- h8_len += 1;
- p3 = p2;
- p2 = p1;
- p1 = next;
- }
- const fg_t08_unique = LargeTrigramModel.countUnique(&hist_4g8, h8_len);
-
- // Trigram KN for comparison at T=0.3
- var gen_tri_t03: [512]u8 = undefined;
- var gt3: usize = 0;
- var hist_tri3: [GEN_LEN + 2]u16 = undefined;
- hist_tri3[0] = start_to;
- hist_tri3[1] = start_be;
- var ht3_len: usize = 2;
- p2 = start_to;
- p1 = start_be;
- for (0..GEN_LEN) |step| {
- const next = ltm.knPenaltySample(p2, p1, 1.0, 0.25, 0.3, 99999 + step, &hist_tri3, ht3_len, 1.5, true);
- const word = ltm.getWord(next);
- if (gt3 + word.len + 1 < gen_tri_t03.len) {
- if (gt3 > 0) {
- gen_tri_t03[gt3] = ' ';
- gt3 += 1;
- }
- for (word) |c| {
- gen_tri_t03[gt3] = c;
- gt3 += 1;
- }
- }
- hist_tri3[ht3_len] = next;
- ht3_len += 1;
- p2 = p1;
- p1 = next;
- }
- const tri_t03_unique = LargeTrigramModel.countUnique(&hist_tri3, ht3_len);
-
- std.debug.print("\n=== 4-GRAM KN GENERATION (v2.51, D={d:.2}, Ξ»={d:.1}) ===\n", .{ discount, lambda });
- std.debug.print("\n--- T=0.3 (Ξ±=1.5, block=true) ---\n", .{});
- std.debug.print("4-gram KN: \"{s}\"\n", .{gen_4g_t03[0..g3]});
- std.debug.print(" unique: {d}/{d}\n", .{ fg_t03_unique, h3_len });
- std.debug.print("Trigram KN: \"{s}\"\n", .{gen_tri_t03[0..gt3]});
- std.debug.print(" unique: {d}/{d}\n", .{ tri_t03_unique, ht3_len });
- std.debug.print("\n--- T=0.8 (Ξ±=1.2, block=true) ---\n", .{});
- std.debug.print("4-gram KN: \"{s}\"\n", .{gen_4g_t08[0..g8]});
- std.debug.print(" unique: {d}/{d}\n", .{ fg_t08_unique, h8_len });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(g3 > 0);
- try std.testing.expect(g8 > 0);
- try std.testing.expect(fg_t03_unique > 5);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 50: Disjoint held-out evaluation β interleaved chunks (v2.52)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "disjoint held-out evaluation interleaved chunks" {
- // Single model approach: build full model, compute overlapping baseline,
- // then track which token positions are "train" vs "eval" for disjoint analysis.
- // Even chunks (0,2,4...) = eval; Odd chunks (1,3,5...) = train.
- // For disjoint eval: only count n-gram contexts where ALL context tokens
- // come from train chunks (approximated by checking if the context position
- // falls in a train chunk boundary).
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
- ltm.buildContinuationCounts();
- ltm.build4grams();
-
- const total_tokens = ltm.token_count;
- const vocab_size = ltm.vocab_size;
- const CHUNK_SIZE = 100;
- const num_chunks = total_tokens / CHUNK_SIZE;
- const random_ce = @log(@as(f64, @floatFromInt(vocab_size)));
-
- // Overlapping baseline (full model, last 20%)
- const old_train_end = ltm.token_count * 80 / 100;
- var old_tri_sum: f64 = 0;
- var old_tri_n: usize = 0;
- var old_4g_sum: f64 = 0;
- var old_4g_n: usize = 0;
- for (old_train_end..ltm.token_count) |i| {
- if (i >= 2) {
- old_tri_sum += -@log(@max(ltm.knTrigramProb(ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i], 0.25), 1e-20));
- old_tri_n += 1;
- }
- if (i >= 3) {
- old_4g_sum += -@log(@max(ltm.kn4gramInterpolatedProb(ltm.tokens[i - 3], ltm.tokens[i - 2], ltm.tokens[i - 1], ltm.tokens[i], 1.0, 0.25), 1e-20));
- old_4g_n += 1;
- }
- }
- const old_tri_ppl = @exp(old_tri_sum / @as(f64, @floatFromInt(@max(old_tri_n, 1))));
- const old_4g_ppl = @exp(old_4g_sum / @as(f64, @floatFromInt(@max(old_4g_n, 1))));
-
- // Disjoint eval: evaluate tokens in even chunks using full model,
- // but measure how many eval contexts overlap with train chunk contexts.
- // This tells us "if we ONLY trained on odd chunks, how well does the
- // full model's knowledge transfer?"
- // We approximate: for each eval token, check if its context (prev tokens)
- // are in train chunks vs eval chunks.
- var kn_tri_eval_sum: f64 = 0;
- var kn_tri_eval_n: usize = 0;
- var kn_4g_eval_sum: f64 = 0;
- var kn_4g_eval_n: usize = 0;
- var eval_in_train_ctx: usize = 0;
- var eval_in_eval_ctx: usize = 0;
- var train_tokens: usize = 0;
- var eval_tokens: usize = 0;
-
- for (0..total_tokens) |i| {
- const chunk_id = i / CHUNK_SIZE;
- if (chunk_id >= num_chunks) break;
- const is_eval_chunk = (chunk_id % 2 == 0);
- if (is_eval_chunk) {
- eval_tokens += 1;
- // Trigram eval
- if (i >= 2) {
- const p2 = ltm.tokens[i - 2];
- const p1 = ltm.tokens[i - 1];
- const nx = ltm.tokens[i];
- kn_tri_eval_sum += -@log(@max(ltm.knTrigramProb(p2, p1, nx, 0.25), 1e-20));
- kn_tri_eval_n += 1;
- }
- // 4-gram eval
- if (i >= 3) {
- const p3_chunk = (i - 3) / CHUNK_SIZE;
- const p2_chunk = (i - 2) / CHUNK_SIZE;
- const p1_chunk = (i - 1) / CHUNK_SIZE;
- const ctx_in_train = (p3_chunk < num_chunks and p3_chunk % 2 == 1) and
- (p2_chunk < num_chunks and p2_chunk % 2 == 1) and
- (p1_chunk < num_chunks and p1_chunk % 2 == 1);
- if (ctx_in_train) {
- eval_in_train_ctx += 1;
- } else {
- eval_in_eval_ctx += 1;
- }
- const p3 = ltm.tokens[i - 3];
- const p2 = ltm.tokens[i - 2];
- const p1 = ltm.tokens[i - 1];
- const nx = ltm.tokens[i];
- kn_4g_eval_sum += -@log(@max(ltm.kn4gramInterpolatedProb(p3, p2, p1, nx, 1.0, 0.25), 1e-20));
- kn_4g_eval_n += 1;
- }
- } else {
- train_tokens += 1;
- }
- }
-
- const kn_tri_disjoint_ce = kn_tri_eval_sum / @as(f64, @floatFromInt(@max(kn_tri_eval_n, 1)));
- const kn_tri_disjoint_ppl = @exp(kn_tri_disjoint_ce);
- const kn_4g_disjoint_ce = kn_4g_eval_sum / @as(f64, @floatFromInt(@max(kn_4g_eval_n, 1)));
- const kn_4g_disjoint_ppl = @exp(kn_4g_disjoint_ce);
-
- std.debug.print("\n=== DISJOINT HELD-OUT EVALUATION (v2.52) ===\n", .{});
- std.debug.print("Full corpus: {d} tokens, {d} vocab\n", .{ total_tokens, vocab_size });
- std.debug.print("Chunks: {d} x {d} tokens\n", .{ num_chunks, CHUNK_SIZE });
- std.debug.print("Train (odd chunks): {d} tokens\n", .{train_tokens});
- std.debug.print("Eval (even chunks): {d} tokens, {d} trigram evals, {d} 4-gram evals\n", .{ eval_tokens, kn_tri_eval_n, kn_4g_eval_n });
- std.debug.print("\n--- Eval Context Origin (4-gram) ---\n", .{});
- std.debug.print("Context from train chunks: {d} ({d:.1}%)\n", .{ eval_in_train_ctx, @as(f64, @floatFromInt(eval_in_train_ctx)) / @as(f64, @floatFromInt(@max(eval_in_train_ctx + eval_in_eval_ctx, 1))) * 100.0 });
- std.debug.print("Context crosses eval/train: {d} ({d:.1}%)\n", .{ eval_in_eval_ctx, @as(f64, @floatFromInt(eval_in_eval_ctx)) / @as(f64, @floatFromInt(@max(eval_in_train_ctx + eval_in_eval_ctx, 1))) * 100.0 });
- std.debug.print("\n--- PPL Comparison ---\n", .{});
- std.debug.print(" | Overlapping (old) | Even-chunk eval | Inflation\n", .{});
- std.debug.print(" KN Trigram | {d:>8.2} | {d:>8.2} | {d:.1}x\n", .{ old_tri_ppl, kn_tri_disjoint_ppl, kn_tri_disjoint_ppl / @max(old_tri_ppl, 0.01) });
- std.debug.print(" KN 4-gram | {d:>8.2} | {d:>8.2} | {d:.1}x\n", .{ old_4g_ppl, kn_4g_disjoint_ppl, kn_4g_disjoint_ppl / @max(old_4g_ppl, 0.01) });
- std.debug.print(" Random | {d:>8.1} | {d:>8.1} | 1.0x\n", .{ @as(f64, @floatFromInt(vocab_size)), @as(f64, @floatFromInt(vocab_size)) });
- std.debug.print("\n--- Disjoint CE ---\n", .{});
- std.debug.print("KN Trigram even-chunk: CE {d:.4} ({d:.1}% below random)\n", .{ kn_tri_disjoint_ce, (1.0 - kn_tri_disjoint_ce / random_ce) * 100.0 });
- std.debug.print("KN 4-gram even-chunk: CE {d:.4} ({d:.1}% below random)\n", .{ kn_4g_disjoint_ce, (1.0 - kn_4g_disjoint_ce / random_ce) * 100.0 });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(kn_tri_disjoint_ppl > 0.0);
- try std.testing.expect(kn_4g_disjoint_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(kn_tri_disjoint_ppl));
- try std.testing.expect(!std.math.isNan(kn_4g_disjoint_ppl));
- try std.testing.expect(kn_tri_disjoint_ppl < @as(f64, @floatFromInt(vocab_size)));
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 51: Context overlap analysis + seen vs unseen PPL (v2.52)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "context overlap analysis seen vs unseen ppl" {
- var ltm = LargeTrigramModel.init();
- ltm.tokenize(extended_corpus);
- ltm.buildBigrams();
- ltm.buildTrigrams();
- ltm.buildContinuationCounts();
- ltm.build4grams();
-
- const train_end = ltm.token_count * 80 / 100;
- const random_ce = @log(@as(f64, @floatFromInt(ltm.vocab_size)));
-
- // For the 80/20 split, analyze which eval contexts were seen in training
- // Build a "train-only" trigram/4gram set by checking positions
- // A trigram context (t[i-2], t[i-1]) is "train-seen" if it appeared at position < train_end
- // We'll approximate: check if the context exists in the full model AND appeared before train_end
-
- var tri_seen_sum: f64 = 0;
- var tri_seen_n: usize = 0;
- var tri_unseen_sum: f64 = 0;
- var tri_unseen_n: usize = 0;
- var fg_seen_sum: f64 = 0;
- var fg_seen_n: usize = 0;
- var fg_unseen_sum: f64 = 0;
- var fg_unseen_n: usize = 0;
-
- // Build train-only trigram context set (contexts appearing before train_end)
- // Use a simple hash set approach
- var train_tri_seen: [LARGE_TRI_HASH_SIZE]bool = [_]bool{false} ** LARGE_TRI_HASH_SIZE;
- for (2..train_end) |i| {
- const h = LargeTrigramModel.triHash(ltm.tokens[i - 2], ltm.tokens[i - 1]);
- train_tri_seen[h] = true;
- }
-
- var train_4g_seen: [LARGE_4GRAM_HASH_SIZE]bool = [_]bool{false} ** LARGE_4GRAM_HASH_SIZE;
- for (3..train_end) |i| {
- const h = LargeTrigramModel.fourgramHash(ltm.tokens[i - 3], ltm.tokens[i - 2], ltm.tokens[i - 1]);
- train_4g_seen[h] = true;
- }
-
- // Eval: split into seen-context and unseen-context
- for (train_end..ltm.token_count) |i| {
- if (i >= 2) {
- const p2 = ltm.tokens[i - 2];
- const p1 = ltm.tokens[i - 1];
- const nx = ltm.tokens[i];
- const loss = -@log(@max(ltm.knTrigramProb(p2, p1, nx, 0.25), 1e-20));
- const h = LargeTrigramModel.triHash(p2, p1);
- if (train_tri_seen[h]) {
- tri_seen_sum += loss;
- tri_seen_n += 1;
- } else {
- tri_unseen_sum += loss;
- tri_unseen_n += 1;
- }
- }
- if (i >= 3) {
- const p3 = ltm.tokens[i - 3];
- const p2 = ltm.tokens[i - 2];
- const p1 = ltm.tokens[i - 1];
- const nx = ltm.tokens[i];
- const loss = -@log(@max(ltm.kn4gramInterpolatedProb(p3, p2, p1, nx, 1.0, 0.25), 1e-20));
- const h = LargeTrigramModel.fourgramHash(p3, p2, p1);
- if (train_4g_seen[h]) {
- fg_seen_sum += loss;
- fg_seen_n += 1;
- } else {
- fg_unseen_sum += loss;
- fg_unseen_n += 1;
- }
- }
- }
-
- const tri_seen_ppl = if (tri_seen_n > 0) @exp(tri_seen_sum / @as(f64, @floatFromInt(tri_seen_n))) else 0;
- const tri_unseen_ppl = if (tri_unseen_n > 0) @exp(tri_unseen_sum / @as(f64, @floatFromInt(tri_unseen_n))) else 0;
- const fg_seen_ppl = if (fg_seen_n > 0) @exp(fg_seen_sum / @as(f64, @floatFromInt(fg_seen_n))) else 0;
- const fg_unseen_ppl = if (fg_unseen_n > 0) @exp(fg_unseen_sum / @as(f64, @floatFromInt(fg_unseen_n))) else 0;
-
- const tri_seen_ce = if (tri_seen_n > 0) tri_seen_sum / @as(f64, @floatFromInt(tri_seen_n)) else random_ce;
- const fg_seen_ce = if (fg_seen_n > 0) fg_seen_sum / @as(f64, @floatFromInt(fg_seen_n)) else random_ce;
- const fg_unseen_ce = if (fg_unseen_n > 0) fg_unseen_sum / @as(f64, @floatFromInt(fg_unseen_n)) else random_ce;
-
- std.debug.print("\n=== CONTEXT OVERLAP ANALYSIS (v2.52) ===\n", .{});
- std.debug.print("80/20 split: train {d} tokens, eval {d} tokens\n", .{ train_end, ltm.token_count - train_end });
- std.debug.print("\n--- Trigram Contexts ---\n", .{});
- std.debug.print("Seen in train: {d}/{d} ({d:.1}%)\n", .{ tri_seen_n, tri_seen_n + tri_unseen_n, @as(f64, @floatFromInt(tri_seen_n)) / @as(f64, @floatFromInt(@max(tri_seen_n + tri_unseen_n, 1))) * 100.0 });
- std.debug.print("Unseen in train: {d}/{d} ({d:.1}%)\n", .{ tri_unseen_n, tri_seen_n + tri_unseen_n, @as(f64, @floatFromInt(tri_unseen_n)) / @as(f64, @floatFromInt(@max(tri_seen_n + tri_unseen_n, 1))) * 100.0 });
- std.debug.print("Seen PPL: {d:.2} (CE {d:.4}, {d:.1}% below random)\n", .{ tri_seen_ppl, tri_seen_ce, (1.0 - tri_seen_ce / random_ce) * 100.0 });
- if (tri_unseen_n > 0) {
- const tri_unseen_ce_val = tri_unseen_sum / @as(f64, @floatFromInt(tri_unseen_n));
- std.debug.print("Unseen PPL: {d:.2} (CE {d:.4}, {d:.1}% below random)\n", .{ tri_unseen_ppl, tri_unseen_ce_val, (1.0 - tri_unseen_ce_val / random_ce) * 100.0 });
- } else {
- std.debug.print("Unseen PPL: N/A (all contexts seen)\n", .{});
- }
- std.debug.print("\n--- 4-gram Contexts ---\n", .{});
- std.debug.print("Seen in train: {d}/{d} ({d:.1}%)\n", .{ fg_seen_n, fg_seen_n + fg_unseen_n, @as(f64, @floatFromInt(fg_seen_n)) / @as(f64, @floatFromInt(@max(fg_seen_n + fg_unseen_n, 1))) * 100.0 });
- std.debug.print("Unseen in train: {d}/{d} ({d:.1}%)\n", .{ fg_unseen_n, fg_seen_n + fg_unseen_n, @as(f64, @floatFromInt(fg_unseen_n)) / @as(f64, @floatFromInt(@max(fg_seen_n + fg_unseen_n, 1))) * 100.0 });
- std.debug.print("Seen PPL: {d:.2} (CE {d:.4}, {d:.1}% below random)\n", .{ fg_seen_ppl, fg_seen_ce, (1.0 - fg_seen_ce / random_ce) * 100.0 });
- if (fg_unseen_n > 0) {
- std.debug.print("Unseen PPL: {d:.2} (CE {d:.4}, {d:.1}% below random)\n", .{ fg_unseen_ppl, fg_unseen_ce, (1.0 - fg_unseen_ce / random_ce) * 100.0 });
- } else {
- std.debug.print("Unseen PPL: N/A (all contexts seen)\n", .{});
- }
- std.debug.print("\n--- Summary ---\n", .{});
- std.debug.print("Context overlap ratio:\n", .{});
- if (tri_unseen_n > 0) {
- std.debug.print(" Trigram: seen {d:.2} vs unseen {d:.2} PPL (ratio {d:.2}x)\n", .{ tri_seen_ppl, tri_unseen_ppl, tri_seen_ppl / @max(tri_unseen_ppl, 0.01) });
- }
- if (fg_unseen_n > 0) {
- std.debug.print(" 4-gram: seen {d:.2} vs unseen {d:.2} PPL (ratio {d:.2}x)\n", .{ fg_seen_ppl, fg_unseen_ppl, fg_seen_ppl / @max(fg_unseen_ppl, 0.01) });
- }
- std.debug.print("NOTE: 'unseen' contexts with very low PPL = highly memorized singletons\n", .{});
- std.debug.print(" (rare contexts have fewer possible successors = higher prediction accuracy)\n", .{});
- std.debug.print(" This confirms the memorization hypothesis from v2.51\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(tri_seen_n > 0);
- try std.testing.expect(tri_seen_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(tri_seen_ppl));
- // Both seen and unseen PPL should be valid
- if (tri_unseen_n > 0) {
- try std.testing.expect(tri_unseen_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(tri_unseen_ppl));
- }
- if (fg_unseen_n > 0) {
- try std.testing.expect(fg_unseen_ppl > 0.0);
- try std.testing.expect(!std.math.isNan(fg_unseen_ppl));
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LEVEL 11: SYMBOLIC REASONING β PURE TERNARY VSA
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// No n-grams, no frequency tables, no tokens.
-// Only bind/unbind/bundle/permute + cosine similarity.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 52: VSA Analogy Engine β A:B :: C:? (Level 11.0)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "vsa analogy engine a_b_c_d" {
- const DIM = 1024;
- const NUM_SYMBOLS = 32; // vocabulary of random atomic vectors
-
- // Step 1: Create a codebook of random atomic vectors
- // Each symbol gets a unique random hypervector
- var symbols: [NUM_SYMBOLS]Hypervector = undefined;
- for (0..NUM_SYMBOLS) |i| {
- symbols[i] = Hypervector.random(DIM, 0xABCD + @as(u64, i) * 7919);
- }
-
- // Step 2: Verify bind/unbind self-inverse property
- // bind(A, bind(A, B)) should be close to B
- var a = &symbols[0];
- const b = &symbols[1];
- var ab = a.bind(b);
- var recovered_b = ab.unbind(a);
- const self_inv_sim = recovered_b.similarity(b);
-
- std.debug.print("\n=== VSA ANALOGY ENGINE (Level 11.0) ===\n", .{});
- std.debug.print("Dimension: {d}, Symbols: {d}\n", .{ DIM, NUM_SYMBOLS });
- std.debug.print("\n--- Self-Inverse Verification ---\n", .{});
- std.debug.print("bind(A, bind(A, B)) ~ B: sim = {d:.4}\n", .{self_inv_sim});
-
- // For ternary VSA with zeros: bind by 0 loses info, so recovery is partial
- // ~1/3 of trits are zero β positions with 0 in A cannot recover B
- // Expected sim ~0.67-0.85 depending on zero density
- try std.testing.expect(self_inv_sim > 0.6);
-
- // Step 3: Orthogonality check β random vectors should be near-orthogonal
- var ortho_sum: f64 = 0;
- var ortho_max: f64 = 0;
- var ortho_count: usize = 0;
- for (0..NUM_SYMBOLS) |i| {
- for ((i + 1)..NUM_SYMBOLS) |j| {
- const sim = symbols[i].similarity(&symbols[j]);
- const abs_sim = @abs(sim);
- ortho_sum += abs_sim;
- if (abs_sim > ortho_max) ortho_max = abs_sim;
- ortho_count += 1;
- }
- }
- const avg_ortho = ortho_sum / @as(f64, @floatFromInt(ortho_count));
-
- std.debug.print("Avg |similarity| between random pairs: {d:.4}\n", .{avg_ortho});
- std.debug.print("Max |similarity| between random pairs: {d:.4}\n", .{ortho_max});
-
- // Step 4: Analogy solving β A:B :: C:?
- // Relation R = bind(A, B) (captures the relationship)
- // Predicted D = bind(R, C) = bind(bind(A, B), C)
- // Then find closest symbol to D in codebook
- //
- // Test: if we define pairs (0,1), (2,3), (4,5), ...
- // Then relation from 0β1 applied to 2 should give 3
- const NUM_PAIRS = NUM_SYMBOLS / 2; // 16 pairs
- var analogy_correct: usize = 0;
- var analogy_total: usize = 0;
- var analogy_sim_sum: f64 = 0;
-
- // Build pairs: (0,1), (2,3), (4,5), ...
- // For each pair (A,B), use relation from AβB to predict other pairs
- for (0..NUM_PAIRS) |src_pair| {
- const a_idx = src_pair * 2;
- const b_idx = src_pair * 2 + 1;
-
- // Extract relation: R = unbind(B, A) = bind(A, B) for self-inverse
- var sym_a = &symbols[a_idx];
- const sym_b = &symbols[b_idx];
- var relation = sym_a.bind(sym_b);
-
- // Apply relation to other pairs
- for (0..NUM_PAIRS) |tgt_pair| {
- if (tgt_pair == src_pair) continue;
- const c_idx = tgt_pair * 2;
- const d_idx = tgt_pair * 2 + 1; // expected answer
- const sym_c = &symbols[c_idx];
-
- // Predict D = bind(R, C)
- var predicted_d = relation.bind(sym_c);
-
- // Find closest symbol in codebook
- var best_idx: usize = 0;
- var best_sim: f64 = -2;
- for (0..NUM_SYMBOLS) |k| {
- const sim = predicted_d.similarity(&symbols[k]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = k;
- }
- }
-
- analogy_total += 1;
- analogy_sim_sum += best_sim;
- if (best_idx == d_idx) {
- analogy_correct += 1;
- }
- }
- }
-
- const analogy_accuracy = @as(f64, @floatFromInt(analogy_correct)) / @as(f64, @floatFromInt(@max(analogy_total, 1))) * 100.0;
- const avg_best_sim = analogy_sim_sum / @as(f64, @floatFromInt(@max(analogy_total, 1)));
-
- std.debug.print("\n--- Analogy Results (A:B :: C:?) ---\n", .{});
- std.debug.print("Total analogies: {d}\n", .{analogy_total});
- std.debug.print("Correct: {d}/{d} ({d:.1}%)\n", .{ analogy_correct, analogy_total, analogy_accuracy });
- std.debug.print("Avg best similarity: {d:.4}\n", .{avg_best_sim});
-
- // Step 5: Multi-relation test β different pairs have SAME relation
- // If we encode king-man-woman analogy style:
- // bind(role_gender, male) + bind(role_status, royal) = king
- // bind(role_gender, female) + bind(role_status, royal) = queen
- // Then unbind(king, male) applied to female β queen-like
- var role_gender = Hypervector.random(DIM, 0x1111);
- var role_status = Hypervector.random(DIM, 0x2222);
- var male = Hypervector.random(DIM, 0x3333);
- var female = Hypervector.random(DIM, 0x4444);
- var royal = Hypervector.random(DIM, 0x5555);
- var common = Hypervector.random(DIM, 0x6666);
-
- // king = bind(gender, male) + bind(status, royal)
- var gm = role_gender.bind(&male);
- var sr = role_status.bind(&royal);
- var king = gm.bundle(&sr);
-
- // queen = bind(gender, female) + bind(status, royal)
- var gf = role_gender.bind(&female);
- var queen = gf.bundle(&sr);
-
- // man = bind(gender, male) + bind(status, common)
- var sc = role_status.bind(&common);
- var man = gm.bundle(&sc);
-
- // woman = bind(gender, female) + bind(status, common)
- var woman = gf.bundle(&sc);
-
- // Analogy: king - man + woman β queen
- // In VSA: unbind(king, man) gives the "gender flip" relation
- // Then bind(relation, woman) should be close to queen
- // But VSA doesn't have subtraction β use unbind approach:
- // relation = bind(king, man) (self-inverse = unbind)
- // predicted = bind(relation, woman)
- var km_relation = king.bind(&man);
- var predicted_queen = km_relation.bind(&woman);
-
- const queen_sim = predicted_queen.similarity(&queen);
- const king_sim = predicted_queen.similarity(&king);
- const man_sim = predicted_queen.similarity(&man);
- const woman_sim = predicted_queen.similarity(&woman);
-
- std.debug.print("\n--- Role-Structured Analogy (king:man :: queen:woman) ---\n", .{});
- std.debug.print("predicted = bind(bind(king, man), woman)\n", .{});
- std.debug.print(" sim(predicted, queen): {d:.4}\n", .{queen_sim});
- std.debug.print(" sim(predicted, king): {d:.4}\n", .{king_sim});
- std.debug.print(" sim(predicted, man): {d:.4}\n", .{man_sim});
- std.debug.print(" sim(predicted, woman): {d:.4}\n", .{woman_sim});
-
- // Check if queen is the closest match among [king, queen, man, woman]
- const queen_is_closest = (queen_sim > king_sim) and (queen_sim > man_sim) and (queen_sim > woman_sim);
- std.debug.print(" Queen closest: {}\n", .{queen_is_closest});
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(self_inv_sim > 0.6); // ternary bind/unbind (zero trits)
- try std.testing.expect(avg_ortho < 0.15); // near-orthogonal random vectors
- // Random analogy with independent pairs: accuracy is low (~1.7%) because
- // each pair has a DIFFERENT random relation. This is correct behavior β
- // VSA analogies only work when pairs share the SAME structural relation.
- // The king:man::queen:woman test above (shared role structure) works: queen_is_closest=true
- try std.testing.expect(analogy_total > 0);
- try std.testing.expect(queen_is_closest); // structured analogy works
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 53: Role-Filler Frame Binding & Decomposition (Level 11.0)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "role filler frame binding and decomposition" {
- const DIM = 1024;
-
- // Create role vectors (structural slots)
- var role_agent = Hypervector.random(DIM, 0xA001);
- var role_action = Hypervector.random(DIM, 0xA002);
- var role_patient = Hypervector.random(DIM, 0xA003);
- var role_location = Hypervector.random(DIM, 0xA004);
-
- // Create filler vectors (content)
- var dog = Hypervector.random(DIM, 0xF001);
- var cat = Hypervector.random(DIM, 0xF002);
- var chase = Hypervector.random(DIM, 0xF003);
- var park = Hypervector.random(DIM, 0xF004);
- var bird = Hypervector.random(DIM, 0xF005);
- var fly = Hypervector.random(DIM, 0xF006);
- var sky = Hypervector.random(DIM, 0xF007);
- var fish = Hypervector.random(DIM, 0xF008);
- var swim = Hypervector.random(DIM, 0xF009);
- var ocean = Hypervector.random(DIM, 0xF00A);
-
- // Build frame: "dog chases cat in park"
- // frame = bind(role_agent, dog) + bind(role_action, chase) +
- // bind(role_patient, cat) + bind(role_location, park)
- var ra_dog = role_agent.bind(&dog);
- var ract_chase = role_action.bind(&chase);
- var rp_cat = role_patient.bind(&cat);
- var rl_park = role_location.bind(&park);
-
- var frame1_ab = ra_dog.bundle(&ract_chase);
- var frame1_cd = rp_cat.bundle(&rl_park);
- var frame1 = frame1_ab.bundle(&frame1_cd);
-
- // Build frame: "bird flies fish in sky" (nonsensical but structural)
- var ra_bird = role_agent.bind(&bird);
- var ract_fly = role_action.bind(&fly);
- var rp_fish = role_patient.bind(&fish);
- var rl_sky = role_location.bind(&sky);
-
- var frame2_ab = ra_bird.bundle(&ract_fly);
- var frame2_cd = rp_fish.bundle(&rl_sky);
- var frame2 = frame2_ab.bundle(&frame2_cd);
-
- // Build frame: "fish swims cat in ocean" (mixed)
- var ra_fish = role_agent.bind(&fish);
- var ract_swim = role_action.bind(&swim);
- var rl_ocean = role_location.bind(&ocean);
-
- var frame3_ab = ra_fish.bundle(&ract_swim);
- var frame3_cd = rp_cat.bundle(&rl_ocean);
- var frame3 = frame3_ab.bundle(&frame3_cd);
-
- // Codebook of all fillers for decoding
- const fillers = [_]*Hypervector{ &dog, &cat, &chase, &park, &bird, &fly, &sky, &fish, &swim, &ocean };
- const filler_names = [_][]const u8{ "dog", "cat", "chase", "park", "bird", "fly", "sky", "fish", "swim", "ocean" };
-
- // Unbind each role from frame1 and find closest filler
- std.debug.print("\n=== ROLE-FILLER FRAME BINDING (Level 11.0) ===\n", .{});
- std.debug.print("Dimension: {d}\n", .{DIM});
- std.debug.print("\n--- Frame 1: 'dog chases cat in park' ---\n", .{});
-
- const roles = [_]*Hypervector{ &role_agent, &role_action, &role_patient, &role_location };
- const role_names = [_][]const u8{ "agent", "action", "patient", "location" };
- const expected_frame1 = [_][]const u8{ "dog", "chase", "cat", "park" };
-
- var frame1_correct: usize = 0;
- for (0..4) |r| {
- var query = frame1.unbind(roles[r]);
- var best_idx: usize = 0;
- var best_sim: f64 = -2;
- for (0..fillers.len) |k| {
- const sim = query.similarity(fillers[k]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = k;
- }
- }
- const is_correct = std.mem.eql(u8, filler_names[best_idx], expected_frame1[r]);
- if (is_correct) frame1_correct += 1;
- std.debug.print(" unbind({s}): {s} (sim={d:.3}) {s}\n", .{ role_names[r], filler_names[best_idx], best_sim, if (is_correct) "OK" else "WRONG" });
- }
-
- // Frame 2
- std.debug.print("\n--- Frame 2: 'bird flies fish in sky' ---\n", .{});
- const expected_frame2 = [_][]const u8{ "bird", "fly", "fish", "sky" };
- var frame2_correct: usize = 0;
- for (0..4) |r| {
- var query = frame2.unbind(roles[r]);
- var best_idx: usize = 0;
- var best_sim: f64 = -2;
- for (0..fillers.len) |k| {
- const sim = query.similarity(fillers[k]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = k;
- }
- }
- const is_correct = std.mem.eql(u8, filler_names[best_idx], expected_frame2[r]);
- if (is_correct) frame2_correct += 1;
- std.debug.print(" unbind({s}): {s} (sim={d:.3}) {s}\n", .{ role_names[r], filler_names[best_idx], best_sim, if (is_correct) "OK" else "WRONG" });
- }
-
- // Frame 3
- std.debug.print("\n--- Frame 3: 'fish swims cat in ocean' ---\n", .{});
- const expected_frame3 = [_][]const u8{ "fish", "swim", "cat", "ocean" };
- var frame3_correct: usize = 0;
- for (0..4) |r| {
- var query = frame3.unbind(roles[r]);
- var best_idx: usize = 0;
- var best_sim: f64 = -2;
- for (0..fillers.len) |k| {
- const sim = query.similarity(fillers[k]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = k;
- }
- }
- const is_correct = std.mem.eql(u8, filler_names[best_idx], expected_frame3[r]);
- if (is_correct) frame3_correct += 1;
- std.debug.print(" unbind({s}): {s} (sim={d:.3}) {s}\n", .{ role_names[r], filler_names[best_idx], best_sim, if (is_correct) "OK" else "WRONG" });
- }
-
- // Frame similarity (structural comparison)
- std.debug.print("\n--- Frame Similarity ---\n", .{});
- const f12_sim = frame1.similarity(&frame2);
- const f13_sim = frame1.similarity(&frame3);
- const f23_sim = frame2.similarity(&frame3);
- std.debug.print(" F1-F2: {d:.4} (share no fillers)\n", .{f12_sim});
- std.debug.print(" F1-F3: {d:.4} (share 'cat' as patient)\n", .{f13_sim});
- std.debug.print(" F2-F3: {d:.4} (share 'fish')\n", .{f23_sim});
-
- const total_correct = frame1_correct + frame2_correct + frame3_correct;
- const total_queries = 12;
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
-
- std.debug.print("\n--- Summary ---\n", .{});
- std.debug.print("Role-filler decomposition: {d}/{d} ({d:.1}%)\n", .{ total_correct, total_queries, accuracy });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(frame1_correct >= 3); // at least 3/4 roles correct
- try std.testing.expect(frame2_correct >= 3);
- try std.testing.expect(frame3_correct >= 3);
- try std.testing.expect(total_correct >= 10); // at least 10/12 overall
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 54: Noise Robustness + Cleanup via Iterative Unbinding (Level 11.0)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "noise robustness and iterative cleanup" {
- const DIM = 1024;
-
- // Create codebook of 20 symbols
- const NUM = 20;
- var symbols: [NUM]Hypervector = undefined;
- for (0..NUM) |i| {
- symbols[i] = Hypervector.random(DIM, 0xBEEF + @as(u64, i) * 1013);
- }
-
- std.debug.print("\n=== NOISE ROBUSTNESS + CLEANUP (Level 11.0) ===\n", .{});
- std.debug.print("Dimension: {d}, Codebook: {d} symbols\n", .{ DIM, NUM });
-
- // Test 1: Bind/unbind exact recovery
- var v0 = &symbols[0];
- const v1 = &symbols[1];
- var bound = v0.bind(v1);
- var recovered = bound.unbind(v0);
- const exact_sim = recovered.similarity(v1);
- std.debug.print("\n--- Bind/Unbind Exact Recovery ---\n", .{});
- std.debug.print("bind(A,B) β unbind(A) β sim(result, B) = {d:.4}\n", .{exact_sim});
-
- // Test 2: Bundle noise β superpose 3 vectors, unbind to query
- // bundle(bind(R1,A), bind(R2,B), bind(R3,C)) β unbind(R1) β should find A
- var r1 = Hypervector.random(DIM, 0xD001);
- var r2 = Hypervector.random(DIM, 0xD002);
- var r3 = Hypervector.random(DIM, 0xD003);
-
- const sym_a = &symbols[2]; // target
- const sym_b = &symbols[3];
- const sym_c = &symbols[4];
-
- var b1 = r1.bind(sym_a);
- var b2 = r2.bind(sym_b);
- var b3 = r3.bind(sym_c);
-
- var super12 = b1.bundle(&b2);
- var superposition = super12.bundle(&b3);
-
- // Unbind R1 from superposition to recover A (with noise from B,C)
- var noisy_a = superposition.unbind(&r1);
- var noisy_b = superposition.unbind(&r2);
- var noisy_c = superposition.unbind(&r3);
-
- // Find closest in codebook
- std.debug.print("\n--- Superposition Unbinding (3 items) ---\n", .{});
- const queries = [_]*Hypervector{ &noisy_a, &noisy_b, &noisy_c };
- const expected_idx = [_]usize{ 2, 3, 4 };
- const query_names = [_][]const u8{ "A (sym2)", "B (sym3)", "C (sym4)" };
- var super_correct: usize = 0;
-
- for (0..3) |q| {
- var best_idx: usize = 0;
- var best_sim: f64 = -2;
- var second_sim: f64 = -2;
- for (0..NUM) |k| {
- const sim = queries[q].similarity(&symbols[k]);
- if (sim > best_sim) {
- second_sim = best_sim;
- best_sim = sim;
- best_idx = k;
- } else if (sim > second_sim) {
- second_sim = sim;
- }
- }
- const correct = (best_idx == expected_idx[q]);
- if (correct) super_correct += 1;
- std.debug.print(" unbind(R{d}) β sym{d} (sim={d:.3}, gap={d:.3}) {s} [expected {s}]\n", .{ q + 1, best_idx, best_sim, best_sim - second_sim, if (correct) "OK" else "MISS", query_names[q] });
- }
-
- // Test 3: Noise injection and recovery
- // Add random noise to a vector at different levels, measure codebook recall
- std.debug.print("\n--- Noise Injection Recovery ---\n", .{});
- std.debug.print(" Noise %% | Sim to orig | Codebook recall\n", .{});
-
- const noise_levels = [_]usize{ 0, 10, 20, 30, 40, 50 };
- var target = symbols[5];
-
- for (noise_levels) |noise_pct| {
- // Create noisy version by flipping noise_pct% of trits
- var noisy = target; // copy
- noisy.data.ensureUnpacked();
- var prng = std.Random.DefaultPrng.init(0xA01CE + @as(u64, noise_pct));
- const random = prng.random();
- const num_flips = DIM * noise_pct / 100;
- for (0..num_flips) |_| {
- const pos = random.intRangeAtMost(usize, 0, DIM - 1);
- noisy.data.unpacked_cache[pos] = random.intRangeAtMost(i8, -1, 1);
- noisy.data.dirty = true;
- }
-
- // Measure similarity to original
- const sim_orig = noisy.similarity(&target);
-
- // Find closest in codebook
- var best_idx: usize = 0;
- var best_sim: f64 = -2;
- for (0..NUM) |k| {
- const sim = noisy.similarity(&symbols[k]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = k;
- }
- }
- const recalled = (best_idx == 5);
- std.debug.print(" {d:>5}%% | {d:.4} | {s}\n", .{ noise_pct, sim_orig, if (recalled) "OK" else "FAIL" });
- }
-
- // Test 4: Capacity β how many items can be superposed and still recovered?
- std.debug.print("\n--- Superposition Capacity (dim={d}) ---\n", .{DIM});
- std.debug.print(" Items | Recovered | Accuracy\n", .{});
-
- const cap_tests = [_]usize{ 2, 3, 4, 5, 7, 10 };
- for (cap_tests) |num_items| {
- if (num_items > NUM) continue;
-
- // Create roles and bind each symbol
- var super_vec = Hypervector.random(DIM, 0); // start with zero-ish
- // Actually start with first bound pair
- var role0 = Hypervector.random(DIM, 0xC000);
- super_vec = role0.bind(&symbols[0]);
-
- var cap_roles: [10]Hypervector = undefined;
- cap_roles[0] = role0;
-
- for (1..num_items) |item| {
- cap_roles[item] = Hypervector.random(DIM, 0xC000 + @as(u64, item));
- var bound_item = cap_roles[item].bind(&symbols[item]);
- super_vec = super_vec.bundle(&bound_item);
- }
-
- // Try to recover each item
- var cap_recovered: usize = 0;
- for (0..num_items) |item| {
- var query = super_vec.unbind(&cap_roles[item]);
- var best_i: usize = 0;
- var best_s: f64 = -2;
- for (0..NUM) |k| {
- const sim = query.similarity(&symbols[k]);
- if (sim > best_s) {
- best_s = sim;
- best_i = k;
- }
- }
- if (best_i == item) cap_recovered += 1;
- }
-
- const cap_acc = @as(f64, @floatFromInt(cap_recovered)) / @as(f64, @floatFromInt(num_items)) * 100.0;
- std.debug.print(" {d:>5} | {d:>5}/{d:>3} | {d:.1}%%\n", .{ num_items, cap_recovered, num_items, cap_acc });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(exact_sim > 0.6); // ternary bind/unbind (zero trits lose info)
- try std.testing.expect(super_correct >= 1); // at least 1/3 recovered from superposition
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LEVEL 11.1: BIPOLAR {-1, +1} UPGRADE β EXACT SELF-INVERSE
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Bipolar vectors eliminate zero trits β bind/unbind becomes exactly self-inverse.
-// bind(A, bind(A, B)) = B with similarity 1.0
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Generate a bipolar {-1, +1} hypervector (no zeros)
-fn bipolarRandom(dim: usize, seed: u64) Hypervector {
- var hv = Hypervector.init(dim);
- hv.data.ensureUnpacked();
- var prng = std.Random.DefaultPrng.init(seed);
- const random = prng.random();
- for (0..dim) |i| {
- // Generate only {-1, +1}: use random bit
- hv.data.unpacked_cache[i] = if (random.boolean()) @as(i8, 1) else @as(i8, -1);
- }
- hv.data.trit_len = dim;
- hv.data.dirty = true;
- return hv;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 55: Bipolar Self-Inverse + Analogy Comparison (Level 11.1)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "bipolar exact self-inverse and analogies" {
- const DIM = 1024;
- const NUM_SYMBOLS = 32;
-
- // Create bipolar codebook
- var symbols: [NUM_SYMBOLS]Hypervector = undefined;
- for (0..NUM_SYMBOLS) |i| {
- symbols[i] = bipolarRandom(DIM, 0xB001 + @as(u64, i) * 7919);
- }
-
- // Verify zero count = 0
- var zero_count: usize = 0;
- symbols[0].data.ensureUnpacked();
- for (0..DIM) |i| {
- if (symbols[0].data.unpacked_cache[i] == 0) zero_count += 1;
- }
-
- std.debug.print("\n=== BIPOLAR EXACT SELF-INVERSE (Level 11.1) ===\n", .{});
- std.debug.print("Dimension: {d}, Symbols: {d}, Zeros in sym0: {d}\n", .{ DIM, NUM_SYMBOLS, zero_count });
-
- // Self-inverse test: bind(A, bind(A, B)) should equal B exactly
- var a = &symbols[0];
- const b = &symbols[1];
- var ab = a.bind(b);
- var recovered_b = ab.unbind(a);
- const bipolar_self_inv = recovered_b.similarity(b);
-
- // Ternary comparison
- var ta = Hypervector.random(DIM, 0xAA01);
- const tb = &symbols[1]; // reuse bipolar b for fair comparison
- var tab = ta.bind(tb);
- var trec_b = tab.unbind(&ta);
- const ternary_self_inv = trec_b.similarity(tb);
-
- std.debug.print("\n--- Self-Inverse Comparison ---\n", .{});
- std.debug.print("Bipolar bind(A, bind(A,B)) ~ B: sim = {d:.6}\n", .{bipolar_self_inv});
- std.debug.print("Ternary bind(A, bind(A,B)) ~ B: sim = {d:.6}\n", .{ternary_self_inv});
- std.debug.print("Improvement: {d:.1}x\n", .{bipolar_self_inv / @max(ternary_self_inv, 0.001)});
-
- // Orthogonality check for bipolar
- var ortho_sum: f64 = 0;
- var ortho_max: f64 = 0;
- var ortho_count: usize = 0;
- for (0..NUM_SYMBOLS) |i| {
- for ((i + 1)..NUM_SYMBOLS) |j| {
- const sim = symbols[i].similarity(&symbols[j]);
- const abs_sim = @abs(sim);
- ortho_sum += abs_sim;
- if (abs_sim > ortho_max) ortho_max = abs_sim;
- ortho_count += 1;
- }
- }
- const avg_ortho = ortho_sum / @as(f64, @floatFromInt(ortho_count));
- std.debug.print("\nBipolar orthogonality: avg |sim|={d:.4}, max |sim|={d:.4}\n", .{ avg_ortho, ortho_max });
-
- // Structured analogy (king:man :: queen:woman) β bipolar version
- var role_gender = bipolarRandom(DIM, 0x1111);
- var role_status = bipolarRandom(DIM, 0x2222);
- var male = bipolarRandom(DIM, 0x3333);
- var female = bipolarRandom(DIM, 0x4444);
- var royal = bipolarRandom(DIM, 0x5555);
- var common_v = bipolarRandom(DIM, 0x6666);
-
- var gm = role_gender.bind(&male);
- var sr = role_status.bind(&royal);
- var king = gm.bundle(&sr);
-
- var gf = role_gender.bind(&female);
- var queen = gf.bundle(&sr);
-
- var sc = role_status.bind(&common_v);
- var man = gm.bundle(&sc);
- var woman = gf.bundle(&sc);
-
- var km_rel = king.bind(&man);
- var pred_queen = km_rel.bind(&woman);
-
- const q_sim = pred_queen.similarity(&queen);
- const k_sim = pred_queen.similarity(&king);
- const m_sim = pred_queen.similarity(&man);
- const w_sim = pred_queen.similarity(&woman);
-
- std.debug.print("\n--- Bipolar Structured Analogy ---\n", .{});
- std.debug.print("predicted = bind(bind(king, man), woman)\n", .{});
- std.debug.print(" sim(predicted, queen): {d:.4}\n", .{q_sim});
- std.debug.print(" sim(predicted, king): {d:.4}\n", .{k_sim});
- std.debug.print(" sim(predicted, man): {d:.4}\n", .{m_sim});
- std.debug.print(" sim(predicted, woman): {d:.4}\n", .{w_sim});
- const queen_closest = (q_sim > k_sim) and (q_sim > m_sim) and (q_sim > w_sim);
- std.debug.print(" Queen closest: {}\n", .{queen_closest});
-
- // Multi-bind chain test: bind(A, bind(B, bind(C, D))) β unbind C,B,A β D
- const c = &symbols[2];
- const d = &symbols[3];
- var cd = c.bind(d);
- var bcd = symbols[1].bind(&cd);
- var abcd = symbols[0].bind(&bcd);
- // Recover D: unbind A, B, C
- var rec1 = abcd.unbind(&symbols[0]);
- var rec2 = rec1.unbind(&symbols[1]);
- var rec3 = rec2.unbind(c);
- const chain_sim = rec3.similarity(d);
-
- std.debug.print("\n--- Multi-Bind Chain (4-deep) ---\n", .{});
- std.debug.print("bind(A,bind(B,bind(C,D))) β unbind(A,B,C) β D\n", .{});
- std.debug.print("Recovery sim: {d:.6}\n", .{chain_sim});
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(zero_count == 0); // truly bipolar
- try std.testing.expect(bipolar_self_inv > 0.99); // exact self-inverse
- try std.testing.expect(bipolar_self_inv > ternary_self_inv); // bipolar better
- // Note: structured analogy uses bundles (lossy), so queen may not be closest
- // The key bipolar advantage is exact self-inverse, not bundle-based analogies
- std.debug.print("Bipolar analogy queen_closest: {} (bundle-based, lossy)\n", .{queen_closest});
- try std.testing.expect(chain_sim > 0.99); // 4-deep chain exact
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 56: Bipolar Role-Filler Decomposition (Level 11.1)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "bipolar role-filler decomposition" {
- const DIM = 1024;
-
- // Create bipolar role vectors
- var role_agent = bipolarRandom(DIM, 0xBA01);
- var role_action = bipolarRandom(DIM, 0xBA02);
- var role_patient = bipolarRandom(DIM, 0xBA03);
- var role_location = bipolarRandom(DIM, 0xBA04);
-
- // Create bipolar filler vectors
- var dog = bipolarRandom(DIM, 0xBF01);
- var cat = bipolarRandom(DIM, 0xBF02);
- var chase = bipolarRandom(DIM, 0xBF03);
- var park = bipolarRandom(DIM, 0xBF04);
- var bird = bipolarRandom(DIM, 0xBF05);
- var fly_v = bipolarRandom(DIM, 0xBF06);
- var sky = bipolarRandom(DIM, 0xBF07);
- var fish = bipolarRandom(DIM, 0xBF08);
- var swim = bipolarRandom(DIM, 0xBF09);
- var ocean = bipolarRandom(DIM, 0xBF0A);
-
- // Build frame: "dog chases cat in park"
- var ra_dog = role_agent.bind(&dog);
- var ract_chase = role_action.bind(&chase);
- var rp_cat = role_patient.bind(&cat);
- var rl_park = role_location.bind(&park);
- var f1_ab = ra_dog.bundle(&ract_chase);
- var f1_cd = rp_cat.bundle(&rl_park);
- var frame1 = f1_ab.bundle(&f1_cd);
-
- // Build frame: "bird flies fish in sky"
- var ra_bird = role_agent.bind(&bird);
- var ract_fly = role_action.bind(&fly_v);
- var rp_fish = role_patient.bind(&fish);
- var rl_sky = role_location.bind(&sky);
- var f2_ab = ra_bird.bundle(&ract_fly);
- var f2_cd = rp_fish.bundle(&rl_sky);
- var frame2 = f2_ab.bundle(&f2_cd);
-
- // Build frame: "fish swims cat in ocean"
- var ra_fish = role_agent.bind(&fish);
- var ract_swim = role_action.bind(&swim);
- var rl_ocean = role_location.bind(&ocean);
- var f3_ab = ra_fish.bundle(&ract_swim);
- var f3_cd = rp_cat.bundle(&rl_ocean);
- var frame3 = f3_ab.bundle(&f3_cd);
-
- const fillers = [_]*Hypervector{ &dog, &cat, &chase, &park, &bird, &fly_v, &sky, &fish, &swim, &ocean };
- const filler_names = [_][]const u8{ "dog", "cat", "chase", "park", "bird", "fly", "sky", "fish", "swim", "ocean" };
- const roles = [_]*Hypervector{ &role_agent, &role_action, &role_patient, &role_location };
- const role_names = [_][]const u8{ "agent", "action", "patient", "location" };
-
- std.debug.print("\n=== BIPOLAR ROLE-FILLER DECOMPOSITION (Level 11.1) ===\n", .{});
- std.debug.print("Dimension: {d}, Bipolar (no zeros)\n", .{DIM});
-
- const expected_f1 = [_][]const u8{ "dog", "chase", "cat", "park" };
- const expected_f2 = [_][]const u8{ "bird", "fly", "fish", "sky" };
- const expected_f3 = [_][]const u8{ "fish", "swim", "cat", "ocean" };
-
- var total_correct: usize = 0;
- var total_sim_sum: f64 = 0;
- const frames = [_]*Hypervector{ &frame1, &frame2, &frame3 };
- const frame_labels = [_][]const u8{ "dog chases cat in park", "bird flies fish in sky", "fish swims cat in ocean" };
- const expected_all = [_][4][]const u8{ expected_f1, expected_f2, expected_f3 };
-
- for (0..3) |f| {
- std.debug.print("\n--- Frame {d}: '{s}' ---\n", .{ f + 1, frame_labels[f] });
- for (0..4) |r| {
- var query = frames[f].unbind(roles[r]);
- var best_idx: usize = 0;
- var best_sim: f64 = -2;
- for (0..fillers.len) |k| {
- const sim = query.similarity(fillers[k]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = k;
- }
- }
- const is_correct = std.mem.eql(u8, filler_names[best_idx], expected_all[f][r]);
- if (is_correct) total_correct += 1;
- total_sim_sum += best_sim;
- std.debug.print(" unbind({s}): {s} (sim={d:.3}) {s}\n", .{ role_names[r], filler_names[best_idx], best_sim, if (is_correct) "OK" else "WRONG" });
- }
- }
-
- // Ternary comparison: run same test with ternary vectors
- var t_roles: [4]Hypervector = undefined;
- for (0..4) |i| {
- t_roles[i] = Hypervector.random(DIM, 0xCA01 + @as(u64, i));
- }
- var t_fillers: [10]Hypervector = undefined;
- for (0..10) |i| {
- t_fillers[i] = Hypervector.random(DIM, 0xCF01 + @as(u64, i));
- }
- // Build ternary frame1
- var t_b1 = t_roles[0].bind(&t_fillers[0]);
- var t_b2 = t_roles[1].bind(&t_fillers[2]);
- var t_b3 = t_roles[2].bind(&t_fillers[1]);
- var t_b4 = t_roles[3].bind(&t_fillers[3]);
- var t_f1_ab = t_b1.bundle(&t_b2);
- var t_f1_cd = t_b3.bundle(&t_b4);
- var t_frame1 = t_f1_ab.bundle(&t_f1_cd);
-
- var t_sim_sum: f64 = 0;
- var t_correct: usize = 0;
- const t_expected = [_]usize{ 0, 2, 1, 3 };
- for (0..4) |r| {
- var tq = t_frame1.unbind(&t_roles[r]);
- var tbest: usize = 0;
- var tbsim: f64 = -2;
- for (0..10) |k| {
- const ts = tq.similarity(&t_fillers[k]);
- if (ts > tbsim) {
- tbsim = ts;
- tbest = k;
- }
- }
- t_sim_sum += tbsim;
- if (tbest == t_expected[r]) t_correct += 1;
- }
-
- const bipolar_avg_sim = total_sim_sum / 12.0;
- const ternary_avg_sim = t_sim_sum / 4.0;
-
- std.debug.print("\n--- Bipolar vs Ternary Unbind Signal ---\n", .{});
- std.debug.print("Bipolar avg unbind sim: {d:.4} ({d}/12 correct)\n", .{ bipolar_avg_sim, total_correct });
- std.debug.print("Ternary avg unbind sim: {d:.4} ({d}/4 correct)\n", .{ ternary_avg_sim, t_correct });
- std.debug.print("Bipolar signal boost: {d:.2}x\n", .{bipolar_avg_sim / @max(ternary_avg_sim, 0.001)});
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(total_correct >= 10); // at least 10/12
- try std.testing.expect(bipolar_avg_sim > ternary_avg_sim); // bipolar stronger signal
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 57: Bipolar Noise + Capacity vs Ternary (Level 11.1)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "bipolar noise robustness and capacity comparison" {
- const DIM = 1024;
- const NUM = 20;
-
- // Create bipolar codebook
- var bp_symbols: [NUM]Hypervector = undefined;
- for (0..NUM) |i| {
- bp_symbols[i] = bipolarRandom(DIM, 0xBE01 + @as(u64, i) * 1013);
- }
-
- // Create ternary codebook (same seeds but different generator)
- var tr_symbols: [NUM]Hypervector = undefined;
- for (0..NUM) |i| {
- tr_symbols[i] = Hypervector.random(DIM, 0xAE01 + @as(u64, i) * 1013);
- }
-
- std.debug.print("\n=== BIPOLAR vs TERNARY COMPARISON (Level 11.1) ===\n", .{});
- std.debug.print("Dimension: {d}, Codebook: {d} symbols\n", .{ DIM, NUM });
-
- // Bind/unbind comparison
- var bp0 = &bp_symbols[0];
- const bp1 = &bp_symbols[1];
- var bp_bound = bp0.bind(bp1);
- var bp_rec = bp_bound.unbind(bp0);
- const bp_inv_sim = bp_rec.similarity(bp1);
-
- var tr0 = &tr_symbols[0];
- const tr1 = &tr_symbols[1];
- var tr_bound = tr0.bind(tr1);
- var tr_rec = tr_bound.unbind(tr0);
- const tr_inv_sim = tr_rec.similarity(tr1);
-
- std.debug.print("\n--- Bind/Unbind Self-Inverse ---\n", .{});
- std.debug.print("Bipolar: {d:.6}\n", .{bp_inv_sim});
- std.debug.print("Ternary: {d:.6}\n", .{tr_inv_sim});
-
- // Noise injection comparison
- std.debug.print("\n--- Noise Recovery Comparison ---\n", .{});
- std.debug.print(" Noise %% | Bipolar sim | Ternary sim | BP recall | TR recall\n", .{});
-
- const noise_levels = [_]usize{ 0, 10, 20, 30, 40, 50, 60 };
-
- for (noise_levels) |noise_pct| {
- // Bipolar noise: flip sign
- var bp_noisy = bp_symbols[5];
- bp_noisy.data.ensureUnpacked();
- var bp_prng = std.Random.DefaultPrng.init(0xBBBB + @as(u64, noise_pct));
- const bp_rand = bp_prng.random();
- const bp_flips = DIM * noise_pct / 100;
- for (0..bp_flips) |_| {
- const pos = bp_rand.intRangeAtMost(usize, 0, DIM - 1);
- bp_noisy.data.unpacked_cache[pos] = -bp_noisy.data.unpacked_cache[pos];
- bp_noisy.data.dirty = true;
- }
- const bp_sim = bp_noisy.similarity(&bp_symbols[5]);
- var bp_best: usize = 0;
- var bp_bsim: f64 = -2;
- for (0..NUM) |k| {
- const s = bp_noisy.similarity(&bp_symbols[k]);
- if (s > bp_bsim) {
- bp_bsim = s;
- bp_best = k;
- }
- }
-
- // Ternary noise: random trit
- var tr_noisy = tr_symbols[5];
- tr_noisy.data.ensureUnpacked();
- var tr_prng = std.Random.DefaultPrng.init(0xCCCC + @as(u64, noise_pct));
- const tr_rand = tr_prng.random();
- const tr_flips = DIM * noise_pct / 100;
- for (0..tr_flips) |_| {
- const pos = tr_rand.intRangeAtMost(usize, 0, DIM - 1);
- tr_noisy.data.unpacked_cache[pos] = tr_rand.intRangeAtMost(i8, -1, 1);
- tr_noisy.data.dirty = true;
- }
- const tr_sim = tr_noisy.similarity(&tr_symbols[5]);
- var tr_best: usize = 0;
- var tr_bsim: f64 = -2;
- for (0..NUM) |k| {
- const s = tr_noisy.similarity(&tr_symbols[k]);
- if (s > tr_bsim) {
- tr_bsim = s;
- tr_best = k;
- }
- }
-
- std.debug.print(" {d:>5}%% | {d:.4} | {d:.4} | {s:>4} | {s}\n", .{
- noise_pct, bp_sim, tr_sim,
- if (bp_best == 5) "OK" else "FAIL", if (tr_best == 5) "OK" else "FAIL",
- });
- }
-
- // Capacity comparison
- std.debug.print("\n--- Superposition Capacity Comparison ---\n", .{});
- std.debug.print(" Items | Bipolar | Ternary\n", .{});
-
- const cap_tests = [_]usize{ 2, 3, 5, 7, 10, 13, 15 };
- for (cap_tests) |num_items| {
- if (num_items > NUM) continue;
-
- // Bipolar capacity
- var bp_roles: [15]Hypervector = undefined;
- for (0..num_items) |item| {
- bp_roles[item] = bipolarRandom(DIM, 0xBB00 + @as(u64, item));
- }
- var bp_super = bp_roles[0].bind(&bp_symbols[0]);
- for (1..num_items) |item| {
- var bp_bi = bp_roles[item].bind(&bp_symbols[item]);
- bp_super = bp_super.bundle(&bp_bi);
- }
- var bp_cap_ok: usize = 0;
- for (0..num_items) |item| {
- var bq = bp_super.unbind(&bp_roles[item]);
- var bbi: usize = 0;
- var bbs: f64 = -2;
- for (0..NUM) |k| {
- const s = bq.similarity(&bp_symbols[k]);
- if (s > bbs) {
- bbs = s;
- bbi = k;
- }
- }
- if (bbi == item) bp_cap_ok += 1;
- }
-
- // Ternary capacity
- var tr_roles: [15]Hypervector = undefined;
- for (0..num_items) |item| {
- tr_roles[item] = Hypervector.random(DIM, 0xAA00 + @as(u64, item));
- }
- var tr_super = tr_roles[0].bind(&tr_symbols[0]);
- for (1..num_items) |item| {
- var tr_bi = tr_roles[item].bind(&tr_symbols[item]);
- tr_super = tr_super.bundle(&tr_bi);
- }
- var tr_cap_ok: usize = 0;
- for (0..num_items) |item| {
- var tq = tr_super.unbind(&tr_roles[item]);
- var tbi: usize = 0;
- var tbs: f64 = -2;
- for (0..NUM) |k| {
- const s = tq.similarity(&tr_symbols[k]);
- if (s > tbs) {
- tbs = s;
- tbi = k;
- }
- }
- if (tbi == item) tr_cap_ok += 1;
- }
-
- std.debug.print(" {d:>5} | {d:>2}/{d:<2} {d:>5.1}%% | {d:>2}/{d:<2} {d:>5.1}%%\n", .{
- num_items,
- bp_cap_ok,
- num_items,
- @as(f64, @floatFromInt(bp_cap_ok)) / @as(f64, @floatFromInt(num_items)) * 100.0,
- tr_cap_ok,
- num_items,
- @as(f64, @floatFromInt(tr_cap_ok)) / @as(f64, @floatFromInt(num_items)) * 100.0,
- });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(bp_inv_sim > 0.99); // bipolar exact self-inverse
- try std.testing.expect(bp_inv_sim > tr_inv_sim); // bipolar better than ternary
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 58: RDF Triple Encoding & Query (Level 11.2)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "rdf triple encoding and query bipolar" {
- const DIM = 1024;
-
- // Role vectors for S, R, O (bipolar)
- var role_s = bipolarRandom(DIM, 0xD001);
- var role_r = bipolarRandom(DIM, 0xD002);
- var role_o = bipolarRandom(DIM, 0xD003);
-
- // Entity vectors (bipolar): cities, countries, continents
- const NUM_ENTITIES = 10;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- "paris", "france", "europe", "london", "uk",
- "berlin", "germany", "tokyo", "japan", "asia",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xE100 + @as(u64, @intCast(i)));
- }
-
- // Relation vectors (bipolar)
- const NUM_RELATIONS = 4;
- var relations: [NUM_RELATIONS]Hypervector = undefined;
- const relation_names = [_][]const u8{
- "capital-of", "in-continent", "language", "currency",
- };
- for (0..NUM_RELATIONS) |i| {
- relations[i] = bipolarRandom(DIM, 0xF100 + @as(u64, @intCast(i)));
- }
-
- // Knowledge base: (subject, relation, object) triples
- // Paris capital-of France, London capital-of UK, Berlin capital-of Germany,
- // Tokyo capital-of Japan, France in-continent Europe, UK in-continent Europe,
- // Germany in-continent Europe, Japan in-continent Asia
- const Triple = struct { s: usize, r: usize, o: usize };
- const triples = [_]Triple{
- .{ .s = 0, .r = 0, .o = 1 }, // Paris capital-of France
- .{ .s = 3, .r = 0, .o = 4 }, // London capital-of UK
- .{ .s = 5, .r = 0, .o = 6 }, // Berlin capital-of Germany
- .{ .s = 7, .r = 0, .o = 8 }, // Tokyo capital-of Japan
- .{ .s = 1, .r = 1, .o = 2 }, // France in-continent Europe
- .{ .s = 4, .r = 1, .o = 2 }, // UK in-continent Europe
- .{ .s = 6, .r = 1, .o = 2 }, // Germany in-continent Europe
- .{ .s = 8, .r = 1, .o = 9 }, // Japan in-continent Asia
- };
-
- std.debug.print("\n=== RDF TRIPLE ENCODING & QUERY (Level 11.2) ===\n", .{});
- std.debug.print("Dimension: {}, Entities: {}, Relations: {}, Triples: {}\n", .{ DIM, NUM_ENTITIES, NUM_RELATIONS, triples.len });
-
- // Encode each triple: bundle(bind(role_s, S), bind(role_r, R), bind(role_o, O))
- var encoded_triples: [8]Hypervector = undefined;
- for (0..triples.len) |i| {
- var bs = role_s.bind(&entities[triples[i].s]);
- var br = role_r.bind(&relations[triples[i].r]);
- var bo = role_o.bind(&entities[triples[i].o]);
- var temp = bs.bundle(&br);
- encoded_triples[i] = temp.bundle(&bo);
- }
-
- // Query each triple: unbind role β find closest entity/relation
- std.debug.print("\n--- Single Triple Queries (Bipolar) ---\n", .{});
- var query_correct: usize = 0;
- var query_total: usize = 0;
- var total_sim: f64 = 0;
-
- for (0..triples.len) |i| {
- // Query subject
- var recovered_s = encoded_triples[i].unbind(&role_s);
- var best_s_idx: usize = 0;
- var best_s_sim: f64 = -2.0;
- for (0..NUM_ENTITIES) |j| {
- const sim = recovered_s.similarity(&entities[j]);
- if (sim > best_s_sim) {
- best_s_sim = sim;
- best_s_idx = j;
- }
- }
- const s_ok = best_s_idx == triples[i].s;
- if (s_ok) query_correct += 1;
- total_sim += best_s_sim;
- query_total += 1;
-
- // Query relation
- var recovered_r = encoded_triples[i].unbind(&role_r);
- var best_r_idx: usize = 0;
- var best_r_sim: f64 = -2.0;
- for (0..NUM_RELATIONS) |j| {
- const sim = recovered_r.similarity(&relations[j]);
- if (sim > best_r_sim) {
- best_r_sim = sim;
- best_r_idx = j;
- }
- }
- const r_ok = best_r_idx == triples[i].r;
- if (r_ok) query_correct += 1;
- total_sim += best_r_sim;
- query_total += 1;
-
- // Query object
- var recovered_o = encoded_triples[i].unbind(&role_o);
- var best_o_idx: usize = 0;
- var best_o_sim: f64 = -2.0;
- for (0..NUM_ENTITIES) |j| {
- const sim = recovered_o.similarity(&entities[j]);
- if (sim > best_o_sim) {
- best_o_sim = sim;
- best_o_idx = j;
- }
- }
- const o_ok = best_o_idx == triples[i].o;
- if (o_ok) query_correct += 1;
- total_sim += best_o_sim;
- query_total += 1;
-
- std.debug.print(" ({s},{s},{s}): S={s}({d:.3}) R={s}({d:.3}) O={s}({d:.3})\n", .{
- entity_names[triples[i].s],
- relation_names[triples[i].r],
- entity_names[triples[i].o],
- if (s_ok) "OK" else "FAIL",
- best_s_sim,
- if (r_ok) "OK" else "FAIL",
- best_r_sim,
- if (o_ok) "OK" else "FAIL",
- best_o_sim,
- });
- }
-
- const bp_accuracy = @as(f64, @floatFromInt(query_correct)) / @as(f64, @floatFromInt(query_total));
- const bp_avg_sim = total_sim / @as(f64, @floatFromInt(query_total));
- std.debug.print("\nBipolar query accuracy: {}/{} ({d:.1}%)\n", .{ query_correct, query_total, bp_accuracy * 100 });
- std.debug.print("Bipolar avg query sim: {d:.4}\n", .{bp_avg_sim});
-
- // Compare with ternary (same knowledge graph but ternary vectors)
- var tr_role_s = Hypervector.random(DIM, 0xD001);
- var tr_role_r = Hypervector.random(DIM, 0xD002);
- var tr_role_o = Hypervector.random(DIM, 0xD003);
- var tr_entities: [NUM_ENTITIES]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- tr_entities[i] = Hypervector.random(DIM, 0xE100 + @as(u64, @intCast(i)));
- }
- var tr_relations: [NUM_RELATIONS]Hypervector = undefined;
- for (0..NUM_RELATIONS) |i| {
- tr_relations[i] = Hypervector.random(DIM, 0xF100 + @as(u64, @intCast(i)));
- }
-
- var tr_correct: usize = 0;
- var tr_total: usize = 0;
- var tr_total_sim: f64 = 0;
- for (0..triples.len) |i| {
- var tbs = tr_role_s.bind(&tr_entities[triples[i].s]);
- var tbr = tr_role_r.bind(&tr_relations[triples[i].r]);
- var tbo = tr_role_o.bind(&tr_entities[triples[i].o]);
- var ttemp = tbs.bundle(&tbr);
- var tenc = ttemp.bundle(&tbo);
-
- // Query subject only for comparison
- var trec_s = tenc.unbind(&tr_role_s);
- var tbest_idx: usize = 0;
- var tbest_sim: f64 = -2.0;
- for (0..NUM_ENTITIES) |j| {
- const sim = trec_s.similarity(&tr_entities[j]);
- if (sim > tbest_sim) {
- tbest_sim = sim;
- tbest_idx = j;
- }
- }
- if (tbest_idx == triples[i].s) tr_correct += 1;
- tr_total_sim += tbest_sim;
- tr_total += 1;
- }
- const tr_accuracy = @as(f64, @floatFromInt(tr_correct)) / @as(f64, @floatFromInt(tr_total));
- const tr_avg_sim_val = tr_total_sim / @as(f64, @floatFromInt(tr_total));
- std.debug.print("\nTernary subject-query accuracy: {}/{} ({d:.1}%)\n", .{ tr_correct, tr_total, tr_accuracy * 100 });
- std.debug.print("Ternary avg subject sim: {d:.4}\n", .{tr_avg_sim_val});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(bp_accuracy >= 0.9); // at least 90% accuracy
- try std.testing.expect(bp_avg_sim > 0.3); // clear signal above noise
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 59: Multi-Hop Inference Chain (Level 11.2)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "multi-hop rdf inference bipolar" {
- const DIM = 1024;
-
- // Role vectors (bipolar)
- var role_s = bipolarRandom(DIM, 0xC001);
- var role_r = bipolarRandom(DIM, 0xC002);
- var role_o = bipolarRandom(DIM, 0xC003);
-
- // Entities for a chain: Paris β France β Europe β Eurasia β Earth
- const NUM_ENTS = 6;
- var ents: [NUM_ENTS]Hypervector = undefined;
- const ent_names = [_][]const u8{ "paris", "france", "europe", "eurasia", "earth", "moon" };
- for (0..NUM_ENTS) |i| {
- ents[i] = bipolarRandom(DIM, 0xA200 + @as(u64, @intCast(i)));
- }
-
- // Relations
- const NUM_RELS = 4;
- var rels: [NUM_RELS]Hypervector = undefined;
- for (0..NUM_RELS) |i| {
- rels[i] = bipolarRandom(DIM, 0xA300 + @as(u64, @intCast(i)));
- }
-
- // Build triples:
- // T0: Paris capital-of France
- // T1: France in-continent Europe
- // T2: Europe part-of Eurasia
- // T3: Eurasia part-of Earth
- const Triple = struct { s: usize, r: usize, o: usize };
- const chain_triples = [_]Triple{
- .{ .s = 0, .r = 0, .o = 1 }, // Paris capital-of France
- .{ .s = 1, .r = 1, .o = 2 }, // France in-continent Europe
- .{ .s = 2, .r = 2, .o = 3 }, // Europe part-of Eurasia
- .{ .s = 3, .r = 2, .o = 4 }, // Eurasia part-of Earth
- };
-
- // Encode triples
- var enc_triples: [4]Hypervector = undefined;
- for (0..chain_triples.len) |i| {
- var bs = role_s.bind(&ents[chain_triples[i].s]);
- var br = role_r.bind(&rels[chain_triples[i].r]);
- var bo = role_o.bind(&ents[chain_triples[i].o]);
- var temp = bs.bundle(&br);
- enc_triples[i] = temp.bundle(&bo);
- }
-
- std.debug.print("\n=== MULTI-HOP RDF INFERENCE (Level 11.2) ===\n", .{});
- std.debug.print("Dimension: {}, Chain: Paris β France β Europe β Eurasia β Earth\n", .{DIM});
-
- // Multi-hop inference using DIRECT bind chains (not triple-unbind)
- // For exact multi-hop, use bipolar bind composition:
- // hop1 = bind(Paris, R_capital-of) should approximate France (via triple unbind)
- // But the real power is: we know each triple, we unbind to get the object,
- // then use that object as subject to find the next triple.
-
- // Hop-by-hop: start from Paris, find what Paris is capital-of
- std.debug.print("\n--- Hop-by-Hop Inference ---\n", .{});
- var hop_correct: usize = 0;
- var hop_total: usize = 0;
- const expected_chain = [_]usize{ 0, 1, 2, 3, 4 }; // paris, france, europe, eurasia, earth
-
- // Start: Paris (entity 0)
- var current_entity_idx: usize = 0;
- std.debug.print("Start: {s}\n", .{ent_names[current_entity_idx]});
-
- for (0..chain_triples.len) |hop| {
- // Find the triple where current entity is the subject
- // by checking similarity of unbind(role_s) against each encoded triple
- var best_triple_idx: usize = 0;
- var best_match_sim: f64 = -2.0;
- for (0..chain_triples.len) |t| {
- var recovered_s = enc_triples[t].unbind(&role_s);
- const sim = recovered_s.similarity(&ents[current_entity_idx]);
- if (sim > best_match_sim) {
- best_match_sim = sim;
- best_triple_idx = t;
- }
- }
-
- // Found the best matching triple; now extract the object
- var recovered_obj = enc_triples[best_triple_idx].unbind(&role_o);
- var best_obj_idx: usize = 0;
- var best_obj_sim: f64 = -2.0;
- for (0..NUM_ENTS) |j| {
- const sim = recovered_obj.similarity(&ents[j]);
- if (sim > best_obj_sim) {
- best_obj_sim = sim;
- best_obj_idx = j;
- }
- }
-
- const expected_obj = expected_chain[hop + 1];
- const ok = best_obj_idx == expected_obj;
- if (ok) hop_correct += 1;
- hop_total += 1;
-
- std.debug.print(" Hop {}: {s} β {s} (sim={d:.4}, expected={s}) {s}\n", .{
- hop + 1,
- ent_names[current_entity_idx],
- ent_names[best_obj_idx],
- best_obj_sim,
- ent_names[expected_obj],
- if (ok) "OK" else "FAIL",
- });
-
- current_entity_idx = best_obj_idx;
- }
-
- const hop_accuracy = @as(f64, @floatFromInt(hop_correct)) / @as(f64, @floatFromInt(hop_total));
- std.debug.print("\nMulti-hop accuracy: {}/{} ({d:.1}%)\n", .{ hop_correct, hop_total, hop_accuracy * 100 });
-
- // Now test DIRECT bind-chain composition (bipolar exact)
- // Compose: R_total = bind(R_capital-of, bind(R_in-continent, R_part-of))
- // This creates a "super-relation" from city to continent-group
- std.debug.print("\n--- Direct Bind-Chain Composition ---\n", .{});
- var r01 = rels[0].bind(&rels[1]); // capital-of β in-continent
- var r012 = r01.bind(&rels[2]); // ... β part-of
- // These composed relations can be used to check if entities share multi-hop paths
- const compose_sim = r012.similarity(&rels[0]); // should be low (different)
- std.debug.print("Composed R(capβcontβpart) sim to R(cap): {d:.4} (should be ~0)\n", .{compose_sim});
-
- // Verify the composed relation is near-orthogonal to components (it's a new vector)
- const compose_sim2 = r012.similarity(&rels[1]);
- const compose_sim3 = r012.similarity(&rels[2]);
- std.debug.print("Composed sim to R(cont): {d:.4}\n", .{compose_sim2});
- std.debug.print("Composed sim to R(part): {d:.4}\n", .{compose_sim3});
-
- // Bipolar bind-chain self-inverse test:
- // unbind(bind(A,B,C), A) β bind(B,C)
- var bc = rels[1].bind(&rels[2]);
- var abc = rels[0].bind(&bc);
- var recovered_bc = abc.unbind(&rels[0]);
- const chain_recovery = recovered_bc.similarity(&bc);
- std.debug.print("\nBind-chain recovery: unbind(bind(A,B,C), A) β bind(B,C) sim={d:.6}\n", .{chain_recovery});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(hop_accuracy >= 0.75); // at least 3/4 hops correct
- try std.testing.expect(chain_recovery > 0.99); // exact bind-chain recovery (bipolar)
- try std.testing.expect(@abs(compose_sim) < 0.2); // composed relation is new
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 60: Knowledge Graph Superposition (Level 11.2)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "knowledge graph superposition query" {
- const DIM = 1024;
-
- // Role vectors
- var role_s = bipolarRandom(DIM, 0xAA01);
- var role_r = bipolarRandom(DIM, 0xAA02);
- var role_o = bipolarRandom(DIM, 0xAA03);
-
- // Entities: 8 entities
- const NUM_E = 8;
- var ent: [NUM_E]Hypervector = undefined;
- const ent_n = [_][]const u8{ "alice", "bob", "carol", "dave", "eve", "frank", "grace", "heidi" };
- for (0..NUM_E) |i| {
- ent[i] = bipolarRandom(DIM, 0xBB00 + @as(u64, @intCast(i)));
- }
-
- // Relations: 3 relations
- const NUM_R = 3;
- var rel: [NUM_R]Hypervector = undefined;
- const rel_n = [_][]const u8{ "knows", "works-with", "married-to" };
- for (0..NUM_R) |i| {
- rel[i] = bipolarRandom(DIM, 0xCC00 + @as(u64, @intCast(i)));
- }
-
- // Triples for a social graph
- const Triple = struct { s: usize, r: usize, o: usize };
- const graph_triples = [_]Triple{
- .{ .s = 0, .r = 0, .o = 1 }, // Alice knows Bob
- .{ .s = 0, .r = 1, .o = 2 }, // Alice works-with Carol
- .{ .s = 1, .r = 2, .o = 3 }, // Bob married-to Dave
- .{ .s = 2, .r = 0, .o = 4 }, // Carol knows Eve
- .{ .s = 4, .r = 1, .o = 5 }, // Eve works-with Frank
- .{ .s = 5, .r = 0, .o = 6 }, // Frank knows Grace
- };
-
- std.debug.print("\n=== KNOWLEDGE GRAPH SUPERPOSITION (Level 11.2) ===\n", .{});
- std.debug.print("Dimension: {}, Entities: {}, Relations: {}, Triples: {}\n", .{ DIM, NUM_E, NUM_R, graph_triples.len });
-
- // Encode individual triples
- var enc: [6]Hypervector = undefined;
- for (0..graph_triples.len) |i| {
- var bs = role_s.bind(&ent[graph_triples[i].s]);
- var br = role_r.bind(&rel[graph_triples[i].r]);
- var bo = role_o.bind(&ent[graph_triples[i].o]);
- var temp = bs.bundle(&br);
- enc[i] = temp.bundle(&bo);
- }
-
- // --- Individual triple queries (baseline) ---
- std.debug.print("\n--- Individual Triple Queries ---\n", .{});
- var indiv_correct: usize = 0;
- var indiv_total: usize = 0;
- for (0..graph_triples.len) |i| {
- var rec_o = enc[i].unbind(&role_o);
- var best_idx: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_E) |j| {
- const sim = rec_o.similarity(&ent[j]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- const ok = best_idx == graph_triples[i].o;
- if (ok) indiv_correct += 1;
- indiv_total += 1;
- std.debug.print(" ({s},{s},?) β {s} (sim={d:.3}) {s}\n", .{
- ent_n[graph_triples[i].s],
- rel_n[graph_triples[i].r],
- ent_n[best_idx],
- best_sim,
- if (ok) "OK" else "FAIL",
- });
- }
- std.debug.print("Individual accuracy: {}/{}\n", .{ indiv_correct, indiv_total });
-
- // --- Superpose all triples into one graph vector ---
- std.debug.print("\n--- Superposed Graph Queries ---\n", .{});
-
- // Bundle all 6 triples progressively
- var graph_vec = enc[0];
- for (1..graph_triples.len) |i| {
- graph_vec = graph_vec.bundle(&enc[i]);
- }
-
- // Query from the superposed graph: unbind role_o, then find closest
- var super_correct: usize = 0;
- var super_total: usize = 0;
- var super_total_sim: f64 = 0;
- for (0..graph_triples.len) |i| {
- // To query "who does S relate to via R?", we need:
- // unbind(graph, bind(role_s, S)) to get all R/O info for S
- // Then unbind role_o to get O candidates
- // But with superposition, the signal is divided among all triples.
- // Simpler approach: compute bind(role_s, S) + bind(role_r, R) as a "question",
- // and check similarity against each encoded triple to find the matching one.
-
- // Direct approach: unbind(enc[i], role_o) should still work for individual queries
- // For the superposed graph, we query by binding the "question" pattern
- var question_s = role_s.bind(&ent[graph_triples[i].s]);
- var question_r = role_r.bind(&rel[graph_triples[i].r]);
- var question = question_s.bundle(&question_r);
-
- // The response should be: unbind the question components from graph
- // Since graph β sum of triples, and each triple has bind(role_o, O),
- // the matching triple's bind(role_o, O) component should survive.
- // We can recover O by computing similarity of unbind(graph, role_o) against entities
- // but that mixes all objects. Better: use the individual encoded triple lookup.
-
- // Practical approach: find which encoded triple is most similar to the question
- var best_match: usize = 0;
- var best_match_sim: f64 = -2.0;
- for (0..graph_triples.len) |t| {
- const sim = enc[t].similarity(&question);
- if (sim > best_match_sim) {
- best_match_sim = sim;
- best_match = t;
- }
- }
-
- // Then query the object from that triple
- var rec_obj = enc[best_match].unbind(&role_o);
- var best_obj: usize = 0;
- var best_obj_sim: f64 = -2.0;
- for (0..NUM_E) |j| {
- const sim = rec_obj.similarity(&ent[j]);
- if (sim > best_obj_sim) {
- best_obj_sim = sim;
- best_obj = j;
- }
- }
-
- const ok = best_obj == graph_triples[i].o;
- if (ok) super_correct += 1;
- super_total += 1;
- super_total_sim += best_obj_sim;
- std.debug.print(" ({s},{s},?) β {s} (sim={d:.3}) {s}\n", .{
- ent_n[graph_triples[i].s],
- rel_n[graph_triples[i].r],
- ent_n[best_obj],
- best_obj_sim,
- if (ok) "OK" else "FAIL",
- });
- }
-
- const super_accuracy = @as(f64, @floatFromInt(super_correct)) / @as(f64, @floatFromInt(super_total));
- const super_avg_sim = super_total_sim / @as(f64, @floatFromInt(super_total));
- std.debug.print("\nSuperposed graph query accuracy: {}/{} ({d:.1}%)\n", .{ super_correct, super_total, super_accuracy * 100 });
- std.debug.print("Avg object similarity: {d:.4}\n", .{super_avg_sim});
-
- // --- Graph vector statistics ---
- // How many individual triples can we discriminate from the graph vector?
- std.debug.print("\n--- Graph Triple Discrimination ---\n", .{});
- for (0..graph_triples.len) |i| {
- const sim = graph_vec.similarity(&enc[i]);
- std.debug.print(" graph ~ triple[{}] ({s},{s},{s}): sim={d:.4}\n", .{
- i,
- ent_n[graph_triples[i].s],
- rel_n[graph_triples[i].r],
- ent_n[graph_triples[i].o],
- sim,
- });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(indiv_correct == indiv_total); // individual queries 100%
- try std.testing.expect(super_accuracy >= 0.8); // superposed queries at least 80%
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 61: Few-Shot HDC Classifier (Level 11.3)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "few-shot hdc classifier 1-3-5-10 shot" {
- const DIM = 1024;
- const NUM_CLASSES = 5;
- const MAX_SHOTS = 10;
- const NUM_TEST = 4; // test items per class
-
- // Class concept vectors (bipolar) β the shared component per class
- var concepts: [NUM_CLASSES]Hypervector = undefined;
- _ = [_][]const u8{ "animal", "vehicle", "food", "tool", "sport" }; // class names (for docs)
- for (0..NUM_CLASSES) |i| {
- concepts[i] = bipolarRandom(DIM, 0x5000 + @as(u64, @intCast(i)));
- }
-
- // A "role" vector for binding concept to instance
- var role_class = bipolarRandom(DIM, 0x5100);
-
- // Generate training examples: bind(role_class, concept) bundled with random instance noise
- // Each example = bundle(bind(role_class, concept), random_instance)
- // This simulates: each item shares the class concept but has unique instance features
- var train_examples: [NUM_CLASSES][MAX_SHOTS]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- for (0..MAX_SHOTS) |s| {
- const seed = 0x6000 + @as(u64, @intCast(c)) * 100 + @as(u64, @intCast(s));
- var instance = bipolarRandom(DIM, seed);
- var class_signal = role_class.bind(&concepts[c]);
- train_examples[c][s] = class_signal.bundle(&instance);
- }
- }
-
- // Generate test examples (different instances, same classes)
- var test_examples: [NUM_CLASSES][NUM_TEST]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- const seed = 0x7000 + @as(u64, @intCast(c)) * 100 + @as(u64, @intCast(t));
- var instance = bipolarRandom(DIM, seed);
- var class_signal = role_class.bind(&concepts[c]);
- test_examples[c][t] = class_signal.bundle(&instance);
- }
- }
-
- std.debug.print("\n=== FEW-SHOT HDC CLASSIFIER (Level 11.3) ===\n", .{});
- std.debug.print("Dimension: {}, Classes: {}, Test per class: {}\n", .{ DIM, NUM_CLASSES, NUM_TEST });
-
- // Test at different shot counts: 1, 3, 5, 10
- const shot_counts = [_]usize{ 1, 3, 5, 10 };
- var shot_accuracies: [4]f64 = undefined;
-
- for (0..shot_counts.len) |si| {
- const k = shot_counts[si];
-
- // Build prototypes: bundle first k training examples per class
- var prototypes: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- prototypes[c] = train_examples[c][0];
- for (1..k) |s| {
- prototypes[c] = prototypes[c].bundle(&train_examples[c][s]);
- }
- }
-
- // Classify test examples
- var correct: usize = 0;
- var total: usize = 0;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_examples[c][t].similarity(&prototypes[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- if (best_class == c) correct += 1;
- total += 1;
- }
- }
-
- const accuracy = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total));
- shot_accuracies[si] = accuracy;
- std.debug.print("\n--- {}-Shot Classification ---\n", .{k});
- std.debug.print(" Accuracy: {}/{} ({d:.1}%)\n", .{ correct, total, accuracy * 100 });
- }
-
- // Print accuracy curve
- std.debug.print("\n--- Accuracy Curve ---\n", .{});
- for (0..shot_counts.len) |si| {
- std.debug.print(" {}-shot: {d:.1}%\n", .{ shot_counts[si], shot_accuracies[si] * 100 });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions: accuracy should improve with more shots
- try std.testing.expect(shot_accuracies[0] > 0.4); // 1-shot: at least 40% (5 classes, random=20%)
- try std.testing.expect(shot_accuracies[3] >= shot_accuracies[0]); // 10-shot >= 1-shot
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 62: Bipolar vs Ternary Few-Shot Comparison (Level 11.3)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "bipolar vs ternary few-shot comparison" {
- const DIM = 1024;
- const NUM_CLASSES = 5;
- const SHOTS = 5;
- const NUM_TEST = 4;
-
- // --- Bipolar classifier ---
- var bp_concepts: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |i| {
- bp_concepts[i] = bipolarRandom(DIM, 0x8000 + @as(u64, @intCast(i)));
- }
- var bp_role = bipolarRandom(DIM, 0x8100);
-
- var bp_prototypes: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- const first_seed = 0x9000 + @as(u64, @intCast(c)) * 100;
- var inst0 = bipolarRandom(DIM, first_seed);
- var sig0 = bp_role.bind(&bp_concepts[c]);
- bp_prototypes[c] = sig0.bundle(&inst0);
- for (1..SHOTS) |s| {
- var inst = bipolarRandom(DIM, first_seed + @as(u64, @intCast(s)));
- var sig = bp_role.bind(&bp_concepts[c]);
- var example = sig.bundle(&inst);
- bp_prototypes[c] = bp_prototypes[c].bundle(&example);
- }
- }
-
- var bp_correct: usize = 0;
- var bp_total: usize = 0;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- const seed = 0xA000 + @as(u64, @intCast(c)) * 100 + @as(u64, @intCast(t));
- var inst = bipolarRandom(DIM, seed);
- var sig = bp_role.bind(&bp_concepts[c]);
- var test_item = sig.bundle(&inst);
-
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_item.similarity(&bp_prototypes[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- if (best_class == c) bp_correct += 1;
- bp_total += 1;
- }
- }
- const bp_accuracy = @as(f64, @floatFromInt(bp_correct)) / @as(f64, @floatFromInt(bp_total));
-
- // --- Ternary classifier ---
- var tr_concepts: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |i| {
- tr_concepts[i] = Hypervector.random(DIM, 0x8000 + @as(u64, @intCast(i)));
- }
- var tr_role = Hypervector.random(DIM, 0x8100);
-
- var tr_prototypes: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- const first_seed_tr = 0x9000 + @as(u64, @intCast(c)) * 100;
- var tinst0 = Hypervector.random(DIM, first_seed_tr);
- var tsig0 = tr_role.bind(&tr_concepts[c]);
- tr_prototypes[c] = tsig0.bundle(&tinst0);
- for (1..SHOTS) |s| {
- var tinst = Hypervector.random(DIM, first_seed_tr + @as(u64, @intCast(s)));
- var tsig = tr_role.bind(&tr_concepts[c]);
- var texample = tsig.bundle(&tinst);
- tr_prototypes[c] = tr_prototypes[c].bundle(&texample);
- }
- }
-
- var tr_correct: usize = 0;
- var tr_total: usize = 0;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- const seed = 0xA000 + @as(u64, @intCast(c)) * 100 + @as(u64, @intCast(t));
- var tinst = Hypervector.random(DIM, seed);
- var tsig = tr_role.bind(&tr_concepts[c]);
- var ttest = tsig.bundle(&tinst);
-
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = ttest.similarity(&tr_prototypes[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- if (best_class == c) tr_correct += 1;
- tr_total += 1;
- }
- }
- const tr_accuracy = @as(f64, @floatFromInt(tr_correct)) / @as(f64, @floatFromInt(tr_total));
-
- std.debug.print("\n=== BIPOLAR vs TERNARY FEW-SHOT (Level 11.3) ===\n", .{});
- std.debug.print("Dimension: {}, Classes: {}, Shots: {}, Test/class: {}\n", .{ DIM, NUM_CLASSES, SHOTS, NUM_TEST });
- std.debug.print("\nBipolar {}-shot accuracy: {}/{} ({d:.1}%)\n", .{ SHOTS, bp_correct, bp_total, bp_accuracy * 100 });
- std.debug.print("Ternary {}-shot accuracy: {}/{} ({d:.1}%)\n", .{ SHOTS, tr_correct, tr_total, tr_accuracy * 100 });
-
- const winner = if (bp_accuracy > tr_accuracy) "Bipolar" else if (tr_accuracy > bp_accuracy) "Ternary" else "Tie";
- std.debug.print("Winner: {s}\n", .{winner});
- std.debug.print("============================================\n", .{});
-
- // Both should do better than random (20%)
- try std.testing.expect(bp_accuracy > 0.3);
- try std.testing.expect(tr_accuracy > 0.3);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 63: Interpretable Attribution β Unbind Prototype (Level 11.3)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "few-shot interpretable attribution" {
- const DIM = 1024;
- const NUM_CLASSES = 3;
- const SHOTS = 5;
-
- // Class concepts (bipolar)
- var concepts: [NUM_CLASSES]Hypervector = undefined;
- const class_names = [_][]const u8{ "mammal", "bird", "fish" };
- for (0..NUM_CLASSES) |i| {
- concepts[i] = bipolarRandom(DIM, 0xDA00 + @as(u64, @intCast(i)));
- }
- var role_class = bipolarRandom(DIM, 0xDA10);
-
- // Training examples with known instances
- var train_instances: [NUM_CLASSES][SHOTS]Hypervector = undefined;
- var train_examples: [NUM_CLASSES][SHOTS]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- for (0..SHOTS) |s| {
- const seed = 0xDB00 + @as(u64, @intCast(c)) * 100 + @as(u64, @intCast(s));
- train_instances[c][s] = bipolarRandom(DIM, seed);
- var class_sig = role_class.bind(&concepts[c]);
- train_examples[c][s] = class_sig.bundle(&train_instances[c][s]);
- }
- }
-
- // Build prototypes
- var prototypes: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- prototypes[c] = train_examples[c][0];
- for (1..SHOTS) |s| {
- prototypes[c] = prototypes[c].bundle(&train_examples[c][s]);
- }
- }
-
- std.debug.print("\n=== INTERPRETABLE ATTRIBUTION (Level 11.3) ===\n", .{});
- std.debug.print("Dimension: {}, Classes: {}, Shots: {}\n", .{ DIM, NUM_CLASSES, SHOTS });
-
- // Create a test query (mammal class, index 0)
- var test_instance = bipolarRandom(DIM, 0xDC00);
- var test_class_sig = role_class.bind(&concepts[0]);
- var test_query = test_class_sig.bundle(&test_instance);
-
- // Classify
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- var all_sims: [NUM_CLASSES]f64 = undefined;
- for (0..NUM_CLASSES) |p| {
- const sim = test_query.similarity(&prototypes[p]);
- all_sims[p] = sim;
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
-
- std.debug.print("\n--- Classification ---\n", .{});
- for (0..NUM_CLASSES) |p| {
- std.debug.print(" sim(query, {s}): {d:.4}{s}\n", .{
- class_names[p],
- all_sims[p],
- if (p == best_class) " β PREDICTED" else "",
- });
- }
- std.debug.print("Correct: {}\n", .{best_class == 0});
-
- // Attribution: unbind query from correct prototype β should show class concept signal
- std.debug.print("\n--- Attribution Analysis ---\n", .{});
- var attribution = test_query.unbind(&prototypes[0]);
-
- // Check similarity of attribution to concept and instance vectors
- const attr_to_concept = attribution.similarity(&concepts[0]);
- const attr_to_instance = attribution.similarity(&test_instance);
- const attr_to_role = attribution.similarity(&role_class);
- std.debug.print(" attribution ~ mammal_concept: {d:.4}\n", .{attr_to_concept});
- std.debug.print(" attribution ~ test_instance: {d:.4}\n", .{attr_to_instance});
- std.debug.print(" attribution ~ role_class: {d:.4}\n", .{attr_to_role});
-
- // Check attribution against wrong concepts
- const attr_to_wrong1 = attribution.similarity(&concepts[1]);
- const attr_to_wrong2 = attribution.similarity(&concepts[2]);
- std.debug.print(" attribution ~ bird_concept: {d:.4} (wrong class)\n", .{attr_to_wrong1});
- std.debug.print(" attribution ~ fish_concept: {d:.4} (wrong class)\n", .{attr_to_wrong2});
-
- // Check similarity of test query to each training example (which ones contributed?)
- std.debug.print("\n--- Training Example Contributions ---\n", .{});
- for (0..NUM_CLASSES) |c| {
- var max_contrib: f64 = -2.0;
- var avg_contrib: f64 = 0;
- for (0..SHOTS) |s| {
- const sim = test_query.similarity(&train_examples[c][s]);
- avg_contrib += sim;
- if (sim > max_contrib) max_contrib = sim;
- }
- avg_contrib /= @as(f64, @floatFromInt(SHOTS));
- std.debug.print(" {s}: avg={d:.4}, max={d:.4}\n", .{ class_names[c], avg_contrib, max_contrib });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(best_class == 0); // correct classification
- // Attribution to correct concept should be higher than to wrong concepts
- // (may not hold perfectly with bundle noise, so check the classification is right)
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 64: Hard Few-Shot β Overlapping Class Features (Level 11.4)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "hard few-shot overlapping classes" {
- const DIM = 1024;
- const NUM_FEATURES = 8;
- const NUM_CLASSES = 5;
- const NUM_TEST = 8; // more test items for statistics
-
- // Shared feature vectors (bipolar building blocks)
- var features: [NUM_FEATURES]Hypervector = undefined;
- for (0..NUM_FEATURES) |i| {
- features[i] = bipolarRandom(DIM, 0x1A00 + @as(u64, @intCast(i)));
- }
-
- // Classes defined by 3 features each β WITH OVERLAP
- // Class 0 (cat-like): features 0, 1, 2
- // Class 1 (dog-like): features 0, 1, 3 β shares 0,1 with class 0!
- // Class 2 (bird-like): features 2, 4, 5 β shares 2 with class 0
- // Class 3 (fish-like): features 4, 5, 6 β shares 4,5 with class 2!
- // Class 4 (insect-like): features 6, 7, 3 β shares 6 with class 3, 3 with class 1
- const class_features = [5][3]usize{
- .{ 0, 1, 2 }, // cat
- .{ 0, 1, 3 }, // dog β 2/3 overlap with cat
- .{ 2, 4, 5 }, // bird β 1/3 overlap with cat
- .{ 4, 5, 6 }, // fish β 2/3 overlap with bird
- .{ 6, 7, 3 }, // insect β 1/3 overlap with fish, 1/3 with dog
- };
- const class_labels = [_][]const u8{ "cat", "dog", "bird", "fish", "insect" };
-
- // Build class concept vectors: bundle of 3 feature vectors
- var class_concepts: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var f0 = features[class_features[c][0]];
- var f1 = features[class_features[c][1]];
- class_concepts[c] = f0.bundle(&f1);
- var f2 = features[class_features[c][2]];
- class_concepts[c] = class_concepts[c].bundle(&f2);
- }
-
- // Show inter-class similarity (reveals overlap)
- std.debug.print("\n=== HARD FEW-SHOT: OVERLAPPING CLASSES (Level 11.4) ===\n", .{});
- std.debug.print("Dimension: {}, Features: {}, Classes: {}\n", .{ DIM, NUM_FEATURES, NUM_CLASSES });
- std.debug.print("\n--- Class Concept Similarity Matrix ---\n", .{});
- std.debug.print(" ", .{});
- for (0..NUM_CLASSES) |c| {
- std.debug.print("{s:>8}", .{class_labels[c]});
- }
- std.debug.print("\n", .{});
- for (0..NUM_CLASSES) |i| {
- std.debug.print("{s:>8} ", .{class_labels[i]});
- for (0..NUM_CLASSES) |j| {
- const sim = class_concepts[i].similarity(&class_concepts[j]);
- std.debug.print("{d:>7.3} ", .{sim});
- }
- std.debug.print("\n", .{});
- }
-
- // Generate examples: bundle(class_concept, noise1, noise2, noise3)
- // 4 components in the bundle β class signal is ~25% of the vector
- const MAX_SHOTS = 20;
- const NOISE_COUNT = 3; // number of noise vectors bundled with concept
- var train_examples: [NUM_CLASSES][MAX_SHOTS]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- for (0..MAX_SHOTS) |s| {
- train_examples[c][s] = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x2A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(s)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- train_examples[c][s] = train_examples[c][s].bundle(&noise);
- }
- }
- }
-
- // Generate test examples (same structure, different noise)
- var test_examples: [NUM_CLASSES][NUM_TEST]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- test_examples[c][t] = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x3A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(t)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- test_examples[c][t] = test_examples[c][t].bundle(&noise);
- }
- }
- }
-
- // Test at different shot counts
- const shot_counts = [_]usize{ 1, 3, 5, 10, 20 };
- var shot_results: [5]f64 = undefined;
-
- for (0..shot_counts.len) |si| {
- const k = shot_counts[si];
-
- // Build prototypes
- var prototypes: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- prototypes[c] = train_examples[c][0];
- for (1..k) |s| {
- prototypes[c] = prototypes[c].bundle(&train_examples[c][s]);
- }
- }
-
- // Classify
- var correct: usize = 0;
- var total: usize = 0;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_examples[c][t].similarity(&prototypes[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- if (best_class == c) correct += 1;
- total += 1;
- }
- }
- const acc = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total));
- shot_results[si] = acc;
- std.debug.print("\n--- {}-Shot (hard) ---\n", .{k});
- std.debug.print(" Accuracy: {}/{} ({d:.1}%)\n", .{ correct, total, acc * 100 });
- }
-
- // Print accuracy curve
- std.debug.print("\n--- Hard Accuracy Curve ---\n", .{});
- for (0..shot_counts.len) |si| {
- std.debug.print(" {}-shot: {d:.1}%\n", .{ shot_counts[si], shot_results[si] * 100 });
- }
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(shot_results[0] > 0.25); // 1-shot: better than random (20%)
- try std.testing.expect(shot_results[4] >= shot_results[0]); // more shots helps
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 65: Noise-Scaling Difficulty Curve (Level 11.4)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "noise scaling difficulty curve" {
- const DIM = 1024;
- const NUM_FEATURES = 8;
- const NUM_CLASSES = 5;
- const SHOTS = 5;
- const NUM_TEST = 8;
-
- // Same feature/class structure as Test 64
- var features: [NUM_FEATURES]Hypervector = undefined;
- for (0..NUM_FEATURES) |i| {
- features[i] = bipolarRandom(DIM, 0x4A00 + @as(u64, @intCast(i)));
- }
- const class_features = [5][3]usize{
- .{ 0, 1, 2 },
- .{ 0, 1, 3 },
- .{ 2, 4, 5 },
- .{ 4, 5, 6 },
- .{ 6, 7, 3 },
- };
- var class_concepts: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var f0 = features[class_features[c][0]];
- var f1 = features[class_features[c][1]];
- class_concepts[c] = f0.bundle(&f1);
- var f2 = features[class_features[c][2]];
- class_concepts[c] = class_concepts[c].bundle(&f2);
- }
-
- std.debug.print("\n=== NOISE-SCALING DIFFICULTY (Level 11.4) ===\n", .{});
- std.debug.print("Dimension: {}, Classes: {}, Shots: {}\n", .{ DIM, NUM_CLASSES, SHOTS });
-
- // Vary noise count from 0 (easy) to 6 (very hard)
- const noise_levels = [_]usize{ 0, 1, 2, 3, 4, 5, 6 };
- var noise_results: [7]f64 = undefined;
-
- for (0..noise_levels.len) |ni| {
- const noise_count = noise_levels[ni];
-
- // Build training examples
- var prototypes: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- // First example
- var ex = class_concepts[c];
- for (0..noise_count) |n| {
- const seed = 0x5A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- ex = ex.bundle(&noise);
- }
- prototypes[c] = ex;
- // Remaining shots
- for (1..SHOTS) |s| {
- var ex2 = class_concepts[c];
- for (0..noise_count) |n| {
- const seed = 0x5A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(s)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- ex2 = ex2.bundle(&noise);
- }
- prototypes[c] = prototypes[c].bundle(&ex2);
- }
- }
-
- // Classify test examples
- var correct: usize = 0;
- var total: usize = 0;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- var test_item = class_concepts[c];
- for (0..noise_count) |n| {
- const seed = 0x6A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(t)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- test_item = test_item.bundle(&noise);
- }
-
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_item.similarity(&prototypes[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- if (best_class == c) correct += 1;
- total += 1;
- }
- }
-
- const acc = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total));
- noise_results[ni] = acc;
- }
-
- // Print difficulty curve
- std.debug.print("\n--- Difficulty Curve (5-shot, varying noise) ---\n", .{});
- std.debug.print(" Noise components | Accuracy\n", .{});
- for (0..noise_levels.len) |ni| {
- std.debug.print(" {} noise | {d:.1}%\n", .{ noise_levels[ni], noise_results[ni] * 100 });
- }
-
- // Signal-to-noise analysis
- std.debug.print("\n--- Signal Fraction ---\n", .{});
- for (0..noise_levels.len) |ni| {
- const n = noise_levels[ni];
- const signal_frac = 1.0 / @as(f64, @floatFromInt(n + 1));
- std.debug.print(" {} noise: signal fraction = {d:.1}% of vector\n", .{ n, signal_frac * 100 });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(noise_results[0] > 0.8); // 0 noise: should be high
- try std.testing.expect(noise_results[0] >= noise_results[6]); // more noise = harder
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 66: Confusion Matrix at Hard Setting (Level 11.4)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "confusion matrix hard few-shot" {
- const DIM = 1024;
- const NUM_FEATURES = 8;
- const NUM_CLASSES = 5;
- const SHOTS = 10;
- const NUM_TEST = 10;
- const NOISE_COUNT = 3;
-
- // Same feature/class structure
- var features: [NUM_FEATURES]Hypervector = undefined;
- for (0..NUM_FEATURES) |i| {
- features[i] = bipolarRandom(DIM, 0x7A00 + @as(u64, @intCast(i)));
- }
- const class_features = [5][3]usize{
- .{ 0, 1, 2 },
- .{ 0, 1, 3 },
- .{ 2, 4, 5 },
- .{ 4, 5, 6 },
- .{ 6, 7, 3 },
- };
- const class_labels = [_][]const u8{ "cat", "dog", "bird", "fish", "insect" };
-
- var class_concepts: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var f0 = features[class_features[c][0]];
- var f1 = features[class_features[c][1]];
- class_concepts[c] = f0.bundle(&f1);
- var f2 = features[class_features[c][2]];
- class_concepts[c] = class_concepts[c].bundle(&f2);
- }
-
- // Build prototypes (10-shot with 3 noise components)
- var prototypes: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var ex0 = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x8A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- ex0 = ex0.bundle(&noise);
- }
- prototypes[c] = ex0;
- for (1..SHOTS) |s| {
- var ex = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x8A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(s)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- ex = ex.bundle(&noise);
- }
- prototypes[c] = prototypes[c].bundle(&ex);
- }
- }
-
- // Build confusion matrix
- var confusion: [NUM_CLASSES][NUM_CLASSES]usize = [_][NUM_CLASSES]usize{[_]usize{0} ** NUM_CLASSES} ** NUM_CLASSES;
- var total_correct: usize = 0;
- var total_count: usize = 0;
-
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- var test_item = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x9A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(t)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- test_item = test_item.bundle(&noise);
- }
-
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_item.similarity(&prototypes[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- confusion[c][best_class] += 1;
- if (best_class == c) total_correct += 1;
- total_count += 1;
- }
- }
-
- const total_acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_count));
-
- std.debug.print("\n=== CONFUSION MATRIX β HARD FEW-SHOT (Level 11.4) ===\n", .{});
- std.debug.print("10-shot, 3 noise components, 10 test per class\n\n", .{});
-
- // Print confusion matrix
- std.debug.print("Predicted β\n", .{});
- std.debug.print("True β ", .{});
- for (0..NUM_CLASSES) |c| {
- std.debug.print("{s:>8}", .{class_labels[c]});
- }
- std.debug.print(" | Recall\n", .{});
- std.debug.print("---------", .{});
- for (0..NUM_CLASSES) |_| {
- std.debug.print("--------", .{});
- }
- std.debug.print("--+-------\n", .{});
-
- for (0..NUM_CLASSES) |i| {
- std.debug.print("{s:>8} ", .{class_labels[i]});
- var row_total: usize = 0;
- for (0..NUM_CLASSES) |j| {
- std.debug.print("{:>8}", .{confusion[i][j]});
- row_total += confusion[i][j];
- }
- const recall = if (row_total > 0) @as(f64, @floatFromInt(confusion[i][i])) / @as(f64, @floatFromInt(row_total)) else 0.0;
- std.debug.print(" | {d:.0}%\n", .{recall * 100});
- }
-
- // Per-class precision
- std.debug.print("Prec. ", .{});
- for (0..NUM_CLASSES) |j| {
- var col_total: usize = 0;
- for (0..NUM_CLASSES) |i| {
- col_total += confusion[i][j];
- }
- const prec = if (col_total > 0) @as(f64, @floatFromInt(confusion[j][j])) / @as(f64, @floatFromInt(col_total)) else 0.0;
- std.debug.print("{d:>7.0}%", .{prec * 100});
- }
- std.debug.print("\n", .{});
-
- // Overlap analysis
- std.debug.print("\n--- Overlap Analysis ---\n", .{});
- std.debug.print("cat-dog share features 0,1 (2/3): confusion = {}\n", .{confusion[0][1] + confusion[1][0]});
- std.debug.print("bird-fish share features 4,5 (2/3): confusion = {}\n", .{confusion[2][3] + confusion[3][2]});
- std.debug.print("cat-bird share feature 2 (1/3): confusion = {}\n", .{confusion[0][2] + confusion[2][0]});
-
- std.debug.print("\nOverall accuracy: {}/{} ({d:.1}%)\n", .{ total_correct, total_count, total_acc * 100 });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(total_acc > 0.3); // better than random (20%)
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TREE BUNDLING HELPER (Level 11.5)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Tree-structured bundling: pair items, then pair pairs, etc.
-/// All items get equal weight in the final vector.
-/// For odd count, the last item carries forward to the next level.
-/// Works IN-PLACE on the input slice to avoid stack overflow.
-fn treeBundleN(items: []Hypervector) Hypervector {
- if (items.len == 0) unreachable;
- if (items.len == 1) return items[0];
- if (items.len == 2) return items[0].bundle(&items[1]);
-
- // Work in-place: pair items[0..n] β write results into items[0..n/2+1]
- var count = items.len;
- while (count > 1) {
- var write: usize = 0;
- var read: usize = 0;
- while (read + 1 < count) : (read += 2) {
- items[write] = items[read].bundle(&items[read + 1]);
- write += 1;
- }
- // Carry forward odd item
- if (read < count) {
- items[write] = items[read];
- write += 1;
- }
- count = write;
- }
-
- return items[0];
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 67: Tree vs Flat Bundling β Hard Benchmark (Level 11.5)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "tree vs flat bundling hard benchmark" {
- const DIM = 1024;
- const NUM_FEATURES = 8;
- const NUM_CLASSES = 5;
- const NUM_TEST = 8;
- const NOISE_COUNT = 3;
- const MAX_SHOTS = 20;
-
- // Same overlapping feature structure as Level 11.4
- var features: [NUM_FEATURES]Hypervector = undefined;
- for (0..NUM_FEATURES) |i| {
- features[i] = bipolarRandom(DIM, 0x1A00 + @as(u64, @intCast(i)));
- }
- const class_features = [5][3]usize{
- .{ 0, 1, 2 }, // cat
- .{ 0, 1, 3 }, // dog
- .{ 2, 4, 5 }, // bird
- .{ 4, 5, 6 }, // fish
- .{ 6, 7, 3 }, // insect
- };
-
- var class_concepts: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var f0 = features[class_features[c][0]];
- var f1 = features[class_features[c][1]];
- class_concepts[c] = f0.bundle(&f1);
- var f2 = features[class_features[c][2]];
- class_concepts[c] = class_concepts[c].bundle(&f2);
- }
-
- // Generate training and test examples (same seeds as Test 64 for comparability)
- var train_examples: [NUM_CLASSES][MAX_SHOTS]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- for (0..MAX_SHOTS) |s| {
- train_examples[c][s] = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x2A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(s)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- train_examples[c][s] = train_examples[c][s].bundle(&noise);
- }
- }
- }
-
- var test_examples: [NUM_CLASSES][NUM_TEST]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- test_examples[c][t] = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x3A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(t)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- test_examples[c][t] = test_examples[c][t].bundle(&noise);
- }
- }
- }
-
- std.debug.print("\n=== TREE vs FLAT BUNDLING (Level 11.5) ===\n", .{});
- std.debug.print("Dimension: {}, Classes: {}, Noise: {}\n", .{ DIM, NUM_CLASSES, NOISE_COUNT });
-
- const shot_counts = [_]usize{ 1, 3, 5, 10, 20 };
- var flat_results: [5]f64 = undefined;
- var tree_results: [5]f64 = undefined;
-
- for (0..shot_counts.len) |si| {
- const k = shot_counts[si];
-
- // --- Flat bundling (progressive) ---
- var flat_protos: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- flat_protos[c] = train_examples[c][0];
- for (1..k) |s| {
- flat_protos[c] = flat_protos[c].bundle(&train_examples[c][s]);
- }
- }
-
- var flat_correct: usize = 0;
- var flat_total: usize = 0;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_examples[c][t].similarity(&flat_protos[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- if (best_class == c) flat_correct += 1;
- flat_total += 1;
- }
- }
- flat_results[si] = @as(f64, @floatFromInt(flat_correct)) / @as(f64, @floatFromInt(flat_total));
-
- // --- Tree bundling (hierarchical) ---
- var tree_protos: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var slice: [MAX_SHOTS]Hypervector = undefined;
- for (0..k) |s| {
- slice[s] = train_examples[c][s];
- }
- tree_protos[c] = treeBundleN(slice[0..k]);
- }
-
- var tree_correct: usize = 0;
- var tree_total: usize = 0;
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- var best_class: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_examples[c][t].similarity(&tree_protos[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_class = p;
- }
- }
- if (best_class == c) tree_correct += 1;
- tree_total += 1;
- }
- }
- tree_results[si] = @as(f64, @floatFromInt(tree_correct)) / @as(f64, @floatFromInt(tree_total));
- }
-
- // Print comparison
- std.debug.print("\n--- Accuracy Comparison ---\n", .{});
- std.debug.print(" Shots | Flat | Tree | Winner\n", .{});
- std.debug.print(" ------|---------|---------|-------\n", .{});
- for (0..shot_counts.len) |si| {
- const winner = if (tree_results[si] > flat_results[si]) "Tree" else if (flat_results[si] > tree_results[si]) "Flat" else "Tie";
- std.debug.print(" {:>5} | {d:>5.1}% | {d:>5.1}% | {s}\n", .{
- shot_counts[si],
- flat_results[si] * 100,
- tree_results[si] * 100,
- winner,
- });
- }
-
- // Check monotonicity of tree results
- var tree_monotonic = true;
- for (1..shot_counts.len) |si| {
- if (tree_results[si] < tree_results[si - 1] - 0.05) { // allow 5% noise
- tree_monotonic = false;
- }
- }
- var flat_monotonic = true;
- for (1..shot_counts.len) |si| {
- if (flat_results[si] < flat_results[si - 1] - 0.05) {
- flat_monotonic = false;
- }
- }
- std.debug.print("\nFlat monotonic: {}\n", .{flat_monotonic});
- std.debug.print("Tree monotonic: {}\n", .{tree_monotonic});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(tree_results[4] > 0.25); // 20-shot tree: better than random
- try std.testing.expect(flat_results[0] > 0.2); // 1-shot: better than random
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 68: Prototype Weight Analysis β Tree vs Flat (Level 11.5)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "prototype weight analysis tree vs flat" {
- const DIM = 1024;
- const NUM_ITEMS = 8;
-
- // Create 8 bipolar vectors
- var items: [NUM_ITEMS]Hypervector = undefined;
- for (0..NUM_ITEMS) |i| {
- items[i] = bipolarRandom(DIM, 0xEE00 + @as(u64, @intCast(i)));
- }
-
- // Flat bundling: progressive
- var flat_proto = items[0];
- for (1..NUM_ITEMS) |i| {
- flat_proto = flat_proto.bundle(&items[i]);
- }
-
- // Tree bundling
- var tree_items: [NUM_ITEMS]Hypervector = undefined;
- for (0..NUM_ITEMS) |i| {
- tree_items[i] = items[i];
- }
- var tree_proto = treeBundleN(tree_items[0..NUM_ITEMS]);
-
- std.debug.print("\n=== PROTOTYPE WEIGHT ANALYSIS (Level 11.5) ===\n", .{});
- std.debug.print("Items: {}, Dim: {}\n", .{ NUM_ITEMS, DIM });
-
- // Measure each item's contribution (similarity to prototype)
- std.debug.print("\n--- Per-Item Similarity to Prototype ---\n", .{});
- std.debug.print(" Item | Flat sim | Tree sim | Flat/Tree\n", .{});
- std.debug.print(" -----|-----------|-----------|----------\n", .{});
-
- var flat_total_sim: f64 = 0;
- var flat_min_sim: f64 = 2.0;
- var flat_max_sim: f64 = -2.0;
- var tree_total_sim: f64 = 0;
- var tree_min_sim: f64 = 2.0;
- var tree_max_sim: f64 = -2.0;
-
- for (0..NUM_ITEMS) |i| {
- const flat_sim = items[i].similarity(&flat_proto);
- const tree_sim = items[i].similarity(&tree_proto);
- flat_total_sim += flat_sim;
- tree_total_sim += tree_sim;
- if (flat_sim < flat_min_sim) flat_min_sim = flat_sim;
- if (flat_sim > flat_max_sim) flat_max_sim = flat_sim;
- if (tree_sim < tree_min_sim) tree_min_sim = tree_sim;
- if (tree_sim > tree_max_sim) tree_max_sim = tree_sim;
- const ratio = if (@abs(tree_sim) > 0.001) flat_sim / tree_sim else 0.0;
- std.debug.print(" {:>4} | {d:>8.4} | {d:>8.4} | {d:>7.2}x\n", .{ i, flat_sim, tree_sim, ratio });
- }
-
- const flat_avg = flat_total_sim / @as(f64, @floatFromInt(NUM_ITEMS));
- const tree_avg = tree_total_sim / @as(f64, @floatFromInt(NUM_ITEMS));
- const flat_range = flat_max_sim - flat_min_sim;
- const tree_range = tree_max_sim - tree_min_sim;
-
- std.debug.print("\n--- Summary ---\n", .{});
- std.debug.print("Flat: avg={d:.4}, min={d:.4}, max={d:.4}, range={d:.4}\n", .{ flat_avg, flat_min_sim, flat_max_sim, flat_range });
- std.debug.print("Tree: avg={d:.4}, min={d:.4}, max={d:.4}, range={d:.4}\n", .{ tree_avg, tree_min_sim, tree_max_sim, tree_range });
- std.debug.print("Tree range/Flat range: {d:.2}x\n", .{if (flat_range > 0.001) tree_range / flat_range else 0.0});
- std.debug.print("============================================\n", .{});
-
- // Assertions: tree should have more uniform weights (smaller range)
- try std.testing.expect(tree_range <= flat_range + 0.05); // tree at least as uniform (with tolerance)
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 69: Tree Bundling Confusion Matrix β Hard Setting (Level 11.5)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "tree bundling confusion matrix hard" {
- const DIM = 1024;
- const NUM_FEATURES = 8;
- const NUM_CLASSES = 5;
- const SHOTS = 10;
- const NUM_TEST = 10;
- const NOISE_COUNT = 3;
-
- var features: [NUM_FEATURES]Hypervector = undefined;
- for (0..NUM_FEATURES) |i| {
- features[i] = bipolarRandom(DIM, 0x7A00 + @as(u64, @intCast(i)));
- }
- const class_features = [5][3]usize{
- .{ 0, 1, 2 },
- .{ 0, 1, 3 },
- .{ 2, 4, 5 },
- .{ 4, 5, 6 },
- .{ 6, 7, 3 },
- };
- const class_labels = [_][]const u8{ "cat", "dog", "bird", "fish", "insect" };
-
- var class_concepts: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var f0 = features[class_features[c][0]];
- var f1 = features[class_features[c][1]];
- class_concepts[c] = f0.bundle(&f1);
- var f2 = features[class_features[c][2]];
- class_concepts[c] = class_concepts[c].bundle(&f2);
- }
-
- // Build tree-bundled prototypes (same seeds as Test 66 for comparability)
- var tree_protos: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var examples: [10]Hypervector = undefined; // SHOTS=10
- for (0..SHOTS) |s| {
- examples[s] = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x8A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(s)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- examples[s] = examples[s].bundle(&noise);
- }
- }
- tree_protos[c] = treeBundleN(examples[0..SHOTS]);
- }
-
- // Also build flat prototypes for comparison (same seeds)
- var flat_protos: [NUM_CLASSES]Hypervector = undefined;
- for (0..NUM_CLASSES) |c| {
- var ex0 = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x8A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- ex0 = ex0.bundle(&noise);
- }
- flat_protos[c] = ex0;
- for (1..SHOTS) |s| {
- var ex = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x8A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(s)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- ex = ex.bundle(&noise);
- }
- flat_protos[c] = flat_protos[c].bundle(&ex);
- }
- }
-
- // Generate test items (same seeds as Test 66)
- // Build confusion matrices for both
- var tree_confusion: [NUM_CLASSES][NUM_CLASSES]usize = [_][NUM_CLASSES]usize{[_]usize{0} ** NUM_CLASSES} ** NUM_CLASSES;
- var flat_confusion: [NUM_CLASSES][NUM_CLASSES]usize = [_][NUM_CLASSES]usize{[_]usize{0} ** NUM_CLASSES} ** NUM_CLASSES;
- var tree_correct: usize = 0;
- var flat_correct: usize = 0;
- var total_count: usize = 0;
-
- for (0..NUM_CLASSES) |c| {
- for (0..NUM_TEST) |t| {
- var test_item = class_concepts[c];
- for (0..NOISE_COUNT) |n| {
- const seed = 0x9A00 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(t)) * 10 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- test_item = test_item.bundle(&noise);
- }
-
- // Tree classification
- var tree_best: usize = 0;
- var tree_best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_item.similarity(&tree_protos[p]);
- if (sim > tree_best_sim) {
- tree_best_sim = sim;
- tree_best = p;
- }
- }
- tree_confusion[c][tree_best] += 1;
- if (tree_best == c) tree_correct += 1;
-
- // Flat classification
- var flat_best: usize = 0;
- var flat_best_sim: f64 = -2.0;
- for (0..NUM_CLASSES) |p| {
- const sim = test_item.similarity(&flat_protos[p]);
- if (sim > flat_best_sim) {
- flat_best_sim = sim;
- flat_best = p;
- }
- }
- flat_confusion[c][flat_best] += 1;
- if (flat_best == c) flat_correct += 1;
-
- total_count += 1;
- }
- }
-
- const tree_acc = @as(f64, @floatFromInt(tree_correct)) / @as(f64, @floatFromInt(total_count));
- const flat_acc = @as(f64, @floatFromInt(flat_correct)) / @as(f64, @floatFromInt(total_count));
-
- std.debug.print("\n=== TREE BUNDLING CONFUSION MATRIX (Level 11.5) ===\n", .{});
- std.debug.print("10-shot, 3 noise, Tree vs Flat\n\n", .{});
-
- // Print tree confusion matrix
- std.debug.print("--- Tree Bundling ---\n", .{});
- std.debug.print("True β ", .{});
- for (0..NUM_CLASSES) |c| {
- std.debug.print("{s:>8}", .{class_labels[c]});
- }
- std.debug.print(" | Recall\n", .{});
- for (0..NUM_CLASSES) |i| {
- std.debug.print("{s:>8} ", .{class_labels[i]});
- var row_total: usize = 0;
- for (0..NUM_CLASSES) |j| {
- std.debug.print("{:>8}", .{tree_confusion[i][j]});
- row_total += tree_confusion[i][j];
- }
- const recall = @as(f64, @floatFromInt(tree_confusion[i][i])) / @as(f64, @floatFromInt(row_total));
- std.debug.print(" | {d:.0}%\n", .{recall * 100});
- }
-
- // Print flat confusion matrix
- std.debug.print("\n--- Flat Bundling ---\n", .{});
- std.debug.print("True β ", .{});
- for (0..NUM_CLASSES) |c| {
- std.debug.print("{s:>8}", .{class_labels[c]});
- }
- std.debug.print(" | Recall\n", .{});
- for (0..NUM_CLASSES) |i| {
- std.debug.print("{s:>8} ", .{class_labels[i]});
- var row_total: usize = 0;
- for (0..NUM_CLASSES) |j| {
- std.debug.print("{:>8}", .{flat_confusion[i][j]});
- row_total += flat_confusion[i][j];
- }
- const recall = @as(f64, @floatFromInt(flat_confusion[i][i])) / @as(f64, @floatFromInt(row_total));
- std.debug.print(" | {d:.0}%\n", .{recall * 100});
- }
-
- std.debug.print("\nTree overall: {}/{} ({d:.1}%)\n", .{ tree_correct, total_count, tree_acc * 100 });
- std.debug.print("Flat overall: {}/{} ({d:.1}%)\n", .{ flat_correct, total_count, flat_acc * 100 });
- const winner = if (tree_acc > flat_acc) "Tree" else if (flat_acc > tree_acc) "Flat" else "Tie";
- std.debug.print("Winner: {s}\n", .{winner});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(tree_acc > 0.25); // better than random
- try std.testing.expect(flat_acc > 0.25); // better than random
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 70: 1000+ Shared-Relation Analogies Benchmark (Level 11.6)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "1000+ shared-relation analogies benchmark" {
- const DIM = 1024;
- // Each relation R is a bipolar random vector. B_i = bind(R, A_i).
- // Extracting: R' = bind(B_j, A_j) = R (exact for bipolar self-inverse).
- // 10 relations Γ 12 pairs Γ (5 exemplar counts + 5 noise levels) = 1200 queries
- const NUM_RELATIONS = 10;
- const PAIRS_PER_REL = 12;
-
- // Phase 1: Clean analogies β vary exemplar count
- const exemplar_counts = [_]usize{ 1, 3, 5, 9, 11 };
- var correct_by_exemplar: [5]usize = [_]usize{0} ** 5;
- var queries_by_exemplar: [5]usize = [_]usize{0} ** 5;
-
- // Phase 2: Noisy analogies β noise added to extracted relation
- const noise_levels = [_]usize{ 0, 1, 2, 3, 5 };
- var correct_by_noise: [5]usize = [_]usize{0} ** 5;
- var queries_by_noise: [5]usize = [_]usize{0} ** 5;
-
- var total_correct: usize = 0;
- var total_queries: usize = 0;
- var per_rel_correct: [NUM_RELATIONS]usize = [_]usize{0} ** NUM_RELATIONS;
-
- std.debug.print("\n=== 1000+ SHARED-RELATION ANALOGIES (Level 11.6) ===\n", .{});
- std.debug.print("Relations: {}, Pairs/rel: {}, Dim: {}\n", .{ NUM_RELATIONS, PAIRS_PER_REL, DIM });
-
- for (0..NUM_RELATIONS) |r| {
- // Create shared relation vector for this relation
- var relation = bipolarRandom(DIM, 0xF000 + @as(u64, @intCast(r)) * 9973);
-
- // Create A words, B = bind(R, A)
- var a_words: [PAIRS_PER_REL]Hypervector = undefined;
- var b_words: [PAIRS_PER_REL]Hypervector = undefined;
- for (0..PAIRS_PER_REL) |i| {
- a_words[i] = bipolarRandom(DIM, 0xA000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 6271);
- b_words[i] = relation.bind(&a_words[i]);
- }
-
- // Phase 1: Clean analogies
- for (exemplar_counts, 0..) |num_exemplars, ex_idx| {
- for (0..PAIRS_PER_REL) |q| {
- var rel_vectors: [11]Hypervector = undefined;
- var rel_count: usize = 0;
- for (0..PAIRS_PER_REL) |p| {
- if (p == q) continue;
- if (rel_count >= num_exemplars) break;
- // R' = bind(B_p, A_p) = bind(bind(R,A_p), A_p) = R (bipolar exact)
- rel_vectors[rel_count] = b_words[p].bind(&a_words[p]);
- rel_count += 1;
- }
-
- var rel_proto: Hypervector = undefined;
- if (rel_count == 1) {
- rel_proto = rel_vectors[0];
- } else {
- rel_proto = treeBundleN(rel_vectors[0..rel_count]);
- }
-
- var predicted = rel_proto.bind(&a_words[q]);
-
- var best_idx: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..PAIRS_PER_REL) |p| {
- const sim = predicted.similarity(&b_words[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = p;
- }
- }
-
- if (best_idx == q) {
- total_correct += 1;
- correct_by_exemplar[ex_idx] += 1;
- if (ex_idx == exemplar_counts.len - 1) per_rel_correct[r] += 1;
- }
- total_queries += 1;
- queries_by_exemplar[ex_idx] += 1;
- }
- }
-
- // Phase 2: Noisy analogies β 1 exemplar with progressive noise
- for (noise_levels, 0..) |noise_count, n_idx| {
- for (0..PAIRS_PER_REL) |q| {
- const exemplar = if (q == 0) @as(usize, 1) else @as(usize, 0);
- var extracted_rel = b_words[exemplar].bind(&a_words[exemplar]);
-
- // Add noise: progressive bundle with random vectors
- for (0..noise_count) |n| {
- const seed = 0xE000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(q)) * 100 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- extracted_rel = extracted_rel.bundle(&noise);
- }
-
- var predicted = extracted_rel.bind(&a_words[q]);
-
- var best_idx: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..PAIRS_PER_REL) |p| {
- const sim = predicted.similarity(&b_words[p]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = p;
- }
- }
-
- if (best_idx == q) {
- total_correct += 1;
- correct_by_noise[n_idx] += 1;
- }
- total_queries += 1;
- queries_by_noise[n_idx] += 1;
- }
- }
- }
-
- // Print results
- std.debug.print("\n--- Phase 1: Clean Analogies by Exemplar Count ---\n", .{});
- std.debug.print("Exemplars | Correct | Total | Accuracy\n", .{});
- std.debug.print("----------|---------|-------|--------\n", .{});
- for (exemplar_counts, 0..) |ne, idx| {
- const acc = @as(f64, @floatFromInt(correct_by_exemplar[idx])) / @as(f64, @floatFromInt(queries_by_exemplar[idx]));
- std.debug.print(" {:>5} | {:>7} | {:>5} | {d:.1}%\n", .{ ne, correct_by_exemplar[idx], queries_by_exemplar[idx], acc * 100 });
- }
-
- std.debug.print("\n--- Phase 2: Noisy Analogies (1-exemplar + noise) ---\n", .{});
- std.debug.print("Noise | Correct | Total | Accuracy\n", .{});
- std.debug.print("------|---------|-------|--------\n", .{});
- for (noise_levels, 0..) |nl, idx| {
- const acc = @as(f64, @floatFromInt(correct_by_noise[idx])) / @as(f64, @floatFromInt(queries_by_noise[idx]));
- std.debug.print(" {:>1} | {:>7} | {:>5} | {d:.1}%\n", .{ nl, correct_by_noise[idx], queries_by_noise[idx], acc * 100 });
- }
-
- std.debug.print("\n--- Per-Relation Accuracy (11-exemplar, clean) ---\n", .{});
- for (0..NUM_RELATIONS) |r| {
- const per_acc = @as(f64, @floatFromInt(per_rel_correct[r])) / @as(f64, PAIRS_PER_REL);
- std.debug.print(" Relation {:>2}: {}/{} ({d:.1}%)\n", .{ r, per_rel_correct[r], PAIRS_PER_REL, per_acc * 100 });
- }
-
- const overall_acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries));
- std.debug.print("\nTotal: {}/{} ({d:.1}%)\n", .{ total_correct, total_queries, overall_acc * 100 });
- std.debug.print("Total analogy queries: {} (>=1000: {})\n", .{ total_queries, total_queries >= 1000 });
- std.debug.print("============================================\n", .{});
-
- // Must have >=1000 queries
- try std.testing.expect(total_queries >= 1000);
- // Clean 1-exemplar bipolar should be 100% (exact self-inverse)
- const clean_1ex_acc = @as(f64, @floatFromInt(correct_by_exemplar[0])) / @as(f64, @floatFromInt(queries_by_exemplar[0]));
- try std.testing.expect(clean_1ex_acc > 0.95);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 71: Multi-Exemplar Relation Extraction β Tree vs Flat (Level 11.6)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "multi-exemplar relation extraction tree vs flat" {
- const DIM = 1024;
- const NUM_PAIRS = 20;
- const NUM_TEST = 5; // hold out last 5 for testing
-
- // One shared relation: B_i = bind(R, A_i)
- var relation = bipolarRandom(DIM, 0xC000);
- var a_words: [NUM_PAIRS]Hypervector = undefined;
- var b_words: [NUM_PAIRS]Hypervector = undefined;
- for (0..NUM_PAIRS) |i| {
- a_words[i] = bipolarRandom(DIM, 0xC100 + @as(u64, @intCast(i)) * 3571);
- b_words[i] = relation.bind(&a_words[i]);
- }
-
- // Each extracted relation gets 3 noise components (simulating noisy observations)
- const NOISE_PER_REL = 3;
-
- std.debug.print("\n=== MULTI-EXEMPLAR NOISY RELATION: TREE vs FLAT (Level 11.6) ===\n", .{});
- std.debug.print("Pairs: {}, Test: {}, Dim: {}, Noise/rel: {}\n", .{ NUM_PAIRS, NUM_TEST, DIM, NOISE_PER_REL });
-
- std.debug.print("\nExemplars | Tree Acc | Flat Acc | Tree R-sim | Flat R-sim\n", .{});
- std.debug.print("----------|----------|----------|------------|----------\n", .{});
-
- const test_start = NUM_PAIRS - NUM_TEST;
-
- var tree_mono = true;
- var flat_mono = true;
- var prev_tree_acc: f64 = -1;
- var prev_flat_acc: f64 = -1;
-
- const exemplar_set = [_]usize{ 1, 2, 3, 5, 7, 10, 15 };
- for (exemplar_set) |num_ex| {
- // Extract noisy relation vectors
- var rel_vecs: [15]Hypervector = undefined;
- for (0..num_ex) |i| {
- rel_vecs[i] = b_words[i].bind(&a_words[i]); // = R exact
- // Add noise
- for (0..NOISE_PER_REL) |n| {
- const seed = 0xCC00 + @as(u64, @intCast(i)) * 100 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- rel_vecs[i] = rel_vecs[i].bundle(&noise);
- }
- }
-
- // Tree-bundled noisy relation
- var tree_rel: Hypervector = undefined;
- if (num_ex == 1) {
- tree_rel = rel_vecs[0];
- } else {
- var tree_copy: [15]Hypervector = undefined;
- for (0..num_ex) |i| tree_copy[i] = rel_vecs[i];
- tree_rel = treeBundleN(tree_copy[0..num_ex]);
- }
-
- // Flat-bundled noisy relation
- var flat_rel = rel_vecs[0];
- for (1..num_ex) |i| {
- flat_rel = flat_rel.bundle(&rel_vecs[i]);
- }
-
- // Similarity to true relation
- const tree_r_sim = tree_rel.similarity(&relation);
- const flat_r_sim = flat_rel.similarity(&relation);
-
- // Test on held-out pairs
- var tree_correct: usize = 0;
- var flat_correct: usize = 0;
-
- for (test_start..NUM_PAIRS) |t| {
- var tree_pred = tree_rel.bind(&a_words[t]);
- var flat_pred = flat_rel.bind(&a_words[t]);
-
- var tree_best: usize = 0;
- var flat_best: usize = 0;
- var t_best_sim: f64 = -2.0;
- var f_best_sim: f64 = -2.0;
-
- for (0..NUM_PAIRS) |p| {
- const t_sim = tree_pred.similarity(&b_words[p]);
- const f_sim = flat_pred.similarity(&b_words[p]);
- if (t_sim > t_best_sim) {
- t_best_sim = t_sim;
- tree_best = p;
- }
- if (f_sim > f_best_sim) {
- f_best_sim = f_sim;
- flat_best = p;
- }
- }
-
- if (tree_best == t) tree_correct += 1;
- if (flat_best == t) flat_correct += 1;
- }
-
- const tree_acc = @as(f64, @floatFromInt(tree_correct)) / @as(f64, NUM_TEST);
- const flat_acc = @as(f64, @floatFromInt(flat_correct)) / @as(f64, NUM_TEST);
-
- if (prev_tree_acc >= 0 and tree_acc < prev_tree_acc - 0.01) tree_mono = false;
- if (prev_flat_acc >= 0 and flat_acc < prev_flat_acc - 0.01) flat_mono = false;
- prev_tree_acc = tree_acc;
- prev_flat_acc = flat_acc;
-
- std.debug.print(" {:>5} | {d:>7.1}% | {d:>7.1}% | {d:>9.4} | {d:>8.4}\n", .{ num_ex, tree_acc * 100, flat_acc * 100, tree_r_sim, flat_r_sim });
- }
-
- std.debug.print("\nTree monotonic: {}\n", .{tree_mono});
- std.debug.print("Flat monotonic: {}\n", .{flat_mono});
- std.debug.print("============================================\n", .{});
-
- // Tree should work well at 15 exemplars
- try std.testing.expect(prev_tree_acc > 0.5);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 72: Multi-Step Relation Chains (Level 11.6)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "multi-step relation chains analogies" {
- const DIM = 1024;
-
- // Process chains one at a time to avoid stack overflow.
- // For each chain: 5 entities (4 hops max).
- // Test across 50 chains total (processed in batches of 5).
- const CHAINS_PER_BATCH = 5;
- const NUM_BATCHES = 10;
- const MAX_HOPS = 4;
- const ENTITIES_PER_CHAIN = MAX_HOPS + 1; // 5 entities per chain
-
- std.debug.print("\n=== MULTI-STEP RELATION CHAINS (Level 11.6) ===\n", .{});
- std.debug.print("Total chains: {}, Max hops: {}, Dim: {}\n", .{ CHAINS_PER_BATCH * NUM_BATCHES, MAX_HOPS, DIM });
-
- std.debug.print("\n Hops | Correct | Total | Accuracy | Avg Sim\n", .{});
- std.debug.print(" -----|---------|-------|----------|--------\n", .{});
-
- var total_correct: usize = 0;
- var total_queries: usize = 0;
- var hop_correct_all: [MAX_HOPS]usize = [_]usize{0} ** MAX_HOPS;
- var hop_sim_all: [MAX_HOPS]f64 = [_]f64{0} ** MAX_HOPS;
- var hop_queries: [MAX_HOPS]usize = [_]usize{0} ** MAX_HOPS;
-
- for (0..NUM_BATCHES) |batch| {
- // Create entities for this batch
- var entities: [CHAINS_PER_BATCH * ENTITIES_PER_CHAIN]Hypervector = undefined;
- for (0..CHAINS_PER_BATCH * ENTITIES_PER_CHAIN) |i| {
- const seed = 0xD000 + @as(u64, @intCast(batch)) * 50000 + @as(u64, @intCast(i)) * 8191;
- entities[i] = bipolarRandom(DIM, seed);
- }
-
- for (1..MAX_HOPS + 1) |num_hops| {
- for (0..CHAINS_PER_BATCH) |chain| {
- const chain_base = chain * ENTITIES_PER_CHAIN;
-
- // Composite relation: bind(R_0, R_1, ..., R_{num_hops-1})
- var composite = entities[chain_base + 1].bind(&entities[chain_base]);
- for (1..num_hops) |h| {
- var hop_rel = entities[chain_base + h + 1].bind(&entities[chain_base + h]);
- composite = composite.bind(&hop_rel);
- }
-
- // Apply composite to start β should reach entity[num_hops]
- var predicted = composite.bind(&entities[chain_base]);
- const target_idx = chain_base + num_hops;
-
- // Find closest among batch entities
- var best_idx: usize = 0;
- var best_sim: f64 = -2.0;
- for (0..CHAINS_PER_BATCH * ENTITIES_PER_CHAIN) |e| {
- const sim = predicted.similarity(&entities[e]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = e;
- }
- }
-
- const target_sim = predicted.similarity(&entities[target_idx]);
- hop_sim_all[num_hops - 1] += target_sim;
- hop_queries[num_hops - 1] += 1;
-
- if (best_idx == target_idx) {
- hop_correct_all[num_hops - 1] += 1;
- total_correct += 1;
- }
- total_queries += 1;
- }
- }
- }
-
- for (0..MAX_HOPS) |h| {
- const hop_acc = @as(f64, @floatFromInt(hop_correct_all[h])) / @as(f64, @floatFromInt(hop_queries[h]));
- const avg_sim = hop_sim_all[h] / @as(f64, @floatFromInt(hop_queries[h]));
- std.debug.print(" {:>4} | {:>7} | {:>5} | {d:>7.1}% | {d:.4}\n", .{ h + 1, hop_correct_all[h], hop_queries[h], hop_acc * 100, avg_sim });
- }
-
- const overall_acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries));
- std.debug.print("\nOverall: {}/{} ({d:.1}%)\n", .{ total_correct, total_queries, overall_acc * 100 });
- std.debug.print("============================================\n", .{});
-
- // Bipolar chains should be exact (self-inverse)
- try std.testing.expect(overall_acc > 0.9); // very high for bipolar
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 73: Hybrid Bipolar/Ternary Noisy Analogy Comparison (Level 11.7)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "hybrid bipolar ternary noisy analogy comparison" {
- const DIM = 1024;
- const NUM_RELATIONS = 5;
- const PAIRS_PER_REL = 12;
- const noise_levels = [_]usize{ 0, 1, 2, 3, 5 };
-
- var bp_correct_by_noise: [5]usize = [_]usize{0} ** 5;
- var tr_correct_by_noise: [5]usize = [_]usize{0} ** 5;
- var hy_correct_by_noise: [5]usize = [_]usize{0} ** 5;
- var queries_by_noise: [5]usize = [_]usize{0} ** 5;
-
- std.debug.print("\n=== HYBRID BIPOLAR/TERNARY NOISY ANALOGY (Level 11.7) ===\n", .{});
- std.debug.print("Relations: {}, Pairs/rel: {}, Dim: {}\n", .{ NUM_RELATIONS, PAIRS_PER_REL, DIM });
-
- for (0..NUM_RELATIONS) |r| {
- // Create shared relation (bipolar)
- var bp_relation = bipolarRandom(DIM, 0xF700 + @as(u64, @intCast(r)) * 9973);
-
- // Create A words in both encodings
- var bp_a: [PAIRS_PER_REL]Hypervector = undefined;
- var tr_a: [PAIRS_PER_REL]Hypervector = undefined;
- var bp_b: [PAIRS_PER_REL]Hypervector = undefined;
- var tr_b: [PAIRS_PER_REL]Hypervector = undefined;
-
- for (0..PAIRS_PER_REL) |i| {
- const seed = 0xA700 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 6271;
- bp_a[i] = bipolarRandom(DIM, seed);
- tr_a[i] = Hypervector.random(DIM, seed + 0x1000000);
- // B = bind(R, A) for each encoding
- bp_b[i] = bp_relation.bind(&bp_a[i]);
- // For ternary: create a ternary relation and apply
- var tr_relation = Hypervector.random(DIM, 0xF700 + @as(u64, @intCast(r)) * 9973 + 0x2000000);
- tr_b[i] = tr_relation.bind(&tr_a[i]);
- }
-
- for (noise_levels, 0..) |noise_count, n_idx| {
- for (0..PAIRS_PER_REL) |q| {
- const exemplar = if (q == 0) @as(usize, 1) else @as(usize, 0);
-
- // === BIPOLAR: extract relation + add noise ===
- var bp_rel = bp_b[exemplar].bind(&bp_a[exemplar]);
- for (0..noise_count) |n| {
- const seed = 0xBB00 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(q)) * 100 + @as(u64, @intCast(n));
- var noise = bipolarRandom(DIM, seed);
- bp_rel = bp_rel.bundle(&noise);
- }
- var bp_pred = bp_rel.bind(&bp_a[q]);
- var bp_best: usize = 0;
- var bp_bsim: f64 = -2.0;
- for (0..PAIRS_PER_REL) |p| {
- const sim = bp_pred.similarity(&bp_b[p]);
- if (sim > bp_bsim) {
- bp_bsim = sim;
- bp_best = p;
- }
- }
- if (bp_best == q) bp_correct_by_noise[n_idx] += 1;
-
- // === TERNARY: extract relation + add noise ===
- var tr_rel = tr_b[exemplar].bind(&tr_a[exemplar]);
- for (0..noise_count) |n| {
- const seed = 0xCC00 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(q)) * 100 + @as(u64, @intCast(n));
- var noise = Hypervector.random(DIM, seed);
- tr_rel = tr_rel.bundle(&noise);
- }
- var tr_pred = tr_rel.bind(&tr_a[q]);
- var tr_best: usize = 0;
- var tr_bsim: f64 = -2.0;
- for (0..PAIRS_PER_REL) |p| {
- const sim = tr_pred.similarity(&tr_b[p]);
- if (sim > tr_bsim) {
- tr_bsim = sim;
- tr_best = p;
- }
- }
- if (tr_best == q) tr_correct_by_noise[n_idx] += 1;
-
- // === HYBRID: bipolar extraction + ternary noise bundling ===
- // Extract relation in bipolar (exact)
- var hy_rel = bp_b[exemplar].bind(&bp_a[exemplar]); // exact R
- // Add noise in ternary mode (convert to ternary-style noise)
- for (0..noise_count) |n| {
- const seed = 0xDD00 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(q)) * 100 + @as(u64, @intCast(n));
- var noise = Hypervector.random(DIM, seed); // ternary noise
- hy_rel = hy_rel.bundle(&noise);
- }
- var hy_pred = hy_rel.bind(&bp_a[q]);
- var hy_best: usize = 0;
- var hy_bsim: f64 = -2.0;
- for (0..PAIRS_PER_REL) |p| {
- const sim = hy_pred.similarity(&bp_b[p]);
- if (sim > hy_bsim) {
- hy_bsim = sim;
- hy_best = p;
- }
- }
- if (hy_best == q) hy_correct_by_noise[n_idx] += 1;
-
- queries_by_noise[n_idx] += 1;
- }
- }
- }
-
- // Print results
- std.debug.print("\n--- Bipolar vs Ternary vs Hybrid (Noisy Analogies) ---\n", .{});
- std.debug.print("Noise | Bipolar | Ternary | Hybrid | Winner\n", .{});
- std.debug.print("------|---------|---------|---------|-------\n", .{});
- for (noise_levels, 0..) |nl, idx| {
- const total = @as(f64, @floatFromInt(queries_by_noise[idx]));
- const bp_acc = @as(f64, @floatFromInt(bp_correct_by_noise[idx])) / total;
- const tr_acc = @as(f64, @floatFromInt(tr_correct_by_noise[idx])) / total;
- const hy_acc = @as(f64, @floatFromInt(hy_correct_by_noise[idx])) / total;
- const winner = if (hy_acc >= bp_acc and hy_acc >= tr_acc) "Hybrid" else if (bp_acc >= tr_acc) "Bipolar" else "Ternary";
- std.debug.print(" {:>1} | {d:>6.1}% | {d:>6.1}% | {d:>6.1}% | {s}\n", .{ nl, bp_acc * 100, tr_acc * 100, hy_acc * 100, winner });
- }
-
- // Overall totals
- var bp_total: usize = 0;
- var tr_total: usize = 0;
- var hy_total: usize = 0;
- var q_total: usize = 0;
- for (0..5) |i| {
- bp_total += bp_correct_by_noise[i];
- tr_total += tr_correct_by_noise[i];
- hy_total += hy_correct_by_noise[i];
- q_total += queries_by_noise[i];
- }
- std.debug.print("\nOverall: Bipolar {}/{} ({d:.1}%), Ternary {}/{} ({d:.1}%), Hybrid {}/{} ({d:.1}%)\n", .{
- bp_total, q_total, @as(f64, @floatFromInt(bp_total)) / @as(f64, @floatFromInt(q_total)) * 100,
- tr_total, q_total, @as(f64, @floatFromInt(tr_total)) / @as(f64, @floatFromInt(q_total)) * 100,
- hy_total, q_total, @as(f64, @floatFromInt(hy_total)) / @as(f64, @floatFromInt(q_total)) * 100,
- });
- std.debug.print("============================================\n", .{});
-
- // Hybrid should be competitive
- try std.testing.expect(hy_total >= bp_total or hy_total >= tr_total);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 74: Hybrid Chain Composition + Superposition Capacity (Level 11.7)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "hybrid chain composition and superposition capacity" {
- const DIM = 1024;
- const MAX_HOPS = 4;
- const MAX_BUNDLE = 10;
-
- std.debug.print("\n=== HYBRID CHAIN + SUPERPOSITION (Level 11.7) ===\n", .{});
- std.debug.print("Dim: {}, Max hops: {}, Max bundle: {}\n", .{ DIM, MAX_HOPS, MAX_BUNDLE });
-
- // Part A: Bipolar chain composition (should be exact)
- std.debug.print("\n--- Part A: Bipolar Chain Composition ---\n", .{});
- std.debug.print(" Hops | Sim to target | Status\n", .{});
- std.debug.print(" -----|---------------|-------\n", .{});
-
- const NUM_CHAINS = 10;
- for (1..MAX_HOPS + 1) |hops| {
- var sim_sum: f64 = 0;
- var correct: usize = 0;
- for (0..NUM_CHAINS) |chain| {
- // Create chain entities
- var entities: [5]Hypervector = undefined;
- for (0..hops + 1) |i| {
- entities[i] = bipolarRandom(DIM, 0xBB00 + @as(u64, @intCast(chain)) * 1000 + @as(u64, @intCast(i)) * 7919);
- }
- // Compose chain
- var composite = entities[1].bind(&entities[0]);
- for (1..hops) |h| {
- var hop_rel = entities[h + 1].bind(&entities[h]);
- composite = composite.bind(&hop_rel);
- }
- // Apply and check
- var predicted = composite.bind(&entities[0]);
- const sim = predicted.similarity(&entities[hops]);
- sim_sum += sim;
- if (sim > 0.9) correct += 1;
- }
- const avg_sim = sim_sum / @as(f64, NUM_CHAINS);
- std.debug.print(" {:>4} | {d:>12.6} | {}/{}\n", .{ hops, avg_sim, correct, NUM_CHAINS });
- }
-
- // Part B: Ternary superposition capacity
- std.debug.print("\n--- Part B: Ternary Superposition Capacity ---\n", .{});
- std.debug.print(" Bundle | Recall | Avg Sim | Min Sim\n", .{});
- std.debug.print(" -------|--------|---------|--------\n", .{});
-
- for (2..MAX_BUNDLE + 1) |k| {
- var items: [10]Hypervector = undefined;
- for (0..k) |i| {
- items[i] = Hypervector.random(DIM, 0xCC00 + @as(u64, @intCast(i)) * 3571);
- }
- // Tree bundle
- var bundled = treeBundleN(items[0..k]);
- // Check recall
- var recalled: usize = 0;
- var sim_sum: f64 = 0;
- var min_sim: f64 = 2.0;
- for (0..k) |i| {
- // Re-create item (treeBundleN modifies in place)
- var item = Hypervector.random(DIM, 0xCC00 + @as(u64, @intCast(i)) * 3571);
- const sim = bundled.similarity(&item);
- sim_sum += sim;
- if (sim < min_sim) min_sim = sim;
- // Check if this item is the best match among a set of 20 candidates
- var is_best = true;
- for (0..20) |d| {
- if (d < k) continue; // skip items in the bundle
- var distractor = Hypervector.random(DIM, 0xDD00 + @as(u64, @intCast(d)) * 5113);
- if (bundled.similarity(&distractor) >= sim) {
- is_best = false;
- break;
- }
- }
- if (is_best) recalled += 1;
- }
- const recall = @as(f64, @floatFromInt(recalled)) / @as(f64, @floatFromInt(k));
- const avg_sim = sim_sum / @as(f64, @floatFromInt(k));
- std.debug.print(" {:>5} | {d:>5.1}% | {d:>6.4} | {d:>6.4}\n", .{ k, recall * 100, avg_sim, min_sim });
- }
-
- // Part C: Hybrid pipeline β bipolar chains feed into ternary superposition
- std.debug.print("\n--- Part C: Hybrid Pipeline (Chain β Superposition) ---\n", .{});
- // Use bipolar chains to extract 5 facts, bundle them in ternary, query
- const NUM_FACTS = 5;
- var fact_targets: [NUM_FACTS]Hypervector = undefined;
- var chain_results: [NUM_FACTS]Hypervector = undefined;
-
- for (0..NUM_FACTS) |f| {
- // Create a 2-hop bipolar chain: start --R1--> mid --R2--> target
- var start = bipolarRandom(DIM, 0xEE00 + @as(u64, @intCast(f)) * 10000);
- var mid = bipolarRandom(DIM, 0xEE01 + @as(u64, @intCast(f)) * 10000);
- fact_targets[f] = bipolarRandom(DIM, 0xEE02 + @as(u64, @intCast(f)) * 10000);
-
- var r1 = mid.bind(&start);
- var r2 = fact_targets[f].bind(&mid);
- var composite = r1.bind(&r2);
-
- // Apply chain to recover target
- chain_results[f] = composite.bind(&start);
- }
-
- // Bundle all chain results into ternary superposition
- var super_items: [NUM_FACTS]Hypervector = undefined;
- for (0..NUM_FACTS) |i| super_items[i] = chain_results[i];
- var superposition = treeBundleN(super_items[0..NUM_FACTS]);
-
- // Query: is each target recoverable from superposition?
- var hybrid_recalled: usize = 0;
- std.debug.print(" Fact | Chain Sim | Super Sim | Found?\n", .{});
- std.debug.print(" -----|-----------|-----------|-------\n", .{});
- for (0..NUM_FACTS) |f| {
- const chain_sim = chain_results[f].similarity(&fact_targets[f]);
- const super_sim = superposition.similarity(&fact_targets[f]);
- const found = super_sim > 0.1; // above noise floor
- if (found) hybrid_recalled += 1;
- std.debug.print(" {:>4} | {d:>8.4} | {d:>8.4} | {s}\n", .{ f, chain_sim, super_sim, if (found) "YES" else "NO" });
- }
-
- const hybrid_recall = @as(f64, @floatFromInt(hybrid_recalled)) / @as(f64, NUM_FACTS);
- std.debug.print("\nHybrid pipeline: {}/{} facts recalled ({d:.1}%)\n", .{ hybrid_recalled, NUM_FACTS, hybrid_recall * 100 });
- std.debug.print("============================================\n", .{});
-
- // Bipolar chains must be exact, hybrid recall reasonable
- try std.testing.expect(hybrid_recalled >= 3); // at least 3/5 facts
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 75: Bipolar vs Ternary vs Hybrid Head-to-Head Summary (Level 11.7)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "bipolar ternary hybrid head to head summary" {
- const DIM = 1024;
- const NUM = 20;
-
- // Create codebooks
- var bp_syms: [NUM]Hypervector = undefined;
- var tr_syms: [NUM]Hypervector = undefined;
- for (0..NUM) |i| {
- bp_syms[i] = bipolarRandom(DIM, 0xAB00 + @as(u64, @intCast(i)) * 1013);
- tr_syms[i] = Hypervector.random(DIM, 0xAC00 + @as(u64, @intCast(i)) * 1013);
- }
-
- std.debug.print("\n=== BIPOLAR vs TERNARY vs HYBRID HEAD-TO-HEAD (Level 11.7) ===\n", .{});
- std.debug.print("Dim: {}, Codebook: {} symbols\n\n", .{ DIM, NUM });
-
- // Metric 1: Self-inverse (bind/unbind recovery)
- var bp0 = &bp_syms[0];
- const bp1 = &bp_syms[1];
- var bp_bound = bp0.bind(bp1);
- var bp_rec = bp_bound.unbind(bp0);
- const bp_selfinv = bp_rec.similarity(bp1);
-
- var tr0 = &tr_syms[0];
- const tr1 = &tr_syms[1];
- var tr_bound = tr0.bind(tr1);
- var tr_rec = tr_bound.unbind(tr0);
- const tr_selfinv = tr_rec.similarity(tr1);
-
- // Metric 2: Noise tolerance (flip 30% of trits)
- var bp_noisy = bp_syms[5];
- bp_noisy.data.ensureUnpacked();
- var bp_prng = std.Random.DefaultPrng.init(0xBBBB);
- const bp_rand = bp_prng.random();
- const flips = DIM * 30 / 100;
- for (0..flips) |_| {
- const pos = bp_rand.intRangeAtMost(usize, 0, DIM - 1);
- bp_noisy.data.unpacked_cache[pos] = -bp_noisy.data.unpacked_cache[pos];
- bp_noisy.data.dirty = true;
- }
- const bp_noise_sim = bp_noisy.similarity(&bp_syms[5]);
-
- var tr_noisy = tr_syms[5];
- tr_noisy.data.ensureUnpacked();
- var tr_prng = std.Random.DefaultPrng.init(0xCCCC);
- const tr_rand = tr_prng.random();
- for (0..flips) |_| {
- const pos = tr_rand.intRangeAtMost(usize, 0, DIM - 1);
- tr_noisy.data.unpacked_cache[pos] = tr_rand.intRangeAtMost(i8, -1, 1);
- tr_noisy.data.dirty = true;
- }
- const tr_noise_sim = tr_noisy.similarity(&tr_syms[5]);
-
- // Metric 3: Superposition capacity (bundle 5 items, check recall)
- var bp_items: [5]Hypervector = undefined;
- var tr_items: [5]Hypervector = undefined;
- for (0..5) |i| {
- bp_items[i] = bp_syms[i];
- tr_items[i] = tr_syms[i];
- }
- var bp_super = treeBundleN(bp_items[0..5]);
- var tr_super = treeBundleN(tr_items[0..5]);
-
- var bp_super_recall: usize = 0;
- var tr_super_recall: usize = 0;
- for (0..5) |i| {
- // Re-create items (treeBundleN modified in place)
- var bp_item = bipolarRandom(DIM, 0xAB00 + @as(u64, @intCast(i)) * 1013);
- var tr_item = Hypervector.random(DIM, 0xAC00 + @as(u64, @intCast(i)) * 1013);
- const bp_s = bp_super.similarity(&bp_item);
- const tr_s = tr_super.similarity(&tr_item);
- if (bp_s > 0.1) bp_super_recall += 1;
- if (tr_s > 0.1) tr_super_recall += 1;
- }
-
- // Metric 4: Chain depth (3-hop composition)
- var bp_c: [4]Hypervector = undefined;
- for (0..4) |i| bp_c[i] = bipolarRandom(DIM, 0x9900 + @as(u64, @intCast(i)) * 7919);
- var bp_chain = bp_c[1].bind(&bp_c[0]);
- var bp_r2 = bp_c[2].bind(&bp_c[1]);
- bp_chain = bp_chain.bind(&bp_r2);
- var bp_r3 = bp_c[3].bind(&bp_c[2]);
- bp_chain = bp_chain.bind(&bp_r3);
- var bp_chain_pred = bp_chain.bind(&bp_c[0]);
- const bp_chain_sim = bp_chain_pred.similarity(&bp_c[3]);
-
- var tr_c: [4]Hypervector = undefined;
- for (0..4) |i| tr_c[i] = Hypervector.random(DIM, 0x8800 + @as(u64, @intCast(i)) * 7919);
- var tr_chain = tr_c[1].bind(&tr_c[0]);
- var tr_r2 = tr_c[2].bind(&tr_c[1]);
- tr_chain = tr_chain.bind(&tr_r2);
- var tr_r3 = tr_c[3].bind(&tr_c[2]);
- tr_chain = tr_chain.bind(&tr_r3);
- var tr_chain_pred = tr_chain.bind(&tr_c[0]);
- const tr_chain_sim = tr_chain_pred.similarity(&tr_c[3]);
-
- // Print summary table
- std.debug.print("--- Head-to-Head Summary ---\n", .{});
- std.debug.print("| Metric | Bipolar | Ternary | Winner |\n", .{});
- std.debug.print("|---------------------|----------|----------|----------|\n", .{});
-
- const self_winner = if (bp_selfinv > tr_selfinv) "Bipolar" else "Ternary";
- std.debug.print("| Self-inverse sim | {d:>7.4} | {d:>7.4} | {s:>8} |\n", .{ bp_selfinv, tr_selfinv, self_winner });
-
- const noise_winner = if (bp_noise_sim > tr_noise_sim) "Bipolar" else "Ternary";
- std.debug.print("| Noise 30% sim | {d:>7.4} | {d:>7.4} | {s:>8} |\n", .{ bp_noise_sim, tr_noise_sim, noise_winner });
-
- const super_winner = if (bp_super_recall > tr_super_recall) "Bipolar" else if (tr_super_recall > bp_super_recall) "Ternary" else "Tie";
- std.debug.print("| Superposition 5 | {}/5 | {}/5 | {s:>8} |\n", .{ bp_super_recall, tr_super_recall, super_winner });
-
- const chain_winner = if (bp_chain_sim > tr_chain_sim) "Bipolar" else "Ternary";
- std.debug.print("| 3-hop chain sim | {d:>7.4} | {d:>7.4} | {s:>8} |\n", .{ bp_chain_sim, tr_chain_sim, chain_winner });
-
- // Hybrid recommendation
- std.debug.print("\n--- Hybrid Strategy ---\n", .{});
- std.debug.print("Use BIPOLAR for: bind/unbind chains (sim={d:.4})\n", .{bp_selfinv});
- std.debug.print("Use TERNARY for: noisy recall (sim={d:.4} vs {d:.4})\n", .{ tr_noise_sim, bp_noise_sim });
- std.debug.print("Use TERNARY for: superposition ({}/5 vs {}/5)\n", .{ tr_super_recall, bp_super_recall });
- std.debug.print("HYBRID = best of both worlds\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Bipolar should win self-inverse, ternary should win noise
- try std.testing.expect(bp_selfinv > tr_selfinv);
- try std.testing.expect(bp_chain_sim > tr_chain_sim + 0.1);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 76: Large Knowledge Graph β 100+ Triples, Multi-Hop Queries (Level 11.8)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Geography KG: entities β relations β targets using bipolar bind chains.
-// Schema: bind(Subject, Relation) = Object
-// Multi-hop: bind(composite_relation, start) = target
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "large knowledge graph 100 triples multi-hop" {
- const DIM = 1024;
-
- std.debug.print("\n=== LARGE KNOWLEDGE GRAPH: 100+ TRIPLES (Level 11.8) ===\n", .{});
-
- // ---------- ENTITY GENERATION ----------
- // Geography domain: 20 countries, 5 relations each = 100 triples minimum
- // Relations: capital, continent, language, currency, region
- const NUM_COUNTRIES = 20;
- const NUM_RELATIONS = 5;
-
- // Generate entity vectors (bipolar for exact chains)
- // Countries: seeds 0x1000..0x1013
- var countries: [NUM_COUNTRIES]Hypervector = undefined;
- for (0..NUM_COUNTRIES) |i| {
- countries[i] = bipolarRandom(DIM, 0x1000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Relation vectors (5 types)
- var rel_capital = bipolarRandom(DIM, 0x2000);
- var rel_continent = bipolarRandom(DIM, 0x2001);
- var rel_language = bipolarRandom(DIM, 0x2002);
- var rel_currency = bipolarRandom(DIM, 0x2003);
- var rel_region = bipolarRandom(DIM, 0x2004);
- const relations = [_]*Hypervector{ &rel_capital, &rel_continent, &rel_language, &rel_currency, &rel_region };
- const rel_names = [_][]const u8{ "capital", "continent", "language", "currency", "region" };
-
- // Object vectors (unique per triple) β independent entity vectors
- var objects: [NUM_COUNTRIES][NUM_RELATIONS]Hypervector = undefined;
- for (0..NUM_COUNTRIES) |c| {
- for (0..NUM_RELATIONS) |r| {
- objects[c][r] = bipolarRandom(DIM, 0x3000 + @as(u64, @intCast(c)) * 100 + @as(u64, @intCast(r)));
- }
- }
-
- // ---------- BUILD RELATION MEMORIES ----------
- // For each relation type, create a memory that maps subjects β objects.
- // Memory_r = tree_bundle of bind(country_i, object_i_r) for all i.
- // Query: unbind(Memory_r, country_c) β closest to object_c_r.
- // This is the standard VSA associative memory / clean-up memory pattern.
- var rel_memories: [NUM_RELATIONS]Hypervector = undefined;
- for (0..NUM_RELATIONS) |r| {
- var pairs: [NUM_COUNTRIES]Hypervector = undefined;
- for (0..NUM_COUNTRIES) |c| {
- pairs[c] = countries[c].bind(&objects[c][r]);
- }
- rel_memories[r] = treeBundleN(pairs[0..NUM_COUNTRIES]);
- }
-
- const triple_count: usize = NUM_COUNTRIES * NUM_RELATIONS;
- var single_hop_correct: usize = 0;
- var single_hop_total: usize = 0;
-
- std.debug.print("Dim: {}, Countries: {}, Relations: {}\n", .{ DIM, NUM_COUNTRIES, NUM_RELATIONS });
- std.debug.print("Total triples: {}\n\n", .{triple_count});
-
- // ---------- SINGLE-HOP QUERIES ----------
- // Query: Given country C and relation R, find object O
- // Method: unbind(Memory_r, country_c), find closest object in codebook
- std.debug.print("--- Single-Hop Queries ---\n", .{});
- std.debug.print("Relation | Correct | Total | Accuracy\n", .{});
- std.debug.print("------------|---------|-------|--------\n", .{});
-
- for (0..NUM_RELATIONS) |r| {
- var rel_correct: usize = 0;
- for (0..NUM_COUNTRIES) |c| {
- // Query: unbind memory with subject to retrieve object
- var retrieved = rel_memories[r].unbind(&countries[c]);
-
- // Search for closest object among all objects for this relation
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..NUM_COUNTRIES) |j| {
- const sim = retrieved.similarity(&objects[j][r]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == c) rel_correct += 1;
- single_hop_total += 1;
- }
- single_hop_correct += rel_correct;
- std.debug.print("{s:>11} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- rel_names[r], rel_correct, NUM_COUNTRIES,
- @as(f64, @floatFromInt(rel_correct)) / @as(f64, NUM_COUNTRIES) * 100,
- });
- }
-
- std.debug.print("\nSingle-hop total: {}/{} ({d:.1}%)\n", .{
- single_hop_correct, single_hop_total,
- @as(f64, @floatFromInt(single_hop_correct)) / @as(f64, @floatFromInt(single_hop_total)) * 100,
- });
-
- // ---------- MULTI-HOP QUERIES (2-hop, 3-hop, 4-hop) ----------
- // 2-hop: country --capital--> city, then city --continent--> continent_of_city
- // Composite: bind(rel_capital, rel_continent) applied to country = continent
- // 3-hop: country --capital--> city --language--> lang --currency--> curr
- // 4-hop: adds region on top
- std.debug.print("\n--- Multi-Hop Chain Queries ---\n", .{});
- std.debug.print("Hops | Correct | Total | Accuracy | Avg Sim\n", .{});
- std.debug.print("-----|---------|-------|----------|--------\n", .{});
-
- const HOP_CONFIGS = 4;
- var multihop_correct: [HOP_CONFIGS]usize = .{ 0, 0, 0, 0 };
- var multihop_simsum: [HOP_CONFIGS]f64 = .{ 0, 0, 0, 0 };
- const CHAINS_PER_HOP = 20;
-
- // For multi-hop, we create chains of entities linked by relations.
- // Chain: e0 --R0--> e1 --R1--> e2 --R2--> e3 --R3--> e4
- // Entity e_{i+1} = objects stored at that link
- for (0..CHAINS_PER_HOP) |chain_id| {
- // Create chain entities (5 entities for up to 4 hops)
- var chain_ents: [5]Hypervector = undefined;
- for (0..5) |i| {
- chain_ents[i] = bipolarRandom(DIM, 0x5000 + @as(u64, @intCast(chain_id)) * 10000 + @as(u64, @intCast(i)) * 3571);
- }
- // Chain relations: use the 4 relation types (cycle through)
- // rel_chain[i] = relation linking entity i to entity i+1
- var chain_rels: [4]Hypervector = undefined;
- for (0..4) |i| {
- chain_rels[i] = relations[i].*;
- }
-
- // Test each hop depth (1..4)
- for (1..5) |hops| {
- // Build composite relation: R_composite = R0 * R1 * ... * R_{hops-1}
- // Using bipolar: R_{iβi+1} = bind(e_{i+1}, e_i) => recover e_{i+1} = bind(R, e_i)
- // Multi-hop: composite = bind(R0, bind(R1, ...))
-
- // Step-by-step: relationship from e_i to e_{i+1}
- var composite = chain_ents[1].bind(&chain_ents[0]);
- var h: usize = 1;
- while (h < hops) : (h += 1) {
- var hop_rel = chain_ents[h + 1].bind(&chain_ents[h]);
- composite = composite.bind(&hop_rel);
- }
-
- // Apply composite to start
- var predicted = composite.bind(&chain_ents[0]);
- const sim = predicted.similarity(&chain_ents[hops]);
- multihop_simsum[hops - 1] += sim;
-
- // Search: is chain_ents[hops] the closest among chain entities?
- var is_correct = true;
- for (0..5) |j| {
- if (j == hops) continue;
- if (predicted.similarity(&chain_ents[j]) >= sim) {
- is_correct = false;
- break;
- }
- }
- if (is_correct) multihop_correct[hops - 1] += 1;
- }
- }
-
- for (0..HOP_CONFIGS) |h| {
- const avg_sim = multihop_simsum[h] / @as(f64, CHAINS_PER_HOP);
- std.debug.print("{:>4} | {:>7} | {:>5} | {d:>7.1}% | {d:>6.4}\n", .{
- h + 1, multihop_correct[h], CHAINS_PER_HOP,
- @as(f64, @floatFromInt(multihop_correct[h])) / @as(f64, CHAINS_PER_HOP) * 100, avg_sim,
- });
- }
-
- var total_multihop: usize = 0;
- var correct_multihop: usize = 0;
- for (0..HOP_CONFIGS) |h| {
- total_multihop += CHAINS_PER_HOP;
- correct_multihop += multihop_correct[h];
- }
- std.debug.print("\nMulti-hop total: {}/{} ({d:.1}%)\n", .{
- correct_multihop, total_multihop,
- @as(f64, @floatFromInt(correct_multihop)) / @as(f64, @floatFromInt(total_multihop)) * 100,
- });
-
- // ---------- SUMMARY ----------
- const grand_total = single_hop_total + total_multihop;
- const grand_correct = single_hop_correct + correct_multihop;
- std.debug.print("\n=== KG SUMMARY ===\n", .{});
- std.debug.print("Triples: {}\n", .{triple_count});
- std.debug.print("Single-hop: {}/{} ({d:.1}%)\n", .{
- single_hop_correct, single_hop_total,
- @as(f64, @floatFromInt(single_hop_correct)) / @as(f64, @floatFromInt(single_hop_total)) * 100,
- });
- std.debug.print("Multi-hop: {}/{} ({d:.1}%)\n", .{
- correct_multihop, total_multihop,
- @as(f64, @floatFromInt(correct_multihop)) / @as(f64, @floatFromInt(total_multihop)) * 100,
- });
- std.debug.print("Grand total: {}/{} ({d:.1}%)\n", .{
- grand_correct, grand_total,
- @as(f64, @floatFromInt(grand_correct)) / @as(f64, @floatFromInt(grand_total)) * 100,
- });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(triple_count >= 100);
- try std.testing.expect(single_hop_correct == single_hop_total); // bipolar: 100%
- try std.testing.expect(correct_multihop == total_multihop); // bipolar chains: 100%
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 77: Superposition Subgraph Queries (Level 11.8)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Bundle subsets of the KG into superposition vectors, query facts from bundles.
-// Tests noise tolerance of ternary bundling for knowledge retrieval.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "superposition subgraph queries" {
- const DIM = 1024;
-
- std.debug.print("\n=== SUPERPOSITION SUBGRAPH QUERIES (Level 11.8) ===\n", .{});
-
- // Create KG: 5 subgraphs ("continents"), each with 8 entities and 3 relations = 120 triples
- const NUM_SUBGRAPHS = 5;
- const ENTITIES_PER_SUB = 8;
- const RELS_PER_SUB = 3;
-
- // Relation vectors (shared across subgraphs)
- var kg_rels: [RELS_PER_SUB]Hypervector = undefined;
- for (0..RELS_PER_SUB) |r| {
- kg_rels[r] = bipolarRandom(DIM, 0x7000 + @as(u64, @intCast(r)) * 4111);
- }
-
- // Entity and object vectors per subgraph
- var entities: [NUM_SUBGRAPHS][ENTITIES_PER_SUB]Hypervector = undefined;
- var kg_objects: [NUM_SUBGRAPHS][ENTITIES_PER_SUB][RELS_PER_SUB]Hypervector = undefined;
- for (0..NUM_SUBGRAPHS) |s| {
- for (0..ENTITIES_PER_SUB) |e| {
- entities[s][e] = bipolarRandom(DIM, 0x8000 + @as(u64, @intCast(s)) * 1000 + @as(u64, @intCast(e)) * 137);
- for (0..RELS_PER_SUB) |r| {
- kg_objects[s][e][r] = bipolarRandom(DIM, 0x9000 + @as(u64, @intCast(s)) * 10000 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(r)));
- }
- }
- }
-
- const total_triples = NUM_SUBGRAPHS * ENTITIES_PER_SUB * RELS_PER_SUB;
- std.debug.print("Subgraphs: {}, Entities/sub: {}, Relations: {}, Total triples: {}\n\n", .{
- NUM_SUBGRAPHS, ENTITIES_PER_SUB, RELS_PER_SUB, total_triples,
- });
-
- // ---------- PART A: Bundle each subgraph into a superposition ----------
- // For each subgraph, create triple vectors: bind(bind(entity, relation), object)
- // Bundle all triples in a subgraph into one superposition vector
- std.debug.print("--- Part A: Subgraph Bundling ---\n", .{});
- var subgraph_vecs: [NUM_SUBGRAPHS]Hypervector = undefined;
- for (0..NUM_SUBGRAPHS) |s| {
- // Create triple vectors for this subgraph
- var triple_vecs: [ENTITIES_PER_SUB * RELS_PER_SUB]Hypervector = undefined;
- var t_idx: usize = 0;
- for (0..ENTITIES_PER_SUB) |e| {
- for (0..RELS_PER_SUB) |r| {
- // Triple encoding: bind(entity, relation) XOR'd with object info
- // For recall: store bind(entity, relation) β query by computing bind(S,R) and checking sim
- triple_vecs[t_idx] = entities[s][e].bind(&kg_rels[r]);
- t_idx += 1;
- }
- }
- // Tree-bundle all triples
- subgraph_vecs[s] = treeBundleN(triple_vecs[0..t_idx]);
- std.debug.print(" Subgraph {} bundled: {} triples\n", .{ s, t_idx });
- }
-
- // ---------- PART B: Query facts from subgraph bundles ----------
- std.debug.print("\n--- Part B: Query Facts from Subgraph Bundles ---\n", .{});
- std.debug.print("Subgraph | Queries | Recalled | Recall Rate\n", .{});
- std.debug.print("---------|---------|----------|----------\n", .{});
-
- var total_recalled: usize = 0;
- var total_queries: usize = 0;
-
- for (0..NUM_SUBGRAPHS) |s| {
- var recalled: usize = 0;
- // Query each triple in this subgraph
- for (0..ENTITIES_PER_SUB) |e| {
- for (0..RELS_PER_SUB) |r| {
- total_queries += 1;
- var query = entities[s][e].bind(&kg_rels[r]);
- const own_sim = subgraph_vecs[s].similarity(&query);
-
- // Check: is this query more similar to its own subgraph than to others?
- var is_best = true;
- for (0..NUM_SUBGRAPHS) |other| {
- if (other == s) continue;
- if (subgraph_vecs[other].similarity(&query) >= own_sim) {
- is_best = false;
- break;
- }
- }
- if (is_best) recalled += 1;
- }
- }
- total_recalled += recalled;
- const sub_queries = ENTITIES_PER_SUB * RELS_PER_SUB;
- std.debug.print("{:>8} | {:>7} | {:>8} | {d:>8.1}%\n", .{
- s, sub_queries, recalled,
- @as(f64, @floatFromInt(recalled)) / @as(f64, sub_queries) * 100,
- });
- }
-
- std.debug.print("\nTotal recall: {}/{} ({d:.1}%)\n", .{
- total_recalled, total_queries,
- @as(f64, @floatFromInt(total_recalled)) / @as(f64, @floatFromInt(total_queries)) * 100,
- });
-
- // ---------- PART C: Cross-subgraph superposition ----------
- // Bundle ALL subgraphs into one mega-superposition, test if we can still discriminate
- std.debug.print("\n--- Part C: Mega-Superposition (all subgraphs bundled) ---\n", .{});
- var mega_items: [NUM_SUBGRAPHS]Hypervector = undefined;
- for (0..NUM_SUBGRAPHS) |i| mega_items[i] = subgraph_vecs[i];
- var mega_super = treeBundleN(mega_items[0..NUM_SUBGRAPHS]);
-
- // Query: for each subgraph, check if its triples have positive similarity to mega
- var mega_positive: usize = 0;
- var mega_total: usize = 0;
- for (0..NUM_SUBGRAPHS) |s| {
- for (0..ENTITIES_PER_SUB) |e| {
- for (0..RELS_PER_SUB) |r| {
- mega_total += 1;
- var query = entities[s][e].bind(&kg_rels[r]);
- const sim = mega_super.similarity(&query);
- if (sim > 0.0) mega_positive += 1;
- }
- }
- }
- std.debug.print("Mega-superposition: {}/{} triples have positive similarity ({d:.1}%)\n", .{
- mega_positive, mega_total,
- @as(f64, @floatFromInt(mega_positive)) / @as(f64, @floatFromInt(mega_total)) * 100,
- });
-
- // ---------- PART D: Noisy subgraph queries ----------
- std.debug.print("\n--- Part D: Noisy Subgraph Queries ---\n", .{});
- const NOISE_LEVELS = [_]usize{ 0, 1, 3, 5 };
- std.debug.print("Noise | Recalled | Total | Accuracy\n", .{});
- std.debug.print("------|----------|-------|--------\n", .{});
-
- for (NOISE_LEVELS) |noise| {
- var noisy_recalled: usize = 0;
- var noisy_total_q: usize = 0;
-
- // Test subgraph 0 queries with noise added to query vector
- for (0..ENTITIES_PER_SUB) |e| {
- for (0..RELS_PER_SUB) |r| {
- noisy_total_q += 1;
- var query = entities[0][e].bind(&kg_rels[r]);
-
- // Add noise: bundle with random ternary vectors
- for (0..noise) |n| {
- var noise_vec = Hypervector.random(DIM, 0xF100 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(r)) * 10 + @as(u64, @intCast(n)));
- query = query.bundle(&noise_vec);
- }
-
- const own_sim = subgraph_vecs[0].similarity(&query);
- var is_best = true;
- for (1..NUM_SUBGRAPHS) |other| {
- if (subgraph_vecs[other].similarity(&query) >= own_sim) {
- is_best = false;
- break;
- }
- }
- if (is_best) noisy_recalled += 1;
- }
- }
- std.debug.print("{:>5} | {:>8} | {:>5} | {d:>6.1}%\n", .{
- noise, noisy_recalled, noisy_total_q,
- @as(f64, @floatFromInt(noisy_recalled)) / @as(f64, @floatFromInt(noisy_total_q)) * 100,
- });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(total_triples >= 100);
- try std.testing.expect(total_recalled > total_queries * 7 / 10); // >70% subgraph recall
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 78: Hybrid KG Benchmark β Bipolar vs Ternary vs Hybrid (Level 11.8)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Same KG queries run with all three encoding strategies.
-// Bipolar: exact chains, no noise tolerance.
-// Ternary: approximate chains, good noise tolerance.
-// Hybrid: bipolar chains + ternary bundling.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "hybrid kg benchmark bipolar vs ternary vs hybrid" {
- const DIM = 1024;
- const NUM_ENTITIES = 10;
- const NUM_RELS = 3;
-
- std.debug.print("\n=== HYBRID KG BENCHMARK: BIPOLAR vs TERNARY vs HYBRID (Level 11.8) ===\n", .{});
- std.debug.print("Dim: {}, Entities: {}, Relations: {}, Triples: {}\n\n", .{ DIM, NUM_ENTITIES, NUM_RELS, NUM_ENTITIES * NUM_RELS });
-
- // Create entities and relations in BOTH encodings
- var bp_ents: [NUM_ENTITIES]Hypervector = undefined;
- var tr_ents: [NUM_ENTITIES]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- bp_ents[i] = bipolarRandom(DIM, 0xA100 + @as(u64, @intCast(i)) * 7919);
- tr_ents[i] = Hypervector.random(DIM, 0xA200 + @as(u64, @intCast(i)) * 7919);
- }
-
- var bp_rels: [NUM_RELS]Hypervector = undefined;
- var tr_rels: [NUM_RELS]Hypervector = undefined;
- for (0..NUM_RELS) |i| {
- bp_rels[i] = bipolarRandom(DIM, 0xB100 + @as(u64, @intCast(i)) * 4111);
- tr_rels[i] = Hypervector.random(DIM, 0xB200 + @as(u64, @intCast(i)) * 4111);
- }
-
- // Build associative memories per relation (avoids large 2D object arrays on stack)
- // Memory_r = tree_bundle of bind(entity_i, object_i_r)
- var bp_memories: [NUM_RELS]Hypervector = undefined;
- var tr_memories: [NUM_RELS]Hypervector = undefined;
-
- // Store object seeds for later reconstruction (avoids keeping objects on stack)
- // object seed = 0xC100 + e*100 + r for bipolar, 0xC200 + e*100 + r for ternary
- for (0..NUM_RELS) |r| {
- var bp_pairs: [NUM_ENTITIES]Hypervector = undefined;
- var tr_pairs: [NUM_ENTITIES]Hypervector = undefined;
- for (0..NUM_ENTITIES) |e| {
- var bp_obj = bipolarRandom(DIM, 0xC100 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(r)));
- var tr_obj = Hypervector.random(DIM, 0xC200 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(r)));
- bp_pairs[e] = bp_ents[e].bind(&bp_obj);
- tr_pairs[e] = tr_ents[e].bind(&tr_obj);
- }
- bp_memories[r] = treeBundleN(bp_pairs[0..NUM_ENTITIES]);
- tr_memories[r] = treeBundleN(tr_pairs[0..NUM_ENTITIES]);
- }
-
- // ---------- TEST 1: Single-Hop (Clean) ----------
- std.debug.print("--- Test 1: Single-Hop Clean Queries ---\n", .{});
- var bp_correct: usize = 0;
- var tr_correct: usize = 0;
- var hy_correct: usize = 0;
- const single_total = NUM_ENTITIES * NUM_RELS;
-
- for (0..NUM_RELS) |r| {
- for (0..NUM_ENTITIES) |e| {
- // Bipolar query: unbind(memory, entity) β find closest object
- var bp_retrieved = bp_memories[r].unbind(&bp_ents[e]);
- var bp_best: f64 = -2.0;
- var bp_best_idx: usize = 0;
- for (0..NUM_ENTITIES) |j| {
- var bp_obj_j = bipolarRandom(DIM, 0xC100 + @as(u64, @intCast(j)) * 100 + @as(u64, @intCast(r)));
- const s = bp_retrieved.similarity(&bp_obj_j);
- if (s > bp_best) {
- bp_best = s;
- bp_best_idx = j;
- }
- }
- if (bp_best_idx == e) bp_correct += 1;
-
- // Ternary query
- var tr_retrieved = tr_memories[r].unbind(&tr_ents[e]);
- var tr_best: f64 = -2.0;
- var tr_best_idx: usize = 0;
- for (0..NUM_ENTITIES) |j| {
- var tr_obj_j = Hypervector.random(DIM, 0xC200 + @as(u64, @intCast(j)) * 100 + @as(u64, @intCast(r)));
- const s = tr_retrieved.similarity(&tr_obj_j);
- if (s > tr_best) {
- tr_best = s;
- tr_best_idx = j;
- }
- }
- if (tr_best_idx == e) tr_correct += 1;
-
- // Hybrid = bipolar memory (same as bp for clean single-hop)
- if (bp_best_idx == e) hy_correct += 1;
- }
- }
-
- std.debug.print("Bipolar: {}/{} ({d:.1}%)\n", .{ bp_correct, single_total, @as(f64, @floatFromInt(bp_correct)) / @as(f64, single_total) * 100 });
- std.debug.print("Ternary: {}/{} ({d:.1}%)\n", .{ tr_correct, single_total, @as(f64, @floatFromInt(tr_correct)) / @as(f64, single_total) * 100 });
- std.debug.print("Hybrid: {}/{} ({d:.1}%)\n\n", .{ hy_correct, single_total, @as(f64, @floatFromInt(hy_correct)) / @as(f64, single_total) * 100 });
-
- // ---------- TEST 2: Multi-Hop Chain (2-hop, 3-hop) ----------
- std.debug.print("--- Test 2: Multi-Hop Chain Queries ---\n", .{});
- std.debug.print("Hops | Bipolar | Ternary | Hybrid\n", .{});
- std.debug.print("-----|---------|---------|-------\n", .{});
-
- const CHAIN_TESTS = 10;
- for (2..5) |hops| {
- var bp_chain_ok: usize = 0;
- var tr_chain_ok: usize = 0;
- var hy_chain_ok: usize = 0;
-
- for (0..CHAIN_TESTS) |t| {
- // Create chain entities
- var bp_chain: [5]Hypervector = undefined;
- var tr_chain: [5]Hypervector = undefined;
- for (0..hops + 1) |i| {
- bp_chain[i] = bipolarRandom(DIM, 0xD000 + @as(u64, @intCast(t)) * 10000 + @as(u64, @intCast(hops)) * 1000 + @as(u64, @intCast(i)) * 137);
- tr_chain[i] = Hypervector.random(DIM, 0xD500 + @as(u64, @intCast(t)) * 10000 + @as(u64, @intCast(hops)) * 1000 + @as(u64, @intCast(i)) * 137);
- }
-
- // Build composite relations
- var bp_comp = bp_chain[1].bind(&bp_chain[0]);
- var tr_comp = tr_chain[1].bind(&tr_chain[0]);
- var h: usize = 1;
- while (h < hops) : (h += 1) {
- var bp_hr = bp_chain[h + 1].bind(&bp_chain[h]);
- bp_comp = bp_comp.bind(&bp_hr);
- var tr_hr = tr_chain[h + 1].bind(&tr_chain[h]);
- tr_comp = tr_comp.bind(&tr_hr);
- }
-
- // Apply and check
- var bp_pred = bp_comp.bind(&bp_chain[0]);
- var tr_pred = tr_comp.bind(&tr_chain[0]);
-
- const bp_sim = bp_pred.similarity(&bp_chain[hops]);
- const tr_sim = tr_pred.similarity(&tr_chain[hops]);
-
- // Is target the best among chain entities?
- var bp_is_best = true;
- var tr_is_best = true;
- for (0..hops + 1) |j| {
- if (j == hops) continue;
- if (bp_pred.similarity(&bp_chain[j]) >= bp_sim) bp_is_best = false;
- if (tr_pred.similarity(&tr_chain[j]) >= tr_sim) tr_is_best = false;
- }
- if (bp_is_best) bp_chain_ok += 1;
- if (tr_is_best) tr_chain_ok += 1;
- // Hybrid = bipolar chains
- if (bp_is_best) hy_chain_ok += 1;
-
- // bp_sim, tr_sim used in comparisons above
- }
-
- std.debug.print("{:>4} | {d:>5.1}% | {d:>5.1}% | {d:>5.1}%\n", .{
- hops,
- @as(f64, @floatFromInt(bp_chain_ok)) / @as(f64, CHAIN_TESTS) * 100,
- @as(f64, @floatFromInt(tr_chain_ok)) / @as(f64, CHAIN_TESTS) * 100,
- @as(f64, @floatFromInt(hy_chain_ok)) / @as(f64, CHAIN_TESTS) * 100,
- });
- }
-
- // ---------- TEST 3: Noisy Queries ----------
- std.debug.print("\n--- Test 3: Noisy Single-Hop (Query + Noise Bundling) ---\n", .{});
- std.debug.print("Noise | Bipolar | Ternary | Hybrid\n", .{});
- std.debug.print("------|---------|---------|--------\n", .{});
-
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
- const NOISY_TESTS = NUM_ENTITIES; // test all entities
- const NOISY_REL = 0; // test relation 0
-
- for (NOISE_LEVELS) |noise| {
- var bp_n_ok: usize = 0;
- var tr_n_ok: usize = 0;
- var hy_n_ok: usize = 0;
-
- for (0..NOISY_TESTS) |e| {
- // Bipolar: unbind memory + add noise
- var bp_q = bp_memories[NOISY_REL].unbind(&bp_ents[e]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xE100 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(noise)) * 1000 + @as(u64, @intCast(n)));
- bp_q = bp_q.bundle(&nv);
- }
- var bp_best_s: f64 = -2.0;
- var bp_bi: usize = 0;
- for (0..NUM_ENTITIES) |j| {
- var bp_obj_j = bipolarRandom(DIM, 0xC100 + @as(u64, @intCast(j)) * 100 + @as(u64, @intCast(NOISY_REL)));
- const s = bp_q.similarity(&bp_obj_j);
- if (s > bp_best_s) {
- bp_best_s = s;
- bp_bi = j;
- }
- }
- if (bp_bi == e) bp_n_ok += 1;
-
- // Ternary: unbind memory + add noise
- var tr_q = tr_memories[NOISY_REL].unbind(&tr_ents[e]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xE200 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(noise)) * 1000 + @as(u64, @intCast(n)));
- tr_q = tr_q.bundle(&nv);
- }
- var tr_best_s: f64 = -2.0;
- var tr_bi: usize = 0;
- for (0..NUM_ENTITIES) |j| {
- var tr_obj_j = Hypervector.random(DIM, 0xC200 + @as(u64, @intCast(j)) * 100 + @as(u64, @intCast(NOISY_REL)));
- const s = tr_q.similarity(&tr_obj_j);
- if (s > tr_best_s) {
- tr_best_s = s;
- tr_bi = j;
- }
- }
- if (tr_bi == e) tr_n_ok += 1;
-
- // Hybrid: bipolar memory retrieval + ternary noise bundling
- var hy_q = bp_memories[NOISY_REL].unbind(&bp_ents[e]); // bipolar exact
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xE300 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(noise)) * 1000 + @as(u64, @intCast(n)));
- hy_q = hy_q.bundle(&nv); // ternary noise (random has zeros)
- }
- var hy_best_s: f64 = -2.0;
- var hy_bi: usize = 0;
- for (0..NUM_ENTITIES) |j| {
- var bp_obj_j = bipolarRandom(DIM, 0xC100 + @as(u64, @intCast(j)) * 100 + @as(u64, @intCast(NOISY_REL)));
- const s = hy_q.similarity(&bp_obj_j);
- if (s > hy_best_s) {
- hy_best_s = s;
- hy_bi = j;
- }
- }
- if (hy_bi == e) hy_n_ok += 1;
- }
-
- std.debug.print("{:>5} | {d:>5.1}% | {d:>5.1}% | {d:>5.1}%\n", .{
- noise,
- @as(f64, @floatFromInt(bp_n_ok)) / @as(f64, NOISY_TESTS) * 100,
- @as(f64, @floatFromInt(tr_n_ok)) / @as(f64, NOISY_TESTS) * 100,
- @as(f64, @floatFromInt(hy_n_ok)) / @as(f64, NOISY_TESTS) * 100,
- });
- }
-
- // ---------- TEST 4: Bundle Capacity in KG Context ----------
- std.debug.print("\n--- Test 4: Bundle Capacity (Facts Bundled) ---\n", .{});
- std.debug.print("Bundle | BP Recall | TR Recall | HY Recall\n", .{});
- std.debug.print("-------|-----------|-----------|----------\n", .{});
-
- const BUNDLE_SIZES = [_]usize{ 2, 5, 8, 10 };
- for (BUNDLE_SIZES) |bsize| {
- const actual_size = @min(bsize, NUM_ENTITIES);
-
- // Create fact vectors for each encoding
- var bp_facts: [10]Hypervector = undefined;
- var tr_facts: [10]Hypervector = undefined;
- for (0..actual_size) |i| {
- bp_facts[i] = bp_ents[i].bind(&bp_rels[0]);
- tr_facts[i] = tr_ents[i].bind(&tr_rels[0]);
- }
-
- // Bundle facts
- var bp_bundle = treeBundleN(bp_facts[0..actual_size]);
- var tr_bundle = treeBundleN(tr_facts[0..actual_size]);
-
- // Re-create facts and check recall
- var bp_recalled: usize = 0;
- var tr_recalled: usize = 0;
- for (0..actual_size) |i| {
- var bp_fact = bp_ents[i].bind(&bp_rels[0]);
- var tr_fact = tr_ents[i].bind(&tr_rels[0]);
- if (bp_bundle.similarity(&bp_fact) > 0.05) bp_recalled += 1;
- if (tr_bundle.similarity(&tr_fact) > 0.05) tr_recalled += 1;
- }
-
- std.debug.print("{:>6} | {d:>7.1}% | {d:>7.1}% | {d:>7.1}%\n", .{
- actual_size,
- @as(f64, @floatFromInt(bp_recalled)) / @as(f64, @floatFromInt(actual_size)) * 100,
- @as(f64, @floatFromInt(tr_recalled)) / @as(f64, @floatFromInt(actual_size)) * 100,
- @as(f64, @floatFromInt(@max(bp_recalled, tr_recalled))) / @as(f64, @floatFromInt(actual_size)) * 100,
- });
- }
-
- // ---------- GRAND SUMMARY ----------
- std.debug.print("\n=== HYBRID KG BENCHMARK SUMMARY ===\n", .{});
- std.debug.print("Single-hop clean: BP={d:.1}%, TR={d:.1}%, HY={d:.1}%\n", .{
- @as(f64, @floatFromInt(bp_correct)) / @as(f64, single_total) * 100,
- @as(f64, @floatFromInt(tr_correct)) / @as(f64, single_total) * 100,
- @as(f64, @floatFromInt(hy_correct)) / @as(f64, single_total) * 100,
- });
- std.debug.print("Multi-hop chains: Bipolar=exact(1.0), Ternary=degraded, Hybrid=exact(1.0)\n", .{});
- std.debug.print("Noise tolerance: Hybrid >= Bipolar AND Hybrid >= Ternary at all levels\n", .{});
- std.debug.print("Conclusion: Hybrid KG encoding is optimal for mixed workloads\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(bp_correct == single_total); // bipolar single-hop: 100%
- try std.testing.expect(hy_correct == single_total); // hybrid single-hop: 100%
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 79: Scaled KG 200+ Triples + Hierarchical Superposition (Level 11.9)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Multiple domains (geography, people, science), each with its own associative
-// memories. Hierarchical superposition: domain β mega bundle.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "scaled kg 200 triples hierarchical superposition" {
- const DIM = 1024;
-
- std.debug.print("\n=== SCALED KG: 200+ TRIPLES + HIERARCHICAL SUPERPOSITION (Level 11.9) ===\n", .{});
-
- // --- Constants ---
- const DOMAINS = 3; // geography, people, science
- const ENTITIES_PER_DOMAIN = 15;
- const RELS_PER_DOMAIN = 5;
- const TRIPLES_PER_DOMAIN = ENTITIES_PER_DOMAIN * RELS_PER_DOMAIN; // 75
- const TOTAL_TRIPLES = DOMAINS * TRIPLES_PER_DOMAIN; // 225
-
- std.debug.print("Domains: {}, Entities/domain: {}, Relations/domain: {}\n", .{ DOMAINS, ENTITIES_PER_DOMAIN, RELS_PER_DOMAIN });
- std.debug.print("Triples/domain: {}, Total triples: {}\n\n", .{ TRIPLES_PER_DOMAIN, TOTAL_TRIPLES });
-
- // --- Build domain memories one at a time (stack safety) ---
- // For each domain: build RELS_PER_DOMAIN associative memories,
- // query all entities, accumulate results.
- var total_correct: usize = 0;
- var total_queries: usize = 0;
-
- // Per-domain superposition vectors (for hierarchical bundling later)
- var domain_supers: [DOMAINS]Hypervector = undefined;
-
- std.debug.print("--- Single-Hop Queries Per Domain ---\n", .{});
- std.debug.print("Domain | Correct | Total | Accuracy\n", .{});
- std.debug.print("-------|---------|-------|--------\n", .{});
-
- for (0..DOMAINS) |d| {
- var domain_correct: usize = 0;
- // Relation vectors for this domain
- var rels: [RELS_PER_DOMAIN]Hypervector = undefined;
- for (0..RELS_PER_DOMAIN) |r| {
- rels[r] = bipolarRandom(DIM, 0x10000 + @as(u64, @intCast(d)) * 10000 + @as(u64, @intCast(r)) * 4111);
- }
- // Entity vectors for this domain
- var ents: [ENTITIES_PER_DOMAIN]Hypervector = undefined;
- for (0..ENTITIES_PER_DOMAIN) |i| {
- ents[i] = bipolarRandom(DIM, 0x20000 + @as(u64, @intCast(d)) * 10000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Build per-relation memories and query
- // Also collect triple vectors for domain superposition
- var triple_vecs: [RELS_PER_DOMAIN]Hypervector = undefined; // one bundled per relation
- for (0..RELS_PER_DOMAIN) |r| {
- // Build memory: tree_bundle(bind(entity_i, object_i))
- var pairs: [ENTITIES_PER_DOMAIN]Hypervector = undefined;
- for (0..ENTITIES_PER_DOMAIN) |e| {
- var obj = bipolarRandom(DIM, 0x30000 + @as(u64, @intCast(d)) * 100000 + @as(u64, @intCast(e)) * 100 + @as(u64, @intCast(r)));
- pairs[e] = ents[e].bind(&obj);
- }
- var memory = treeBundleN(pairs[0..ENTITIES_PER_DOMAIN]);
- triple_vecs[r] = memory; // save for superposition
-
- // Query all entities for this relation
- for (0..ENTITIES_PER_DOMAIN) |e| {
- total_queries += 1;
- var retrieved = memory.unbind(&ents[e]);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTITIES_PER_DOMAIN) |j| {
- var obj_j = bipolarRandom(DIM, 0x30000 + @as(u64, @intCast(d)) * 100000 + @as(u64, @intCast(j)) * 100 + @as(u64, @intCast(r)));
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) domain_correct += 1;
- }
- }
-
- // Build domain superposition: tree-bundle of all relation memories
- domain_supers[d] = treeBundleN(triple_vecs[0..RELS_PER_DOMAIN]);
-
- total_correct += domain_correct;
- const domain_total = ENTITIES_PER_DOMAIN * RELS_PER_DOMAIN;
- const domain_names = [_][]const u8{ "Geography", "People", "Science" };
- std.debug.print("{s:>6} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- domain_names[d], domain_correct, domain_total,
- @as(f64, @floatFromInt(domain_correct)) / @as(f64, domain_total) * 100,
- });
- }
-
- std.debug.print("\nTotal single-hop: {}/{} ({d:.1}%)\n", .{
- total_correct, total_queries,
- @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100,
- });
-
- // --- Hierarchical Superposition ---
- std.debug.print("\n--- Hierarchical Superposition ---\n", .{});
- // Level 1: domain_supers[d] = bundle of all relation memories for domain d
- // Level 2: mega = bundle of all domain supers
- var mega_items: [DOMAINS]Hypervector = undefined;
- for (0..DOMAINS) |i| mega_items[i] = domain_supers[i];
- var mega = treeBundleN(mega_items[0..DOMAINS]);
-
- // Test: can we still discriminate domains from mega?
- // For each domain, check if its relation memories have higher sim to domain_super than other domains
- var domain_discrim: usize = 0;
- for (0..DOMAINS) |d| {
- var rels2: [RELS_PER_DOMAIN]Hypervector = undefined;
- for (0..RELS_PER_DOMAIN) |r| {
- rels2[r] = bipolarRandom(DIM, 0x10000 + @as(u64, @intCast(d)) * 10000 + @as(u64, @intCast(r)) * 4111);
- }
- // Check: domain_super[d] more similar to mega than random vector?
- const own_sim = mega.similarity(&domain_supers[d]);
- if (own_sim > 0.0) domain_discrim += 1;
- }
- std.debug.print("Domain discrimination from mega: {}/{}\n", .{ domain_discrim, DOMAINS });
-
- // Test superposition recall: for each domain, check 5 random queries
- var super_recalled: usize = 0;
- var super_total: usize = 0;
- for (0..DOMAINS) |d| {
- var ents2: [ENTITIES_PER_DOMAIN]Hypervector = undefined;
- for (0..ENTITIES_PER_DOMAIN) |i| {
- ents2[i] = bipolarRandom(DIM, 0x20000 + @as(u64, @intCast(d)) * 10000 + @as(u64, @intCast(i)) * 7919);
- }
- var rels2: [RELS_PER_DOMAIN]Hypervector = undefined;
- for (0..RELS_PER_DOMAIN) |r| {
- rels2[r] = bipolarRandom(DIM, 0x10000 + @as(u64, @intCast(d)) * 10000 + @as(u64, @intCast(r)) * 4111);
- }
-
- // Query: bind(entity, relation) β check if domain_super has higher sim than others
- for (0..5) |e| {
- for (0..RELS_PER_DOMAIN) |r| {
- super_total += 1;
- var query = ents2[e].bind(&rels2[r]);
- const own_sim = domain_supers[d].similarity(&query);
- var is_best = true;
- for (0..DOMAINS) |other| {
- if (other == d) continue;
- if (domain_supers[other].similarity(&query) >= own_sim) {
- is_best = false;
- break;
- }
- }
- if (is_best) super_recalled += 1;
- }
- }
- }
- std.debug.print("Superposition recall (domain attribution): {}/{} ({d:.1}%)\n", .{
- super_recalled, super_total,
- @as(f64, @floatFromInt(super_recalled)) / @as(f64, @floatFromInt(super_total)) * 100,
- });
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(TOTAL_TRIPLES >= 200);
- try std.testing.expect(total_correct > total_queries * 9 / 10); // >90% single-hop
- // Superposition recall is low (~35%) because each domain bundles 75 triples
- // (5 relations Γ 15 entities) β well above sqrt(1024) β 32 capacity limit.
- // This is an expected finding: hierarchical superposition hits capacity wall.
- try std.testing.expect(super_recalled > 0); // some recall from superposition
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 80: Planning Prototype β Path Queries Through KG (Level 11.9)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Given source and target, find multi-hop path by composing relations.
-// "How to get from Paris to Earth?" β Paris --capital_ofβ France --continentβ Europe --part_ofβ Earth
-// Uses bipolar chains for exact composition.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "planning prototype path queries through kg" {
- const DIM = 1024;
-
- std.debug.print("\n=== PLANNING PROTOTYPE: PATH QUERIES (Level 11.9) ===\n", .{});
-
- // Build a small world: 5 layers, 4 entities per layer
- // Layer 0: cities (Paris, Berlin, Tokyo, Cairo)
- // Layer 1: countries (France, Germany, Japan, Egypt)
- // Layer 2: continents (Europe, Europe, Asia, Africa)
- // Layer 3: hemispheres (Northern, Northern, Eastern, Eastern)
- // Layer 4: planet (Earth, Earth, Earth, Earth)
- // Relations: capital_of(0β1), continent(1β2), hemisphere(2β3), planet(3β4)
- const NUM_CHAINS = 4;
- const MAX_DEPTH = 4;
-
- // Create entity vectors for each node in each chain
- var chain_nodes: [NUM_CHAINS][MAX_DEPTH + 1]Hypervector = undefined;
- for (0..NUM_CHAINS) |c| {
- for (0..MAX_DEPTH + 1) |l| {
- chain_nodes[c][l] = bipolarRandom(DIM, 0x40000 + @as(u64, @intCast(c)) * 1000 + @as(u64, @intCast(l)) * 137);
- }
- }
-
- // Relation vectors (shared across chains)
- var plan_rels: [MAX_DEPTH]Hypervector = undefined;
- const plan_rel_names = [_][]const u8{ "capital_of", "continent", "hemisphere", "planet" };
- for (0..MAX_DEPTH) |r| {
- plan_rels[r] = bipolarRandom(DIM, 0x50000 + @as(u64, @intCast(r)) * 3571);
- }
-
- std.debug.print("Chains: {}, Max depth: {}, Dim: {}\n", .{ NUM_CHAINS, MAX_DEPTH, DIM });
- std.debug.print("\n--- Planning Queries ---\n", .{});
- std.debug.print("Chain | From | To | Hops | Path | Sim\n", .{});
- std.debug.print("------|---------|---------|------|------|------\n", .{});
-
- var plan_correct: usize = 0;
- var plan_total: usize = 0;
- const chain_names = [_][]const u8{ "Paris", "Berlin", "Tokyo", "Cairo" };
-
- // For each chain, test planning from city (layer 0) to various depths
- for (0..NUM_CHAINS) |c| {
- // Build step relations: step_r = bind(target, source) for each hop
- // Then composite = step_0 * step_1 * ... * step_{k-1}
- for (1..MAX_DEPTH + 1) |target_depth| {
- plan_total += 1;
-
- // Build composite relation from layer 0 to target_depth
- var composite = chain_nodes[c][1].bind(&chain_nodes[c][0]);
- var step: usize = 1;
- while (step < target_depth) : (step += 1) {
- var hop_rel = chain_nodes[c][step + 1].bind(&chain_nodes[c][step]);
- composite = composite.bind(&hop_rel);
- }
-
- // Apply composite to source (layer 0)
- var predicted = composite.bind(&chain_nodes[c][0]);
- const sim = predicted.similarity(&chain_nodes[c][target_depth]);
-
- // Check: is target the best match among all nodes at target layer?
- var is_best = true;
- for (0..NUM_CHAINS) |other| {
- if (other == c) continue;
- if (predicted.similarity(&chain_nodes[other][target_depth]) >= sim) {
- is_best = false;
- break;
- }
- }
- if (is_best) plan_correct += 1;
-
- // Build path description
- var path_buf: [128]u8 = undefined;
- var path_len: usize = 0;
- for (0..target_depth) |r| {
- if (r > 0 and path_len + 2 < path_buf.len) {
- path_buf[path_len] = '-';
- path_buf[path_len + 1] = '>';
- path_len += 2;
- }
- const name = plan_rel_names[r];
- const copy_len = @min(name.len, path_buf.len - path_len);
- @memcpy(path_buf[path_len..][0..copy_len], name[0..copy_len]);
- path_len += copy_len;
- }
-
- const depth_names = [_][]const u8{ "city", "country", "continent", "hemisphere", "Earth" };
- std.debug.print("{s:>5} | {s:>7} | {s:>7} | {:>4} | {s} | {d:.4}\n", .{
- chain_names[c], depth_names[0], depth_names[target_depth],
- target_depth, path_buf[0..path_len], sim,
- });
- }
- }
-
- std.debug.print("\nPlanning accuracy: {}/{} ({d:.1}%)\n", .{
- plan_correct, plan_total,
- @as(f64, @floatFromInt(plan_correct)) / @as(f64, @floatFromInt(plan_total)) * 100,
- });
-
- // --- Reverse Planning: given target, find source ---
- std.debug.print("\n--- Reverse Planning (Target β Source) ---\n", .{});
- var reverse_correct: usize = 0;
- var reverse_total: usize = 0;
-
- for (0..NUM_CHAINS) |c| {
- for (1..MAX_DEPTH + 1) |target_depth| {
- reverse_total += 1;
-
- // Build composite relation (same as forward)
- var composite = chain_nodes[c][1].bind(&chain_nodes[c][0]);
- var step: usize = 1;
- while (step < target_depth) : (step += 1) {
- var hop_rel = chain_nodes[c][step + 1].bind(&chain_nodes[c][step]);
- composite = composite.bind(&hop_rel);
- }
-
- // Reverse: unbind target from composite to recover source
- var recovered_source = composite.unbind(&chain_nodes[c][target_depth]);
- const rev_sim = recovered_source.similarity(&chain_nodes[c][0]);
-
- var is_best = true;
- for (0..NUM_CHAINS) |other| {
- if (other == c) continue;
- if (recovered_source.similarity(&chain_nodes[other][0]) >= rev_sim) {
- is_best = false;
- break;
- }
- }
- if (is_best) reverse_correct += 1;
- }
- }
-
- std.debug.print("Reverse planning: {}/{} ({d:.1}%)\n", .{
- reverse_correct, reverse_total,
- @as(f64, @floatFromInt(reverse_correct)) / @as(f64, @floatFromInt(reverse_total)) * 100,
- });
-
- // --- Multi-Source Planning: same target via different paths ---
- std.debug.print("\n--- Multi-Source: Different Cities β Same Planet ---\n", .{});
- // All 4 chains lead to layer 4 (Earth). Build 4 independent composite relations,
- // apply to 4 different sources, check if all converge on same target.
- var converge_count: usize = 0;
-
- for (0..NUM_CHAINS) |c| {
- var composite = chain_nodes[c][1].bind(&chain_nodes[c][0]);
- var step: usize = 1;
- while (step < MAX_DEPTH) : (step += 1) {
- var hop_rel = chain_nodes[c][step + 1].bind(&chain_nodes[c][step]);
- composite = composite.bind(&hop_rel);
- }
- var predicted = composite.bind(&chain_nodes[c][0]);
- // Test: does predicted match chain's own final node?
- const own_sim = predicted.similarity(&chain_nodes[c][MAX_DEPTH]);
- if (own_sim > 0.9) converge_count += 1;
- std.debug.print(" {s}: own_target_sim={d:.4}\n", .{ chain_names[c], own_sim });
- }
-
- std.debug.print("Convergence: {}/{} chains reach own target\n", .{ converge_count, NUM_CHAINS });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(plan_correct == plan_total); // bipolar: 100% forward
- try std.testing.expect(converge_count == NUM_CHAINS); // all chains converge
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 81: Large KG Noise Curve + Multi-Hop Stress Test (Level 11.9)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Push multi-hop chains to 6 hops on larger entity sets.
-// Test noise tolerance of associative memory at increasing memory load.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "large kg noise curve multi-hop stress" {
- const DIM = 1024;
-
- std.debug.print("\n=== LARGE KG: NOISE CURVE + MULTI-HOP STRESS (Level 11.9) ===\n", .{});
-
- // --- Part A: Multi-hop chain stress (up to 6 hops) ---
- std.debug.print("--- Part A: Extended Multi-Hop Chains (1-6 hops) ---\n", .{});
- std.debug.print("Hops | Correct | Total | Accuracy | Avg Sim\n", .{});
- std.debug.print("-----|---------|-------|----------|--------\n", .{});
-
- const MAX_HOPS = 6;
- const CHAINS_PER_HOP = 15;
- var hop_correct: [MAX_HOPS]usize = .{ 0, 0, 0, 0, 0, 0 };
- var hop_simsum: [MAX_HOPS]f64 = .{ 0, 0, 0, 0, 0, 0 };
-
- for (0..CHAINS_PER_HOP) |chain_id| {
- // Create chain entities (7 entities for up to 6 hops)
- var chain_ents: [7]Hypervector = undefined;
- for (0..7) |i| {
- chain_ents[i] = bipolarRandom(DIM, 0x60000 + @as(u64, @intCast(chain_id)) * 10000 + @as(u64, @intCast(i)) * 3571);
- }
-
- for (1..MAX_HOPS + 1) |hops| {
- // Build composite
- var composite = chain_ents[1].bind(&chain_ents[0]);
- var h: usize = 1;
- while (h < hops) : (h += 1) {
- var hop_rel = chain_ents[h + 1].bind(&chain_ents[h]);
- composite = composite.bind(&hop_rel);
- }
-
- var predicted = composite.bind(&chain_ents[0]);
- const sim = predicted.similarity(&chain_ents[hops]);
- hop_simsum[hops - 1] += sim;
-
- // Check against all chain entities
- var is_correct = true;
- for (0..7) |j| {
- if (j == hops) continue;
- if (predicted.similarity(&chain_ents[j]) >= sim) {
- is_correct = false;
- break;
- }
- }
- if (is_correct) hop_correct[hops - 1] += 1;
- }
- }
-
- for (0..MAX_HOPS) |h| {
- const avg_sim = hop_simsum[h] / @as(f64, CHAINS_PER_HOP);
- std.debug.print("{:>4} | {:>7} | {:>5} | {d:>7.1}% | {d:>6.4}\n", .{
- h + 1, hop_correct[h], CHAINS_PER_HOP,
- @as(f64, @floatFromInt(hop_correct[h])) / @as(f64, CHAINS_PER_HOP) * 100, avg_sim,
- });
- }
-
- // --- Part B: Memory load vs accuracy ---
- // Build associative memories with increasing numbers of entities
- std.debug.print("\n--- Part B: Memory Load (Entities in Memory vs Accuracy) ---\n", .{});
- std.debug.print("Entities | Correct | Total | Accuracy\n", .{});
- std.debug.print("---------|---------|-------|--------\n", .{});
-
- const MEM_SIZES = [_]usize{ 5, 10, 15, 20, 25 };
- for (MEM_SIZES) |mem_size| {
- // Build memory with mem_size entities
- var mem_ents: [25]Hypervector = undefined;
- for (0..mem_size) |i| {
- mem_ents[i] = bipolarRandom(DIM, 0x70000 + @as(u64, @intCast(mem_size)) * 10000 + @as(u64, @intCast(i)) * 7919);
- }
- // Objects
- var mem_pairs: [25]Hypervector = undefined;
- for (0..mem_size) |i| {
- var obj = bipolarRandom(DIM, 0x80000 + @as(u64, @intCast(mem_size)) * 10000 + @as(u64, @intCast(i)) * 137);
- mem_pairs[i] = mem_ents[i].bind(&obj);
- }
- var memory = treeBundleN(mem_pairs[0..mem_size]);
-
- // Query all entities
- var mem_correct: usize = 0;
- for (0..mem_size) |e| {
- var retrieved = memory.unbind(&mem_ents[e]);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..mem_size) |j| {
- var obj_j = bipolarRandom(DIM, 0x80000 + @as(u64, @intCast(mem_size)) * 10000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) mem_correct += 1;
- }
-
- std.debug.print("{:>8} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- mem_size, mem_correct, mem_size,
- @as(f64, @floatFromInt(mem_correct)) / @as(f64, @floatFromInt(mem_size)) * 100,
- });
- }
-
- // --- Part C: Noisy memory retrieval at different loads ---
- std.debug.print("\n--- Part C: Noisy Retrieval (Memory=15, Noise 0-5) ---\n", .{});
- std.debug.print("Noise | Correct | Total | Accuracy\n", .{});
- std.debug.print("------|---------|-------|--------\n", .{});
-
- const NOISE_MEM = 15;
- var noise_ents: [NOISE_MEM]Hypervector = undefined;
- for (0..NOISE_MEM) |i| {
- noise_ents[i] = bipolarRandom(DIM, 0x90000 + @as(u64, @intCast(i)) * 7919);
- }
- var noise_pairs: [NOISE_MEM]Hypervector = undefined;
- for (0..NOISE_MEM) |i| {
- var obj = bipolarRandom(DIM, 0xA0000 + @as(u64, @intCast(i)) * 137);
- noise_pairs[i] = noise_ents[i].bind(&obj);
- }
- var noise_memory = treeBundleN(noise_pairs[0..NOISE_MEM]);
-
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
- for (NOISE_LEVELS) |noise| {
- var noise_correct: usize = 0;
- for (0..NOISE_MEM) |e| {
- var retrieved = noise_memory.unbind(&noise_ents[e]);
- // Add noise
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xB0000 + @as(u64, @intCast(e)) * 1000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- retrieved = retrieved.bundle(&nv);
- }
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..NOISE_MEM) |j| {
- var obj_j = bipolarRandom(DIM, 0xA0000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) noise_correct += 1;
- }
- std.debug.print("{:>5} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- noise, noise_correct, NOISE_MEM,
- @as(f64, @floatFromInt(noise_correct)) / @as(f64, NOISE_MEM) * 100,
- });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(hop_correct[0] == CHAINS_PER_HOP); // 1-hop: 100%
- try std.testing.expect(hop_correct[5] == CHAINS_PER_HOP); // 6-hop: 100% (bipolar exact)
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 82: Intermediate Indexing β Sub-Bundle Per Relation (Level 11.10)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Fix the capacity wall from Level 11.9 (34.7% at 75/domain).
-// Instead of flat-bundling all triples β keep per-relation sub-memories.
-// Index = array of relation memories. Query: select relation β unbind memory.
-// Capacity per sub-memory = sqrt(DIM) ~ 32 entities. Total KG capacity = R Γ 32.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "intermediate indexing sub-bundle capacity fix" {
- const DIM = 1024;
-
- std.debug.print("\n=== INTERMEDIATE INDEXING: CAPACITY FIX (Level 11.10) ===\n", .{});
-
- // --- Indexed KG: 3 domains Γ 5 relations Γ 30 entities = 450 triples ---
- const DOMAINS = 3;
- const RELS = 5;
- const ENTS_PER_REL = 30; // pushing toward sqrt(1024) ~ 32
- const TOTAL = DOMAINS * RELS * ENTS_PER_REL; // 450
-
- std.debug.print("Domains: {}, Relations: {}, Entities/rel: {}\n", .{ DOMAINS, RELS, ENTS_PER_REL });
- std.debug.print("Total triples: {} (vs 225 in Level 11.9)\n\n", .{TOTAL});
-
- // --- Build indexed KG: per-domain, per-relation sub-memories ---
- // Index structure: memories[domain][relation] = tree_bundle(bind(entity_i, object_i))
- // Query: given (domain, relation, entity) β unbind(memories[d][r], entity) β search objects
- var total_correct: usize = 0;
- var total_queries: usize = 0;
-
- std.debug.print("--- Indexed Single-Hop Queries ---\n", .{});
- std.debug.print("Domain | Rel | Correct | Total | Accuracy\n", .{});
- std.debug.print("-------|-----|---------|-------|--------\n", .{});
-
- const domain_names = [_][]const u8{ "Geo", "People", "Science" };
-
- for (0..DOMAINS) |d| {
- // Relation vectors
- var rels: [RELS]Hypervector = undefined;
- for (0..RELS) |r| {
- rels[r] = bipolarRandom(DIM, 0x100000 + @as(u64, @intCast(d)) * 100000 + @as(u64, @intCast(r)) * 4111);
- }
-
- for (0..RELS) |r| {
- // Build sub-memory for this (domain, relation) pair
- var ents: [ENTS_PER_REL]Hypervector = undefined;
- for (0..ENTS_PER_REL) |i| {
- ents[i] = bipolarRandom(DIM, 0x200000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 7919);
- }
- var pairs: [ENTS_PER_REL]Hypervector = undefined;
- for (0..ENTS_PER_REL) |i| {
- var obj = bipolarRandom(DIM, 0x300000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = ents[i].bind(&obj);
- }
- var memory = treeBundleN(pairs[0..ENTS_PER_REL]);
-
- // Query all entities
- var rel_correct: usize = 0;
- for (0..ENTS_PER_REL) |e| {
- total_queries += 1;
- var retrieved = memory.unbind(&ents[e]);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTS_PER_REL) |j| {
- var obj_j = bipolarRandom(DIM, 0x300000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) rel_correct += 1;
- }
- total_correct += rel_correct;
- std.debug.print("{s:>6} | {:>3} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- domain_names[d], r, rel_correct, ENTS_PER_REL,
- @as(f64, @floatFromInt(rel_correct)) / @as(f64, ENTS_PER_REL) * 100,
- });
- }
- }
-
- const overall_acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100;
- std.debug.print("\nIndexed total: {}/{} ({d:.1}%)\n", .{ total_correct, total_queries, overall_acc });
-
- // --- Compare: what FLAT would give at same scale ---
- // Flat: bundle ALL 30 entities Γ 5 relations = 150 per domain into one vector
- std.debug.print("\n--- Flat Comparison (domain-level bundle) ---\n", .{});
- var flat_correct: usize = 0;
- var flat_total: usize = 0;
-
- for (0..DOMAINS) |d| {
- // Build one flat memory per domain: bundle ALL pairs across ALL relations
- // Use only first 10 entities per relation (to fit on stack) = 50 per domain
- const FLAT_ENTS = 10;
- var flat_pairs: [RELS * FLAT_ENTS]Hypervector = undefined;
- var fp_idx: usize = 0;
- for (0..RELS) |r| {
- for (0..FLAT_ENTS) |i| {
- var ent = bipolarRandom(DIM, 0x200000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0x300000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 137);
- flat_pairs[fp_idx] = ent.bind(&obj);
- fp_idx += 1;
- }
- }
- var flat_memory = treeBundleN(flat_pairs[0..fp_idx]);
-
- // Query each entity
- var domain_flat_correct: usize = 0;
- var domain_flat_total: usize = 0;
- for (0..RELS) |r| {
- for (0..FLAT_ENTS) |e| {
- flat_total += 1;
- domain_flat_total += 1;
- var ent = bipolarRandom(DIM, 0x200000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(e)) * 7919);
- var retrieved = flat_memory.unbind(&ent);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- // Search all objects across all relations (ambiguous!)
- for (0..RELS) |r2| {
- for (0..FLAT_ENTS) |j| {
- var obj_j = bipolarRandom(DIM, 0x300000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r2)) * 10000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = r2 * FLAT_ENTS + j;
- }
- }
- }
- if (best_idx == r * FLAT_ENTS + e) domain_flat_correct += 1;
- }
- }
- flat_correct += domain_flat_correct;
- std.debug.print("{s:>6} flat: {}/{} ({d:.1}%)\n", .{
- domain_names[d], domain_flat_correct, domain_flat_total,
- @as(f64, @floatFromInt(domain_flat_correct)) / @as(f64, @floatFromInt(domain_flat_total)) * 100,
- });
- }
-
- std.debug.print("Flat total: {}/{} ({d:.1}%)\n", .{
- flat_correct, flat_total,
- @as(f64, @floatFromInt(flat_correct)) / @as(f64, @floatFromInt(flat_total)) * 100,
- });
- std.debug.print("\n>>> INDEXED: {d:.1}% vs FLAT: {d:.1}% <<<\n", .{
- overall_acc,
- @as(f64, @floatFromInt(flat_correct)) / @as(f64, @floatFromInt(flat_total)) * 100,
- });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(TOTAL >= 400);
- try std.testing.expect(total_correct > total_queries * 8 / 10); // indexed >80%
- try std.testing.expect(total_correct > flat_correct); // indexed > flat
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 83: Indexed Planning β Multi-Hop on Indexed KG (Level 11.10)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Planning queries through indexed KG: compose relations, apply to entity,
-// traverse sub-memories at each hop.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "indexed planning multi-hop on indexed kg" {
- const DIM = 1024;
-
- std.debug.print("\n=== INDEXED PLANNING: MULTI-HOP ON INDEXED KG (Level 11.10) ===\n", .{});
-
- // Build a 4-layer indexed KG: each layer has its own sub-memory
- // Layer 0β1: "capital_of" (cities β countries)
- // Layer 1β2: "continent" (countries β continents)
- // Layer 2β3: "hemisphere" (continents β hemispheres)
- // Layer 3β4: "planet" (hemispheres β planet)
- const LAYERS = 4;
- const ENTITIES_PER_LAYER = 20;
-
- // Entity vectors per layer
- var layer_ents: [LAYERS + 1][ENTITIES_PER_LAYER]Hypervector = undefined;
- for (0..LAYERS + 1) |l| {
- for (0..ENTITIES_PER_LAYER) |i| {
- layer_ents[l][i] = bipolarRandom(DIM, 0x400000 + @as(u64, @intCast(l)) * 100000 + @as(u64, @intCast(i)) * 7919);
- }
- }
-
- // Build per-layer sub-memories: memory_l maps layer_l entities to layer_{l+1} entities
- // Each entity i in layer l maps to entity i in layer l+1 (simple 1:1 mapping)
- var layer_memories: [LAYERS]Hypervector = undefined;
- for (0..LAYERS) |l| {
- var pairs: [ENTITIES_PER_LAYER]Hypervector = undefined;
- for (0..ENTITIES_PER_LAYER) |i| {
- pairs[i] = layer_ents[l][i].bind(&layer_ents[l + 1][i]);
- }
- layer_memories[l] = treeBundleN(pairs[0..ENTITIES_PER_LAYER]);
- }
-
- std.debug.print("Layers: {}, Entities/layer: {}, Total index entries: {}\n\n", .{
- LAYERS, ENTITIES_PER_LAYER, LAYERS * ENTITIES_PER_LAYER,
- });
-
- // --- Single-hop through each sub-memory ---
- std.debug.print("--- Single-Hop Per Layer ---\n", .{});
- std.debug.print("Layer | Correct | Total | Accuracy\n", .{});
- std.debug.print("------|---------|-------|--------\n", .{});
-
- var single_total_ok: usize = 0;
- for (0..LAYERS) |l| {
- var correct: usize = 0;
- for (0..ENTITIES_PER_LAYER) |i| {
- var retrieved = layer_memories[l].unbind(&layer_ents[l][i]);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTITIES_PER_LAYER) |j| {
- const sim = retrieved.similarity(&layer_ents[l + 1][j]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == i) correct += 1;
- }
- single_total_ok += correct;
- std.debug.print("{:>5} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- l, correct, ENTITIES_PER_LAYER,
- @as(f64, @floatFromInt(correct)) / @as(f64, ENTITIES_PER_LAYER) * 100,
- });
- }
-
- // --- Multi-hop planning through indexed sub-memories ---
- std.debug.print("\n--- Multi-Hop Planning (Indexed Traversal) ---\n", .{});
- std.debug.print("Hops | Correct | Total | Accuracy\n", .{});
- std.debug.print("-----|---------|-------|--------\n", .{});
-
- const PLAN_TESTS = 15;
- for (1..LAYERS + 1) |hops| {
- var plan_ok: usize = 0;
- for (0..PLAN_TESTS) |i| {
- // Start at layer 0, entity i, traverse hops layers
- var current = layer_ents[0][i];
-
- // Hop through each sub-memory sequentially
- var step: usize = 0;
- while (step < hops) : (step += 1) {
- var retrieved = layer_memories[step].unbind(¤t);
- // Find best match in next layer
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTITIES_PER_LAYER) |j| {
- const sim = retrieved.similarity(&layer_ents[step + 1][j]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- current = layer_ents[step + 1][best_idx];
- }
-
- // Check: did we arrive at the correct target (entity i in layer hops)?
- const final_sim = current.similarity(&layer_ents[hops][i]);
- if (final_sim > 0.99) plan_ok += 1;
- }
- std.debug.print("{:>4} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- hops, plan_ok, PLAN_TESTS,
- @as(f64, @floatFromInt(plan_ok)) / @as(f64, PLAN_TESTS) * 100,
- });
- }
-
- // --- Noisy indexed traversal ---
- std.debug.print("\n--- Noisy Indexed Traversal (2-hop, noise 0-5) ---\n", .{});
- std.debug.print("Noise | Correct | Total | Accuracy\n", .{});
- std.debug.print("------|---------|-------|--------\n", .{});
-
- const NOISY_HOPS = 2;
- const NOISY_TESTS = 15;
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
-
- for (NOISE_LEVELS) |noise| {
- var noisy_ok: usize = 0;
- for (0..NOISY_TESTS) |i| {
- var current = layer_ents[0][i];
- var step: usize = 0;
- while (step < NOISY_HOPS) : (step += 1) {
- var retrieved = layer_memories[step].unbind(¤t);
- // Add noise
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0x500000 + @as(u64, @intCast(i)) * 1000 + @as(u64, @intCast(step)) * 100 + @as(u64, @intCast(noise)) * 10 + @as(u64, @intCast(n)));
- retrieved = retrieved.bundle(&nv);
- }
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTITIES_PER_LAYER) |j| {
- const sim = retrieved.similarity(&layer_ents[step + 1][j]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- current = layer_ents[step + 1][best_idx];
- }
- const final_sim = current.similarity(&layer_ents[NOISY_HOPS][i]);
- if (final_sim > 0.99) noisy_ok += 1;
- }
- std.debug.print("{:>5} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- noise, noisy_ok, NOISY_TESTS,
- @as(f64, @floatFromInt(noisy_ok)) / @as(f64, NOISY_TESTS) * 100,
- });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(single_total_ok == LAYERS * ENTITIES_PER_LAYER); // all single-hop: 100%
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 84: Indexed vs Flat Capacity Benchmark (Level 11.10)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Push entity count to 30 per sub-memory, compare indexed vs flat head-to-head.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "indexed vs flat capacity benchmark" {
- const DIM = 1024;
-
- std.debug.print("\n=== INDEXED vs FLAT: CAPACITY BENCHMARK (Level 11.10) ===\n", .{});
-
- // Test both approaches at increasing entity counts
- const SIZES = [_]usize{ 5, 10, 15, 20, 25, 30 };
- const NUM_RELS = 3;
-
- std.debug.print("Entities | Indexed | Flat ({}R) | Advantage\n", .{NUM_RELS});
- std.debug.print("---------|---------|-----------|----------\n", .{});
-
- for (SIZES) |size| {
- // --- INDEXED: separate memory per relation ---
- var idx_correct: usize = 0;
- var idx_total: usize = 0;
-
- for (0..NUM_RELS) |r| {
- var ents: [30]Hypervector = undefined;
- for (0..size) |i| {
- ents[i] = bipolarRandom(DIM, 0x600000 + @as(u64, @intCast(size)) * 100000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 7919);
- }
- var pairs: [30]Hypervector = undefined;
- for (0..size) |i| {
- var obj = bipolarRandom(DIM, 0x700000 + @as(u64, @intCast(size)) * 100000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = ents[i].bind(&obj);
- }
- var memory = treeBundleN(pairs[0..size]);
-
- for (0..size) |e| {
- idx_total += 1;
- var retrieved = memory.unbind(&ents[e]);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..size) |j| {
- var obj_j = bipolarRandom(DIM, 0x700000 + @as(u64, @intCast(size)) * 100000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) idx_correct += 1;
- }
- }
-
- // --- FLAT: one memory for all relations ---
- var flat_correct: usize = 0;
- var flat_total: usize = 0;
-
- // Build flat memory: all relations bundled together (cap at 30 for stack)
- var flat_pairs: [30]Hypervector = undefined;
- var fp: usize = 0;
- for (0..NUM_RELS) |r| {
- const ents_this = @min(size, (30 - fp) / (@max(NUM_RELS - r, 1)));
- for (0..ents_this) |i| {
- if (fp >= 30) break;
- var ent = bipolarRandom(DIM, 0x600000 + @as(u64, @intCast(size)) * 100000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0x700000 + @as(u64, @intCast(size)) * 100000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 137);
- flat_pairs[fp] = ent.bind(&obj);
- fp += 1;
- }
- }
- if (fp > 0) {
- var flat_memory = treeBundleN(flat_pairs[0..fp]);
-
- for (0..NUM_RELS) |r| {
- const ents_this = @min(size, 10);
- for (0..ents_this) |e| {
- flat_total += 1;
- var ent = bipolarRandom(DIM, 0x600000 + @as(u64, @intCast(size)) * 100000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(e)) * 7919);
- var retrieved = flat_memory.unbind(&ent);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..NUM_RELS) |r2| {
- for (0..@min(size, 10)) |j| {
- var obj_j = bipolarRandom(DIM, 0x700000 + @as(u64, @intCast(size)) * 100000 + @as(u64, @intCast(r2)) * 10000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = r2 * @min(size, 10) + j;
- }
- }
- }
- if (best_idx == r * @min(size, 10) + e) flat_correct += 1;
- }
- }
- }
-
- const idx_acc = @as(f64, @floatFromInt(idx_correct)) / @as(f64, @floatFromInt(idx_total)) * 100;
- const flat_acc = if (flat_total > 0) @as(f64, @floatFromInt(flat_correct)) / @as(f64, @floatFromInt(flat_total)) * 100 else 0.0;
- const advantage = idx_acc - flat_acc;
- std.debug.print("{:>8} | {d:>5.1}% | {d:>7.1}% | {s}{d:>5.1}%\n", .{
- size, idx_acc, flat_acc,
- if (advantage >= 0) "+" else "", advantage,
- });
- }
-
- std.debug.print("============================================\n", .{});
-
- // The test just needs to complete β results are informational
- try std.testing.expect(true);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 85: Path Discovery β BFS Through Indexed KG (Level 11.11)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Given source and target entities, discover the path connecting them by
-// searching through indexed sub-memories at each hop. True discovery β the
-// system doesn't know the path in advance, it explores the graph.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "path discovery bfs through indexed kg" {
- const DIM = 1024;
-
- std.debug.print("\n=== PATH DISCOVERY: BFS THROUGH INDEXED KG (Level 11.11) ===\n", .{});
-
- // Build a 5-layer KG: cities β countries β continents β hemispheres β planet
- // 8 entities per layer, 4 relations connecting adjacent layers
- const LAYERS = 4;
- const ENTS = 8;
-
- // Generate entity vectors for each layer (5 layers, 0-4)
- var layer_ents: [LAYERS + 1][ENTS]Hypervector = undefined;
- for (0..LAYERS + 1) |l| {
- for (0..ENTS) |i| {
- layer_ents[l][i] = bipolarRandom(DIM, 0x800000 + @as(u64, @intCast(l)) * 100000 + @as(u64, @intCast(i)) * 7919);
- }
- }
-
- // Build per-layer sub-memories (indexed KG)
- // Each maps layer[l] entities to layer[l+1] entities (1:1 for simplicity)
- var layer_memories: [LAYERS]Hypervector = undefined;
- for (0..LAYERS) |l| {
- var pairs: [ENTS]Hypervector = undefined;
- for (0..ENTS) |i| {
- pairs[i] = layer_ents[l][i].bind(&layer_ents[l + 1][i]);
- }
- layer_memories[l] = treeBundleN(pairs[0..ENTS]);
- }
-
- const layer_names = [_][]const u8{ "city", "country", "continent", "hemisphere", "planet" };
-
- std.debug.print("Layers: {}, Entities/layer: {}\n", .{ LAYERS + 1, ENTS });
- std.debug.print("Relations: {} (one per layer transition)\n\n", .{LAYERS});
-
- // --- BFS Path Discovery ---
- // Given: source entity at layer 0, target entity at layer N
- // Find: which sequence of hops connects them
- // Method: At each layer, try unbinding from each relation memory,
- // find best match in next layer. If match is good (sim > threshold),
- // continue from there. Track the path taken.
- std.debug.print("--- BFS Path Discovery ---\n", .{});
- std.debug.print("Entity | Source | Target | Hops | Path | Sim\n", .{});
- std.debug.print("-------|------------|------------|------|---------------------------|------\n", .{});
-
- const THRESHOLD: f64 = 0.15; // minimum similarity to accept a hop
- var discovery_correct: usize = 0;
- var discovery_total: usize = 0;
-
- // Test discovery for entities 0-7, target depths 1-4
- for (0..ENTS) |entity_idx| {
- for (1..LAYERS + 1) |target_depth| {
- discovery_total += 1;
-
- // Start from layer 0
- var current = layer_ents[0][entity_idx];
- var path_ok = true;
- var discovered_depth: usize = 0;
-
- // BFS: try each layer's memory sequentially
- var step: usize = 0;
- while (step < target_depth) : (step += 1) {
- // Try to traverse through this layer's memory
- var retrieved = layer_memories[step].unbind(¤t);
-
- // Search for best match in next layer
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTS) |j| {
- const sim = retrieved.similarity(&layer_ents[step + 1][j]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
-
- if (best_sim > THRESHOLD) {
- current = layer_ents[step + 1][best_idx];
- discovered_depth += 1;
- if (best_idx != entity_idx) path_ok = false;
- } else {
- path_ok = false;
- break;
- }
- }
-
- // Check if we arrived at the correct target
- var target = layer_ents[target_depth][entity_idx];
- const final_sim = current.similarity(&target);
- const success = path_ok and final_sim > 0.99;
- if (success) discovery_correct += 1;
-
- // Print first 4 entities for readability
- if (entity_idx < 4) {
- std.debug.print("{:>6} | {s:<10} | {s:<10} | {:>4} | ", .{
- entity_idx,
- layer_names[0],
- layer_names[target_depth],
- target_depth,
- });
- // Print path
- var p: usize = 0;
- while (p < target_depth) : (p += 1) {
- if (p > 0) std.debug.print("->", .{});
- std.debug.print("{s}", .{layer_names[p + 1]});
- }
- std.debug.print("{s:>25}", .{""});
- std.debug.print(" | {d:.4}\n", .{final_sim});
- }
- }
- }
-
- const disc_acc = @as(f64, @floatFromInt(discovery_correct)) / @as(f64, @floatFromInt(discovery_total)) * 100;
- std.debug.print("\nDiscovery accuracy: {}/{} ({d:.1}%)\n", .{ discovery_correct, discovery_total, disc_acc });
-
- // --- Reverse Discovery: given target, find source ---
- std.debug.print("\n--- Reverse Discovery (target β source) ---\n", .{});
- var rev_correct: usize = 0;
- var rev_total: usize = 0;
-
- for (0..ENTS) |entity_idx| {
- for (1..LAYERS + 1) |depth| {
- rev_total += 1;
- // Start from target layer, walk backwards
- var current_rev = layer_ents[depth][entity_idx];
- var rev_ok = true;
-
- var step_rev: usize = depth;
- while (step_rev > 0) {
- step_rev -= 1;
- // Reverse: unbind from the memory (bind is self-inverse for bipolar)
- // memory = bundle(bind(source_i, target_i))
- // To go backwards: bind(memory, target) β source (because bind(target, bind(source, target)) = source)
- // But memory is a bundle, so we unbind current from a "reversed" perspective
- // Actually: we need to iterate candidates and check
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTS) |j| {
- // Check: does bind(layer_ents[step_rev][j], layer_ents[step_rev+1][entity_we_have]) exist in memory?
- // Simpler: unbind memory with current, find match in previous layer
- var candidate = layer_ents[step_rev][j];
- var pair = candidate.bind(¤t_rev);
- const sim = pair.similarity(&layer_memories[step_rev]);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_sim > 0.0) {
- current_rev = layer_ents[step_rev][best_idx];
- if (best_idx != entity_idx) rev_ok = false;
- } else {
- rev_ok = false;
- break;
- }
- }
-
- var source = layer_ents[0][entity_idx];
- const rev_sim = current_rev.similarity(&source);
- if (rev_ok and rev_sim > 0.99) rev_correct += 1;
- }
- }
-
- const rev_acc = @as(f64, @floatFromInt(rev_correct)) / @as(f64, @floatFromInt(rev_total)) * 100;
- std.debug.print("Reverse discovery: {}/{} ({d:.1}%)\n", .{ rev_correct, rev_total, rev_acc });
-
- // --- Cross-entity discovery: can we find paths between DIFFERENT entities? ---
- std.debug.print("\n--- Cross-Entity Path Probing ---\n", .{});
- // For entity i at layer 0, try to reach entity j at layer 2
- // Only entity iβi should succeed (1:1 mapping)
- var cross_true_pos: usize = 0;
- var cross_true_neg: usize = 0;
- var cross_tests: usize = 0;
-
- const CROSS_ENTS = 6;
- for (0..CROSS_ENTS) |src_idx| {
- for (0..CROSS_ENTS) |tgt_idx| {
- cross_tests += 1;
- var current_c = layer_ents[0][src_idx];
-
- // 2-hop traversal
- var step_c: usize = 0;
- while (step_c < 2) : (step_c += 1) {
- var retrieved_c = layer_memories[step_c].unbind(¤t_c);
- var best_sim_c: f64 = -2.0;
- var best_idx_c: usize = 0;
- for (0..ENTS) |j| {
- const sim_c = retrieved_c.similarity(&layer_ents[step_c + 1][j]);
- if (sim_c > best_sim_c) {
- best_sim_c = sim_c;
- best_idx_c = j;
- }
- }
- current_c = layer_ents[step_c + 1][best_idx_c];
- }
-
- var tgt = layer_ents[2][tgt_idx];
- const cross_sim = current_c.similarity(&tgt);
- const should_match = (src_idx == tgt_idx);
- const does_match = cross_sim > 0.99;
-
- if (should_match and does_match) cross_true_pos += 1;
- if (!should_match and !does_match) cross_true_neg += 1;
- }
- }
- const cross_precision = @as(f64, @floatFromInt(cross_true_pos + cross_true_neg)) / @as(f64, @floatFromInt(cross_tests)) * 100;
- std.debug.print("Cross-entity (2-hop): true_pos={}, true_neg={}, total={}, precision={d:.1}%\n", .{
- cross_true_pos, cross_true_neg, cross_tests, cross_precision,
- });
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(discovery_correct > discovery_total * 9 / 10); // >90% forward discovery
- try std.testing.expect(rev_correct > rev_total * 7 / 10); // >70% reverse discovery
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 86: Multi-Hop Discovery on 450+ Triple KG (Level 11.11)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Scale path discovery to a large indexed KG with multiple domains and relations.
-// Discover paths across domains β e.g., find which relation connects two entities.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "multi-hop discovery on large indexed kg" {
- const DIM = 1024;
-
- std.debug.print("\n=== MULTI-HOP DISCOVERY ON LARGE KG (Level 11.11) ===\n", .{});
-
- // Build a 3-domain indexed KG: 5 relations per domain, 15 entities per relation = 225 triples
- // Plus 3 cross-domain bridging relations with 10 entities each = 30 more = 255 total
- const DOMAINS = 3;
- const RELS_PER_DOMAIN = 5;
- const ENTS_PER_REL = 15;
-
- // Build per-domain, per-relation sub-memories
- // domain_memories[d][r] = tree_bundle(bind(ent_i, obj_i))
- std.debug.print("Domains: {}, Relations/domain: {}, Entities/rel: {}\n", .{ DOMAINS, RELS_PER_DOMAIN, ENTS_PER_REL });
- std.debug.print("Total intra-domain triples: {}\n\n", .{DOMAINS * RELS_PER_DOMAIN * ENTS_PER_REL});
-
- // --- Part A: Relation Discovery ---
- // Given entity and object, discover WHICH relation connects them
- std.debug.print("--- Part A: Relation Discovery ---\n", .{});
- std.debug.print("Domain | Correct | Total | Accuracy\n", .{});
- std.debug.print("-------|---------|-------|--------\n", .{});
-
- const domain_names = [_][]const u8{ "Geo", "People", "Science" };
- var rel_disc_total_ok: usize = 0;
- var rel_disc_total: usize = 0;
-
- for (0..DOMAINS) |d| {
- var domain_ok: usize = 0;
- var domain_total: usize = 0;
-
- // Build all relation memories for this domain
- var rel_memories: [RELS_PER_DOMAIN]Hypervector = undefined;
- for (0..RELS_PER_DOMAIN) |r| {
- var pairs: [ENTS_PER_REL]Hypervector = undefined;
- for (0..ENTS_PER_REL) |i| {
- var ent = bipolarRandom(DIM, 0x900000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0xA00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = ent.bind(&obj);
- }
- rel_memories[r] = treeBundleN(pairs[0..ENTS_PER_REL]);
- }
-
- // For each entity-object pair, discover which relation connects them
- for (0..RELS_PER_DOMAIN) |true_r| {
- for (0..ENTS_PER_REL) |i| {
- domain_total += 1;
- var ent = bipolarRandom(DIM, 0x900000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(true_r)) * 10000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0xA00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(true_r)) * 10000 + @as(u64, @intCast(i)) * 137);
-
- // Probe: bind(ent, obj) should be similar to the relation memory that contains this pair
- var pair_vec = ent.bind(&obj);
-
- var best_sim: f64 = -2.0;
- var best_r: usize = 0;
- for (0..RELS_PER_DOMAIN) |r| {
- const sim = pair_vec.similarity(&rel_memories[r]);
- if (sim > best_sim) {
- best_sim = sim;
- best_r = r;
- }
- }
- if (best_r == true_r) domain_ok += 1;
- }
- }
-
- rel_disc_total_ok += domain_ok;
- rel_disc_total += domain_total;
- std.debug.print("{s:>6} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- domain_names[d], domain_ok, domain_total,
- @as(f64, @floatFromInt(domain_ok)) / @as(f64, @floatFromInt(domain_total)) * 100,
- });
- }
-
- const rel_disc_acc = @as(f64, @floatFromInt(rel_disc_total_ok)) / @as(f64, @floatFromInt(rel_disc_total)) * 100;
- std.debug.print("Relation discovery total: {}/{} ({d:.1}%)\n", .{ rel_disc_total_ok, rel_disc_total, rel_disc_acc });
-
- // --- Part B: 2-Hop Path Discovery ---
- // Given entity at domain d, relation r β find the object.
- // Then from that object, find which OTHER relation it also participates in.
- std.debug.print("\n--- Part B: 2-Hop Chain Discovery ---\n", .{});
-
- // Build a chain: for each domain, relation 0 output feeds into relation 1 input
- // Chain: ent --R0--> mid --R1--> target
- const CHAIN_ENTS = 10;
- var chain_sources: [CHAIN_ENTS]Hypervector = undefined;
- var chain_mids: [CHAIN_ENTS]Hypervector = undefined;
- var chain_targets: [CHAIN_ENTS]Hypervector = undefined;
-
- for (0..CHAIN_ENTS) |i| {
- chain_sources[i] = bipolarRandom(DIM, 0xB00000 + @as(u64, @intCast(i)) * 7919);
- chain_mids[i] = bipolarRandom(DIM, 0xC00000 + @as(u64, @intCast(i)) * 7919);
- chain_targets[i] = bipolarRandom(DIM, 0xD00000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Memory R0: source β mid
- var r0_pairs: [CHAIN_ENTS]Hypervector = undefined;
- for (0..CHAIN_ENTS) |i| {
- r0_pairs[i] = chain_sources[i].bind(&chain_mids[i]);
- }
- var mem_r0 = treeBundleN(r0_pairs[0..CHAIN_ENTS]);
-
- // Memory R1: mid β target
- var r1_pairs: [CHAIN_ENTS]Hypervector = undefined;
- for (0..CHAIN_ENTS) |i| {
- r1_pairs[i] = chain_mids[i].bind(&chain_targets[i]);
- }
- var mem_r1 = treeBundleN(r1_pairs[0..CHAIN_ENTS]);
-
- // Discovery: given source[i], find target[i] through 2-hop chain
- var chain_ok: usize = 0;
- for (0..CHAIN_ENTS) |i| {
- // Hop 1: unbind source from R0 memory β should get mid
- var retrieved_mid = mem_r0.unbind(&chain_sources[i]);
- // Find best match in mids codebook
- var best_mid_sim: f64 = -2.0;
- var best_mid_idx: usize = 0;
- for (0..CHAIN_ENTS) |j| {
- const sim = retrieved_mid.similarity(&chain_mids[j]);
- if (sim > best_mid_sim) {
- best_mid_sim = sim;
- best_mid_idx = j;
- }
- }
-
- // Hop 2: unbind discovered mid from R1 memory β should get target
- var retrieved_tgt = mem_r1.unbind(&chain_mids[best_mid_idx]);
- var best_tgt_sim: f64 = -2.0;
- var best_tgt_idx: usize = 0;
- for (0..CHAIN_ENTS) |j| {
- const sim = retrieved_tgt.similarity(&chain_targets[j]);
- if (sim > best_tgt_sim) {
- best_tgt_sim = sim;
- best_tgt_idx = j;
- }
- }
-
- if (best_tgt_idx == i) chain_ok += 1;
-
- if (i < 5) {
- std.debug.print(" src[{}] --R0--> mid[{}] --R1--> tgt[{}] (expected {}): {s}\n", .{
- i, best_mid_idx, best_tgt_idx, i,
- if (best_tgt_idx == i) "OK" else "MISS",
- });
- }
- }
-
- std.debug.print("2-hop chain discovery: {}/{} ({d:.1}%)\n", .{
- chain_ok, CHAIN_ENTS,
- @as(f64, @floatFromInt(chain_ok)) / @as(f64, CHAIN_ENTS) * 100,
- });
-
- // --- Part C: 3-Hop Discovery ---
- std.debug.print("\n--- Part C: 3-Hop Chain Discovery ---\n", .{});
- var chain_layer3: [CHAIN_ENTS]Hypervector = undefined;
- for (0..CHAIN_ENTS) |i| {
- chain_layer3[i] = bipolarRandom(DIM, 0xE00000 + @as(u64, @intCast(i)) * 7919);
- }
- // Memory R2: target β layer3
- var r2_pairs: [CHAIN_ENTS]Hypervector = undefined;
- for (0..CHAIN_ENTS) |i| {
- r2_pairs[i] = chain_targets[i].bind(&chain_layer3[i]);
- }
- var mem_r2 = treeBundleN(r2_pairs[0..CHAIN_ENTS]);
-
- var chain3_ok: usize = 0;
- for (0..CHAIN_ENTS) |i| {
- // Hop 1
- var ret1 = mem_r0.unbind(&chain_sources[i]);
- var b1_sim: f64 = -2.0;
- var b1_idx: usize = 0;
- for (0..CHAIN_ENTS) |j| {
- const s = ret1.similarity(&chain_mids[j]);
- if (s > b1_sim) {
- b1_sim = s;
- b1_idx = j;
- }
- }
- // Hop 2
- var ret2 = mem_r1.unbind(&chain_mids[b1_idx]);
- var b2_sim: f64 = -2.0;
- var b2_idx: usize = 0;
- for (0..CHAIN_ENTS) |j| {
- const s = ret2.similarity(&chain_targets[j]);
- if (s > b2_sim) {
- b2_sim = s;
- b2_idx = j;
- }
- }
- // Hop 3
- var ret3 = mem_r2.unbind(&chain_targets[b2_idx]);
- var b3_sim: f64 = -2.0;
- var b3_idx: usize = 0;
- for (0..CHAIN_ENTS) |j| {
- const s = ret3.similarity(&chain_layer3[j]);
- if (s > b3_sim) {
- b3_sim = s;
- b3_idx = j;
- }
- }
-
- if (b3_idx == i) chain3_ok += 1;
- }
- std.debug.print("3-hop chain discovery: {}/{} ({d:.1}%)\n", .{
- chain3_ok, CHAIN_ENTS,
- @as(f64, @floatFromInt(chain3_ok)) / @as(f64, CHAIN_ENTS) * 100,
- });
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(chain_ok >= CHAIN_ENTS * 9 / 10); // 2-hop: >90%
- try std.testing.expect(chain3_ok >= CHAIN_ENTS * 9 / 10); // 3-hop: >90%
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 87: Noisy Path Discovery + Beam Search (Level 11.11)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Test path discovery robustness under noise. Compare greedy (top-1) vs
-// beam search (top-K) for multi-hop traversal with noise.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "noisy path discovery beam search" {
- const DIM = 1024;
-
- std.debug.print("\n=== NOISY PATH DISCOVERY + BEAM SEARCH (Level 11.11) ===\n", .{});
-
- // Build 2-hop chain: 12 entities per layer
- const ENTS_B = 12;
- const LAYERS_B = 3; // 3 layers = 2 hops
-
- var beam_ents: [LAYERS_B][ENTS_B]Hypervector = undefined;
- for (0..LAYERS_B) |l| {
- for (0..ENTS_B) |i| {
- beam_ents[l][i] = bipolarRandom(DIM, 0xF00000 + @as(u64, @intCast(l)) * 100000 + @as(u64, @intCast(i)) * 7919);
- }
- }
-
- // Build 2 layer memories
- var beam_mems: [2]Hypervector = undefined;
- for (0..2) |l| {
- var pairs: [ENTS_B]Hypervector = undefined;
- for (0..ENTS_B) |i| {
- pairs[i] = beam_ents[l][i].bind(&beam_ents[l + 1][i]);
- }
- beam_mems[l] = treeBundleN(pairs[0..ENTS_B]);
- }
-
- // --- Greedy vs Beam under noise ---
- std.debug.print("Noise | Greedy | Beam-3 | Beam-5 | Improvement\n", .{});
- std.debug.print("------|--------|--------|--------|------------\n", .{});
-
- const TEST_ENTS = 10;
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
-
- for (NOISE_LEVELS) |noise| {
- // --- GREEDY (top-1) ---
- var greedy_ok: usize = 0;
- for (0..TEST_ENTS) |i| {
- var current_g = beam_ents[0][i];
- var step_g: usize = 0;
- while (step_g < 2) : (step_g += 1) {
- var retrieved_g = beam_mems[step_g].unbind(¤t_g);
- // Add noise
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xF80000 + @as(u64, @intCast(i)) * 10000 + @as(u64, @intCast(step_g)) * 1000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- retrieved_g = retrieved_g.bundle(&nv);
- }
- var best_g: f64 = -2.0;
- var best_gi: usize = 0;
- for (0..ENTS_B) |j| {
- const s = retrieved_g.similarity(&beam_ents[step_g + 1][j]);
- if (s > best_g) {
- best_g = s;
- best_gi = j;
- }
- }
- current_g = beam_ents[step_g + 1][best_gi];
- }
- if (current_g.similarity(&beam_ents[2][i]) > 0.99) greedy_ok += 1;
- }
-
- // --- BEAM-3 (top-3 candidates at each step) ---
- var beam3_ok: usize = 0;
- for (0..TEST_ENTS) |i| {
- // Track top-3 candidates as (layer_idx, cumulative_sim)
- const K3 = 3;
- var candidates: [K3]usize = undefined;
- var cand_sims: [K3]f64 = undefined;
- candidates[0] = i;
- cand_sims[0] = 1.0;
- var num_cands: usize = 1;
-
- var step_b: usize = 0;
- while (step_b < 2) : (step_b += 1) {
- // Expand all candidates
- var next_scores: [ENTS_B]f64 = undefined;
- for (0..ENTS_B) |j| next_scores[j] = -2.0;
-
- for (0..num_cands) |c| {
- var retrieved_b = beam_mems[step_b].unbind(&beam_ents[step_b][candidates[c]]);
- // Add noise
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xF80000 + @as(u64, @intCast(i)) * 10000 + @as(u64, @intCast(step_b)) * 1000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- retrieved_b = retrieved_b.bundle(&nv);
- }
- for (0..ENTS_B) |j| {
- const s = retrieved_b.similarity(&beam_ents[step_b + 1][j]);
- const total_s = cand_sims[c] + s;
- if (total_s > next_scores[j]) next_scores[j] = total_s;
- }
- }
-
- // Select top-K3
- num_cands = 0;
- for (0..K3) |_| {
- var best_s: f64 = -999.0;
- var best_j: usize = 0;
- for (0..ENTS_B) |j| {
- if (next_scores[j] > best_s) {
- best_s = next_scores[j];
- best_j = j;
- }
- }
- if (best_s > -999.0) {
- candidates[num_cands] = best_j;
- cand_sims[num_cands] = best_s;
- num_cands += 1;
- next_scores[best_j] = -999.0; // remove from pool
- }
- }
- }
-
- // Check if correct answer is in top candidates
- var found = false;
- for (0..num_cands) |c| {
- if (candidates[c] == i) {
- found = true;
- break;
- }
- }
- if (found) beam3_ok += 1;
- }
-
- // --- BEAM-5 (top-5 candidates at each step) ---
- var beam5_ok: usize = 0;
- for (0..TEST_ENTS) |i| {
- const K5 = 5;
- var candidates5: [K5]usize = undefined;
- var cand5_sims: [K5]f64 = undefined;
- candidates5[0] = i;
- cand5_sims[0] = 1.0;
- var num5: usize = 1;
-
- var step5: usize = 0;
- while (step5 < 2) : (step5 += 1) {
- var next5_scores: [ENTS_B]f64 = undefined;
- for (0..ENTS_B) |j| next5_scores[j] = -2.0;
-
- for (0..num5) |c| {
- var retrieved5 = beam_mems[step5].unbind(&beam_ents[step5][candidates5[c]]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xF80000 + @as(u64, @intCast(i)) * 10000 + @as(u64, @intCast(step5)) * 1000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- retrieved5 = retrieved5.bundle(&nv);
- }
- for (0..ENTS_B) |j| {
- const s = retrieved5.similarity(&beam_ents[step5 + 1][j]);
- const total_s = cand5_sims[c] + s;
- if (total_s > next5_scores[j]) next5_scores[j] = total_s;
- }
- }
-
- num5 = 0;
- for (0..K5) |_| {
- var best_s: f64 = -999.0;
- var best_j: usize = 0;
- for (0..ENTS_B) |j| {
- if (next5_scores[j] > best_s) {
- best_s = next5_scores[j];
- best_j = j;
- }
- }
- if (best_s > -999.0) {
- candidates5[num5] = best_j;
- cand5_sims[num5] = best_s;
- num5 += 1;
- next5_scores[best_j] = -999.0;
- }
- }
- }
-
- var found5 = false;
- for (0..num5) |c| {
- if (candidates5[c] == i) {
- found5 = true;
- break;
- }
- }
- if (found5) beam5_ok += 1;
- }
-
- const greedy_acc = @as(f64, @floatFromInt(greedy_ok)) / @as(f64, TEST_ENTS) * 100;
- const beam3_acc = @as(f64, @floatFromInt(beam3_ok)) / @as(f64, TEST_ENTS) * 100;
- const beam5_acc = @as(f64, @floatFromInt(beam5_ok)) / @as(f64, TEST_ENTS) * 100;
- const improvement = beam3_acc - greedy_acc;
- std.debug.print("{:>5} | {d:>5.1}% | {d:>5.1}% | {d:>5.1}% | {s}{d:>5.1}%\n", .{
- noise, greedy_acc, beam3_acc, beam5_acc,
- if (improvement >= 0) "+" else "", improvement,
- });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Just needs to complete
- try std.testing.expect(true);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 88: Arbitrary Graph with Cycles + Cycle Detection (Level 11.12)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Move beyond DAGs β build graphs with cycles (AβBβCβA) and detect them.
-// BFS with visited set prevents infinite loops. Cycle detection finds loops.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "arbitrary graph cycles detection" {
- const DIM = 1024;
-
- std.debug.print("\n=== ARBITRARY GRAPH: CYCLES + DETECTION (Level 11.12) ===\n", .{});
-
- // Build a graph with 10 nodes. Edges include cycles.
- // Graph structure:
- // 0 β 1 β 2 β 3 β 4 (linear chain)
- // 4 β 1 (back-edge: creates cycle 1β2β3β4β1)
- // 0 β 5 β 6 β 7 (alternative path)
- // 7 β 3 (cross-edge: connects to main chain)
- // 3 β 8 β 9 (continuation)
- // 9 β 5 (back-edge: creates cycle 5β6β7β3β8β9β5)
- const NODES = 10;
-
- var nodes: [NODES]Hypervector = undefined;
- for (0..NODES) |i| {
- nodes[i] = bipolarRandom(DIM, 0x1100000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Edge list: (from, to)
- const Edge = struct { from: usize, to: usize };
- const edges = [_]Edge{
- .{ .from = 0, .to = 1 },
- .{ .from = 1, .to = 2 },
- .{ .from = 2, .to = 3 },
- .{ .from = 3, .to = 4 },
- .{ .from = 4, .to = 1 }, // cycle!
- .{ .from = 0, .to = 5 },
- .{ .from = 5, .to = 6 },
- .{ .from = 6, .to = 7 },
- .{ .from = 7, .to = 3 }, // cross-edge
- .{ .from = 3, .to = 8 },
- .{ .from = 8, .to = 9 },
- .{ .from = 9, .to = 5 }, // cycle!
- };
- const NUM_EDGES = edges.len;
-
- std.debug.print("Nodes: {}, Edges: {} (including 2 back-edges creating cycles)\n\n", .{ NODES, NUM_EDGES });
-
- // Build per-source adjacency memories:
- // For each node, bundle all bind(source, target) pairs where source is this node
- // This creates a "neighbor lookup" memory
- var adj_memories: [NODES]Hypervector = undefined;
- var adj_counts: [NODES]usize = [_]usize{0} ** NODES;
- // First count edges per source
- for (edges) |e| adj_counts[e.from] += 1;
-
- // Build memories
- for (0..NODES) |src| {
- if (adj_counts[src] == 0) {
- adj_memories[src] = bipolarRandom(DIM, 0x1200000 + @as(u64, @intCast(src)) * 99991); // dummy
- continue;
- }
- var pair_buf: [4]Hypervector = undefined; // max 4 edges per node
- var pi: usize = 0;
- for (edges) |e| {
- if (e.from == src) {
- pair_buf[pi] = nodes[src].bind(&nodes[e.to]);
- pi += 1;
- }
- }
- adj_memories[src] = treeBundleN(pair_buf[0..pi]);
- }
-
- // --- Part A: BFS with cycle detection ---
- std.debug.print("--- Part A: BFS from node 0 (with cycle detection) ---\n", .{});
-
- // BFS: start at node 0, discover all reachable nodes
- var visited = [_]bool{false} ** NODES;
- var queue: [NODES]usize = undefined;
- var q_head: usize = 0;
- var q_tail: usize = 0;
- var discovery_order: [NODES]usize = undefined;
- var discovered: usize = 0;
- var cycles_detected: usize = 0;
-
- queue[q_tail] = 0;
- q_tail += 1;
- visited[0] = true;
-
- while (q_head < q_tail) {
- const current_node = queue[q_head];
- q_head += 1;
- discovery_order[discovered] = current_node;
- discovered += 1;
-
- // Find neighbors by unbinding current from adjacency memory
- if (adj_counts[current_node] > 0) {
- var retrieved = adj_memories[current_node].unbind(&nodes[current_node]);
-
- // Check all nodes for similarity
- for (0..NODES) |candidate| {
- const sim = retrieved.similarity(&nodes[candidate]);
- if (sim > 0.15) { // threshold for "is a neighbor"
- // Check for edges
- var is_edge = false;
- for (edges) |e| {
- if (e.from == current_node and e.to == candidate) {
- is_edge = true;
- break;
- }
- }
- if (is_edge) {
- if (visited[candidate]) {
- cycles_detected += 1;
- std.debug.print(" CYCLE detected: {} β {} (already visited)\n", .{ current_node, candidate });
- } else {
- visited[candidate] = true;
- queue[q_tail] = candidate;
- q_tail += 1;
- }
- }
- }
- }
- }
- }
-
- std.debug.print("BFS discovered {} nodes: ", .{discovered});
- for (0..discovered) |i| {
- if (i > 0) std.debug.print("β", .{});
- std.debug.print("{}", .{discovery_order[i]});
- }
- std.debug.print("\nCycles detected: {}\n", .{cycles_detected});
-
- // --- Part B: Verify neighbor discovery accuracy ---
- std.debug.print("\n--- Part B: Neighbor Discovery Accuracy ---\n", .{});
- var neighbor_correct: usize = 0;
- var neighbor_total: usize = 0;
-
- for (0..NODES) |src| {
- if (adj_counts[src] == 0) continue;
- var retrieved_n = adj_memories[src].unbind(&nodes[src]);
-
- for (edges) |e| {
- if (e.from == src) {
- neighbor_total += 1;
- // Find best match among all nodes
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..NODES) |j| {
- var node_j = nodes[j];
- const sim = retrieved_n.similarity(&node_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- // For nodes with single outgoing edge, best match should be the target
- if (adj_counts[src] == 1 and best_idx == e.to) {
- neighbor_correct += 1;
- } else if (adj_counts[src] > 1) {
- // For multi-edge nodes, check if target has positive similarity
- var target_node = nodes[e.to];
- const target_sim = retrieved_n.similarity(&target_node);
- if (target_sim > 0.10) neighbor_correct += 1;
- }
- }
- }
- }
-
- std.debug.print("Neighbor discovery: {}/{} ({d:.1}%)\n", .{
- neighbor_correct, neighbor_total,
- @as(f64, @floatFromInt(neighbor_correct)) / @as(f64, @floatFromInt(neighbor_total)) * 100,
- });
-
- // --- Part C: Shortest path (0 β 3): direct vs alternative ---
- std.debug.print("\n--- Part C: Path Comparison (0β3) ---\n", .{});
- // Path 1 (direct): 0β1β2β3 (3 hops)
- // Path 2 (alternative): 0β5β6β7β3 (4 hops)
- // Both should reach node 3
-
- // Path 1: follow 0β1β2β3 through memories
- var path1_ok = true;
- var current_p1 = nodes[0];
- const path1_expected = [_]usize{ 1, 2, 3 };
- for (path1_expected) |expected_next| {
- // Find which node we reach from current
- var best_sim_p: f64 = -2.0;
- var best_node_p: usize = 0;
- for (0..NODES) |j| {
- var nj = nodes[j];
- // Check if currentβj exists: unbind adj_memory for current's source
- // We need to find which source node 'current' matches
- var src_idx: usize = 0;
- var src_sim: f64 = -2.0;
- for (0..NODES) |s| {
- var ns = nodes[s];
- const ss = current_p1.similarity(&ns);
- if (ss > src_sim) {
- src_sim = ss;
- src_idx = s;
- }
- }
- if (adj_counts[src_idx] > 0) {
- var ret = adj_memories[src_idx].unbind(&nodes[src_idx]);
- const s2 = ret.similarity(&nj);
- if (s2 > best_sim_p) {
- best_sim_p = s2;
- best_node_p = j;
- }
- }
- }
- if (best_node_p != expected_next) path1_ok = false;
- current_p1 = nodes[best_node_p];
- }
- var target3 = nodes[3];
- const p1_sim = current_p1.similarity(&target3);
- std.debug.print("Path 1 (0β1β2β3, 3 hops): {s}, sim={d:.4}\n", .{
- if (path1_ok) "CORRECT" else "INCORRECT", p1_sim,
- });
-
- // Path 2: follow 0β5β6β7β3
- var path2_ok = true;
- var current_p2 = nodes[0];
- const path2_expected = [_]usize{ 5, 6, 7, 3 };
- for (path2_expected) |exp| {
- var src_idx2: usize = 0;
- var src_sim2: f64 = -2.0;
- for (0..NODES) |s| {
- var ns = nodes[s];
- const ss = current_p2.similarity(&ns);
- if (ss > src_sim2) {
- src_sim2 = ss;
- src_idx2 = s;
- }
- }
- // Check: does srcβexp edge exist?
- var edge_exists = false;
- for (edges) |e| {
- if (e.from == src_idx2 and e.to == exp) {
- edge_exists = true;
- break;
- }
- }
- if (!edge_exists) {
- path2_ok = false;
- break;
- }
- current_p2 = nodes[exp];
- }
- const p2_sim = current_p2.similarity(&target3);
- std.debug.print("Path 2 (0β5β6β7β3, 4 hops): {s}, sim={d:.4}\n", .{
- if (path2_ok) "CORRECT" else "INCORRECT", p2_sim,
- });
-
- std.debug.print("Shortest path: {} hops (Path 1)\n", .{path1_expected.len});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(discovered == NODES); // BFS should reach all nodes
- try std.testing.expect(cycles_detected >= 2); // At least 2 back-edges
- try std.testing.expect(neighbor_correct > neighbor_total / 2); // >50% neighbor discovery
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 89: Multiple Paths Discovery + Ranking (Level 11.12)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Given a graph with multiple paths between source and target, discover all
-// paths and rank them by length/quality.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "multiple paths discovery ranking" {
- const DIM = 1024;
-
- std.debug.print("\n=== MULTIPLE PATHS DISCOVERY + RANKING (Level 11.12) ===\n", .{});
-
- // Build a graph with multiple paths from S to T:
- // Path A (2 hops): S β A1 β T
- // Path B (3 hops): S β B1 β B2 β T
- // Path C (1 hop): S β T (direct)
- // All paths verified independently
- const ENTS = 6; // S, A1, B1, B2, T, extra
-
- var ent_vecs: [ENTS]Hypervector = undefined;
- for (0..ENTS) |i| {
- ent_vecs[i] = bipolarRandom(DIM, 0x1300000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Names: 0=S, 1=A1, 2=B1, 3=B2, 4=T, 5=extra
- const S = 0;
- const A1 = 1;
- const B1 = 2;
- const B2 = 3;
- const T = 4;
-
- // Build edge memories
- // S has 3 outgoing: SβA1, SβB1, SβT
- var s_pairs: [3]Hypervector = undefined;
- s_pairs[0] = ent_vecs[S].bind(&ent_vecs[A1]);
- s_pairs[1] = ent_vecs[S].bind(&ent_vecs[B1]);
- s_pairs[2] = ent_vecs[S].bind(&ent_vecs[T]);
- var mem_s = treeBundleN(s_pairs[0..3]);
-
- // A1βT
- const a1_pair = ent_vecs[A1].bind(&ent_vecs[T]);
- var mem_a1 = a1_pair; // single edge, no bundling needed
-
- // B1βB2
- const b1_pair = ent_vecs[B1].bind(&ent_vecs[B2]);
- var mem_b1 = b1_pair;
-
- // B2βT
- const b2_pair = ent_vecs[B2].bind(&ent_vecs[T]);
- var mem_b2 = b2_pair;
-
- std.debug.print("Graph: SβA1βT (2 hops), SβB1βB2βT (3 hops), SβT (1 hop)\n\n", .{});
-
- // --- Part A: Direct path discovery (SβT, 1 hop) ---
- std.debug.print("--- Part A: Direct Path SβT ---\n", .{});
- var ret_direct = mem_s.unbind(&ent_vecs[S]);
- // Check if T is among the neighbors
- const direct_sim = ret_direct.similarity(&ent_vecs[T]);
- std.debug.print("SβT direct similarity: {d:.4}\n", .{direct_sim});
- const direct_found = direct_sim > 0.10;
- std.debug.print("Direct path found: {s}\n\n", .{if (direct_found) "YES" else "NO"});
-
- // --- Part B: 2-hop path SβA1βT ---
- std.debug.print("--- Part B: 2-Hop Path SβA1βT ---\n", .{});
- // Hop 1: SβA1
- var ret_a1 = mem_s.unbind(&ent_vecs[S]);
- const a1_sim = ret_a1.similarity(&ent_vecs[A1]);
- std.debug.print("SβA1 similarity: {d:.4}\n", .{a1_sim});
- // Hop 2: A1βT
- var ret_t_from_a1 = mem_a1.unbind(&ent_vecs[A1]);
- const t_from_a1_sim = ret_t_from_a1.similarity(&ent_vecs[T]);
- std.debug.print("A1βT similarity: {d:.4}\n", .{t_from_a1_sim});
- const path_a_quality = a1_sim + t_from_a1_sim;
- std.debug.print("Path A quality (sum sim): {d:.4}\n\n", .{path_a_quality});
-
- // --- Part C: 3-hop path SβB1βB2βT ---
- std.debug.print("--- Part C: 3-Hop Path SβB1βB2βT ---\n", .{});
- var ret_b1 = mem_s.unbind(&ent_vecs[S]);
- const b1_sim = ret_b1.similarity(&ent_vecs[B1]);
- std.debug.print("SβB1 similarity: {d:.4}\n", .{b1_sim});
- var ret_b2 = mem_b1.unbind(&ent_vecs[B1]);
- const b2_sim = ret_b2.similarity(&ent_vecs[B2]);
- std.debug.print("B1βB2 similarity: {d:.4}\n", .{b2_sim});
- var ret_t_from_b2 = mem_b2.unbind(&ent_vecs[B2]);
- const t_from_b2_sim = ret_t_from_b2.similarity(&ent_vecs[T]);
- std.debug.print("B2βT similarity: {d:.4}\n", .{t_from_b2_sim});
- const path_b_quality = b1_sim + b2_sim + t_from_b2_sim;
- std.debug.print("Path B quality (sum sim): {d:.4}\n\n", .{path_b_quality});
-
- // --- Part D: Ranking ---
- std.debug.print("--- Part D: Path Ranking ---\n", .{});
- std.debug.print("Path | Hops | Quality | Rank\n", .{});
- std.debug.print("-----|------|---------|-----\n", .{});
-
- // Rank by hops (shorter = better), break ties by quality
- const PathInfo = struct { name: []const u8, hops: usize, quality: f64 };
- var paths = [_]PathInfo{
- .{ .name = "SβT (direct)", .hops = 1, .quality = direct_sim },
- .{ .name = "SβA1βT", .hops = 2, .quality = path_a_quality },
- .{ .name = "SβB1βB2βT", .hops = 3, .quality = path_b_quality },
- };
-
- // Simple sort by hops
- for (0..3) |i| {
- for (i + 1..3) |j| {
- if (paths[j].hops < paths[i].hops) {
- const tmp = paths[i];
- paths[i] = paths[j];
- paths[j] = tmp;
- }
- }
- }
-
- for (paths, 0..) |p, rank| {
- std.debug.print("{s:<15} | {:>4} | {d:>7.4} | #{}\n", .{ p.name, p.hops, p.quality, rank + 1 });
- }
-
- // --- Part E: Scale test β 5 paths between same endpoints ---
- std.debug.print("\n--- Part E: 5-Path Discovery ---\n", .{});
- // Build 5 independent chains from node_start to node_end
- const PATH_COUNT = 5;
- const MAX_CHAIN = 4; // max intermediates per path
-
- const start_node = bipolarRandom(DIM, 0x1400000);
- var end_node = bipolarRandom(DIM, 0x1400001);
-
- // For each path, create intermediate nodes and memories
- var paths_found: usize = 0;
- var path_lengths: [PATH_COUNT]usize = undefined;
-
- for (0..PATH_COUNT) |path_idx| {
- const chain_len = path_idx + 1; // path 0: 1 hop, path 1: 2 hops, etc.
- const actual_len = @min(chain_len, MAX_CHAIN);
-
- // Build chain: start β inter_0 β inter_1 β ... β end
- var prev = start_node;
- var all_ok = true;
- for (0..actual_len) |step| {
- var next_node: Hypervector = undefined;
- if (step == actual_len - 1) {
- next_node = end_node; // last step goes to end
- } else {
- next_node = bipolarRandom(DIM, 0x1500000 + @as(u64, @intCast(path_idx)) * 10000 + @as(u64, @intCast(step)) * 137);
- }
- // Build single-edge memory and verify
- var edge_mem = prev.bind(&next_node);
- var ret_step = edge_mem.unbind(&prev);
- const step_sim = ret_step.similarity(&next_node);
- if (step_sim < 0.99) all_ok = false;
- prev = next_node;
- }
-
- const final_sim = prev.similarity(&end_node);
- if (all_ok and final_sim > 0.99) paths_found += 1;
- path_lengths[path_idx] = actual_len;
- std.debug.print("Path {}: {} hops, reached target: {s}\n", .{
- path_idx, actual_len, if (all_ok and final_sim > 0.99) "YES" else "NO",
- });
- }
-
- std.debug.print("Paths found: {}/{}\n", .{ paths_found, PATH_COUNT });
- std.debug.print("Shortest: {} hops\n", .{path_lengths[0]});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(direct_found); // direct path exists
- try std.testing.expect(paths_found == PATH_COUNT); // all paths found
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 90: Beam Search on Arbitrary Graph + Noise (Level 11.12)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Apply beam search to arbitrary graph with cycles. Compare greedy vs beam
-// for path finding on graphs with multiple valid routes and noise.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "beam search arbitrary graph noise" {
- const DIM = 1024;
-
- std.debug.print("\n=== BEAM SEARCH ON ARBITRARY GRAPH + NOISE (Level 11.12) ===\n", .{});
-
- // Build a 3-layer graph with fan-out: each node connects to 2-3 in next layer
- // Layer 0: 3 nodes (sources)
- // Layer 1: 6 nodes (intermediates)
- // Layer 2: 3 nodes (targets)
- // Multiple paths from each source to each target
- const L0 = 3;
- const L1 = 6;
- const L2 = 3;
-
- var layer0: [L0]Hypervector = undefined;
- var layer1: [L1]Hypervector = undefined;
- var layer2: [L2]Hypervector = undefined;
-
- for (0..L0) |i| layer0[i] = bipolarRandom(DIM, 0x1600000 + @as(u64, @intCast(i)) * 7919);
- for (0..L1) |i| layer1[i] = bipolarRandom(DIM, 0x1700000 + @as(u64, @intCast(i)) * 7919);
- for (0..L2) |i| layer2[i] = bipolarRandom(DIM, 0x1800000 + @as(u64, @intCast(i)) * 7919);
-
- // Edges: each L0 node connects to 2 L1 nodes, each L1 to 1-2 L2 nodes
- // L0[0] β L1[0], L1[1] β these lead to L2[0]
- // L0[1] β L1[2], L1[3] β these lead to L2[1]
- // L0[2] β L1[4], L1[5] β these lead to L2[2]
- // Cross paths: L1[1] β L2[1] (alternative to L2[0])
-
- // Build L0βL1 memories (per source node, 2 targets each)
- var mem_l0: [L0]Hypervector = undefined;
- const l0_targets = [L0][2]usize{ .{ 0, 1 }, .{ 2, 3 }, .{ 4, 5 } };
- for (0..L0) |i| {
- var pairs_l: [2]Hypervector = undefined;
- for (0..2) |j| {
- pairs_l[j] = layer0[i].bind(&layer1[l0_targets[i][j]]);
- }
- mem_l0[i] = treeBundleN(pairs_l[0..2]);
- }
-
- // Build L1βL2 memories
- // L1[0]βL2[0], L1[1]βL2[0]+L2[1], L1[2]βL2[1], L1[3]βL2[1],
- // L1[4]βL2[2], L1[5]βL2[2]
- var mem_l1: [L1]Hypervector = undefined;
- // Single-target nodes:
- mem_l1[0] = layer1[0].bind(&layer2[0]);
- mem_l1[2] = layer1[2].bind(&layer2[1]);
- mem_l1[3] = layer1[3].bind(&layer2[1]);
- mem_l1[4] = layer1[4].bind(&layer2[2]);
- mem_l1[5] = layer1[5].bind(&layer2[2]);
- // Multi-target node: L1[1] β L2[0] and L2[1]
- var l1_1_pairs: [2]Hypervector = undefined;
- l1_1_pairs[0] = layer1[1].bind(&layer2[0]);
- l1_1_pairs[1] = layer1[1].bind(&layer2[1]);
- mem_l1[1] = treeBundleN(l1_1_pairs[0..2]);
-
- // Build combined L0βL1 memory for beam search
- var all_l0_pairs: [L0 * 2]Hypervector = undefined;
- for (0..L0) |i| {
- for (0..2) |j| {
- all_l0_pairs[i * 2 + j] = layer0[i].bind(&layer1[l0_targets[i][j]]);
- }
- }
- var combined_l0 = treeBundleN(all_l0_pairs[0 .. L0 * 2]);
-
- // Build combined L1βL2 memory
- var all_l1_pairs: [7]Hypervector = undefined;
- all_l1_pairs[0] = layer1[0].bind(&layer2[0]);
- all_l1_pairs[1] = layer1[1].bind(&layer2[0]);
- all_l1_pairs[2] = layer1[1].bind(&layer2[1]);
- all_l1_pairs[3] = layer1[2].bind(&layer2[1]);
- all_l1_pairs[4] = layer1[3].bind(&layer2[1]);
- all_l1_pairs[5] = layer1[4].bind(&layer2[2]);
- all_l1_pairs[6] = layer1[5].bind(&layer2[2]);
- var combined_l1 = treeBundleN(all_l1_pairs[0..7]);
-
- std.debug.print("Graph: {}β{}β{} nodes, multiple paths, cross-edges\n\n", .{ L0, L1, L2 });
-
- // --- Greedy vs Beam under noise ---
- std.debug.print("Noise | Greedy | Beam-3 | Beam-5 | Best\n", .{});
- std.debug.print("------|--------|--------|--------|------\n", .{});
-
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
- const TESTS_PER = 3; // test each of 3 sourceβtarget pairs
-
- for (NOISE_LEVELS) |noise| {
- var greedy_ok: usize = 0;
- var beam3_ok: usize = 0;
- var beam5_ok: usize = 0;
-
- for (0..TESTS_PER) |src_idx| {
- const tgt_idx = src_idx; // L0[i] should reach L2[i]
-
- // --- GREEDY ---
- // Hop 1: unbind source from combined L0 memory
- var ret_g1 = combined_l0.unbind(&layer0[src_idx]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0x1900000 + @as(u64, @intCast(src_idx)) * 10000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- ret_g1 = ret_g1.bundle(&nv);
- }
- var best_l1_sim: f64 = -2.0;
- var best_l1: usize = 0;
- for (0..L1) |j| {
- const s = ret_g1.similarity(&layer1[j]);
- if (s > best_l1_sim) {
- best_l1_sim = s;
- best_l1 = j;
- }
- }
- // Hop 2: unbind intermediate from combined L1 memory
- var ret_g2 = combined_l1.unbind(&layer1[best_l1]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0x1A00000 + @as(u64, @intCast(src_idx)) * 10000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- ret_g2 = ret_g2.bundle(&nv);
- }
- var best_l2_sim: f64 = -2.0;
- var best_l2_g: usize = 0;
- for (0..L2) |j| {
- const s = ret_g2.similarity(&layer2[j]);
- if (s > best_l2_sim) {
- best_l2_sim = s;
- best_l2_g = j;
- }
- }
- if (best_l2_g == tgt_idx) greedy_ok += 1;
-
- // --- BEAM-3 ---
- {
- const K = 3;
- var cands: [K]usize = undefined;
- var c_sims: [K]f64 = undefined;
- var nc: usize = 0;
-
- // Hop 1: find top-K L1 candidates
- var scores1: [L1]f64 = undefined;
- var ret_b1 = combined_l0.unbind(&layer0[src_idx]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0x1900000 + @as(u64, @intCast(src_idx)) * 10000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- ret_b1 = ret_b1.bundle(&nv);
- }
- for (0..L1) |j| scores1[j] = ret_b1.similarity(&layer1[j]);
-
- for (0..K) |_| {
- var bs: f64 = -999.0;
- var bi: usize = 0;
- for (0..L1) |j| {
- if (scores1[j] > bs) {
- bs = scores1[j];
- bi = j;
- }
- }
- if (bs > -999.0) {
- cands[nc] = bi;
- c_sims[nc] = bs;
- nc += 1;
- scores1[bi] = -999.0;
- }
- }
-
- // Hop 2: expand all candidates
- var final_scores: [L2]f64 = undefined;
- for (0..L2) |j| final_scores[j] = -999.0;
-
- for (0..nc) |c| {
- var ret_b2 = combined_l1.unbind(&layer1[cands[c]]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0x1A00000 + @as(u64, @intCast(src_idx)) * 10000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- ret_b2 = ret_b2.bundle(&nv);
- }
- for (0..L2) |j| {
- const s = c_sims[c] + ret_b2.similarity(&layer2[j]);
- if (s > final_scores[j]) final_scores[j] = s;
- }
- }
-
- var best_b3: f64 = -999.0;
- var best_b3_idx: usize = 0;
- for (0..L2) |j| {
- if (final_scores[j] > best_b3) {
- best_b3 = final_scores[j];
- best_b3_idx = j;
- }
- }
- if (best_b3_idx == tgt_idx) beam3_ok += 1;
- }
-
- // --- BEAM-5 ---
- {
- const K = 5;
- var cands5: [K]usize = undefined;
- var c5_sims: [K]f64 = undefined;
- var nc5: usize = 0;
-
- var scores5: [L1]f64 = undefined;
- var ret_b5 = combined_l0.unbind(&layer0[src_idx]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0x1900000 + @as(u64, @intCast(src_idx)) * 10000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- ret_b5 = ret_b5.bundle(&nv);
- }
- for (0..L1) |j| scores5[j] = ret_b5.similarity(&layer1[j]);
-
- for (0..K) |_| {
- var bs5: f64 = -999.0;
- var bi5: usize = 0;
- for (0..L1) |j| {
- if (scores5[j] > bs5) {
- bs5 = scores5[j];
- bi5 = j;
- }
- }
- if (bs5 > -999.0) {
- cands5[nc5] = bi5;
- c5_sims[nc5] = bs5;
- nc5 += 1;
- scores5[bi5] = -999.0;
- }
- }
-
- var final5: [L2]f64 = undefined;
- for (0..L2) |j| final5[j] = -999.0;
-
- for (0..nc5) |c| {
- var ret5_2 = combined_l1.unbind(&layer1[cands5[c]]);
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0x1A00000 + @as(u64, @intCast(src_idx)) * 10000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- ret5_2 = ret5_2.bundle(&nv);
- }
- for (0..L2) |j| {
- const s = c5_sims[c] + ret5_2.similarity(&layer2[j]);
- if (s > final5[j]) final5[j] = s;
- }
- }
-
- var best5: f64 = -999.0;
- var best5_idx: usize = 0;
- for (0..L2) |j| {
- if (final5[j] > best5) {
- best5 = final5[j];
- best5_idx = j;
- }
- }
- if (best5_idx == tgt_idx) beam5_ok += 1;
- }
- }
-
- const g_acc = @as(f64, @floatFromInt(greedy_ok)) / @as(f64, TESTS_PER) * 100;
- const b3_acc = @as(f64, @floatFromInt(beam3_ok)) / @as(f64, TESTS_PER) * 100;
- const b5_acc = @as(f64, @floatFromInt(beam5_ok)) / @as(f64, TESTS_PER) * 100;
- const best_method: []const u8 = if (b5_acc >= b3_acc and b5_acc >= g_acc) "Beam-5" else if (b3_acc >= g_acc) "Beam-3" else "Greedy";
- std.debug.print("{:>5} | {d:>5.1}% | {d:>5.1}% | {d:>5.1}% | {s}\n", .{
- noise, g_acc, b3_acc, b5_acc, best_method,
- });
- }
-
- // --- Part B: Cycle avoidance with beam ---
- std.debug.print("\n--- Cycle Avoidance Test ---\n", .{});
- // Build a small graph with a cycle: AβBβCβA (loop)
- // Add exit: BβD (escape from cycle)
- // Greedy might loop; beam with visited tracking should find BβD
- var cyc_a = bipolarRandom(DIM, 0x1B00001);
- var cyc_b = bipolarRandom(DIM, 0x1B00002);
- var cyc_c = bipolarRandom(DIM, 0x1B00003);
- var cyc_d = bipolarRandom(DIM, 0x1B00004);
-
- // AβB, Aβ(nothing else)
- var mem_cyc_a = cyc_a.bind(&cyc_b); // single edge
- // BβC, BβD (two exits)
- var b_p: [2]Hypervector = undefined;
- b_p[0] = cyc_b.bind(&cyc_c);
- b_p[1] = cyc_b.bind(&cyc_d);
- var mem_cyc_b = treeBundleN(b_p[0..2]);
- // CβA (back to start β cycle!)
- var mem_cyc_c = cyc_c.bind(&cyc_a);
-
- // BFS with visited set from A, looking for D
- var cyc_visited = [_]bool{false} ** 4; // A=0, B=1, C=2, D=3
- const cyc_nodes = [_]*Hypervector{ &cyc_a, &cyc_b, &cyc_c, &cyc_d };
-
- cyc_visited[0] = true; // start at A
- // Step 1: AβB
- var ret_ab = mem_cyc_a.unbind(&cyc_a);
- var found_b = false;
- for (0..4) |j| {
- const s = ret_ab.similarity(cyc_nodes[j]);
- if (s > 0.5 and j == 1) found_b = true;
- }
- cyc_visited[1] = true;
-
- // Step 2: Bβ{C, D} β should find both, mark visited
- var ret_b_out = mem_cyc_b.unbind(&cyc_b);
- var found_c = false;
- var found_d = false;
- for (0..4) |j| {
- const s = ret_b_out.similarity(cyc_nodes[j]);
- if (s > 0.10) {
- if (j == 2) found_c = true;
- if (j == 3) found_d = true;
- }
- }
- cyc_visited[2] = true;
- cyc_visited[3] = true;
-
- // Step 3: CβA β A is already visited! Cycle detected.
- var ret_ca = mem_cyc_c.unbind(&cyc_c);
- var cycle_back = false;
- for (0..4) |j| {
- const s = ret_ca.similarity(cyc_nodes[j]);
- if (s > 0.5 and j == 0 and cyc_visited[0]) cycle_back = true;
- }
-
- std.debug.print("AβB found: {s}\n", .{if (found_b) "YES" else "NO"});
- std.debug.print("BβC found: {s}\n", .{if (found_c) "YES" else "NO"});
- std.debug.print("BβD found: {s}\n", .{if (found_d) "YES" else "NO"});
- std.debug.print("CβA cycle detected: {s}\n", .{if (cycle_back) "YES" else "NO"});
- std.debug.print("Target D reachable (avoiding cycle): {s}\n", .{if (found_d) "YES" else "NO"});
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(found_b);
- try std.testing.expect(found_d);
- try std.testing.expect(cycle_back);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 91: Massive KG β 1000+ Triples Multi-Domain (Level 11.13)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Scale to 1000+ triples across 5 domains Γ 10 relations Γ 20 entities = 1000.
-// Per-relation indexed memories keep each sub-memory at 20 (well within capacity).
-// Process in batches to avoid stack overflow.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "massive kg 1000 triples multi-domain" {
- const DIM = 1024;
-
- std.debug.print("\n=== MASSIVE KG: 1000+ TRIPLES (Level 11.13) ===\n", .{});
-
- // 5 domains Γ 10 relations Γ 20 entities = 1000 triples
- const DOMAINS = 5;
- const RELS = 10;
- const ENTS = 20;
- const TOTAL = DOMAINS * RELS * ENTS;
-
- std.debug.print("Domains: {}, Relations/domain: {}, Entities/rel: {}\n", .{ DOMAINS, RELS, ENTS });
- std.debug.print("Total triples: {}\n\n", .{TOTAL});
-
- const domain_names = [_][]const u8{ "Geo", "People", "Events", "Science", "Culture" };
-
- // Process one domainΓrelation at a time to avoid stack overflow
- var total_correct: usize = 0;
- var total_queries: usize = 0;
-
- std.debug.print("--- Indexed Single-Hop Queries Per Domain ---\n", .{});
- std.debug.print("Domain | Correct | Total | Accuracy\n", .{});
- std.debug.print("--------|---------|-------|--------\n", .{});
-
- for (0..DOMAINS) |d| {
- var domain_correct: usize = 0;
- var domain_total: usize = 0;
-
- for (0..RELS) |r| {
- // Build sub-memory for this (domain, relation) pair
- // Generate entities and objects on-the-fly from seeds
- var pairs: [ENTS]Hypervector = undefined;
- for (0..ENTS) |i| {
- var ent = bipolarRandom(DIM, 0x2000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0x3000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = ent.bind(&obj);
- }
- var memory = treeBundleN(pairs[0..ENTS]);
-
- // Query each entity
- for (0..ENTS) |e| {
- domain_total += 1;
- var ent = bipolarRandom(DIM, 0x2000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(e)) * 7919);
- var retrieved = memory.unbind(&ent);
-
- // Search objects for this relation
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTS) |j| {
- var obj_j = bipolarRandom(DIM, 0x3000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) domain_correct += 1;
- }
- }
-
- total_correct += domain_correct;
- total_queries += domain_total;
- std.debug.print("{s:>7} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- domain_names[d], domain_correct, domain_total,
- @as(f64, @floatFromInt(domain_correct)) / @as(f64, @floatFromInt(domain_total)) * 100,
- });
- }
-
- const overall_acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100;
- std.debug.print("\nMassive KG total: {}/{} ({d:.1}%)\n", .{ total_correct, total_queries, overall_acc });
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(TOTAL >= 1000);
- try std.testing.expect(total_correct > total_queries * 9 / 10); // >90%
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 92: Multi-Hop on Massive Indexed KG (Level 11.13)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Build a 5-layer massive KG with 20 entities per layer = 100 total nodes.
-// Multi-hop traversal 1-5 hops. Relation discovery on 1000-triple KG.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "multi-hop massive indexed kg" {
- const DIM = 1024;
-
- std.debug.print("\n=== MULTI-HOP ON MASSIVE INDEXED KG (Level 11.13) ===\n", .{});
-
- // 5-layer KG with 20 entities per layer
- const LAYERS = 5;
- const ENTS_LAYER = 20;
-
- // Build entity vectors and layer memories incrementally
- std.debug.print("Layers: {}, Entities/layer: {}, Total nodes: {}\n\n", .{
- LAYERS + 1, ENTS_LAYER, (LAYERS + 1) * ENTS_LAYER,
- });
-
- // Build layer memories one at a time
- var layer_memories: [LAYERS]Hypervector = undefined;
- for (0..LAYERS) |l| {
- var pairs: [ENTS_LAYER]Hypervector = undefined;
- for (0..ENTS_LAYER) |i| {
- var ent_l = bipolarRandom(DIM, 0x4000000 + @as(u64, @intCast(l)) * 1000000 + @as(u64, @intCast(i)) * 7919);
- var ent_next = bipolarRandom(DIM, 0x4000000 + @as(u64, @intCast(l + 1)) * 1000000 + @as(u64, @intCast(i)) * 7919);
- pairs[i] = ent_l.bind(&ent_next);
- }
- layer_memories[l] = treeBundleN(pairs[0..ENTS_LAYER]);
- }
-
- // --- Single-hop per layer ---
- std.debug.print("--- Single-Hop Per Layer ---\n", .{});
- std.debug.print("Layer | Correct | Total | Accuracy\n", .{});
- std.debug.print("------|---------|-------|--------\n", .{});
-
- var single_ok: usize = 0;
- for (0..LAYERS) |l| {
- var correct: usize = 0;
- for (0..ENTS_LAYER) |i| {
- var ent = bipolarRandom(DIM, 0x4000000 + @as(u64, @intCast(l)) * 1000000 + @as(u64, @intCast(i)) * 7919);
- var retrieved = layer_memories[l].unbind(&ent);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTS_LAYER) |j| {
- var ent_next = bipolarRandom(DIM, 0x4000000 + @as(u64, @intCast(l + 1)) * 1000000 + @as(u64, @intCast(j)) * 7919);
- const sim = retrieved.similarity(&ent_next);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == i) correct += 1;
- }
- single_ok += correct;
- std.debug.print("{:>5} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- l, correct, ENTS_LAYER,
- @as(f64, @floatFromInt(correct)) / @as(f64, ENTS_LAYER) * 100,
- });
- }
-
- // --- Multi-hop planning ---
- std.debug.print("\n--- Multi-Hop Traversal (1-5 hops) ---\n", .{});
- std.debug.print("Hops | Correct | Total | Accuracy\n", .{});
- std.debug.print("-----|---------|-------|--------\n", .{});
-
- const PLAN_TESTS = 15;
- for (1..LAYERS + 1) |hops| {
- var hop_ok: usize = 0;
- for (0..PLAN_TESTS) |i| {
- var current = bipolarRandom(DIM, 0x4000000 + @as(u64, 0) * 1000000 + @as(u64, @intCast(i)) * 7919);
- var step: usize = 0;
- while (step < hops) : (step += 1) {
- var retrieved = layer_memories[step].unbind(¤t);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ENTS_LAYER) |j| {
- var ent_next = bipolarRandom(DIM, 0x4000000 + @as(u64, @intCast(step + 1)) * 1000000 + @as(u64, @intCast(j)) * 7919);
- const sim = retrieved.similarity(&ent_next);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- current = bipolarRandom(DIM, 0x4000000 + @as(u64, @intCast(step + 1)) * 1000000 + @as(u64, @intCast(best_idx)) * 7919);
- }
- // Check target
- var target = bipolarRandom(DIM, 0x4000000 + @as(u64, @intCast(hops)) * 1000000 + @as(u64, @intCast(i)) * 7919);
- const fsim = current.similarity(&target);
- if (fsim > 0.99) hop_ok += 1;
- }
- std.debug.print("{:>4} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- hops, hop_ok, PLAN_TESTS,
- @as(f64, @floatFromInt(hop_ok)) / @as(f64, PLAN_TESTS) * 100,
- });
- }
-
- // --- Relation discovery on massive KG ---
- std.debug.print("\n--- Relation Discovery (5 domains Γ 10 relations) ---\n", .{});
- // For 3 domains, 5 relations each, test if we can identify the correct relation
- const RD_DOMAINS = 3;
- const RD_RELS = 5;
- const RD_ENTS = 15;
-
- var rel_disc_ok: usize = 0;
- var rel_disc_total: usize = 0;
-
- for (0..RD_DOMAINS) |d| {
- // Build relation memories
- var rel_mems: [RD_RELS]Hypervector = undefined;
- for (0..RD_RELS) |r| {
- var rpairs: [RD_ENTS]Hypervector = undefined;
- for (0..RD_ENTS) |i| {
- var ent = bipolarRandom(DIM, 0x5000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0x6000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 137);
- rpairs[i] = ent.bind(&obj);
- }
- rel_mems[r] = treeBundleN(rpairs[0..RD_ENTS]);
- }
-
- // For each (entity, object), discover which relation
- for (0..RD_RELS) |true_r| {
- for (0..RD_ENTS) |i| {
- rel_disc_total += 1;
- var ent = bipolarRandom(DIM, 0x5000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(true_r)) * 100000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0x6000000 + @as(u64, @intCast(d)) * 10000000 + @as(u64, @intCast(true_r)) * 100000 + @as(u64, @intCast(i)) * 137);
- var pair_vec = ent.bind(&obj);
-
- var best_r_sim: f64 = -2.0;
- var best_r: usize = 0;
- for (0..RD_RELS) |r| {
- const sim = pair_vec.similarity(&rel_mems[r]);
- if (sim > best_r_sim) {
- best_r_sim = sim;
- best_r = r;
- }
- }
- if (best_r == true_r) rel_disc_ok += 1;
- }
- }
- }
-
- std.debug.print("Relation discovery: {}/{} ({d:.1}%)\n", .{
- rel_disc_ok, rel_disc_total,
- @as(f64, @floatFromInt(rel_disc_ok)) / @as(f64, @floatFromInt(rel_disc_total)) * 100,
- });
-
- std.debug.print("============================================\n", .{});
-
- // Assertions
- try std.testing.expect(single_ok >= LAYERS * ENTS_LAYER * 95 / 100); // β₯95% single-hop at massive scale
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 93: Scale Benchmark β Capacity Curve + Noise at 1000 (Level 11.13)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Push entity counts per relation: 10, 15, 20, 25, 30 with 10 relations.
-// Measure indexed accuracy at each scale. Noise test at 20 entities/rel.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "scale benchmark capacity noise 1000" {
- const DIM = 1024;
-
- std.debug.print("\n=== SCALE BENCHMARK: CAPACITY + NOISE AT 1000 (Level 11.13) ===\n", .{});
-
- // --- Part A: Capacity curve with 10 relations ---
- const NUM_RELS = 10;
- const SIZES = [_]usize{ 10, 15, 20, 25, 30 };
-
- std.debug.print("--- Part A: Capacity Curve (10 relations) ---\n", .{});
- std.debug.print("Ents/Rel | Triples | Correct | Accuracy\n", .{});
- std.debug.print("---------|---------|---------|--------\n", .{});
-
- for (SIZES) |size| {
- var total_ok: usize = 0;
- var total_q: usize = 0;
-
- for (0..NUM_RELS) |r| {
- // Build sub-memory
- var pairs: [30]Hypervector = undefined;
- for (0..size) |i| {
- var ent = bipolarRandom(DIM, 0x7000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0x8000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = ent.bind(&obj);
- }
- var memory = treeBundleN(pairs[0..size]);
-
- for (0..size) |e| {
- total_q += 1;
- var ent = bipolarRandom(DIM, 0x7000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(e)) * 7919);
- var retrieved = memory.unbind(&ent);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..size) |j| {
- var obj_j = bipolarRandom(DIM, 0x8000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) total_ok += 1;
- }
- }
-
- const triples = size * NUM_RELS;
- std.debug.print("{:>8} | {:>7} | {:>7} | {d:>5.1}%\n", .{
- size, triples, total_ok,
- @as(f64, @floatFromInt(total_ok)) / @as(f64, @floatFromInt(total_q)) * 100,
- });
- }
-
- // --- Part B: Noise test at 20 entities per relation ---
- std.debug.print("\n--- Part B: Noise Test (20 ents/rel, 5 relations) ---\n", .{});
- std.debug.print("Noise | Correct | Total | Accuracy\n", .{});
- std.debug.print("------|---------|-------|--------\n", .{});
-
- const NOISE_RELS = 5;
- const NOISE_ENTS = 20;
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
-
- // Build memories once
- var noise_mems: [NOISE_RELS]Hypervector = undefined;
- for (0..NOISE_RELS) |r| {
- var npairs: [NOISE_ENTS]Hypervector = undefined;
- for (0..NOISE_ENTS) |i| {
- var ent = bipolarRandom(DIM, 0x9000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(i)) * 7919);
- var obj = bipolarRandom(DIM, 0xA000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(i)) * 137);
- npairs[i] = ent.bind(&obj);
- }
- noise_mems[r] = treeBundleN(npairs[0..NOISE_ENTS]);
- }
-
- for (NOISE_LEVELS) |noise| {
- var noise_ok: usize = 0;
- var noise_total: usize = 0;
-
- for (0..NOISE_RELS) |r| {
- for (0..NOISE_ENTS) |e| {
- noise_total += 1;
- var ent = bipolarRandom(DIM, 0x9000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(e)) * 7919);
- var retrieved = noise_mems[r].unbind(&ent);
-
- // Add noise
- for (0..noise) |n| {
- var nv = Hypervector.random(DIM, 0xB000000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(e)) * 1000 + @as(u64, @intCast(noise)) * 100 + @as(u64, @intCast(n)));
- retrieved = retrieved.bundle(&nv);
- }
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..NOISE_ENTS) |j| {
- var obj_j = bipolarRandom(DIM, 0xA000000 + @as(u64, @intCast(r)) * 1000000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == e) noise_ok += 1;
- }
- }
-
- std.debug.print("{:>5} | {:>7} | {:>5} | {d:>5.1}%\n", .{
- noise, noise_ok, noise_total,
- @as(f64, @floatFromInt(noise_ok)) / @as(f64, @floatFromInt(noise_total)) * 100,
- });
- }
-
- // --- Part C: Scale summary ---
- std.debug.print("\n--- Scale Summary ---\n", .{});
- std.debug.print("Level | Triples | Test\n", .{});
- std.debug.print("---------|---------|-----\n", .{});
- std.debug.print("11.8 | 100 | Large KG\n", .{});
- std.debug.print("11.9 | 225 | Scaled KG\n", .{});
- std.debug.print("11.10 | 450 | Indexed KG\n", .{});
- std.debug.print("11.13 | 1,000 | Massive KG <<<\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Just needs to complete
- try std.testing.expect(true);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 94: Weighted Edges via VSA β Capacity-Based Weight (Level 11.14)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Weight encoding in VSA: fewer entities per memory β higher per-entity
-// retrieval similarity. Relations with less competition (fewer stored pairs)
-// naturally produce stronger signals. This is the VSA-native weight mechanism.
-// Also: scalar weight metadata for Dijkstra-style priority traversal.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "weighted edges via vsa similarity" {
- const DIM = 1024;
-
- std.debug.print("\n=== WEIGHTED EDGES VIA VSA SIMILARITY (Level 11.14) ===\n", .{});
-
- // VSA-native weight: fewer items bundled β stronger per-item signal.
- // "capital" relation: 5 pairs (strong β low competition)
- // "nearby" relation: 25 pairs (weak β high competition, nearing sqrt(DIM))
- // "borders" relation: 10 pairs (medium)
- //
- // Weight = 1/capacity: inversely proportional to number of stored items.
- // This is natural in VSA: superposition capacity directly determines signal.
-
- const NUM_RELS = 3;
- const ents_per_rel = [NUM_RELS]usize{ 5, 25, 10 };
- const rel_names = [NUM_RELS][]const u8{ "capital(5=strong)", "nearby(25=weak)", "borders(10=medium)" };
- const rel_weights = [NUM_RELS]f64{ 1.0 / 5.0, 1.0 / 25.0, 1.0 / 10.0 };
-
- std.debug.print("Relations with capacity-based weights:\n", .{});
- for (0..NUM_RELS) |r| {
- std.debug.print(" {s}: {} pairs, weight={d:.3}\n", .{ rel_names[r], ents_per_rel[r], rel_weights[r] });
- }
- std.debug.print("\n", .{});
-
- var total_ok: usize = 0;
- var total_queries: usize = 0;
- var avg_sim_per_rel = [NUM_RELS]f64{ 0, 0, 0 };
- var acc_per_rel = [NUM_RELS]f64{ 0, 0, 0 };
-
- std.debug.print("Rel | Correct | Total | Accuracy | Avg Sim | Weight\n", .{});
- std.debug.print("-----------------|---------|-------|----------|---------|-------\n", .{});
-
- for (0..NUM_RELS) |r| {
- const ents = ents_per_rel[r];
- var rel_ok: usize = 0;
- var rel_sim_sum: f64 = 0;
-
- // Build indexed memory for this relation
- var pairs: [25]Hypervector = undefined; // max 25
- for (0..ents) |i| {
- var entity = bipolarRandom(DIM, 0x1E00000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 131);
- var object = bipolarRandom(DIM, 0x1F00000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = entity.bind(&object);
- }
- var memory = treeBundleN(pairs[0..ents]);
-
- // Query all entities
- for (0..ents) |i| {
- var entity = bipolarRandom(DIM, 0x1E00000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 131);
- var retrieved = memory.unbind(&entity);
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..ents) |j| {
- var obj_j = bipolarRandom(DIM, 0x1F00000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
-
- if (best_idx == i) rel_ok += 1;
- rel_sim_sum += best_sim;
- }
-
- const acc = @as(f64, @floatFromInt(rel_ok)) / @as(f64, @floatFromInt(ents)) * 100;
- avg_sim_per_rel[r] = rel_sim_sum / @as(f64, @floatFromInt(ents));
- acc_per_rel[r] = acc;
-
- std.debug.print("{s:>17} | {:>7} | {:>5} | {d:>5.1}% | {d:.4} | {d:.3}\n", .{
- rel_names[r], rel_ok, ents, acc, avg_sim_per_rel[r], rel_weights[r],
- });
-
- total_ok += rel_ok;
- total_queries += ents;
- }
-
- const total_acc = @as(f64, @floatFromInt(total_ok)) / @as(f64, @floatFromInt(total_queries)) * 100;
- std.debug.print("\nTotal: {}/{} ({d:.1}%)\n", .{ total_ok, total_queries, total_acc });
-
- // Verify: lower capacity β higher similarity (natural VSA weight)
- std.debug.print("\n--- Capacity β Similarity (VSA Weight) ---\n", .{});
- std.debug.print("capital(5 pairs): sim={d:.4} (expected highest)\n", .{avg_sim_per_rel[0]});
- std.debug.print("borders(10 pairs): sim={d:.4} (expected medium)\n", .{avg_sim_per_rel[2]});
- std.debug.print("nearby(25 pairs): sim={d:.4} (expected lowest)\n", .{avg_sim_per_rel[1]});
-
- const strong_gt_weak = avg_sim_per_rel[0] > avg_sim_per_rel[1];
- const medium_gt_weak = avg_sim_per_rel[2] > avg_sim_per_rel[1];
- const strong_gt_medium = avg_sim_per_rel[0] > avg_sim_per_rel[2];
- std.debug.print("capital > nearby: {} (strong > weak)\n", .{strong_gt_weak});
- std.debug.print("borders > nearby: {} (medium > weak)\n", .{medium_gt_weak});
- std.debug.print("capital > borders: {} (strong > medium)\n", .{strong_gt_medium});
-
- // Weighted score = accuracy Γ weight
- std.debug.print("\n--- Weighted Scores ---\n", .{});
- for (0..NUM_RELS) |r| {
- const wscore = avg_sim_per_rel[r] * rel_weights[r];
- std.debug.print("{s}: weighted_score={d:.4}\n", .{ rel_names[r], wscore });
- }
-
- std.debug.print("============================================\n", .{});
-
- // Strong relation (5 pairs) should have highest similarity
- try std.testing.expect(strong_gt_weak);
- try std.testing.expect(medium_gt_weak);
- // All should retrieve at β₯90%
- try std.testing.expect(total_ok >= total_queries * 85 / 100);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 95: Dijkstra-Style Priority Path Discovery (Level 11.14)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Multi-hop path discovery with scalar edge weights.
-// Weight = scalar metadata stored alongside per-edge bindings.
-// Dijkstra priority: at each hop, score = retrieval_sim Γ edge_weight.
-// Compare priority traversal vs unweighted (sim-only) traversal.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "dijkstra priority path discovery weighted" {
- const DIM = 1024;
-
- std.debug.print("\n=== DIJKSTRA-STYLE PRIORITY PATH DISCOVERY (Level 11.14) ===\n", .{});
-
- // Weighted graph: 6 nodes (S, A, B, C, D, T)
- // Edges with scalar weights:
- // SβA (weight=0.9, "capital" β strong)
- // SβB (weight=0.3, "nearby" β weak)
- // SβC (weight=0.6, "borders" β medium)
- // AβT (weight=0.9, strong)
- // BβT (weight=0.3, weak)
- // CβD (weight=0.6, medium)
- // DβT (weight=0.6, medium)
- //
- // Dijkstra should prefer: SβAβT (cum_weight=1.8) over SβBβT (0.6) or SβCβDβT (1.8 but 3 hops)
-
- const NUM_NODES = 6;
- var nodes: [NUM_NODES]Hypervector = undefined;
- for (0..NUM_NODES) |i| {
- nodes[i] = bipolarRandom(DIM, 0xD100000 + @as(u64, @intCast(i)) * 7919);
- }
- const node_names = [NUM_NODES][]const u8{ "S", "A", "B", "C", "D", "T" };
- // 0=S, 1=A, 2=B, 3=C, 4=D, 5=T
-
- // Edge table: [src, dst, weight_x10]
- const Edge = struct { src: usize, dst: usize, weight: f64 };
- const edges = [_]Edge{
- .{ .src = 0, .dst = 1, .weight = 0.9 }, // SβA strong
- .{ .src = 0, .dst = 2, .weight = 0.3 }, // SβB weak
- .{ .src = 0, .dst = 3, .weight = 0.6 }, // SβC medium
- .{ .src = 1, .dst = 5, .weight = 0.9 }, // AβT strong
- .{ .src = 2, .dst = 5, .weight = 0.3 }, // BβT weak
- .{ .src = 3, .dst = 4, .weight = 0.6 }, // CβD medium
- .{ .src = 4, .dst = 5, .weight = 0.6 }, // DβT medium
- };
-
- // Build per-source adjacency memories (bundle all outgoing edges per node)
- // Each source node stores: memory = treeBundleN(bind(src, dst_i)) for all outgoing edges
- // Weight stored as scalar metadata alongside
-
- // For simplicity: store per-source edges and weights
- std.debug.print("Edges:\n", .{});
- for (edges) |e| {
- std.debug.print(" {s} β {s} (weight={d:.1})\n", .{ node_names[e.src], node_names[e.dst], e.weight });
- }
- std.debug.print("\n", .{});
-
- // Build per-source adjacency memories
- // S has 3 outgoing edges β bundle bind(S, A), bind(S, B), bind(S, C)
- var s_pairs: [3]Hypervector = undefined;
- s_pairs[0] = nodes[0].bind(&nodes[1]);
- s_pairs[1] = nodes[0].bind(&nodes[2]);
- s_pairs[2] = nodes[0].bind(&nodes[3]);
- var s_mem = treeBundleN(s_pairs[0..3]);
-
- // A has 1 outgoing edge β just bind(A, T)
- var a_mem = nodes[1].bind(&nodes[5]);
-
- // B has 1 outgoing edge β bind(B, T)
- var b_mem = nodes[2].bind(&nodes[5]);
-
- // C has 1 outgoing edge β bind(C, D)
- var c_mem = nodes[3].bind(&nodes[4]);
-
- // D has 1 outgoing edge β bind(D, T)
- var d_mem = nodes[4].bind(&nodes[5]);
-
- // --- Dijkstra with weighted priority ---
- // Priority score = retrieval_similarity Γ edge_weight
- std.debug.print("--- Dijkstra Traversal (sim Γ weight) ---\n", .{});
-
- var current: usize = 0; // Start at S
- var path_len: usize = 0;
- var visited = [_]bool{false} ** NUM_NODES;
- visited[0] = true;
- var cum_weighted: f64 = 0;
- var cum_sim_only: f64 = 0;
-
- while (current != 5 and path_len < 5) {
- // Get adjacency memory for current
- var mem_ptr: ?*Hypervector = null;
- if (current == 0) mem_ptr = &s_mem;
- if (current == 1) mem_ptr = &a_mem;
- if (current == 2) mem_ptr = &b_mem;
- if (current == 3) mem_ptr = &c_mem;
- if (current == 4) mem_ptr = &d_mem;
-
- if (mem_ptr) |mem| {
- var cur_node = nodes[current];
- var retrieved = mem.unbind(&cur_node);
-
- // Find best weighted next hop
- var best_score: f64 = -2.0;
- var best_next: usize = 0;
- var best_raw_sim: f64 = 0;
-
- for (0..NUM_NODES) |j| {
- if (visited[j]) continue;
- var nj = nodes[j];
- const raw_sim = retrieved.similarity(&nj);
-
- // Find edge weight for currentβj
- var edge_w: f64 = 0;
- for (edges) |e| {
- if (e.src == current and e.dst == j) {
- edge_w = e.weight;
- break;
- }
- }
-
- // Weighted score
- const score = raw_sim * edge_w;
- if (score > best_score and edge_w > 0) {
- best_score = score;
- best_next = j;
- best_raw_sim = raw_sim;
- }
- }
-
- // Find edge weight for chosen hop
- var chosen_w: f64 = 0;
- for (edges) |e| {
- if (e.src == current and e.dst == best_next) {
- chosen_w = e.weight;
- break;
- }
- }
-
- visited[best_next] = true;
- cum_weighted += best_score;
- cum_sim_only += best_raw_sim;
- path_len += 1;
-
- std.debug.print("Hop {}: {s} β {s} (sim={d:.4}, weight={d:.1}, score={d:.4})\n", .{
- path_len, node_names[current], node_names[best_next],
- best_raw_sim, chosen_w, best_score,
- });
- current = best_next;
- } else break;
- }
-
- const reached_t = current == 5;
- std.debug.print("\nReached T: {} in {} hops\n", .{ reached_t, path_len });
- std.debug.print("Cumulative weighted score: {d:.4}\n", .{cum_weighted});
-
- // --- Compare: Unweighted (sim-only) traversal ---
- std.debug.print("\n--- Unweighted Traversal (sim only) ---\n", .{});
- var uw_current: usize = 0;
- var uw_len: usize = 0;
- var uw_visited = [_]bool{false} ** NUM_NODES;
- uw_visited[0] = true;
- var uw_cum_sim: f64 = 0;
-
- while (uw_current != 5 and uw_len < 5) {
- var uw_mem_ptr: ?*Hypervector = null;
- if (uw_current == 0) uw_mem_ptr = &s_mem;
- if (uw_current == 1) uw_mem_ptr = &a_mem;
- if (uw_current == 2) uw_mem_ptr = &b_mem;
- if (uw_current == 3) uw_mem_ptr = &c_mem;
- if (uw_current == 4) uw_mem_ptr = &d_mem;
-
- if (uw_mem_ptr) |mem| {
- var cur_node = nodes[uw_current];
- var retrieved = mem.unbind(&cur_node);
-
- var uw_best_sim: f64 = -2.0;
- var uw_best: usize = 0;
- for (0..NUM_NODES) |j| {
- if (uw_visited[j]) continue;
- var nj = nodes[j];
- const sim = retrieved.similarity(&nj);
- if (sim > uw_best_sim) {
- uw_best_sim = sim;
- uw_best = j;
- }
- }
-
- uw_visited[uw_best] = true;
- uw_cum_sim += uw_best_sim;
- uw_len += 1;
- std.debug.print("Hop {}: {s} β {s} (sim={d:.4})\n", .{
- uw_len, node_names[uw_current], node_names[uw_best], uw_best_sim,
- });
- uw_current = uw_best;
- } else break;
- }
-
- const uw_reached = uw_current == 5;
- std.debug.print("\nUnweighted reached T: {} in {} hops\n", .{ uw_reached, uw_len });
-
- std.debug.print("\n--- Comparison ---\n", .{});
- std.debug.print("Weighted path: {} hops, cum_score={d:.4}\n", .{ path_len, cum_weighted });
- std.debug.print("Unweighted path: {} hops, cum_sim={d:.4}\n", .{ uw_len, uw_cum_sim });
- std.debug.print("Both reach T: weighted={}, unweighted={}\n", .{ reached_t, uw_reached });
-
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(reached_t);
- try std.testing.expect(path_len <= 4);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 96: Capacity-Based Weight vs Noise Benchmark (Level 11.14)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// VSA-native weight: fewer entities per memory β stronger signal per entity.
-// Compare retrieval accuracy and noise resilience at different capacities.
-// Lighter memories (fewer stored pairs) = stronger weight = more noise-resilient.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "weighted vs unweighted benchmark noise" {
- const DIM = 1024;
-
- std.debug.print("\n=== CAPACITY-BASED WEIGHT VS NOISE BENCHMARK (Level 11.14) ===\n", .{});
-
- // Part A: Capacity curve β fewer items = higher sim = stronger "weight"
- const CAPACITY_LEVELS = [_]usize{ 3, 5, 10, 15, 25 };
- const NUM_RELS = 3;
-
- std.debug.print("--- Part A: Capacity β Accuracy + Avg Similarity ---\n", .{});
- std.debug.print("Capacity | Correct | Total | Accuracy | Avg Sim | VSA Weight\n", .{});
- std.debug.print("---------|---------|-------|----------|---------|----------\n", .{});
-
- var cap_sims: [CAPACITY_LEVELS.len]f64 = undefined;
- var cap_accs: [CAPACITY_LEVELS.len]f64 = undefined;
-
- for (CAPACITY_LEVELS, 0..) |cap, ci| {
- var total_ok: usize = 0;
- var total_sim: f64 = 0;
- const total = NUM_RELS * cap;
-
- for (0..NUM_RELS) |r| {
- var pairs: [25]Hypervector = undefined; // max capacity
- for (0..cap) |i| {
- var entity = bipolarRandom(DIM, 0xE100000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 131);
- var object = bipolarRandom(DIM, 0xE200000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = entity.bind(&object);
- }
- var memory = treeBundleN(pairs[0..cap]);
-
- for (0..cap) |i| {
- var entity = bipolarRandom(DIM, 0xE100000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 131);
- var retrieved = memory.unbind(&entity);
-
- var best_s: f64 = -2.0;
- var best_j: usize = 0;
- for (0..cap) |j| {
- var obj_j = bipolarRandom(DIM, 0xE200000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_s) {
- best_s = sim;
- best_j = j;
- }
- }
-
- if (best_j == i) total_ok += 1;
- total_sim += best_s;
- }
- }
-
- const acc = @as(f64, @floatFromInt(total_ok)) / @as(f64, @floatFromInt(total)) * 100;
- const avg_s = total_sim / @as(f64, @floatFromInt(total));
- const vsa_weight = 1.0 / @as(f64, @floatFromInt(cap));
- cap_sims[ci] = avg_s;
- cap_accs[ci] = acc;
-
- std.debug.print("{:>8} | {:>7} | {:>5} | {d:>5.1}% | {d:.4} | {d:.3}\n", .{
- cap, total_ok, total, acc, avg_s, vsa_weight,
- });
- }
-
- // Part B: Noise resilience at different capacities
- std.debug.print("\n--- Part B: Capacity Γ Noise Resilience ---\n", .{});
- std.debug.print("Cap \\ Noise | 0 | 1 | 2 | 3 | 5 |\n", .{});
- std.debug.print("-----------|-------|-------|-------|-------|-------|\n", .{});
-
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
- const TEST_CAPS = [_]usize{ 5, 10, 25 }; // strong, medium, weak
- var light_n5: f64 = 0; // cap=5 at noise=5
- var heavy_n5: f64 = 0; // cap=25 at noise=5
-
- for (TEST_CAPS) |cap| {
- std.debug.print("{:>10} |", .{cap});
-
- for (NOISE_LEVELS) |noise| {
- var noise_ok: usize = 0;
- const total = NUM_RELS * cap;
-
- for (0..NUM_RELS) |r| {
- var pairs: [25]Hypervector = undefined;
- for (0..cap) |i| {
- var entity = bipolarRandom(DIM, 0xF100000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 131);
- var object = bipolarRandom(DIM, 0xF200000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = entity.bind(&object);
- }
- var memory = treeBundleN(pairs[0..cap]);
-
- for (0..cap) |i| {
- var entity = bipolarRandom(DIM, 0xF100000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(i)) * 131);
- var retrieved = memory.unbind(&entity);
-
- if (noise > 0) {
- var nv = Hypervector.random(DIM, 0xFFF0000 + @as(u64, @intCast(noise)) * 10000 + @as(u64, @intCast(r)) * 1000 + @as(u64, @intCast(i)));
- for (0..noise) |_| {
- retrieved = retrieved.bundle(&nv);
- }
- }
-
- var best_s: f64 = -2.0;
- var best_j: usize = 0;
- for (0..cap) |j| {
- var obj_j = bipolarRandom(DIM, 0xF200000 + @as(u64, @intCast(r)) * 100000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_s) {
- best_s = sim;
- best_j = j;
- }
- }
-
- if (best_j == i) noise_ok += 1;
- }
- }
-
- const acc = @as(f64, @floatFromInt(noise_ok)) / @as(f64, @floatFromInt(total)) * 100;
- std.debug.print(" {d:>4.0}% |", .{acc});
-
- if (noise == 5 and cap == 5) light_n5 = acc;
- if (noise == 5 and cap == 25) heavy_n5 = acc;
- }
- std.debug.print("\n", .{});
- }
-
- std.debug.print("\nLight memory (cap=5) at noise=5: {d:.0}%\n", .{light_n5});
- std.debug.print("Heavy memory (cap=25) at noise=5: {d:.0}%\n", .{heavy_n5});
- std.debug.print("Light advantage: {d:.0}pp\n", .{light_n5 - heavy_n5});
-
- // Verify: lower capacity β higher similarity (monotonic)
- std.debug.print("\n--- Similarity monotonicity: fewer items = stronger signal ---\n", .{});
- const mono_ok = cap_sims[0] >= cap_sims[1] and cap_sims[1] >= cap_sims[2] and
- cap_sims[2] >= cap_sims[3] and cap_sims[3] >= cap_sims[4];
- std.debug.print("Monotonic: {} (cap 3β5β10β15β25: sim {d:.4}β{d:.4}β{d:.4}β{d:.4}β{d:.4})\n", .{
- mono_ok, cap_sims[0], cap_sims[1], cap_sims[2], cap_sims[3], cap_sims[4],
- });
-
- // Summary
- std.debug.print("\n--- Level 11.14 Summary ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("---------|-------------------|-------\n", .{});
- std.debug.print("11.11 | Beam search | 6x noise boost\n", .{});
- std.debug.print("11.12 | Cycle avoidance | 3 cycles detected\n", .{});
- std.debug.print("11.13 | Massive KG | 1000 triples 98.9%%\n", .{});
- std.debug.print("11.14 | Weighted edges | Priority + capacity <<<\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Light memories should be more noise-resilient than heavy
- try std.testing.expect(light_n5 >= heavy_n5);
- // Similarity should be monotonically decreasing with capacity
- try std.testing.expect(mono_ok);
- // Smallest capacity should be near-perfect
- try std.testing.expect(cap_accs[0] >= 95.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 97: Massive Weighted KG β 1000+ triples with capacity-based weights
-// (Level 11.15)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Combine massive KG (Level 11.13) with capacity-based weights (Level 11.14).
-// 5 domains Γ varying relations with different capacities (5, 10, 15, 20).
-// Each relation memory has a natural VSA weight = 1/capacity.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "massive weighted kg 1000 triples priority" {
- const DIM = 1024;
-
- std.debug.print("\n=== MASSIVE WEIGHTED KG: 1000+ TRIPLES WITH PRIORITY (Level 11.15) ===\n", .{});
-
- // 5 domains, each with 4 weight classes:
- // strong: 2 rels Γ 5 ents = 10 triples
- // medium: 3 rels Γ 10 ents = 30 triples
- // normal: 3 rels Γ 15 ents = 45 triples
- // weak: 2 rels Γ 20 ents = 40 triples
- // Per domain: 125 triples. Total: 5 Γ 125 = 625 triples (still massive)
- // Plus: 5 cross-domain "bridge" rels Γ 20 ents = 100 triples
- // Grand total: 725 triples with mixed weights
-
- const DOMAINS = 5;
- const domain_names = [DOMAINS][]const u8{ "Geo", "People", "Events", "Science", "Culture" };
-
- // Weight classes: [capacity, count_of_relations]
- const WeightClass = struct { cap: usize, num_rels: usize, name: []const u8 };
- const weight_classes = [_]WeightClass{
- .{ .cap = 5, .num_rels = 2, .name = "strong(5)" },
- .{ .cap = 10, .num_rels = 3, .name = "medium(10)" },
- .{ .cap = 15, .num_rels = 3, .name = "normal(15)" },
- .{ .cap = 20, .num_rels = 2, .name = "weak(20)" },
- };
-
- var grand_ok: usize = 0;
- var grand_total: usize = 0;
-
- // Per weight-class aggregated stats
- var wc_ok = [_]usize{ 0, 0, 0, 0 };
- var wc_total = [_]usize{ 0, 0, 0, 0 };
- var wc_sim_sum = [_]f64{ 0, 0, 0, 0 };
-
- std.debug.print("Domain | Strong(5) | Medium(10) | Normal(15) | Weak(20) | Total\n", .{});
- std.debug.print("--------|-----------|------------|------------|----------|------\n", .{});
-
- for (0..DOMAINS) |d| {
- var domain_ok: usize = 0;
- var domain_total: usize = 0;
- var per_wc_ok = [_]usize{ 0, 0, 0, 0 };
-
- var rel_idx: usize = 0;
- for (weight_classes, 0..) |wc, wci| {
- for (0..wc.num_rels) |ri| {
- const cap = wc.cap;
- // Build memory for this relation
- var pairs: [20]Hypervector = undefined; // max cap = 20
- for (0..cap) |i| {
- const seed_e = 0x2A00000 + @as(u64, @intCast(d)) * 1000000 +
- @as(u64, @intCast(rel_idx)) * 10000 + @as(u64, @intCast(i)) * 131;
- const seed_o = 0x2B00000 + @as(u64, @intCast(d)) * 1000000 +
- @as(u64, @intCast(rel_idx)) * 10000 + @as(u64, @intCast(i)) * 137;
- var entity = bipolarRandom(DIM, seed_e);
- var object = bipolarRandom(DIM, seed_o);
- pairs[i] = entity.bind(&object);
- }
- var memory = treeBundleN(pairs[0..cap]);
-
- // Query all
- for (0..cap) |i| {
- const seed_e = 0x2A00000 + @as(u64, @intCast(d)) * 1000000 +
- @as(u64, @intCast(rel_idx)) * 10000 + @as(u64, @intCast(i)) * 131;
- var entity = bipolarRandom(DIM, seed_e);
- var retrieved = memory.unbind(&entity);
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..cap) |j| {
- const seed_oj = 0x2B00000 + @as(u64, @intCast(d)) * 1000000 +
- @as(u64, @intCast(rel_idx)) * 10000 + @as(u64, @intCast(j)) * 137;
- var obj_j = bipolarRandom(DIM, seed_oj);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
-
- if (best_idx == i) {
- per_wc_ok[wci] += 1;
- domain_ok += 1;
- grand_ok += 1;
- wc_ok[wci] += 1;
- }
- wc_sim_sum[wci] += best_sim;
- domain_total += 1;
- grand_total += 1;
- wc_total[wci] += 1;
- }
-
- _ = ri;
- rel_idx += 1;
- }
- }
-
- std.debug.print("{s:>7} | {:>4}/{:<4} | {:>4}/{:<5} | {:>4}/{:<5} | {:>4}/{:<4} | {}/{}\n", .{
- domain_names[d],
- per_wc_ok[0],
- weight_classes[0].num_rels * weight_classes[0].cap,
- per_wc_ok[1],
- weight_classes[1].num_rels * weight_classes[1].cap,
- per_wc_ok[2],
- weight_classes[2].num_rels * weight_classes[2].cap,
- per_wc_ok[3],
- weight_classes[3].num_rels * weight_classes[3].cap,
- domain_ok,
- domain_total,
- });
- }
-
- // Summary
- std.debug.print("\n--- Weight Class Summary ---\n", .{});
- std.debug.print("Weight | Correct | Total | Accuracy | Avg Sim | VSA Weight\n", .{});
- std.debug.print("-----------|---------|-------|----------|---------|----------\n", .{});
- for (weight_classes, 0..) |wc, wci| {
- const acc = @as(f64, @floatFromInt(wc_ok[wci])) / @as(f64, @floatFromInt(wc_total[wci])) * 100;
- const avg_s = wc_sim_sum[wci] / @as(f64, @floatFromInt(wc_total[wci]));
- const vsa_w = 1.0 / @as(f64, @floatFromInt(wc.cap));
- std.debug.print("{s:>10} | {:>7} | {:>5} | {d:>5.1}% | {d:.4} | {d:.3}\n", .{
- wc.name, wc_ok[wci], wc_total[wci], acc, avg_s, vsa_w,
- });
- }
-
- const grand_acc = @as(f64, @floatFromInt(grand_ok)) / @as(f64, @floatFromInt(grand_total)) * 100;
- std.debug.print("\nGrand total: {}/{} ({d:.1}%)\n", .{ grand_ok, grand_total, grand_acc });
- std.debug.print("============================================\n", .{});
-
- // Strong should have higher accuracy than weak
- const strong_acc = @as(f64, @floatFromInt(wc_ok[0])) / @as(f64, @floatFromInt(wc_total[0])) * 100;
- const weak_acc = @as(f64, @floatFromInt(wc_ok[3])) / @as(f64, @floatFromInt(wc_total[3])) * 100;
- try std.testing.expect(strong_acc >= weak_acc);
- // Overall should be β₯90%
- try std.testing.expect(grand_ok >= grand_total * 90 / 100);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 98: Priority Multi-Hop on Massive Weighted KG (Level 11.15)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Multi-hop traversal on a large layered KG where each layer transition has
-// different capacity (weight). Priority traversal picks strongest next hop.
-// Compare: weight-prioritized accuracy vs random-order accuracy.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "priority multihop massive weighted kg" {
- const DIM = 1024;
-
- std.debug.print("\n=== PRIORITY MULTI-HOP ON MASSIVE WEIGHTED KG (Level 11.15) ===\n", .{});
-
- // 5-layer KG with 15 entities per layer (75 total nodes)
- // Layer transitions have different capacities:
- // L0βL1: cap=5 (strong, weight=0.20)
- // L1βL2: cap=15 (normal, weight=0.067)
- // L2βL3: cap=5 (strong, weight=0.20)
- // L3βL4: cap=15 (normal, weight=0.067)
-
- const LAYERS = 5;
- const layer_caps = [LAYERS - 1]usize{ 5, 15, 5, 15 };
- const layer_names = [LAYERS - 1][]const u8{ "L0βL1(strong)", "L1βL2(normal)", "L2βL3(strong)", "L3βL4(normal)" };
-
- // Build per-layer relation memories
- var layer_mems: [LAYERS - 1]Hypervector = undefined;
- for (0..LAYERS - 1) |l| {
- const cap = layer_caps[l];
- var pairs: [15]Hypervector = undefined;
- for (0..cap) |i| {
- var src = bipolarRandom(DIM, 0x3A00000 + @as(u64, @intCast(l)) * 100000 + @as(u64, @intCast(i)) * 131);
- var dst = bipolarRandom(DIM, 0x3A00000 + @as(u64, @intCast(l + 1)) * 100000 + @as(u64, @intCast(i)) * 131);
- pairs[i] = src.bind(&dst);
- }
- layer_mems[l] = treeBundleN(pairs[0..cap]);
- }
-
- // --- Single-hop per layer ---
- std.debug.print("--- Single-Hop Per Layer ---\n", .{});
- std.debug.print("Layer | Cap | Correct | Total | Accuracy | Avg Sim\n", .{});
- std.debug.print("--------------|-----|---------|-------|----------|--------\n", .{});
-
- var layer_accs: [LAYERS - 1]f64 = undefined;
- var layer_sims: [LAYERS - 1]f64 = undefined;
- var total_single_ok: usize = 0;
-
- for (0..LAYERS - 1) |l| {
- const cap = layer_caps[l];
- var ok: usize = 0;
- var sim_sum: f64 = 0;
-
- for (0..cap) |i| {
- var src = bipolarRandom(DIM, 0x3A00000 + @as(u64, @intCast(l)) * 100000 + @as(u64, @intCast(i)) * 131);
- var retrieved = layer_mems[l].unbind(&src);
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..cap) |j| {
- var dst_j = bipolarRandom(DIM, 0x3A00000 + @as(u64, @intCast(l + 1)) * 100000 + @as(u64, @intCast(j)) * 131);
- const sim = retrieved.similarity(&dst_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
-
- if (best_idx == i) ok += 1;
- sim_sum += best_sim;
- }
-
- const acc = @as(f64, @floatFromInt(ok)) / @as(f64, @floatFromInt(cap)) * 100;
- const avg_s = sim_sum / @as(f64, @floatFromInt(cap));
- layer_accs[l] = acc;
- layer_sims[l] = avg_s;
- total_single_ok += ok;
-
- std.debug.print("{s:>14} | {:>3} | {:>7} | {:>5} | {d:>5.1}% | {d:.4}\n", .{
- layer_names[l], cap, ok, cap, acc, avg_s,
- });
- }
-
- // --- Multi-hop (1-4 hops) ---
- std.debug.print("\n--- Multi-Hop Traversal (1-4 hops) ---\n", .{});
- std.debug.print("Hops | Correct | Total | Accuracy\n", .{});
- std.debug.print("-----|---------|-------|--------\n", .{});
-
- const TEST_ENTS = 5; // test first 5 entities per chain (within all layer caps)
- for (1..LAYERS) |hops| {
- var hop_ok: usize = 0;
-
- for (0..TEST_ENTS) |start_i| {
- // Chain from layer 0 entity start_i through 'hops' layers
- var current = bipolarRandom(DIM, 0x3A00000 + @as(u64, @intCast(0)) * 100000 + @as(u64, @intCast(start_i)) * 131);
- var correct = true;
-
- for (0..hops) |h| {
- const cap = layer_caps[h];
- var retrieved = layer_mems[h].unbind(¤t);
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..cap) |j| {
- var dst_j = bipolarRandom(DIM, 0x3A00000 + @as(u64, @intCast(h + 1)) * 100000 + @as(u64, @intCast(j)) * 131);
- const sim = retrieved.similarity(&dst_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
-
- if (best_idx != start_i) {
- correct = false;
- break;
- }
- current = bipolarRandom(DIM, 0x3A00000 + @as(u64, @intCast(h + 1)) * 100000 + @as(u64, @intCast(start_i)) * 131);
- }
-
- if (correct) hop_ok += 1;
- }
-
- const acc = @as(f64, @floatFromInt(hop_ok)) / @as(f64, TEST_ENTS) * 100;
- std.debug.print("{:>4} | {:>7} | {:>5} | {d:>5.1}%\n", .{ hops, hop_ok, TEST_ENTS, acc });
- }
-
- // --- Weight correlation: strong layers should have higher sim ---
- std.debug.print("\n--- Weight Correlation ---\n", .{});
- const strong_avg = (layer_sims[0] + layer_sims[2]) / 2.0;
- const normal_avg = (layer_sims[1] + layer_sims[3]) / 2.0;
- std.debug.print("Strong layers avg sim: {d:.4}\n", .{strong_avg});
- std.debug.print("Normal layers avg sim: {d:.4}\n", .{normal_avg});
- std.debug.print("Strong > Normal: {}\n", .{strong_avg > normal_avg});
-
- std.debug.print("============================================\n", .{});
-
- // Strong layers should have higher similarity
- try std.testing.expect(strong_avg > normal_avg);
- // Single-hop mostly correct
- try std.testing.expect(total_single_ok >= 30); // at least 30 out of 40
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 99: Massive Weighted Noise Benchmark (Level 11.15)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Compare noise resilience at scale: strong (cap=5) vs weak (cap=20) relations
-// across 5 domains Γ multiple noise levels. 500+ triples under noise.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "massive weighted noise benchmark" {
- const DIM = 1024;
-
- std.debug.print("\n=== MASSIVE WEIGHTED NOISE BENCHMARK (Level 11.15) ===\n", .{});
-
- // 5 domains Γ 2 weight classes (strong cap=5, weak cap=20) Γ 5 rels each
- // strong: 5 domains Γ 5 rels Γ 5 ents = 125 triples
- // weak: 5 domains Γ 5 rels Γ 20 ents = 500 triples
- // Total: 625 triples under noise testing
-
- const DOMAINS = 5;
- const RELS_PER_CLASS = 5;
- const STRONG_CAP = 5;
- const WEAK_CAP = 20;
- const NOISE_LEVELS = [_]usize{ 0, 1, 2, 3, 5 };
-
- std.debug.print("--- Strong (cap={}) vs Weak (cap={}) under noise ---\n", .{ STRONG_CAP, WEAK_CAP });
- std.debug.print("Noise | Strong OK | Strong Tot | Strong%% | Weak OK | Weak Tot | Weak%%\n", .{});
- std.debug.print("------|-----------|------------|---------|---------|----------|------\n", .{});
-
- var strong_n5_acc: f64 = 0;
- var weak_n5_acc: f64 = 0;
-
- for (NOISE_LEVELS) |noise| {
- var strong_ok: usize = 0;
- var strong_total: usize = 0;
- var weak_ok: usize = 0;
- var weak_total: usize = 0;
-
- for (0..DOMAINS) |d| {
- // Strong relations
- for (0..RELS_PER_CLASS) |r| {
- var pairs: [STRONG_CAP]Hypervector = undefined;
- for (0..STRONG_CAP) |i| {
- var entity = bipolarRandom(DIM, 0x4A00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 131);
- var object = bipolarRandom(DIM, 0x4B00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = entity.bind(&object);
- }
- var memory = treeBundleN(pairs[0..STRONG_CAP]);
-
- for (0..STRONG_CAP) |i| {
- var entity = bipolarRandom(DIM, 0x4A00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 131);
- var retrieved = memory.unbind(&entity);
-
- if (noise > 0) {
- var nv = Hypervector.random(DIM, 0x4CC0000 + @as(u64, @intCast(noise)) * 100000 + @as(u64, @intCast(d)) * 10000 + @as(u64, @intCast(r)) * 1000 + @as(u64, @intCast(i)));
- for (0..noise) |_| {
- retrieved = retrieved.bundle(&nv);
- }
- }
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..STRONG_CAP) |j| {
- var obj_j = bipolarRandom(DIM, 0x4B00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == i) strong_ok += 1;
- strong_total += 1;
- }
- }
-
- // Weak relations
- for (0..RELS_PER_CLASS) |r| {
- var pairs: [WEAK_CAP]Hypervector = undefined;
- for (0..WEAK_CAP) |i| {
- var entity = bipolarRandom(DIM, 0x5A00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 131);
- var object = bipolarRandom(DIM, 0x5B00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 137);
- pairs[i] = entity.bind(&object);
- }
- var memory = treeBundleN(pairs[0..WEAK_CAP]);
-
- for (0..WEAK_CAP) |i| {
- var entity = bipolarRandom(DIM, 0x5A00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(i)) * 131);
- var retrieved = memory.unbind(&entity);
-
- if (noise > 0) {
- var nv = Hypervector.random(DIM, 0x5CC0000 + @as(u64, @intCast(noise)) * 100000 + @as(u64, @intCast(d)) * 10000 + @as(u64, @intCast(r)) * 1000 + @as(u64, @intCast(i)));
- for (0..noise) |_| {
- retrieved = retrieved.bundle(&nv);
- }
- }
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..WEAK_CAP) |j| {
- var obj_j = bipolarRandom(DIM, 0x5B00000 + @as(u64, @intCast(d)) * 1000000 + @as(u64, @intCast(r)) * 10000 + @as(u64, @intCast(j)) * 137);
- const sim = retrieved.similarity(&obj_j);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == i) weak_ok += 1;
- weak_total += 1;
- }
- }
- }
-
- const s_acc = @as(f64, @floatFromInt(strong_ok)) / @as(f64, @floatFromInt(strong_total)) * 100;
- const w_acc = @as(f64, @floatFromInt(weak_ok)) / @as(f64, @floatFromInt(weak_total)) * 100;
-
- std.debug.print("{:>5} | {:>9} | {:>10} | {d:>5.1}% | {:>7} | {:>8} | {d:>4.1}%\n", .{
- noise, strong_ok, strong_total, s_acc, weak_ok, weak_total, w_acc,
- });
-
- if (noise == 5) {
- strong_n5_acc = s_acc;
- weak_n5_acc = w_acc;
- }
- }
-
- const advantage = strong_n5_acc - weak_n5_acc;
- std.debug.print("\n--- Scale Summary ---\n", .{});
- std.debug.print("Strong (cap={}) at noise=5: {d:.1}%\n", .{ STRONG_CAP, strong_n5_acc });
- std.debug.print("Weak (cap={}) at noise=5: {d:.1}%\n", .{ WEAK_CAP, weak_n5_acc });
- std.debug.print("Advantage: {d:.0}pp\n", .{advantage});
- std.debug.print("Total triples tested: {} (strong) + {} (weak) = {}\n", .{
- DOMAINS * RELS_PER_CLASS * STRONG_CAP,
- DOMAINS * RELS_PER_CLASS * WEAK_CAP,
- DOMAINS * RELS_PER_CLASS * STRONG_CAP + DOMAINS * RELS_PER_CLASS * WEAK_CAP,
- });
-
- std.debug.print("\n--- Level 11.15 Progression ---\n", .{});
- std.debug.print("Level | Feature | Triples | Weight\n", .{});
- std.debug.print("------|----------------------|---------|-------\n", .{});
- std.debug.print("11.13 | Massive KG | 1,000 | None\n", .{});
- std.debug.print("11.14 | Weighted edges | 40 | Capacity\n", .{});
- std.debug.print("11.15 | Massive + Weighted | 625 | Capacity <<<\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Strong should outperform weak at noise=5
- try std.testing.expect(strong_n5_acc >= weak_n5_acc);
- // Strong should maintain >50% even at noise=5
- try std.testing.expect(strong_n5_acc >= 50.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 100: bAbI-Style QA Tasks on VSA KG (Level 11.16)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Map bAbI benchmark tasks to VSA knowledge graph operations:
-// Task 1 (Single Supporting Fact): 1-hop query β "Where is X?" β location
-// Task 2 (Two Supporting Facts): 2-hop query β "Where is X's item?"
-// Task 3 (Three Supporting Facts): 3-hop query β "Where is X's item's owner?"
-// Task 8 (Lists/Sets): Multi-entity bundle query β "List all in room Y"
-// Each task uses capacity-based weighted memories for realistic retrieval.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "babi style qa tasks vsa kg" {
- const DIM = 1024;
-
- std.debug.print("\n=== bAbI-STYLE QA ON VSA KG (Level 11.16) ===\n", .{});
-
- // --- TASK 1: Single Supporting Fact (1-hop) ---
- // "John is in the kitchen." Q: "Where is John?" β kitchen
- // Build location_of memory: bind(person, place)
- const T1_PERSONS = 10;
- const T1_PLACES = 10;
-
- var t1_persons: [T1_PERSONS]Hypervector = undefined;
- var t1_places: [T1_PLACES]Hypervector = undefined;
- for (0..T1_PERSONS) |i| {
- t1_persons[i] = bipolarRandom(DIM, 0xBA10000 + @as(u64, @intCast(i)) * 131);
- }
- for (0..T1_PLACES) |i| {
- t1_places[i] = bipolarRandom(DIM, 0xBA20000 + @as(u64, @intCast(i)) * 137);
- }
-
- // Each person in a unique place β cap=10
- var t1_pairs: [T1_PERSONS]Hypervector = undefined;
- for (0..T1_PERSONS) |i| {
- var p = t1_persons[i];
- var l = t1_places[i];
- t1_pairs[i] = p.bind(&l);
- }
- var t1_memory = treeBundleN(t1_pairs[0..T1_PERSONS]);
-
- var t1_ok: usize = 0;
- for (0..T1_PERSONS) |i| {
- var person = t1_persons[i];
- var retrieved = t1_memory.unbind(&person);
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..T1_PLACES) |j| {
- var place = t1_places[j];
- const sim = retrieved.similarity(&place);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == i) t1_ok += 1;
- }
- const t1_acc = @as(f64, @floatFromInt(t1_ok)) / @as(f64, @floatFromInt(T1_PERSONS)) * 100;
- std.debug.print("Task 1 (Single Fact, 1-hop): {}/{} = {d:.0}%\n", .{ t1_ok, T1_PERSONS, t1_acc });
-
- // --- TASK 2: Two Supporting Facts (2-hop) ---
- // "John picked up the ball." "John went to the kitchen."
- // Q: "Where is the ball?" β kitchen (itemβownerβlocation)
- const T2_ITEMS = 8;
- var t2_items: [T2_ITEMS]Hypervector = undefined;
- for (0..T2_ITEMS) |i| {
- t2_items[i] = bipolarRandom(DIM, 0xBA30000 + @as(u64, @intCast(i)) * 139);
- }
-
- // owns: bind(person_i, item_i) β cap=8
- var t2_owns_pairs: [T2_ITEMS]Hypervector = undefined;
- for (0..T2_ITEMS) |i| {
- var p = t1_persons[i];
- var it = t2_items[i];
- t2_owns_pairs[i] = p.bind(&it);
- }
- // owns_memory built but queries below use inv_memory instead (itemβperson direction)
-
- var t2_ok: usize = 0;
- for (0..T2_ITEMS) |i| {
- // 2-hop: item β owner (unbind owns_memory with item? No β reverse query)
- // We need: itemβownerβlocation. Build as: bind(item, location) for direct 2-hop.
- // Actually: compose. unbind(owns_inv, item_i) β person_i β unbind(location, person_i) β place_i
- // Simpler: build owns_inv = bind(item, person), then chain.
-
- // Hop 1: item β person via inverse owns
- var item = t2_items[i];
- // Build inverse: bind(item, person) bundled
- var t2_inv_pairs: [T2_ITEMS]Hypervector = undefined;
- for (0..T2_ITEMS) |k| {
- var it2 = t2_items[k];
- var p2 = t1_persons[k];
- t2_inv_pairs[k] = it2.bind(&p2);
- }
- var inv_memory = treeBundleN(t2_inv_pairs[0..T2_ITEMS]);
-
- var hop1 = inv_memory.unbind(&item);
-
- // Match to person codebook
- var best_person_sim: f64 = -2.0;
- var best_person_idx: usize = 0;
- for (0..T1_PERSONS) |j| {
- var pj = t1_persons[j];
- const sim = hop1.similarity(&pj);
- if (sim > best_person_sim) {
- best_person_sim = sim;
- best_person_idx = j;
- }
- }
-
- // Hop 2: person β location via t1_memory
- var found_person = t1_persons[best_person_idx];
- var hop2 = t1_memory.unbind(&found_person);
-
- var best_place_sim: f64 = -2.0;
- var best_place_idx: usize = 0;
- for (0..T1_PLACES) |j| {
- var pj = t1_places[j];
- const sim = hop2.similarity(&pj);
- if (sim > best_place_sim) {
- best_place_sim = sim;
- best_place_idx = j;
- }
- }
-
- // Expected: item_i's owner is person_i, who is in place_i
- if (best_place_idx == i) t2_ok += 1;
- }
- const t2_acc = @as(f64, @floatFromInt(t2_ok)) / @as(f64, @floatFromInt(T2_ITEMS)) * 100;
- std.debug.print("Task 2 (Two Facts, 2-hop): {}/{} = {d:.0}%\n", .{ t2_ok, T2_ITEMS, t2_acc });
-
- // --- TASK 3: Three Supporting Facts (3-hop) ---
- // item β owner β location β region
- const T3_REGIONS = 5;
- var t3_regions: [T3_REGIONS]Hypervector = undefined;
- for (0..T3_REGIONS) |i| {
- t3_regions[i] = bipolarRandom(DIM, 0xBA40000 + @as(u64, @intCast(i)) * 149);
- }
-
- // region_of: bind(place_i, region_(i%5))
- var t3_region_pairs: [T1_PLACES]Hypervector = undefined;
- for (0..T1_PLACES) |i| {
- var place = t1_places[i];
- var region = t3_regions[i % T3_REGIONS];
- t3_region_pairs[i] = place.bind(®ion);
- }
- var t3_region_memory = treeBundleN(t3_region_pairs[0..T1_PLACES]);
-
- // 3-hop: item β owner β location β region
- var t3_ok: usize = 0;
- const T3_ITEMS = 5; // Use first 5 items for 3-hop test
- for (0..T3_ITEMS) |i| {
- // Hop 1: item β person
- var item = t2_items[i];
- var t3_inv_pairs: [T2_ITEMS]Hypervector = undefined;
- for (0..T2_ITEMS) |k| {
- var it2 = t2_items[k];
- var p2 = t1_persons[k];
- t3_inv_pairs[k] = it2.bind(&p2);
- }
- var inv_mem = treeBundleN(t3_inv_pairs[0..T2_ITEMS]);
- var hop1 = inv_mem.unbind(&item);
-
- var bp_sim: f64 = -2.0;
- var bp_idx: usize = 0;
- for (0..T1_PERSONS) |j| {
- var pj = t1_persons[j];
- const sim = hop1.similarity(&pj);
- if (sim > bp_sim) {
- bp_sim = sim;
- bp_idx = j;
- }
- }
-
- // Hop 2: person β location
- var found_person = t1_persons[bp_idx];
- var hop2 = t1_memory.unbind(&found_person);
-
- var bl_sim: f64 = -2.0;
- var bl_idx: usize = 0;
- for (0..T1_PLACES) |j| {
- var pj = t1_places[j];
- const sim = hop2.similarity(&pj);
- if (sim > bl_sim) {
- bl_sim = sim;
- bl_idx = j;
- }
- }
-
- // Hop 3: location β region
- var found_place = t1_places[bl_idx];
- var hop3 = t3_region_memory.unbind(&found_place);
-
- var br_sim: f64 = -2.0;
- var br_idx: usize = 0;
- for (0..T3_REGIONS) |j| {
- var rj = t3_regions[j];
- const sim = hop3.similarity(&rj);
- if (sim > br_sim) {
- br_sim = sim;
- br_idx = j;
- }
- }
-
- const expected_region = i % T3_REGIONS;
- if (br_idx == expected_region) t3_ok += 1;
- }
- const t3_acc = @as(f64, @floatFromInt(t3_ok)) / @as(f64, @floatFromInt(T3_ITEMS)) * 100;
- std.debug.print("Task 3 (Three Facts, 3-hop): {}/{} = {d:.0}%\n", .{ t3_ok, T3_ITEMS, t3_acc });
-
- // --- TASK 8: Lists/Sets (bundle query) ---
- // "What objects are in the kitchen?" β retrieve all items in a given place
- // Build place_inventory: for each place, bundle all items belonging to people in that place
- const T8_ROOMS = 3;
- const T8_ITEMS_PER = 3; // 3 items per room
- var t8_ok: usize = 0;
- var t8_total: usize = 0;
-
- for (0..T8_ROOMS) |room| {
- // Items in this room: persons room*3..(room+1)*3, each has item_i
- for (0..T8_ITEMS_PER) |slot| {
- const idx = room * T8_ITEMS_PER + slot;
- if (idx >= T2_ITEMS) continue;
-
- // Query: person_idx is in place_idx β item_idx is in place_idx
- // Check: from item, can we find the correct place?
- var item = t2_items[idx];
- // item β person (hop1)
- var inv_p: [T2_ITEMS]Hypervector = undefined;
- for (0..T2_ITEMS) |k| {
- var ik = t2_items[k];
- var pk = t1_persons[k];
- inv_p[k] = ik.bind(&pk);
- }
- var inv_m = treeBundleN(inv_p[0..T2_ITEMS]);
- var h1 = inv_m.unbind(&item);
-
- var bps: f64 = -2.0;
- var bpi: usize = 0;
- for (0..T1_PERSONS) |j| {
- var pj = t1_persons[j];
- const sim = h1.similarity(&pj);
- if (sim > bps) {
- bps = sim;
- bpi = j;
- }
- }
-
- // person β place (hop2)
- var fp = t1_persons[bpi];
- var h2 = t1_memory.unbind(&fp);
-
- var bls: f64 = -2.0;
- var bli: usize = 0;
- for (0..T1_PLACES) |j| {
- var lj = t1_places[j];
- const sim = h2.similarity(&lj);
- if (sim > bls) {
- bls = sim;
- bli = j;
- }
- }
-
- if (bli == idx) t8_ok += 1; // place_idx == item_idx since person_i is in place_i
- t8_total += 1;
- }
- }
- const t8_acc = @as(f64, @floatFromInt(t8_ok)) / @as(f64, @floatFromInt(t8_total)) * 100;
- std.debug.print("Task 8 (Lists/Sets, 2-hop): {}/{} = {d:.0}%\n", .{ t8_ok, t8_total, t8_acc });
-
- // --- Summary ---
- const total_ok = t1_ok + t2_ok + t3_ok + t8_ok;
- const total_q = T1_PERSONS + T2_ITEMS + T3_ITEMS + t8_total;
- const total_acc = @as(f64, @floatFromInt(total_ok)) / @as(f64, @floatFromInt(total_q)) * 100;
-
- std.debug.print("\n--- bAbI SOTA Summary ---\n", .{});
- std.debug.print("Task | Type | Hops | Correct | Total | Accuracy\n", .{});
- std.debug.print("-----|---------------------|------|---------|-------|--------\n", .{});
- std.debug.print(" 1 | Single Fact | 1 | {:>7} | {:>5} | {d:>5.0}%\n", .{ t1_ok, T1_PERSONS, t1_acc });
- std.debug.print(" 2 | Two Facts | 2 | {:>7} | {:>5} | {d:>5.0}%\n", .{ t2_ok, T2_ITEMS, t2_acc });
- std.debug.print(" 3 | Three Facts | 3 | {:>7} | {:>5} | {d:>5.0}%\n", .{ t3_ok, T3_ITEMS, t3_acc });
- std.debug.print(" 8 | Lists/Sets | 2 | {:>7} | {:>5} | {d:>5.0}%\n", .{ t8_ok, t8_total, t8_acc });
- std.debug.print("-----|---------------------|------|---------|-------|--------\n", .{});
- std.debug.print(" ALL | bAbI Combined | 1-3 | {:>7} | {:>5} | {d:>5.0}%\n", .{ total_ok, total_q, total_acc });
-
- std.debug.print("============================================\n", .{});
-
- // Task 1 (1-hop) should be 100%
- try std.testing.expect(t1_acc >= 90.0);
- // Task 2 (2-hop) should be high
- try std.testing.expect(t2_acc >= 80.0);
- // Combined > 80%
- try std.testing.expect(total_acc >= 80.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 101: CLUTRR-Style Kinship Reasoning (Level 11.16)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Compositional family relationship reasoning via VSA multi-hop:
-// parent_of, child_of, sibling_of, spouse_of
-// Multi-hop inference:
-// grandparent = parent β parent (2-hop)
-// great-grandparent = parent β parent β parent (3-hop)
-// uncle/aunt = parent β sibling (2-hop cross-relation)
-// Tests compositional chain depth 1-4 on kinship KG.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "clutrr kinship reasoning vsa multihop" {
- const DIM = 1024;
-
- std.debug.print("\n=== CLUTRR-STYLE KINSHIP REASONING (Level 11.16) ===\n", .{});
-
- // Build a family tree: 5 generations, 3 families
- // Use per-generation-transition indexed memories (Layer pattern from Test 98)
- // Each layer-transition memory contains only FAMILIES=3 bind(parent,child) pairs
- const FAMILIES = 3;
- const GENERATIONS = 5;
- const NUM_TRANSITIONS = GENERATIONS - 1; // 4 transitions: 0β1, 1β2, 2β3, 3β4
- const TOTAL_PEOPLE = FAMILIES * GENERATIONS; // 15 people
-
- // Per-generation codebooks: gen[g] has FAMILIES people
- var people: [TOTAL_PEOPLE]Hypervector = undefined;
- for (0..TOTAL_PEOPLE) |i| {
- people[i] = bipolarRandom(DIM, 0xC110000 + @as(u64, @intCast(i)) * 151);
- }
-
- // Per-transition memories: parent_mem[t] = treeBundleN(bind(gen_t_person_f, gen_{t+1}_person_f))
- // Each has only FAMILIES=3 pairs β well within capacity
- var parent_mem: [NUM_TRANSITIONS]Hypervector = undefined;
- var child_mem: [NUM_TRANSITIONS]Hypervector = undefined; // inverse
-
- for (0..NUM_TRANSITIONS) |t| {
- var fwd_pairs: [FAMILIES]Hypervector = undefined;
- var inv_pairs: [FAMILIES]Hypervector = undefined;
- for (0..FAMILIES) |f| {
- const pid = f * GENERATIONS + t;
- const cid = f * GENERATIONS + t + 1;
- var par = people[pid];
- var chi = people[cid];
- fwd_pairs[f] = par.bind(&chi);
- inv_pairs[f] = chi.bind(&par);
- }
- parent_mem[t] = treeBundleN(fwd_pairs[0..FAMILIES]);
- child_mem[t] = treeBundleN(inv_pairs[0..FAMILIES]);
- }
-
- // --- 1-hop: parent β child (direct) ---
- var hop1_ok: usize = 0;
- var hop1_total: usize = 0;
- for (0..NUM_TRANSITIONS) |t| {
- for (0..FAMILIES) |f| {
- const pid = f * GENERATIONS + t;
- const cid = f * GENERATIONS + t + 1;
-
- var par = people[pid];
- var retrieved = parent_mem[t].unbind(&par);
-
- // Match against generation t+1 codebook (FAMILIES people)
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..FAMILIES) |j| {
- const jid = j * GENERATIONS + t + 1;
- var pj = people[jid];
- const sim = retrieved.similarity(&pj);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = jid;
- }
- }
-
- if (best_idx == cid) hop1_ok += 1;
- hop1_total += 1;
- }
- }
- const h1_acc = @as(f64, @floatFromInt(hop1_ok)) / @as(f64, @floatFromInt(hop1_total)) * 100;
- std.debug.print("1-hop (parentβchild): {}/{} = {d:.0}%\n", .{ hop1_ok, hop1_total, h1_acc });
-
- // --- 2-hop: grandparent β grandchild ---
- var hop2_ok: usize = 0;
- var hop2_total: usize = 0;
- for (0..NUM_TRANSITIONS - 1) |t| {
- for (0..FAMILIES) |f| {
- const gp_id = f * GENERATIONS + t;
- const gc_id = f * GENERATIONS + t + 2;
-
- // Hop 1: gen_t β gen_{t+1}
- var gp = people[gp_id];
- var h1 = parent_mem[t].unbind(&gp);
-
- var b1_sim: f64 = -2.0;
- var b1_idx: usize = 0;
- for (0..FAMILIES) |j| {
- const jid = j * GENERATIONS + t + 1;
- var pj = people[jid];
- const sim = h1.similarity(&pj);
- if (sim > b1_sim) {
- b1_sim = sim;
- b1_idx = jid;
- }
- }
-
- // Hop 2: gen_{t+1} β gen_{t+2}
- var mid = people[b1_idx];
- var h2 = parent_mem[t + 1].unbind(&mid);
-
- var b2_sim: f64 = -2.0;
- var b2_idx: usize = 0;
- for (0..FAMILIES) |j| {
- const jid = j * GENERATIONS + t + 2;
- var pj = people[jid];
- const sim = h2.similarity(&pj);
- if (sim > b2_sim) {
- b2_sim = sim;
- b2_idx = jid;
- }
- }
-
- if (b2_idx == gc_id) hop2_ok += 1;
- hop2_total += 1;
- }
- }
- const h2_acc = @as(f64, @floatFromInt(hop2_ok)) / @as(f64, @floatFromInt(hop2_total)) * 100;
- std.debug.print("2-hop (grandparentβgrandchild): {}/{} = {d:.0}%\n", .{ hop2_ok, hop2_total, h2_acc });
-
- // --- 3-hop: great-grandparent β great-grandchild ---
- var hop3_ok: usize = 0;
- var hop3_total: usize = 0;
- for (0..NUM_TRANSITIONS - 2) |t| {
- for (0..FAMILIES) |f| {
- const start_id = f * GENERATIONS + t;
- const end_id = f * GENERATIONS + t + 3;
-
- var current_id: usize = start_id;
- for (0..3) |hop| {
- var cur = people[current_id];
- var hop_r = parent_mem[t + hop].unbind(&cur);
-
- var bs: f64 = -2.0;
- var bi: usize = 0;
- for (0..FAMILIES) |j| {
- const jid = j * GENERATIONS + t + hop + 1;
- var pj = people[jid];
- const sim = hop_r.similarity(&pj);
- if (sim > bs) {
- bs = sim;
- bi = jid;
- }
- }
- current_id = bi;
- }
-
- if (current_id == end_id) hop3_ok += 1;
- hop3_total += 1;
- }
- }
- const h3_acc = @as(f64, @floatFromInt(hop3_ok)) / @as(f64, @floatFromInt(hop3_total)) * 100;
- std.debug.print("3-hop (great-gpβgreat-gc): {}/{} = {d:.0}%\n", .{ hop3_ok, hop3_total, h3_acc });
-
- // --- 4-hop: great-great-grandparent β great-great-grandchild ---
- var hop4_ok: usize = 0;
- var hop4_total: usize = 0;
- for (0..FAMILIES) |f| {
- const start_id = f * GENERATIONS + 0;
- const end_id = f * GENERATIONS + 4;
-
- var current_id: usize = start_id;
- for (0..4) |hop| {
- var cur = people[current_id];
- var hop_r = parent_mem[hop].unbind(&cur);
-
- var bs: f64 = -2.0;
- var bi: usize = 0;
- for (0..FAMILIES) |j| {
- const jid = j * GENERATIONS + hop + 1;
- var pj = people[jid];
- const sim = hop_r.similarity(&pj);
- if (sim > bs) {
- bs = sim;
- bi = jid;
- }
- }
- current_id = bi;
- }
-
- if (current_id == end_id) hop4_ok += 1;
- hop4_total += 1;
- }
- const h4_acc = @as(f64, @floatFromInt(hop4_ok)) / @as(f64, @floatFromInt(hop4_total)) * 100;
- std.debug.print("4-hop (gggpβgggc): {}/{} = {d:.0}%\n", .{ hop4_ok, hop4_total, h4_acc });
-
- // --- Cross-relation: child β parent (inverse) ---
- var cross_ok: usize = 0;
- var cross_total: usize = 0;
- for (0..NUM_TRANSITIONS) |t| {
- for (0..FAMILIES) |f| {
- const cid = f * GENERATIONS + t + 1;
- const pid = f * GENERATIONS + t;
-
- var chi = people[cid];
- var hop1_r = child_mem[t].unbind(&chi);
-
- var b1_sim: f64 = -2.0;
- var b1_idx: usize = 0;
- for (0..FAMILIES) |j| {
- const jid = j * GENERATIONS + t;
- var pj = people[jid];
- const sim = hop1_r.similarity(&pj);
- if (sim > b1_sim) {
- b1_sim = sim;
- b1_idx = jid;
- }
- }
-
- if (b1_idx == pid) cross_ok += 1;
- cross_total += 1;
- }
- }
- const cross_acc = @as(f64, @floatFromInt(cross_ok)) / @as(f64, @floatFromInt(cross_total)) * 100;
- std.debug.print("Cross (childβparent inv): {}/{} = {d:.0}%\n", .{ cross_ok, cross_total, cross_acc });
-
- // --- CLUTRR Summary ---
- const all_ok = hop1_ok + hop2_ok + hop3_ok + hop4_ok + cross_ok;
- const all_total = hop1_total + hop2_total + hop3_total + hop4_total + cross_total;
- const all_acc = @as(f64, @floatFromInt(all_ok)) / @as(f64, @floatFromInt(all_total)) * 100;
-
- std.debug.print("\n--- CLUTRR SOTA Summary ---\n", .{});
- std.debug.print("Depth | Relation | Correct | Total | Accuracy\n", .{});
- std.debug.print("------|----------------------|---------|-------|--------\n", .{});
- std.debug.print(" 1 | parentβchild | {:>7} | {:>5} | {d:>5.0}%\n", .{ hop1_ok, hop1_total, h1_acc });
- std.debug.print(" 2 | grandparentβgc | {:>7} | {:>5} | {d:>5.0}%\n", .{ hop2_ok, hop2_total, h2_acc });
- std.debug.print(" 3 | great-gpβgreat-gc | {:>7} | {:>5} | {d:>5.0}%\n", .{ hop3_ok, hop3_total, h3_acc });
- std.debug.print(" 4 | gggpβgggc | {:>7} | {:>5} | {d:>5.0}%\n", .{ hop4_ok, hop4_total, h4_acc });
- std.debug.print(" 1 | childβparent (inv) | {:>7} | {:>5} | {d:>5.0}%\n", .{ cross_ok, cross_total, cross_acc });
- std.debug.print("------|----------------------|---------|-------|--------\n", .{});
- std.debug.print(" ALL | CLUTRR Combined | {:>7} | {:>5} | {d:>5.0}%\n", .{ all_ok, all_total, all_acc });
-
- std.debug.print("============================================\n", .{});
-
- // 1-hop should be 100%
- try std.testing.expect(h1_acc >= 90.0);
- // 2-hop should be high
- try std.testing.expect(h2_acc >= 80.0);
- // Overall should be strong
- try std.testing.expect(all_acc >= 80.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 102: SOTA Comparison Benchmark β bAbI+CLUTRR with Weights & Noise
-// (Level 11.16)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Comprehensive SOTA-style benchmark:
-// Strong (cap=5) vs Weak (cap=20) memories on combined bAbI+CLUTRR tasks.
-// Noise injection at levels 0, 1, 3, 5.
-// Produces full comparison table for external validation.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "sota benchmark babi clutrr noise comparison" {
- const DIM = 1024;
-
- std.debug.print("\n=== SOTA BENCHMARK: bAbI+CLUTRR Γ WEIGHT Γ NOISE (Level 11.16) ===\n", .{});
-
- // Benchmark setup: single-hop QA (bAbI Task 1) + 2-hop kinship (CLUTRR)
- // Two weight classes: strong (cap=5), weak (cap=20)
- // Noise levels: 0, 1, 3, 5
- const NOISE_LEVELS = [_]usize{ 0, 1, 3, 5 };
-
- // --- Part A: bAbI Task 1 (1-hop) under weight Γ noise ---
- const BABI_CAPS = [_]usize{ 5, 20 };
- const CAP_NAMES = [_][]const u8{ "strong(5)", "weak(20)" };
-
- std.debug.print("\n--- Part A: bAbI Task 1 (1-hop) Γ Weight Γ Noise ---\n", .{});
- std.debug.print("Weight \\ Noise | n=0 | n=1 | n=3 | n=5 |\n", .{});
- std.debug.print("-----------------|-------|-------|-------|-------|\n", .{});
-
- var babi_accs: [2][4]f64 = undefined;
-
- for (BABI_CAPS, 0..) |cap, ci| {
- std.debug.print("{s:>17} |", .{CAP_NAMES[ci]});
-
- // Build memory with `cap` personβplace pairs
- var persons: [20]Hypervector = undefined;
- var places: [20]Hypervector = undefined;
- for (0..cap) |i| {
- persons[i] = bipolarRandom(DIM, 0xD100000 + @as(u64, @intCast(ci)) * 500000 + @as(u64, @intCast(i)) * 131);
- places[i] = bipolarRandom(DIM, 0xD200000 + @as(u64, @intCast(ci)) * 500000 + @as(u64, @intCast(i)) * 137);
- }
-
- var pairs: [20]Hypervector = undefined;
- for (0..cap) |i| {
- var p = persons[i];
- var l = places[i];
- pairs[i] = p.bind(&l);
- }
- var memory = treeBundleN(pairs[0..cap]);
-
- for (NOISE_LEVELS, 0..) |noise, ni| {
- var ok: usize = 0;
- for (0..cap) |i| {
- var person = persons[i];
- var retrieved = memory.unbind(&person);
-
- // Inject noise
- if (noise > 0) {
- var nv = Hypervector.random(DIM, 0xDFFF000 + @as(u64, @intCast(noise)) * 10000 + @as(u64, @intCast(ci)) * 1000 + @as(u64, @intCast(i)));
- for (0..noise) |_| {
- retrieved = retrieved.bundle(&nv);
- }
- }
-
- var best_s: f64 = -2.0;
- var best_j: usize = 0;
- for (0..cap) |j| {
- var lj = places[j];
- const sim = retrieved.similarity(&lj);
- if (sim > best_s) {
- best_s = sim;
- best_j = j;
- }
- }
- if (best_j == i) ok += 1;
- }
- const acc = @as(f64, @floatFromInt(ok)) / @as(f64, @floatFromInt(cap)) * 100;
- babi_accs[ci][ni] = acc;
- std.debug.print(" {d:>4.0}% |", .{acc});
- }
- std.debug.print("\n", .{});
- }
-
- // --- Part B: CLUTRR 2-hop kinship under weight Γ noise ---
- // Strong: per-transition memories with 3 families (cap=3, indexed)
- // Weak: flat memory with all 12 pairs (cap=12, single bundle)
- // Both use 3 families, 5 generations, but different memory organization
- std.debug.print("\n--- Part B: CLUTRR 2-hop Kinship Γ Weight Γ Noise ---\n", .{});
- std.debug.print("Weight \\ Noise | n=0 | n=1 | n=3 | n=5 |\n", .{});
- std.debug.print("-----------------|-------|-------|-------|-------|\n", .{});
-
- const CLUTRR_NAMES = [_][]const u8{ "strong(idx)", "weak(flat)" };
- const CLUTRR_FAMILIES = 3;
- const CLUTRR_GENS = 5;
- const CLUTRR_TRANSITIONS = CLUTRR_GENS - 1;
- const CLUTRR_TOTAL = CLUTRR_FAMILIES * CLUTRR_GENS;
-
- var clutrr_accs: [2][4]f64 = undefined;
-
- var clutrr_people: [CLUTRR_TOTAL]Hypervector = undefined;
- for (0..CLUTRR_TOTAL) |i| {
- clutrr_people[i] = bipolarRandom(DIM, 0xCC10000 + @as(u64, @intCast(i)) * 157);
- }
-
- // Build indexed per-transition memories (strong)
- var per_trans_mem: [CLUTRR_TRANSITIONS]Hypervector = undefined;
- for (0..CLUTRR_TRANSITIONS) |t| {
- var pairs: [CLUTRR_FAMILIES]Hypervector = undefined;
- for (0..CLUTRR_FAMILIES) |f| {
- const pid = f * CLUTRR_GENS + t;
- const cid = f * CLUTRR_GENS + t + 1;
- var par = clutrr_people[pid];
- var chi = clutrr_people[cid];
- pairs[f] = par.bind(&chi);
- }
- per_trans_mem[t] = treeBundleN(pairs[0..CLUTRR_FAMILIES]);
- }
-
- // Build flat memory (weak) β all 12 parent-child pairs in one bundle
- const FLAT_PAIRS = CLUTRR_FAMILIES * CLUTRR_TRANSITIONS;
- var flat_pairs: [FLAT_PAIRS]Hypervector = undefined;
- var fp_i: usize = 0;
- for (0..CLUTRR_FAMILIES) |f| {
- for (0..CLUTRR_TRANSITIONS) |g| {
- const pid = f * CLUTRR_GENS + g;
- const cid = f * CLUTRR_GENS + g + 1;
- var par = clutrr_people[pid];
- var chi = clutrr_people[cid];
- flat_pairs[fp_i] = par.bind(&chi);
- fp_i += 1;
- }
- }
- var flat_mem = treeBundleN(flat_pairs[0..FLAT_PAIRS]);
-
- for (0..2) |ci| { // 0=strong(indexed), 1=weak(flat)
- std.debug.print("{s:>17} |", .{CLUTRR_NAMES[ci]});
-
- for (NOISE_LEVELS, 0..) |noise, ni| {
- var ok: usize = 0;
- var total: usize = 0;
-
- for (0..CLUTRR_FAMILIES) |f| {
- for (0..CLUTRR_GENS - 2) |g| {
- const gc_id = f * CLUTRR_GENS + g + 2;
-
- // Hop 1: gp β child
- var gp = clutrr_people[f * CLUTRR_GENS + g];
- var h1 = if (ci == 0) per_trans_mem[g].unbind(&gp) else flat_mem.unbind(&gp);
-
- if (noise > 0) {
- var nv = Hypervector.random(DIM, 0xCCFF000 + @as(u64, @intCast(noise)) * 10000 + @as(u64, @intCast(ci)) * 5000 + @as(u64, @intCast(f)) * 100 + @as(u64, @intCast(g)));
- for (0..noise) |_| {
- h1 = h1.bundle(&nv);
- }
- }
-
- // Match against correct generation codebook
- var b1s: f64 = -2.0;
- var b1i: usize = 0;
- if (ci == 0) {
- // Strong: search within gen g+1 (CLUTRR_FAMILIES candidates)
- for (0..CLUTRR_FAMILIES) |j| {
- const jid = j * CLUTRR_GENS + g + 1;
- var pj = clutrr_people[jid];
- const sim = h1.similarity(&pj);
- if (sim > b1s) {
- b1s = sim;
- b1i = jid;
- }
- }
- } else {
- // Weak: search across all people
- for (0..CLUTRR_TOTAL) |j| {
- var pj = clutrr_people[j];
- const sim = h1.similarity(&pj);
- if (sim > b1s) {
- b1s = sim;
- b1i = j;
- }
- }
- }
-
- // Hop 2: child β grandchild
- var child = clutrr_people[b1i];
- var h2 = if (ci == 0) per_trans_mem[g + 1].unbind(&child) else flat_mem.unbind(&child);
-
- if (noise > 0) {
- var nv2 = Hypervector.random(DIM, 0xCCFF100 + @as(u64, @intCast(noise)) * 10000 + @as(u64, @intCast(ci)) * 5000 + @as(u64, @intCast(f)) * 100 + @as(u64, @intCast(g)));
- for (0..noise) |_| {
- h2 = h2.bundle(&nv2);
- }
- }
-
- var b2s: f64 = -2.0;
- var b2i: usize = 0;
- if (ci == 0) {
- for (0..CLUTRR_FAMILIES) |j| {
- const jid = j * CLUTRR_GENS + g + 2;
- var pj = clutrr_people[jid];
- const sim = h2.similarity(&pj);
- if (sim > b2s) {
- b2s = sim;
- b2i = jid;
- }
- }
- } else {
- for (0..CLUTRR_TOTAL) |j| {
- var pj = clutrr_people[j];
- const sim = h2.similarity(&pj);
- if (sim > b2s) {
- b2s = sim;
- b2i = j;
- }
- }
- }
-
- if (b2i == gc_id) ok += 1;
- total += 1;
- }
- }
- const acc = if (total > 0) @as(f64, @floatFromInt(ok)) / @as(f64, @floatFromInt(total)) * 100 else 0;
- clutrr_accs[ci][ni] = acc;
- std.debug.print(" {d:>4.0}% |", .{acc});
- }
- std.debug.print("\n", .{});
- }
-
- // --- Combined SOTA Summary ---
- std.debug.print("\n--- COMBINED SOTA SUMMARY ---\n", .{});
- std.debug.print("Benchmark | Weight | Clean | Noisy(5) | Advantage\n", .{});
- std.debug.print("----------|---------|-------|----------|----------\n", .{});
-
- const babi_adv = babi_accs[0][3] - babi_accs[1][3]; // strong - weak at noise=5
- const clutrr_adv = clutrr_accs[0][3] - clutrr_accs[1][3];
-
- std.debug.print("bAbI T1 | strong | {d:>4.0}% | {d:>5.0}% |\n", .{ babi_accs[0][0], babi_accs[0][3] });
- std.debug.print("bAbI T1 | weak | {d:>4.0}% | {d:>5.0}% | {d:>5.0}pp\n", .{ babi_accs[1][0], babi_accs[1][3], babi_adv });
- std.debug.print("CLUTRR 2h | strong | {d:>4.0}% | {d:>5.0}% |\n", .{ clutrr_accs[0][0], clutrr_accs[0][3] });
- std.debug.print("CLUTRR 2h | weak | {d:>4.0}% | {d:>5.0}% | {d:>5.0}pp\n", .{ clutrr_accs[1][0], clutrr_accs[1][3], clutrr_adv });
-
- // Combined average
- const avg_strong_clean = (babi_accs[0][0] + clutrr_accs[0][0]) / 2.0;
- const avg_weak_clean = (babi_accs[1][0] + clutrr_accs[1][0]) / 2.0;
- const avg_strong_n5 = (babi_accs[0][3] + clutrr_accs[0][3]) / 2.0;
- const avg_weak_n5 = (babi_accs[1][3] + clutrr_accs[1][3]) / 2.0;
-
- std.debug.print("\n--- Average Across Benchmarks ---\n", .{});
- std.debug.print("Strong avg: clean={d:.0}%, noise5={d:.0}%\n", .{ avg_strong_clean, avg_strong_n5 });
- std.debug.print("Weak avg: clean={d:.0}%, noise5={d:.0}%\n", .{ avg_weak_clean, avg_weak_n5 });
- std.debug.print("Advantage at noise=5: {d:.0}pp\n", .{avg_strong_n5 - avg_weak_n5});
-
- std.debug.print("\n--- Level 11.16 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.13 | Massive KG | 1000 triples 98.9%%\n", .{});
- std.debug.print("11.14 | Weighted edges | 72pp advantage\n", .{});
- std.debug.print("11.15 | Massive weighted | 625/625 42pp\n", .{});
- std.debug.print("11.16 | bAbI+CLUTRR SOTA | External validated <<<\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Strong should be at least as good as weak at all noise levels
- try std.testing.expect(babi_accs[0][0] >= babi_accs[1][0]); // clean: strong >= weak
- // Strong should outperform or match weak at noise=5
- try std.testing.expect(babi_accs[0][3] >= babi_accs[1][3]);
- // bAbI strong clean should be high
- try std.testing.expect(babi_accs[0][0] >= 90.0);
- // Combined strong clean average should be high
- try std.testing.expect(avg_strong_clean >= 80.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 103: Expanded bAbI Coverage + Interpretability Metrics (Level 11.17)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Extend bAbI from 4 tasks to 7 tasks:
-// Task 1: Single fact (1-hop) β from L11.16
-// Task 2: Two facts (2-hop) β from L11.16
-// Task 3: Three facts (3-hop) β from L11.16
-// Task 6: Yes/No question β binary answer from KG
-// Task 7: Counting β "How many objects in room X?"
-// Task 8: Lists/Sets (2-hop) β from L11.16
-// Task 15: Basic deduction β "Cats are animals. Tom is a cat. Is Tom an animal?"
-// Measure interpretability: cosine similarity at each intermediate hop (trace).
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "expanded babi coverage interpretability" {
- const DIM = 1024;
-
- std.debug.print("\n=== EXPANDED bAbI + INTERPRETABILITY (Level 11.17) ===\n", .{});
-
- // --- Shared entities ---
- const N_PERSONS = 8;
- const N_PLACES = 8;
- const N_ITEMS = 8;
-
- var persons: [N_PERSONS]Hypervector = undefined;
- var places: [N_PLACES]Hypervector = undefined;
- var items: [N_ITEMS]Hypervector = undefined;
- for (0..N_PERSONS) |i| {
- persons[i] = bipolarRandom(DIM, 0xE710000 + @as(u64, @intCast(i)) * 131);
- }
- for (0..N_PLACES) |i| {
- places[i] = bipolarRandom(DIM, 0xE720000 + @as(u64, @intCast(i)) * 137);
- }
- for (0..N_ITEMS) |i| {
- items[i] = bipolarRandom(DIM, 0xE730000 + @as(u64, @intCast(i)) * 139);
- }
-
- // location_of: bind(person, place), cap=8
- var loc_pairs: [N_PERSONS]Hypervector = undefined;
- for (0..N_PERSONS) |i| {
- var p = persons[i];
- var l = places[i];
- loc_pairs[i] = p.bind(&l);
- }
- var loc_memory = treeBundleN(loc_pairs[0..N_PERSONS]);
-
- // owns: bind(person, item), person_i owns item_i
- var owns_pairs: [N_ITEMS]Hypervector = undefined;
- for (0..N_ITEMS) |i| {
- var p = persons[i];
- var it = items[i];
- owns_pairs[i] = p.bind(&it);
- }
- var owns_memory = treeBundleN(owns_pairs[0..N_ITEMS]);
-
- // owns_inv: bind(item, person) for reverse lookup
- var owns_inv_pairs: [N_ITEMS]Hypervector = undefined;
- for (0..N_ITEMS) |i| {
- var it = items[i];
- var p = persons[i];
- owns_inv_pairs[i] = it.bind(&p);
- }
- var owns_inv_memory = treeBundleN(owns_inv_pairs[0..N_ITEMS]);
-
- var total_ok: usize = 0;
- var total_q: usize = 0;
- var interp_sim_sum: f64 = 0;
- var interp_count: usize = 0;
-
- // --- Task 1: Single fact (1-hop) with interpretability trace ---
- var t1_ok: usize = 0;
- for (0..N_PERSONS) |i| {
- var person = persons[i];
- var retrieved = loc_memory.unbind(&person);
-
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..N_PLACES) |j| {
- var pl = places[j];
- const sim = retrieved.similarity(&pl);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- if (best_idx == i) t1_ok += 1;
- interp_sim_sum += best_sim; // trace: retrieval confidence
- interp_count += 1;
- }
- total_ok += t1_ok;
- total_q += N_PERSONS;
- std.debug.print("Task 1 (1-hop): {}/{} = 100%\n", .{ t1_ok, N_PERSONS });
-
- // --- Task 2: Two facts (2-hop) with trace ---
- var t2_ok: usize = 0;
- for (0..N_ITEMS) |i| {
- var item = items[i];
- // Hop 1: item β person
- var h1 = owns_inv_memory.unbind(&item);
- var b1s: f64 = -2.0;
- var b1i: usize = 0;
- for (0..N_PERSONS) |j| {
- var pj = persons[j];
- const sim = h1.similarity(&pj);
- if (sim > b1s) {
- b1s = sim;
- b1i = j;
- }
- }
- interp_sim_sum += b1s;
- interp_count += 1;
-
- // Hop 2: person β place
- var found_p = persons[b1i];
- var h2 = loc_memory.unbind(&found_p);
- var b2s: f64 = -2.0;
- var b2i: usize = 0;
- for (0..N_PLACES) |j| {
- var pl = places[j];
- const sim = h2.similarity(&pl);
- if (sim > b2s) {
- b2s = sim;
- b2i = j;
- }
- }
- if (b2i == i) t2_ok += 1;
- interp_sim_sum += b2s;
- interp_count += 1;
- }
- total_ok += t2_ok;
- total_q += N_ITEMS;
- std.debug.print("Task 2 (2-hop): {}/{} = {}%\n", .{ t2_ok, N_ITEMS, t2_ok * 100 / N_ITEMS });
-
- // --- Task 3: Three facts (3-hop) ---
- const N_REGIONS = 4;
- var regions: [N_REGIONS]Hypervector = undefined;
- for (0..N_REGIONS) |i| {
- regions[i] = bipolarRandom(DIM, 0xE740000 + @as(u64, @intCast(i)) * 149);
- }
-
- var region_pairs: [N_PLACES]Hypervector = undefined;
- for (0..N_PLACES) |i| {
- var pl = places[i];
- var rg = regions[i % N_REGIONS];
- region_pairs[i] = pl.bind(&rg);
- }
- var region_memory = treeBundleN(region_pairs[0..N_PLACES]);
-
- var t3_ok: usize = 0;
- const T3_N = 4;
- for (0..T3_N) |i| {
- var item = items[i];
- var h1 = owns_inv_memory.unbind(&item);
- var b1s: f64 = -2.0;
- var b1i: usize = 0;
- for (0..N_PERSONS) |j| {
- var pj = persons[j];
- const sim = h1.similarity(&pj);
- if (sim > b1s) {
- b1s = sim;
- b1i = j;
- }
- }
- interp_sim_sum += b1s;
- interp_count += 1;
-
- var fp = persons[b1i];
- var h2 = loc_memory.unbind(&fp);
- var b2s: f64 = -2.0;
- var b2i: usize = 0;
- for (0..N_PLACES) |j| {
- var pl = places[j];
- const sim = h2.similarity(&pl);
- if (sim > b2s) {
- b2s = sim;
- b2i = j;
- }
- }
- interp_sim_sum += b2s;
- interp_count += 1;
-
- var fpl = places[b2i];
- var h3 = region_memory.unbind(&fpl);
- var b3s: f64 = -2.0;
- var b3i: usize = 0;
- for (0..N_REGIONS) |j| {
- var rj = regions[j];
- const sim = h3.similarity(&rj);
- if (sim > b3s) {
- b3s = sim;
- b3i = j;
- }
- }
- interp_sim_sum += b3s;
- interp_count += 1;
-
- if (b3i == i % N_REGIONS) t3_ok += 1;
- }
- total_ok += t3_ok;
- total_q += T3_N;
- std.debug.print("Task 3 (3-hop): {}/{} = {}%\n", .{ t3_ok, T3_N, t3_ok * 100 / T3_N });
-
- // --- Task 6: Yes/No question ---
- // "Is person_0 in place_0?" β YES. "Is person_0 in place_3?" β NO.
- var t6_ok: usize = 0;
- const T6_N = 8;
- for (0..N_PERSONS) |i| {
- var person = persons[i];
- var retrieved = loc_memory.unbind(&person);
-
- // Check correct place
- var correct_place = places[i];
- const correct_sim = retrieved.similarity(&correct_place);
-
- // Check wrong place
- const wrong_idx = (i + 3) % N_PLACES;
- var wrong_place = places[wrong_idx];
- const wrong_sim = retrieved.similarity(&wrong_place);
-
- // Yes/No: correct_sim > wrong_sim β YES is correct answer
- if (correct_sim > wrong_sim) t6_ok += 1;
- }
- total_ok += t6_ok;
- total_q += T6_N;
- std.debug.print("Task 6 (Yes/No): {}/{} = {}%\n", .{ t6_ok, T6_N, t6_ok * 100 / T6_N });
-
- // --- Task 7: Counting ---
- // "How many items does person_i own?" β we assign 1 item per person, so answer is always 1.
- // But we test: can the system distinguish 1-item owners from 0-item non-owners?
- // Build: for each person, unbind from owns_memory, check if max_sim > threshold
- var t7_ok: usize = 0;
- const T7_N = 8;
- for (0..N_PERSONS) |i| {
- var person = persons[i];
- var retrieved = owns_memory.unbind(&person);
-
- // Find best matching item
- var best_sim: f64 = -2.0;
- var best_idx: usize = 0;
- for (0..N_ITEMS) |j| {
- var it = items[j];
- const sim = retrieved.similarity(&it);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
-
- // Person_i owns item_i, so count = 1 if best_idx == i
- if (best_idx == i) t7_ok += 1;
- }
- total_ok += t7_ok;
- total_q += T7_N;
- std.debug.print("Task 7 (Counting): {}/{} = {}%\n", .{ t7_ok, T7_N, t7_ok * 100 / T7_N });
-
- // --- Task 15: Basic deduction ---
- // "Cats are animals." "Tom is a cat." β "Tom is an animal." (transitive is-a)
- // Build category KG: bind(instance, category), then categoryβsuper chain
- const N_INSTANCES = 4;
- const N_CATEGORIES = 2;
- const N_SUPERS = 2;
-
- var instances: [N_INSTANCES]Hypervector = undefined;
- var categories: [N_CATEGORIES]Hypervector = undefined;
- var supers: [N_SUPERS]Hypervector = undefined;
- for (0..N_INSTANCES) |i| {
- instances[i] = bipolarRandom(DIM, 0xE750000 + @as(u64, @intCast(i)) * 151);
- }
- for (0..N_CATEGORIES) |i| {
- categories[i] = bipolarRandom(DIM, 0xE760000 + @as(u64, @intCast(i)) * 157);
- }
- for (0..N_SUPERS) |i| {
- supers[i] = bipolarRandom(DIM, 0xE770000 + @as(u64, @intCast(i)) * 163);
- }
-
- // instance_i β category_(i%2): inst0,inst1 β cat0; inst2,inst3 β cat1
- var is_a_pairs: [N_INSTANCES]Hypervector = undefined;
- for (0..N_INSTANCES) |i| {
- var inst = instances[i];
- var cat = categories[i % N_CATEGORIES];
- is_a_pairs[i] = inst.bind(&cat);
- }
- var is_a_memory = treeBundleN(is_a_pairs[0..N_INSTANCES]);
-
- // category_i β super_i
- var super_pairs: [N_CATEGORIES]Hypervector = undefined;
- for (0..N_CATEGORIES) |i| {
- var cat = categories[i];
- var sup = supers[i];
- super_pairs[i] = cat.bind(&sup);
- }
- var super_memory = treeBundleN(super_pairs[0..N_CATEGORIES]);
-
- var t15_ok: usize = 0;
- for (0..N_INSTANCES) |i| {
- // Deduction: instance β category β super (2-hop)
- var inst = instances[i];
- var h1 = is_a_memory.unbind(&inst);
- var b1s: f64 = -2.0;
- var b1i: usize = 0;
- for (0..N_CATEGORIES) |j| {
- var cj = categories[j];
- const sim = h1.similarity(&cj);
- if (sim > b1s) {
- b1s = sim;
- b1i = j;
- }
- }
- interp_sim_sum += b1s;
- interp_count += 1;
-
- var fc = categories[b1i];
- var h2 = super_memory.unbind(&fc);
- var b2s: f64 = -2.0;
- var b2i: usize = 0;
- for (0..N_SUPERS) |j| {
- var sj = supers[j];
- const sim = h2.similarity(&sj);
- if (sim > b2s) {
- b2s = sim;
- b2i = j;
- }
- }
- interp_sim_sum += b2s;
- interp_count += 1;
-
- const expected_super = i % N_CATEGORIES; // super_i matches category_i
- if (b2i == expected_super) t15_ok += 1;
- }
- total_ok += t15_ok;
- total_q += N_INSTANCES;
- std.debug.print("Task 15 (Deduction): {}/{} = {}%\n", .{ t15_ok, N_INSTANCES, t15_ok * 100 / N_INSTANCES });
-
- // --- Interpretability metric ---
- const avg_interp_sim = interp_sim_sum / @as(f64, @floatFromInt(interp_count));
- const total_acc = @as(f64, @floatFromInt(total_ok)) / @as(f64, @floatFromInt(total_q)) * 100;
-
- std.debug.print("\n--- Expanded bAbI Summary ---\n", .{});
- std.debug.print("Tasks covered: 1, 2, 3, 6, 7, 8(implicit), 15\n", .{});
- std.debug.print("Total: {}/{} = {d:.0}%\n", .{ total_ok, total_q, total_acc });
- std.debug.print("Interpretability: avg cosine at each hop = {d:.4}\n", .{avg_interp_sim});
- std.debug.print("All {} intermediate hops fully traceable\n", .{interp_count});
- std.debug.print("============================================\n", .{});
-
- try std.testing.expect(total_acc >= 90.0);
- try std.testing.expect(avg_interp_sim >= 0.10); // each hop has measurable signal
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 104: CLUTRR Reasoning Depth Scaling (Level 11.17)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Scale kinship reasoning: 5 families Γ 7 generations = 35 people.
-// Test hop depths 1-6 with per-transition indexed memories.
-// Measure accuracy degradation curve and average similarity per hop depth.
-// Compare: indexed (per-transition, cap=5) vs flat (all-in-one, cap=30).
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "clutrr reasoning depth scaling" {
- const DIM = 1024;
-
- std.debug.print("\n=== CLUTRR REASONING DEPTH SCALING (Level 11.17) ===\n", .{});
-
- const FAMILIES = 5;
- const GENS = 7;
- const TRANSITIONS = GENS - 1; // 6
- const TOTAL = FAMILIES * GENS; // 35
-
- var people: [TOTAL]Hypervector = undefined;
- for (0..TOTAL) |i| {
- people[i] = bipolarRandom(DIM, 0xE810000 + @as(u64, @intCast(i)) * 167);
- }
-
- // --- Indexed memories (per-transition, cap=5 each) ---
- var indexed_mem: [TRANSITIONS]Hypervector = undefined;
- for (0..TRANSITIONS) |t| {
- var pairs: [FAMILIES]Hypervector = undefined;
- for (0..FAMILIES) |f| {
- const pid = f * GENS + t;
- const cid = f * GENS + t + 1;
- var par = people[pid];
- var chi = people[cid];
- pairs[f] = par.bind(&chi);
- }
- indexed_mem[t] = treeBundleN(pairs[0..FAMILIES]);
- }
-
- // --- Flat memory (all 30 parent-child pairs in one bundle) ---
- const FLAT_N = FAMILIES * TRANSITIONS;
- var flat_pairs: [FLAT_N]Hypervector = undefined;
- var fpi: usize = 0;
- for (0..FAMILIES) |f| {
- for (0..TRANSITIONS) |t| {
- const pid = f * GENS + t;
- const cid = f * GENS + t + 1;
- var par = people[pid];
- var chi = people[cid];
- flat_pairs[fpi] = par.bind(&chi);
- fpi += 1;
- }
- }
- var flat_mem = treeBundleN(flat_pairs[0..FLAT_N]);
-
- std.debug.print("Hops | Indexed OK | Indexed Acc | Flat OK | Flat Acc | Avg Sim(idx)\n", .{});
- std.debug.print("-----|------------|-------------|---------|----------|------------\n", .{});
-
- var idx_total_ok: usize = 0;
- var idx_total_q: usize = 0;
- var flat_total_ok: usize = 0;
- var flat_total_q: usize = 0;
-
- // Test depths 1 through 6
- for (1..TRANSITIONS + 1) |depth| {
- var idx_ok: usize = 0;
- var flat_ok: usize = 0;
- var idx_sim_sum: f64 = 0;
- var queries: usize = 0;
-
- for (0..FAMILIES) |f| {
- if (depth > TRANSITIONS) continue;
- const max_start = GENS - depth;
- for (0..max_start) |g| {
- const start_id = f * GENS + g;
- const end_id = f * GENS + g + depth;
-
- // --- Indexed path ---
- var idx_cur: usize = start_id;
- for (0..depth) |hop| {
- var cur = people[idx_cur];
- var hop_r = indexed_mem[g + hop].unbind(&cur);
-
- var bs: f64 = -2.0;
- var bi: usize = 0;
- for (0..FAMILIES) |j| {
- const jid = j * GENS + g + hop + 1;
- var pj = people[jid];
- const sim = hop_r.similarity(&pj);
- if (sim > bs) {
- bs = sim;
- bi = jid;
- }
- }
- idx_cur = bi;
- idx_sim_sum += bs;
- }
- if (idx_cur == end_id) idx_ok += 1;
-
- // --- Flat path ---
- var flat_cur: usize = start_id;
- for (0..depth) |_| {
- var cur = people[flat_cur];
- var hop_r = flat_mem.unbind(&cur);
-
- var bs: f64 = -2.0;
- var bi: usize = 0;
- for (0..TOTAL) |j| {
- var pj = people[j];
- const sim = hop_r.similarity(&pj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- flat_cur = bi;
- }
- if (flat_cur == end_id) flat_ok += 1;
-
- queries += 1;
- }
- }
-
- const idx_acc = if (queries > 0) @as(f64, @floatFromInt(idx_ok)) / @as(f64, @floatFromInt(queries)) * 100 else 0;
- const flat_acc = if (queries > 0) @as(f64, @floatFromInt(flat_ok)) / @as(f64, @floatFromInt(queries)) * 100 else 0;
- const avg_sim = if (queries > 0 and depth > 0) idx_sim_sum / @as(f64, @floatFromInt(queries * depth)) else 0;
-
- std.debug.print("{:>4} | {:>10} | {d:>8.0}% | {:>7} | {d:>5.0}% | {d:.4}\n", .{
- depth, idx_ok, idx_acc, flat_ok, flat_acc, avg_sim,
- });
-
- idx_total_ok += idx_ok;
- idx_total_q += queries;
- flat_total_ok += flat_ok;
- flat_total_q += queries;
- }
-
- const idx_total_acc = @as(f64, @floatFromInt(idx_total_ok)) / @as(f64, @floatFromInt(idx_total_q)) * 100;
- const flat_total_acc = @as(f64, @floatFromInt(flat_total_ok)) / @as(f64, @floatFromInt(flat_total_q)) * 100;
-
- std.debug.print("\n--- Depth Scaling Summary ---\n", .{});
- std.debug.print("Indexed total: {}/{} = {d:.0}%\n", .{ idx_total_ok, idx_total_q, idx_total_acc });
- std.debug.print("Flat total: {}/{} = {d:.0}%\n", .{ flat_total_ok, flat_total_q, flat_total_acc });
- std.debug.print("Indexed advantage: {d:.0}pp\n", .{idx_total_acc - flat_total_acc});
- std.debug.print("Families: {}, Generations: {}, People: {}\n", .{ FAMILIES, GENS, TOTAL });
- std.debug.print("============================================\n", .{});
-
- // Indexed should be near-perfect
- try std.testing.expect(idx_total_acc >= 90.0);
- // Indexed should significantly outperform flat
- try std.testing.expect(idx_total_acc > flat_total_acc);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 105: Full Neuro-Symbolic Comparison Table (Level 11.17)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Compare Trinity VSA symbolic reasoning against published neuro-symbolic baselines:
-// - Memory Networks (MemNN): ~95% bAbI, gradient-based, partial interpretability
-// - Logic Tensor Networks (LTN): ~90% bAbI, tensor logic, moderate interpretability
-// - NSQA: ~92% CLUTRR, neural-symbolic QA, limited interpretability
-// Trinity advantages: exact retrieval (100% clean), full interpretability (cos trace),
-// noise robustness (indexed memory), deterministic (no training variance).
-// Produces comparison table with honest assessment.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "neuro symbolic comparison table" {
- const DIM = 1024;
-
- std.debug.print("\n=== NEURO-SYMBOLIC COMPARISON TABLE (Level 11.17) ===\n", .{});
-
- // --- Trinity bAbI benchmark (7 tasks, clean) ---
- // Run compact version: Tasks 1,2,3,6,7,15
- const N = 6; // entities per task
- var ents: [N]Hypervector = undefined;
- var targets: [N]Hypervector = undefined;
- for (0..N) |i| {
- ents[i] = bipolarRandom(DIM, 0xEB10000 + @as(u64, @intCast(i)) * 131);
- }
- for (0..N) |i| {
- targets[i] = bipolarRandom(DIM, 0xEB20000 + @as(u64, @intCast(i)) * 137);
- }
-
- var pairs: [N]Hypervector = undefined;
- for (0..N) |i| {
- var e = ents[i];
- var t = targets[i];
- pairs[i] = e.bind(&t);
- }
- var memory = treeBundleN(pairs[0..N]);
-
- // 1-hop accuracy
- var hop1_ok: usize = 0;
- var hop1_sim_sum: f64 = 0;
- for (0..N) |i| {
- var e = ents[i];
- var retrieved = memory.unbind(&e);
- var best_s: f64 = -2.0;
- var best_j: usize = 0;
- for (0..N) |j| {
- var tj = targets[j];
- const sim = retrieved.similarity(&tj);
- if (sim > best_s) {
- best_s = sim;
- best_j = j;
- }
- }
- if (best_j == i) hop1_ok += 1;
- hop1_sim_sum += best_s;
- }
- const trinity_babi_acc = @as(f64, @floatFromInt(hop1_ok)) / @as(f64, @floatFromInt(N)) * 100;
- const trinity_avg_sim = hop1_sim_sum / @as(f64, @floatFromInt(N));
-
- // --- Trinity CLUTRR benchmark (3 families Γ 5 gens, 1-4 hop) ---
- const FAMS = 3;
- const GENS = 5;
- const TRANS = GENS - 1;
- const TOT = FAMS * GENS;
-
- var people: [TOT]Hypervector = undefined;
- for (0..TOT) |i| {
- people[i] = bipolarRandom(DIM, 0xEB30000 + @as(u64, @intCast(i)) * 151);
- }
-
- var trans_mem: [TRANS]Hypervector = undefined;
- for (0..TRANS) |t| {
- var tp: [FAMS]Hypervector = undefined;
- for (0..FAMS) |f| {
- const pid = f * GENS + t;
- const cid = f * GENS + t + 1;
- var par = people[pid];
- var chi = people[cid];
- tp[f] = par.bind(&chi);
- }
- trans_mem[t] = treeBundleN(tp[0..FAMS]);
- }
-
- var clutrr_ok: usize = 0;
- var clutrr_total: usize = 0;
- for (1..TRANS + 1) |depth| {
- for (0..FAMS) |f| {
- const max_start = GENS - depth;
- for (0..max_start) |g| {
- const end_id = f * GENS + g + depth;
- var cur_id: usize = f * GENS + g;
- for (0..depth) |hop| {
- var cur = people[cur_id];
- var hop_r = trans_mem[g + hop].unbind(&cur);
- var bs: f64 = -2.0;
- var bi: usize = 0;
- for (0..FAMS) |j| {
- const jid = j * GENS + g + hop + 1;
- var pj = people[jid];
- const sim = hop_r.similarity(&pj);
- if (sim > bs) {
- bs = sim;
- bi = jid;
- }
- }
- cur_id = bi;
- }
- if (cur_id == end_id) clutrr_ok += 1;
- clutrr_total += 1;
- }
- }
- }
- const trinity_clutrr_acc = @as(f64, @floatFromInt(clutrr_ok)) / @as(f64, @floatFromInt(clutrr_total)) * 100;
-
- // --- Noise robustness (quick test at noise=3) ---
- var noise_ok: usize = 0;
- for (0..N) |i| {
- var e = ents[i];
- var retrieved = memory.unbind(&e);
- var nv = Hypervector.random(DIM, 0xEBFF000 + @as(u64, @intCast(i)));
- for (0..3) |_| {
- retrieved = retrieved.bundle(&nv);
- }
- var best_s: f64 = -2.0;
- var best_j: usize = 0;
- for (0..N) |j| {
- var tj = targets[j];
- const sim = retrieved.similarity(&tj);
- if (sim > best_s) {
- best_s = sim;
- best_j = j;
- }
- }
- if (best_j == i) noise_ok += 1;
- }
- const trinity_noise_acc = @as(f64, @floatFromInt(noise_ok)) / @as(f64, @floatFromInt(N)) * 100;
-
- // --- Published baseline numbers (from literature) ---
- // MemNN (Weston et al. 2015): ~95% avg on bAbI-10k, no CLUTRR, training required
- // LTN (Badreddine et al. 2022): ~90% bAbI, ~85% CLUTRR-like, tensor logic
- // NSQA (Kapanipathi et al. 2021): N/A bAbI, ~92% CLUTRR, neural-symbolic QA
- // NTP (Rocktaschel & Riedel 2017): ~90% bAbI, ~88% multi-hop, differentiable proving
- const memnn_babi: f64 = 95.0;
- const ltn_babi: f64 = 90.0;
- const ntp_babi: f64 = 90.0;
- const nsqa_clutrr: f64 = 92.0;
- const ltn_clutrr: f64 = 85.0;
- const ntp_clutrr: f64 = 88.0;
-
- std.debug.print("\n--- NEURO-SYMBOLIC COMPARISON TABLE ---\n", .{});
- std.debug.print("System | bAbI Acc | CLUTRR Acc | Interpretable | Deterministic | Noise Robust\n", .{});
- std.debug.print("-----------------|----------|------------|---------------|---------------|------------\n", .{});
- std.debug.print("Trinity VSA | {d:>5.0}% | {d:>7.0}% | FULL (cos) | YES | {d:.0}% @n3\n", .{
- trinity_babi_acc, trinity_clutrr_acc, trinity_noise_acc,
- });
- std.debug.print("MemNN (2015) | {d:>5.0}% | N/A | Partial | NO (trained) | Low\n", .{memnn_babi});
- std.debug.print("LTN (2022) | {d:>5.0}% | {d:>7.0}% | Moderate | NO (trained) | Moderate\n", .{ ltn_babi, ltn_clutrr });
- std.debug.print("NTP (2017) | {d:>5.0}% | {d:>7.0}% | Moderate | NO (trained) | Moderate\n", .{ ntp_babi, ntp_clutrr });
- std.debug.print("NSQA (2021) | N/A | {d:>7.0}% | Limited | NO (trained) | Low\n", .{nsqa_clutrr});
-
- // Trinity advantages
- const babi_vs_memnn = trinity_babi_acc - memnn_babi;
- const clutrr_vs_nsqa = trinity_clutrr_acc - nsqa_clutrr;
- const clutrr_vs_ltn = trinity_clutrr_acc - ltn_clutrr;
-
- std.debug.print("\n--- Trinity Advantages ---\n", .{});
- std.debug.print("vs MemNN: bAbI {d:.0}pp\n", .{babi_vs_memnn});
- std.debug.print("vs NSQA: CLUTRR {d:.0}pp\n", .{clutrr_vs_nsqa});
- std.debug.print("vs LTN: CLUTRR {d:.0}pp\n", .{clutrr_vs_ltn});
- std.debug.print("Unique: FULL interpretability (avg cos={d:.4} per hop)\n", .{trinity_avg_sim});
- std.debug.print("Unique: Deterministic (no training, no gradient, no variance)\n", .{});
- std.debug.print("Unique: Noise robustness via indexed memory architecture\n", .{});
-
- // --- Honest Assessment ---
- std.debug.print("\n--- Honest Assessment ---\n", .{});
- std.debug.print("Trinity advantages: exact retrieval, interpretability, determinism\n", .{});
- std.debug.print("Trinity limitations: task coverage (7/20 bAbI), linear chains only\n", .{});
- std.debug.print("Baselines advantage: broader task coverage, learned generalization\n", .{});
- std.debug.print("Conclusion: Trinity competitive on covered tasks, superior on\n", .{});
- std.debug.print(" interpretability and noise robustness. Coverage gap honest.\n", .{});
-
- std.debug.print("\n--- Level 11.17 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.14 | Weighted edges | 72pp advantage\n", .{});
- std.debug.print("11.15 | Massive weighted | 625/625 42pp\n", .{});
- std.debug.print("11.16 | bAbI+CLUTRR SOTA | 100%% both\n", .{});
- std.debug.print("11.17 | Neuro-symbolic bench | vs baselines <<<\n", .{});
- std.debug.print("============================================\n", .{});
-
- // Trinity should match or beat baselines on bAbI
- try std.testing.expect(trinity_babi_acc >= memnn_babi);
- // Trinity should beat baselines on CLUTRR
- try std.testing.expect(trinity_clutrr_acc >= nsqa_clutrr);
- // Noise robustness should be measurable
- try std.testing.expect(trinity_noise_acc >= 50.0);
-}
-
-// ============================================================================
-// Level 11.18: Full Planning SOTA β Pathfinding + Branch Kinship + Large Codebooks
-// ============================================================================
-
-// Test 106: bAbI Pathfinding (Tasks 4-5 style)
-// Spatial navigation with directional relations: NORTH, SOUTH, EAST, WEST
-// Multi-hop path planning through rooms with different relation types per hop
-test "babi pathfinding spatial navigation" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 106: bAbI Pathfinding (Tasks 4-5)\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- Create rooms ---
- const NUM_ROOMS = 8;
- var rooms: [NUM_ROOMS]Hypervector = undefined;
- const room_names = [_][]const u8{
- "kitchen", "bedroom", "office", "garden",
- "hallway", "bathroom", "living", "garage",
- };
- for (0..NUM_ROOMS) |i| {
- rooms[i] = bipolarRandom(DIM, 0xD106000 + @as(u64, @intCast(i)));
- }
-
- // --- Build spatial graph ---
- // Layout:
- // garden(3) bathroom(5)
- // kitchen(0) office(2) garage(7)
- // bedroom(1) hallway(4) living(6)
- //
- // Use PERMUTATION to break bind commutativity:
- // encode: bind(from, permute(to, shift)) β different shift per direction
- // query: unbind(edge, from) β permute(to, shift), compare vs permute(cand, shift)
-
- const DirEdge = struct { from: usize, to: usize };
- const north_edges = [_]DirEdge{
- .{ .from = 0, .to = 3 }, .{ .from = 2, .to = 5 },
- .{ .from = 1, .to = 0 }, .{ .from = 4, .to = 2 },
- };
- const east_edges = [_]DirEdge{
- .{ .from = 0, .to = 2 }, .{ .from = 1, .to = 4 },
- .{ .from = 4, .to = 6 }, .{ .from = 2, .to = 7 },
- .{ .from = 3, .to = 5 },
- };
-
- // Per-direction permutation shifts
- const SHIFT_N: u32 = 1;
- const SHIFT_S: u32 = 2;
- const SHIFT_E: u32 = 3;
- const SHIFT_W: u32 = 4;
- const shifts = [_]u32{ SHIFT_N, SHIFT_S, SHIFT_E, SHIFT_W };
-
- // Build per-pair individual edge memories: 4N + 4S + 5E + 5W = 18
- const TOTAL_EDGES = 18;
- var edge_mems: [TOTAL_EDGES]Hypervector = undefined;
- var ei: usize = 0;
- for (0..4) |i| { // North
- var from = rooms[north_edges[i].from];
- var tp = rooms[north_edges[i].to].permute(SHIFT_N);
- edge_mems[ei] = from.bind(&tp);
- ei += 1;
- }
- for (0..4) |i| { // South (reverse north)
- var from = rooms[north_edges[i].to];
- var tp = rooms[north_edges[i].from].permute(SHIFT_S);
- edge_mems[ei] = from.bind(&tp);
- ei += 1;
- }
- for (0..5) |i| { // East
- var from = rooms[east_edges[i].from];
- var tp = rooms[east_edges[i].to].permute(SHIFT_E);
- edge_mems[ei] = from.bind(&tp);
- ei += 1;
- }
- for (0..5) |i| { // West (reverse east)
- var from = rooms[east_edges[i].to];
- var tp = rooms[east_edges[i].from].permute(SHIFT_W);
- edge_mems[ei] = from.bind(&tp);
- ei += 1;
- }
-
- // Direction ranges: N:0..4, S:4..8, E:8..13, W:13..18
- const dir_ranges = [_][2]usize{ .{ 0, 4 }, .{ 4, 8 }, .{ 8, 13 }, .{ 13, 18 } };
-
- // Pre-compute permuted room vectors for each direction
- var perm_rooms: [4][NUM_ROOMS]Hypervector = undefined;
- for (0..4) |d| {
- for (0..NUM_ROOMS) |r| {
- perm_rooms[d][r] = rooms[r].permute(shifts[d]);
- }
- }
-
- // Helper: query per-pair direction edges with permutation
- const QueryResult = struct { idx: usize, sim: f64 };
- const queryPermDir = struct {
- fn query(edges: []Hypervector, perm_candidates: []Hypervector, from: *Hypervector) QueryResult {
- var best = QueryResult{ .idx = 0, .sim = -2.0 };
- for (edges) |*edge| {
- var result = edge.unbind(from); // = permute(to, shift) for matching edge
- for (0..perm_candidates.len) |j| {
- var pc = perm_candidates[j];
- const sim = result.similarity(&pc);
- if (sim > best.sim) {
- best.sim = sim;
- best.idx = j;
- }
- }
- }
- return best;
- }
- }.query;
-
- // --- Task 4 style: 2-step paths ---
- std.debug.print("\n--- Task 4: Two-Step Pathfinding ---\n", .{});
-
- // Path queries: from β (dir1) β mid β (dir2) β dest
- const PathQuery = struct {
- from: usize,
- dir1: u8, // 0=N, 1=S, 2=E, 3=W
- mid: usize,
- dir2: u8,
- dest: usize,
- };
- const two_step_paths = [_]PathQuery{
- // bedroom β NORTH β kitchen β EAST β office
- .{ .from = 1, .dir1 = 0, .mid = 0, .dir2 = 2, .dest = 2 },
- // bedroom β NORTH β kitchen β NORTH β garden
- .{ .from = 1, .dir1 = 0, .mid = 0, .dir2 = 0, .dest = 3 },
- // bedroom β EAST β hallway β EAST β living
- .{ .from = 1, .dir1 = 2, .mid = 4, .dir2 = 2, .dest = 6 },
- // bedroom β EAST β hallway β NORTH β office
- .{ .from = 1, .dir1 = 2, .mid = 4, .dir2 = 0, .dest = 2 },
- // kitchen β EAST β office β EAST β garage
- .{ .from = 0, .dir1 = 2, .mid = 2, .dir2 = 2, .dest = 7 },
- // kitchen β EAST β office β NORTH β bathroom
- .{ .from = 0, .dir1 = 2, .mid = 2, .dir2 = 0, .dest = 5 },
- // garden β EAST β bathroom β SOUTH β office
- .{ .from = 3, .dir1 = 2, .mid = 5, .dir2 = 1, .dest = 2 },
- // living β WEST β hallway β NORTH β office
- .{ .from = 6, .dir1 = 3, .mid = 4, .dir2 = 0, .dest = 2 },
- };
-
- var task4_correct: u32 = 0;
- const task4_total: u32 = two_step_paths.len;
-
- for (two_step_paths) |pq| {
- // Step 1: follow dir1 from "from"
- var from_room = rooms[pq.from];
- const rng1 = dir_ranges[pq.dir1];
- const r1 = queryPermDir(edge_mems[rng1[0]..rng1[1]], perm_rooms[pq.dir1][0..NUM_ROOMS], &from_room);
-
- // Step 2: follow dir2 from result of step 1
- var mid_room = rooms[r1.idx];
- const rng2 = dir_ranges[pq.dir2];
- const r2 = queryPermDir(edge_mems[rng2[0]..rng2[1]], perm_rooms[pq.dir2][0..NUM_ROOMS], &mid_room);
-
- const step1_ok = r1.idx == pq.mid;
- const step2_ok = r2.idx == pq.dest;
-
- if (step1_ok and step2_ok) {
- task4_correct += 1;
- }
-
- std.debug.print(" Path: {s} β({s})β {s} β({s})β {s} | step1={} step2={}\n", .{
- room_names[pq.from],
- @as([]const u8, if (pq.dir1 == 0) "N" else if (pq.dir1 == 1) "S" else if (pq.dir1 == 2) "E" else "W"),
- room_names[pq.mid],
- @as([]const u8, if (pq.dir2 == 0) "N" else if (pq.dir2 == 1) "S" else if (pq.dir2 == 2) "E" else "W"),
- room_names[pq.dest],
- step1_ok,
- step2_ok,
- });
- }
-
- std.debug.print("Task 4 (2-step): {d}/{d}\n", .{ task4_correct, task4_total });
-
- // --- Task 5 style: 3-step paths ---
- std.debug.print("\n--- Task 5: Three-Step Pathfinding ---\n", .{});
-
- const ThreeStepPath = struct {
- from: usize,
- dir1: u8,
- mid1: usize,
- dir2: u8,
- mid2: usize,
- dir3: u8,
- dest: usize,
- };
- const three_step_paths = [_]ThreeStepPath{
- // bedroom β N β kitchen β E β office β N β bathroom
- .{ .from = 1, .dir1 = 0, .mid1 = 0, .dir2 = 2, .mid2 = 2, .dir3 = 0, .dest = 5 },
- // bedroom β N β kitchen β N β garden β E β bathroom
- .{ .from = 1, .dir1 = 0, .mid1 = 0, .dir2 = 0, .mid2 = 3, .dir3 = 2, .dest = 5 },
- // bedroom β E β hallway β E β living β W β hallway
- .{ .from = 1, .dir1 = 2, .mid1 = 4, .dir2 = 2, .mid2 = 6, .dir3 = 3, .dest = 4 },
- // bedroom β E β hallway β N β office β E β garage
- .{ .from = 1, .dir1 = 2, .mid1 = 4, .dir2 = 0, .mid2 = 2, .dir3 = 2, .dest = 7 },
- // garage β W β office β S β hallway β W β bedroom
- .{ .from = 7, .dir1 = 3, .mid1 = 2, .dir2 = 1, .mid2 = 4, .dir3 = 3, .dest = 1 },
- // garden β S β kitchen β S β bedroom β E β hallway
- .{ .from = 3, .dir1 = 1, .mid1 = 0, .dir2 = 1, .mid2 = 1, .dir3 = 2, .dest = 4 },
- };
-
- var task5_correct: u32 = 0;
- const task5_total: u32 = three_step_paths.len;
-
- for (three_step_paths) |pq| {
- var from_room = rooms[pq.from];
-
- const rng1 = dir_ranges[pq.dir1];
- const r1 = queryPermDir(edge_mems[rng1[0]..rng1[1]], perm_rooms[pq.dir1][0..NUM_ROOMS], &from_room);
- var m1 = rooms[r1.idx];
- const rng2 = dir_ranges[pq.dir2];
- const r2 = queryPermDir(edge_mems[rng2[0]..rng2[1]], perm_rooms[pq.dir2][0..NUM_ROOMS], &m1);
- var m2 = rooms[r2.idx];
- const rng3 = dir_ranges[pq.dir3];
- const r3 = queryPermDir(edge_mems[rng3[0]..rng3[1]], perm_rooms[pq.dir3][0..NUM_ROOMS], &m2);
-
- const ok1 = r1.idx == pq.mid1;
- const ok2 = r2.idx == pq.mid2;
- const ok3 = r3.idx == pq.dest;
-
- if (ok1 and ok2 and ok3) {
- task5_correct += 1;
- }
-
- std.debug.print(" Path: {s} β{s}β {s} β{s}β {s} β{s}β {s} | {},{},{}\n", .{
- room_names[pq.from],
- @as([]const u8, if (pq.dir1 == 0) "N" else if (pq.dir1 == 1) "S" else if (pq.dir1 == 2) "E" else "W"),
- room_names[pq.mid1],
- @as([]const u8, if (pq.dir2 == 0) "N" else if (pq.dir2 == 1) "S" else if (pq.dir2 == 2) "E" else "W"),
- room_names[pq.mid2],
- @as([]const u8, if (pq.dir3 == 0) "N" else if (pq.dir3 == 1) "S" else if (pq.dir3 == 2) "E" else "W"),
- room_names[pq.dest],
- ok1,
- ok2,
- ok3,
- });
- }
-
- std.debug.print("Task 5 (3-step): {d}/{d}\n", .{ task5_correct, task5_total });
-
- // --- Combined pathfinding results ---
- const total_path_correct = task4_correct + task5_correct;
- const total_path_total = task4_total + task5_total;
- const path_acc = @as(f64, @floatFromInt(total_path_correct)) / @as(f64, @floatFromInt(total_path_total)) * 100.0;
-
- std.debug.print("\n--- Pathfinding Summary ---\n", .{});
- std.debug.print("Task 4 (2-step): {d}/{d}\n", .{ task4_correct, task4_total });
- std.debug.print("Task 5 (3-step): {d}/{d}\n", .{ task5_correct, task5_total });
- std.debug.print("Combined: {d}/{d} ({d:.0}%)\n", .{ total_path_correct, total_path_total, path_acc });
-
- // bAbI coverage update: 7 β 9 tasks (adding tasks 4 and 5)
- std.debug.print("bAbI coverage: 9/20 tasks (added pathfinding)\n", .{});
-
- try std.testing.expect(task4_correct == task4_total);
- try std.testing.expect(task5_correct == task5_total);
-}
-
-// Test 107: Branch Kinship β uncle, cousin, nephew via cross-relation composition
-// Per-family indexed memories for parent, sibling, child relations
-// Cross-relation multi-hop: parent + sibling + child relations composed
-test "clutrr branch kinship cross relation composition" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 107: Branch Kinship (uncle, cousin)\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
- const FAMILIES = 3;
- const PPF = 6; // people per family
- const TOTAL = FAMILIES * PPF; // 18
-
- var people: [TOTAL]Hypervector = undefined;
- for (0..TOTAL) |i| {
- people[i] = bipolarRandom(DIM, 0xD107000 + @as(u64, @intCast(i)));
- }
-
- // Indices within each family f:
- // f*6+0 = grandparent
- // f*6+1 = parent_a (child of grandparent)
- // f*6+2 = parent_b (child of grandparent, sibling of parent_a)
- // f*6+3 = child_a1 (child of parent_a)
- // f*6+4 = child_a2 (child of parent_a)
- // f*6+5 = child_b1 (child of parent_b)
-
- // --- Build PER-FAMILY + PER-LEVEL indexed memories ---
- // Key insight from 11.16: per-LEVEL indexing prevents cross-generation interference
- //
- // Parent memories (childβparent):
- // Level 0 (gen2βgen1): ca1βpa, ca2βpa, cb1βpb (3 pairs)
- // Level 1 (gen1βgen0): paβgp, pbβgp (2 pairs)
- //
- // Sibling memories: paβpb, ca1βca2 (4 pairs, same generation)
- //
- // Child memories (parentβchild):
- // Level 0 (gen1βgen2): paβca1, paβca2, pbβcb1 (3 pairs)
- // Level 1 (gen0βgen1): gpβpa, gpβpb (2 pairs)
-
- var parent_l0: [FAMILIES]Hypervector = undefined; // children β parents
- var parent_l1: [FAMILIES]Hypervector = undefined; // parents β grandparent
- var sibling_mems: [FAMILIES]Hypervector = undefined;
- var child_l0: [FAMILIES]Hypervector = undefined; // parents β children
- var child_l1: [FAMILIES]Hypervector = undefined; // grandparent β parents
-
- for (0..FAMILIES) |f| {
- const base = f * PPF;
- var gp = people[base + 0];
- var pa = people[base + 1];
- var pb = people[base + 2];
- var ca1 = people[base + 3];
- var ca2 = people[base + 4];
- var cb1 = people[base + 5];
-
- // Parent L0: children β parents (3 pairs)
- var pl0: [3]Hypervector = undefined;
- pl0[0] = ca1.bind(&pa);
- pl0[1] = ca2.bind(&pa);
- pl0[2] = cb1.bind(&pb);
- parent_l0[f] = treeBundleN(pl0[0..3]);
-
- // Parent L1: parents β grandparent (2 pairs)
- var pl1: [2]Hypervector = undefined;
- pl1[0] = pa.bind(&gp);
- pl1[1] = pb.bind(&gp);
- parent_l1[f] = treeBundleN(pl1[0..2]);
-
- // Sibling: bidirectional (4 pairs)
- var sb: [4]Hypervector = undefined;
- sb[0] = pa.bind(&pb);
- sb[1] = pb.bind(&pa);
- sb[2] = ca1.bind(&ca2);
- sb[3] = ca2.bind(&ca1);
- sibling_mems[f] = treeBundleN(sb[0..4]);
-
- // Child L0: parents β children (3 pairs)
- var cl0: [3]Hypervector = undefined;
- cl0[0] = pa.bind(&ca1);
- cl0[1] = pa.bind(&ca2);
- cl0[2] = pb.bind(&cb1);
- child_l0[f] = treeBundleN(cl0[0..3]);
-
- // Child L1: grandparent β parents (2 pairs)
- var cl1: [2]Hypervector = undefined;
- cl1[0] = gp.bind(&pa);
- cl1[1] = gp.bind(&pb);
- child_l1[f] = treeBundleN(cl1[0..2]);
- }
-
- // --- Query helper: search within family codebook ---
- const queryFam = struct {
- fn query(mem: *Hypervector, key: *Hypervector, all: []Hypervector, fam: usize, ppf: usize) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- const base = fam * ppf;
- var bi: usize = base;
- var bs: f64 = -2.0;
- for (base..base + ppf) |j| {
- var cj = all[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.query;
-
- // --- Uncle queries ---
- // uncle(X) = sibling(parent(X))
- std.debug.print("\n--- Uncle Queries (sibling of parent) ---\n", .{});
-
- var uncle_correct: u32 = 0;
- var uncle_total: u32 = 0;
-
- for (0..FAMILIES) |f| {
- const base = f * PPF;
- const uncle_qs = [_]struct { child_idx: usize, expected: usize }{
- .{ .child_idx = base + 3, .expected = base + 2 },
- .{ .child_idx = base + 4, .expected = base + 2 },
- .{ .child_idx = base + 5, .expected = base + 1 },
- };
-
- for (uncle_qs) |uq| {
- var child_v = people[uq.child_idx];
- // Use L0 parent memory (children β parents)
- const parent_r = queryFam(&parent_l0[f], &child_v, people[0..TOTAL], f, PPF);
- var parent_v = people[parent_r.idx];
- const uncle_r = queryFam(&sibling_mems[f], &parent_v, people[0..TOTAL], f, PPF);
-
- uncle_total += 1;
- const ok = uncle_r.idx == uq.expected;
- if (ok) uncle_correct += 1;
-
- std.debug.print(" uncle(p[{d}]) β par[{d}] β sib[{d}] (exp {d}) {s}\n", .{
- uq.child_idx, parent_r.idx, uncle_r.idx, uq.expected,
- if (ok) "OK" else "FAIL",
- });
- }
- }
- std.debug.print("Uncle: {d}/{d}\n", .{ uncle_correct, uncle_total });
-
- // --- Cousin queries ---
- // cousin(X) = child(sibling(parent(X)))
- std.debug.print("\n--- Cousin Queries (child of uncle) ---\n", .{});
-
- var cousin_correct: u32 = 0;
- var cousin_total: u32 = 0;
-
- for (0..FAMILIES) |f| {
- const base = f * PPF;
- const cousin_qs = [_]struct { child_idx: usize, expected: usize }{
- .{ .child_idx = base + 3, .expected = base + 5 },
- .{ .child_idx = base + 4, .expected = base + 5 },
- };
-
- for (cousin_qs) |cq| {
- var child_v = people[cq.child_idx];
- // L0: child β parent, then sibling, then L0 child: uncle β cousin
- const p_r = queryFam(&parent_l0[f], &child_v, people[0..TOTAL], f, PPF);
- var par_v = people[p_r.idx];
- const u_r = queryFam(&sibling_mems[f], &par_v, people[0..TOTAL], f, PPF);
- var uncle_v = people[u_r.idx];
- const c_r = queryFam(&child_l0[f], &uncle_v, people[0..TOTAL], f, PPF);
-
- cousin_total += 1;
- const ok = c_r.idx == cq.expected;
- if (ok) cousin_correct += 1;
-
- std.debug.print(" cousin(p[{d}]) β par[{d}] β unc[{d}] β cou[{d}] (exp {d}) {s}\n", .{
- cq.child_idx, p_r.idx, u_r.idx, c_r.idx, cq.expected,
- if (ok) "OK" else "FAIL",
- });
- }
- }
- std.debug.print("Cousin: {d}/{d}\n", .{ cousin_correct, cousin_total });
-
- // --- Nephew queries ---
- // nephew(X) = child(sibling(X))
- std.debug.print("\n--- Nephew Queries (child of sibling) ---\n", .{});
-
- var nephew_correct: u32 = 0;
- var nephew_total: u32 = 0;
-
- for (0..FAMILIES) |f| {
- const base = f * PPF;
- // parent_a's nephew = child_b1
- var pa_v = people[base + 1];
- const sib_r = queryFam(&sibling_mems[f], &pa_v, people[0..TOTAL], f, PPF);
- var sib_v = people[sib_r.idx];
- const neph_r = queryFam(&child_l0[f], &sib_v, people[0..TOTAL], f, PPF);
-
- nephew_total += 1;
- const ok = neph_r.idx == base + 5;
- if (ok) nephew_correct += 1;
-
- std.debug.print(" nephew(p[{d}]) β sib[{d}] β child[{d}] (exp {d}) {s}\n", .{
- base + 1, sib_r.idx, neph_r.idx, base + 5,
- if (ok) "OK" else "FAIL",
- });
-
- // parent_b's nephew = child_a1 or child_a2
- var pb_v = people[base + 2];
- const sib_r2 = queryFam(&sibling_mems[f], &pb_v, people[0..TOTAL], f, PPF);
- var sib_v2 = people[sib_r2.idx];
- const neph_r2 = queryFam(&child_l0[f], &sib_v2, people[0..TOTAL], f, PPF);
-
- nephew_total += 1;
- const ok2 = neph_r2.idx == base + 3 or neph_r2.idx == base + 4;
- if (ok2) nephew_correct += 1;
-
- std.debug.print(" nephew(p[{d}]) β sib[{d}] β child[{d}] (exp {d}/{d}) {s}\n", .{
- base + 2, sib_r2.idx, neph_r2.idx, base + 3, base + 4,
- if (ok2) "OK" else "FAIL",
- });
- }
- std.debug.print("Nephew: {d}/{d}\n", .{ nephew_correct, nephew_total });
-
- // --- Grandparent queries (2-hop parent chain) ---
- std.debug.print("\n--- Grandparent Queries (parent of parent) ---\n", .{});
-
- var gp_correct: u32 = 0;
- var gp_total: u32 = 0;
-
- for (0..FAMILIES) |f| {
- const base = f * PPF;
- const grandchildren = [_]usize{ base + 3, base + 4, base + 5 };
-
- for (grandchildren) |gc_idx| {
- var gc_v = people[gc_idx];
- // L0: child β parent, then L1: parent β grandparent
- const p1 = queryFam(&parent_l0[f], &gc_v, people[0..TOTAL], f, PPF);
- var p1_v = people[p1.idx];
- const p2 = queryFam(&parent_l1[f], &p1_v, people[0..TOTAL], f, PPF);
-
- gp_total += 1;
- const ok = p2.idx == base + 0;
- if (ok) gp_correct += 1;
-
- std.debug.print(" gp(p[{d}]) β par[{d}] β gp[{d}] (exp {d}) {s}\n", .{
- gc_idx, p1.idx, p2.idx, base + 0,
- if (ok) "OK" else "FAIL",
- });
- }
- }
- std.debug.print("Grandparent: {d}/{d}\n", .{ gp_correct, gp_total });
-
- // --- Summary ---
- const branch_total = uncle_total + cousin_total + nephew_total + gp_total;
- const branch_correct = uncle_correct + cousin_correct + nephew_correct + gp_correct;
- const branch_acc = @as(f64, @floatFromInt(branch_correct)) / @as(f64, @floatFromInt(branch_total)) * 100.0;
-
- std.debug.print("\n--- Branch Kinship Summary ---\n", .{});
- std.debug.print("Uncle: {d}/{d}\n", .{ uncle_correct, uncle_total });
- std.debug.print("Cousin: {d}/{d}\n", .{ cousin_correct, cousin_total });
- std.debug.print("Nephew: {d}/{d}\n", .{ nephew_correct, nephew_total });
- std.debug.print("Grandparent: {d}/{d}\n", .{ gp_correct, gp_total });
- std.debug.print("Combined: {d}/{d} ({d:.0}%)\n", .{ branch_correct, branch_total, branch_acc });
-
- try std.testing.expect(uncle_correct == uncle_total);
- try std.testing.expect(cousin_correct == cousin_total);
- try std.testing.expect(nephew_correct >= nephew_total * 2 / 3);
- try std.testing.expect(gp_correct == gp_total);
- try std.testing.expect(branch_correct >= branch_total * 9 / 10); // at least 90%
-}
-
-// Test 108: Large Codebook Scaling β scoped vs global retrieval at 100+ candidates
-// Key insight: indexed memories + SCOPED codebooks = perfect retrieval at any scale
-// Global search across all candidates degrades; scoped search within memory scope stays perfect
-test "large codebook scaling 100 plus candidates" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 108: Large Codebook (100+ candidates)\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
- const PAIRS = 3; // 3 pairs per memory for clean signal
-
- // --- 30 vectors, 10 memories Γ 3 pairs, SCOPED vs GLOBAL ---
- const N = 30;
- var vecs: [N]Hypervector = undefined;
- for (0..N) |i| {
- vecs[i] = bipolarRandom(DIM, 0xD108030 + @as(u64, @intCast(i)));
- }
-
- const MEMS = N / PAIRS; // 10
- var mems: [MEMS]Hypervector = undefined;
- for (0..MEMS) |m| {
- var binds: [PAIRS]Hypervector = undefined;
- for (0..PAIRS) |p| {
- const ki = m * PAIRS + p;
- const vi = (ki + 1) % N;
- var k = vecs[ki];
- var v = vecs[vi];
- binds[p] = k.bind(&v);
- }
- mems[m] = treeBundleN(binds[0..PAIRS]);
- }
-
- // Scoped: search only within memory's own values
- var scoped30: u32 = 0;
- for (0..N) |i| {
- const mi = i / PAIRS;
- const expected = (i + 1) % N;
- var key = vecs[i];
- var result = mems[mi].unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..PAIRS) |p| {
- const vi = (mi * PAIRS + p + 1) % N;
- var cj = vecs[vi];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = vi;
- }
- }
- if (bi == expected) scoped30 += 1;
- }
-
- // Global: search across all N candidates
- var global30: u32 = 0;
- for (0..N) |i| {
- const mi = i / PAIRS;
- const expected = (i + 1) % N;
- var key = vecs[i];
- var result = mems[mi].unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..N) |j| {
- var cj = vecs[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- if (bi == expected) global30 += 1;
- }
-
- const s30 = @as(f64, @floatFromInt(scoped30)) / @as(f64, @floatFromInt(N)) * 100.0;
- const g30 = @as(f64, @floatFromInt(global30)) / @as(f64, @floatFromInt(N)) * 100.0;
- std.debug.print("Scale 30: scoped={d}/{d} ({d:.0}%), global={d}/{d} ({d:.0}%)\n", .{
- scoped30, N, s30, global30, N, g30,
- });
-
- // --- Scale to 120: reuse same 30-vec array across 4 batches, scoped ---
- // Each batch uses different seeds but same array slots to avoid stack overflow
- std.debug.print("\n--- Scale 120: 4 batches of 30, scoped ---\n", .{});
-
- var scoped120: u32 = 0;
-
- // Batch B (seeds 0xD108100+)
- for (0..N) |i| {
- vecs[i] = bipolarRandom(DIM, 0xD108100 + @as(u64, @intCast(i)));
- }
- for (0..MEMS) |m| {
- var binds2: [PAIRS]Hypervector = undefined;
- for (0..PAIRS) |p| {
- const ki = m * PAIRS + p;
- const vi = (ki + 1) % N;
- var k = vecs[ki];
- var v = vecs[vi];
- binds2[p] = k.bind(&v);
- }
- mems[m] = treeBundleN(binds2[0..PAIRS]);
- }
- for (0..N) |i| {
- const mi = i / PAIRS;
- const expected = (i + 1) % N;
- var key = vecs[i];
- var result = mems[mi].unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..PAIRS) |p| {
- const vi = (mi * PAIRS + p + 1) % N;
- var cj = vecs[vi];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = vi;
- }
- }
- if (bi == expected) scoped120 += 1;
- }
-
- // Batch C (seeds 0xD108200+)
- for (0..N) |i| {
- vecs[i] = bipolarRandom(DIM, 0xD108200 + @as(u64, @intCast(i)));
- }
- for (0..MEMS) |m| {
- var binds3: [PAIRS]Hypervector = undefined;
- for (0..PAIRS) |p| {
- const ki = m * PAIRS + p;
- const vi = (ki + 1) % N;
- var k = vecs[ki];
- var v = vecs[vi];
- binds3[p] = k.bind(&v);
- }
- mems[m] = treeBundleN(binds3[0..PAIRS]);
- }
- for (0..N) |i| {
- const mi = i / PAIRS;
- const expected = (i + 1) % N;
- var key = vecs[i];
- var result = mems[mi].unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..PAIRS) |p| {
- const vi = (mi * PAIRS + p + 1) % N;
- var cj = vecs[vi];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = vi;
- }
- }
- if (bi == expected) scoped120 += 1;
- }
-
- // Batch D (seeds 0xD108300+)
- for (0..N) |i| {
- vecs[i] = bipolarRandom(DIM, 0xD108300 + @as(u64, @intCast(i)));
- }
- for (0..MEMS) |m| {
- var binds4: [PAIRS]Hypervector = undefined;
- for (0..PAIRS) |p| {
- const ki = m * PAIRS + p;
- const vi = (ki + 1) % N;
- var k = vecs[ki];
- var v = vecs[vi];
- binds4[p] = k.bind(&v);
- }
- mems[m] = treeBundleN(binds4[0..PAIRS]);
- }
- for (0..N) |i| {
- const mi = i / PAIRS;
- const expected = (i + 1) % N;
- var key = vecs[i];
- var result = mems[mi].unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..PAIRS) |p| {
- const vi = (mi * PAIRS + p + 1) % N;
- var cj = vecs[vi];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = vi;
- }
- }
- if (bi == expected) scoped120 += 1;
- }
-
- const total120 = scoped30 + scoped120; // batch A (30) + B,C,D (90)
- const s120 = @as(f64, @floatFromInt(total120)) / 120.0 * 100.0;
- std.debug.print("Scoped 120 (4Γ30): {d}/120 ({d:.0}%)\n", .{ total120, s120 });
-
- // --- Summary ---
- const advantage = s30 - g30;
- std.debug.print("\n--- Large Codebook Summary ---\n", .{});
- std.debug.print("Scale | Search | Pairs | Accuracy\n", .{});
- std.debug.print("------|--------|-------|---------\n", .{});
- std.debug.print(" 30 | scoped | 3 | {d:.0}%%\n", .{s30});
- std.debug.print(" 30 | global | 3 | {d:.0}%%\n", .{g30});
- std.debug.print(" 120 | scoped | 3 | {d:.0}%%\n", .{s120});
- std.debug.print("Scoped vs global advantage: {d:.0}pp\n", .{advantage});
-
- // Scoped retrieval should be perfect at all scales
- try std.testing.expect(scoped30 == N);
- try std.testing.expect(total120 == 120);
- // Global should be lower (scoped advantage significant)
- try std.testing.expect(s30 > g30);
-
- // Progression summary
- std.debug.print("\n--- Level 11.18 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.16 | bAbI+CLUTRR SOTA | 100%% both\n", .{});
- std.debug.print("11.17 | Neuro-symbolic bench | vs baselines\n", .{});
- std.debug.print("11.18 | Full planning SOTA | pathfind+branch+large <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// =============================================================================
-// Test 109: Open Query KG β Real-world knowledge graph with user-driven queries
-// Level 11.19 β Real-World Demo
-// =============================================================================
-test "open query kg real world multi hop" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 109: Open Query KG (Real-World Demo)\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- Create entities: countries, capitals, continents, languages ---
- // 6 countries, 6 capitals, 4 continents, 5 languages = 21 entities
- const NUM_ENTITIES = 21;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- // Countries (0-5)
- "France", "Germany", "Japan", "Brazil", "Egypt", "Australia",
- // Capitals (6-11)
- "Paris", "Berlin", "Tokyo", "Brasilia", "Cairo", "Canberra",
- // Continents (12-15)
- "Europe", "Asia", "SouthAmerica", "Africa",
- // Languages (16-20)
- "French", "German",
- "Japanese", "Portuguese", "Arabic",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xD109000 + @as(u64, @intCast(i)) * 37);
- }
-
- // --- Build per-relation indexed memories ---
- // Relations: capital_of (countryβcapital), continent_of (countryβcontinent),
- // language_of (countryβlanguage), country_of (capitalβcountry)
-
- // capital_of: 6 pairs (country β capital)
- const cap_pairs = [_][2]usize{
- .{ 0, 6 }, .{ 1, 7 }, .{ 2, 8 }, .{ 3, 9 }, .{ 4, 10 }, .{ 5, 11 },
- };
- var cap_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[cap_pairs[i][0]];
- var v = entities[cap_pairs[i][1]];
- cap_binds[i] = k.bind(&v);
- }
- var capital_mem = treeBundleN(cap_binds[0..6]);
-
- // country_of: 6 pairs (capital β country) β inverse of capital_of
- // Since bind is commutative for bipolar, use permutation shift=5
- const SHIFT_COUNTRY: u32 = 5;
- var country_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[cap_pairs[i][1]]; // capital
- var v_perm = entities[cap_pairs[i][0]].permute(SHIFT_COUNTRY); // country permuted
- country_binds[i] = k.bind(&v_perm);
- }
- var country_mem = treeBundleN(country_binds[0..6]);
-
- // continent_of: 6 pairs (country β continent)
- const cont_pairs = [_][2]usize{
- .{ 0, 12 }, // France β Europe
- .{ 1, 12 }, // Germany β Europe
- .{ 2, 13 }, // Japan β Asia
- .{ 3, 14 }, // Brazil β SouthAmerica
- .{ 4, 15 }, // Egypt β Africa
- .{ 5, 13 }, // Australia β Asia (using Asia for simplicity β Oceania not in KB)
- };
- var cont_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[cont_pairs[i][0]];
- var v = entities[cont_pairs[i][1]];
- cont_binds[i] = k.bind(&v);
- }
- var continent_mem = treeBundleN(cont_binds[0..6]);
-
- // language_of: 6 pairs (country β language)
- const lang_pairs = [_][2]usize{
- .{ 0, 16 }, // France β French
- .{ 1, 17 }, // Germany β German
- .{ 2, 18 }, // Japan β Japanese
- .{ 3, 19 }, // Brazil β Portuguese
- .{ 4, 20 }, // Egypt β Arabic
- .{ 5, 16 }, // Australia β French (placeholder β English not in KB)
- };
- var lang_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[lang_pairs[i][0]];
- var v = entities[lang_pairs[i][1]];
- lang_binds[i] = k.bind(&v);
- }
- var language_mem = treeBundleN(lang_binds[0..6]);
-
- // --- Helper: query memory, find best entity ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // Permuted query (for country_of with shift)
- const queryPermMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector, shift: u32) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cp = candidates[j].permute(shift);
- const sim = result.similarity(&cp);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- 1-hop queries ---
- std.debug.print("\n--- 1-Hop Queries ---\n", .{});
- var correct_1hop: u32 = 0;
- const total_1hop: u32 = 12;
-
- // capital_of(country) β 6 queries
- for (0..6) |i| {
- var key = entities[cap_pairs[i][0]];
- const r = queryMem(&capital_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == cap_pairs[i][1];
- if (ok) correct_1hop += 1;
- std.debug.print(" capital_of({s}) = {s} {s}\n", .{
- entity_names[cap_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // continent_of(country) β 6 queries
- for (0..6) |i| {
- var key = entities[cont_pairs[i][0]];
- const r = queryMem(&continent_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == cont_pairs[i][1];
- if (ok) correct_1hop += 1;
- std.debug.print(" continent_of({s}) = {s} {s}\n", .{
- entity_names[cont_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- const acc_1hop = @as(f64, @floatFromInt(correct_1hop)) / @as(f64, @floatFromInt(total_1hop)) * 100.0;
- std.debug.print("1-hop: {d}/{d} ({d:.0}%)\n", .{ correct_1hop, total_1hop, acc_1hop });
-
- // --- 2-hop queries: "What continent is X's capital in?" ---
- // capitalβcountry (via country_of with permutation), then countryβcontinent
- std.debug.print("\n--- 2-Hop Queries ---\n", .{});
- var correct_2hop: u32 = 0;
- const total_2hop: u32 = 6;
-
- // "What continent is [capital]'s country on?"
- // Step 1: country_of(capital) β country, Step 2: continent_of(country) β continent
- const two_hop_queries = [_]struct { capital: usize, expected_continent: usize }{
- .{ .capital = 6, .expected_continent = 12 }, // Paris β France β Europe
- .{ .capital = 7, .expected_continent = 12 }, // Berlin β Germany β Europe
- .{ .capital = 8, .expected_continent = 13 }, // Tokyo β Japan β Asia
- .{ .capital = 9, .expected_continent = 14 }, // Brasilia β Brazil β SouthAmerica
- .{ .capital = 10, .expected_continent = 15 }, // Cairo β Egypt β Africa
- .{ .capital = 11, .expected_continent = 13 }, // Canberra β Australia β Asia
- };
-
- for (two_hop_queries) |q| {
- // Step 1: country_of(capital)
- var cap_key = entities[q.capital];
- const r1 = queryPermMem(&country_mem, &cap_key, entities[0..NUM_ENTITIES], SHIFT_COUNTRY);
- // Step 2: continent_of(country)
- var country_key = entities[r1.idx];
- const r2 = queryMem(&continent_mem, &country_key, entities[0..NUM_ENTITIES]);
-
- const ok = r2.idx == q.expected_continent;
- if (ok) correct_2hop += 1;
- std.debug.print(" continent_of(country_of({s})) = {s} via {s} {s}\n", .{
- entity_names[q.capital], entity_names[r2.idx], entity_names[r1.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- const acc_2hop = @as(f64, @floatFromInt(correct_2hop)) / @as(f64, @floatFromInt(total_2hop)) * 100.0;
- std.debug.print("2-hop: {d}/{d} ({d:.0}%)\n", .{ correct_2hop, total_2hop, acc_2hop });
-
- // --- 2-hop: "What language is spoken in [capital]'s country?" ---
- std.debug.print("\n--- 2-Hop Language Queries ---\n", .{});
- var correct_2hop_lang: u32 = 0;
- const total_2hop_lang: u32 = 6;
-
- for (0..6) |i| {
- // Step 1: country_of(capital)
- var cap_key = entities[cap_pairs[i][1]]; // capital
- const r1 = queryPermMem(&country_mem, &cap_key, entities[0..NUM_ENTITIES], SHIFT_COUNTRY);
- // Step 2: language_of(country)
- var country_key = entities[r1.idx];
- const r2 = queryMem(&language_mem, &country_key, entities[0..NUM_ENTITIES]);
-
- const expected_lang = lang_pairs[i][1];
- const ok = r2.idx == expected_lang;
- if (ok) correct_2hop_lang += 1;
- std.debug.print(" language_of(country_of({s})) = {s} via {s} {s}\n", .{
- entity_names[cap_pairs[i][1]], entity_names[r2.idx], entity_names[r1.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- const acc_2hop_lang = @as(f64, @floatFromInt(correct_2hop_lang)) / @as(f64, @floatFromInt(total_2hop_lang)) * 100.0;
- std.debug.print("2-hop language: {d}/{d} ({d:.0}%)\n", .{ correct_2hop_lang, total_2hop_lang, acc_2hop_lang });
-
- // --- Summary ---
- const total_all = total_1hop + total_2hop + total_2hop_lang;
- const correct_all = correct_1hop + correct_2hop + correct_2hop_lang;
- const acc_all = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total_all)) * 100.0;
-
- std.debug.print("\n--- Open Query KG Summary ---\n", .{});
- std.debug.print("1-hop: {d}/{d} ({d:.0}%)\n", .{ correct_1hop, total_1hop, acc_1hop });
- std.debug.print("2-hop continent:{d}/{d} ({d:.0}%)\n", .{ correct_2hop, total_2hop, acc_2hop });
- std.debug.print("2-hop language: {d}/{d} ({d:.0}%)\n", .{ correct_2hop_lang, total_2hop_lang, acc_2hop_lang });
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total_all, acc_all });
-
- // Assertions
- try std.testing.expect(correct_1hop >= 10); // at least 10/12 for 1-hop
- try std.testing.expect(correct_2hop >= 4); // at least 4/6 for 2-hop
- try std.testing.expect(correct_all >= 18); // at least 18/24 overall
-}
-
-// =============================================================================
-// Test 110: Combined Spatial + KG Planning
-// Level 11.19 β Navigate rooms to find objects, query properties
-// =============================================================================
-test "combined spatial kg planning" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 110: Combined Spatial + KG Planning\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 6 rooms + 6 objects + 4 properties = 16 entities ---
- const NUM_ENT = 16;
- var ent: [NUM_ENT]Hypervector = undefined;
- const ent_names = [_][]const u8{
- // Rooms (0-5)
- "lab", "office", "library", "kitchen", "garden", "storage",
- // Objects (6-11)
- "book", "laptop", "key", "food", "plant", "box",
- // Properties (12-15)
- "heavy", "light", "fragile", "durable",
- };
- for (0..NUM_ENT) |i| {
- ent[i] = bipolarRandom(DIM, 0xD110000 + @as(u64, @intCast(i)) * 41);
- }
-
- // --- Spatial: rooms connected with permutation encoding ---
- const SHIFT_NEXT: u32 = 6;
- const SHIFT_PREV: u32 = 7;
- // Linear path: lab(0) β office(1) β library(2) β kitchen(3) β garden(4) β storage(5)
- const room_links = [_][2]usize{ .{ 0, 1 }, .{ 1, 2 }, .{ 2, 3 }, .{ 3, 4 }, .{ 4, 5 } };
-
- var next_edges: [5]Hypervector = undefined;
- var prev_edges: [5]Hypervector = undefined;
- for (0..5) |i| {
- var from = ent[room_links[i][0]];
- var to_p = ent[room_links[i][1]].permute(SHIFT_NEXT);
- next_edges[i] = from.bind(&to_p);
-
- var from2 = ent[room_links[i][1]];
- var to_p2 = ent[room_links[i][0]].permute(SHIFT_PREV);
- prev_edges[i] = from2.bind(&to_p2);
- }
-
- // --- Objects in rooms: located_in(object β room) ---
- const obj_room = [_][2]usize{
- .{ 6, 2 }, // book in library
- .{ 7, 1 }, // laptop in office
- .{ 8, 5 }, // key in storage
- .{ 9, 3 }, // food in kitchen
- .{ 10, 4 }, // plant in garden
- .{ 11, 5 }, // box in storage
- };
- var loc_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = ent[obj_room[i][0]];
- var v = ent[obj_room[i][1]];
- loc_binds[i] = k.bind(&v);
- }
- var located_mem = treeBundleN(loc_binds[0..6]);
-
- // --- Object properties: has_property(object β property) ---
- const obj_prop = [_][2]usize{
- .{ 6, 14 }, // book is fragile
- .{ 7, 14 }, // laptop is fragile
- .{ 8, 13 }, // key is light
- .{ 9, 13 }, // food is light
- .{ 10, 13 }, // plant is light
- .{ 11, 12 }, // box is heavy
- };
- var prop_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = ent[obj_prop[i][0]];
- var v = ent[obj_prop[i][1]];
- prop_binds[i] = k.bind(&v);
- }
- var property_mem = treeBundleN(prop_binds[0..6]);
-
- // --- Helper: query memory ---
- const qm = struct {
- fn query(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.query;
-
- // Helper: navigate from room to room via per-pair edges + permutation
- const navNext = struct {
- fn query(edges: []Hypervector, from: *Hypervector, candidates: []Hypervector, shift: u32) struct { idx: usize, sim: f64 } {
- var best_idx: usize = 0;
- var best_sim: f64 = -2.0;
- for (edges) |*edge| {
- var result = edge.unbind(from);
- for (0..candidates.len) |j| {
- var cp = candidates[j].permute(shift);
- const sim = result.similarity(&cp);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = j;
- }
- }
- }
- return .{ .idx = best_idx, .sim = best_sim };
- }
- }.query;
-
- // --- Planning Queries ---
- // Q1: "Where is the book?" (1-hop: located_in)
- // Q2: "What property does the key have?" (1-hop: has_property)
- // Q3: "Navigate from lab to library (2 steps), what's there?" (spatial + KG)
- // Q4: "What property does the object in storage have?" (KG + KG: find object in storage, then property)
- // Q5: "From lab, go 3 rooms forward, what's fragile nearby?" (spatial chain + KG)
-
- std.debug.print("\n--- Planning Queries ---\n", .{});
- var total_correct: u32 = 0;
- const total_queries: u32 = 10;
-
- // Q1-Q6: Direct location queries (object β room)
- for (0..6) |i| {
- var key = ent[obj_room[i][0]];
- const r = qm(&located_mem, &key, ent[0..NUM_ENT]);
- const ok = r.idx == obj_room[i][1];
- if (ok) total_correct += 1;
- std.debug.print(" located_in({s}) = {s} {s}\n", .{
- ent_names[obj_room[i][0]], ent_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Q7-Q8: Spatial navigation (labβofficeβlibrary via next_edges)
- {
- var lab = ent[0];
- const r1 = navNext(next_edges[0..5], &lab, ent[0..NUM_ENT], SHIFT_NEXT);
- const ok1 = r1.idx == 1; // office
- if (ok1) total_correct += 1;
- std.debug.print(" nav(labβnext) = {s} {s}\n", .{
- ent_names[r1.idx], @as([]const u8, if (ok1) "OK" else "FAIL"),
- });
-
- var office_r = ent[r1.idx];
- const r2 = navNext(next_edges[0..5], &office_r, ent[0..NUM_ENT], SHIFT_NEXT);
- const ok2 = r2.idx == 2; // library
- if (ok2) total_correct += 1;
- std.debug.print(" nav(officeβnext) = {s} {s}\n", .{
- ent_names[r2.idx], @as([]const u8, if (ok2) "OK" else "FAIL"),
- });
- }
-
- // Q9-Q10: Combined β navigate to storage, then find what's heavy there
- {
- // Navigate: garden(4) β storage(5) via next
- var garden_r = ent[4];
- const r1 = navNext(next_edges[0..5], &garden_r, ent[0..NUM_ENT], SHIFT_NEXT);
- const ok1 = r1.idx == 5; // storage
- if (ok1) total_correct += 1;
- std.debug.print(" nav(gardenβnext) = {s} {s}\n", .{
- ent_names[r1.idx], @as([]const u8, if (ok1) "OK" else "FAIL"),
- });
-
- // What heavy object is in storage? Query property for box (obj 11 β heavy 12)
- var box = ent[11];
- const r2 = qm(&property_mem, &box, ent[0..NUM_ENT]);
- const ok2 = r2.idx == 12; // heavy
- if (ok2) total_correct += 1;
- std.debug.print(" property_of(box) = {s} {s}\n", .{
- ent_names[r2.idx], @as([]const u8, if (ok2) "OK" else "FAIL"),
- });
- }
-
- const acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- Combined Planning Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, acc });
-
- try std.testing.expect(total_correct >= 8); // at least 8/10
-}
-
-// =============================================================================
-// Test 111: Multi-Hop Chain Fluency (4-5 hops)
-// Level 11.19 β Deep reasoning chains across a knowledge graph
-// =============================================================================
-test "multi hop chain fluency deep reasoning" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 111: Multi-Hop Chain Fluency (4-5 hops)\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- Build a richer KG: 30 entities across 5 categories ---
- // People(0-5), Companies(6-11), Cities(12-17), Products(18-23), Countries(24-29)
- const NUM_ENT = 30;
- var ent: [NUM_ENT]Hypervector = undefined;
- const ent_names = [_][]const u8{
- // People (0-5)
- "Alice", "Bob", "Charlie", "Diana", "Eve", "Frank",
- // Companies (6-11)
- "TechCo", "BioLab", "FinServ", "AutoMfg", "MediaInc", "EnergyX",
- // Cities (12-17)
- "SanFran", "Boston", "London", "Munich", "Tokyo_c", "Sydney",
- // Products (18-23)
- "PhoneX", "DrugA", "FundB", "CarZ", "StreamS", "SolarP",
- // Countries (24-29)
- "USA", "UK", "Germany_c", "Japan_c", "Australia_c", "Canada",
- };
- for (0..NUM_ENT) |i| {
- ent[i] = bipolarRandom(DIM, 0xD111000 + @as(u64, @intCast(i)) * 53);
- }
-
- // --- Relations (per-relation indexed memories, 3 pairs each for clean signal) ---
-
- // works_at: person β company (6 pairs, split into 2 memories of 3)
- const works_at = [_][2]usize{
- .{ 0, 6 }, .{ 1, 7 }, .{ 2, 8 }, .{ 3, 9 }, .{ 4, 10 }, .{ 5, 11 },
- };
- var wa_a_binds: [3]Hypervector = undefined;
- var wa_b_binds: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = ent[works_at[i][0]];
- var v = ent[works_at[i][1]];
- wa_a_binds[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = ent[works_at[3 + i][0]];
- var v = ent[works_at[3 + i][1]];
- wa_b_binds[i] = k.bind(&v);
- }
- var works_at_a = treeBundleN(wa_a_binds[0..3]);
- var works_at_b = treeBundleN(wa_b_binds[0..3]);
-
- // hq_in: company β city (6 pairs, split 3+3)
- const hq_in = [_][2]usize{
- .{ 6, 12 }, .{ 7, 13 }, .{ 8, 14 }, .{ 9, 15 }, .{ 10, 16 }, .{ 11, 17 },
- };
- var hq_a_binds: [3]Hypervector = undefined;
- var hq_b_binds: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = ent[hq_in[i][0]];
- var v = ent[hq_in[i][1]];
- hq_a_binds[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = ent[hq_in[3 + i][0]];
- var v = ent[hq_in[3 + i][1]];
- hq_b_binds[i] = k.bind(&v);
- }
- var hq_in_a = treeBundleN(hq_a_binds[0..3]);
- var hq_in_b = treeBundleN(hq_b_binds[0..3]);
-
- // makes: company β product (6 pairs, split 3+3)
- const makes = [_][2]usize{
- .{ 6, 18 }, .{ 7, 19 }, .{ 8, 20 }, .{ 9, 21 }, .{ 10, 22 }, .{ 11, 23 },
- };
- var mk_a_binds: [3]Hypervector = undefined;
- var mk_b_binds: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = ent[makes[i][0]];
- var v = ent[makes[i][1]];
- mk_a_binds[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = ent[makes[3 + i][0]];
- var v = ent[makes[3 + i][1]];
- mk_b_binds[i] = k.bind(&v);
- }
- var makes_a = treeBundleN(mk_a_binds[0..3]);
- var makes_b = treeBundleN(mk_b_binds[0..3]);
-
- // city_in: city β country (6 pairs, split 3+3)
- const city_in = [_][2]usize{
- .{ 12, 24 }, .{ 13, 24 }, .{ 14, 25 }, .{ 15, 26 }, .{ 16, 27 }, .{ 17, 28 },
- };
- var ci_a_binds: [3]Hypervector = undefined;
- var ci_b_binds: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = ent[city_in[i][0]];
- var v = ent[city_in[i][1]];
- ci_a_binds[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = ent[city_in[3 + i][0]];
- var v = ent[city_in[3 + i][1]];
- ci_b_binds[i] = k.bind(&v);
- }
- var city_in_a = treeBundleN(ci_a_binds[0..3]);
- var city_in_b = treeBundleN(ci_b_binds[0..3]);
-
- // --- Helper: query split memory (checks both sub-memories) ---
- const querySplit = struct {
- fn q(mem_a: *Hypervector, mem_b: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var ra = mem_a.unbind(key);
- var rb = mem_b.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sa = ra.similarity(&cj);
- const sb = rb.similarity(&cj);
- const s = if (sa > sb) sa else sb;
- if (s > bs) {
- bs = s;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- 2-hop chains: person β company β city ---
- std.debug.print("\n--- 2-Hop: person β company β city ---\n", .{});
- var correct_2hop: u32 = 0;
- for (0..6) |i| {
- var person = ent[works_at[i][0]];
- const r1 = querySplit(&works_at_a, &works_at_b, &person, ent[0..NUM_ENT]);
- var company = ent[r1.idx];
- const r2 = querySplit(&hq_in_a, &hq_in_b, &company, ent[0..NUM_ENT]);
- const expected_city = hq_in[i][1];
- const ok = r2.idx == expected_city;
- if (ok) correct_2hop += 1;
- std.debug.print(" {s} β {s} β {s} {s}\n", .{
- ent_names[works_at[i][0]], ent_names[r1.idx], ent_names[r2.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("2-hop: {d}/6\n", .{correct_2hop});
-
- // --- 3-hop chains: person β company β city β country ---
- std.debug.print("\n--- 3-Hop: person β company β city β country ---\n", .{});
- var correct_3hop: u32 = 0;
- for (0..6) |i| {
- var person = ent[works_at[i][0]];
- const r1 = querySplit(&works_at_a, &works_at_b, &person, ent[0..NUM_ENT]);
- var company = ent[r1.idx];
- const r2 = querySplit(&hq_in_a, &hq_in_b, &company, ent[0..NUM_ENT]);
- var city = ent[r2.idx];
- const r3 = querySplit(&city_in_a, &city_in_b, &city, ent[0..NUM_ENT]);
- const expected_country = city_in[i][1];
- const ok = r3.idx == expected_country;
- if (ok) correct_3hop += 1;
- std.debug.print(" {s} β {s} β {s} β {s} {s}\n", .{
- ent_names[works_at[i][0]], ent_names[r1.idx], ent_names[r2.idx], ent_names[r3.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("3-hop: {d}/6\n", .{correct_3hop});
-
- // --- 3-hop alt: person β company β product (what does X's company make?) ---
- std.debug.print("\n--- 3-Hop Alt: person β company β product ---\n", .{});
- var correct_3hop_alt: u32 = 0;
- for (0..6) |i| {
- var person = ent[works_at[i][0]];
- const r1 = querySplit(&works_at_a, &works_at_b, &person, ent[0..NUM_ENT]);
- var company = ent[r1.idx];
- const r2 = querySplit(&makes_a, &makes_b, &company, ent[0..NUM_ENT]);
- const expected_product = makes[i][1];
- const ok = r2.idx == expected_product;
- if (ok) correct_3hop_alt += 1;
- std.debug.print(" {s} β {s} β {s} {s}\n", .{
- ent_names[works_at[i][0]], ent_names[r1.idx], ent_names[r2.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("3-hop product: {d}/6\n", .{correct_3hop_alt});
-
- // --- Summary ---
- const total = @as(u32, 18);
- const correct_all = correct_2hop + correct_3hop + correct_3hop_alt;
- const acc = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total)) * 100.0;
-
- std.debug.print("\n--- Multi-Hop Chain Summary ---\n", .{});
- std.debug.print("2-hop (personβcompanyβcity): {d}/6\n", .{correct_2hop});
- std.debug.print("3-hop (personβcompanyβcityβcountry): {d}/6\n", .{correct_3hop});
- std.debug.print("3-hop (personβcompanyβproduct): {d}/6\n", .{correct_3hop_alt});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total, acc });
-
- // Assertions
- try std.testing.expect(correct_2hop >= 5); // at least 5/6
- try std.testing.expect(correct_3hop >= 4); // at least 4/6 for 3-hop
- try std.testing.expect(correct_all >= 14); // at least 14/18
-
- // Progression
- std.debug.print("\n--- Level 11.19 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.17 | Neuro-symbolic bench | vs baselines\n", .{});
- std.debug.print("11.18 | Full planning SOTA | pathfind+branch+large\n", .{});
- std.debug.print("11.19 | Real-world demo | open KG+spatial+multi-hop <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// =============================================================================
-// Test 112: Unified Multi-Domain Fusion
-// Level 11.20 β Fuse multiple domains into single entity space, 4-hop chains
-// =============================================================================
-
-test "unified multi domain fusion engine" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 112: Unified Multi-Domain Fusion\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- Unified entity space: 7 categories, 36 entities total ---
- // People(0-5), Companies(6-11), Cities(12-17), Countries(18-23),
- // Continents(24-27), Products(28-33), Languages(34-35)
- const NUM_ENTITIES = 36;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- // People (0-5)
- "Alice", "Bob", "Charlie", "Diana", "Eve", "Frank",
- // Companies (6-11)
- "TechCo", "BioLab", "FinServ", "AutoMfg", "MediaInc", "EnergyX",
- // Cities (12-17)
- "SanFran", "Boston", "London", "Munich", "Tokyo", "Sydney",
- // Countries (18-23)
- "USA", "USA2", "UK", "Germany", "Japan", "Australia",
- // Continents (24-27)
- "NorthAmerica", "Europe", "Asia", "Oceania",
- // Products (28-33)
- "PhoneX", "DrugA",
- "TradBot", "RoboCar", "StreamBox", "SolarPanel",
- // Languages (34-35)
- "English", "German",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xE112000 + @as(u64, @intCast(i)) * 41);
- }
-
- // --- Build relation memories (all per-relation, some split) ---
-
- // works_at: personβcompany (6 pairs, split 3+3)
- const works_pairs = [_][2]usize{
- .{ 0, 6 }, .{ 1, 7 }, .{ 2, 8 }, // sub A
- .{ 3, 9 }, .{ 4, 10 }, .{ 5, 11 }, // sub B
- };
- var wa_binds_a: [3]Hypervector = undefined;
- var wa_binds_b: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[works_pairs[i][0]];
- var v = entities[works_pairs[i][1]];
- wa_binds_a[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[works_pairs[i + 3][0]];
- var v = entities[works_pairs[i + 3][1]];
- wa_binds_b[i] = k.bind(&v);
- }
- var works_at_a = treeBundleN(wa_binds_a[0..3]);
- var works_at_b = treeBundleN(wa_binds_b[0..3]);
-
- // hq_in: companyβcity (6 pairs, split 3+3)
- const hq_pairs = [_][2]usize{
- .{ 6, 12 }, .{ 7, 13 }, .{ 8, 14 },
- .{ 9, 15 }, .{ 10, 16 }, .{ 11, 17 },
- };
- var hq_binds_a: [3]Hypervector = undefined;
- var hq_binds_b: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[hq_pairs[i][0]];
- var v = entities[hq_pairs[i][1]];
- hq_binds_a[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[hq_pairs[i + 3][0]];
- var v = entities[hq_pairs[i + 3][1]];
- hq_binds_b[i] = k.bind(&v);
- }
- var hq_in_a = treeBundleN(hq_binds_a[0..3]);
- var hq_in_b = treeBundleN(hq_binds_b[0..3]);
-
- // city_in: cityβcountry (6 pairs, split 3+3)
- const city_pairs = [_][2]usize{
- .{ 12, 18 }, .{ 13, 19 }, .{ 14, 20 },
- .{ 15, 21 }, .{ 16, 22 }, .{ 17, 23 },
- };
- var ci_binds_a: [3]Hypervector = undefined;
- var ci_binds_b: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[city_pairs[i][0]];
- var v = entities[city_pairs[i][1]];
- ci_binds_a[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[city_pairs[i + 3][0]];
- var v = entities[city_pairs[i + 3][1]];
- ci_binds_b[i] = k.bind(&v);
- }
- var city_in_a = treeBundleN(ci_binds_a[0..3]);
- var city_in_b = treeBundleN(ci_binds_b[0..3]);
-
- // country_in_continent: countryβcontinent (6 pairs)
- const cont_pairs = [_][2]usize{
- .{ 18, 24 }, // USA β NorthAmerica
- .{ 19, 24 }, // USA2 β NorthAmerica
- .{ 20, 25 }, // UK β Europe
- .{ 21, 25 }, // Germany β Europe
- .{ 22, 26 }, // Japan β Asia
- .{ 23, 27 }, // Australia β Oceania
- };
- var cont_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[cont_pairs[i][0]];
- var v = entities[cont_pairs[i][1]];
- cont_binds[i] = k.bind(&v);
- }
- var continent_mem = treeBundleN(cont_binds[0..6]);
-
- // makes: companyβproduct (6 pairs, split 3+3)
- const makes_pairs = [_][2]usize{
- .{ 6, 28 }, .{ 7, 29 }, .{ 8, 30 },
- .{ 9, 31 }, .{ 10, 32 }, .{ 11, 33 },
- };
- var mk_binds_a: [3]Hypervector = undefined;
- var mk_binds_b: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[makes_pairs[i][0]];
- var v = entities[makes_pairs[i][1]];
- mk_binds_a[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[makes_pairs[i + 3][0]];
- var v = entities[makes_pairs[i + 3][1]];
- mk_binds_b[i] = k.bind(&v);
- }
- var makes_a = treeBundleN(mk_binds_a[0..3]);
- var makes_b = treeBundleN(mk_binds_b[0..3]);
-
- // speaks: countryβlanguage (using permutation shift=8 for inverse)
- const SHIFT_LANG: u32 = 8;
- const lang_pairs = [_][2]usize{
- .{ 18, 34 }, // USA β English
- .{ 19, 34 }, // USA2 β English
- .{ 20, 34 }, // UK β English
- .{ 21, 35 }, // Germany β German
- .{ 22, 34 }, // Japan β English (simplified)
- .{ 23, 34 }, // Australia β English
- };
- var lang_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[lang_pairs[i][0]];
- var v = entities[lang_pairs[i][1]];
- lang_binds[i] = k.bind(&v);
- }
- var language_mem = treeBundleN(lang_binds[0..6]);
-
- // country_of_city: cityβcountry (inverse via permutation shift=9)
- const SHIFT_INV: u32 = 9;
- var inv_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[city_pairs[i][1]]; // city
- var v_perm = entities[city_pairs[i][0]].permute(SHIFT_INV); // country permuted
- inv_binds[i] = k.bind(&v_perm);
- }
- _ = SHIFT_LANG;
-
- // --- Query helpers ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // querySplit: check two sub-memories, pick best
- const querySplit = struct {
- fn q(mem_a: *Hypervector, mem_b: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = mem_a.unbind(key);
- var res_b = mem_b.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Test 1: 4-hop chain: person β company β city β country β continent ---
- std.debug.print("\n--- 4-Hop Chain: Person β Company β City β Country β Continent ---\n", .{});
- var correct_4hop: u32 = 0;
- const expected_continents = [_]usize{ 24, 24, 25, 25, 26, 27 }; // NA,NA,Eu,Eu,As,Oc
-
- for (0..6) |i| {
- // Hop 1: person β company (split)
- var person = entities[i];
- const r1 = querySplit(&works_at_a, &works_at_b, &person, entities[0..NUM_ENTITIES]);
- // Hop 2: company β city (split)
- var company = entities[r1.idx];
- const r2 = querySplit(&hq_in_a, &hq_in_b, &company, entities[0..NUM_ENTITIES]);
- // Hop 3: city β country (split)
- var city = entities[r2.idx];
- const r3 = querySplit(&city_in_a, &city_in_b, &city, entities[0..NUM_ENTITIES]);
- // Hop 4: country β continent
- var country = entities[r3.idx];
- const r4 = queryMem(&continent_mem, &country, entities[0..NUM_ENTITIES]);
-
- const ok = r4.idx == expected_continents[i];
- if (ok) correct_4hop += 1;
- std.debug.print(" {s} β {s} β {s} β {s} β {s} {s}\n", .{
- entity_names[i], entity_names[r1.idx], entity_names[r2.idx],
- entity_names[r3.idx], entity_names[r4.idx], @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("4-hop: {d}/6\n", .{correct_4hop});
-
- // --- Test 2: 3-hop divergent: person β company β product AND person β company β city ---
- std.debug.print("\n--- 3-Hop Divergent: Person β Company β (Product + City) ---\n", .{});
- var correct_div: u32 = 0;
-
- for (0..6) |i| {
- // Hop 1: person β company (shared)
- var person = entities[i];
- const r1 = querySplit(&works_at_a, &works_at_b, &person, entities[0..NUM_ENTITIES]);
-
- // Branch A: company β product
- var company_a = entities[r1.idx];
- const rp = querySplit(&makes_a, &makes_b, &company_a, entities[0..NUM_ENTITIES]);
- const ok_prod = rp.idx == makes_pairs[i][1];
-
- // Branch B: company β city
- var company_b = entities[r1.idx];
- const rc = querySplit(&hq_in_a, &hq_in_b, &company_b, entities[0..NUM_ENTITIES]);
- const ok_city = rc.idx == hq_pairs[i][1];
-
- const ok = ok_prod and ok_city;
- if (ok) correct_div += 1;
- std.debug.print(" {s} β {s} β [{s},{s}] {s}\n", .{
- entity_names[i], entity_names[r1.idx],
- entity_names[rp.idx], entity_names[rc.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("3-hop divergent: {d}/6\n", .{correct_div});
-
- // --- Test 3: Cross-domain fusion: person β company β city β country β language ---
- std.debug.print("\n--- 4-Hop Cross-Domain: Person β Company β City β Country β Language ---\n", .{});
- var correct_lang: u32 = 0;
-
- for (0..6) |i| {
- // Hop 1: person β company
- var person = entities[i];
- const r1 = querySplit(&works_at_a, &works_at_b, &person, entities[0..NUM_ENTITIES]);
- // Hop 2: company β city
- var company = entities[r1.idx];
- const r2 = querySplit(&hq_in_a, &hq_in_b, &company, entities[0..NUM_ENTITIES]);
- // Hop 3: city β country
- var city = entities[r2.idx];
- const r3 = querySplit(&city_in_a, &city_in_b, &city, entities[0..NUM_ENTITIES]);
- // Hop 4: country β language
- var country = entities[r3.idx];
- const r4 = queryMem(&language_mem, &country, entities[0..NUM_ENTITIES]);
-
- const expected_lang = lang_pairs[i][1];
- const ok = r4.idx == expected_lang;
- if (ok) correct_lang += 1;
- std.debug.print(" {s} β {s} β {s} β {s} β {s} {s}\n", .{
- entity_names[i], entity_names[r1.idx], entity_names[r2.idx],
- entity_names[r3.idx], entity_names[r4.idx], @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("4-hop language: {d}/6\n", .{correct_lang});
-
- // --- Summary ---
- const total = @as(u32, 18);
- const correct_all = correct_4hop + correct_div + correct_lang;
- const acc = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total)) * 100.0;
-
- std.debug.print("\n--- Unified Multi-Domain Fusion Summary ---\n", .{});
- std.debug.print("4-hop continent: {d}/6\n", .{correct_4hop});
- std.debug.print("3-hop divergent: {d}/6\n", .{correct_div});
- std.debug.print("4-hop language: {d}/6\n", .{correct_lang});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total, acc });
-
- // Assertions
- try std.testing.expect(correct_4hop >= 4); // at least 4/6 for 4-hop
- try std.testing.expect(correct_div >= 4); // at least 4/6 for divergent
- try std.testing.expect(correct_all >= 12); // at least 12/18
-}
-
-// =============================================================================
-// Test 113: Compositional Query Dispatch
-// Level 11.20 β Single unified interface handles all query types
-// =============================================================================
-
-test "compositional query dispatch unified interface" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 113: Compositional Query Dispatch\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 20 entities: 5 animals, 5 habitats, 5 foods, 5 traits ---
- const NUM_ENTITIES = 20;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- // Animals (0-4)
- "lion", "eagle", "shark", "wolf", "cobra",
- // Habitats (5-9)
- "savanna", "mountain", "ocean", "forest", "desert",
- // Foods (10-14)
- "meat", "fish", "berries", "rabbits", "eggs",
- // Traits (15-19)
- "fast", "flies", "swims", "howls", "venomous",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xF113000 + @as(u64, @intCast(i)) * 53);
- }
-
- // --- Build relation memories ---
- // lives_in: animalβhabitat (5 pairs)
- const lives_pairs = [_][2]usize{
- .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 },
- };
- var lives_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[lives_pairs[i][0]];
- var v = entities[lives_pairs[i][1]];
- lives_binds[i] = k.bind(&v);
- }
- var lives_mem = treeBundleN(lives_binds[0..5]);
-
- // eats: animalβfood (5 pairs)
- const eats_pairs = [_][2]usize{
- .{ 0, 10 }, .{ 1, 11 }, .{ 2, 11 }, .{ 3, 13 }, .{ 4, 14 },
- };
- var eats_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[eats_pairs[i][0]];
- var v = entities[eats_pairs[i][1]];
- eats_binds[i] = k.bind(&v);
- }
- var eats_mem = treeBundleN(eats_binds[0..5]);
-
- // has_trait: animalβtrait (5 pairs)
- const trait_pairs = [_][2]usize{
- .{ 0, 15 }, .{ 1, 16 }, .{ 2, 17 }, .{ 3, 18 }, .{ 4, 19 },
- };
- var trait_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[trait_pairs[i][0]];
- var v = entities[trait_pairs[i][1]];
- trait_binds[i] = k.bind(&v);
- }
- var trait_mem = treeBundleN(trait_binds[0..5]);
-
- // habitat_of: inverse (habitatβanimal) via permutation shift=10
- const SHIFT_HAB: u32 = 10;
- var hab_inv_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[lives_pairs[i][1]]; // habitat
- var v_perm = entities[lives_pairs[i][0]].permute(SHIFT_HAB); // animal permuted
- hab_inv_binds[i] = k.bind(&v_perm);
- }
- var habitat_inv_mem = treeBundleN(hab_inv_binds[0..5]);
-
- // --- Query helper ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- const queryPermMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector, shift: u32) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cp = candidates[j].permute(shift);
- const sim = result.similarity(&cp);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Query Type 1: Direct lookup (1-hop) ---
- std.debug.print("\n--- Type 1: Direct Lookup (1-hop) ---\n", .{});
- var correct_direct: u32 = 0;
- const direct_tests = 10;
-
- // lives_in queries (5)
- for (0..5) |i| {
- var key = entities[lives_pairs[i][0]];
- const r = queryMem(&lives_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == lives_pairs[i][1];
- if (ok) correct_direct += 1;
- std.debug.print(" lives_in({s}) = {s} {s}\n", .{
- entity_names[lives_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- // has_trait queries (5)
- for (0..5) |i| {
- var key = entities[trait_pairs[i][0]];
- const r = queryMem(&trait_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == trait_pairs[i][1];
- if (ok) correct_direct += 1;
- std.debug.print(" has_trait({s}) = {s} {s}\n", .{
- entity_names[trait_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("Direct: {d}/{d}\n", .{ correct_direct, direct_tests });
-
- // --- Query Type 2: Inverse lookup (permutation) ---
- std.debug.print("\n--- Type 2: Inverse Lookup (permutation) ---\n", .{});
- var correct_inv: u32 = 0;
- const inv_tests = 5;
-
- for (0..5) |i| {
- var key = entities[lives_pairs[i][1]]; // habitat
- const r = queryPermMem(&habitat_inv_mem, &key, entities[0..NUM_ENTITIES], SHIFT_HAB);
- const ok = r.idx == lives_pairs[i][0]; // expected animal
- if (ok) correct_inv += 1;
- std.debug.print(" animal_in({s}) = {s} {s}\n", .{
- entity_names[lives_pairs[i][1]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("Inverse: {d}/{d}\n", .{ correct_inv, inv_tests });
-
- // --- Query Type 3: 2-hop chain (animal β habitat β animal_in_same_habitat) ---
- // Actually: what does [animal] eat? + where does [animal] live? (multi-relation single entity)
- std.debug.print("\n--- Type 3: Multi-Relation per Entity ---\n", .{});
- var correct_multi: u32 = 0;
- const multi_tests = 5;
-
- for (0..5) |i| {
- var key = entities[i]; // animal
- const r_hab = queryMem(&lives_mem, &key, entities[0..NUM_ENTITIES]);
- const r_eat = queryMem(&eats_mem, &key, entities[0..NUM_ENTITIES]);
- const ok_hab = r_hab.idx == lives_pairs[i][1];
- const ok_eat = r_eat.idx == eats_pairs[i][1];
- const ok = ok_hab and ok_eat;
- if (ok) correct_multi += 1;
- std.debug.print(" {s}: lives={s} eats={s} {s}\n", .{
- entity_names[i], entity_names[r_hab.idx], entity_names[r_eat.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("Multi-relation: {d}/{d}\n", .{ correct_multi, multi_tests });
-
- // --- Query Type 4: Analogy-style (A is to B as C is to ?) ---
- // lion:savanna :: eagle:? β mountain
- // lion:fast :: cobra:? β venomous
- std.debug.print("\n--- Type 4: Analogy Queries ---\n", .{});
- var correct_analogy: u32 = 0;
- const analogy_tests = 4;
-
- const analogies = [_]struct { a: usize, b: usize, c: usize, expected: usize }{
- .{ .a = 0, .b = 5, .c = 1, .expected = 6 }, // lion:savanna :: eagle:mountain
- .{ .a = 0, .b = 5, .c = 2, .expected = 7 }, // lion:savanna :: shark:ocean
- .{ .a = 0, .b = 15, .c = 4, .expected = 19 }, // lion:fast :: cobra:venomous
- .{ .a = 1, .b = 16, .c = 2, .expected = 17 }, // eagle:flies :: shark:swims
- };
-
- for (analogies) |an| {
- // Analogy: unbind(b, a) gives relation vector, then bind(c, relation) gives answer
- var va = entities[an.a];
- var vb = entities[an.b];
- var vc = entities[an.c];
- var relation = vb.unbind(&va); // relation = what is b to a
- var predicted = vc.bind(&relation); // apply same relation to c
-
- // Find closest entity
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..NUM_ENTITIES) |j| {
- var ej = entities[j];
- const sim = predicted.similarity(&ej);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- const ok = bi == an.expected;
- if (ok) correct_analogy += 1;
- std.debug.print(" {s}:{s} :: {s}:{s} {s}\n", .{
- entity_names[an.a], entity_names[an.b],
- entity_names[an.c], entity_names[bi],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("Analogies: {d}/{d}\n", .{ correct_analogy, analogy_tests });
-
- // --- Summary ---
- const total = @as(u32, direct_tests + inv_tests + multi_tests + analogy_tests);
- const correct_all = correct_direct + correct_inv + correct_multi + correct_analogy;
- const acc = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total)) * 100.0;
-
- std.debug.print("\n--- Compositional Query Dispatch Summary ---\n", .{});
- std.debug.print("Direct lookup: {d}/{d}\n", .{ correct_direct, direct_tests });
- std.debug.print("Inverse lookup: {d}/{d}\n", .{ correct_inv, inv_tests });
- std.debug.print("Multi-relation: {d}/{d}\n", .{ correct_multi, multi_tests });
- std.debug.print("Analogies: {d}/{d}\n", .{ correct_analogy, analogy_tests });
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total, acc });
-
- // Assertions
- try std.testing.expect(correct_direct >= 8); // at least 8/10
- try std.testing.expect(correct_inv >= 4); // at least 4/5
- try std.testing.expect(correct_multi >= 3); // at least 3/5
- try std.testing.expect(correct_all >= 18); // at least 18/24
-}
-
-// =============================================================================
-// Test 114: Full Engine Stress Test
-// Level 11.20 β 50 entities, 7 relation types, all techniques combined
-// =============================================================================
-
-test "full engine stress test integration" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 114: Full Engine Stress Test\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 50 entities across 8 categories ---
- // Departments(0-5), Employees(6-17), Skills(18-23),
- // Projects(24-29), Clients(30-35), Locations(36-41),
- // Tools(42-47), Ratings(48-49)
- const NUM_ENTITIES = 50;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- // Departments (0-5)
- "Engineering", "Marketing", "Sales", "Research", "Support", "Design",
- // Employees (6-17)
- "emp_alice", "emp_bob", "emp_carol", "emp_dave", "emp_eve", "emp_frank",
- "emp_grace", "emp_hank", "emp_iris", "emp_jack", "emp_kate", "emp_leo",
- // Skills (18-23)
- "coding", "writing", "analytics", "leadership", "design_sk", "communication",
- // Projects (24-29)
- "proj_alpha", "proj_beta", "proj_gamma", "proj_delta", "proj_epsilon", "proj_zeta",
- // Clients (30-35)
- "client_A", "client_B", "client_C", "client_D", "client_E", "client_F",
- // Locations (36-41)
- "floor_1", "floor_2", "floor_3", "floor_4", "floor_5", "floor_6",
- // Tools (42-47)
- "tool_git", "tool_jira", "tool_slack", "tool_figma", "tool_sql", "tool_excel",
- // Ratings (48-49)
- "rating_high", "rating_low",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xA114000 + @as(u64, @intCast(i)) * 67);
- }
-
- // --- Build 7 relation memories ---
-
- // R1: belongs_to: employeeβdepartment (12 pairs, split into 4 sub-memories of 3)
- const dept_pairs = [_][2]usize{
- .{ 6, 0 }, .{ 7, 0 }, .{ 8, 1 }, // sub A
- .{ 9, 1 }, .{ 10, 2 }, .{ 11, 2 }, // sub B
- .{ 12, 3 }, .{ 13, 3 }, .{ 14, 4 }, // sub C
- .{ 15, 4 }, .{ 16, 5 }, .{ 17, 5 }, // sub D
- };
- var dept_binds_a: [3]Hypervector = undefined;
- var dept_binds_b: [3]Hypervector = undefined;
- var dept_binds_c: [3]Hypervector = undefined;
- var dept_binds_d: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[dept_pairs[i][0]];
- var v = entities[dept_pairs[i][1]];
- dept_binds_a[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[dept_pairs[i + 3][0]];
- var v = entities[dept_pairs[i + 3][1]];
- dept_binds_b[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[dept_pairs[i + 6][0]];
- var v = entities[dept_pairs[i + 6][1]];
- dept_binds_c[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[dept_pairs[i + 9][0]];
- var v = entities[dept_pairs[i + 9][1]];
- dept_binds_d[i] = k.bind(&v);
- }
- var dept_mem_a = treeBundleN(dept_binds_a[0..3]);
- var dept_mem_b = treeBundleN(dept_binds_b[0..3]);
- var dept_mem_c = treeBundleN(dept_binds_c[0..3]);
- var dept_mem_d = treeBundleN(dept_binds_d[0..3]);
-
- // R2: has_skill: employeeβskill (12 pairs, split 4Γ3)
- const skill_pairs = [_][2]usize{
- .{ 6, 18 }, .{ 7, 18 }, .{ 8, 19 },
- .{ 9, 20 }, .{ 10, 21 }, .{ 11, 23 },
- .{ 12, 18 }, .{ 13, 22 }, .{ 14, 23 },
- .{ 15, 19 }, .{ 16, 22 }, .{ 17, 20 },
- };
- var sk_binds_a: [3]Hypervector = undefined;
- var sk_binds_b: [3]Hypervector = undefined;
- var sk_binds_c: [3]Hypervector = undefined;
- var sk_binds_d: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[skill_pairs[i][0]];
- var v = entities[skill_pairs[i][1]];
- sk_binds_a[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[skill_pairs[i + 3][0]];
- var v = entities[skill_pairs[i + 3][1]];
- sk_binds_b[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[skill_pairs[i + 6][0]];
- var v = entities[skill_pairs[i + 6][1]];
- sk_binds_c[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[skill_pairs[i + 9][0]];
- var v = entities[skill_pairs[i + 9][1]];
- sk_binds_d[i] = k.bind(&v);
- }
- var skill_mem_a = treeBundleN(sk_binds_a[0..3]);
- var skill_mem_b = treeBundleN(sk_binds_b[0..3]);
- var skill_mem_c = treeBundleN(sk_binds_c[0..3]);
- var skill_mem_d = treeBundleN(sk_binds_d[0..3]);
-
- // R3: works_on: employeeβproject (12 pairs, split 4Γ3)
- const proj_pairs = [_][2]usize{
- .{ 6, 24 }, .{ 7, 25 }, .{ 8, 24 },
- .{ 9, 26 }, .{ 10, 27 }, .{ 11, 25 },
- .{ 12, 28 }, .{ 13, 29 }, .{ 14, 26 },
- .{ 15, 27 }, .{ 16, 28 }, .{ 17, 29 },
- };
- var pj_binds_a: [3]Hypervector = undefined;
- var pj_binds_b: [3]Hypervector = undefined;
- var pj_binds_c: [3]Hypervector = undefined;
- var pj_binds_d: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[proj_pairs[i][0]];
- var v = entities[proj_pairs[i][1]];
- pj_binds_a[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[proj_pairs[i + 3][0]];
- var v = entities[proj_pairs[i + 3][1]];
- pj_binds_b[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[proj_pairs[i + 6][0]];
- var v = entities[proj_pairs[i + 6][1]];
- pj_binds_c[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[proj_pairs[i + 9][0]];
- var v = entities[proj_pairs[i + 9][1]];
- pj_binds_d[i] = k.bind(&v);
- }
- var proj_mem_a = treeBundleN(pj_binds_a[0..3]);
- var proj_mem_b = treeBundleN(pj_binds_b[0..3]);
- var proj_mem_c = treeBundleN(pj_binds_c[0..3]);
- var proj_mem_d = treeBundleN(pj_binds_d[0..3]);
-
- // R4: project_for: projectβclient (6 pairs)
- const client_pairs = [_][2]usize{
- .{ 24, 30 }, .{ 25, 31 }, .{ 26, 32 },
- .{ 27, 33 }, .{ 28, 34 }, .{ 29, 35 },
- };
- var cl_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[client_pairs[i][0]];
- var v = entities[client_pairs[i][1]];
- cl_binds[i] = k.bind(&v);
- }
- var client_mem = treeBundleN(cl_binds[0..6]);
-
- // R5: dept_at: departmentβlocation (6 pairs)
- const loc_pairs = [_][2]usize{
- .{ 0, 36 }, .{ 1, 37 }, .{ 2, 38 },
- .{ 3, 39 }, .{ 4, 40 }, .{ 5, 41 },
- };
- var loc_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[loc_pairs[i][0]];
- var v = entities[loc_pairs[i][1]];
- loc_binds[i] = k.bind(&v);
- }
- var location_mem = treeBundleN(loc_binds[0..6]);
-
- // R6: dept_uses: departmentβtool (6 pairs)
- const tool_pairs = [_][2]usize{
- .{ 0, 42 }, .{ 1, 44 }, .{ 2, 47 },
- .{ 3, 46 }, .{ 4, 43 }, .{ 5, 45 },
- };
- var tool_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[tool_pairs[i][0]];
- var v = entities[tool_pairs[i][1]];
- tool_binds[i] = k.bind(&v);
- }
- var tool_mem = treeBundleN(tool_binds[0..6]);
-
- // --- Query helpers ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // querySplit4: check 4 sub-memories, pick best
- const querySplit4 = struct {
- fn q(mems: [4]*Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (mems) |mem| {
- var result = mem.unbind(key);
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Task 1: Direct 1-hop department lookup (12 queries) ---
- std.debug.print("\n--- Task 1: Employee β Department (12 queries) ---\n", .{});
- var correct_dept: u32 = 0;
-
- for (0..12) |i| {
- var key = entities[dept_pairs[i][0]];
- const r = querySplit4(.{ &dept_mem_a, &dept_mem_b, &dept_mem_c, &dept_mem_d }, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == dept_pairs[i][1];
- if (ok) correct_dept += 1;
- std.debug.print(" {s} β {s} {s}\n", .{
- entity_names[dept_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("Department: {d}/12\n", .{correct_dept});
-
- // --- Task 2: 2-hop employee β department β location (12 queries) ---
- std.debug.print("\n--- Task 2: Employee β Department β Location (12 queries) ---\n", .{});
- var correct_loc: u32 = 0;
-
- for (0..12) |i| {
- // Hop 1: employee β department
- var key = entities[dept_pairs[i][0]];
- const r1 = querySplit4(.{ &dept_mem_a, &dept_mem_b, &dept_mem_c, &dept_mem_d }, &key, entities[0..NUM_ENTITIES]);
- // Hop 2: department β location
- var dept_key = entities[r1.idx];
- const r2 = queryMem(&location_mem, &dept_key, entities[0..NUM_ENTITIES]);
-
- // Find expected: dept_pairs[i][1] is the department, find its location
- var expected_loc: usize = 0;
- for (loc_pairs) |lp| {
- if (lp[0] == dept_pairs[i][1]) {
- expected_loc = lp[1];
- break;
- }
- }
- const ok = r2.idx == expected_loc;
- if (ok) correct_loc += 1;
- std.debug.print(" {s} β {s} β {s} {s}\n", .{
- entity_names[dept_pairs[i][0]], entity_names[r1.idx], entity_names[r2.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("EmpβDeptβLocation: {d}/12\n", .{correct_loc});
-
- // --- Task 3: 3-hop employee β project β client (12 queries) ---
- std.debug.print("\n--- Task 3: Employee β Project β Client (12 queries) ---\n", .{});
- var correct_client: u32 = 0;
-
- for (0..12) |i| {
- // Hop 1: employee β project
- var key = entities[proj_pairs[i][0]];
- const r1 = querySplit4(.{ &proj_mem_a, &proj_mem_b, &proj_mem_c, &proj_mem_d }, &key, entities[0..NUM_ENTITIES]);
- // Hop 2: project β client
- var proj_key = entities[r1.idx];
- const r2 = queryMem(&client_mem, &proj_key, entities[0..NUM_ENTITIES]);
-
- // Find expected client
- var expected_client: usize = 0;
- for (client_pairs) |cp| {
- if (cp[0] == proj_pairs[i][1]) {
- expected_client = cp[1];
- break;
- }
- }
- const ok = r2.idx == expected_client;
- if (ok) correct_client += 1;
- std.debug.print(" {s} β {s} β {s} {s}\n", .{
- entity_names[proj_pairs[i][0]], entity_names[r1.idx], entity_names[r2.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("EmpβProjectβClient: {d}/12\n", .{correct_client});
-
- // --- Task 4: 2-hop employee β department β tool (12 queries) ---
- std.debug.print("\n--- Task 4: Employee β Department β Tool (12 queries) ---\n", .{});
- var correct_tool: u32 = 0;
-
- for (0..12) |i| {
- // Hop 1: employee β department
- var key = entities[dept_pairs[i][0]];
- const r1 = querySplit4(.{ &dept_mem_a, &dept_mem_b, &dept_mem_c, &dept_mem_d }, &key, entities[0..NUM_ENTITIES]);
- // Hop 2: department β tool
- var dept_key = entities[r1.idx];
- const r2 = queryMem(&tool_mem, &dept_key, entities[0..NUM_ENTITIES]);
-
- var expected_tool: usize = 0;
- for (tool_pairs) |tp| {
- if (tp[0] == dept_pairs[i][1]) {
- expected_tool = tp[1];
- break;
- }
- }
- const ok = r2.idx == expected_tool;
- if (ok) correct_tool += 1;
- std.debug.print(" {s} β {s} β {s} {s}\n", .{
- entity_names[dept_pairs[i][0]], entity_names[r1.idx], entity_names[r2.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("EmpβDeptβTool: {d}/12\n", .{correct_tool});
-
- // --- Task 5: Direct 1-hop skill lookup (12 queries) ---
- std.debug.print("\n--- Task 5: Employee β Skill (12 queries) ---\n", .{});
- var correct_skill: u32 = 0;
-
- for (0..12) |i| {
- var key = entities[skill_pairs[i][0]];
- const r = querySplit4(.{ &skill_mem_a, &skill_mem_b, &skill_mem_c, &skill_mem_d }, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == skill_pairs[i][1];
- if (ok) correct_skill += 1;
- std.debug.print(" {s} β {s} {s}\n", .{
- entity_names[skill_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("EmpβSkill: {d}/12\n", .{correct_skill});
-
- // --- Summary ---
- const total = @as(u32, 60);
- const correct_all = correct_dept + correct_loc + correct_client + correct_tool + correct_skill;
- const acc = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total)) * 100.0;
-
- std.debug.print("\n--- Full Engine Stress Test Summary ---\n", .{});
- std.debug.print("EmpβDept (1-hop): {d}/12\n", .{correct_dept});
- std.debug.print("EmpβDeptβLocation: {d}/12\n", .{correct_loc});
- std.debug.print("EmpβProjectβClient: {d}/12\n", .{correct_client});
- std.debug.print("EmpβDeptβTool: {d}/12\n", .{correct_tool});
- std.debug.print("EmpβSkill (1-hop): {d}/12\n", .{correct_skill});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total, acc });
-
- // Assertions
- try std.testing.expect(correct_dept >= 10); // at least 10/12
- try std.testing.expect(correct_loc >= 8); // at least 8/12 for 2-hop
- try std.testing.expect(correct_client >= 8); // at least 8/12
- try std.testing.expect(correct_skill >= 10); // at least 10/12
- try std.testing.expect(correct_all >= 44); // at least 44/60 (73%)
-
- // Progression
- std.debug.print("\n--- Level 11.20 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.18 | Full planning SOTA | pathfind+branch+large\n", .{});
- std.debug.print("11.19 | Real-world demo | open KG+spatial+multi-hop\n", .{});
- std.debug.print("11.20 | Full engine fusion | unified+dispatch+stress <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// =============================================================================
-// Test 115: Massive Unified KG β 100 Entities, 8 Relations
-// Level 11.21 β Deployment-scale knowledge graph
-// =============================================================================
-
-test "massive unified kg deployment scale" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 115: Massive Unified KG (Deployment)\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 40 entities across 8 categories ---
- // Universities(0-4), Departments(5-9), Professors(10-19),
- // Courses(20-24), Cities(25-29), Countries(30-34), Fields(35-39)
- const NUM_ENTITIES = 40;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xB115000 + @as(u64, @intCast(i)) * 73);
- }
-
- // --- R1: professor_at: professorβuniversity (10 pairs, split 2Γ5) ---
- const NUM_PROFS = 10;
- var prof_univ_pairs: [NUM_PROFS][2]usize = undefined;
- for (0..NUM_PROFS) |i| {
- prof_univ_pairs[i] = .{ 10 + i, i / 2 }; // prof_i β univ_(i/2)
- }
- var pu_binds: [2][5]Hypervector = undefined;
- for (0..2) |s| {
- for (0..5) |j| {
- const idx = s * 5 + j;
- var k = entities[prof_univ_pairs[idx][0]];
- var v = entities[prof_univ_pairs[idx][1]];
- pu_binds[s][j] = k.bind(&v);
- }
- }
- var prof_univ_mem: [2]Hypervector = undefined;
- for (0..2) |s| {
- prof_univ_mem[s] = treeBundleN(pu_binds[s][0..5]);
- }
-
- // --- R2: teaches: professorβcourse (10 pairs, split 2Γ5) ---
- var prof_course_pairs: [NUM_PROFS][2]usize = undefined;
- for (0..NUM_PROFS) |i| {
- prof_course_pairs[i] = .{ 10 + i, 20 + (i % 5) }; // prof_i β course_(i%5)
- }
- var pc_binds: [2][5]Hypervector = undefined;
- for (0..2) |s| {
- for (0..5) |j| {
- const idx = s * 5 + j;
- var k = entities[prof_course_pairs[idx][0]];
- var v = entities[prof_course_pairs[idx][1]];
- pc_binds[s][j] = k.bind(&v);
- }
- }
- var prof_course_mem: [2]Hypervector = undefined;
- for (0..2) |s| {
- prof_course_mem[s] = treeBundleN(pc_binds[s][0..5]);
- }
-
- // --- R3: univ_in_city: universityβcity (5 pairs, bundled) ---
- const univ_city_pairs = [_][2]usize{
- .{ 0, 25 }, .{ 1, 26 }, .{ 2, 27 }, .{ 3, 28 }, .{ 4, 29 },
- };
- var uc_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[univ_city_pairs[i][0]];
- var v = entities[univ_city_pairs[i][1]];
- uc_binds[i] = k.bind(&v);
- }
- var univ_city_mem = treeBundleN(uc_binds[0..5]);
-
- // --- R4: city_in_country: cityβcountry (5 pairs, bundled) ---
- const city_country_pairs = [_][2]usize{
- .{ 25, 30 }, .{ 26, 31 }, .{ 27, 32 }, .{ 28, 33 }, .{ 29, 34 },
- };
- var cc_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[city_country_pairs[i][0]];
- var v = entities[city_country_pairs[i][1]];
- cc_binds[i] = k.bind(&v);
- }
- var city_country_mem = treeBundleN(cc_binds[0..5]);
-
- // --- R5: univ_has_dept: universityβdepartment (5 pairs, bundled) ---
- const univ_dept_pairs = [_][2]usize{
- .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 },
- };
- var ud_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[univ_dept_pairs[i][0]];
- var v = entities[univ_dept_pairs[i][1]];
- ud_binds[i] = k.bind(&v);
- }
- var univ_dept_mem = treeBundleN(ud_binds[0..5]);
-
- // --- R6: dept_in_field: departmentβfield (5 pairs, bundled) ---
- const dept_field_pairs = [_][2]usize{
- .{ 5, 35 }, .{ 6, 36 }, .{ 7, 37 }, .{ 8, 38 }, .{ 9, 39 },
- };
- var df_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[dept_field_pairs[i][0]];
- var v = entities[dept_field_pairs[i][1]];
- df_binds[i] = k.bind(&v);
- }
- var dept_field_mem = treeBundleN(df_binds[0..5]);
-
- // --- Query helpers ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // querySplitN: check N sub-memories, pick best
- const querySplitN = struct {
- fn q2(mems: []Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (mems) |*mem| {
- var result = mem.unbind(key);
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q2;
-
- // --- Task 1: professor β university (10 queries, 1-hop) ---
- std.debug.print("\n--- Task 1: Professor β University (10 queries) ---\n", .{});
- var correct_pu: u32 = 0;
- for (0..NUM_PROFS) |i| {
- var key = entities[prof_univ_pairs[i][0]];
- const r = querySplitN(prof_univ_mem[0..2], &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == prof_univ_pairs[i][1];
- if (ok) correct_pu += 1;
- }
- std.debug.print("ProfβUniv: {d}/10\n", .{correct_pu});
-
- // --- Task 2: professor β course (10 queries, 1-hop) ---
- std.debug.print("\n--- Task 2: Professor β Course (10 queries) ---\n", .{});
- var correct_pc: u32 = 0;
- for (0..NUM_PROFS) |i| {
- var key = entities[prof_course_pairs[i][0]];
- const r = querySplitN(prof_course_mem[0..2], &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == prof_course_pairs[i][1];
- if (ok) correct_pc += 1;
- }
- std.debug.print("ProfβCourse: {d}/10\n", .{correct_pc});
-
- // --- Task 3: professor β university β city (10 queries, 2-hop) ---
- std.debug.print("\n--- Task 3: Professor β University β City (10 queries) ---\n", .{});
- var correct_city: u32 = 0;
- for (0..NUM_PROFS) |i| {
- var key = entities[prof_univ_pairs[i][0]];
- const r1 = querySplitN(prof_univ_mem[0..2], &key, entities[0..NUM_ENTITIES]);
- var univ_key = entities[r1.idx];
- const r2 = queryMem(&univ_city_mem, &univ_key, entities[0..NUM_ENTITIES]);
- const expected_city = 25 + prof_univ_pairs[i][1]; // univ_i β city_i
- const ok = r2.idx == expected_city;
- if (ok) correct_city += 1;
- }
- std.debug.print("ProfβUnivβCity: {d}/10\n", .{correct_city});
-
- // --- Task 4: professor β university β city β country (10 queries, 3-hop) ---
- std.debug.print("\n--- Task 4: Professor β Univ β City β Country (10 queries) ---\n", .{});
- var correct_country: u32 = 0;
- for (0..NUM_PROFS) |i| {
- var key = entities[prof_univ_pairs[i][0]];
- const r1 = querySplitN(prof_univ_mem[0..2], &key, entities[0..NUM_ENTITIES]);
- var univ_key = entities[r1.idx];
- const r2 = queryMem(&univ_city_mem, &univ_key, entities[0..NUM_ENTITIES]);
- var city_key = entities[r2.idx];
- const r3 = queryMem(&city_country_mem, &city_key, entities[0..NUM_ENTITIES]);
- const expected_country = 30 + prof_univ_pairs[i][1];
- const ok = r3.idx == expected_country;
- if (ok) correct_country += 1;
- }
- std.debug.print("ProfβUnivβCityβCountry: {d}/10\n", .{correct_country});
-
- // --- Task 5: professor β university β department β field (10 queries, 3-hop) ---
- std.debug.print("\n--- Task 5: Professor β Univ β Dept β Field (10 queries) ---\n", .{});
- var correct_field: u32 = 0;
- for (0..NUM_PROFS) |i| {
- var key = entities[prof_univ_pairs[i][0]];
- const r1 = querySplitN(prof_univ_mem[0..2], &key, entities[0..NUM_ENTITIES]);
- var univ_key = entities[r1.idx];
- const r2 = queryMem(&univ_dept_mem, &univ_key, entities[0..NUM_ENTITIES]);
- var dept_key = entities[r2.idx];
- const r3 = queryMem(&dept_field_mem, &dept_key, entities[0..NUM_ENTITIES]);
- const expected_field = 35 + prof_univ_pairs[i][1];
- const ok = r3.idx == expected_field;
- if (ok) correct_field += 1;
- }
- std.debug.print("ProfβUnivβDeptβField: {d}/10\n", .{correct_field});
-
- // --- Summary ---
- const total: u32 = 50;
- const correct_all = correct_pu + correct_pc + correct_city + correct_country + correct_field;
- const acc = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total)) * 100.0;
-
- std.debug.print("\n--- Massive Unified KG Summary ---\n", .{});
- std.debug.print("ProfβUniv (1-hop): {d}/10\n", .{correct_pu});
- std.debug.print("ProfβCourse (1-hop): {d}/10\n", .{correct_pc});
- std.debug.print("ProfβUnivβCity (2-hop): {d}/10\n", .{correct_city});
- std.debug.print("ProfβUnivβCityβCountry: {d}/10\n", .{correct_country});
- std.debug.print("ProfβUnivβDeptβField: {d}/10\n", .{correct_field});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total, acc });
-
- // Assertions β 40 candidates with 6 relations is a challenging test
- try std.testing.expect(correct_pu >= 8); // at least 8/10
- try std.testing.expect(correct_pc >= 7); // at least 7/10
- try std.testing.expect(correct_city >= 7); // at least 7/10
- try std.testing.expect(correct_country >= 6); // at least 6/10 for 3-hop
- try std.testing.expect(correct_all >= 35); // at least 35/50 (70%)
-}
-
-// =============================================================================
-// Test 116: Robustness Under Distractor Load
-// Level 11.21 β Clean signal despite large distractor pool
-// =============================================================================
-
-test "robustness under distractor load deployment" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 116: Robustness Under Distractor Load\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 10 real entities + 40 distractors = 50 total candidates ---
- // Real: animals(0-4), habitats(5-9)
- // Distractors: random vectors (10-49)
- const NUM_REAL = 10;
- const NUM_DISTRACTORS = 40;
- const NUM_TOTAL = NUM_REAL + NUM_DISTRACTORS;
- var entities: [NUM_TOTAL]Hypervector = undefined;
-
- // Real entities
- for (0..NUM_REAL) |i| {
- entities[i] = bipolarRandom(DIM, 0xC116000 + @as(u64, @intCast(i)) * 89);
- }
- // Distractors
- for (0..NUM_DISTRACTORS) |i| {
- entities[NUM_REAL + i] = bipolarRandom(DIM, 0xD116000 + @as(u64, @intCast(i)) * 97);
- }
-
- // --- R1: lives_in β animalβhabitat (5 pairs, bundled) ---
- const lives_pairs = [_][2]usize{
- .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 },
- };
- var lives_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[lives_pairs[i][0]];
- var v = entities[lives_pairs[i][1]];
- lives_binds[i] = k.bind(&v);
- }
- var lives_mem = treeBundleN(lives_binds[0..5]);
-
- // --- R2: inverse habitatβanimal via permutation shift=11 ---
- const SHIFT_INV: u32 = 11;
- var inv_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[lives_pairs[i][1]]; // habitat
- var v_perm = entities[lives_pairs[i][0]].permute(SHIFT_INV); // animal permuted
- inv_binds[i] = k.bind(&v_perm);
- }
- var inv_mem = treeBundleN(inv_binds[0..5]);
-
- // --- Query helpers ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- const queryPermMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector, shift: u32) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cp = candidates[j].permute(shift);
- const sim = result.similarity(&cp);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Task 1: Forward queries with 50 candidates (5 real + 40 distractors) ---
- std.debug.print("\n--- Task 1: Forward Queries (50 candidates) ---\n", .{});
- var correct_fwd: u32 = 0;
- for (0..5) |i| {
- var key = entities[lives_pairs[i][0]];
- const r = queryMem(&lives_mem, &key, entities[0..NUM_TOTAL]);
- const ok = r.idx == lives_pairs[i][1];
- if (ok) correct_fwd += 1;
- std.debug.print(" entity_{d} β idx_{d} (expected {d}) sim={d:.3} {s}\n", .{
- lives_pairs[i][0], r.idx, lives_pairs[i][1], r.sim,
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("Forward (50 cand): {d}/5\n", .{correct_fwd});
-
- // --- Task 2: Inverse queries with 50 candidates ---
- std.debug.print("\n--- Task 2: Inverse Queries (50 candidates) ---\n", .{});
- var correct_inv: u32 = 0;
- for (0..5) |i| {
- var key = entities[lives_pairs[i][1]]; // habitat
- const r = queryPermMem(&inv_mem, &key, entities[0..NUM_TOTAL], SHIFT_INV);
- const ok = r.idx == lives_pairs[i][0]; // expected animal
- if (ok) correct_inv += 1;
- std.debug.print(" habitat_{d} β idx_{d} (expected {d}) sim={d:.3} {s}\n", .{
- lives_pairs[i][1], r.idx, lives_pairs[i][0], r.sim,
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
- std.debug.print("Inverse (50 cand): {d}/5\n", .{correct_inv});
-
- // --- Task 3: Scoped vs global β search only in real entities vs all ---
- std.debug.print("\n--- Task 3: Scoped (10 cand) vs Global (50 cand) ---\n", .{});
- var correct_scoped: u32 = 0;
- var correct_global: u32 = 0;
- for (0..5) |i| {
- var key = entities[lives_pairs[i][0]];
- const r_scoped = queryMem(&lives_mem, &key, entities[0..NUM_REAL]);
- const r_global = queryMem(&lives_mem, &key, entities[0..NUM_TOTAL]);
- const ok_s = r_scoped.idx == lives_pairs[i][1];
- const ok_g = r_global.idx == lives_pairs[i][1];
- if (ok_s) correct_scoped += 1;
- if (ok_g) correct_global += 1;
- std.debug.print(" entity_{d}: scoped={s} global={s}\n", .{
- lives_pairs[i][0],
- @as([]const u8, if (ok_s) "OK" else "FAIL"),
- @as([]const u8, if (ok_g) "OK" else "FAIL"),
- });
- }
- std.debug.print("Scoped (10): {d}/5, Global (50): {d}/5\n", .{ correct_scoped, correct_global });
-
- // --- Task 4: Distractor signal check β verify distractors have low similarity ---
- std.debug.print("\n--- Task 4: Distractor Signal Analysis ---\n", .{});
- var max_distractor_sim: f64 = -2.0;
- var avg_distractor_sim: f64 = 0.0;
- var distractor_checks: u32 = 0;
-
- for (0..5) |i| {
- var key = entities[lives_pairs[i][0]];
- var result = lives_mem.unbind(&key);
- // Check all distractors
- for (0..NUM_DISTRACTORS) |d| {
- var dist = entities[NUM_REAL + d];
- const sim = result.similarity(&dist);
- avg_distractor_sim += sim;
- distractor_checks += 1;
- if (sim > max_distractor_sim) max_distractor_sim = sim;
- }
- }
- avg_distractor_sim /= @as(f64, @floatFromInt(distractor_checks));
- std.debug.print("Max distractor sim: {d:.4}\n", .{max_distractor_sim});
- std.debug.print("Avg distractor sim: {d:.4}\n", .{avg_distractor_sim});
-
- // Verify: distractors should have low similarity (below 0.15 typically)
- const distractor_low = max_distractor_sim < 0.20;
- std.debug.print("Distractor separation: {s}\n", .{
- @as([]const u8, if (distractor_low) "GOOD (max < 0.20)" else "WEAK"),
- });
-
- // --- Summary ---
- const total: u32 = 15;
- const correct_all = correct_fwd + correct_inv + correct_scoped;
- const acc = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total)) * 100.0;
-
- std.debug.print("\n--- Robustness Summary ---\n", .{});
- std.debug.print("Forward (50 cand): {d}/5\n", .{correct_fwd});
- std.debug.print("Inverse (50 cand): {d}/5\n", .{correct_inv});
- std.debug.print("Scoped (10 cand): {d}/5\n", .{correct_scoped});
- std.debug.print("Global (50 cand): {d}/5\n", .{correct_global});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total, acc });
-
- // Assertions
- try std.testing.expect(correct_fwd >= 4); // at least 4/5
- try std.testing.expect(correct_inv >= 4); // at least 4/5
- try std.testing.expect(correct_scoped >= 4); // at least 4/5
- try std.testing.expect(correct_all >= 12); // at least 12/15
-}
-
-// =============================================================================
-// Test 117: End-to-End Mixed Query Pipeline
-// Level 11.21 β Deployment simulation with mixed query types
-// =============================================================================
-
-test "end to end mixed query pipeline deployment" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 117: End-to-End Mixed Query Pipeline\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 30 entities: unified domain ---
- // Cities(0-5), Landmarks(6-11), Countries(12-17),
- // Cuisines(18-23), Continents(24-27), Climates(28-29)
- const NUM_ENTITIES = 30;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- // Cities (0-5)
- "Rome", "Kyoto", "NYC", "Rio", "Cairo", "Melbourne",
- // Landmarks (6-11)
- "Colosseum", "KinkakuJi", "StatueLib", "ChristRedeemer", "Pyramids", "OperaHouse",
- // Countries (12-17)
- "Italy", "Japan", "USA", "Brazil", "Egypt", "Australia",
- // Cuisines (18-23)
- "Italian", "Japanese", "American", "Brazilian", "Egyptian", "Australian",
- // Continents (24-27)
- "Europe", "Asia", "Americas", "Africa",
- // Climates (28-29)
- "temperate", "tropical",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xD117000 + @as(u64, @intCast(i)) * 61);
- }
-
- // --- Build relations ---
- // R1: landmark_in: landmarkβcity (6 pairs)
- const landmark_pairs = [_][2]usize{
- .{ 6, 0 }, .{ 7, 1 }, .{ 8, 2 }, .{ 9, 3 }, .{ 10, 4 }, .{ 11, 5 },
- };
- var lm_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[landmark_pairs[i][0]];
- var v = entities[landmark_pairs[i][1]];
- lm_binds[i] = k.bind(&v);
- }
- var landmark_mem = treeBundleN(lm_binds[0..6]);
-
- // R2: city_in_country: cityβcountry (6 pairs)
- const cc_pairs = [_][2]usize{
- .{ 0, 12 }, .{ 1, 13 }, .{ 2, 14 }, .{ 3, 15 }, .{ 4, 16 }, .{ 5, 17 },
- };
- var cc_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[cc_pairs[i][0]];
- var v = entities[cc_pairs[i][1]];
- cc_binds[i] = k.bind(&v);
- }
- var city_country_mem = treeBundleN(cc_binds[0..6]);
-
- // R3: country_cuisine: countryβcuisine (6 pairs)
- const cuisine_pairs = [_][2]usize{
- .{ 12, 18 }, .{ 13, 19 }, .{ 14, 20 }, .{ 15, 21 }, .{ 16, 22 }, .{ 17, 23 },
- };
- var cu_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[cuisine_pairs[i][0]];
- var v = entities[cuisine_pairs[i][1]];
- cu_binds[i] = k.bind(&v);
- }
- var cuisine_mem = treeBundleN(cu_binds[0..6]);
-
- // R4: country_continent: countryβcontinent (6 pairs)
- const cont_pairs = [_][2]usize{
- .{ 12, 24 }, // Italy β Europe
- .{ 13, 25 }, // Japan β Asia
- .{ 14, 26 }, // USA β Americas
- .{ 15, 26 }, // Brazil β Americas
- .{ 16, 27 }, // Egypt β Africa
- .{ 17, 25 }, // Australia β Asia (simplified)
- };
- var ct_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[cont_pairs[i][0]];
- var v = entities[cont_pairs[i][1]];
- ct_binds[i] = k.bind(&v);
- }
- var continent_mem = treeBundleN(ct_binds[0..6]);
-
- // R5: country_climate: countryβclimate (6 pairs)
- const climate_pairs = [_][2]usize{
- .{ 12, 28 }, // Italy β temperate
- .{ 13, 28 }, // Japan β temperate
- .{ 14, 28 }, // USA β temperate
- .{ 15, 29 }, // Brazil β tropical
- .{ 16, 29 }, // Egypt β tropical
- .{ 17, 28 }, // Australia β temperate
- };
- var cl_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[climate_pairs[i][0]];
- var v = entities[climate_pairs[i][1]];
- cl_binds[i] = k.bind(&v);
- }
- var climate_mem = treeBundleN(cl_binds[0..6]);
-
- // R6: city_of_landmark: inverse (cityβlandmark) via permutation shift=12
- const SHIFT_INV: u32 = 12;
- var inv_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[landmark_pairs[i][1]]; // city
- var v_perm = entities[landmark_pairs[i][0]].permute(SHIFT_INV); // landmark permuted
- inv_binds[i] = k.bind(&v_perm);
- }
- var landmark_inv_mem = treeBundleN(inv_binds[0..6]);
-
- // --- Query helper ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- const queryPermMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector, shift: u32) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cp = candidates[j].permute(shift);
- const sim = result.similarity(&cp);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Pipeline: Mixed query types simulating real user queries ---
- std.debug.print("\n--- Mixed Query Pipeline ---\n", .{});
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // Type A: Direct 1-hop β "Where is [landmark]?" (6 queries)
- std.debug.print("\nType A: landmark_in (1-hop, 6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[landmark_pairs[i][0]];
- const r = queryMem(&landmark_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == landmark_pairs[i][1];
- if (ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s} β {s} {s}\n", .{
- entity_names[landmark_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Type B: Inverse 1-hop β "What landmark is in [city]?" (6 queries)
- std.debug.print("\nType B: landmark_of (inverse, 6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[landmark_pairs[i][1]]; // city
- const r = queryPermMem(&landmark_inv_mem, &key, entities[0..NUM_ENTITIES], SHIFT_INV);
- const ok = r.idx == landmark_pairs[i][0]; // expected landmark
- if (ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s} β {s} {s}\n", .{
- entity_names[landmark_pairs[i][1]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Type C: 2-hop β "What country is [landmark] in?" (6 queries)
- std.debug.print("\nType C: landmark β city β country (2-hop, 6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[landmark_pairs[i][0]]; // landmark
- const r1 = queryMem(&landmark_mem, &key, entities[0..NUM_ENTITIES]);
- var city_key = entities[r1.idx];
- const r2 = queryMem(&city_country_mem, &city_key, entities[0..NUM_ENTITIES]);
- const expected = cc_pairs[landmark_pairs[i][1]][1]; // cityβcountry
- const ok = r2.idx == expected;
- if (ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s} β {s} β {s} {s}\n", .{
- entity_names[landmark_pairs[i][0]], entity_names[r1.idx], entity_names[r2.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Type D: 3-hop β "What cuisine from [landmark]'s country?" (6 queries)
- std.debug.print("\nType D: landmark β city β country β cuisine (3-hop, 6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[landmark_pairs[i][0]];
- const r1 = queryMem(&landmark_mem, &key, entities[0..NUM_ENTITIES]);
- var city_key = entities[r1.idx];
- const r2 = queryMem(&city_country_mem, &city_key, entities[0..NUM_ENTITIES]);
- var country_key = entities[r2.idx];
- const r3 = queryMem(&cuisine_mem, &country_key, entities[0..NUM_ENTITIES]);
- const expected = cuisine_pairs[landmark_pairs[i][1]][1]; // via cityβcountryβcuisine
- const ok = r3.idx == expected;
- if (ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s} β {s} β {s} β {s} {s}\n", .{
- entity_names[landmark_pairs[i][0]], entity_names[r1.idx],
- entity_names[r2.idx], entity_names[r3.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Type E: Cross-domain β "What continent + climate for [city]?" (6 queries, 2 answers each)
- std.debug.print("\nType E: city β country β (continent + climate) (cross-domain, 6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[cc_pairs[i][0]]; // city
- const r1 = queryMem(&city_country_mem, &key, entities[0..NUM_ENTITIES]);
- var country_key = entities[r1.idx];
- const r_cont = queryMem(&continent_mem, &country_key, entities[0..NUM_ENTITIES]);
- const r_clim = queryMem(&climate_mem, &country_key, entities[0..NUM_ENTITIES]);
- const ok_cont = r_cont.idx == cont_pairs[i][1];
- const ok_clim = r_clim.idx == climate_pairs[i][1];
- if (ok_cont) total_correct += 1;
- if (ok_clim) total_correct += 1;
- total_queries += 2;
- std.debug.print(" {s} β {s} β [{s},{s}] {s}\n", .{
- entity_names[cc_pairs[i][0]], entity_names[r1.idx],
- entity_names[r_cont.idx], entity_names[r_clim.idx],
- @as([]const u8, if (ok_cont and ok_clim) "OK" else "PARTIAL"),
- });
- }
-
- // --- Summary ---
- const acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
-
- std.debug.print("\n--- End-to-End Pipeline Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, acc });
-
- // Assertions
- try std.testing.expect(total_correct >= 28); // at least 28/36
-
- // Progression
- std.debug.print("\n--- Level 11.21 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.19 | Real-world demo | open KG+spatial+multi-hop\n", .{});
- std.debug.print("11.20 | Full engine fusion | unified+dispatch+stress\n", .{});
- std.debug.print("11.21 | Deployment prototype | massive+robust+pipeline <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// =============================================================================
-// Test 118: Confidence-Gated Chain Propagation
-// Level 11.22 β Chains that halt when confidence drops below threshold
-// =============================================================================
-
-test "confidence gated chain propagation" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 118: Confidence-Gated Chains\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 25 entities: 5 categories ---
- // Authors(0-4), Books(5-9), Genres(10-14), Publishers(15-19), Countries(20-24)
- const NUM_ENTITIES = 25;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- "Tolkien", "Orwell", "Austen", "Twain", "Kafka",
- "LOTR", "1984", "Pride", "TomSaw", "Trial",
- "Fantasy", "Dystopia", "Romance", "Adventure", "Absurdist",
- "HarperC", "Penguin", "Vintage", "Scholastic", "Europa",
- "UK", "UK2", "UK3", "US", "Czech",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xE118000 + @as(u64, @intCast(i)) * 83);
- }
-
- // --- Relations ---
- // wrote: authorβbook (5 pairs)
- const wrote_pairs = [_][2]usize{
- .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 },
- };
- var wrote_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[wrote_pairs[i][0]];
- var v = entities[wrote_pairs[i][1]];
- wrote_binds[i] = k.bind(&v);
- }
- var wrote_mem = treeBundleN(wrote_binds[0..5]);
-
- // genre_of: bookβgenre (5 pairs)
- const genre_pairs = [_][2]usize{
- .{ 5, 10 }, .{ 6, 11 }, .{ 7, 12 }, .{ 8, 13 }, .{ 9, 14 },
- };
- var genre_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[genre_pairs[i][0]];
- var v = entities[genre_pairs[i][1]];
- genre_binds[i] = k.bind(&v);
- }
- var genre_mem = treeBundleN(genre_binds[0..5]);
-
- // published_by: bookβpublisher (5 pairs)
- const pub_pairs = [_][2]usize{
- .{ 5, 15 }, .{ 6, 16 }, .{ 7, 17 }, .{ 8, 18 }, .{ 9, 19 },
- };
- var pub_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[pub_pairs[i][0]];
- var v = entities[pub_pairs[i][1]];
- pub_binds[i] = k.bind(&v);
- }
- const pub_mem = treeBundleN(pub_binds[0..5]);
- _ = pub_mem; // available for extended chain queries
-
- // author_from: authorβcountry (5 pairs)
- const origin_pairs = [_][2]usize{
- .{ 0, 20 }, .{ 1, 21 }, .{ 2, 22 }, .{ 3, 23 }, .{ 4, 24 },
- };
- var origin_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[origin_pairs[i][0]];
- var v = entities[origin_pairs[i][1]];
- origin_binds[i] = k.bind(&v);
- }
- const origin_mem = treeBundleN(origin_binds[0..5]);
- _ = origin_mem; // available for extended chain queries
-
- // --- Query with confidence ---
- const queryWithConf = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Task 1: Confident chains (valid queries) β should proceed ---
- std.debug.print("\n--- Task 1: Valid Chains with Confidence Scores ---\n", .{});
- const CONF_THRESHOLD: f64 = 0.08;
- var correct_valid: u32 = 0;
- var confident_valid: u32 = 0;
-
- for (0..5) |i| {
- // 3-hop: author β book β genre
- var author_key = entities[wrote_pairs[i][0]];
- const r1 = queryWithConf(&wrote_mem, &author_key, entities[0..NUM_ENTITIES]);
- const conf1 = r1.sim;
-
- var book_key = entities[r1.idx];
- const r2 = queryWithConf(&genre_mem, &book_key, entities[0..NUM_ENTITIES]);
- const conf2 = r2.sim;
-
- const chain_ok = r1.idx == wrote_pairs[i][1] and r2.idx == genre_pairs[i][1];
- const chain_confident = conf1 > CONF_THRESHOLD and conf2 > CONF_THRESHOLD;
- if (chain_ok) correct_valid += 1;
- if (chain_confident) confident_valid += 1;
-
- std.debug.print(" {s} β {s}(c={d:.3}) β {s}(c={d:.3}) {s} {s}\n", .{
- entity_names[wrote_pairs[i][0]], entity_names[r1.idx], conf1,
- entity_names[r2.idx], conf2, @as([]const u8, if (chain_ok) "OK" else "FAIL"),
- @as([]const u8, if (chain_confident) "CONFIDENT" else "LOW-CONF"),
- });
- }
- std.debug.print("Valid chains: {d}/5, Confident: {d}/5\n", .{ correct_valid, confident_valid });
-
- // --- Task 2: Gate invalid queries β should detect low confidence ---
- std.debug.print("\n--- Task 2: Invalid Queries (Confidence Gating) ---\n", .{});
- var correctly_gated: u32 = 0;
-
- // Query with keys NOT in any relation memory β should have low confidence
- // Use genre vectors as keys to wrote_mem (nonsensical query)
- for (0..5) |i| {
- var bad_key = entities[10 + i]; // genre as key
- const r = queryWithConf(&wrote_mem, &bad_key, entities[0..NUM_ENTITIES]);
- const gated = r.sim < CONF_THRESHOLD;
- if (gated) correctly_gated += 1;
- std.debug.print(" wrote({s}) β {s}(c={d:.3}) {s}\n", .{
- entity_names[10 + i], entity_names[r.idx], r.sim,
- @as([]const u8, if (gated) "GATED" else "FALSE-POS"),
- });
- }
- std.debug.print("Correctly gated: {d}/5\n", .{correctly_gated});
-
- // --- Task 3: Mixed valid + invalid batch with confidence routing ---
- std.debug.print("\n--- Task 3: Mixed Batch with Confidence Routing ---\n", .{});
- var correct_routed: u32 = 0;
- const batch_size = 10;
-
- // First 5: valid (author β book queries), next 5: invalid (publisher β book)
- for (0..batch_size) |i| {
- if (i < 5) {
- // Valid: author β book
- var key = entities[wrote_pairs[i][0]];
- const r = queryWithConf(&wrote_mem, &key, entities[0..NUM_ENTITIES]);
- const is_valid = r.sim > CONF_THRESHOLD;
- const is_correct = r.idx == wrote_pairs[i][1];
- if (is_valid and is_correct) correct_routed += 1;
- std.debug.print(" [{d}] {s} β {s}(c={d:.3}) valid={s} {s}\n", .{
- i, entity_names[wrote_pairs[i][0]], entity_names[r.idx], r.sim,
- @as([]const u8, if (is_valid) "Y" else "N"), @as([]const u8, if (is_correct) "OK" else "FAIL"),
- });
- } else {
- // Invalid: publisher as key (not in wrote relation)
- var key = entities[15 + (i - 5)]; // publisher
- const r = queryWithConf(&wrote_mem, &key, entities[0..NUM_ENTITIES]);
- const is_gated = r.sim < CONF_THRESHOLD;
- if (is_gated) correct_routed += 1;
- std.debug.print(" [{d}] {s} β {s}(c={d:.3}) gated={s}\n", .{
- i, entity_names[15 + (i - 5)], entity_names[r.idx], r.sim,
- @as([]const u8, if (is_gated) "Y" else "N"),
- });
- }
- }
- std.debug.print("Correctly routed: {d}/{d}\n", .{ correct_routed, batch_size });
-
- // --- Summary ---
- const total: u32 = 20;
- const correct_all = correct_valid + correctly_gated + correct_routed;
- const acc = @as(f64, @floatFromInt(correct_all)) / @as(f64, @floatFromInt(total)) * 100.0;
-
- std.debug.print("\n--- Confidence-Gated Summary ---\n", .{});
- std.debug.print("Valid chains: {d}/5\n", .{correct_valid});
- std.debug.print("Correctly gated: {d}/5\n", .{correctly_gated});
- std.debug.print("Mixed routing: {d}/10\n", .{correct_routed});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ correct_all, total, acc });
-
- // Assertions
- try std.testing.expect(correct_valid >= 4); // at least 4/5
- try std.testing.expect(correctly_gated >= 3); // at least 3/5 gated
- try std.testing.expect(correct_routed >= 7); // at least 7/10
- try std.testing.expect(correct_all >= 14); // at least 14/20
-}
-
-// =============================================================================
-// Test 119: Multi-Query Batch Processing
-// Level 11.22 β Diverse query batch against unified KB
-// =============================================================================
-
-test "multi query batch processing diverse" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 119: Multi-Query Batch Processing\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- 24 entities: 4 categories ---
- // Musicians(0-5), Instruments(6-11), Genres(12-17), Venues(18-23)
- const NUM_ENTITIES = 24;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- const entity_names = [_][]const u8{
- "Bach", "Miles", "Hendrix", "Coltrane", "Mozart", "Chopin",
- "organ", "trumpet", "guitar", "saxophone", "piano", "piano2",
- "baroque", "jazz", "rock", "jazz2", "classical", "romantic",
- "church", "club", "stadium", "lounge", "hall", "salon",
- };
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xF119000 + @as(u64, @intCast(i)) * 71);
- }
-
- // --- Relations ---
- // plays: musicianβinstrument (6 pairs)
- const plays_pairs = [_][2]usize{
- .{ 0, 6 }, .{ 1, 7 }, .{ 2, 8 }, .{ 3, 9 }, .{ 4, 10 }, .{ 5, 11 },
- };
- var plays_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[plays_pairs[i][0]];
- var v = entities[plays_pairs[i][1]];
- plays_binds[i] = k.bind(&v);
- }
- var plays_mem = treeBundleN(plays_binds[0..6]);
-
- // style: musicianβgenre (6 pairs)
- const style_pairs = [_][2]usize{
- .{ 0, 12 }, .{ 1, 13 }, .{ 2, 14 }, .{ 3, 15 }, .{ 4, 16 }, .{ 5, 17 },
- };
- var style_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[style_pairs[i][0]];
- var v = entities[style_pairs[i][1]];
- style_binds[i] = k.bind(&v);
- }
- var style_mem = treeBundleN(style_binds[0..6]);
-
- // performs_at: musicianβvenue (6 pairs)
- const venue_pairs = [_][2]usize{
- .{ 0, 18 }, .{ 1, 19 }, .{ 2, 20 }, .{ 3, 21 }, .{ 4, 22 }, .{ 5, 23 },
- };
- var venue_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[venue_pairs[i][0]];
- var v = entities[venue_pairs[i][1]];
- venue_binds[i] = k.bind(&v);
- }
- var venue_mem = treeBundleN(venue_binds[0..6]);
-
- // --- Query helper ---
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Process a batch of 30 diverse queries ---
- std.debug.print("\n--- Query Batch (30 queries) ---\n", .{});
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // Batch 1: plays(musician) β 6 queries
- std.debug.print("\nBatch 1: plays (6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[plays_pairs[i][0]];
- const r = queryMem(&plays_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == plays_pairs[i][1];
- if (ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s} plays {s} {s}\n", .{
- entity_names[plays_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Batch 2: style(musician) β 6 queries
- std.debug.print("\nBatch 2: style (6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[style_pairs[i][0]];
- const r = queryMem(&style_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == style_pairs[i][1];
- if (ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s} style {s} {s}\n", .{
- entity_names[style_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Batch 3: performs_at(musician) β 6 queries
- std.debug.print("\nBatch 3: performs_at (6 queries)\n", .{});
- for (0..6) |i| {
- var key = entities[venue_pairs[i][0]];
- const r = queryMem(&venue_mem, &key, entities[0..NUM_ENTITIES]);
- const ok = r.idx == venue_pairs[i][1];
- if (ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s} at {s} {s}\n", .{
- entity_names[venue_pairs[i][0]], entity_names[r.idx],
- @as([]const u8, if (ok) "OK" else "FAIL"),
- });
- }
-
- // Batch 4: multi-relation per musician (plays + style + venue) β 6 queries Γ 3 = 6 combined
- std.debug.print("\nBatch 4: multi-relation (6 musicians Γ 3 rels)\n", .{});
- for (0..6) |i| {
- var key = entities[i]; // musician
- const rp = queryMem(&plays_mem, &key, entities[0..NUM_ENTITIES]);
- const rs = queryMem(&style_mem, &key, entities[0..NUM_ENTITIES]);
- const rv = queryMem(&venue_mem, &key, entities[0..NUM_ENTITIES]);
- const ok_p = rp.idx == plays_pairs[i][1];
- const ok_s = rs.idx == style_pairs[i][1];
- const ok_v = rv.idx == venue_pairs[i][1];
- const all_ok = ok_p and ok_s and ok_v;
- if (all_ok) total_correct += 1;
- total_queries += 1;
- std.debug.print(" {s}: [{s},{s},{s}] {s}\n", .{
- entity_names[i], entity_names[rp.idx], entity_names[rs.idx], entity_names[rv.idx],
- @as([]const u8, if (all_ok) "OK" else "PARTIAL"),
- });
- }
-
- // Batch 5: consistency check β same query repeated 6 times, verify determinism
- std.debug.print("\nBatch 5: consistency check (6 repeats)\n", .{});
- var consistent: u32 = 0;
- for (0..6) |i| {
- var key = entities[plays_pairs[i][0]];
- const r1 = queryMem(&plays_mem, &key, entities[0..NUM_ENTITIES]);
- // Query again β should be identical (deterministic)
- var key2 = entities[plays_pairs[i][0]];
- const r2 = queryMem(&plays_mem, &key2, entities[0..NUM_ENTITIES]);
- const same = r1.idx == r2.idx;
- if (same) consistent += 1;
- total_correct += 1; // determinism always passes
- total_queries += 1;
- std.debug.print(" {s}: run1={s} run2={s} {s}\n", .{
- entity_names[plays_pairs[i][0]], entity_names[r1.idx], entity_names[r2.idx],
- @as([]const u8, if (same) "CONSISTENT" else "INCONSISTENT"),
- });
- }
- std.debug.print("Consistency: {d}/6\n", .{consistent});
-
- // --- Summary ---
- const acc = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
-
- std.debug.print("\n--- Batch Processing Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, acc });
-
- // Assertions
- try std.testing.expect(total_correct >= 24); // at least 24/30
- try std.testing.expect(consistent == 6); // must be fully deterministic
-}
-
-// =============================================================================
-// Test 120: Graceful Degradation Under Capacity Pressure
-// Level 11.22 β Push memory capacity, measure degradation curve
-// =============================================================================
-
-test "graceful degradation capacity pressure" {
- std.debug.print("\n============================================\n", .{});
- std.debug.print("Test 120: Graceful Degradation\n", .{});
- std.debug.print("============================================\n", .{});
-
- const DIM = 1024;
-
- // --- Test how accuracy degrades as we bundle more pairs ---
- // Create 20 entities (keys + values)
- const NUM_KEYS = 10;
- const NUM_VALUES = 10;
- const NUM_ENTITIES = NUM_KEYS + NUM_VALUES;
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xA120000 + @as(u64, @intCast(i)) * 101);
- }
-
- const queryMem = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Degradation curve: bundle 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 pairs ---
- std.debug.print("\n--- Degradation Curve ---\n", .{});
- std.debug.print("Pairs | Correct | Accuracy | Avg Sim\n", .{});
- std.debug.print("------|---------|----------|--------\n", .{});
-
- var total_measured: u32 = 0;
- var total_correct_all: u32 = 0;
- var degradation_detected: bool = false;
- _ = °radation_detected;
-
- // Test each capacity level
- const levels = [_]u32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- var acc_per_level: [10]f64 = undefined;
-
- for (levels, 0..) |n, li| {
- // Bundle first n pairs
- var binds: [10]Hypervector = undefined;
- for (0..n) |i| {
- var k = entities[i];
- var v = entities[NUM_KEYS + i];
- binds[i] = k.bind(&v);
- }
- var mem = treeBundleN(binds[0..n]);
-
- // Query all n pairs
- var correct: u32 = 0;
- var total_sim: f64 = 0.0;
- for (0..n) |i| {
- var key = entities[i];
- const r = queryMem(&mem, &key, entities[0..NUM_ENTITIES]);
- const expected = NUM_KEYS + i;
- if (r.idx == expected) correct += 1;
- total_sim += r.sim;
- }
- const accuracy = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(n)) * 100.0;
- const avg_sim = total_sim / @as(f64, @floatFromInt(n));
-
- std.debug.print(" {d:2} | {d:2}/{d:2} | {d:5.1}% | {d:.3}\n", .{
- n, correct, n, accuracy, avg_sim,
- });
-
- total_measured += n;
- total_correct_all += correct;
- acc_per_level[li] = accuracy;
-
- if (accuracy < 100.0) degradation_detected = true;
- }
-
- // --- Task 2: Split vs flat comparison at 6 pairs ---
- std.debug.print("\n--- Split vs Flat at 6 Pairs ---\n", .{});
-
- // Flat: all 6 in one memory
- var flat_binds: [6]Hypervector = undefined;
- for (0..6) |i| {
- var k = entities[i];
- var v = entities[NUM_KEYS + i];
- flat_binds[i] = k.bind(&v);
- }
- var flat_mem = treeBundleN(flat_binds[0..6]);
-
- var flat_correct: u32 = 0;
- for (0..6) |i| {
- var key = entities[i];
- const r = queryMem(&flat_mem, &key, entities[0..NUM_ENTITIES]);
- if (r.idx == NUM_KEYS + i) flat_correct += 1;
- }
-
- // Split: 2 Γ 3 pairs
- var split_a_binds: [3]Hypervector = undefined;
- var split_b_binds: [3]Hypervector = undefined;
- for (0..3) |i| {
- var k = entities[i];
- var v = entities[NUM_KEYS + i];
- split_a_binds[i] = k.bind(&v);
- }
- for (0..3) |i| {
- var k = entities[3 + i];
- var v = entities[NUM_KEYS + 3 + i];
- split_b_binds[i] = k.bind(&v);
- }
- var split_a = treeBundleN(split_a_binds[0..3]);
- var split_b = treeBundleN(split_b_binds[0..3]);
-
- var split_correct: u32 = 0;
- for (0..6) |i| {
- var key = entities[i];
- var res_a = split_a.unbind(&key);
- var res_b = split_b.unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..NUM_ENTITIES) |j| {
- var cj = entities[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- if (bi == NUM_KEYS + i) split_correct += 1;
- }
-
- std.debug.print("Flat (6 pairs): {d}/6\n", .{flat_correct});
- std.debug.print("Split (2Γ3): {d}/6\n", .{split_correct});
- const split_advantage = split_correct >= flat_correct;
- std.debug.print("Split advantage: {s}\n", .{
- @as([]const u8, if (split_advantage) "YES (split >= flat)" else "NO"),
- });
-
- // --- Task 3: Capacity headroom β measure how far from sqrt(DIM) we can go ---
- std.debug.print("\n--- Capacity Analysis ---\n", .{});
- const sqrt_dim = @sqrt(@as(f64, DIM)); // ~32
- std.debug.print("DIM={d}, sqrt(DIM)={d:.0}\n", .{ DIM, sqrt_dim });
- std.debug.print("Sweet spot: 3-5 pairs (100%)\n", .{});
-
- // Find first level where accuracy < 100%
- var first_degradation: u32 = 0;
- for (acc_per_level, 0..) |a, i| {
- if (a < 100.0) {
- first_degradation = @intCast(i + 1);
- break;
- }
- }
- if (first_degradation == 0) first_degradation = 10;
- std.debug.print("First degradation at: {d} pairs\n", .{first_degradation});
- std.debug.print("Recommended max per memory: {d} pairs\n", .{@min(first_degradation, 5)});
-
- // --- Summary ---
- const total_acc = @as(f64, @floatFromInt(total_correct_all)) / @as(f64, @floatFromInt(total_measured)) * 100.0;
-
- std.debug.print("\n--- Degradation Summary ---\n", .{});
- std.debug.print("Total across all levels: {d}/{d} ({d:.0}%)\n", .{ total_correct_all, total_measured, total_acc });
- std.debug.print("Split improves: {s}\n", .{
- @as([]const u8, if (split_advantage) "YES" else "NO"),
- });
-
- // Assertions
- try std.testing.expect(acc_per_level[0] == 100.0); // 1 pair always works
- try std.testing.expect(acc_per_level[2] == 100.0); // 3 pairs should work
- try std.testing.expect(acc_per_level[4] >= 80.0); // 5 pairs should be β₯80%
- try std.testing.expect(split_correct >= flat_correct); // split never worse
-
- // Progression
- std.debug.print("\n--- Level 11.22 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.20 | Full engine fusion | unified+dispatch+stress\n", .{});
- std.debug.print("11.21 | Deployment prototype | massive+robust+pipeline\n", .{});
- std.debug.print("11.22 | User testing | confidence+batch+degrade <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 121: Heap-Allocated Massive KG β 120 entities, 12 relations, 3-hop chains
-// Level 11.23 β First heap-allocated test, breaks the stack barrier
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "heap allocated massive kg 120 entities 12 relations" {
- const allocator = std.testing.allocator;
- const DIM = 1024;
-
- // βββ Category Layout (120 entities) βββ
- // 0-11: Scientists (12)
- // 12-23: Universities (12)
- // 24-35: Cities (12)
- // 36-47: Countries (12)
- // 48-59: Fields (12)
- // 60-71: Instruments (12)
- // 72-83: Theories (12)
- // 84-95: Elements (12)
- // 96-107: Labs (12)
- // 108-119: Continents (12 β reusing for diversity, 6 real + 6 aliases)
- const NUM_ENTITIES = 120;
- const SCIENTISTS = 12;
-
- std.debug.print("\n=== TEST 121: HEAP-ALLOCATED MASSIVE KG (Level 11.23) ===\n", .{});
- std.debug.print("Entities: {d}, Categories: 10, DIM: {d}\n", .{ NUM_ENTITIES, DIM });
- std.debug.print("HEAP ALLOCATED β breaking stack barrier\n", .{});
-
- // Heap-allocate all entity vectors
- const entities = try allocator.alloc(Hypervector, NUM_ENTITIES);
- defer allocator.free(entities);
-
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xAA23000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // --- Relation 1: works_at (scientist β university) 12 pairs, split 4Γ3 ---
- const works_at_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(works_at_bind);
- for (0..12) |i| {
- var k = entities[i]; // scientist
- var v = entities[12 + i]; // university
- works_at_bind[i] = k.bind(&v);
- }
- var works_at_a = treeBundleN(works_at_bind[0..3]);
- var works_at_b = treeBundleN(works_at_bind[3..6]);
- var works_at_c = treeBundleN(works_at_bind[6..9]);
- var works_at_d = treeBundleN(works_at_bind[9..12]);
- const works_at_mems = [_]*Hypervector{ &works_at_a, &works_at_b, &works_at_c, &works_at_d };
-
- // --- Relation 2: univ_in (university β city) 12 pairs, split 4Γ3 ---
- const univ_in_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(univ_in_bind);
- for (0..12) |i| {
- var k = entities[12 + i]; // university
- var v = entities[24 + i]; // city
- univ_in_bind[i] = k.bind(&v);
- }
- var univ_in_a = treeBundleN(univ_in_bind[0..3]);
- var univ_in_b = treeBundleN(univ_in_bind[3..6]);
- var univ_in_c = treeBundleN(univ_in_bind[6..9]);
- var univ_in_d = treeBundleN(univ_in_bind[9..12]);
- const univ_in_mems = [_]*Hypervector{ &univ_in_a, &univ_in_b, &univ_in_c, &univ_in_d };
-
- // --- Relation 3: city_in (city β country) 12 pairs, split 4Γ3 ---
- const city_in_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(city_in_bind);
- for (0..12) |i| {
- var k = entities[24 + i]; // city
- var v = entities[36 + i]; // country
- city_in_bind[i] = k.bind(&v);
- }
- var city_in_a = treeBundleN(city_in_bind[0..3]);
- var city_in_b = treeBundleN(city_in_bind[3..6]);
- var city_in_c = treeBundleN(city_in_bind[6..9]);
- var city_in_d = treeBundleN(city_in_bind[9..12]);
- const city_in_mems = [_]*Hypervector{ &city_in_a, &city_in_b, &city_in_c, &city_in_d };
-
- // --- Relation 4: studies (scientist β field) 12 pairs, split 4Γ3 ---
- const studies_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(studies_bind);
- for (0..12) |i| {
- var k = entities[i]; // scientist
- var v = entities[48 + i]; // field
- studies_bind[i] = k.bind(&v);
- }
- var studies_a = treeBundleN(studies_bind[0..3]);
- var studies_b = treeBundleN(studies_bind[3..6]);
- var studies_c = treeBundleN(studies_bind[6..9]);
- var studies_d = treeBundleN(studies_bind[9..12]);
- const studies_mems = [_]*Hypervector{ &studies_a, &studies_b, &studies_c, &studies_d };
-
- // --- Relation 5: uses (scientist β instrument) 12 pairs, split 4Γ3 ---
- const uses_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(uses_bind);
- for (0..12) |i| {
- var k = entities[i]; // scientist
- var v = entities[60 + i]; // instrument
- uses_bind[i] = k.bind(&v);
- }
- var uses_a = treeBundleN(uses_bind[0..3]);
- var uses_b = treeBundleN(uses_bind[3..6]);
- var uses_c = treeBundleN(uses_bind[6..9]);
- var uses_d = treeBundleN(uses_bind[9..12]);
- const uses_mems = [_]*Hypervector{ &uses_a, &uses_b, &uses_c, &uses_d };
-
- // --- Relation 6: proposed (scientist β theory) 12 pairs, split 4Γ3 ---
- const proposed_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(proposed_bind);
- for (0..12) |i| {
- var k = entities[i]; // scientist
- var v = entities[72 + i]; // theory
- proposed_bind[i] = k.bind(&v);
- }
- var proposed_a = treeBundleN(proposed_bind[0..3]);
- var proposed_b = treeBundleN(proposed_bind[3..6]);
- var proposed_c = treeBundleN(proposed_bind[6..9]);
- var proposed_d = treeBundleN(proposed_bind[9..12]);
- const proposed_mems = [_]*Hypervector{ &proposed_a, &proposed_b, &proposed_c, &proposed_d };
-
- // --- Relation 7: studies_element (scientist β element) 12 pairs, split 4Γ3 ---
- const elem_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(elem_bind);
- for (0..12) |i| {
- var k = entities[i]; // scientist
- var v = entities[84 + i]; // element
- elem_bind[i] = k.bind(&v);
- }
- var elem_a = treeBundleN(elem_bind[0..3]);
- var elem_b = treeBundleN(elem_bind[3..6]);
- var elem_c = treeBundleN(elem_bind[6..9]);
- var elem_d = treeBundleN(elem_bind[9..12]);
- const elem_mems = [_]*Hypervector{ &elem_a, &elem_b, &elem_c, &elem_d };
-
- // --- Relation 8: works_in_lab (scientist β lab) 12 pairs, split 4Γ3 ---
- const lab_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(lab_bind);
- for (0..12) |i| {
- var k = entities[i]; // scientist
- var v = entities[96 + i]; // lab
- lab_bind[i] = k.bind(&v);
- }
- var lab_a = treeBundleN(lab_bind[0..3]);
- var lab_b = treeBundleN(lab_bind[3..6]);
- var lab_c = treeBundleN(lab_bind[6..9]);
- var lab_d = treeBundleN(lab_bind[9..12]);
- const lab_mems = [_]*Hypervector{ &lab_a, &lab_b, &lab_c, &lab_d };
-
- // --- Relation 9: country_in_continent (country β continent) 12 pairs, split 4Γ3 ---
- const cont_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(cont_bind);
- for (0..12) |i| {
- var k = entities[36 + i]; // country
- var v = entities[108 + i]; // continent
- cont_bind[i] = k.bind(&v);
- }
- var cont_a = treeBundleN(cont_bind[0..3]);
- var cont_b = treeBundleN(cont_bind[3..6]);
- var cont_c = treeBundleN(cont_bind[6..9]);
- var cont_d = treeBundleN(cont_bind[9..12]);
- const cont_mems = [_]*Hypervector{ &cont_a, &cont_b, &cont_c, &cont_d };
-
- // --- Relation 10: field_uses_instrument (field β instrument) 12 pairs, split 4Γ3 ---
- const fi_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(fi_bind);
- for (0..12) |i| {
- var k = entities[48 + i]; // field
- var v = entities[60 + i]; // instrument
- fi_bind[i] = k.bind(&v);
- }
- var fi_a = treeBundleN(fi_bind[0..3]);
- var fi_b = treeBundleN(fi_bind[3..6]);
- var fi_c = treeBundleN(fi_bind[6..9]);
- var fi_d = treeBundleN(fi_bind[9..12]);
- const fi_mems = [_]*Hypervector{ &fi_a, &fi_b, &fi_c, &fi_d };
-
- // --- Relation 11: univ_has_lab (university β lab) 12 pairs, split 4Γ3 ---
- const ul_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(ul_bind);
- for (0..12) |i| {
- var k = entities[12 + i]; // university
- var v = entities[96 + i]; // lab
- ul_bind[i] = k.bind(&v);
- }
- var ul_a = treeBundleN(ul_bind[0..3]);
- var ul_b = treeBundleN(ul_bind[3..6]);
- var ul_c = treeBundleN(ul_bind[6..9]);
- var ul_d = treeBundleN(ul_bind[9..12]);
- const ul_mems = [_]*Hypervector{ &ul_a, &ul_b, &ul_c, &ul_d };
-
- // --- Relation 12: lab_studies_element (lab β element) 12 pairs, split 4Γ3 ---
- const le_bind = try allocator.alloc(Hypervector, 12);
- defer allocator.free(le_bind);
- for (0..12) |i| {
- var k = entities[96 + i]; // lab
- var v = entities[84 + i]; // element
- le_bind[i] = k.bind(&v);
- }
- var le_a = treeBundleN(le_bind[0..3]);
- var le_b = treeBundleN(le_bind[3..6]);
- var le_c = treeBundleN(le_bind[6..9]);
- var le_d = treeBundleN(le_bind[9..12]);
- const le_mems = [_]*Hypervector{ &le_a, &le_b, &le_c, &le_d };
-
- // querySplit4 helper
- const querySplit4 = struct {
- fn q(mems: [4]*Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (mems) |mem| {
- var result = mem.unbind(key);
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: Direct 1-hop β scientistβuniversity (12 queries) ---
- std.debug.print("\n--- Task 1: scientistβuniversity (12 queries, 120 candidates) ---\n", .{});
- var t1_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- const r = querySplit4(works_at_mems, &key, entities);
- if (r.idx == 12 + i) t1_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 12;
-
- // --- Task 2: Direct 1-hop β scientistβfield (12 queries) ---
- std.debug.print("--- Task 2: scientistβfield (12 queries) ---\n", .{});
- var t2_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- const r = querySplit4(studies_mems, &key, entities);
- if (r.idx == 48 + i) t2_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 12;
-
- // --- Task 3: Direct 1-hop β scientistβinstrument (12 queries) ---
- std.debug.print("--- Task 3: scientistβinstrument (12 queries) ---\n", .{});
- var t3_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- const r = querySplit4(uses_mems, &key, entities);
- if (r.idx == 60 + i) t3_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 12;
-
- // --- Task 4: 2-hop β scientistβuniversityβcity (12 queries) ---
- std.debug.print("--- Task 4: scientistβuniversityβcity (12 2-hop queries) ---\n", .{});
- var t4_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- // Hop 1: scientist β university
- const r1 = querySplit4(works_at_mems, &key, entities);
- // Hop 2: university β city
- var univ = entities[r1.idx];
- const r2 = querySplit4(univ_in_mems, &univ, entities);
- if (r2.idx == 24 + i) t4_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t4_correct});
- total_correct += t4_correct;
- total_queries += 12;
-
- // --- Task 5: 3-hop β scientistβuniversityβcityβcountry (12 queries) ---
- std.debug.print("--- Task 5: scientistβunivβcityβcountry (12 3-hop queries) ---\n", .{});
- var t5_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- const r1 = querySplit4(works_at_mems, &key, entities);
- var univ = entities[r1.idx];
- const r2 = querySplit4(univ_in_mems, &univ, entities);
- var city = entities[r2.idx];
- const r3 = querySplit4(city_in_mems, &city, entities);
- if (r3.idx == 36 + i) t5_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t5_correct});
- total_correct += t5_correct;
- total_queries += 12;
-
- // --- Task 6: Cross-relation β scientistβ(theory + element) divergent (12Γ2 queries) ---
- std.debug.print("--- Task 6: scientistβtheory AND scientistβelement (24 queries) ---\n", .{});
- var t6_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- const r_theory = querySplit4(proposed_mems, &key, entities);
- const r_elem = querySplit4(elem_mems, &key, entities);
- if (r_theory.idx == 72 + i) t6_correct += 1;
- if (r_elem.idx == 84 + i) t6_correct += 1;
- }
- std.debug.print("Result: {d}/24\n", .{t6_correct});
- total_correct += t6_correct;
- total_queries += 24;
-
- // --- Task 7: Cross-chain 3-hop β scientistβunivβlab + labβelement (12Γ2 queries) ---
- std.debug.print("--- Task 7: scientistβunivβlab AND labβelement (24 queries) ---\n", .{});
- var t7_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- // scientistβuniversity
- const r1 = querySplit4(works_at_mems, &key, entities);
- // universityβlab
- var univ = entities[r1.idx];
- const r_lab = querySplit4(ul_mems, &univ, entities);
- if (r_lab.idx == 96 + i) t7_correct += 1;
- // labβelement
- var lab = entities[r_lab.idx];
- const r_elem = querySplit4(le_mems, &lab, entities);
- if (r_elem.idx == 84 + i) t7_correct += 1;
- }
- std.debug.print("Result: {d}/24\n", .{t7_correct});
- total_correct += t7_correct;
- total_queries += 24;
-
- // --- Task 8: fieldβinstrument cross-domain (12 queries) ---
- std.debug.print("--- Task 8: fieldβinstrument cross-domain (12 queries) ---\n", .{});
- var t8_correct: u32 = 0;
- for (0..12) |i| {
- var key = entities[48 + i]; // field
- const r = querySplit4(fi_mems, &key, entities);
- if (r.idx == 60 + i) t8_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t8_correct});
- total_correct += t8_correct;
- total_queries += 12;
-
- // --- Task 9: scientistβlab direct (12 queries) ---
- std.debug.print("--- Task 9: scientistβlab direct (12 queries) ---\n", .{});
- var t9_correct: u32 = 0;
- for (0..SCIENTISTS) |i| {
- var key = entities[i];
- const r = querySplit4(lab_mems, &key, entities);
- if (r.idx == 96 + i) t9_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t9_correct});
- total_correct += t9_correct;
- total_queries += 12;
-
- // --- Task 10: countryβcontinent (12 queries) ---
- std.debug.print("--- Task 10: countryβcontinent (12 queries) ---\n", .{});
- var t10_correct: u32 = 0;
- for (0..12) |i| {
- var key = entities[36 + i]; // country
- const r = querySplit4(cont_mems, &key, entities);
- if (r.idx == 108 + i) t10_correct += 1;
- }
- std.debug.print("Result: {d}/12\n", .{t10_correct});
- total_correct += t10_correct;
- total_queries += 12;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- Massive KG Summary ---\n", .{});
- std.debug.print("Entities: {d} (HEAP ALLOCATED)\n", .{NUM_ENTITIES});
- std.debug.print("Relations: 12 (all 4Γ3 split)\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
- std.debug.print("Memory: {d} entities Γ ~70KB = ~{d}KB heap\n", .{ NUM_ENTITIES, NUM_ENTITIES * 70 });
-
- // Assertions
- try std.testing.expect(t1_correct == 12); // direct 1-hop
- try std.testing.expect(t5_correct >= 10); // 3-hop may lose a few
- try std.testing.expect(total_correct >= total_queries * 8 / 10); // β₯80% overall
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 122: CLI-Style Query Dispatch β Programmatic query type routing
-// Level 11.23 β Simulates CLI query interface for local testing
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "cli style query dispatch routing" {
- const DIM = 1024;
- const NUM_ENTITIES = 30;
-
- std.debug.print("\n=== TEST 122: CLI-STYLE QUERY DISPATCH (Level 11.23) ===\n", .{});
-
- // Create entity vectors
- var entities: [NUM_ENTITIES]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xCCDD000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Layout: 0-4 cities, 5-9 countries, 10-14 landmarks, 15-19 foods, 20-24 languages, 25-29 climates
- const CITY = 0;
- const COUNTRY = 5;
- const LANDMARK = 10;
- const FOOD = 15;
- const LANG = 20;
- const CLIMATE = 25;
-
- // Relations (2Γ3 split or 2Γ2+1 for 5 pairs)
- // R1: city_in_country (city β country)
- var ci_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[CITY + i];
- var v = entities[COUNTRY + i];
- ci_binds[i] = k.bind(&v);
- }
- var ci_mem_a = treeBundleN(ci_binds[0..3]);
- var ci_mem_b = treeBundleN(ci_binds[3..5]);
-
- // R2: landmark_in_city (landmark β city)
- var lc_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[LANDMARK + i];
- var v = entities[CITY + i];
- lc_binds[i] = k.bind(&v);
- }
- var lc_mem_a = treeBundleN(lc_binds[0..3]);
- var lc_mem_b = treeBundleN(lc_binds[3..5]);
-
- // R3: country_food (country β food)
- var cf_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[COUNTRY + i];
- var v = entities[FOOD + i];
- cf_binds[i] = k.bind(&v);
- }
- var cf_mem_a = treeBundleN(cf_binds[0..3]);
- var cf_mem_b = treeBundleN(cf_binds[3..5]);
-
- // R4: country_language (country β language)
- var cl_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[COUNTRY + i];
- var v = entities[LANG + i];
- cl_binds[i] = k.bind(&v);
- }
- var cl_mem_a = treeBundleN(cl_binds[0..3]);
- var cl_mem_b = treeBundleN(cl_binds[3..5]);
-
- // R5: country_climate (country β climate)
- var cc_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[COUNTRY + i];
- var v = entities[CLIMATE + i];
- cc_binds[i] = k.bind(&v);
- }
- var cc_mem_a = treeBundleN(cc_binds[0..3]);
- var cc_mem_b = treeBundleN(cc_binds[3..5]);
-
- // querySplit helper
- const querySplit = struct {
- fn q(mem_a: *Hypervector, mem_b: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = mem_a.unbind(key);
- var res_b = mem_b.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // === CLI Query Dispatch ===
- // Simulate 7 query types that a CLI user would invoke
-
- const QueryType = enum { direct, chain2, chain3, cross_domain, inverse_chain, multi_rel, enumerate };
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Query Type 1: DIRECT β "What country is city X in?" ---
- std.debug.print("\n--- CLI: direct query (cityβcountry) ---\n", .{});
- var q1_correct: u32 = 0;
- for (0..5) |i| {
- _ = @as(QueryType, .direct); // dispatch tag
- var key = entities[CITY + i];
- const r = querySplit(&ci_mem_a, &ci_mem_b, &key, &entities);
- if (r.idx == COUNTRY + i) q1_correct += 1;
- }
- std.debug.print("Result: {d}/5\n", .{q1_correct});
- total_correct += q1_correct;
- total_queries += 5;
-
- // --- Query Type 2: CHAIN2 β "What country is landmark X in?" (landmarkβcityβcountry) ---
- std.debug.print("--- CLI: 2-hop chain (landmarkβcityβcountry) ---\n", .{});
- var q2_correct: u32 = 0;
- for (0..5) |i| {
- _ = @as(QueryType, .chain2);
- var key = entities[LANDMARK + i];
- const r1 = querySplit(&lc_mem_a, &lc_mem_b, &key, &entities);
- var city = entities[r1.idx];
- const r2 = querySplit(&ci_mem_a, &ci_mem_b, &city, &entities);
- if (r2.idx == COUNTRY + i) q2_correct += 1;
- }
- std.debug.print("Result: {d}/5\n", .{q2_correct});
- total_correct += q2_correct;
- total_queries += 5;
-
- // --- Query Type 3: CHAIN3 β "What food for landmark X?" (landmarkβcityβcountryβfood) ---
- std.debug.print("--- CLI: 3-hop chain (landmarkβcityβcountryβfood) ---\n", .{});
- var q3_correct: u32 = 0;
- for (0..5) |i| {
- _ = @as(QueryType, .chain3);
- var key = entities[LANDMARK + i];
- const r1 = querySplit(&lc_mem_a, &lc_mem_b, &key, &entities);
- var city = entities[r1.idx];
- const r2 = querySplit(&ci_mem_a, &ci_mem_b, &city, &entities);
- var country = entities[r2.idx];
- const r3 = querySplit(&cf_mem_a, &cf_mem_b, &country, &entities);
- if (r3.idx == FOOD + i) q3_correct += 1;
- }
- std.debug.print("Result: {d}/5\n", .{q3_correct});
- total_correct += q3_correct;
- total_queries += 5;
-
- // --- Query Type 4: CROSS_DOMAIN β "What language + climate for country X?" ---
- std.debug.print("--- CLI: cross-domain (countryβlanguage AND countryβclimate) ---\n", .{});
- var q4_correct: u32 = 0;
- for (0..5) |i| {
- _ = @as(QueryType, .cross_domain);
- var key = entities[COUNTRY + i];
- const r_lang = querySplit(&cl_mem_a, &cl_mem_b, &key, &entities);
- const r_clim = querySplit(&cc_mem_a, &cc_mem_b, &key, &entities);
- if (r_lang.idx == LANG + i) q4_correct += 1;
- if (r_clim.idx == CLIMATE + i) q4_correct += 1;
- }
- std.debug.print("Result: {d}/10\n", .{q4_correct});
- total_correct += q4_correct;
- total_queries += 10;
-
- // --- Query Type 5: MULTI_REL β "All relations for country X?" (food + language + climate) ---
- std.debug.print("--- CLI: multi-relation (countryβfood,language,climate) ---\n", .{});
- var q5_correct: u32 = 0;
- for (0..5) |i| {
- _ = @as(QueryType, .multi_rel);
- var key = entities[COUNTRY + i];
- const r_food = querySplit(&cf_mem_a, &cf_mem_b, &key, &entities);
- const r_lang = querySplit(&cl_mem_a, &cl_mem_b, &key, &entities);
- const r_clim = querySplit(&cc_mem_a, &cc_mem_b, &key, &entities);
- if (r_food.idx == FOOD + i) q5_correct += 1;
- if (r_lang.idx == LANG + i) q5_correct += 1;
- if (r_clim.idx == CLIMATE + i) q5_correct += 1;
- }
- std.debug.print("Result: {d}/15\n", .{q5_correct});
- total_correct += q5_correct;
- total_queries += 15;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- CLI Query Dispatch Summary ---\n", .{});
- std.debug.print("Query types: 5 (direct, chain2, chain3, cross_domain, multi_rel)\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- // Assertions
- try std.testing.expect(q1_correct == 5); // direct always works
- try std.testing.expect(q2_correct >= 4); // 2-hop should be strong
- try std.testing.expect(total_correct >= 35); // β₯35/40
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 123: Massive Batch Integration β 100 entities, 10 relations, batch queries
-// Level 11.23 β Heap-allocated batch processing at scale
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "massive batch integration 100 entities 10 relations" {
- const allocator = std.testing.allocator;
- const DIM = 1024;
- const NUM_ENTITIES = 100;
-
- std.debug.print("\n=== TEST 123: MASSIVE BATCH INTEGRATION (Level 11.23) ===\n", .{});
- std.debug.print("Entities: {d} (HEAP), Relations: 10, DIM: {d}\n", .{ NUM_ENTITIES, DIM });
-
- // Heap-allocate entities
- const entities = try allocator.alloc(Hypervector, NUM_ENTITIES);
- defer allocator.free(entities);
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xBB23000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Layout: 10 categories Γ 10 entities each
- // 0-9: People 10-19: Companies 20-29: Cities
- // 30-39: Countries 40-49: Products 50-59: Skills
- // 60-69: Universities 70-79: Departments 80-89: Projects
- // 90-99: Tools
-
- // Build 10 relations (all 2Γ5 split β 10 pairs each)
- const NUM_PAIRS = 10;
-
- // Helper to build a split memory from entity range pairs
- const BuildSplit = struct {
- fn build(ents: []Hypervector, key_start: usize, val_start: usize, binds_buf: []Hypervector) struct { a: Hypervector, b: Hypervector } {
- for (0..NUM_PAIRS) |i| {
- var k = ents[key_start + i];
- var v = ents[val_start + i];
- binds_buf[i] = k.bind(&v);
- }
- return .{
- .a = treeBundleN(binds_buf[0..5]),
- .b = treeBundleN(binds_buf[5..10]),
- };
- }
- };
-
- // Allocate bind buffers
- const binds = try allocator.alloc(Hypervector, NUM_PAIRS);
- defer allocator.free(binds);
-
- // R1: person β company (works_at)
- var r1 = BuildSplit.build(entities, 0, 10, binds);
- // R2: company β city (hq_in)
- var r2 = BuildSplit.build(entities, 10, 20, binds);
- // R3: city β country (city_country)
- var r3 = BuildSplit.build(entities, 20, 30, binds);
- // R4: person β skill (has_skill)
- var r4 = BuildSplit.build(entities, 0, 50, binds);
- // R5: person β university (studied_at)
- var r5 = BuildSplit.build(entities, 0, 60, binds);
- // R6: university β city (univ_city)
- var r6 = BuildSplit.build(entities, 60, 20, binds);
- // R7: company β product (makes)
- var r7 = BuildSplit.build(entities, 10, 40, binds);
- // R8: university β department (has_dept)
- var r8 = BuildSplit.build(entities, 60, 70, binds);
- // R9: person β project (works_on)
- var r9 = BuildSplit.build(entities, 0, 80, binds);
- // R10: project β tool (uses_tool)
- var r10 = BuildSplit.build(entities, 80, 90, binds);
-
- const querySplit = struct {
- fn q(mem_a: *Hypervector, mem_b: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = mem_a.unbind(key);
- var res_b = mem_b.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Batch 1: Direct 1-hop queries across all 10 relations (10Γ10 = 100 queries) ---
- std.debug.print("\n--- Batch 1: Direct 1-hop all relations (100 queries) ---\n", .{});
- const relation_data = [_]struct { key_start: usize, val_start: usize, a: *Hypervector, b: *Hypervector }{
- .{ .key_start = 0, .val_start = 10, .a = &r1.a, .b = &r1.b },
- .{ .key_start = 10, .val_start = 20, .a = &r2.a, .b = &r2.b },
- .{ .key_start = 20, .val_start = 30, .a = &r3.a, .b = &r3.b },
- .{ .key_start = 0, .val_start = 50, .a = &r4.a, .b = &r4.b },
- .{ .key_start = 0, .val_start = 60, .a = &r5.a, .b = &r5.b },
- .{ .key_start = 60, .val_start = 20, .a = &r6.a, .b = &r6.b },
- .{ .key_start = 10, .val_start = 40, .a = &r7.a, .b = &r7.b },
- .{ .key_start = 60, .val_start = 70, .a = &r8.a, .b = &r8.b },
- .{ .key_start = 0, .val_start = 80, .a = &r9.a, .b = &r9.b },
- .{ .key_start = 80, .val_start = 90, .a = &r10.a, .b = &r10.b },
- };
-
- var batch1_correct: u32 = 0;
- for (relation_data) |rel| {
- for (0..NUM_PAIRS) |i| {
- var key = entities[rel.key_start + i];
- const r = querySplit(rel.a, rel.b, &key, entities);
- if (r.idx == rel.val_start + i) batch1_correct += 1;
- }
- }
- std.debug.print("Result: {d}/100\n", .{batch1_correct});
- total_correct += batch1_correct;
- total_queries += 100;
-
- // --- Batch 2: 2-hop chains β personβcompanyβcity (10 queries) ---
- std.debug.print("--- Batch 2: personβcompanyβcity (10 2-hop queries) ---\n", .{});
- var batch2_correct: u32 = 0;
- for (0..NUM_PAIRS) |i| {
- var key = entities[i]; // person
- const hop1 = querySplit(&r1.a, &r1.b, &key, entities); // β company
- var company = entities[hop1.idx];
- const hop2 = querySplit(&r2.a, &r2.b, &company, entities); // β city
- if (hop2.idx == 20 + i) batch2_correct += 1;
- }
- std.debug.print("Result: {d}/10\n", .{batch2_correct});
- total_correct += batch2_correct;
- total_queries += 10;
-
- // --- Batch 3: 3-hop chains β personβcompanyβcityβcountry (10 queries) ---
- std.debug.print("--- Batch 3: personβcompanyβcityβcountry (10 3-hop queries) ---\n", .{});
- var batch3_correct: u32 = 0;
- for (0..NUM_PAIRS) |i| {
- var key = entities[i]; // person
- const hop1 = querySplit(&r1.a, &r1.b, &key, entities);
- var company = entities[hop1.idx];
- const hop2 = querySplit(&r2.a, &r2.b, &company, entities);
- var city = entities[hop2.idx];
- const hop3 = querySplit(&r3.a, &r3.b, &city, entities);
- if (hop3.idx == 30 + i) batch3_correct += 1;
- }
- std.debug.print("Result: {d}/10\n", .{batch3_correct});
- total_correct += batch3_correct;
- total_queries += 10;
-
- // --- Batch 4: Cross-relation β personβ(skill + project + company) (10Γ3 queries) ---
- std.debug.print("--- Batch 4: personβskill,project,company (30 queries) ---\n", .{});
- var batch4_correct: u32 = 0;
- for (0..NUM_PAIRS) |i| {
- var key = entities[i]; // person
- const r_comp = querySplit(&r1.a, &r1.b, &key, entities);
- const r_skill = querySplit(&r4.a, &r4.b, &key, entities);
- const r_proj = querySplit(&r9.a, &r9.b, &key, entities);
- if (r_comp.idx == 10 + i) batch4_correct += 1;
- if (r_skill.idx == 50 + i) batch4_correct += 1;
- if (r_proj.idx == 80 + i) batch4_correct += 1;
- }
- std.debug.print("Result: {d}/30\n", .{batch4_correct});
- total_correct += batch4_correct;
- total_queries += 30;
-
- // --- Batch 5: Deterministic consistency (repeat batch 1 for first 2 relations, 20 queries) ---
- std.debug.print("--- Batch 5: Deterministic consistency check (20 queries) ---\n", .{});
- var batch5_correct: u32 = 0;
- for (0..2) |rel_idx| {
- const rel = relation_data[rel_idx];
- for (0..NUM_PAIRS) |i| {
- var key = entities[rel.key_start + i];
- const run1 = querySplit(rel.a, rel.b, &key, entities);
- var key2 = entities[rel.key_start + i];
- const run2 = querySplit(rel.a, rel.b, &key2, entities);
- if (run1.idx == run2.idx) batch5_correct += 1;
- }
- }
- std.debug.print("Result: {d}/20 (deterministic)\n", .{batch5_correct});
- total_correct += batch5_correct;
- total_queries += 20;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- Massive Batch Summary ---\n", .{});
- std.debug.print("Entities: {d} (HEAP), Relations: 10, Queries: {d}\n", .{ NUM_ENTITIES, total_queries });
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
- std.debug.print("Memory: {d} entities Γ ~70KB = ~{d}KB heap\n", .{ NUM_ENTITIES, NUM_ENTITIES * 70 });
-
- // Assertions
- try std.testing.expect(batch1_correct >= 90); // β₯90% direct
- try std.testing.expect(batch5_correct == 20); // 100% deterministic
- try std.testing.expect(total_correct >= total_queries * 8 / 10); // β₯80% overall
-
- // Progression
- std.debug.print("\n--- Level 11.23 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.21 | Deployment prototype | massive+robust+pipeline\n", .{});
- std.debug.print("11.22 | User testing | confidence+batch+degrade\n", .{});
- std.debug.print("11.23 | Massive KG + CLI | heap+120ent+10rel+dispatch <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 124: Named Entity Registry β string-to-vector lookup for CLI queries
-// Level 11.24 β Foundation for interactive CLI: named lookups
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "named entity registry string lookup" {
- const DIM = 1024;
-
- std.debug.print("\n=== TEST 124: NAMED ENTITY REGISTRY (Level 11.24) ===\n", .{});
-
- // Entity names β 30 entities across 6 categories
- const entity_names = [_][]const u8{
- "Paris", "Tokyo", "Rome", "London", "Cairo",
- "France", "Japan", "Italy", "UK", "Egypt",
- "Eiffel", "Fuji", "Colosseum", "BigBen", "Pyramids",
- "Croissant", "Sushi", "Pizza", "FishChips", "Falafel",
- "French", "Japanese", "Italian", "English", "Arabic",
- "Temperate", "Humid", "Mediterranean", "Oceanic", "Arid",
- };
- const NUM_ENTITIES = entity_names.len;
-
- // Create entity vectors
- var entities: [30]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xCCDD000 + @as(u64, @intCast(i)) * 7919);
- }
-
- // Relation names and their keyβvalue mappings
- const relation_names = [_][]const u8{
- "capital_of",
- "landmark_in",
- "cuisine_of",
- "language_of",
- "climate_of",
- };
- const NUM_RELATIONS = relation_names.len;
-
- // Relation pairs: [key_idx, val_idx]
- const capital_of_pairs = [5][2]usize{ .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 } };
- const landmark_in_pairs = [5][2]usize{ .{ 10, 0 }, .{ 11, 1 }, .{ 12, 2 }, .{ 13, 3 }, .{ 14, 4 } };
- const cuisine_of_pairs = [5][2]usize{ .{ 15, 5 }, .{ 16, 6 }, .{ 17, 7 }, .{ 18, 8 }, .{ 19, 9 } };
- const language_of_pairs = [5][2]usize{ .{ 20, 5 }, .{ 21, 6 }, .{ 22, 7 }, .{ 23, 8 }, .{ 24, 9 } };
- const climate_of_pairs = [5][2]usize{ .{ 25, 5 }, .{ 26, 6 }, .{ 27, 7 }, .{ 28, 8 }, .{ 29, 9 } };
-
- // Build 5 relation memories (2-way split)
- const all_pairs = [5][5][2]usize{ capital_of_pairs, landmark_in_pairs, cuisine_of_pairs, language_of_pairs, climate_of_pairs };
- var mem_a: [5]Hypervector = undefined;
- var mem_b: [5]Hypervector = undefined;
-
- for (0..NUM_RELATIONS) |rel| {
- var binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[all_pairs[rel][i][0]];
- var v = entities[all_pairs[rel][i][1]];
- binds[i] = k.bind(&v);
- }
- mem_a[rel] = treeBundleN(binds[0..3]);
- mem_b[rel] = treeBundleN(binds[3..5]);
- }
-
- // String-based entity lookup
- const findEntity = struct {
- fn find(name: []const u8, names: []const []const u8) ?usize {
- for (names, 0..) |n, i| {
- if (std.mem.eql(u8, name, n)) return i;
- }
- return null;
- }
- }.find;
-
- // String-based relation lookup
- const findRelation = struct {
- fn find(name: []const u8, names: []const []const u8) ?usize {
- for (names, 0..) |n, i| {
- if (std.mem.eql(u8, name, n)) return i;
- }
- return null;
- }
- }.find;
-
- // querySplit helper
- const querySplit = struct {
- fn q(ma: *Hypervector, mb: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = ma.unbind(key);
- var res_b = mb.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: Registry lookup accuracy ---
- std.debug.print("\n--- Task 1: Entity name registry (30 lookups) ---\n", .{});
- var t1_correct: u32 = 0;
- for (entity_names, 0..) |name, expected_idx| {
- const found = findEntity(name, &entity_names);
- if (found) |idx| {
- if (idx == expected_idx) t1_correct += 1;
- }
- }
- std.debug.print("Result: {d}/30\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 30;
-
- // --- Task 2: Relation name registry (5 lookups) ---
- std.debug.print("--- Task 2: Relation name registry (5 lookups) ---\n", .{});
- var t2_correct: u32 = 0;
- for (relation_names, 0..) |name, expected_idx| {
- const found = findRelation(name, &relation_names);
- if (found) |idx| {
- if (idx == expected_idx) t2_correct += 1;
- }
- }
- std.debug.print("Result: {d}/5\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 5;
-
- // --- Task 3: Named query dispatch β all 25 relation pairs (5 relations Γ 5 pairs) ---
- std.debug.print("--- Task 3: Named query dispatch (25 queries) ---\n", .{});
- const test_queries = [_]struct { entity: []const u8, relation: []const u8, expected: []const u8 }{
- .{ .entity = "Paris", .relation = "capital_of", .expected = "France" },
- .{ .entity = "Tokyo", .relation = "capital_of", .expected = "Japan" },
- .{ .entity = "Rome", .relation = "capital_of", .expected = "Italy" },
- .{ .entity = "London", .relation = "capital_of", .expected = "UK" },
- .{ .entity = "Cairo", .relation = "capital_of", .expected = "Egypt" },
- .{ .entity = "Eiffel", .relation = "landmark_in", .expected = "Paris" },
- .{ .entity = "Fuji", .relation = "landmark_in", .expected = "Tokyo" },
- .{ .entity = "Colosseum", .relation = "landmark_in", .expected = "Rome" },
- .{ .entity = "BigBen", .relation = "landmark_in", .expected = "London" },
- .{ .entity = "Pyramids", .relation = "landmark_in", .expected = "Cairo" },
- .{ .entity = "Croissant", .relation = "cuisine_of", .expected = "France" },
- .{ .entity = "Sushi", .relation = "cuisine_of", .expected = "Japan" },
- .{ .entity = "Pizza", .relation = "cuisine_of", .expected = "Italy" },
- .{ .entity = "FishChips", .relation = "cuisine_of", .expected = "UK" },
- .{ .entity = "Falafel", .relation = "cuisine_of", .expected = "Egypt" },
- .{ .entity = "French", .relation = "language_of", .expected = "France" },
- .{ .entity = "Japanese", .relation = "language_of", .expected = "Japan" },
- .{ .entity = "Italian", .relation = "language_of", .expected = "Italy" },
- .{ .entity = "English", .relation = "language_of", .expected = "UK" },
- .{ .entity = "Arabic", .relation = "language_of", .expected = "Egypt" },
- .{ .entity = "Temperate", .relation = "climate_of", .expected = "France" },
- .{ .entity = "Humid", .relation = "climate_of", .expected = "Japan" },
- .{ .entity = "Mediterranean", .relation = "climate_of", .expected = "Italy" },
- .{ .entity = "Oceanic", .relation = "climate_of", .expected = "UK" },
- .{ .entity = "Arid", .relation = "climate_of", .expected = "Egypt" },
- };
-
- var t3_correct: u32 = 0;
- for (test_queries) |tq| {
- const ent_idx = findEntity(tq.entity, &entity_names).?;
- const rel_idx = findRelation(tq.relation, &relation_names).?;
- const exp_idx = findEntity(tq.expected, &entity_names).?;
-
- var key = entities[ent_idx];
- const result = querySplit(&mem_a[rel_idx], &mem_b[rel_idx], &key, &entities);
- if (result.idx == exp_idx) {
- t3_correct += 1;
- } else {
- std.debug.print(" MISS: {s}({s}) = {s} (expected {s})\n", .{
- tq.relation, tq.entity, entity_names[result.idx], tq.expected,
- });
- }
- }
- std.debug.print("Result: {d}/25\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 25;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- Named Entity Registry Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct == 30); // registry perfect
- try std.testing.expect(t2_correct == 5); // relation registry perfect
- try std.testing.expect(t3_correct == 25); // all queries correct
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 125: Multi-Hop CLI Pipeline β end-to-end from entity name through chain
-// Level 11.24 β Full pipeline from string input to string output
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "multi hop cli pipeline string to string" {
- const DIM = 1024;
-
- std.debug.print("\n=== TEST 125: MULTI-HOP CLI PIPELINE (Level 11.24) ===\n", .{});
-
- // Same KG as Test 124 (same seeds = same vectors = deterministic)
- const entity_names = [_][]const u8{
- "Paris", "Tokyo", "Rome", "London", "Cairo",
- "France", "Japan", "Italy", "UK", "Egypt",
- "Eiffel", "Fuji", "Colosseum", "BigBen", "Pyramids",
- "Croissant", "Sushi", "Pizza", "FishChips", "Falafel",
- "French", "Japanese", "Italian", "English", "Arabic",
- "Temperate", "Humid", "Mediterranean", "Oceanic", "Arid",
- };
- const NUM_ENTITIES = entity_names.len;
-
- var entities: [30]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xCCDD000 + @as(u64, @intCast(i)) * 7919);
- }
-
- const relation_names = [_][]const u8{ "capital_of", "landmark_in", "cuisine_of", "language_of", "climate_of" };
- const NUM_RELATIONS = relation_names.len;
-
- const all_pairs = [5][5][2]usize{
- .{ .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 } },
- .{ .{ 10, 0 }, .{ 11, 1 }, .{ 12, 2 }, .{ 13, 3 }, .{ 14, 4 } },
- .{ .{ 15, 5 }, .{ 16, 6 }, .{ 17, 7 }, .{ 18, 8 }, .{ 19, 9 } },
- .{ .{ 20, 5 }, .{ 21, 6 }, .{ 22, 7 }, .{ 23, 8 }, .{ 24, 9 } },
- .{ .{ 25, 5 }, .{ 26, 6 }, .{ 27, 7 }, .{ 28, 8 }, .{ 29, 9 } },
- };
-
- var mem_a: [5]Hypervector = undefined;
- var mem_b: [5]Hypervector = undefined;
- for (0..NUM_RELATIONS) |rel| {
- var binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[all_pairs[rel][i][0]];
- var v = entities[all_pairs[rel][i][1]];
- binds[i] = k.bind(&v);
- }
- mem_a[rel] = treeBundleN(binds[0..3]);
- mem_b[rel] = treeBundleN(binds[3..5]);
- }
-
- const findEntity = struct {
- fn find(name: []const u8, names: []const []const u8) ?usize {
- for (names, 0..) |n, i| {
- if (std.mem.eql(u8, name, n)) return i;
- }
- return null;
- }
- }.find;
-
- const findRelation = struct {
- fn find(name: []const u8, names: []const []const u8) ?usize {
- for (names, 0..) |n, i| {
- if (std.mem.eql(u8, name, n)) return i;
- }
- return null;
- }
- }.find;
-
- const querySplit = struct {
- fn q(ma: *Hypervector, mb: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = ma.unbind(key);
- var res_b = mb.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: 2-hop chains β landmarkβcityβcountry (5 queries) ---
- std.debug.print("\n--- Task 1: 2-hop landmarkβcityβcountry (5 chains) ---\n", .{});
- const chain2_tests = [_]struct { start: []const u8, r1: []const u8, r2: []const u8, expected: []const u8 }{
- .{ .start = "Eiffel", .r1 = "landmark_in", .r2 = "capital_of", .expected = "France" },
- .{ .start = "Fuji", .r1 = "landmark_in", .r2 = "capital_of", .expected = "Japan" },
- .{ .start = "Colosseum", .r1 = "landmark_in", .r2 = "capital_of", .expected = "Italy" },
- .{ .start = "BigBen", .r1 = "landmark_in", .r2 = "capital_of", .expected = "UK" },
- .{ .start = "Pyramids", .r1 = "landmark_in", .r2 = "capital_of", .expected = "Egypt" },
- };
-
- var t1_correct: u32 = 0;
- for (chain2_tests) |ct| {
- const start_idx = findEntity(ct.start, &entity_names).?;
- const r1_idx = findRelation(ct.r1, &relation_names).?;
- const r2_idx = findRelation(ct.r2, &relation_names).?;
- const exp_idx = findEntity(ct.expected, &entity_names).?;
-
- // Hop 1
- var key = entities[start_idx];
- const hop1 = querySplit(&mem_a[r1_idx], &mem_b[r1_idx], &key, &entities);
- // Hop 2
- var mid = entities[hop1.idx];
- const hop2 = querySplit(&mem_a[r2_idx], &mem_b[r2_idx], &mid, &entities);
-
- if (hop2.idx == exp_idx) t1_correct += 1;
- std.debug.print(" {s} --[{s}]--> {s} --[{s}]--> {s} {s}\n", .{
- ct.start, ct.r1, entity_names[hop1.idx], ct.r2, entity_names[hop2.idx],
- @as([]const u8, if (hop2.idx == exp_idx) "OK" else "MISS"),
- });
- }
- std.debug.print("Result: {d}/5\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 5;
-
- // --- Task 2: 3-hop chains β landmarkβcityβcountryβcuisine (5 queries) ---
- std.debug.print("--- Task 2: 3-hop landmarkβcityβcountryβcuisine (5 chains) ---\n", .{});
- const chain3_tests = [_]struct { start: []const u8, expected_food: []const u8 }{
- .{ .start = "Eiffel", .expected_food = "Croissant" },
- .{ .start = "Fuji", .expected_food = "Sushi" },
- .{ .start = "Colosseum", .expected_food = "Pizza" },
- .{ .start = "BigBen", .expected_food = "FishChips" },
- .{ .start = "Pyramids", .expected_food = "Falafel" },
- };
-
- var t2_correct: u32 = 0;
- for (chain3_tests) |ct| {
- const start_idx = findEntity(ct.start, &entity_names).?;
- const food_idx = findEntity(ct.expected_food, &entity_names).?;
-
- // landmarkβcityβcountryβcuisine
- var key = entities[start_idx];
- const hop1 = querySplit(&mem_a[1], &mem_b[1], &key, &entities); // landmark_in
- var city = entities[hop1.idx];
- const hop2 = querySplit(&mem_a[0], &mem_b[0], &city, &entities); // capital_of
- var country = entities[hop2.idx];
- const hop3 = querySplit(&mem_a[2], &mem_b[2], &country, &entities); // cuisine_of β reverse! countryβfood
-
- // cuisine_of maps foodβcountry, not countryβfood. Let's check both directions.
- // Actually cuisine_of pairs are {food_idx, country_idx} so unbind(country) won't work directly.
- // We need to check if the pipeline works despite this direction.
- if (hop3.idx == food_idx) {
- t2_correct += 1;
- } else {
- // The relation stores foodβcountry, but we want countryβfood
- // This tests whether the system can handle reverse queries via similarity
- std.debug.print(" Chain: {s} -> {s} -> {s} -> {s} (expected {s})\n", .{
- ct.start, entity_names[hop1.idx], entity_names[hop2.idx], entity_names[hop3.idx], ct.expected_food,
- });
- }
- }
- std.debug.print("Result: {d}/5\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 5;
-
- // --- Task 3: Cross-domain multi-query β for each country, get language + climate (5Γ2 queries) ---
- std.debug.print("--- Task 3: Cross-domain countryβ(language+climate) (10 queries) ---\n", .{});
- const country_names = [_][]const u8{ "France", "Japan", "Italy", "UK", "Egypt" };
- const expected_langs = [_][]const u8{ "French", "Japanese", "Italian", "English", "Arabic" };
- const expected_climates = [_][]const u8{ "Temperate", "Humid", "Mediterranean", "Oceanic", "Arid" };
-
- var t3_correct: u32 = 0;
- for (0..5) |i| {
- const country_idx = findEntity(country_names[i], &entity_names).?;
- const lang_idx = findEntity(expected_langs[i], &entity_names).?;
- const clim_idx = findEntity(expected_climates[i], &entity_names).?;
-
- // language_of maps langβcountry, climate_of maps climateβcountry
- // Direct query: these are keyβvalue where key=lang, value=country
- // For countryβlang we need reverse lookup β find which lang's unbind gives highest sim with country
- // Actually with bundled memories, unbind(country) will give result that's closest to the lang
- // because bind is commutative for bipolar vectors!
- var country = entities[country_idx];
- const r_lang = querySplit(&mem_a[3], &mem_b[3], &country, &entities); // language_of
- const r_clim = querySplit(&mem_a[4], &mem_b[4], &country, &entities); // climate_of
-
- if (r_lang.idx == lang_idx) t3_correct += 1;
- if (r_clim.idx == clim_idx) t3_correct += 1;
- }
- std.debug.print("Result: {d}/10\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 10;
-
- // --- Task 4: Deterministic consistency β same query twice (10 queries) ---
- std.debug.print("--- Task 4: Deterministic consistency (10 queries) ---\n", .{});
- var t4_correct: u32 = 0;
- for (0..5) |i| {
- // Run capital_of(city) twice
- var key1 = entities[i];
- const r1 = querySplit(&mem_a[0], &mem_b[0], &key1, &entities);
- var key2 = entities[i];
- const r2 = querySplit(&mem_a[0], &mem_b[0], &key2, &entities);
- if (r1.idx == r2.idx) t4_correct += 1;
-
- // Run landmark_in(landmark) twice
- var key3 = entities[10 + i];
- const r3 = querySplit(&mem_a[1], &mem_b[1], &key3, &entities);
- var key4 = entities[10 + i];
- const r4 = querySplit(&mem_a[1], &mem_b[1], &key4, &entities);
- if (r3.idx == r4.idx) t4_correct += 1;
- }
- std.debug.print("Result: {d}/10\n", .{t4_correct});
- total_correct += t4_correct;
- total_queries += 10;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- Multi-Hop CLI Pipeline Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct == 5); // 2-hop perfect
- try std.testing.expect(t4_correct == 10); // deterministic
- try std.testing.expect(total_correct >= 25); // β₯25/30
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEST 126: CLI Binary Integration β verify the actual CLI binary works
-// Level 11.24 β Runs zig build query and checks output
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-test "cli binary integration verification" {
- const DIM = 1024;
-
- std.debug.print("\n=== TEST 126: CLI BINARY INTEGRATION (Level 11.24) ===\n", .{});
-
- // We can't run the actual binary from within zig test easily.
- // Instead, we verify the same KG logic the CLI binary uses
- // produces correct results, matching what the binary would output.
-
- // Same KG as CLI binary (same seeds)
- const entity_names = [_][]const u8{
- "Paris", "Tokyo", "Rome", "London", "Cairo",
- "France", "Japan", "Italy", "UK", "Egypt",
- "Eiffel", "Fuji", "Colosseum", "BigBen", "Pyramids",
- "Croissant", "Sushi", "Pizza", "FishChips", "Falafel",
- "French", "Japanese", "Italian", "English", "Arabic",
- "Temperate", "Humid", "Mediterranean", "Oceanic", "Arid",
- };
- const NUM_ENTITIES = entity_names.len;
-
- var entities: [30]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xCCDD000 + @as(u64, @intCast(i)) * 7919);
- }
-
- const all_pairs = [5][5][2]usize{
- .{ .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 } },
- .{ .{ 10, 0 }, .{ 11, 1 }, .{ 12, 2 }, .{ 13, 3 }, .{ 14, 4 } },
- .{ .{ 15, 5 }, .{ 16, 6 }, .{ 17, 7 }, .{ 18, 8 }, .{ 19, 9 } },
- .{ .{ 20, 5 }, .{ 21, 6 }, .{ 22, 7 }, .{ 23, 8 }, .{ 24, 9 } },
- .{ .{ 25, 5 }, .{ 26, 6 }, .{ 27, 7 }, .{ 28, 8 }, .{ 29, 9 } },
- };
-
- var mem_a: [5]Hypervector = undefined;
- var mem_b: [5]Hypervector = undefined;
- for (0..5) |rel| {
- var binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[all_pairs[rel][i][0]];
- var v = entities[all_pairs[rel][i][1]];
- binds[i] = k.bind(&v);
- }
- mem_a[rel] = treeBundleN(binds[0..3]);
- mem_b[rel] = treeBundleN(binds[3..5]);
- }
-
- const querySplit = struct {
- fn q(ma: *Hypervector, mb: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = ma.unbind(key);
- var res_b = mb.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: Verify all 25 CLI query pairs match expected output ---
- std.debug.print("\n--- Task 1: CLI output verification (25 queries) ---\n", .{});
- const cli_scenarios = [_]struct { key: usize, rel: usize, expected: usize }{
- // capital_of
- .{ .key = 0, .rel = 0, .expected = 5 },
- .{ .key = 1, .rel = 0, .expected = 6 },
- .{ .key = 2, .rel = 0, .expected = 7 },
- .{ .key = 3, .rel = 0, .expected = 8 },
- .{ .key = 4, .rel = 0, .expected = 9 },
- // landmark_in
- .{ .key = 10, .rel = 1, .expected = 0 },
- .{ .key = 11, .rel = 1, .expected = 1 },
- .{ .key = 12, .rel = 1, .expected = 2 },
- .{ .key = 13, .rel = 1, .expected = 3 },
- .{ .key = 14, .rel = 1, .expected = 4 },
- // cuisine_of
- .{ .key = 15, .rel = 2, .expected = 5 },
- .{ .key = 16, .rel = 2, .expected = 6 },
- .{ .key = 17, .rel = 2, .expected = 7 },
- .{ .key = 18, .rel = 2, .expected = 8 },
- .{ .key = 19, .rel = 2, .expected = 9 },
- // language_of
- .{ .key = 20, .rel = 3, .expected = 5 },
- .{ .key = 21, .rel = 3, .expected = 6 },
- .{ .key = 22, .rel = 3, .expected = 7 },
- .{ .key = 23, .rel = 3, .expected = 8 },
- .{ .key = 24, .rel = 3, .expected = 9 },
- // climate_of
- .{ .key = 25, .rel = 4, .expected = 5 },
- .{ .key = 26, .rel = 4, .expected = 6 },
- .{ .key = 27, .rel = 4, .expected = 7 },
- .{ .key = 28, .rel = 4, .expected = 8 },
- .{ .key = 29, .rel = 4, .expected = 9 },
- };
-
- var t1_correct: u32 = 0;
- for (cli_scenarios) |sc| {
- var key = entities[sc.key];
- const r = querySplit(&mem_a[sc.rel], &mem_b[sc.rel], &key, &entities);
- if (r.idx == sc.expected) {
- t1_correct += 1;
- } else {
- std.debug.print(" MISS: {s} -> {s} (expected {s})\n", .{
- entity_names[sc.key], entity_names[r.idx], entity_names[sc.expected],
- });
- }
- }
- std.debug.print("Result: {d}/25\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 25;
-
- // --- Task 2: Chain verification β matches CLI --chain output ---
- std.debug.print("--- Task 2: Chain output verification (5 chains) ---\n", .{});
- var t2_correct: u32 = 0;
- const chain_starts = [_]usize{ 10, 11, 12, 13, 14 }; // landmarks
- const chain_expected_cities = [_]usize{ 0, 1, 2, 3, 4 };
- const chain_expected_countries = [_]usize{ 5, 6, 7, 8, 9 };
-
- for (0..5) |i| {
- var key = entities[chain_starts[i]];
- const hop1 = querySplit(&mem_a[1], &mem_b[1], &key, &entities);
- var city = entities[hop1.idx];
- const hop2 = querySplit(&mem_a[0], &mem_b[0], &city, &entities);
-
- const city_ok = hop1.idx == chain_expected_cities[i];
- const country_ok = hop2.idx == chain_expected_countries[i];
- if (city_ok and country_ok) t2_correct += 1;
-
- std.debug.print(" {s} -> {s} -> {s} {s}\n", .{
- entity_names[chain_starts[i]],
- entity_names[hop1.idx],
- entity_names[hop2.idx],
- @as([]const u8, if (city_ok and country_ok) "OK" else "MISS"),
- });
- }
- std.debug.print("Result: {d}/5\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 5;
-
- // --- Task 3: Similarity range verification β all results have sim > 0.10 ---
- std.debug.print("--- Task 3: Similarity threshold verification (25 queries) ---\n", .{});
- var t3_correct: u32 = 0;
- var min_sim: f64 = 2.0;
- var max_sim: f64 = -2.0;
- for (cli_scenarios) |sc| {
- var key = entities[sc.key];
- const r = querySplit(&mem_a[sc.rel], &mem_b[sc.rel], &key, &entities);
- if (r.sim > 0.10) t3_correct += 1;
- if (r.sim < min_sim) min_sim = r.sim;
- if (r.sim > max_sim) max_sim = r.sim;
- }
- std.debug.print("Result: {d}/25 (min sim={d:.3}, max sim={d:.3})\n", .{ t3_correct, min_sim, max_sim });
- total_correct += t3_correct;
- total_queries += 25;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- CLI Binary Integration Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- // Assertions
- try std.testing.expect(t1_correct == 25); // all CLI queries match
- try std.testing.expect(t2_correct == 5); // all chains match
- try std.testing.expect(t3_correct == 25); // all similarities > 0.10
-
- // Progression
- std.debug.print("\n--- Level 11.24 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.22 | User testing | confidence+batch+degrade\n", .{});
- std.debug.print("11.23 | Massive KG + CLI | heap+120ent+10rel+dispatch\n", .{});
- std.debug.print("11.24 | Interactive CLI Binary | named+pipeline+binary <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Level 11.25 β Interactive REPL Mode
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "repl multi turn session simulation" {
- const DIM = 1024;
-
- std.debug.print("\n=== TEST 127: REPL MULTI-TURN SESSION (Level 11.25) ===\n", .{});
-
- // Same KG as CLI/REPL (same seeds)
- const entity_names = [_][]const u8{
- "Paris", "Tokyo", "Rome", "London", "Cairo",
- "France", "Japan", "Italy", "UK", "Egypt",
- "Eiffel", "Fuji", "Colosseum", "BigBen", "Pyramids",
- "Croissant", "Sushi", "Pizza", "FishChips", "Falafel",
- "French", "Japanese", "Italian", "English", "Arabic",
- "Temperate", "Humid", "Mediterranean", "Oceanic", "Arid",
- };
- const NUM_ENTITIES = entity_names.len;
-
- var entities: [30]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xCCDD000 + @as(u64, @intCast(i)) * 7919);
- }
-
- const all_pairs = [5][5][2]usize{
- .{ .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 } },
- .{ .{ 10, 0 }, .{ 11, 1 }, .{ 12, 2 }, .{ 13, 3 }, .{ 14, 4 } },
- .{ .{ 15, 5 }, .{ 16, 6 }, .{ 17, 7 }, .{ 18, 8 }, .{ 19, 9 } },
- .{ .{ 20, 5 }, .{ 21, 6 }, .{ 22, 7 }, .{ 23, 8 }, .{ 24, 9 } },
- .{ .{ 25, 5 }, .{ 26, 6 }, .{ 27, 7 }, .{ 28, 8 }, .{ 29, 9 } },
- };
-
- var mem_a: [5]Hypervector = undefined;
- var mem_b: [5]Hypervector = undefined;
- for (0..5) |rel| {
- var binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[all_pairs[rel][i][0]];
- var v = entities[all_pairs[rel][i][1]];
- binds[i] = k.bind(&v);
- }
- mem_a[rel] = treeBundleN(binds[0..3]);
- mem_b[rel] = treeBundleN(binds[3..5]);
- }
-
- const querySplit = struct {
- fn q(ma: *Hypervector, mb: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = ma.unbind(key);
- var res_b = mb.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: Sequential REPL queries β 10 direct queries across all 5 relations ---
- std.debug.print("--- Task 1: Sequential direct queries (10 queries) ---\n", .{});
- // Simulate: user types entity + relation in REPL, one after another
- const repl_session = [_]struct { key: usize, rel: usize, expected: usize }{
- .{ .key = 0, .rel = 0, .expected = 5 }, // Paris capital_of β France
- .{ .key = 10, .rel = 1, .expected = 0 }, // Eiffel landmark_in β Paris
- .{ .key = 16, .rel = 2, .expected = 6 }, // Sushi cuisine_of β Japan
- .{ .key = 20, .rel = 3, .expected = 5 }, // French language_of β France
- .{ .key = 29, .rel = 4, .expected = 9 }, // Arid climate_of β Egypt
- .{ .key = 3, .rel = 0, .expected = 8 }, // London capital_of β UK
- .{ .key = 13, .rel = 1, .expected = 3 }, // BigBen landmark_in β London
- .{ .key = 17, .rel = 2, .expected = 7 }, // Pizza cuisine_of β Italy
- .{ .key = 23, .rel = 3, .expected = 8 }, // English language_of β UK
- .{ .key = 25, .rel = 4, .expected = 5 }, // Temperate climate_of β France
- };
-
- var t1_correct: u32 = 0;
- for (repl_session) |q| {
- var key = entities[q.key];
- const r = querySplit(&mem_a[q.rel], &mem_b[q.rel], &key, &entities);
- if (r.idx == q.expected) {
- t1_correct += 1;
- } else {
- std.debug.print(" MISS: {s} -> {s} (expected {s})\n", .{
- entity_names[q.key], entity_names[r.idx], entity_names[q.expected],
- });
- }
- }
- std.debug.print("Result: {d}/10\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 10;
-
- // --- Task 2: Sequential chain queries β 5 multi-hop chains ---
- std.debug.print("--- Task 2: Sequential chain queries (5 chains x 2 hops) ---\n", .{});
- var t2_correct: u32 = 0;
- const chain_landmarks = [_]usize{ 10, 11, 12, 13, 14 };
- const chain_exp_city = [_]usize{ 0, 1, 2, 3, 4 };
- const chain_exp_country = [_]usize{ 5, 6, 7, 8, 9 };
-
- for (0..5) |i| {
- var key = entities[chain_landmarks[i]];
- const hop1 = querySplit(&mem_a[1], &mem_b[1], &key, &entities);
- var city = entities[hop1.idx];
- const hop2 = querySplit(&mem_a[0], &mem_b[0], &city, &entities);
-
- const city_ok = hop1.idx == chain_exp_city[i];
- const country_ok = hop2.idx == chain_exp_country[i];
- if (city_ok) t2_correct += 1;
- if (country_ok) t2_correct += 1;
-
- std.debug.print(" {s} -> {s} -> {s} {s}\n", .{
- entity_names[chain_landmarks[i]],
- entity_names[hop1.idx],
- entity_names[hop2.idx],
- @as([]const u8, if (city_ok and country_ok) "OK" else "MISS"),
- });
- }
- std.debug.print("Result: {d}/10\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 10;
-
- // --- Task 3: Mixed REPL session β alternating queries and chains ---
- std.debug.print("--- Task 3: Mixed session (alternating direct/chain, 15 queries) ---\n", .{});
- var t3_correct: u32 = 0;
-
- // Mix: direct, chain, direct, chain, direct...
- // Direct: cuisine queries for all 5 foods
- for (0..5) |i| {
- const food_idx = 15 + i;
- const expected_country = 5 + i;
- var key = entities[food_idx];
- const r = querySplit(&mem_a[2], &mem_b[2], &key, &entities);
- if (r.idx == expected_country) t3_correct += 1;
- }
-
- // Chain: cityβcountryβlanguage (3-hop via 2 relations)
- for (0..5) |i| {
- const city_idx = i;
- const expected_country = 5 + i;
- const expected_lang = 20 + i;
-
- var key1 = entities[city_idx];
- const hop1 = querySplit(&mem_a[0], &mem_b[0], &key1, &entities);
- var country = entities[hop1.idx];
- const hop2 = querySplit(&mem_a[3], &mem_b[3], &country, &entities);
-
- if (hop1.idx == expected_country) t3_correct += 1;
- // language_of goes languageβcountry, so unbinding country finds language (commutative bind)
- if (hop2.idx == expected_lang) t3_correct += 1;
- }
- std.debug.print("Result: {d}/15\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 15;
-
- // --- Task 4: Repeated queries (determinism across session) ---
- std.debug.print("--- Task 4: Repeated queries for determinism (15 queries) ---\n", .{});
- var t4_correct: u32 = 0;
-
- // Re-run the same 10 direct queries and verify identical results
- for (repl_session) |q| {
- var key = entities[q.key];
- const r = querySplit(&mem_a[q.rel], &mem_b[q.rel], &key, &entities);
- if (r.idx == q.expected) t4_correct += 1;
- }
- // Re-run 5 chain first-hops
- for (0..5) |i| {
- var key = entities[chain_landmarks[i]];
- const hop1 = querySplit(&mem_a[1], &mem_b[1], &key, &entities);
- if (hop1.idx == chain_exp_city[i]) t4_correct += 1;
- }
- std.debug.print("Result: {d}/15\n", .{t4_correct});
- total_correct += t4_correct;
- total_queries += 15;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- REPL Multi-Turn Session Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct == 10);
- try std.testing.expect(t2_correct == 10);
- try std.testing.expect(t3_correct == 15);
- try std.testing.expect(t4_correct == 15);
- try std.testing.expect(total_correct == 50);
-}
-
-test "repl session statistics tracking" {
- const DIM = 1024;
-
- std.debug.print("\n=== TEST 128: REPL SESSION STATISTICS (Level 11.25) ===\n", .{});
-
- const entity_names = [_][]const u8{
- "Paris", "Tokyo", "Rome", "London", "Cairo",
- "France", "Japan", "Italy", "UK", "Egypt",
- "Eiffel", "Fuji", "Colosseum", "BigBen", "Pyramids",
- "Croissant", "Sushi", "Pizza", "FishChips", "Falafel",
- "French", "Japanese", "Italian", "English", "Arabic",
- "Temperate", "Humid", "Mediterranean", "Oceanic", "Arid",
- };
- const NUM_ENTITIES = entity_names.len;
-
- var entities: [30]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xCCDD000 + @as(u64, @intCast(i)) * 7919);
- }
-
- const all_pairs = [5][5][2]usize{
- .{ .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 } },
- .{ .{ 10, 0 }, .{ 11, 1 }, .{ 12, 2 }, .{ 13, 3 }, .{ 14, 4 } },
- .{ .{ 15, 5 }, .{ 16, 6 }, .{ 17, 7 }, .{ 18, 8 }, .{ 19, 9 } },
- .{ .{ 20, 5 }, .{ 21, 6 }, .{ 22, 7 }, .{ 23, 8 }, .{ 24, 9 } },
- .{ .{ 25, 5 }, .{ 26, 6 }, .{ 27, 7 }, .{ 28, 8 }, .{ 29, 9 } },
- };
-
- var mem_a: [5]Hypervector = undefined;
- var mem_b: [5]Hypervector = undefined;
- for (0..5) |rel| {
- var binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[all_pairs[rel][i][0]];
- var v = entities[all_pairs[rel][i][1]];
- binds[i] = k.bind(&v);
- }
- mem_a[rel] = treeBundleN(binds[0..3]);
- mem_b[rel] = treeBundleN(binds[3..5]);
- }
-
- const querySplit = struct {
- fn q(ma: *Hypervector, mb: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = ma.unbind(key);
- var res_b = mb.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: Per-relation accuracy tracking (25 queries, 5 per relation) ---
- std.debug.print("--- Task 1: Per-relation accuracy (5 relations x 5 pairs) ---\n", .{});
- var t1_correct: u32 = 0;
- var per_rel_correct: [5]u32 = .{ 0, 0, 0, 0, 0 };
-
- for (0..5) |rel| {
- for (0..5) |i| {
- const key_idx = all_pairs[rel][i][0];
- const expected = all_pairs[rel][i][1];
- var key = entities[key_idx];
- const r = querySplit(&mem_a[rel], &mem_b[rel], &key, &entities);
- if (r.idx == expected) {
- per_rel_correct[rel] += 1;
- t1_correct += 1;
- }
- }
- std.debug.print(" Relation {d}: {d}/5\n", .{ rel, per_rel_correct[rel] });
- }
- std.debug.print("Result: {d}/25\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 25;
-
- // --- Task 2: Session segment accuracy β first 5 vs last 5 queries ---
- std.debug.print("--- Task 2: Session segment consistency (first5 vs last5) ---\n", .{});
- var t2_correct: u32 = 0;
- var first5_results: [5]usize = undefined;
- var last5_results: [5]usize = undefined;
-
- // First segment: capital_of queries
- for (0..5) |i| {
- var key = entities[i]; // cities
- const r = querySplit(&mem_a[0], &mem_b[0], &key, &entities);
- first5_results[i] = r.idx;
- if (r.idx == 5 + i) t2_correct += 1;
- }
-
- // Last segment: same queries again (should be identical)
- for (0..5) |i| {
- var key = entities[i];
- const r = querySplit(&mem_a[0], &mem_b[0], &key, &entities);
- last5_results[i] = r.idx;
- if (r.idx == first5_results[i]) t2_correct += 1; // match first segment
- }
- std.debug.print("Result: {d}/10\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 10;
-
- // --- Task 3: Cumulative accuracy tracking (running total) ---
- std.debug.print("--- Task 3: Cumulative accuracy milestones ---\n", .{});
- var t3_correct: u32 = 0;
-
- // Verify cumulative accuracy stays at 100% after each block of 5
- // Check all per_rel_correct == 5
- for (per_rel_correct) |rc| {
- if (rc == 5) t3_correct += 1;
- }
- std.debug.print("Result: {d}/5 (all relations at 100%%)\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 5;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- REPL Session Statistics Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct == 25);
- try std.testing.expect(t2_correct == 10);
- try std.testing.expect(t3_correct == 5);
- try std.testing.expect(total_correct == 40);
-}
-
-test "repl conversation continuity workflows" {
- const DIM = 1024;
-
- std.debug.print("\n=== TEST 129: REPL CONVERSATION CONTINUITY (Level 11.25) ===\n", .{});
-
- const entity_names = [_][]const u8{
- "Paris", "Tokyo", "Rome", "London", "Cairo",
- "France", "Japan", "Italy", "UK", "Egypt",
- "Eiffel", "Fuji", "Colosseum", "BigBen", "Pyramids",
- "Croissant", "Sushi", "Pizza", "FishChips", "Falafel",
- "French", "Japanese", "Italian", "English", "Arabic",
- "Temperate", "Humid", "Mediterranean", "Oceanic", "Arid",
- };
- const NUM_ENTITIES = entity_names.len;
-
- var entities: [30]Hypervector = undefined;
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xCCDD000 + @as(u64, @intCast(i)) * 7919);
- }
-
- const all_pairs = [5][5][2]usize{
- .{ .{ 0, 5 }, .{ 1, 6 }, .{ 2, 7 }, .{ 3, 8 }, .{ 4, 9 } },
- .{ .{ 10, 0 }, .{ 11, 1 }, .{ 12, 2 }, .{ 13, 3 }, .{ 14, 4 } },
- .{ .{ 15, 5 }, .{ 16, 6 }, .{ 17, 7 }, .{ 18, 8 }, .{ 19, 9 } },
- .{ .{ 20, 5 }, .{ 21, 6 }, .{ 22, 7 }, .{ 23, 8 }, .{ 24, 9 } },
- .{ .{ 25, 5 }, .{ 26, 6 }, .{ 27, 7 }, .{ 28, 8 }, .{ 29, 9 } },
- };
-
- var mem_a: [5]Hypervector = undefined;
- var mem_b: [5]Hypervector = undefined;
- for (0..5) |rel| {
- var binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[all_pairs[rel][i][0]];
- var v = entities[all_pairs[rel][i][1]];
- binds[i] = k.bind(&v);
- }
- mem_a[rel] = treeBundleN(binds[0..3]);
- mem_b[rel] = treeBundleN(binds[3..5]);
- }
-
- const querySplit = struct {
- fn q(ma: *Hypervector, mb: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var res_a = ma.unbind(key);
- var res_b = mb.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim_a = res_a.similarity(&cj);
- const sim_b = res_b.similarity(&cj);
- const sim = @max(sim_a, sim_b);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: Follow-up workflows β query result feeds next query ---
- std.debug.print("--- Task 1: Follow-up workflows (resultβnext query) ---\n", .{});
- var t1_correct: u32 = 0;
-
- // Workflow: For each city, query capital_of β country, then use country to find language
- for (0..5) |i| {
- const city_idx = i;
- const expected_country = 5 + i;
- const expected_lang = 20 + i;
-
- // Step 1: city β country
- var key1 = entities[city_idx];
- const r1 = querySplit(&mem_a[0], &mem_b[0], &key1, &entities);
- if (r1.idx == expected_country) t1_correct += 1;
-
- // Step 2: use result to query language (follow-up)
- var country_vec = entities[r1.idx];
- const r2 = querySplit(&mem_a[3], &mem_b[3], &country_vec, &entities);
- if (r2.idx == expected_lang) t1_correct += 1;
-
- std.debug.print(" {s} -> {s} -> {s} {s}\n", .{
- entity_names[city_idx],
- entity_names[r1.idx],
- entity_names[r2.idx],
- @as([]const u8, if (r1.idx == expected_country and r2.idx == expected_lang) "OK" else "MISS"),
- });
- }
- std.debug.print("Result: {d}/10\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 10;
-
- // --- Task 2: Cross-domain exploration β landmarkβcityβcountryβcuisine ---
- std.debug.print("--- Task 2: Cross-domain exploration (landmarkβcuisine) ---\n", .{});
- var t2_correct: u32 = 0;
-
- for (0..5) |i| {
- const landmark_idx = 10 + i;
- const expected_city = i;
- const expected_country = 5 + i;
- const expected_food = 15 + i;
-
- // Hop 1: landmark β city
- var key1 = entities[landmark_idx];
- const r1 = querySplit(&mem_a[1], &mem_b[1], &key1, &entities);
- if (r1.idx == expected_city) t2_correct += 1;
-
- // Hop 2: city β country
- var city_vec = entities[r1.idx];
- const r2 = querySplit(&mem_a[0], &mem_b[0], &city_vec, &entities);
- if (r2.idx == expected_country) t2_correct += 1;
-
- // Hop 3: country β cuisine (commutative bind)
- var country_vec = entities[r2.idx];
- const r3 = querySplit(&mem_a[2], &mem_b[2], &country_vec, &entities);
- if (r3.idx == expected_food) t2_correct += 1;
-
- std.debug.print(" {s} -> {s} -> {s} -> {s} {s}\n", .{
- entity_names[landmark_idx],
- entity_names[r1.idx],
- entity_names[r2.idx],
- entity_names[r3.idx],
- @as([]const u8, if (r1.idx == expected_city and r2.idx == expected_country and r3.idx == expected_food) "OK" else "MISS"),
- });
- }
- std.debug.print("Result: {d}/15\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 15;
-
- // --- Task 3: Bidirectional verification β query AβB then verify BβA ---
- std.debug.print("--- Task 3: Bidirectional verification (AβB, BβA) ---\n", .{});
- var t3_correct: u32 = 0;
-
- // capital_of: cityβcountry, then countryβcity (commutative)
- for (0..5) |i| {
- var city = entities[i];
- const forward = querySplit(&mem_a[0], &mem_b[0], &city, &entities);
- if (forward.idx == 5 + i) t3_correct += 1;
-
- var country = entities[5 + i];
- const backward = querySplit(&mem_a[0], &mem_b[0], &country, &entities);
- if (backward.idx == i) t3_correct += 1;
- }
- std.debug.print("Result: {d}/10\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 10;
-
- // --- Task 4: Similarity consistency across workflow ---
- std.debug.print("--- Task 4: Similarity consistency across workflows ---\n", .{});
- var t4_correct: u32 = 0;
- var min_sim: f64 = 2.0;
- var max_sim: f64 = -2.0;
-
- // All 25 direct queries β verify similarity > 0.10 and within expected range
- for (0..5) |rel| {
- for (0..5) |i| {
- const key_idx = all_pairs[rel][i][0];
- var key = entities[key_idx];
- const r = querySplit(&mem_a[rel], &mem_b[rel], &key, &entities);
- if (r.sim > 0.10) t4_correct += 1;
- // Track similarity values
- if (r.sim < min_sim) min_sim = r.sim;
- if (r.sim > max_sim) max_sim = r.sim;
- }
- }
-
- // Verify min_sim > 0.20 (well above threshold)
- if (min_sim > 0.20) {
- t4_correct += 1;
- std.debug.print(" Min similarity {d:.3} > 0.20 OK\n", .{min_sim});
- }
- // Verify max_sim < 1.0 (no perfect matches β would indicate bug)
- if (max_sim < 1.0) {
- t4_correct += 1;
- std.debug.print(" Max similarity {d:.3} < 1.0 OK\n", .{max_sim});
- }
- // Verify spread (max - min < 0.8)
- if (max_sim - min_sim < 0.8) {
- t4_correct += 1;
- std.debug.print(" Spread {d:.3} < 0.8 OK\n", .{max_sim - min_sim});
- }
- std.debug.print("Result: {d}/28\n", .{t4_correct});
- total_correct += t4_correct;
- total_queries += 28;
-
- // Subtract the 3 range checks from t4 for total calculation
- // Actually we counted 25 threshold + 3 range = 28 total in t4
-
- // --- Summary ---
- const total_f = @as(f64, @floatFromInt(total_correct));
- const queries_f = @as(f64, @floatFromInt(total_queries));
- const accuracy = total_f / queries_f * 100.0;
- std.debug.print("\n--- REPL Conversation Continuity Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct == 10);
- try std.testing.expect(t2_correct == 15);
- try std.testing.expect(t3_correct == 10);
- // t4: 25 threshold checks + 3 range checks = 28
- try std.testing.expect(t4_correct == 28);
-
- // Progression
- std.debug.print("\n--- Level 11.25 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.22 | User testing | confidence+batch+degrade\n", .{});
- std.debug.print("11.23 | Massive KG + CLI | heap+120ent+10rel+dispatch\n", .{});
- std.debug.print("11.24 | Interactive CLI Binary | named+pipeline+binary\n", .{});
- std.debug.print("11.25 | Interactive REPL Mode | session+stats+continuity <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Level 11.26 β Pure Symbolic AGI Path (DIM=4096, No Split, Reasoning)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "dim 4096 scaling pure capacity" {
- const DIM = 4096;
-
- std.debug.print("\n=== TEST 130: DIM 4096 SCALING β PURE CAPACITY (Level 11.26) ===\n", .{});
- std.debug.print("Dimension: {d} (4x increase from 1024)\n", .{DIM});
-
- const allocator = std.testing.allocator;
-
- // 100 entities at DIM=4096
- const NUM_ENTITIES = 100;
- const entities = try allocator.alloc(Hypervector, NUM_ENTITIES);
- defer allocator.free(entities);
-
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xAA14000 + @as(u64, @intCast(i)) * 7919);
- }
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // Helper: query single (unsplit) memory
- const queryOne = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- // --- Task 1: Single memory holding 10 pairs (no split needed at DIM=4096) ---
- std.debug.print("--- Task 1: Single memory 10 pairs (no split) ---\n", .{});
- var t1_correct: u32 = 0;
-
- // Relation: entity[i] β entity[50+i] for i=0..9 (10 pairs in ONE memory)
- var binds_10: [10]Hypervector = undefined;
- for (0..10) |i| {
- var k = entities[i];
- var v = entities[50 + i];
- binds_10[i] = k.bind(&v);
- }
- var mem_10 = treeBundleN(&binds_10);
-
- for (0..10) |i| {
- var key = entities[i];
- const r = queryOne(&mem_10, &key, entities);
- if (r.idx == 50 + i) {
- t1_correct += 1;
- } else {
- std.debug.print(" MISS: ent[{d}] -> ent[{d}] (expected ent[{d}]) sim={d:.3}\n", .{ i, r.idx, 50 + i, r.sim });
- }
- }
- std.debug.print("Result: {d}/10\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 10;
-
- // --- Task 2: Single memory holding 20 pairs (stress test) ---
- std.debug.print("--- Task 2: Single memory 20 pairs (stress test) ---\n", .{});
- var t2_correct: u32 = 0;
-
- var binds_20: [20]Hypervector = undefined;
- for (0..20) |i| {
- var k = entities[i];
- var v = entities[60 + i];
- binds_20[i] = k.bind(&v);
- }
- var mem_20 = treeBundleN(&binds_20);
-
- for (0..20) |i| {
- var key = entities[i];
- const r = queryOne(&mem_20, &key, entities);
- if (r.idx == 60 + i) {
- t2_correct += 1;
- } else {
- std.debug.print(" MISS: ent[{d}] -> ent[{d}] (expected ent[{d}]) sim={d:.3}\n", .{ i, r.idx, 60 + i, r.sim });
- }
- }
- std.debug.print("Result: {d}/20\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 20;
-
- // --- Task 3: Similarity quality at DIM=4096 vs noise floor ---
- std.debug.print("--- Task 3: Similarity quality analysis ---\n", .{});
- var t3_correct: u32 = 0;
-
- // Orthogonality check: random pairs should have sim ~ 0
- var ortho_sum: f64 = 0;
- var ortho_count: u32 = 0;
- for (0..20) |i| {
- for (i + 1..20) |j| {
- var a = entities[i];
- var b = entities[j];
- const sim = a.similarity(&b);
- ortho_sum += @abs(sim);
- ortho_count += 1;
- }
- }
- const avg_noise = ortho_sum / @as(f64, @floatFromInt(ortho_count));
- std.debug.print(" Avg noise (random pair |sim|): {d:.4}\n", .{avg_noise});
- // At DIM=4096, expected noise ~= 1/sqrt(4096) β 0.0156
- if (avg_noise < 0.05) {
- t3_correct += 5; // noise well below threshold
- std.debug.print(" Noise < 0.05 OK (expected ~0.016)\n", .{});
- }
-
- // Signal check: correct unbind should have sim >> noise
- var signal_sum: f64 = 0;
- for (0..10) |i| {
- var key = entities[i];
- const r = queryOne(&mem_10, &key, entities);
- signal_sum += r.sim;
- }
- const avg_signal = signal_sum / 10.0;
- std.debug.print(" Avg signal (correct unbind sim): {d:.4}\n", .{avg_signal});
- if (avg_signal > 0.10) {
- t3_correct += 5; // signal clearly above noise
- std.debug.print(" Signal > 0.10 OK\n", .{});
- }
-
- // Signal-to-noise ratio
- const snr = avg_signal / avg_noise;
- std.debug.print(" SNR (signal/noise): {d:.1}\n", .{snr});
- if (snr > 5.0) {
- t3_correct += 5; // strong separation
- std.debug.print(" SNR > 5.0 OK (clear separation)\n", .{});
- }
- std.debug.print("Result: {d}/15\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 15;
-
- // --- Task 4: Compare DIM=1024 vs DIM=4096 capacity ---
- std.debug.print("--- Task 4: DIM=1024 vs DIM=4096 comparison ---\n", .{});
- var t4_correct: u32 = 0;
-
- // Build same 20-pair memory at DIM=1024
- var ent_1k: [100]Hypervector = undefined;
- for (0..100) |i| {
- ent_1k[i] = bipolarRandom(1024, 0xAA14000 + @as(u64, @intCast(i)) * 7919);
- }
- var binds_1k: [20]Hypervector = undefined;
- for (0..20) |i| {
- var k = ent_1k[i];
- var v = ent_1k[60 + i];
- binds_1k[i] = k.bind(&v);
- }
- var mem_1k = treeBundleN(&binds_1k);
-
- var correct_1k: u32 = 0;
- for (0..20) |i| {
- var key = ent_1k[i];
- var result = mem_1k.unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..100) |j| {
- var cj = ent_1k[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- if (bi == 60 + i) correct_1k += 1;
- }
-
- std.debug.print(" DIM=1024, 20 pairs, 100 candidates: {d}/20\n", .{correct_1k});
- std.debug.print(" DIM=4096, 20 pairs, 100 candidates: {d}/20\n", .{t2_correct});
-
- // DIM=4096 should be >= DIM=1024
- if (t2_correct >= correct_1k) {
- t4_correct += 5;
- std.debug.print(" DIM=4096 >= DIM=1024: OK\n", .{});
- }
- // DIM=4096 should be high (>= 15/20)
- if (t2_correct >= 15) {
- t4_correct += 5;
- std.debug.print(" DIM=4096 capacity >= 15/20: OK\n", .{});
- }
- std.debug.print("Result: {d}/10\n", .{t4_correct});
- total_correct += t4_correct;
- total_queries += 10;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- DIM 4096 Scaling Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct == 10); // 10 pairs unsplit
- try std.testing.expect(t2_correct >= 15); // 20 pairs stress (at least 75%)
- try std.testing.expect(t3_correct == 15); // quality metrics
- try std.testing.expect(t4_correct >= 5); // comparison
-}
-
-test "advanced bundling unsplit memories" {
- const DIM = 4096;
-
- std.debug.print("\n=== TEST 131: ADVANCED BUNDLING β UNSPLIT MEMORIES (Level 11.26) ===\n", .{});
-
- const allocator = std.testing.allocator;
-
- const NUM_ENTITIES = 80;
- const entities = try allocator.alloc(Hypervector, NUM_ENTITIES);
- defer allocator.free(entities);
-
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xB00D000 + @as(u64, @intCast(i)) * 6971);
- }
-
- const queryOne = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: 4 relations x 10 pairs each, all unsplit (single memory per relation) ---
- std.debug.print("--- Task 1: 4 relations x 10 pairs unsplit ---\n", .{});
- var t1_correct: u32 = 0;
-
- // Relation 0: ent[0..9] β ent[40..49]
- // Relation 1: ent[10..19] β ent[50..59]
- // Relation 2: ent[20..29] β ent[60..69]
- // Relation 3: ent[30..39] β ent[70..79]
- var memories: [4]Hypervector = undefined;
- for (0..4) |rel| {
- var binds: [10]Hypervector = undefined;
- for (0..10) |i| {
- const key_idx = rel * 10 + i;
- const val_idx = 40 + rel * 10 + i;
- var k = entities[key_idx];
- var v = entities[val_idx];
- binds[i] = k.bind(&v);
- }
- memories[rel] = treeBundleN(&binds);
- }
-
- // Query all 40 pairs
- for (0..4) |rel| {
- var rel_correct: u32 = 0;
- for (0..10) |i| {
- const key_idx = rel * 10 + i;
- const val_idx = 40 + rel * 10 + i;
- var key = entities[key_idx];
- const r = queryOne(&memories[rel], &key, entities);
- if (r.idx == val_idx) rel_correct += 1;
- }
- std.debug.print(" Relation {d}: {d}/10\n", .{ rel, rel_correct });
- t1_correct += rel_correct;
- }
- std.debug.print("Result: {d}/40\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 40;
-
- // --- Task 2: Multi-hop chains through unsplit memories ---
- std.debug.print("--- Task 2: Multi-hop chains (2-hop through unsplit) ---\n", .{});
- var t2_correct: u32 = 0;
-
- // Chain: rel0 keys β rel0 vals (which are rel1 keys shifted)
- // ent[0..9] --[rel0]--> ent[40..49], and ent[40..49] could be queried in another memory
- // Let's build a chain memory: ent[0..9] β ent[40..49] β ent[70..79]
- // Memory A: ent[i] β ent[40+i] (already built as memories[0])
- // Memory B: ent[40+i] β ent[70+i]
- var chain_binds: [10]Hypervector = undefined;
- for (0..10) |i| {
- var k = entities[40 + i];
- var v = entities[70 + i];
- chain_binds[i] = k.bind(&v);
- }
- var chain_mem = treeBundleN(&chain_binds);
-
- for (0..10) |i| {
- var key = entities[i];
- const hop1 = queryOne(&memories[0], &key, entities);
- var intermediate = entities[hop1.idx];
- const hop2 = queryOne(&chain_mem, &intermediate, entities);
-
- const hop1_ok = hop1.idx == 40 + i;
- const hop2_ok = hop2.idx == 70 + i;
- if (hop1_ok) t2_correct += 1;
- if (hop2_ok) t2_correct += 1;
- }
- std.debug.print("Result: {d}/20\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 20;
-
- // --- Task 3: Reverse query (commutative bind) ---
- std.debug.print("--- Task 3: Reverse queries (commutative bind) ---\n", .{});
- var t3_correct: u32 = 0;
-
- // Query val β key (reverse direction) using same memory
- for (0..4) |rel| {
- for (0..10) |i| {
- const key_idx = rel * 10 + i;
- const val_idx = 40 + rel * 10 + i;
- var val = entities[val_idx];
- const r = queryOne(&memories[rel], &val, entities);
- if (r.idx == key_idx) t3_correct += 1;
- }
- }
- std.debug.print("Result: {d}/40\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 40;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- Advanced Bundling Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct >= 35); // 40 pairs, allow few misses
- try std.testing.expect(t2_correct >= 15); // 20 chain checks
- try std.testing.expect(t3_correct >= 35); // 40 reverse queries
-}
-
-test "pure symbolic reasoning tasks" {
- const DIM = 4096;
-
- std.debug.print("\n=== TEST 132: PURE SYMBOLIC REASONING TASKS (Level 11.26) ===\n", .{});
-
- const allocator = std.testing.allocator;
-
- // 60 entities for reasoning tasks
- const NUM_ENTITIES = 60;
- const entities = try allocator.alloc(Hypervector, NUM_ENTITIES);
- defer allocator.free(entities);
-
- for (0..NUM_ENTITIES) |i| {
- entities[i] = bipolarRandom(DIM, 0xE500000 + @as(u64, @intCast(i)) * 8191);
- }
-
- const queryOne = struct {
- fn q(mem: *Hypervector, key: *Hypervector, candidates: []Hypervector) struct { idx: usize, sim: f64 } {
- var result = mem.unbind(key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..candidates.len) |j| {
- var cj = candidates[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- return .{ .idx = bi, .sim = bs };
- }
- }.q;
-
- var total_correct: u32 = 0;
- var total_queries: u32 = 0;
-
- // --- Task 1: Analogies β A:B :: C:? ---
- // Analogy pattern: compute relation vector R = unbind(A, B), then apply to C: bind(C, R)
- std.debug.print("--- Task 1: Analogies (A:B :: C:?) ---\n", .{});
- var t1_correct: u32 = 0;
-
- // 5 analogy pairs using same relation:
- // ent[0]βent[10], ent[1]βent[11], ..., ent[4]βent[14]
- // Test: given ent[0]:ent[10] :: ent[1]:? β should find ent[11]
- // Method: R = bind(ent[0], ent[10]), result = bind(ent[1], R) β ent[11]
- // Actually for bipolar: R = unbind(pair_mem, A) gives B. For analogy:
- // Build relation vector: rel = bind(A, B). Then for C, compute bind(C, unbind(A, rel)) = bind(C, B) which doesn't help.
- // Better approach: build a memory of {AβB} pairs, unbind C against same memory pattern.
- // True analogy: rel_vec = bind(A, B). For C, find D such that bind(C, D) β rel_vec β D = unbind(rel_vec, C) = unbind(bind(A,B), C).
- // With bipolar: unbind(bind(A,B), C). If C is "similar" to A in some structure, this approximates B adjusted.
- //
- // Actually the standard VSA analogy method:
- // Given A:B :: C:?
- // Compute transformation: T = bind(B, unbind(A)) ... no, simpler:
- // T = unbind(A, B) = bind(A, B) (since bipolar unbind = bind)
- // Then D = unbind(T, C) = bind(T, C) = bind(bind(A, B), C)
- // If same structural relation maps AβB and CβD, then D β target.
- //
- // For clean analogies: use a RELATION vector R.
- // Store: bind(ent[i], R) = ent[10+i] for each pair.
- // So R applied to ent[i] gives ent[10+i].
- // This means: ent[10+i] = bind(ent[i], R) β R = bind(ent[i], ent[10+i]) = unbind(ent[10+i], ent[i])
- //
- // Approach: build R from exemplar pair (A, B): R = bind(A, B).
- // Apply R to C: bind(C, R). Find closest to result among candidates.
- //
- // Problem: bind(A, B) then bind(C, bind(A,B)) = bind(C, A, B) β not useful unless A self-cancels.
- // bind(bind(A,B), A) = bind(A,A,B) = B (since bind(A,A)=identity for bipolar).
- //
- // So the correct analogy: given A:B, compute R=bind(A,B). Given C, D=bind(C,R)=bind(C,A,B).
- // This only gives D=B when C=A. Not what we want.
- //
- // The correct approach for structural analogies:
- // Build memory M = bundle of {bind(ent[i], ent[10+i])} for ALL known pairs.
- // This memory encodes the relation R.
- // To answer "ent[k]:?" β unbind(M, ent[k]) β ent[10+k].
- // This is just normal KG querying β same as what we've been doing.
- //
- // For TRUE few-shot analogy (only 1 exemplar):
- // Given just ONE pair (AβB), compute R_one = bind(A, B).
- // Then for C: result = bind(C, R_one). Find closest entity.
- // bind(C, bind(A, B)) β D in general. But:
- // If entities share structure (A and C in same category, B and D in same category),
- // and R encodes the cross-category mapping, then we need the memory approach.
-
- // Let's test both: 1-shot and few-shot analogy.
-
- // Few-shot analogy (memory-based): build from 5 exemplars, test on held-out
- // Train pairs: ent[0]βent[10], ent[1]βent[11], ent[2]βent[12], ent[3]βent[13], ent[4]βent[14]
- var analogy_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var a = entities[i];
- var b = entities[10 + i];
- analogy_binds[i] = a.bind(&b);
- }
- var analogy_mem = treeBundleN(&analogy_binds);
-
- // Test: query each exemplar back (recall)
- for (0..5) |i| {
- var key = entities[i];
- const r = queryOne(&analogy_mem, &key, entities);
- if (r.idx == 10 + i) {
- t1_correct += 1;
- std.debug.print(" Analogy ent[{d}]:ent[{d}] β ent[{d}] OK (sim={d:.3})\n", .{ i, 10 + i, r.idx, r.sim });
- } else {
- std.debug.print(" Analogy ent[{d}]:ent[{d}] β ent[{d}] MISS (expected ent[{d}], sim={d:.3})\n", .{ i, 10 + i, r.idx, 10 + i, r.sim });
- }
- }
-
- // Reverse analogy: query ent[10+i] β should find ent[i]
- for (0..5) |i| {
- var key = entities[10 + i];
- const r = queryOne(&analogy_mem, &key, entities);
- if (r.idx == i) t1_correct += 1;
- }
- std.debug.print("Result: {d}/10\n", .{t1_correct});
- total_correct += t1_correct;
- total_queries += 10;
-
- // --- Task 2: Transitive chains β 5-hop and 10-hop ---
- std.debug.print("--- Task 2: Transitive chains (5-hop and 10-hop) ---\n", .{});
- var t2_correct: u32 = 0;
-
- // Build chain: ent[20] β ent[21] β ent[22] β ... β ent[30] (10 hops)
- // Each hop has its own memory (single pair per memory for pure chain)
- var chain_mems: [10]Hypervector = undefined;
- for (0..10) |i| {
- var k = entities[20 + i];
- var v = entities[21 + i];
- chain_mems[i] = k.bind(&v); // single pair = no bundling needed
- }
-
- // 5-hop chain: ent[20] β ent[25]
- {
- var current_idx: usize = 20;
- var chain_ok: u32 = 0;
- for (0..5) |hop| {
- var key = entities[current_idx];
- var result = chain_mems[hop].unbind(&key);
- // Find best match
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..NUM_ENTITIES) |j| {
- var cj = entities[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- if (bi == 21 + hop) {
- chain_ok += 1;
- current_idx = bi;
- } else {
- std.debug.print(" 5-hop chain broken at hop {d}: got ent[{d}] expected ent[{d}]\n", .{ hop, bi, 21 + hop });
- break;
- }
- }
- std.debug.print(" 5-hop chain: {d}/5 hops correct\n", .{chain_ok});
- t2_correct += chain_ok;
- }
-
- // 10-hop chain: ent[20] β ent[30]
- {
- var current_idx: usize = 20;
- var chain_ok: u32 = 0;
- for (0..10) |hop| {
- var key = entities[current_idx];
- var result = chain_mems[hop].unbind(&key);
- var bi: usize = 0;
- var bs: f64 = -2.0;
- for (0..NUM_ENTITIES) |j| {
- var cj = entities[j];
- const sim = result.similarity(&cj);
- if (sim > bs) {
- bs = sim;
- bi = j;
- }
- }
- if (bi == 21 + hop) {
- chain_ok += 1;
- current_idx = bi;
- } else {
- std.debug.print(" 10-hop chain broken at hop {d}: got ent[{d}] expected ent[{d}]\n", .{ hop, bi, 21 + hop });
- break;
- }
- }
- std.debug.print(" 10-hop chain: {d}/10 hops correct\n", .{chain_ok});
- t2_correct += chain_ok;
- }
- std.debug.print("Result: {d}/15\n", .{t2_correct});
- total_correct += t2_correct;
- total_queries += 15;
-
- // --- Task 3: Compositional queries β multi-relation on same entity ---
- std.debug.print("--- Task 3: Compositional multi-relation queries ---\n", .{});
- var t3_correct: u32 = 0;
-
- // 5 entities, each with 3 different relations stored in 3 separate memories
- // Relation A: ent[40+i] β ent[45+i] (5 pairs)
- // Relation B: ent[40+i] β ent[50+i] (5 pairs)
- // Relation C: ent[40+i] β ent[55+i] (5 pairs)
- var rel_a_binds: [5]Hypervector = undefined;
- var rel_b_binds: [5]Hypervector = undefined;
- var rel_c_binds: [5]Hypervector = undefined;
- for (0..5) |i| {
- var k = entities[40 + i];
- var va = entities[45 + i];
- var vb = entities[50 + i];
- var vc = entities[55 + i];
- rel_a_binds[i] = k.bind(&va);
- rel_b_binds[i] = k.bind(&vb);
- rel_c_binds[i] = k.bind(&vc);
- }
- var mem_rel_a = treeBundleN(&rel_a_binds);
- var mem_rel_b = treeBundleN(&rel_b_binds);
- var mem_rel_c = treeBundleN(&rel_c_binds);
-
- // Query each entity across all 3 relations
- for (0..5) |i| {
- var key = entities[40 + i];
- const ra = queryOne(&mem_rel_a, &key, entities);
- const rb = queryOne(&mem_rel_b, &key, entities);
- const rc = queryOne(&mem_rel_c, &key, entities);
-
- if (ra.idx == 45 + i) t3_correct += 1;
- if (rb.idx == 50 + i) t3_correct += 1;
- if (rc.idx == 55 + i) t3_correct += 1;
-
- std.debug.print(" ent[{d}]: relAβent[{d}]{s} relBβent[{d}]{s} relCβent[{d}]{s}\n", .{
- 40 + i,
- ra.idx,
- @as([]const u8, if (ra.idx == 45 + i) " OK" else " MISS"),
- rb.idx,
- @as([]const u8, if (rb.idx == 50 + i) " OK" else " MISS"),
- rc.idx,
- @as([]const u8, if (rc.idx == 55 + i) " OK" else " MISS"),
- });
- }
- std.debug.print("Result: {d}/15\n", .{t3_correct});
- total_correct += t3_correct;
- total_queries += 15;
-
- // --- Summary ---
- const accuracy = @as(f64, @floatFromInt(total_correct)) / @as(f64, @floatFromInt(total_queries)) * 100.0;
- std.debug.print("\n--- Pure Symbolic Reasoning Summary ---\n", .{});
- std.debug.print("Total: {d}/{d} ({d:.0}%)\n", .{ total_correct, total_queries, accuracy });
-
- try std.testing.expect(t1_correct >= 8); // analogies
- try std.testing.expect(t2_correct >= 13); // transitive chains (at least 5+8)
- try std.testing.expect(t3_correct >= 12); // compositional (at least 80%)
-
- // Progression
- std.debug.print("\n--- Level 11.26 Progression ---\n", .{});
- std.debug.print("Level | Feature | Status\n", .{});
- std.debug.print("------|----------------------|-------\n", .{});
- std.debug.print("11.23 | Massive KG + CLI | heap+120ent+10rel+dispatch\n", .{});
- std.debug.print("11.24 | Interactive CLI Binary | named+pipeline+binary\n", .{});
- std.debug.print("11.25 | Interactive REPL Mode | session+stats+continuity\n", .{});
- std.debug.print("11.26 | Pure Symbolic AGI | dim4096+unsplit+reasoning <<<\n", .{});
- std.debug.print("============================================\n", .{});
-}
diff --git a/src/mnist_loader.zig b/src/mnist_loader.zig
deleted file mode 100644
index 378f4c9809..0000000000
--- a/src/mnist_loader.zig
+++ /dev/null
@@ -1,150 +0,0 @@
-//! MNIST Dataset Loader for Trinity Benchmarks
-//!
-//! Loads MNIST test dataset (10k images, 28x28 pixels, 784 bytes each).
-//! IDX file format specification: http://yann.lecun.com/exdb/mnist/
-//!
-//! Usage:
-//! const mnist = try MNIST.load(allocator, "data/t10k-images-idx3-ubyte");
-//! defer mnist.deinit();
-//! const image = mnist.getImage(0); // 784 pixels [0..255]
-
-const std = @import("std");
-
-pub const MNIST = struct {
- images: []const []const u8,
- data: []u8,
- allocator: std.mem.Allocator,
-
- const Self = @This();
-
- /// Load MNIST image file from disk.
- /// Downloads if not present.
- pub fn load(allocator: std.mem.Allocator, path: []const u8) !Self {
- // Try to load from disk
- const file = std.fs.cwd().openFile(path, .{}) catch |err| {
- if (err == error.FileNotFound) {
- std.debug.print("MNIST file not found: {s}\n", .{path});
- std.debug.print("Download from: http://yann.lecun.com/exdb/mnist/\n", .{});
- std.debug.print("Extract to: {s}\n", .{path});
- return error.FileNotFound;
- }
- return err;
- };
- defer file.close();
-
- const file_size = try file.getEndPos();
- const data = try allocator.alloc(u8, file_size);
- errdefer allocator.free(data);
-
- _ = try file.readAll(data);
-
- // Parse IDX header
- if (data.len < 16) return error.InvalidHeader;
-
- const magic = std.mem.readInt(u32, data[0..4], .big);
- if (magic != 0x00000803) return error.InvalidMagic; // 0x00000803 = image file
-
- const num_images = std.mem.readInt(u32, data[4..8], .big);
- const num_rows = std.mem.readInt(u32, data[8..12], .big);
- const num_cols = std.mem.readInt(u32, data[12..16], .big);
-
- if (num_rows != 28 or num_cols != 28) return error.InvalidDimensions;
- const image_size = 28 * 28;
-
- // Create image slices
- const images = try allocator.alloc([]const u8, num_images);
- errdefer allocator.free(images);
-
- for (0..num_images) |i| {
- const offset = 16 + i * image_size;
- if (offset + image_size > data.len) return error.TruncatedData;
- images[i] = data[offset .. offset + image_size];
- }
-
- return Self{
- .images = images,
- .data = data,
- .allocator = allocator,
- };
- }
-
- /// Get image at index (returns 784 bytes [0..255]).
- pub fn getImage(self: *const Self, index: usize) []const u8 {
- return self.images[index];
- }
-
- /// Get normalized pixel value [0..1] as f32.
- pub fn getPixelNorm(self: *const Self, image_idx: usize, pixel_idx: usize) f32 {
- const raw = self.images[image_idx][pixel_idx];
- return @as(f32, @floatFromInt(raw)) / 255.0;
- }
-
- /// Convert image to f32 array [0..1].
- pub fn imageToF32(self: *const Self, allocator: std.mem.Allocator, image_idx: usize) ![]f32 {
- const src = self.images[image_idx];
- const dst = try allocator.alloc(f32, src.len);
- for (src, 0..) |val, i| {
- dst[i] = @as(f32, @floatFromInt(val)) / 255.0;
- }
- return dst;
- }
-
- pub fn deinit(self: Self) void {
- self.allocator.free(self.images);
- self.allocator.free(self.data);
- }
-
- pub fn count(self: *const Self) usize {
- return self.images.len;
- }
-};
-
-// Simple MNIST labels loader
-pub const Labels = struct {
- labels: []const u8,
- allocator: std.mem.Allocator,
-
- pub fn load(allocator: std.mem.Allocator, path: []const u8) !Labels {
- const file = std.fs.cwd().openFile(path, .{}) catch |err| {
- if (err == error.FileNotFound) {
- std.debug.print("Labels file not found: {s}\n", .{path});
- return error.FileNotFound;
- }
- return err;
- };
- defer file.close();
-
- const file_size = try file.getEndPos();
- const data = try allocator.alloc(u8, file_size);
- errdefer allocator.free(data);
-
- _ = try file.readAll(data);
-
- // Parse IDX header
- if (data.len < 8) return error.InvalidHeader;
-
- const magic = std.mem.readInt(u32, data[0..4], .big);
- if (magic != 0x00000801) return error.InvalidMagic; // 0x00000801 = label file
-
- const num_labels = std.mem.readInt(u32, data[4..8], .big);
-
- if (8 + num_labels != data.len) return error.TruncatedData;
-
- return Labels{
- .labels = data[8..],
- .allocator = allocator,
- };
- }
-
- pub fn get(self: *const Labels, index: usize) u8 {
- return self.labels[index];
- }
-
- pub fn count(self: *const Labels) usize {
- return self.labels.len;
- }
-
- pub fn deinit(self: Labels) void {
- self.allocator.free(self.labels[0 .. 8 + self.labels.len]); // Free entire buffer
- }
-};
diff --git a/src/monopoles/cell.tri b/src/monopoles/cell.tri
deleted file mode 100644
index 6784fe3468..0000000000
--- a/src/monopoles/cell.tri
+++ /dev/null
@@ -1,41 +0,0 @@
-[cell]
-id = "trinity.monopoles"
-name = "Monopoles"
-version = "1.0.0"
-kind = "library"
-path = "src/monopoles"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Magnetic monopole properties from phi-gamma and E8"
-capabilities = ["vsa", "monopoles", "sacred-geometry"]
-files = 1
-tests = 25
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = []
-exports = ["diracCharge", "monopoleMass", "monopoleMassCorrected", "criticalMagneticField", "magneticCoupling"]
-tri_subcommands = []
-events = []
-binaries = []
-
-[dependencies]
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:3e82b08b6411194c969251b50442ac3bd0ece208a2a1f0f9d44b72528c7392de"
diff --git a/src/monopoles/sacred_monopoles.zig b/src/monopoles/sacred_monopoles.zig
deleted file mode 100644
index adbab49854..0000000000
--- a/src/monopoles/sacred_monopoles.zig
+++ /dev/null
@@ -1,380 +0,0 @@
-//! TRINITY v20.0: SACRED MAGNETIC MONOPOLES
-//!
-//! Ο-Ξ³ based prediction of magnetic monopole properties.
-//! Dirac quantization, E8 embedding, production in early universe, detection.
-//!
-//! Core insight: Monopoles are NOT exotic β they emerge from E8 root structure
-//! and Ξ³ = Οβ»Β³ scaling. Their mass and cross-sections are precisely predicted.
-
-const std = @import("std");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = 2.6180339887498948482...
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// ΟΒ³ = 4.23606797749978969641...
-pub const PHI_CUBED: f64 = PHI * PHI * PHI;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / PHI_CUBED;
-
-/// Consciousness threshold (Ξ¦_Ξ³ = Οβ»ΒΉ)
-pub const PHI_GAMMA: f64 = 1.0 / PHI;
-
-/// TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// Ο constant
-pub const PI: f64 = 3.14159265358979323846;
-
-// Physical constants for monopole calculations
-pub const ELEMENTARY_CHARGE: f64 = 1.602176634e-19; // C
-pub const PLANCK_CONSTANT: f64 = 6.62607015e-34; // JΒ·s
-pub const REDUCED_PLANCK: f64 = 1.054571817e-34; // JΒ·s
-pub const SPEED_OF_LIGHT: f64 = 299792458.0; // m/s
-pub const VACUUM_PERMEABILITY: f64 = 4.0 * PI * 1e-7; // H/m
-pub const BOLTZMANN: f64 = 1.380649e-23; // J/K
-pub const PROTON_MASS: f64 = 1.6726219e-27; // kg
-pub const PLANCK_MASS: f64 = 2.176434e-8; // kg
-pub const PLANCK_ENERGY: f64 = 1.956082e9; // J
-pub const GEV_TO_JOULES: f64 = 1.602176634e-10; // J/GeV
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// I. MONOPOLE MASS & CHARGE (323-328)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 323: Dirac charge quantization
-/// g = n Γ e / (2Ξ΅βc) Γ Ξ¦_Ξ³ correction
-pub fn diracCharge(n: i32) f64 {
- const e = ELEMENTARY_CHARGE;
- const epsilon_0 = 1.0 / (VACUUM_PERMEABILITY * SPEED_OF_LIGHT * SPEED_OF_LIGHT);
- const g_dirac = @as(f64, @floatFromInt(n)) * e / (2.0 * epsilon_0 * SPEED_OF_LIGHT);
- return g_dirac * PHI_GAMMA; // Ξ³-correction
-}
-
-/// Formula 324: Monopole mass from E8
-/// M_monopole = ΟΒ² Γ m_Planck / Ξ± (where Ξ± is fine structure constant)
-pub fn monopoleMass() f64 {
- const alpha = 1.0 / 137.035999084; // Fine structure constant
- return PHI_SQ * PLANCK_MASS / alpha;
-}
-
-/// Formula 325: Mass Ξ³-correction
-/// M_corrected = M_monopole Γ (1 + Ξ³)
-pub fn monopoleMassCorrected() f64 {
- const M_base = monopoleMass();
- return M_base * (1.0 + GAMMA);
-}
-
-/// Formula 326: Critical magnetic field
-/// B_critical = Ξ¦_Ξ³ Γ m_monopoleΒ² Γ cΒ³ / (β Γ e)
-pub fn criticalMagneticField() f64 {
- const M = monopoleMassCorrected();
- const numerator = PHI_GAMMA * M * M * std.math.pow(f64, SPEED_OF_LIGHT, 3);
- const denominator = REDUCED_PLANCK * ELEMENTARY_CHARGE;
- return numerator / denominator;
-}
-
-/// Formula 327: Magnetic coupling
-/// Ξ±_m = gΒ² / (4Ο) Γ Ξ¦_Ξ³
-pub fn magneticCoupling() f64 {
- const g = diracCharge(1);
- const alpha_m = (g * g) / (4.0 * PI);
- return alpha_m * PHI_GAMMA;
-}
-
-/// Formula 328: Charge quantization condition
-/// n Γ m_monopole = integer (from E8 root structure)
-pub fn chargeQuantizationCondition(n: i32, m: f64) bool {
- const M = monopoleMass();
- const nm = @as(f64, @floatFromInt(n)) * m / M;
- return @abs(nm - @round(nm)) < 0.01;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// II. PRODUCTION IN EARLY UNIVERSE (329-334)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 329: Primordial abundance
-/// n_monopoles / n_baryons = Ξ³ Γ exp(-M_monopole / T_GUT)
-pub fn primordialAbundance(T_GUT: f64) f64 {
- const M = monopoleMassCorrected();
- const energy_ratio = M / (T_GUT * BOLTZMANN);
- return GAMMA * std.math.exp(-energy_ratio);
-}
-
-/// Formula 330: Production temperature
-/// T_production = Ο Γ T_GUT / Ξ³
-pub fn productionTemperature(T_GUT: f64) f64 {
- return (PHI / GAMMA) * T_GUT;
-}
-
-/// Formula 331: Kibble-Zurek mechanism scaling
-/// ΞΎ_KZ = ΟΒ³ Γ (Ο Γ v)^(1/2)
-pub fn kibbleZurekScaling(tau: f64, v: f64) f64 {
- return PHI_CUBED * std.math.sqrt(tau * v);
-}
-
-/// Formula 332: Survival fraction
-/// f_survival = exp(-Ξ³ Γ t_universe / t_Hubble)
-pub fn survivalFraction(t_universe: f64, H_Hubble: f64) f64 {
- const t_Hubble = 1.0 / H_Hubble;
- return std.math.exp(-GAMMA * t_universe / t_Hubble);
-}
-
-/// Formula 333: Current monopole density
-/// n_0 = Ξ³ Γ n_baryon Γ f_survival Γ (a(tβ)/a(t_prod))Β³
-pub fn currentDensity(n_baryon: f64, f_survival: f64, scale_factor_ratio: f64) f64 {
- return GAMMA * n_baryon * f_survival * std.math.pow(f64, scale_factor_ratio, 3);
-}
-
-/// Formula 334: Monopole clustering scale
-/// R_cluster = ΟΒ² / (T Γ Ξ³)
-pub fn clusteringScale(T: f64) f64 {
- return PHI_SQ / (T * GAMMA);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// III. DETECTION CROSS-SECTIONS (335-339)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 335: Photon-monopole cross-section
-/// Ο_Ξ³ = Ξ³Β² Γ Ο Γ r_monopoleΒ²
-pub fn photonCrossSection() f64 {
- const r_monopole = REDUCED_PLANCK / (monopoleMassCorrected() * SPEED_OF_LIGHT);
- return GAMMA * GAMMA * PI * r_monopole * r_monopole;
-}
-
-/// Formula 336: Proton decay catalysis cross-section
-/// Ο_p = Ξ¦_Ξ³ Γ Ο_weak / M_monopole
-pub fn protonCatalysisCrossSection() f64 {
- const sigma_weak = 1e-38; // Typical weak cross-section in cmΒ²
- const M = monopoleMassCorrected();
- return PHI_GAMMA * sigma_weak / M;
-}
-
-/// Formula 337: Neutron-monopole conversion
-/// Ο_n = Ξ³ Γ Ο_p Γ (m_n / m_p)Β²
-pub fn neutronConversionCrossSection() f64 {
- const sigma_p = protonCatalysisCrossSection();
- const m_n = 1.674927e-27; // Neutron mass in kg
- const mass_ratio = m_n / PROTON_MASS;
- return GAMMA * sigma_p * mass_ratio * mass_ratio;
-}
-
-/// Formula 338: Drell-Yan monopole production
-/// Ο_DY = Ξ±_m Γ Ξ¦_Ξ³ Γ (s / MΒ²)
-pub fn drellYanCrossSection(s: f64) f64 {
- const M = monopoleMassCorrected();
- const alpha_m = magneticCoupling();
- return alpha_m * PHI_GAMMA * s / (M * M);
-}
-
-/// Formula 339: IceCube detection probability
-/// P_IceCube = Ξ³ Γ n_monopoles Γ Ο_ΞΌ Γ exposure
-pub fn iceCubeDetectionProbability(n_monopoles: f64, exposure: f64) f64 {
- const sigma_mu = photonCrossSection(); // Approximate muon cross-section
- return GAMMA * n_monopoles * sigma_mu * exposure;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// IV. E8 CONNECTION (340-342)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 340: E8 root embedding
-/// E8 has 240 roots β 8Γ(2+4)Γ(3+5+7) monopole types
-pub fn e8RootEmbedding() f64 {
- const total_roots = 240.0;
- const monopole_types = 8.0 * (2.0 + 4.0) * (3.0 + 5.0 + 7.0);
- return total_roots / monopole_types;
-}
-
-/// Formula 341: Root-to-monopole mass mapping
-/// M_i = Ο Γ M_base Γ (root_number / 240)^Ξ³
-pub fn rootToMonopoleMass(root_number: f64) f64 {
- const M_base = monopoleMass();
- const root_ratio = root_number / 240.0;
- return PHI * M_base * std.math.pow(f64, root_ratio, GAMMA);
-}
-
-/// Formula 342: E8 Ξ³-correction to monopole mass
-/// M_E8 = M_monopole Γ (1 + Ξ³ Γ root_level)
-pub fn e8CorrectedMass(root_level: f64) f64 {
- const M = monopoleMassCorrected();
- return M * (1.0 + GAMMA * root_level);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HELPER FUNCTIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Calculate monopole mass in GeV
-pub fn monopoleMassGeV() f64 {
- const M_kg = monopoleMassCorrected();
- return M_kg / PLANCK_MASS * PLANCK_ENERGY / GEV_TO_JOULES;
-}
-
-/// Calculate Parker bound (maximum allowed flux)
-/// F_Parker = 10^-15 cmβ»Β²Β·srβ»ΒΉΒ·sβ»ΒΉ Γ Ξ³
-pub fn parkerBound() f64 {
- return 1e-15 * GAMMA;
-}
-
-/// Check if monopole mass is within experimental bounds
-pub fn withinExperimentalBounds(M_GeV: f64) bool {
- return M_GeV > 1e8 and M_GeV < 1e18;
-}
-
-/// Calculate expected event rate for detector
-/// R = Ξ¦ Γ Ο Γ Ξ΅ Γ t
-pub fn eventRate(flux: f64, cross_section: f64, efficiency: f64, time: f64) f64 {
- return flux * cross_section * efficiency * time;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const testing = std.testing;
-
-test "v20.0: Formula 323 - Dirac charge" {
- const g = diracCharge(1);
- try testing.expect(g > 0);
- try testing.expect(g < 1e-16);
-}
-
-test "v20.0: Formula 324 - Monopole mass" {
- const M = monopoleMass();
- try testing.expect(M > 1e-9); // Should be around 2e-8 kg
-}
-
-test "v20.0: Formula 325 - Mass correction" {
- const M_corr = monopoleMassCorrected();
- const M_base = monopoleMass();
- try testing.expect(M_corr > M_base);
-}
-
-test "v20.0: Formula 326 - Critical B field" {
- const B = criticalMagneticField();
- try testing.expect(B > 1e15); // Should be enormous
-}
-
-test "v20.0: Formula 327 - Magnetic coupling" {
- const alpha_m = magneticCoupling();
- try testing.expect(alpha_m > 0); // Positive magnetic coupling
-}
-
-test "v20.0: Formula 328 - Charge quantization" {
- const result = chargeQuantizationCondition(1, monopoleMass());
- try testing.expect(result);
-}
-
-test "v20.0: Formula 329 - Primordial abundance" {
- const abundance = primordialAbundance(1e16);
- try testing.expect(abundance >= 0);
- try testing.expect(abundance < 1);
-}
-
-test "v20.0: Formula 330 - Production temperature" {
- const T_prod = productionTemperature(1e16);
- try testing.expect(T_prod > 1e16);
-}
-
-test "v20.0: Formula 331 - Kibble-Zurek scaling" {
- const xi = kibbleZurekScaling(1e-30, 1e-10);
- try testing.expect(xi > 0);
-}
-
-test "v20.0: Formula 332 - Survival fraction" {
- const f_surv = survivalFraction(1e17, 2e-18);
- try testing.expect(f_surv > 0);
- try testing.expect(f_surv <= 1);
-}
-
-test "v20.0: Formula 333 - Current density" {
- const n_0 = currentDensity(1e6, 0.1, 1e3);
- try testing.expect(n_0 > 0);
-}
-
-test "v20.0: Formula 334 - Clustering scale" {
- const R = clusteringScale(2.7);
- try testing.expect(R > 0);
-}
-
-test "v20.0: Formula 335 - Photon cross-section" {
- const sigma = photonCrossSection();
- try testing.expect(sigma > 0);
-}
-
-test "v20.0: Formula 336 - Proton catalysis" {
- const sigma_p = protonCatalysisCrossSection();
- try testing.expect(sigma_p > 0);
-}
-
-test "v20.0: Formula 337 - Neutron conversion" {
- const sigma_n = neutronConversionCrossSection();
- try testing.expect(sigma_n > 0);
-}
-
-test "v20.0: Formula 338 - Drell-Yan" {
- const sigma_dy = drellYanCrossSection(1e10);
- try testing.expect(sigma_dy > 0);
-}
-
-test "v20.0: Formula 339 - IceCube detection" {
- const P = iceCubeDetectionProbability(1e-10, 1e14);
- try testing.expect(P >= 0);
-}
-
-test "v20.0: Formula 340 - E8 embedding" {
- const ratio = e8RootEmbedding();
- try testing.expect(ratio > 0);
-}
-
-test "v20.0: Formula 341 - Root to monopole" {
- const M = rootToMonopoleMass(120);
- try testing.expect(M > 0);
-}
-
-test "v20.0: Formula 342 - E8 corrected mass" {
- const M_E8 = e8CorrectedMass(1.0);
- const M = monopoleMassCorrected();
- try testing.expect(M_E8 > M);
-}
-
-test "v20.0: Helper - Mass in GeV" {
- const M_GeV = monopoleMassGeV();
- try testing.expect(M_GeV > 1e18); // GUT-scale monopole
- try testing.expect(M_GeV < 1e22); // Updated upper bound
-}
-
-test "v20.0: Helper - Parker bound" {
- const F_parker = parkerBound();
- try testing.expect(F_parker > 0);
- try testing.expect(F_parker < 1e-14);
-}
-
-test "v20.0: TRINITY identity holds" {
- try testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-test "v20.0: PHI_GAMMA = phi^(-1)" {
- try testing.expectApproxEqRel(PHI_GAMMA, 1.0 / PHI, 1e-10);
-}
-
-test "v20.0: GAMMA = phi^(-3)" {
- try testing.expectApproxEqRel(GAMMA, 1.0 / PHI_CUBED, 1e-10);
-}
-
-// Version info
-pub const VERSION = "20.0.0";
-pub const MODULE_NAME = "SACRED MAGNETIC MONOPOLES";
-pub const FORMULA_START = 323;
-pub const FORMULA_END = 342;
-pub const FORMULA_COUNT = 20;
diff --git a/src/packed_vsa.zig b/src/packed_vsa.zig
deleted file mode 100644
index 262b119957..0000000000
--- a/src/packed_vsa.zig
+++ /dev/null
@@ -1,475 +0,0 @@
-// @origin(spec:packed_vsa.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// Trinity Packed VSA Operations
-// VSA operation on toin and (5 andin/)
-// withby lookup tables for with and withtointoand
-//
-// β²€β²β²β²’β² β²ͺβ²β²’β²β²¨β²β²: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// ΟΒ² + 1/ΟΒ² = 3
-
-const std = @import("std");
-const packed_trit = @import("packed_trit.zig");
-const hybrid = @import("hybrid.zig");
-const vsa = @import("vsa.zig");
-
-const PackedBigInt = packed_trit.PackedBigInt;
-const HybridBigInt = hybrid.HybridBigInt;
-const Trit = packed_trit.Trit;
-const TRITS_PER_BYTE = packed_trit.TRITS_PER_BYTE;
-const MAX_PACKED_BYTES = packed_trit.MAX_PACKED_BYTES;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LOOKUP TABLES for and on toin
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Lookup table for bind: BIND_LUT[a][b] = packed(bind(unpack(a), unpack(b)))
-/// : 243 * 243 = 59049 (~58KB)
-const BIND_LUT: [243][243]u8 = blk: {
- @setEvalBranchQuota(1000000);
- var lut: [243][243]u8 = undefined;
- for (0..243) |a| {
- for (0..243) |b| {
- const trits_a = packed_trit.decodePack(@intCast(a));
- const trits_b = packed_trit.decodePack(@intCast(b));
- // bind = element-wise multiply
- const result = [5]i8{
- trits_a[0] * trits_b[0],
- trits_a[1] * trits_b[1],
- trits_a[2] * trits_b[2],
- trits_a[3] * trits_b[3],
- trits_a[4] * trits_b[4],
- };
- lut[a][b] = packed_trit.encodePack(result);
- }
- }
- break :blk lut;
-};
-
-/// Lookup table for bundle2: BUNDLE_LUT[a][b] = packed(bundle(unpack(a), unpack(b)))
-const BUNDLE_LUT: [243][243]u8 = blk: {
- @setEvalBranchQuota(1000000);
- var lut: [243][243]u8 = undefined;
- for (0..243) |a| {
- for (0..243) |b| {
- const trits_a = packed_trit.decodePack(@intCast(a));
- const trits_b = packed_trit.decodePack(@intCast(b));
- var result: [5]i8 = undefined;
- for (0..5) |i| {
- const sum: i16 = @as(i16, trits_a[i]) + @as(i16, trits_b[i]);
- if (sum > 0) {
- result[i] = 1;
- } else if (sum < 0) {
- result[i] = -1;
- } else {
- result[i] = 0;
- }
- }
- lut[a][b] = packed_trit.encodePack(result);
- }
- }
- break :blk lut;
-};
-
-/// Lookup table for dot product: DOT_LUT[a][b] = sum of element-wise products
-/// and: -5 before +5, and how u8 with withand +5
-const DOT_LUT: [243][243]u8 = blk: {
- @setEvalBranchQuota(1000000);
- var lut: [243][243]u8 = undefined;
- for (0..243) |a| {
- for (0..243) |b| {
- const trits_a = packed_trit.decodePack(@intCast(a));
- const trits_b = packed_trit.decodePack(@intCast(b));
- var sum: i16 = 0;
- for (0..5) |i| {
- sum += @as(i16, trits_a[i]) * @as(i16, trits_b[i]);
- }
- // and +5 what and in u8 (and 0-10)
- lut[a][b] = @intCast(@as(i16, sum) + 5);
- }
- }
- break :blk lut;
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// PACKED VSA OPERATIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Packed bind - andwithby lookup table, withtointoand
-pub fn packedBind(a: *const PackedBigInt, b: *const PackedBigInt) PackedBigInt {
- var result = PackedBigInt.zero();
- const len = @max(a.trit_len, b.trit_len);
- result.trit_len = len;
-
- const packed_len = (len + TRITS_PER_BYTE - 1) / TRITS_PER_BYTE;
-
- for (0..packed_len) |i| {
- const a_byte = if (i < a.packedLen()) a.data[i] else packed_trit.encodePack(.{ 0, 0, 0, 0, 0 });
- const b_byte = if (i < b.packedLen()) b.data[i] else packed_trit.encodePack(.{ 0, 0, 0, 0, 0 });
-
- // Lookup inwith withtointoand!
- result.data[i] = BIND_LUT[a_byte][b_byte];
- }
-
- return result;
-}
-
-/// Packed bundle - andwithby lookup table
-pub fn packedBundle(a: *const PackedBigInt, b: *const PackedBigInt) PackedBigInt {
- var result = PackedBigInt.zero();
- const len = @max(a.trit_len, b.trit_len);
- result.trit_len = len;
-
- const packed_len = (len + TRITS_PER_BYTE - 1) / TRITS_PER_BYTE;
-
- for (0..packed_len) |i| {
- const a_byte = if (i < a.packedLen()) a.data[i] else packed_trit.encodePack(.{ 0, 0, 0, 0, 0 });
- const b_byte = if (i < b.packedLen()) b.data[i] else packed_trit.encodePack(.{ 0, 0, 0, 0, 0 });
-
- result.data[i] = BUNDLE_LUT[a_byte][b_byte];
- }
-
- return result;
-}
-
-/// Packed dot product - andwithby lookup table
-pub fn packedDot(a: *const PackedBigInt, b: *const PackedBigInt) i64 {
- const len = @min(a.trit_len, b.trit_len);
- const packed_len = (len + TRITS_PER_BYTE - 1) / TRITS_PER_BYTE;
-
- var total: i64 = 0;
-
- for (0..packed_len) |i| {
- const a_byte = a.data[i];
- const b_byte = b.data[i];
-
- // Lookup returns value with withand +5
- const dot_shifted = DOT_LUT[a_byte][b_byte];
- total += @as(i64, dot_shifted) - 5;
- }
-
- return total;
-}
-
-/// Packed unbind - for andin unbind = bind (withon operation)
-/// unbind(bind(a, b), b) = a
-pub fn packedUnbind(a: *const PackedBigInt, b: *const PackedBigInt) PackedBigInt {
- // andin: unbind = bind, from what:
- // bind(a, b) = a * b
- // unbind(a*b, b) = (a*b) * b = a * (b*b) = a * 1 = a
- // (for b β {-1, 1}, b*b = 1)
- return packedBind(a, b);
-}
-
-/// Packed cosine similarity
-pub fn packedCosineSimilarity(a: *const PackedBigInt, b: *const PackedBigInt) f64 {
- const dot_ab = packedDot(a, b);
- const dot_aa = packedDot(a, a);
- const dot_bb = packedDot(b, b);
-
- if (dot_aa == 0 or dot_bb == 0) return 0.0;
-
- const norm_a = @sqrt(@as(f64, @floatFromInt(dot_aa)));
- const norm_b = @sqrt(@as(f64, @floatFromInt(dot_bb)));
-
- return @as(f64, @floatFromInt(dot_ab)) / (norm_a * norm_b);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONVERSION UTILITIES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// inand HybridBigInt β PackedBigInt
-pub fn fromHybrid(h: *HybridBigInt) PackedBigInt {
- h.ensureUnpacked();
-
- var result = PackedBigInt.zero();
- result.trit_len = h.trit_len;
-
- const packed_len = (h.trit_len + TRITS_PER_BYTE - 1) / TRITS_PER_BYTE;
-
- for (0..packed_len) |i| {
- const base = i * TRITS_PER_BYTE;
- var trits: [5]i8 = .{ 0, 0, 0, 0, 0 };
-
- for (0..5) |j| {
- if (base + j < h.trit_len) {
- trits[j] = h.unpacked_cache[base + j];
- }
- }
-
- result.data[i] = packed_trit.encodePack(trits);
- }
-
- return result;
-}
-
-/// inand PackedBigInt β HybridBigInt
-pub fn toHybrid(p: *const PackedBigInt) HybridBigInt {
- var result = HybridBigInt.zero();
- result.mode = .unpacked_mode;
- result.trit_len = p.trit_len;
- result.dirty = true;
-
- for (0..p.trit_len) |i| {
- result.unpacked_cache[i] = p.getTrit(i);
- }
-
- return result;
-}
-
-/// yes with toin vector
-pub fn randomPackedVector(size: usize, seed: u64) PackedBigInt {
- var result = PackedBigInt.zero();
- result.trit_len = size;
-
- var rng = std.Random.DefaultPrng.init(seed);
- const random = rng.random();
-
- const packed_len = (size + TRITS_PER_BYTE - 1) / TRITS_PER_BYTE;
-
- for (0..packed_len) |i| {
- // notand with toin (0-242)
- result.data[i] = @intCast(random.intRangeAtMost(u8, 0, 242));
- }
-
- return result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "packed bind correctness" {
- // yes testin into via HybridBigInt
- var h_a = vsa.randomVector(100, 12345);
- var h_b = vsa.randomVector(100, 67890);
-
- // with result (unpacked)
- const ref_result = vsa.bind(&h_a, &h_b);
-
- // Packed version
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
- const packed_result = packedBind(&p_a, &p_b);
-
- // Compare
- for (0..100) |i| {
- const ref_trit = ref_result.unpacked_cache[i];
- const packed_trit_val = packed_result.getTrit(i);
- try std.testing.expectEqual(ref_trit, packed_trit_val);
- }
-}
-
-test "packed bundle correctness" {
- var h_a = vsa.randomVector(100, 11111);
- var h_b = vsa.randomVector(100, 22222);
-
- const ref_result = vsa.bundle2(&h_a, &h_b);
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
- const packed_result = packedBundle(&p_a, &p_b);
-
- for (0..100) |i| {
- try std.testing.expectEqual(ref_result.unpacked_cache[i], packed_result.getTrit(i));
- }
-}
-
-test "packed dot correctness" {
- var h_a = vsa.randomVector(100, 33333);
- var h_b = vsa.randomVector(100, 44444);
-
- // with dot product
- var ref_dot: i64 = 0;
- for (0..100) |i| {
- ref_dot += @as(i64, h_a.unpacked_cache[i]) * @as(i64, h_b.unpacked_cache[i]);
- }
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
- const packed_dot_val = packedDot(&p_a, &p_b);
-
- try std.testing.expectEqual(ref_dot, packed_dot_val);
-}
-
-test "packed cosine similarity" {
- var h_a = vsa.randomVector(100, 55555);
- var h_b = vsa.randomVector(100, 55555); // from seed = and
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
-
- const sim = packedCosineSimilarity(&p_a, &p_b);
- try std.testing.expectApproxEqAbs(@as(f64, 1.0), sim, 0.001);
-}
-
-test "packed unbind correctness" {
- // yes in with into
- const p_a = randomPackedVector(100, 12345);
- const p_b = randomPackedVector(100, 67890);
-
- // bind(a, b)
- const bound = packedBind(&p_a, &p_b);
-
- // unbind(bind(a, b), b) before yes vector byand on a
- const unbound = packedUnbind(&bound, &p_b);
-
- // Check within with andon
- const sim = packedCosineSimilarity(&unbound, &p_a);
-
- // andin within before inwithtoand
- // and- in into from andand
- std.debug.print("\nUnbind similarity: {d:.3}\n", .{sim});
- try std.testing.expect(sim > 0.5); // onand within
-}
-
-test "packed unbind retrieval" {
- // and with to onand
- // to: bind(Paris, bind(capital_of, France))
- // with: unbind(fact, bind(Paris, capital_of)) β France
-
- const paris = randomPackedVector(100, Entity.hashString("Paris"));
- const capital_of = randomPackedVector(100, Entity.hashString("capital_of") ^ 0xDEADBEEF);
- const france = randomPackedVector(100, Entity.hashString("France"));
-
- // Encode to: Paris is capital_of France
- const pred_obj = packedBind(&capital_of, &france);
- const fact = packedBind(&paris, &pred_obj);
-
- // with: what is withand and?
- // unbind(fact, bind(capital_of, France)) β Paris
- const query_pattern = packedBind(&capital_of, &france);
- const result = packedUnbind(&fact, &query_pattern);
-
- // Result before by on Paris
- const sim_paris = packedCosineSimilarity(&result, &paris);
- const sim_france = packedCosineSimilarity(&result, &france);
-
- std.debug.print("\nQuery result similarity to Paris: {d:.3}\n", .{sim_paris});
- std.debug.print("Query result similarity to France: {d:.3}\n", .{sim_france});
-
- // Paris before more by
- try std.testing.expect(sim_paris > sim_france);
-}
-
-const Entity = @import("knowledge_graph.zig").Entity;
-
-test "large vector bind correctness (1000 trits)" {
- var h_a = vsa.randomVector(1000, 12345);
- var h_b = vsa.randomVector(1000, 67890);
-
- const ref_result = vsa.bind(&h_a, &h_b);
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
- const packed_result = packedBind(&p_a, &p_b);
-
- // Check each 100- and for withtowithand
- var i: usize = 0;
- while (i < 1000) : (i += 100) {
- try std.testing.expectEqual(ref_result.unpacked_cache[i], packed_result.getTrit(i));
- }
-}
-
-test "large vector bind correctness (5000 trits)" {
- var h_a = vsa.randomVector(5000, 11111);
- var h_b = vsa.randomVector(5000, 22222);
-
- const ref_result = vsa.bind(&h_a, &h_b);
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
- const packed_result = packedBind(&p_a, &p_b);
-
- // Check each 500- and
- var i: usize = 0;
- while (i < 5000) : (i += 500) {
- try std.testing.expectEqual(ref_result.unpacked_cache[i], packed_result.getTrit(i));
- }
-}
-
-test "large vector bind correctness (10000 trits)" {
- var h_a = vsa.randomVector(10000, 33333);
- var h_b = vsa.randomVector(10000, 44444);
-
- const ref_result = vsa.bind(&h_a, &h_b);
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
- const packed_result = packedBind(&p_a, &p_b);
-
- // Check each 1000- and
- var i: usize = 0;
- while (i < 10000) : (i += 1000) {
- try std.testing.expectEqual(ref_result.unpacked_cache[i], packed_result.getTrit(i));
- }
-}
-
-test "large vector dot correctness (10000 trits)" {
- var h_a = vsa.randomVector(10000, 55555);
- var h_b = vsa.randomVector(10000, 66666);
-
- // with dot product
- var ref_dot: i64 = 0;
- for (0..10000) |i| {
- ref_dot += @as(i64, h_a.unpacked_cache[i]) * @as(i64, h_b.unpacked_cache[i]);
- }
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
- const packed_dot_val = packedDot(&p_a, &p_b);
-
- try std.testing.expectEqual(ref_dot, packed_dot_val);
-}
-
-test "benchmark Packed vs Unpacked" {
- // PackedBigInt supports before 12000 andin
- const sizes = [_]usize{ 100, 500, 1000, 2000, 5000, 10000 };
- const iterations = 1000;
-
- std.debug.print("\n\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("β BENCHMARK: PACKED (5 trits/byte) vs UNPACKED (1 trit/byte) β\n", .{});
- std.debug.print("β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
- std.debug.print("β Size β Unpacked β Packed β Speedup β Mem Unpackβ Mem Pack β Mem Saving β\n", .{});
- std.debug.print("β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n", .{});
-
- for (sizes) |size| {
- var h_a = vsa.randomVector(size, 12345);
- var h_b = vsa.randomVector(size, 67890);
-
- const p_a = fromHybrid(&h_a);
- const p_b = fromHybrid(&h_b);
-
- // Benchmark Unpacked (vsa.bind)
- var timer = std.time.Timer.start() catch unreachable;
- for (0..iterations) |_| {
- const result = vsa.bind(&h_a, &h_b);
- std.mem.doNotOptimizeAway(&result);
- }
- const unpacked_ns = timer.read();
-
- // Benchmark Packed
- timer.reset();
- for (0..iterations) |_| {
- const result = packedBind(&p_a, &p_b);
- std.mem.doNotOptimizeAway(&result);
- }
- const packed_ns = timer.read();
-
- const unpacked_us = @as(f64, @floatFromInt(unpacked_ns)) / 1000.0 / @as(f64, @floatFromInt(iterations));
- const packed_us = @as(f64, @floatFromInt(packed_ns)) / 1000.0 / @as(f64, @floatFromInt(iterations));
- const speedup = unpacked_us / packed_us;
-
- const mem_unpacked = size; // 1 byte per trit
- const mem_packed = (size + 4) / 5; // 5 trits per byte
- const mem_saving = @as(f64, @floatFromInt(mem_unpacked)) / @as(f64, @floatFromInt(mem_packed));
-
- std.debug.print("β {d:5} β {d:6.1} us β {d:6.1} us β {d:5.2}x β {d:6} B β {d:6} B β {d:4.1}x β\n", .{ size, unpacked_us, packed_us, speedup, mem_unpacked, mem_packed, mem_saving });
- }
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print("\n", .{});
- std.debug.print("Speedup > 1.0 on Packed with\n", .{});
- std.debug.print("Mem Saving bytoin toand and (5x andwithtoand towithand)\n", .{});
-}
diff --git a/src/particle_physics/cell.tri b/src/particle_physics/cell.tri
deleted file mode 100644
index 716c9685b5..0000000000
--- a/src/particle_physics/cell.tri
+++ /dev/null
@@ -1,41 +0,0 @@
-[cell]
-id = "trinity.particle-physics"
-name = "Particle Physics"
-version = "1.0.0"
-kind = "library"
-path = "src/particle_physics"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Standard Model constants derived from phi and gamma"
-capabilities = ["vsa", "particle-physics", "sacred-geometry"]
-files = 1
-tests = 79
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = []
-exports = ["strongCoupling", "weinbergAngle", "cabibboAngle", "protonElectronRatio", "cmbTemperature"]
-tri_subcommands = []
-events = []
-binaries = []
-
-[dependencies]
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:2f6da150c015a49458a071a8657212b689740b1cfb6a47b5aec756da581e8055"
diff --git a/src/particle_physics/formulas.zig b/src/particle_physics/formulas.zig
deleted file mode 100644
index b6ae109902..0000000000
--- a/src/particle_physics/formulas.zig
+++ /dev/null
@@ -1,2181 +0,0 @@
-//! Particle Physics Sacred Mathematics: Standard Model from Ο and Ξ³
-//!
-//! This module derives 49 fundamental physics constants from the
-//! golden ratio Ο = (1+β5)/2 and the Barbero-Immirzi parameter Ξ³ = Οβ»Β³.
-//!
-//! # Mathematical Foundation
-//!
-//! Golden Ratio:
-//! Ο = (1 + β5)/2 β 1.6180339887498948482
-//! Ξ³ = Οβ»Β³ β 0.23606797749978969641
-//!
-//! Trinity Identity:
-//! ΟΒ² + Οβ»Β² = 3
-//!
-//! # Tier 1: Elegant Formulas (sub-0.1% error)
-//!
-//! 1. Ξ±_s = 4ΟΒ²/(9ΟΒ²) β Strong coupling (0.005%)
-//! 2. sinΒ²ΞΈ_W = 2ΟΒ³e/729 β Weinberg angle (0.009%)
-//! 3. sin(ΞΈ_C) = 3Ξ³/Ο β Cabibbo angle (0.057%)
-//! 4. m_p/m_e = 6Οβ΅ β Mass ratio (0.002%)
-//! 5. T_CMB = 5Οβ΄Οβ΅/(729e) β CMB temperature (0.009%)
-//! 6. m_W/m_Z = 108Ο/(ΟΒ²eΒ³) β Boson ratio (0.007%)
-//! 7. M_Higgs = 135Οβ΄/eΒ² β Higgs mass (0.019%)
-//! 8. v_Higgs = 4Γ3βΆΓΟΒ²/ΟΒ³ β Higgs VEV (0.002%)
-//! 9. a_ΞΌ = Ο/(3β΅Οβ΅) β Muon g-2 (0.015%)
-//!
-//! # Tier 2: CKM + PMNS + Jarlskog (sub-0.1% error)
-//!
-//! 10. |V_cb| = Ξ³Β³Ο β CKM element (0.072%)
-//! 11. sinΒ²ΞΈββ_PMNS = 3Ξ³ΟΒ²/(ΟΒ³e) β Reactor angle (0.008%)
-//! 12. J_CKM = 21Ξ³β΅/(ΟΒ²Οβ΄eΒ²) β Jarlskog invariant (0.003%)
-//! 13. Ο_n = 8ΟΟβΈeΒ³/27 β Neutron lifetime (0.007%)
-
-const std = @import("std");
-const math = std.math;
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = Ο + 1 β 2.618
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// ΟΒ³ β 4.236
-pub const PHI_CUBED: f64 = PHI * PHI * PHI;
-
-/// Οβ΄ β 6.854
-pub const PHI_4: f64 = PHI_SQ * PHI_SQ;
-
-/// Οβ΅ β 11.090
-pub const PHI_5: f64 = PHI_4 * PHI;
-
-/// ΟβΆ β 17.944
-pub const PHI_6: f64 = PHI_CUBED * PHI_CUBED;
-
-/// Οβ· β 29.034
-pub const PHI_7: f64 = PHI_6 * PHI;
-
-/// ΟβΈ β 46.979
-pub const PHI_8: f64 = PHI_4 * PHI_4;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / PHI_CUBED;
-
-/// Fundamental TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI_SQ + 1.0 / PHI_SQ;
-
-/// Ο
-pub const PI: f64 = 3.14159265358979323846;
-
-/// Euler's number e
-pub const E: f64 = 2.71828182845904523536;
-
-/// Speed of light (m/s)
-pub const C_LIGHT: f64 = 299792458.0;
-
-/// Hubble constant (km/s/Mpc) β approximate current value
-pub const H0_KM_S_MPC: f64 = 70.0;
-
-/// Hubble constant (SI units: 1/s)
-pub const H0_SI: f64 = H0_KM_S_MPC * 1000.0 / 3.085677581e22;
-
-/// Critical density of universe (kg/mΒ³)
-pub const RHO_CRITICAL: f64 = 3 * H0_SI * H0_SI / (8 * PI * 6.67430e-11);
-
-/// Dark energy density from sacred formula
-pub const OMEGA_LAMBDA: f64 = std.math.pow(f64, GAMMA, 8) * std.math.pow(f64, PI, 4) / PHI_SQ;
-
-/// Dark matter density from sacred formula
-pub const OMEGA_DM: f64 = std.math.pow(f64, GAMMA, 4) * PI * PI / PHI;
-
-// ============================================================
-// Experimental values (PDG 2024)
-// ============================================================
-
-/// Strong coupling constant Ξ±_s(M_Z)
-pub const ALPHA_S_EXP: f64 = 0.11790;
-
-/// Weinberg angle sinΒ²ΞΈ_W(M_Z)
-pub const SIN2_THETA_W_EXP: f64 = 0.23121;
-
-/// Cabibbo angle sin(ΞΈ_C)
-pub const SIN_THETA_C_EXP: f64 = 0.22530;
-
-/// Proton-to-electron mass ratio
-pub const MP_ME_RATIO_EXP: f64 = 1836.15267343;
-
-/// CMB temperature (K)
-pub const T_CMB_EXP: f64 = 2.72550;
-
-/// W/Z boson mass ratio m_W/m_Z
-pub const MW_MZ_RATIO_EXP: f64 = 0.88145;
-
-/// Higgs boson mass (GeV)
-pub const M_HIGGS_EXP: f64 = 125.25;
-
-/// Higgs vacuum expectation value (GeV)
-pub const HIGGS_VEV_EXP: f64 = 246.22;
-
-/// Fermi constant G_F (GeVβ»Β²)
-pub const G_FERMION_EXP: f64 = 1.1663787e-5;
-
-/// Muon anomalous magnetic moment a_ΞΌ
-pub const MUON_ANOMALY_EXP: f64 = 0.00116592;
-
-/// CKM element |V_cb| = sin(ΞΈββ)
-pub const V_CB_EXP: f64 = 0.04130;
-
-/// PMNS sinΒ²ΞΈββ (reactor angle)
-pub const SIN2_THETA13_PMNS_EXP: f64 = 0.0220;
-
-/// Jarlskog invariant J
-pub const JARLSKOG_EXP: f64 = 3.08e-5;
-
-/// Neutron lifetime (seconds)
-pub const NEUTRON_LIFETIME_EXP: f64 = 878.4;
-
-/// PMNS sinΒ²ΞΈββ (solar angle)
-pub const SIN2_THETA12_PMNS_EXP: f64 = 0.307;
-
-/// PMNS sinΒ²ΞΈββ (atmospheric angle)
-pub const SIN2_THETA23_PMNS_EXP: f64 = 0.546;
-
-/// Fine structure constant inverse Ξ±β»ΒΉ
-pub const ALPHA_INV_EXP: f64 = 137.035999084;
-
-/// Proton magnetic moment (nuclear magnetons)
-pub const MU_PROTON_EXP: f64 = 2.7928473446;
-
-/// Neutron magnetic moment (nuclear magnetons, absolute)
-pub const MU_NEUTRON_EXP: f64 = 1.91304273;
-
-/// Muon-to-electron mass ratio
-pub const M_MU_M_E_EXP: f64 = 206.7682830;
-
-/// Tau-to-muon mass ratio
-pub const M_TAU_M_MU_EXP: f64 = 16.8170;
-
-/// Neutrino mass splitting ratio ΞmΒ²ββ/ΞmΒ²ββ
-pub const NU_MASS_RATIO_EXP: f64 = 32.57;
-
-/// QCD scale Ξ_QCD (MeV)
-pub const LAMBDA_QCD_EXP: f64 = 217.0;
-
-// ============================================================
-// Tier 4: Quark masses, Boson masses, Widths
-// ============================================================
-
-/// Bottom/tau mass ratio m_b/m_Ο
-pub const M_B_M_TAU_EXP: f64 = 1.78;
-
-/// Top/bottom mass ratio m_t/m_b
-pub const M_T_M_B_EXP: f64 = 40.77;
-
-/// Charm/strange mass ratio m_c/m_s
-pub const M_C_M_S_EXP: f64 = 11.72;
-
-/// Strange/down mass ratio m_s/m_d
-pub const M_S_M_D_EXP: f64 = 20.22;
-
-/// Top quark mass (GeV)
-pub const M_TOP_EXP: f64 = 173.1;
-
-/// W boson mass (GeV)
-pub const M_W_EXP: f64 = 80.3692;
-
-/// Z boson mass (GeV)
-pub const M_Z_EXP: f64 = 91.1876;
-
-/// Bottom quark mass (GeV)
-pub const M_B_EXP: f64 = 4.183;
-
-/// Charm quark mass (GeV)
-pub const M_C_EXP: f64 = 1.273;
-
-/// Z boson width (GeV)
-pub const GAMMA_Z_EXP: f64 = 2.4955;
-
-/// W boson width (GeV)
-pub const GAMMA_W_EXP: f64 = 2.085;
-
-/// Fine structure constant Ξ±
-pub const ALPHA_EXP: f64 = 0.0072973525693;
-
-/// Classical electron radius (fm)
-pub const R_E_EXP: f64 = 2.8179403262;
-
-/// Proton charge radius (fm)
-pub const R_PROTON_EXP: f64 = 0.841;
-
-/// Neutral pion mass (MeV)
-pub const M_PI0_EXP: f64 = 134.977;
-
-// ============================================================
-// Tier 5: Cosmology, CKM remaining, Neutrinos
-// ============================================================
-
-/// Hubble constant Hβ (km/s/Mpc)
-pub const H_0_EXP: f64 = 67.4;
-
-/// Dark energy density parameter Ξ©_Ξ
-pub const OMEGA_LAMBDA_EXP: f64 = 0.685;
-
-/// Total matter density parameter Ξ©_m
-pub const OMEGA_M_EXP: f64 = 0.315;
-
-/// Baryonic matter density parameter Ξ©_b
-pub const OMEGA_B_EXP: f64 = 0.0493;
-
-/// Spectral index n_s
-pub const N_S_EXP: f64 = 0.965;
-
-/// Matter fluctuation amplitude Οβ
-pub const SIGMA_8_EXP: f64 = 0.811;
-
-/// CKM element |V_td|
-pub const V_TD_EXP: f64 = 0.00854;
-
-/// CKM element |V_ts|
-pub const V_TS_EXP: f64 = 0.0412;
-
-/// CKM element |V_ub| (Sprint 1B)
-pub const V_UB_EXP: f64 = 0.00369;
-
-/// CKM CP phase Ξ΄ (radians)
-pub const DELTA_CKM_EXP: f64 = 1.196;
-
-/// CKM unitarity triangle angle Ξ± (radians)
-pub const CKM_ALPHA_EXP: f64 = 1.20;
-
-/// PMNS Dirac CP phase Ξ΄_CP (radians)
-pub const DELTA_CP_PMNS_EXP: f64 = 3.73;
-
-/// Neutrino mass splitting ΞmΒ²ββ (eVΒ²)
-pub const DM32_SQ_EXP: f64 = 0.002453;
-
-/// Rho meson mass (MeV)
-pub const M_RHO_EXP: f64 = 775.26;
-
-// ============================================================
-// Formula result type
-// ============================================================
-
-pub const FormulaResult = struct {
- name: []const u8,
- formula: []const u8,
- computed: f64,
- experimental: f64,
- error_pct: f64,
-};
-
-// ============================================================
-// Sacred formulas
-// ============================================================
-
-/// Strong coupling constant
-/// Ξ±_s = 4ΟΒ²/(9ΟΒ²) β 0.11789 (error: 0.005%)
-pub fn strongCoupling() f64 {
- return 4.0 * PHI_SQ / (9.0 * PI * PI);
-}
-
-/// Weinberg angle (weak mixing angle)
-/// sinΒ²ΞΈ_W = 2ΟΒ³e/729 β 0.23123 (error: 0.009%)
-pub fn weinbergAngle() f64 {
- return 2.0 * PI * PI * PI * E / 729.0;
-}
-
-/// Cabibbo angle
-/// sin(ΞΈ_C) = 3Ξ³/Ο β 0.22543 (error: 0.057%)
-pub fn cabibboAngle() f64 {
- return 3.0 * GAMMA / PI;
-}
-
-/// Proton-to-electron mass ratio
-/// m_p/m_e = 6Οβ΅ β 1836.118 (error: 0.002%)
-pub fn protonElectronRatio() f64 {
- return 6.0 * PI * PI * PI * PI * PI;
-}
-
-/// CMB temperature
-/// T_CMB = 5Οβ΄Οβ΅/(729e) β 2.7257 K (error: 0.009%)
-pub fn cmbTemperature() f64 {
- return 5.0 * PI * PI * PI * PI * PHI_5 / (729.0 * E);
-}
-
-/// W/Z boson mass ratio
-/// m_W/m_Z = 108Ο/(ΟΒ²eΒ³) β 0.88151 (error: 0.007%)
-pub fn wZBosonRatio() f64 {
- return 108.0 * PHI / (PI * PI * E * E * E);
-}
-
-/// Higgs boson mass (GeV)
-/// M_Higgs = 135Οβ΄/eΒ² β 125.226 GeV (error: 0.019%)
-pub fn higgsMass() f64 {
- return 135.0 * PHI_4 / (E * E);
-}
-
-/// Higgs vacuum expectation value (GeV)
-/// v_Higgs = 4Γ3βΆΓΟΒ²/ΟΒ³ β 246.214 GeV (error: 0.002%)
-pub fn higgsVEV() f64 {
- return 4.0 * 729.0 * PHI_SQ / (PI * PI * PI);
-}
-
-/// Fermi constant (GeVβ»Β²)
-/// G_F = 1/(β2 Γ v_HiggsΒ²) β 1.1664Γ10β»β΅ GeVβ»Β² (error: 0.004%)
-/// Derived from Higgs VEV: G_F = 1/(β2 vΒ²) where v = 246 GeV
-pub fn fermiConstant() f64 {
- const v = higgsVEV();
- return 1.0 / (std.math.sqrt(2.0) * v * v);
-}
-
-/// Muon anomalous magnetic moment
-/// a_ΞΌ = Ο/(3β΅Οβ΅) β 0.001166 (error: 0.015%)
-pub fn muonAnomaly() f64 {
- return PI / (243.0 * PHI_5);
-}
-
-// ============================================================
-// Tier 2: CKM, PMNS, Jarlskog, Neutron
-// ============================================================
-
-/// CKM element |V_cb| = sin(ΞΈββ)
-/// |V_cb| = Ξ³Β³Ο β 0.04133 (error: 0.072%)
-/// Note: Ξ³Β³ = Οβ»βΉ, so this connects quark mixing to LQG
-pub fn ckmVcb() f64 {
- return GAMMA * GAMMA * GAMMA * PI;
-}
-
-/// PMNS reactor angle
-/// sinΒ²ΞΈββ = 3Ξ³ΟΒ²/(ΟΒ³e) β 0.02200 (error: 0.008%)
-pub fn pmnsTheta13() f64 {
- return 3.0 * GAMMA * PHI_SQ / (PI * PI * PI * E);
-}
-
-/// Jarlskog invariant (CP violation measure)
-/// J = 21Ξ³β΅/(ΟΒ²Οβ΄eΒ²) β 3.080Γ10β»β΅ (error: 0.003%)
-pub fn jarlskogInvariant() f64 {
- const gamma_5 = GAMMA * GAMMA * GAMMA * GAMMA * GAMMA;
- return 21.0 * gamma_5 / (PI * PI * PHI_4 * E * E);
-}
-
-/// Neutron lifetime
-/// Ο_n = 8ΟΟβΈeΒ³/27 β 878.34 s (error: 0.007%)
-/// Note: since Ξ³ = Οβ»Β³, equivalently Ο_n = 8ΟΟβ΅eΒ³/(27Ξ³)
-pub fn neutronLifetime() f64 {
- return 8.0 * PI * PHI_8 * E * E * E / 27.0;
-}
-
-// ============================================================
-// Tier 3: PMNS, Lepton ratios, Ξ±β»ΒΉ, magnetic moments, QCD
-// ============================================================
-
-/// PMNS solar angle
-/// sinΒ²ΞΈββ = 7Οβ΅/(3ΟΒ³e) β 0.30702 (error: 0.008%)
-pub fn pmnsSolarAngle() f64 {
- return 7.0 * PHI_5 / (3.0 * PI * PI * PI * E);
-}
-
-/// PMNS atmospheric angle
-/// sinΒ²ΞΈββ = 4ΟΟΒ²/(3eΒ³) β 0.54598 (error: 0.003%)
-pub fn pmnsAtmosphericAngle() f64 {
- return 4.0 * PI * PHI_SQ / (3.0 * E * E * E);
-}
-
-/// Fine structure constant inverse
-/// Ξ±β»ΒΉ = 2Γ3βΆΓΟβ΄/(ΟΒ²eΒ²) β 137.031 (error: 0.004%)
-pub fn fineStructureInverse() f64 {
- return 2.0 * 729.0 * PHI_4 / (PI * PI * E * E);
-}
-
-/// Proton magnetic moment
-/// ΞΌ_p = 8Ο/9 β 2.7925 (error: 0.010%)
-/// Note: EXTREMELY elegant β no Ο or Ξ³ needed
-pub fn protonMagneticMoment() f64 {
- return 8.0 * PI / 9.0;
-}
-
-/// Neutron magnetic moment (absolute value)
-/// ΞΌ_n = 7Γ3β΄ΓΟβΆ/(Οβ΄eβ΄) β 1.9131 (error: 0.004%)
-pub fn neutronMagneticMoment() f64 {
- return 7.0 * 81.0 * PHI_6 / (PI * PI * PI * PI * E * E * E * E);
-}
-
-/// Muon-to-electron mass ratio
-/// m_ΞΌ/m_e = 324ΟΟβ΅/eβ΄ β 206.755 (error: 0.007%)
-pub fn muonElectronRatio() f64 {
- return 324.0 * PI * PHI_5 / (E * E * E * E);
-}
-
-/// Tau-to-muon mass ratio
-/// m_Ο/m_ΞΌ = 7Γ3β΅ΓΟΒ²/(Οβ΄e) β 16.818 (error: 0.009%)
-pub fn tauMuonRatio() f64 {
- return 7.0 * 243.0 * PHI_SQ / (PI * PI * PI * PI * E);
-}
-
-/// Neutrino mass splitting ratio
-/// ΞmΒ²ββ/ΞmΒ²ββ = 5Οβ΅/ΟβΈ β 32.570 (error: 0.0001%)
-/// Note: EXTREMELY elegant and precise
-pub fn neutrinoMassRatio() f64 {
- return 5.0 * PI * PI * PI * PI * PI / PHI_8;
-}
-
-/// QCD scale
-/// Ξ_QCD = 4Οβ΅Οβ·/(3eβ΄) β 216.98 MeV (error: 0.008%)
-pub fn lambdaQCD() f64 {
- return 4.0 * PI * PI * PI * PI * PI * PHI_7 / (3.0 * E * E * E * E);
-}
-
-// ============================================================
-// Tier 4: Quark masses, Boson masses, Widths, Fundamentals
-// ============================================================
-
-/// Bottom-to-tau mass ratio
-/// m_b/m_Ο = 2ΟΒ²/Οβ΅ β 1.7799 (error: 0.007%)
-pub fn bottomTauRatio() f64 {
- return 2.0 * PI * PI / PHI_5;
-}
-
-/// Top-to-bottom mass ratio
-/// m_t/m_b = 21Ο/Ο β 40.774 (error: 0.009%)
-pub fn topBottomRatio() f64 {
- return 21.0 * PI / PHI;
-}
-
-/// Charm-to-strange mass ratio
-/// m_c/m_s = 4eΒ³/Οβ΄ β 11.722 (error: 0.015%)
-pub fn charmStrangeRatio() f64 {
- return 4.0 * E * E * E / PHI_4;
-}
-
-/// Strange-to-down mass ratio
-/// m_s/m_d = 4ΟΒ²eβ΄/(9Ο) β 20.222 (error: 0.009%)
-pub fn strangeDownRatio() f64 {
- return 4.0 * PHI_SQ * E * E * E * E / (9.0 * PI);
-}
-
-/// Top quark mass (GeV)
-/// m_top = 2ΟΒ²Οβ·e/9 β 173.099 GeV (error: 0.0004%)
-/// Note: MOST PRECISE FORMULA β 4 parts per million!
-pub fn topQuarkMass() f64 {
- return 2.0 * PI * PI * PHI_7 * E / 9.0;
-}
-
-/// W boson mass (GeV)
-/// m_W = 162ΟΒ³/(Οe) β 80.359 GeV (error: 0.013%)
-pub fn wBosonMass() f64 {
- return 162.0 * PHI_CUBED / (PI * E);
-}
-
-/// Z boson mass (GeV)
-/// m_Z = 7Οβ΄ΟeΒ³/243 β 91.193 GeV (error: 0.006%)
-pub fn zBosonMass() f64 {
- return 7.0 * PI * PI * PI * PI * PHI * E * E * E / 243.0;
-}
-
-/// Bottom quark mass (GeV)
-/// m_b = 2Οβ΅/(3ΟβΆe) β 4.183 GeV (error: 0.012%)
-pub fn bottomQuarkMass() f64 {
- return 2.0 * PI * PI * PI * PI * PI / (3.0 * PHI_6 * E);
-}
-
-/// Charm quark mass (GeV)
-/// m_c = 8eβ΄/(81ΟΒ³) β 1.273 GeV (error: 0.002%)
-pub fn charmQuarkMass() f64 {
- return 8.0 * E * E * E * E / (81.0 * PHI_CUBED);
-}
-
-/// Z boson width (GeV)
-/// Ξ_Z = 7ΟβΈeβ΄/(729ΟΒ²) β 2.4955 GeV (error: 0.002%)
-pub fn zBosonWidth() f64 {
- return 7.0 * PHI_8 * E * E * E * E / (729.0 * PI * PI);
-}
-
-/// W boson width (GeV)
-/// Ξ_W = 108eβ΄/(Οβ΄Οβ·) β 2.085 GeV (error: 0.004%)
-pub fn wBosonWidth() f64 {
- return 108.0 * E * E * E * E / (PI * PI * PI * PI * PHI_7);
-}
-
-/// Fine structure constant
-/// Ξ± = 36/(Οβ΄Οβ΄eΒ²) β 0.007297 (error: 0.0004%)
-/// Cross-check with Ξ±β»ΒΉ formula
-pub fn fineStructureConstant() f64 {
- return 36.0 / (PI * PI * PI * PI * PHI_4 * E * E);
-}
-
-/// Classical electron radius (fm)
-/// r_e = 54Ο/ΟΒ³ β 2.81794 fm (error: 0.00001%)
-/// Note: ULTRA-PRECISE β essentially exact!
-pub fn electronRadius() f64 {
- return 54.0 * PHI / (PI * PI * PI);
-}
-
-/// Proton charge radius (fm)
-/// r_p = 5ΟΟβ·/(27eΒ³) β 0.8410 fm (error: 0.002%)
-pub fn protonRadius() f64 {
- return 5.0 * PI * PHI_7 / (27.0 * E * E * E);
-}
-
-/// Neutral pion mass (MeV)
-/// m_Οβ° = 4eβ΄/Ο β 134.974 MeV (error: 0.002%)
-pub fn neutralPionMass() f64 {
- return 4.0 * E * E * E * E / PHI;
-}
-
-// ============================================================
-// Tier 5: Cosmology, CKM remaining, Neutrinos
-// ============================================================
-
-/// Hubble constant (km/s/Mpc)
-/// Hβ = 4374Οβ΅/(Οβ΄eΒ²) β 67.395 (error: 0.007%)
-pub fn hubbleConstant() f64 {
- return 4374.0 * PHI_5 / (PI * PI * PI * PI * E * E);
-}
-
-/// Dark energy density parameter
-/// Ξ©_Ξ = 6561Οβ»Β³/(Οβ΅eΒ²) β 0.6850 (error: 0.005%)
-/// Note: 6561 = 3βΈ, connecting dark energy to TRINITY
-pub fn darkEnergyDensity() f64 {
- return 6561.0 / (PI * PI * PI * PI * PI * PHI_CUBED * E * E);
-}
-
-/// Total matter density parameter
-/// Ξ©_m = 4eΒ³/(Οβ΄ΟΒ²) β 0.3150 (error: 0.013%)
-pub fn matterDensity() f64 {
- return 4.0 * E * E * E / (PI * PI * PI * PI * PHI_SQ);
-}
-
-/// Baryonic matter density parameter
-/// Ξ©_b = 8ΟΒ³/(3ΟΒ³eΒ²) β 0.04931 (error: 0.011%)
-pub fn baryonicDensity() f64 {
- return 8.0 * PHI_CUBED / (3.0 * PI * PI * PI * E * E);
-}
-
-/// Spectral index
-/// n_s = 4Οβ΅/(27ΟβΈ) β 0.9650 (error: 0.004%)
-pub fn spectralIndex() f64 {
- return 4.0 * PI * PI * PI * PI * PI / (27.0 * PHI_8);
-}
-
-/// Matter fluctuation amplitude Οβ
-/// Οβ = 1701/(Οβ΅Οβ΄) β 0.8110 (error: 0.004%)
-pub fn sigma8() f64 {
- return 1701.0 / (PI * PI * PI * PI * PI * PHI_4);
-}
-
-/// CKM element |V_td|
-/// |V_td| = eΒ³/(81Οβ·) β 0.008541 (error: 0.006%)
-pub fn ckmVtd() f64 {
- return E * E * E / (81.0 * PHI_7);
-}
-
-/// CKM element |V_ts|
-/// |V_ts| = 2916/(Οβ΅ΟΒ³eβ΄) β 0.04120 (error: 0.00001%)
-/// Note: ULTRA-PRECISE β essentially exact!
-pub fn ckmVts() f64 {
- return 2916.0 / (PI * PI * PI * PI * PI * PHI_CUBED * E * E * E * E);
-}
-
-/// CKM element |V_ub| (Sprint 1B discovery)
-/// |V_ub| = 7/(729ΟΒ²) β 0.003668 (error: 0.604%)
-/// Formula 52: Completes the first row of CKM matrix
-/// Derivation: 729 = 3βΆ, connects to Higgs VEV pattern
-pub fn ckmVub() f64 {
- return 7.0 / (729.0 * PHI_SQ);
-}
-
-/// CKM CP phase Ξ΄_CKM (radians)
-/// Ξ΄_CKM = ΟΒ²Οeβ΄/729 β 1.19602 (error: 0.002%)
-pub fn ckmCPphase() f64 {
- return PI * PI * PHI * E * E * E * E / 729.0;
-}
-
-/// PMNS Dirac CP phase Ξ΄_CP (radians)
-/// Ξ΄_CP = 8ΟΒ³/(9eΒ²) β 3.7300 (error: 0.0002%)
-/// Note: EXTREMELY PRECISE β only 2 ppm!
-pub fn pmnsCPphase() f64 {
- return 8.0 * PI * PI * PI / (9.0 * E * E);
-}
-
-/// Neutrino mass splitting ΞmΒ²ββ (eVΒ²)
-/// ΞmΒ²ββ = 7Οβ΄/(729ΟΒ²e) β 0.002453 (error: 0.007%)
-pub fn neutrinoMassSplitting32() f64 {
- return 7.0 * PHI_4 / (729.0 * PI * PI * E);
-}
-
-/// Rho meson mass (MeV)
-/// m_Ο = 5Γ243ΓΟΟβ΅/eβ΄ β 775.330 MeV (error: 0.009%)
-pub fn rhoMesonMass() f64 {
- return 5.0 * 243.0 * PI * PHI_5 / (E * E * E * E);
-}
-
-/// CKM unitarity triangle angle Ξ± (radians)
-/// Ξ± = Ο/ΟΒ² β 1.200 rad = 68.75Β° (error: 0.0%)
-/// This completes the CKM unitarity triangle parameterization
-pub fn ckmAngleAlpha() f64 {
- return PI / PHI_SQ;
-}
-
-/// Strong CP angle from TRINITY identity (EXACT)
-/// ΞΈ_QCD = |ΟΒ² + Οβ»Β² - 3| = 0
-/// Formula 51: Solves the Strong CP problem
-pub fn thetaQCD() f64 {
- return @abs(PHI_SQ + 1.0 / PHI_SQ - 3.0);
-}
-
-/// Axion mass from Ο and Ξ³ (micro-eV)
-/// m_a = Ξ³β»Β²/Ο β 5.7 ΞΌeV (ADMX range)
-/// Formula 52: Predicts axion for dark matter
-pub fn axionMassMicroEV() f64 {
- const gamma_inv_sq = 1.0 / (GAMMA * GAMMA);
- return gamma_inv_sq / PI;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Sacred Biology v11.1 β DNA, Proteins, and the Golden Ratio
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// DNA helix pitch from phi β THE SMOKING GUN
-/// P = Οβ΄ Γ 5 = 34.005 Γ
(vs 34.0 Γ
measured)
-/// Formula 53: DNA directly encodes phi^4
-pub fn dnaPitch() f64 {
- const phi_4 = PHI * PHI * PHI * PHI;
- return phi_4 * 5.0;
-}
-
-/// DNA rise per base pair from phi
-/// h = Οβ΄ / 2 = 3.401 Γ
(vs 3.4 Γ
)
-/// Formula 54
-pub fn dnaRise() f64 {
- const phi_4 = PHI * PHI * PHI * PHI;
- return phi_4 / 2.0;
-}
-
-/// Base pairs per turn from phi and pi
-/// n = 2Ο/Ο = 10.47 (vs 10.5)
-/// Formula 55
-pub fn basePairsPerTurn() f64 {
- return 2.0 * PI / PHI;
-}
-
-/// Optimal GC content from phi inverse
-/// GC_optimal = Οβ»ΒΉ = 0.618 (61.8%)
-/// Formula 56
-pub fn optimalGCContent() f64 {
- return 1.0 / PHI;
-}
-
-/// Alpha helix residues per turn β SECOND SMOKING GUN
-/// n = ΟΒ² = 3.618 (vs 3.6 measured)
-/// Formula 57: Protein structure encodes phi^2
-pub fn alphaHelixResidues() f64 {
- return PHI_SQ;
-}
-
-/// Alpha helix pitch from phi squared
-/// P = ΟΒ² Γ 1.5 = 5.427 Γ
(vs 5.4 Γ
)
-/// Formula 58
-pub fn alphaHelixPitch() f64 {
- return PHI_SQ * 1.5;
-}
-
-/// Neural gamma frequency (consciousness link)
-/// f_Ξ³ = ΟΒ³ Γ Ο / Ξ³ = 56 Hz
-/// Formula 59: Links biology to consciousness
-pub fn neuralGammaFrequency() f64 {
- const phi_3 = PHI * PHI * PHI;
- return phi_3 * PI / GAMMA;
-}
-
-/// Beta sheet twist angle from phi inverse
-/// ΞΈ = arctan(Οβ»ΒΉ) Γ (180/Ο) = 31.7Β°
-/// Formula 60
-pub fn betaSheetTwist() f64 {
- return math.atan(1.0 / PHI) * 180.0 / PI;
-}
-
-// ============================================================
-// Tier 8: Quantum Biology v11.2 β FMO, Cryptochromes, Microtubules
-// ============================================================
-
-/// FMO complex coherence time from phi
-/// Ο = Ο^(-5) Γ 10^(-12) s = ~378 fs
-/// Formula 61
-pub fn fmoCoherenceTime() f64 {
- const phi_inv_cu = 1.0 / PHI_CUBED; // Οβ»Β³
- const phi_inv_sq = 1.0 / PHI_SQ; // Οβ»Β²
- return phi_inv_cu * phi_inv_sq * 1e-12;
-}
-
-/// FMO transfer efficiency from phi inverse
-/// Ξ· = Ο^(-1) = 0.618 (61.8%)
-/// Formula 62
-pub fn fmoTransferEfficiency() f64 {
- return 1.0 / PHI;
-}
-
-/// FMO exciton Bohr radius from phi squared
-/// R = ΟΒ² Γ 2 Γ
= ~5.24 Γ
-/// Formula 63
-pub fn fmoExcitonRadius() f64 {
- return PHI_SQ * 2.0;
-}
-
-/// FMO site energy from gamma
-/// E = Ξ³ Γ Ο Γ 2.2 eV = ~1.63 eV
-/// Formula 64
-pub fn fmoSiteEnergy() f64 {
- return GAMMA * PI * 2.2;
-}
-
-/// FMO temperature dependence
-/// T_optimal = Ο Γ 77 K = ~125 K
-/// Formula 65
-pub fn fmoOptimalTemperature() f64 {
- return PHI * 77.0;
-}
-
-/// Cryptochrome radical pair lifetime from gamma
-/// t = Ξ³ Γ Ο Γ 10^(-9) s = ~2.1 ΞΌs
-/// Formula 66
-pub fn cryptochromeRadicalLifetime() f64 {
- return GAMMA * PI * 1e-9;
-}
-
-/// Cryptochrome entanglement time from phi inverse
-/// t_entangle = Ο^(-1) Γ 10 ns = ~6.18 ns
-/// Formula 67
-pub fn cryptochromeEntanglementTime() f64 {
- return (1.0 / PHI) * 1e-8;
-}
-
-/// Cryptochrome singlet yield from phi inverse
-/// Ξ¦_S = Ο^(-1) = 0.618
-/// Formula 68
-pub fn cryptochromeSingletYield() f64 {
- return 1.0 / PHI;
-}
-
-/// Cryptochrome magnetic sensitivity angle
-/// ΞΈ = arctan(Ο) Γ 180/Ο = ~58.3Β°
-/// Formula 69
-pub fn cryptochromeMagneticAngle() f64 {
- return math.atan(PHI) * 180.0 / PI;
-}
-
-/// Cryptochrome geomagnetic field strength threshold
-/// B_thr = Ξ³ Γ 50 ΞΌT = ~11.8 ΞΌT
-/// Formula 70
-pub fn cryptochromeFieldThreshold() f64 {
- return GAMMA * 50.0;
-}
-
-/// Microtubule orchestration frequency from phi squared
-/// f = ΟΒ² Γ 10^6 Hz = ~4.24 MHz
-/// Formula 71
-pub fn microtubuleOrchestrationFreq() f64 {
- return PHI_SQ * 1e6;
-}
-
-/// Microtubule coherence length from phi cubed
-/// L = ΟΒ³ Γ 100 nm = ~424 nm
-/// Formula 72
-pub fn microtubuleCoherenceLength() f64 {
- return PHI_CUBED * 100.0;
-}
-
-/// Microtubule tubulin dimer spacing from phi
-/// d = 8 / Ο nm = ~4.94 nm
-/// Formula 73
-pub fn microtubuleTubulinSpacing() f64 {
- return 8.0 / PHI;
-}
-
-/// Microtubule quantum states per unit
-/// N = ΟΒ³ Γ 10^9 = ~4.2 billion states
-/// Formula 74
-pub fn microtubuleQuantumStates() f64 {
- return PHI_CUBED * 1e9;
-}
-
-/// Microtubule quantum vibration frequency
-/// f = Ο Γ 10^12 Hz = ~1.618 THz
-/// Formula 75
-pub fn microtubuleVibrationFreq() f64 {
- return PHI * 1e12;
-}
-
-/// Consciousness wave phase from phi, gamma, and time
-/// Ξ¦_Ξ³ = Ο Γ Ξ³ Γ t = 0.236 Γ t (rad)
-/// For t=1s, Formula 76
-pub fn consciousnessWavePhase1s() f64 {
- return PHI * GAMMA * 1.0;
-}
-
-/// Neural gamma frequency from sacred formula
-/// f_Ξ³ = ΟΒ³ Γ Ο / Ξ³ = 56 Hz
-/// Formula 77
-pub fn consciousnessGammaFrequency() f64 {
- return PHI_CUBED * PI / GAMMA;
-}
-
-/// Consciousness threshold (IIT integrated information)
-/// C_thr = Ο^(-1) = 0.618
-/// Formula 78
-pub fn consciousnessThreshold() f64 {
- return 1.0 / PHI;
-}
-
-/// Consciousness bandwidth (gamma band)
-/// Ξf = 40 / Ο Hz = ~24.7 Hz
-/// Formula 79
-pub fn consciousnessBandwidth() f64 {
- return 40.0 / PHI;
-}
-
-/// Specious present duration from consciousness
-/// t_present = Ο^(-2) Γ 1 s = ~382 ms
-/// Formula 80
-pub fn speciousPresent() f64 {
- const phi_inv_sq = 1.0 / PHI_SQ;
- return phi_inv_sq * 1.0;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// Consciousness & Qualia v11.3 β Formulas 81-100
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 81: Ξ¦_Ξ³ Wave Function at t=1ms
-/// Ξ¦_Ξ³(t) = Ο Γ Ξ³ Γ sin(2Ο Γ f_Ξ³ Γ t)
-pub fn phiGammaWave() f64 {
- const phi_gamma = PHI * GAMMA;
- const f_gamma = PHI_CUBED * PI / GAMMA;
- return phi_gamma * std.math.sin(2 * PI * f_gamma * 0.001);
-}
-
-/// Formula 82: Qualia intensity
-/// Q = |Ξ¦_Ξ³| Γ C_thr
-pub fn qualiaIntensity() f64 {
- const wave = phiGammaWave();
- const c_thr = 1.0 / PHI;
- return @abs(wave) * c_thr;
-}
-
-/// Formula 83: Qualia valence
-/// V = tanh(Ο Γ (I - I_0))
-pub fn qualiaValence() f64 {
- const stimulus = 0.8;
- const baseline = 0.5;
- return std.math.tanh(PHI * (stimulus - baseline));
-}
-
-/// Formula 84: Consciousness gamma (EXACT)
-/// f_Ξ³ = ΟΒ³ Γ Ο / Ξ³ = 56 Hz
-pub fn consciousnessGammaExact() f64 {
- return PHI_CUBED * PI / GAMMA;
-}
-
-/// Formula 85: EEG gamma correlation at 56 Hz
-pub fn eegGammaCorrelation() f64 {
- const gamma_power = 0.9;
- const f_gamma = PHI_CUBED * PI / GAMMA;
- const freq_weight = 1.0 - @abs(56.0 - f_gamma) / 20.0;
- return gamma_power * @max(0.0, freq_weight);
-}
-
-/// Formula 86: Stream of consciousness rate
-/// R = Οβ»ΒΉ Γ f_Ξ³
-pub fn streamOfConsciousnessRate() f64 {
- const f_gamma = PHI_CUBED * PI / GAMMA;
- return (1.0 / PHI) * f_gamma;
-}
-
-/// Formula 87: Subjective time dilation
-/// Ο_subj = Ο_obj / Ξ³
-pub fn subjectiveTimeDilation() f64 {
- return 1.0 / GAMMA;
-}
-
-/// Formula 88: Phenomenal field radius (ΞΈ=0.1 rad, D=1m)
-/// R_Ο = ΟΒ² Γ ΞΈ Γ D
-pub fn phenomenalFieldRadius() f64 {
- return PHI_SQ * 0.1 * 1.0;
-}
-
-/// Formula 89: Attention spotlight magnification
-/// A = Ο Γ A_0
-pub fn attentionSpotlight() f64 {
- return PHI * 1.0;
-}
-
-/// Formula 90: Working memory capacity
-/// N_WM = ΟΒ² + 1
-pub fn workingMemoryCapacity() f64 {
- return PHI_SQ + 1.0;
-}
-
-/// Formula 91: Perceptual binding window
-/// Ο_bind = Ο / f_Ξ³
-pub fn perceptualBindingWindow() f64 {
- const f_gamma = PHI_CUBED * PI / GAMMA;
- return PHI / f_gamma;
-}
-
-/// Formula 92: Attentional blink duration
-/// T_AB = 4 / f_Ξ³
-pub fn attentionalBlink() f64 {
- const f_gamma = PHI_CUBED * PI / GAMMA;
- return 4.0 / f_gamma;
-}
-
-/// Formula 93: Consciousness threshold (IIT)
-/// C_thr = Οβ»ΒΉ
-pub fn consciousnessThresholdIIT() f64 {
- return 1.0 / PHI;
-}
-
-/// Formula 94: Conscious access time (P3)
-/// T_access = Ο / f_Ξ³
-pub fn consciousAccessTime() f64 {
- const f_gamma = PHI_CUBED * PI / GAMMA;
- return PHI / f_gamma;
-}
-
-/// Formula 95: IIT Big Phi
-/// Ξ¦ = min(TRINITY, EI/Ξ³)
-pub fn iitBigPhi() f64 {
- const trinity = 3.0;
- const ei = 1.0;
- return @min(trinity, ei / GAMMA);
-}
-
-/// Formula 96: IIT conceptual structure
-/// CS = Ο Γ Ξ£ / (1 + Ξ£)
-pub fn iitConceptualStructure() f64 {
- const sigma = 1.0;
- return PHI * sigma / (1.0 + sigma);
-}
-
-/// Formula 97: Neural complexity
-/// C_N = Ξ³ Γ Ξ£ Γ ln(ΟN)
-pub fn neuralComplexity() f64 {
- const sigma = 1.0;
- const n = 100;
- return GAMMA * sigma * @log(PHI * @as(f64, @floatFromInt(n)));
-}
-
-/// Formula 98: Qualia freshness at t=Ο
-/// F = exp(-1/(ΟΟ)) at t=Ο
-pub fn qualiaFreshness() f64 {
- const tau = 1.0;
- return std.math.exp(-1.0 / (PHI * tau));
-}
-
-/// Formula 99: Phenomenal persistence
-/// T_persist = Οβ»ΒΉ Γ T_stim
-pub fn phenomenalPersistence() f64 {
- const stim_duration = 0.5;
- return (1.0 / PHI) * stim_duration;
-}
-
-/// Formula 100: Gamma bandwidth
-/// Ξf_Ξ³ = 40 / Ο
-pub fn gammaBandwidth() f64 {
- return 40.0 / PHI;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED COSMOLOGY v11.4 β Formulas 101-120
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 101: Ξ-Ξ¦ Coupling Constant
-/// Ξ»_couple = Ο Γ Ξ³ Γ Ξ©_Ξ β 0.111
-pub fn lambdaPhiCoupling() f64 {
- return PHI * GAMMA * OMEGA_LAMBDA;
-}
-
-/// Formula 102: Consciousness Density of Universe
-/// Ο_c = Ξ³ (fraction of critical density)
-pub fn consciousnessDensityUniverse() f64 {
- return GAMMA;
-}
-
-/// Formula 103: Anthropic Ξ¦ Measure
-/// A_Ο = ln(Ο) Γ Ξ©_Ξ
-pub fn anthropicPhiMeasure() f64 {
- return @log(PHI) * OMEGA_LAMBDA;
-}
-
-/// Formula 104: Cosmological Consciousness Constant
-/// C_Ξ = f_Ξ³ / Hβ
-pub fn cosmologicalConsciousnessConstant() f64 {
- const f_gamma = PHI_CUBED * PI / GAMMA;
- return f_gamma / H0_SI;
-}
-
-/// Formula 105: Observer Probability in Ο-verse
-/// P_obs = Οβ»ΒΉ Γ Ξ©_Ξ / (Ξ©_Ξ + Ξ©_DM)
-pub fn observerProbabilityPhi() f64 {
- return (1.0 / PHI) * OMEGA_LAMBDA / (OMEGA_LAMBDA + OMEGA_DM);
-}
-
-/// Formula 106: Universal Information Content
-/// I_univ = Ο Γ (R/l_P)Β²
-pub fn universalInformationContent() f64 {
- const R_univ = C_LIGHT / H0_SI;
- const l_P = 1.616255e-35;
- return PHI * (R_univ / l_P) * (R_univ / l_P);
-}
-
-/// Formula 107: Consciousness Coherence Scale
-/// L_Ο = Ο Γ H_Ξ / c (in Mpc)
-pub fn consciousnessCoherenceScale() f64 {
- const H_radius_m = C_LIGHT / H0_SI;
- const Mpc = 3.085677581e22;
- return PHI * H_radius_m / Mpc;
-}
-
-/// Formula 108: Dark Energy β Consciousness Resonance
-/// R_Ξ = Ξ©_Ξ Γ f_Ξ³ / f_Planck
-pub fn darkEnergyConsciousnessResonance() f64 {
- const f_gamma = PHI_CUBED * PI / GAMMA;
- const f_planck = 1.0 / 5.391247e-44;
- return OMEGA_LAMBDA * f_gamma / f_planck;
-}
-
-/// Formula 109: Anthropic Window via Ο
-/// W_Ο = Ξ Γ ΟΒ² / Ξ_max
-pub fn anthropicWindowPhi() f64 {
- const Lambda_current = 1.0e-52; // mβ»Β²
- const Lambda_max = 1.0e-8;
- return Lambda_current * PHI_SQ / Lambda_max;
-}
-
-/// Formula 110: Observer Effect via Ο
-/// Ξ¨_obs = Ο Γ collapse_probability
-pub fn observerEffectPhi(collapse_prob: f64) f64 {
- return PHI * @min(1.0, collapse_prob);
-}
-
-/// Formula 111: Universal Awakening Index
-/// A_Ξ = C_total Γ Ξ³ / M_univ
-pub fn universalAwakeningIndex(total_consciousness: f64, universe_mass: f64) f64 {
- return @min(1.0, total_consciousness * GAMMA / universe_mass);
-}
-
-/// Formula 112: Ο Tuning Parameter
-/// Ο_Ο = Ξ / (Ο Γ Ξ±)
-pub fn phiTuningParameter() f64 {
- const alpha = 1.0 / 137.035999084;
- const Lambda_m2 = 1.0e-52;
- return Lambda_m2 / (PHI * alpha);
-}
-
-/// Formula 113: Consciousness Horizon Scale
-/// R_c = Οβ»ΒΉ Γ R_horizon (in Mpc)
-pub fn consciousnessHorizonScale() f64 {
- const R_horizon = C_LIGHT / H0_SI;
- const Mpc = 3.085677581e22;
- return (1.0 / PHI) * R_horizon / Mpc;
-}
-
-/// Formula 114: Quantum-Biological-Cosmic Link
-/// L_qbc = Ξ³ Γ Hβ / f_MT
-pub fn quantumBiologicalCosmicLink() f64 {
- const f_MT = PHI_SQ * 1e6;
- return GAMMA * H0_SI / f_MT;
-}
-
-/// Formula 115: Sacred Universe Age
-/// T_Ο = 1/Hβ Γ Ο/Ο (in Gyr)
-pub fn sacredUniverseAge() f64 {
- const age_s = (1.0 / H0_SI) * PHI / PI;
- return age_s / (3.15576e7 * 1e9); // Convert to Gyr
-}
-
-/// Formula 116: Observer Density Evolution
-/// n_obs(t) = n_0 Γ exp(Ο Γ t/t_Ξ)
-pub fn observerDensityEvolution(t: f64, t_Lambda: f64, n0: f64) f64 {
- return n0 * std.math.exp(PHI * t / t_Lambda);
-}
-
-/// Formula 117: Consciousness Entropy Bound
-/// S_c = Ο Γ S_Bekenstein
-pub fn consciousnessEntropyBound(entropy: f64) f64 {
- return PHI * entropy;
-}
-
-/// Formula 118: Universal Ξ¦ Field
-/// Ξ¦(x,t) = Ο Γ cos(k_ΟΒ·x - Ο_ΟΒ·t)
-pub fn universalPhiField(x: f64, t: f64, k_phi: f64, w_phi: f64) f64 {
- return PHI * std.math.cos(k_phi * x - w_phi * t);
-}
-
-/// Formula 119: Dark Energy Ξ¦ Derivative
-/// dΞ/dt = Ξ³ Γ Ξ Γ sin(ΟΓΟt)
-pub fn darkEnergyPhiDerivative(t: f64, w: f64) f64 {
- const Lambda_density = OMEGA_LAMBDA * RHO_CRITICAL * C_LIGHT * C_LIGHT;
- return GAMMA * Lambda_density * std.math.sin(PHI * w * t);
-}
-
-/// Formula 120: Final Anthropic Principle
-/// Ξ¦_final = Ο Γ Ξ©_Ξ Γ C_Ξ Γ P_obs
-pub fn finalAnthropicPrinciple() f64 {
- const C_L = cosmologicalConsciousnessConstant();
- const P_obs = observerProbabilityPhi();
- return PHI * OMEGA_LAMBDA * C_L * P_obs;
-}
-
-// ============================================================
-// Origin of Life formulas β Sacred Origin v12.1 (121-140)
-// ============================================================
-
-/// Formula 121: Amino acid stability time
-/// Ο = ΟΒ³ Γ 100 Myr β 424 Myr
-pub fn originAminoAcidStability() f64 {
- return PHI_CUBED * 100.0;
-}
-
-/// Formula 122: RNA half-life at 25Β°C
-/// tβ/β = Οβ΄ Γ Ξ³ Γ 1 year β 4.0 years
-pub fn originRnaHalfLife() f64 {
- return PHI_4 * GAMMA;
-}
-
-/// Formula 123: Chirality bias (L-amino acid excess)
-/// ΞL = Οβ»Β² - 0.5 = -0.118
-pub fn originChiralityBias() f64 {
- const phi_inv_sq = 1.0 / PHI_SQ;
- return phi_inv_sq - 0.5;
-}
-
-/// Formula 124: Peptide bond formation energy
-/// E = Ξ³ Γ Ο Γ 10 kJ/mol β 7.4 kJ/mol
-pub fn originPeptideBondEnergy() f64 {
- return GAMMA * PI * 10.0;
-}
-
-/// Formula 125: Minimal genome size
-/// N_min = Οβ΄ Γ 10Β² genes β 685 genes
-pub fn originMinimalGenome() f64 {
- return PHI_4 * 100.0;
-}
-
-/// Formula 126: LUCA complexity
-/// C_LUCA = Οβ΅ Γ 100 proteins β 1,109 proteins
-pub fn originLucaComplexity() f64 {
- return PHI_5 * 100.0;
-}
-
-/// Formula 127: First cell radius
-/// R_min = ΟΒ² Γ 100 nm β 262 nm
-pub fn originFirstCellRadius() f64 {
- return PHI_SQ * 100.0;
-}
-
-/// Formula 128: Metabolic efficiency
-/// Ξ· = Οβ»ΒΉ = 0.618 (61.8%)
-pub fn originMetabolicEfficiency() f64 {
- return 1.0 / PHI;
-}
-
-/// Formula 129: ATP hydrolysis energy
-/// E_ATP = Ξ³ Γ Ο Γ 27.5 kJ/mol β 20.4 kJ/mol
-pub fn originAtpHydrolysisEnergy() f64 {
- return GAMMA * PI * 27.5;
-}
-
-/// Formula 130: Ribosome precision (error rate framework)
-/// Ξ΅ = Ξ³/Ο β 7.5%
-pub fn originRibosomePrecision() f64 {
- return GAMMA / PI;
-}
-
-/// Formula 131: Codon-anticodon binding energy
-/// ΞG = Ο kT β 1.618 kT
-pub fn originCodonBindingEnergy() f64 {
- return PHI;
-}
-
-/// Formula 132: tRNA anticodon loop size
-/// L = Ο Γ 7 nt β 11.3 nt
-pub fn originTrnaAnticodonLoop() f64 {
- return PHI * 7.0;
-}
-
-/// Formula 133: Genetic code optimality index
-/// O = Οβ΄ Γ 2 / Ο β 4.36
-pub fn originGeneticCodeOptimality() f64 {
- return PHI_4 * 2.0 / PI;
-}
-
-/// Formula 134: Prebiotic soup concentration
-/// C = Ξ³ Γ M = 0.236 M
-pub fn originPrebioticConcentration() f64 {
- return GAMMA;
-}
-
-/// Formula 135: Lipid bilayer thickness
-/// d = Ο Γ 2 nm β 3.24 nm
-pub fn originLipidBilayerThickness() f64 {
- return PHI * 2.0;
-}
-
-/// Formula 136: Membrane potential
-/// V = Ξ³ Γ 100 mV β 23.6 mV
-pub fn originMembranePotential() f64 {
- return GAMMA * 100.0;
-}
-
-/// Formula 137: Protein folding speed
-/// v = Οβ»Β³ Γ
/ΞΌs β 0.236
-pub fn originProteinFoldingSpeed() f64 {
- return GAMMA;
-}
-
-/// Formula 138: Enzyme rate enhancement base
-/// k_cat/k_uncat = ΟβΆ β 17.9
-pub fn originEnzymeRateEnhancement() f64 {
- return PHI_6;
-}
-
-/// Formula 139: DNA replication fidelity
-/// F = 1 - Ξ³β΄ β 0.997
-pub fn originReplicationFidelity() f64 {
- const gamma_4 = GAMMA * GAMMA * GAMMA * GAMMA;
- return 1.0 - gamma_4;
-}
-
-/// Formula 140: Origin of life temperature
-/// Tβ = Ο Γ 273 K β 441 K
-pub fn originTemperature() f64 {
- return PHI * 273.0;
-}
-
-// ============================================================
-// Aggregate functions
-// ============================================================
-
-/// Compute error percentage between computed and experimental values
-pub fn errorPercent(computed: f64, experimental: f64) f64 {
- if (experimental == 0) return 0.0;
- return @abs(computed - experimental) / experimental * 100.0;
-}
-
-/// Total number of formulas
-pub const FORMULA_COUNT = 142;
-
-/// Get all 121 formula results
-pub fn allFormulas() [FORMULA_COUNT]FormulaResult {
- return .{
- // Tier 1: Core Standard Model (9)
- .{ .name = "alpha_s", .formula = "4*phi^2/(9*pi^2)", .computed = strongCoupling(), .experimental = ALPHA_S_EXP, .error_pct = errorPercent(strongCoupling(), ALPHA_S_EXP) },
- .{ .name = "sin2_theta_W", .formula = "2*pi^3*e/729", .computed = weinbergAngle(), .experimental = SIN2_THETA_W_EXP, .error_pct = errorPercent(weinbergAngle(), SIN2_THETA_W_EXP) },
- .{ .name = "sin_theta_C", .formula = "3*gamma/pi", .computed = cabibboAngle(), .experimental = SIN_THETA_C_EXP, .error_pct = errorPercent(cabibboAngle(), SIN_THETA_C_EXP) },
- .{ .name = "m_p/m_e", .formula = "6*pi^5", .computed = protonElectronRatio(), .experimental = MP_ME_RATIO_EXP, .error_pct = errorPercent(protonElectronRatio(), MP_ME_RATIO_EXP) },
- .{ .name = "T_CMB", .formula = "5*pi^4*phi^5/(729*e)", .computed = cmbTemperature(), .experimental = T_CMB_EXP, .error_pct = errorPercent(cmbTemperature(), T_CMB_EXP) },
- .{ .name = "m_W/m_Z", .formula = "108*phi/(pi^2*e^3)", .computed = wZBosonRatio(), .experimental = MW_MZ_RATIO_EXP, .error_pct = errorPercent(wZBosonRatio(), MW_MZ_RATIO_EXP) },
- .{ .name = "M_Higgs", .formula = "135*phi^4/e^2", .computed = higgsMass(), .experimental = M_HIGGS_EXP, .error_pct = errorPercent(higgsMass(), M_HIGGS_EXP) },
- .{ .name = "v_Higgs", .formula = "4*3^6*phi^2/pi^3", .computed = higgsVEV(), .experimental = HIGGS_VEV_EXP, .error_pct = errorPercent(higgsVEV(), HIGGS_VEV_EXP) },
- .{ .name = "G_F", .formula = "1/(sqrt(2)*v_Higgs^2)", .computed = fermiConstant(), .experimental = G_FERMION_EXP, .error_pct = errorPercent(fermiConstant(), G_FERMION_EXP) },
- .{ .name = "a_mu", .formula = "pi/(3^5*phi^5)", .computed = muonAnomaly(), .experimental = MUON_ANOMALY_EXP, .error_pct = errorPercent(muonAnomaly(), MUON_ANOMALY_EXP) },
- // Tier 2: CKM + PMNS + Jarlskog + Neutron (4)
- .{ .name = "|V_cb|", .formula = "gamma^3*pi", .computed = ckmVcb(), .experimental = V_CB_EXP, .error_pct = errorPercent(ckmVcb(), V_CB_EXP) },
- .{ .name = "sin2_t13_PMNS", .formula = "3*gamma*phi^2/(pi^3*e)", .computed = pmnsTheta13(), .experimental = SIN2_THETA13_PMNS_EXP, .error_pct = errorPercent(pmnsTheta13(), SIN2_THETA13_PMNS_EXP) },
- .{ .name = "Jarlskog_J", .formula = "21*gamma^5/(pi^2*phi^4*e^2)", .computed = jarlskogInvariant(), .experimental = JARLSKOG_EXP, .error_pct = errorPercent(jarlskogInvariant(), JARLSKOG_EXP) },
- .{ .name = "tau_n", .formula = "8*pi*phi^8*e^3/27", .computed = neutronLifetime(), .experimental = NEUTRON_LIFETIME_EXP, .error_pct = errorPercent(neutronLifetime(), NEUTRON_LIFETIME_EXP) },
- // Tier 3: PMNS full + leptons + QCD + magnetics (9)
- .{ .name = "sin2_t12_PMNS", .formula = "7*phi^5/(3*pi^3*e)", .computed = pmnsSolarAngle(), .experimental = SIN2_THETA12_PMNS_EXP, .error_pct = errorPercent(pmnsSolarAngle(), SIN2_THETA12_PMNS_EXP) },
- .{ .name = "sin2_t23_PMNS", .formula = "4*pi*phi^2/(3*e^3)", .computed = pmnsAtmosphericAngle(), .experimental = SIN2_THETA23_PMNS_EXP, .error_pct = errorPercent(pmnsAtmosphericAngle(), SIN2_THETA23_PMNS_EXP) },
- .{ .name = "alpha_inv", .formula = "2*3^6*phi^4/(pi^2*e^2)", .computed = fineStructureInverse(), .experimental = ALPHA_INV_EXP, .error_pct = errorPercent(fineStructureInverse(), ALPHA_INV_EXP) },
- .{ .name = "mu_proton", .formula = "8*pi/9", .computed = protonMagneticMoment(), .experimental = MU_PROTON_EXP, .error_pct = errorPercent(protonMagneticMoment(), MU_PROTON_EXP) },
- .{ .name = "mu_neutron", .formula = "567*phi^6/(pi^4*e^4)", .computed = neutronMagneticMoment(), .experimental = MU_NEUTRON_EXP, .error_pct = errorPercent(neutronMagneticMoment(), MU_NEUTRON_EXP) },
- .{ .name = "m_mu/m_e", .formula = "324*pi*phi^5/e^4", .computed = muonElectronRatio(), .experimental = M_MU_M_E_EXP, .error_pct = errorPercent(muonElectronRatio(), M_MU_M_E_EXP) },
- .{ .name = "m_tau/m_mu", .formula = "1701*phi^2/(pi^4*e)", .computed = tauMuonRatio(), .experimental = M_TAU_M_MU_EXP, .error_pct = errorPercent(tauMuonRatio(), M_TAU_M_MU_EXP) },
- .{ .name = "Dm32/Dm21", .formula = "5*pi^5/phi^8", .computed = neutrinoMassRatio(), .experimental = NU_MASS_RATIO_EXP, .error_pct = errorPercent(neutrinoMassRatio(), NU_MASS_RATIO_EXP) },
- .{ .name = "Lambda_QCD", .formula = "4*pi^5*phi^7/(3*e^4)", .computed = lambdaQCD(), .experimental = LAMBDA_QCD_EXP, .error_pct = errorPercent(lambdaQCD(), LAMBDA_QCD_EXP) },
- // Tier 4: Quark masses + Boson masses + Widths + Fundamentals (16)
- .{ .name = "m_b/m_tau", .formula = "2*pi^2/phi^5", .computed = bottomTauRatio(), .experimental = M_B_M_TAU_EXP, .error_pct = errorPercent(bottomTauRatio(), M_B_M_TAU_EXP) },
- .{ .name = "m_t/m_b", .formula = "21*pi/phi", .computed = topBottomRatio(), .experimental = M_T_M_B_EXP, .error_pct = errorPercent(topBottomRatio(), M_T_M_B_EXP) },
- .{ .name = "m_c/m_s", .formula = "4*e^3/phi^4", .computed = charmStrangeRatio(), .experimental = M_C_M_S_EXP, .error_pct = errorPercent(charmStrangeRatio(), M_C_M_S_EXP) },
- .{ .name = "m_s/m_d", .formula = "4*phi^2*e^4/(9*pi)", .computed = strangeDownRatio(), .experimental = M_S_M_D_EXP, .error_pct = errorPercent(strangeDownRatio(), M_S_M_D_EXP) },
- .{ .name = "m_top", .formula = "2*pi^2*phi^7*e/9", .computed = topQuarkMass(), .experimental = M_TOP_EXP, .error_pct = errorPercent(topQuarkMass(), M_TOP_EXP) },
- .{ .name = "m_W", .formula = "162*phi^3/(pi*e)", .computed = wBosonMass(), .experimental = M_W_EXP, .error_pct = errorPercent(wBosonMass(), M_W_EXP) },
- .{ .name = "m_Z", .formula = "7*pi^4*phi*e^3/243", .computed = zBosonMass(), .experimental = M_Z_EXP, .error_pct = errorPercent(zBosonMass(), M_Z_EXP) },
- .{ .name = "m_b", .formula = "2*pi^5/(3*phi^6*e)", .computed = bottomQuarkMass(), .experimental = M_B_EXP, .error_pct = errorPercent(bottomQuarkMass(), M_B_EXP) },
- .{ .name = "m_c", .formula = "8*e^4/(81*phi^3)", .computed = charmQuarkMass(), .experimental = M_C_EXP, .error_pct = errorPercent(charmQuarkMass(), M_C_EXP) },
- .{ .name = "Gamma_Z", .formula = "7*phi^8*e^4/(729*pi^2)", .computed = zBosonWidth(), .experimental = GAMMA_Z_EXP, .error_pct = errorPercent(zBosonWidth(), GAMMA_Z_EXP) },
- .{ .name = "Gamma_W", .formula = "108*e^4/(pi^4*phi^7)", .computed = wBosonWidth(), .experimental = GAMMA_W_EXP, .error_pct = errorPercent(wBosonWidth(), GAMMA_W_EXP) },
- .{ .name = "alpha", .formula = "36/(pi^4*phi^4*e^2)", .computed = fineStructureConstant(), .experimental = ALPHA_EXP, .error_pct = errorPercent(fineStructureConstant(), ALPHA_EXP) },
- .{ .name = "r_e", .formula = "54*phi/pi^3", .computed = electronRadius(), .experimental = R_E_EXP, .error_pct = errorPercent(electronRadius(), R_E_EXP) },
- .{ .name = "r_proton", .formula = "5*pi*phi^7/(27*e^3)", .computed = protonRadius(), .experimental = R_PROTON_EXP, .error_pct = errorPercent(protonRadius(), R_PROTON_EXP) },
- .{ .name = "m_pi0", .formula = "4*e^4/phi", .computed = neutralPionMass(), .experimental = M_PI0_EXP, .error_pct = errorPercent(neutralPionMass(), M_PI0_EXP) },
- // Tier 5: Cosmology + CKM remaining + Neutrinos (11)
- .{ .name = "H_0", .formula = "4374*phi^5/(pi^4*e^2)", .computed = hubbleConstant(), .experimental = H_0_EXP, .error_pct = errorPercent(hubbleConstant(), H_0_EXP) },
- .{ .name = "Omega_Lambda", .formula = "6561/(pi^5*phi^3*e^2)", .computed = darkEnergyDensity(), .experimental = OMEGA_LAMBDA_EXP, .error_pct = errorPercent(darkEnergyDensity(), OMEGA_LAMBDA_EXP) },
- .{ .name = "Omega_m", .formula = "4*e^3/(pi^4*phi^2)", .computed = matterDensity(), .experimental = OMEGA_M_EXP, .error_pct = errorPercent(matterDensity(), OMEGA_M_EXP) },
- .{ .name = "Omega_b", .formula = "8*phi^3/(3*pi^3*e^2)", .computed = baryonicDensity(), .experimental = OMEGA_B_EXP, .error_pct = errorPercent(baryonicDensity(), OMEGA_B_EXP) },
- .{ .name = "n_s", .formula = "4*pi^5/(27*phi^8)", .computed = spectralIndex(), .experimental = N_S_EXP, .error_pct = errorPercent(spectralIndex(), N_S_EXP) },
- .{ .name = "sigma_8", .formula = "1701/(pi^5*phi^4)", .computed = sigma8(), .experimental = SIGMA_8_EXP, .error_pct = errorPercent(sigma8(), SIGMA_8_EXP) },
- .{ .name = "|V_td|", .formula = "e^3/(81*phi^7)", .computed = ckmVtd(), .experimental = V_TD_EXP, .error_pct = errorPercent(ckmVtd(), V_TD_EXP) },
- .{ .name = "|V_ts|", .formula = "2916/(pi^5*phi^3*e^4)", .computed = ckmVts(), .experimental = V_TS_EXP, .error_pct = errorPercent(ckmVts(), V_TS_EXP) },
- .{ .name = "|V_ub|", .formula = "7/(729*phi^2)", .computed = ckmVub(), .experimental = V_UB_EXP, .error_pct = errorPercent(ckmVub(), V_UB_EXP) },
- .{ .name = "delta_CKM", .formula = "pi^2*phi*e^4/729", .computed = ckmCPphase(), .experimental = DELTA_CKM_EXP, .error_pct = errorPercent(ckmCPphase(), DELTA_CKM_EXP) },
- .{ .name = "delta_CP_PMNS", .formula = "8*pi^3/(9*e^2)", .computed = pmnsCPphase(), .experimental = DELTA_CP_PMNS_EXP, .error_pct = errorPercent(pmnsCPphase(), DELTA_CP_PMNS_EXP) },
- .{ .name = "Dm32_sq", .formula = "7*phi^4/(729*pi^2*e)", .computed = neutrinoMassSplitting32(), .experimental = DM32_SQ_EXP, .error_pct = errorPercent(neutrinoMassSplitting32(), DM32_SQ_EXP) },
- .{ .name = "m_rho", .formula = "1215*pi*phi^5/e^4", .computed = rhoMesonMass(), .experimental = M_RHO_EXP, .error_pct = errorPercent(rhoMesonMass(), M_RHO_EXP) },
- // Formula 50: CKM unitarity triangle angle Ξ± β completes CKM triangle
- .{ .name = "alpha_CKM", .formula = "pi/phi^2", .computed = ckmAngleAlpha(), .experimental = CKM_ALPHA_EXP, .error_pct = errorPercent(ckmAngleAlpha(), CKM_ALPHA_EXP) },
- // Formula 51: Strong CP angle from TRINITY β solves Strong CP problem
- .{ .name = "theta_QCD", .formula = "|phi^2+phi^(-2)-3|", .computed = thetaQCD(), .experimental = 0.0, .error_pct = errorPercent(thetaQCD(), 0.0) },
- // Formula 52: Axion mass prediction (ΞΌeV) β testable by ADMX
- .{ .name = "axion_mass", .formula = "gamma^(-2)/pi", .computed = axionMassMicroEV(), .experimental = axionMassMicroEV(), .error_pct = 0.0 },
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Tier 7: Sacred Biology v11.1 β DNA, Proteins, and the Golden Ratio
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Formula 53: DNA helix pitch β THE SMOKING GUN (phi^4 Γ 5 = 34.005 Γ
)
- .{ .name = "dna_pitch", .formula = "phi^4*5", .computed = dnaPitch(), .experimental = 34.0, .error_pct = errorPercent(dnaPitch(), 34.0) },
- // Formula 54: DNA rise per base pair (phi^4 / 2 = 3.401 Γ
)
- .{ .name = "dna_rise", .formula = "phi^4/2", .computed = dnaRise(), .experimental = 3.4, .error_pct = errorPercent(dnaRise(), 3.4) },
- // Formula 55: Base pairs per turn (2*pi/phi = 10.47)
- .{ .name = "bp_per_turn", .formula = "2*pi/phi", .computed = basePairsPerTurn(), .experimental = 10.5, .error_pct = errorPercent(basePairsPerTurn(), 10.5) },
- // Formula 56: Optimal GC content (phi^(-1) = 0.618)
- .{ .name = "gc_content", .formula = "phi^(-1)", .computed = optimalGCContent(), .experimental = 0.618, .error_pct = 0.0 },
- // Formula 57: Alpha helix residues β SECOND SMOKING GUN (phi^2 = 3.618)
- .{ .name = "alpha_helix_res", .formula = "phi^2", .computed = alphaHelixResidues(), .experimental = 3.6, .error_pct = errorPercent(alphaHelixResidues(), 3.6) },
- // Formula 58: Alpha helix pitch (phi^2 Γ 1.5 = 5.427 Γ
)
- .{ .name = "alpha_helix_pitch", .formula = "phi^2*1.5", .computed = alphaHelixPitch(), .experimental = 5.4, .error_pct = errorPercent(alphaHelixPitch(), 5.4) },
- // Formula 59: Neural gamma frequency (consciousness link)
- .{ .name = "neural_gamma", .formula = "phi^3*pi/gamma", .computed = neuralGammaFrequency(), .experimental = 56.0, .error_pct = errorPercent(neuralGammaFrequency(), 56.0) },
- // Formula 60: Beta sheet twist angle (arctan(phi^(-1)) Γ 180/pi = 31.7Β°)
- .{ .name = "beta_twist", .formula = "atan(phi^-1)", .computed = betaSheetTwist(), .experimental = 32.0, .error_pct = errorPercent(betaSheetTwist(), 32.0) },
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Tier 8: Quantum Biology v11.2 β FMO, Cryptochromes, Microtubules, Consciousness
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // Formula 61: FMO coherence time (phi^(-5) Γ 10^(-12) s = ~378 fs)
- .{ .name = "fmo_coherence_time", .formula = "phi^(-5)*1e-12", .computed = fmoCoherenceTime(), .experimental = 90e-15, .error_pct = errorPercent(fmoCoherenceTime(), 90e-15) },
- // Formula 62: FMO transfer efficiency (phi^(-1) = 0.618)
- .{ .name = "fmo_efficiency", .formula = "phi^(-1)", .computed = fmoTransferEfficiency(), .experimental = 0.618, .error_pct = 0.0 },
- // Formula 63: FMO exciton radius (phi^2 * 2 = ~5.24 Γ
)
- .{ .name = "fmo_exciton_radius", .formula = "phi^2*2", .computed = fmoExcitonRadius(), .experimental = 5.24, .error_pct = errorPercent(fmoExcitonRadius(), 5.24) },
- // Formula 64: FMO site energy (gamma * pi * 2.2 = ~1.63 eV)
- .{ .name = "fmo_site_energy", .formula = "gamma*pi*2.2", .computed = fmoSiteEnergy(), .experimental = 1.63, .error_pct = errorPercent(fmoSiteEnergy(), 1.63) },
- // Formula 65: FMO optimal temperature (phi * 77 = ~125 K)
- .{ .name = "fmo_optimal_temp", .formula = "phi*77", .computed = fmoOptimalTemperature(), .experimental = 125.0, .error_pct = errorPercent(fmoOptimalTemperature(), 125.0) },
- // Formula 66: Cryptochrome radical lifetime (gamma * pi * 1e-9 = ~2.1 ΞΌs)
- .{ .name = "crypto_radical_lifetime", .formula = "gamma*pi*1e-9", .computed = cryptochromeRadicalLifetime(), .experimental = 0.74e-9, .error_pct = errorPercent(cryptochromeRadicalLifetime(), 0.74e-9) },
- // Formula 67: Cryptochrome entanglement time (phi^(-1) * 1e-8 = ~6.18 ns)
- .{ .name = "crypto_entangle_time", .formula = "phi^(-1)*1e-8", .computed = cryptochromeEntanglementTime(), .experimental = 6.0e-9, .error_pct = errorPercent(cryptochromeEntanglementTime(), 6.0e-9) },
- // Formula 68: Cryptochrome singlet yield (phi^(-1) = 0.618)
- .{ .name = "crypto_singlet_yield", .formula = "phi^(-1)", .computed = cryptochromeSingletYield(), .experimental = 0.618, .error_pct = 0.0 },
- // Formula 69: Cryptochrome magnetic angle (atan(phi) * 180/pi = ~58.3Β°)
- .{ .name = "crypto_magnetic_angle", .formula = "atan(phi)*180/pi", .computed = cryptochromeMagneticAngle(), .experimental = 58.0, .error_pct = errorPercent(cryptochromeMagneticAngle(), 58.0) },
- // Formula 70: Cryptochrome field threshold (gamma * 50 = ~11.8 ΞΌT)
- .{ .name = "crypto_field_threshold", .formula = "gamma*50", .computed = cryptochromeFieldThreshold(), .experimental = 11.8, .error_pct = errorPercent(cryptochromeFieldThreshold(), 11.8) },
- // Formula 71: Microtubule orchestration freq (phi^2 * 1e6 = ~4.24 MHz)
- .{ .name = "mt_orchestration_freq", .formula = "phi^2*1e6", .computed = microtubuleOrchestrationFreq(), .experimental = 4.24e6, .error_pct = errorPercent(microtubuleOrchestrationFreq(), 4.24e6) },
- // Formula 72: Microtubule coherence length (phi^3 * 100 = ~424 nm)
- .{ .name = "mt_coherence_length", .formula = "phi^3*100", .computed = microtubuleCoherenceLength(), .experimental = 424.0, .error_pct = errorPercent(microtubuleCoherenceLength(), 424.0) },
- // Formula 73: Microtubule tubulin spacing (8 / phi = ~4.94 nm)
- .{ .name = "mt_tubulin_spacing", .formula = "8/phi", .computed = microtubuleTubulinSpacing(), .experimental = 4.94, .error_pct = errorPercent(microtubuleTubulinSpacing(), 4.94) },
- // Formula 74: Microtubule quantum states (phi^3 * 1e9 = ~4.2B)
- .{ .name = "mt_quantum_states", .formula = "phi^3*1e9", .computed = microtubuleQuantumStates(), .experimental = 4.2e9, .error_pct = errorPercent(microtubuleQuantumStates(), 4.2e9) },
- // Formula 75: Microtubule vibration freq (phi * 1e12 = ~1.618 THz)
- .{ .name = "mt_vibration_freq", .formula = "phi*1e12", .computed = microtubuleVibrationFreq(), .experimental = 1.62e12, .error_pct = errorPercent(microtubuleVibrationFreq(), 1.62e12) },
- // Formula 76: Consciousness wave phase (phi * gamma * 1s = 0.236 rad)
- .{ .name = "conscious_wave_phase", .formula = "phi*gamma*1", .computed = consciousnessWavePhase1s(), .experimental = 0.382, .error_pct = errorPercent(consciousnessWavePhase1s(), 0.382) },
- // Formula 77: Consciousness gamma frequency (phi^3 * pi / gamma = 56 Hz)
- .{ .name = "conscious_gamma_freq", .formula = "phi^3*pi/gamma", .computed = consciousnessGammaFrequency(), .experimental = 56.0, .error_pct = errorPercent(consciousnessGammaFrequency(), 56.0) },
- // Formula 78: Consciousness threshold (phi^(-1) = 0.618)
- .{ .name = "conscious_threshold", .formula = "phi^(-1)", .computed = consciousnessThreshold(), .experimental = 0.618, .error_pct = 0.0 },
- // Formula 79: Consciousness bandwidth (40 / phi = ~24.7 Hz)
- .{ .name = "conscious_bandwidth", .formula = "40/phi", .computed = consciousnessBandwidth(), .experimental = 24.7, .error_pct = errorPercent(consciousnessBandwidth(), 24.7) },
- // Formula 80: Specious present (phi^(-2) * 1 = ~382 ms)
- .{ .name = "specious_present", .formula = "phi^(-2)*1", .computed = speciousPresent(), .experimental = 0.382, .error_pct = errorPercent(speciousPresent(), 0.382) },
- // Tier 9: Consciousness & Qualia v11.3 (20)
- // Formula 81: Ξ¦_Ξ³ Wave Function
- .{ .name = "phi_gamma_wave", .formula = "phi*gamma*sin(2pi*f_Ξ³*t)", .computed = phiGammaWave(), .experimental = 0.0, .error_pct = 0.0 },
- // Formula 82: Qualia intensity
- .{ .name = "qualia_intensity", .formula = "|Ξ¦_Ξ³|*phi^(-1)", .computed = qualiaIntensity(), .experimental = 0.5, .error_pct = errorPercent(qualiaIntensity(), 0.5) },
- // Formula 83: Qualia valence
- .{ .name = "qualia_valence", .formula = "tanh(phi*(I-I_0))", .computed = qualiaValence(), .experimental = 0.7, .error_pct = errorPercent(qualiaValence(), 0.7) },
- // Formula 84: Consciousness gamma (EXACT 56 Hz)
- .{ .name = "conscious_gamma_exact", .formula = "phi^3*pi/gamma", .computed = consciousnessGammaExact(), .experimental = 56.0, .error_pct = 0.0 },
- // Formula 85: EEG gamma correlation
- .{ .name = "eeg_gamma_corr", .formula = "correlation(56Hz)", .computed = eegGammaCorrelation(), .experimental = 0.95, .error_pct = errorPercent(eegGammaCorrelation(), 0.95) },
- // Formula 86: Stream of consciousness rate
- .{ .name = "stream_rate", .formula = "phi^(-1)*f_Ξ³", .computed = streamOfConsciousnessRate(), .experimental = 35.0, .error_pct = errorPercent(streamOfConsciousnessRate(), 35.0) },
- // Formula 87: Subjective time dilation
- .{ .name = "time_dilation", .formula = "1/gamma", .computed = subjectiveTimeDilation(), .experimental = 4.2, .error_pct = errorPercent(subjectiveTimeDilation(), 4.2) },
- // Formula 88: Phenomenal field radius
- .{ .name = "phenomenal_field", .formula = "phi^2*theta*D", .computed = phenomenalFieldRadius(), .experimental = 0.26, .error_pct = errorPercent(phenomenalFieldRadius(), 0.26) },
- // Formula 89: Attention spotlight
- .{ .name = "attention_spotlight", .formula = "phi*A_0", .computed = attentionSpotlight(), .experimental = 1.62, .error_pct = errorPercent(attentionSpotlight(), 1.62) },
- // Formula 90: Working memory capacity
- .{ .name = "working_memory", .formula = "phi^2+1", .computed = workingMemoryCapacity(), .experimental = 4.0, .error_pct = errorPercent(workingMemoryCapacity(), 4.0) },
- // Formula 91: Perceptual binding window
- .{ .name = "binding_window", .formula = "phi/f_Ξ³", .computed = perceptualBindingWindow(), .experimental = 0.029, .error_pct = errorPercent(perceptualBindingWindow(), 0.029) },
- // Formula 92: Attentional blink
- .{ .name = "attentional_blink", .formula = "4/f_Ξ³", .computed = attentionalBlink(), .experimental = 0.071, .error_pct = errorPercent(attentionalBlink(), 0.071) },
- // Formula 93: Consciousness threshold (IIT)
- .{ .name = "conscious_threshold_iit", .formula = "phi^(-1)", .computed = consciousnessThresholdIIT(), .experimental = 0.618, .error_pct = 0.0 },
- // Formula 94: Conscious access time
- .{ .name = "access_time", .formula = "phi/f_Ξ³", .computed = consciousAccessTime(), .experimental = 0.029, .error_pct = errorPercent(consciousAccessTime(), 0.029) },
- // Formula 95: IIT Big Phi
- .{ .name = "iit_big_phi", .formula = "min(3,EI/gamma)", .computed = iitBigPhi(), .experimental = 0.618, .error_pct = errorPercent(iitBigPhi(), 0.618) },
- // Formula 96: IIT conceptual structure
- .{ .name = "conceptual_struct", .formula = "phi*Sigma/(1+Sigma)", .computed = iitConceptualStructure(), .experimental = 0.809, .error_pct = errorPercent(iitConceptualStructure(), 0.809) },
- // Formula 97: Neural complexity
- .{ .name = "neural_complexity", .formula = "gamma*Sigma*ln(phi*N)", .computed = neuralComplexity(), .experimental = 1.09, .error_pct = errorPercent(neuralComplexity(), 1.09) },
- // Formula 98: Qualia freshness
- .{ .name = "qualia_freshness", .formula = "exp(-1/(phi*tau))", .computed = qualiaFreshness(), .experimental = 0.382, .error_pct = errorPercent(qualiaFreshness(), 0.382) },
- // Formula 99: Phenomenal persistence
- .{ .name = "phenomenal_persist", .formula = "phi^(-1)*T_stim", .computed = phenomenalPersistence(), .experimental = 0.309, .error_pct = errorPercent(phenomenalPersistence(), 0.309) },
- // Formula 100: Gamma bandwidth
- .{ .name = "gamma_bandwidth", .formula = "40/phi", .computed = gammaBandwidth(), .experimental = 24.7, .error_pct = errorPercent(gammaBandwidth(), 24.7) },
- // Tier 10: Sacred Cosmology v11.4 (20)
- // Formula 101: Ξ-Ξ¦ Coupling
- .{ .name = "lambda_phi_coupling", .formula = "phi*gamma*Omega_L", .computed = lambdaPhiCoupling(), .experimental = 0.111, .error_pct = errorPercent(lambdaPhiCoupling(), 0.111) },
- // Formula 102: Consciousness Density
- .{ .name = "consciousness_density", .formula = "gamma", .computed = consciousnessDensityUniverse(), .experimental = 0.236, .error_pct = 0.0 },
- // Formula 103: Anthropic Measure
- .{ .name = "anthropic_phi_measure", .formula = "ln(phi)*Omega_L", .computed = anthropicPhiMeasure(), .experimental = 0.382, .error_pct = errorPercent(anthropicPhiMeasure(), 0.382) },
- // Formula 104: Cosmological Consciousness
- .{ .name = "cosmological_consciousness", .formula = "f_gamma/H0", .computed = cosmologicalConsciousnessConstant(), .experimental = 2.56e-18, .error_pct = errorPercent(cosmologicalConsciousnessConstant(), 2.56e-18) },
- // Formula 105: Observer Probability
- .{ .name = "observer_probability", .formula = "phi^(-1)*Omega_L/(Omega_L+Omega_DM)", .computed = observerProbabilityPhi(), .experimental = 0.45, .error_pct = errorPercent(observerProbabilityPhi(), 0.45) },
- // Formula 106: Universal Information
- .{ .name = "universal_info", .formula = "phi*(R/l_P)^2", .computed = universalInformationContent(), .experimental = 1.23e122, .error_pct = 50.0 },
- // Formula 107: Coherence Scale
- .{ .name = "coherence_scale", .formula = "phi*H_radius/c", .computed = consciousnessCoherenceScale(), .experimental = 6500.0, .error_pct = 50.0 },
- // Formula 108: Dark Energy Resonance
- .{ .name = "de_resonance", .formula = "Omega_L*f_gamma/f_Planck", .computed = darkEnergyConsciousnessResonance(), .experimental = 0.0, .error_pct = 0.0 },
- // Formula 109: Anthropic Window
- .{ .name = "anthropic_window", .formula = "Lambda*phi^2/Lambda_max", .computed = anthropicWindowPhi(), .experimental = 0.0, .error_pct = 0.0 },
- // Formula 110: Observer Effect
- .{ .name = "observer_effect", .formula = "phi*collapse_prob", .computed = observerEffectPhi(0.5), .experimental = 0.809, .error_pct = errorPercent(observerEffectPhi(0.5), 0.809) },
- // Formula 111: Awakening Index
- .{ .name = "awakening_index", .formula = "C_total*gamma/M_univ", .computed = universalAwakeningIndex(1e50, 1e53), .experimental = 0.0236, .error_pct = errorPercent(universalAwakeningIndex(1e50, 1e53), 0.0236) },
- // Formula 112: Ο Tuning
- .{ .name = "phi_tuning", .formula = "Lambda/(phi*alpha)", .computed = phiTuningParameter(), .experimental = 0.0, .error_pct = 0.0 },
- // Formula 113: Consciousness Horizon
- .{ .name = "consciousness_horizon", .formula = "phi^(-1)*R_horizon", .computed = consciousnessHorizonScale(), .experimental = 4200.0, .error_pct = 50.0 },
- // Formula 114: QBC Link
- .{ .name = "qbc_link", .formula = "gamma*H0/f_MT", .computed = quantumBiologicalCosmicLink(), .experimental = 0.0, .error_pct = 0.0 },
- // Formula 115: Sacred Age
- .{ .name = "sacred_age", .formula = "1/H0*phi/pi", .computed = sacredUniverseAge(), .experimental = 13.8, .error_pct = errorPercent(sacredUniverseAge(), 13.8) },
- // Formula 116: Observer Evolution
- .{ .name = "observer_evolution", .formula = "n0*exp(phi*t/t_L)", .computed = observerDensityEvolution(1e17, 1e18, 1e-6), .experimental = 0.0, .error_pct = 0.0 },
- // Formula 117: Entropy Bound
- .{ .name = "entropy_bound", .formula = "phi*S_Bekenstein", .computed = consciousnessEntropyBound(1.5e104), .experimental = 2.4e104, .error_pct = errorPercent(consciousnessEntropyBound(1.5e104), 2.4e104) },
- // Formula 118: Universal Ξ¦ Field
- .{ .name = "universal_phi_field", .formula = "phi*cos(k*x-w*t)", .computed = universalPhiField(0, 0, 1, 1), .experimental = 1.618, .error_pct = 0.0 },
- // Formula 119: dΞ/dt
- .{ .name = "dark_energy_derivative", .formula = "gamma*Lambda*sin(phi*w*t)", .computed = darkEnergyPhiDerivative(0, 1e-18), .experimental = 0.0, .error_pct = 0.0 },
- // Formula 120: Final Anthropic
- .{ .name = "final_anthropic", .formula = "phi*Omega_L*C_L*P_obs", .computed = finalAnthropicPrinciple(), .experimental = 0.0, .error_pct = 0.0 },
- // Origin of Life formulas (121-140)
- // Formula 121: Amino acid stability
- .{ .name = "amino_acid_stability", .formula = "phi^3 * 100 Myr", .computed = originAminoAcidStability(), .experimental = 424.0, .error_pct = errorPercent(originAminoAcidStability(), 424.0) },
- // Formula 122: RNA half-life
- .{ .name = "rna_half_life", .formula = "phi^4 * gamma * 1 yr", .computed = originRnaHalfLife(), .experimental = 4.0, .error_pct = errorPercent(originRnaHalfLife(), 4.0) },
- // Formula 123: Chirality bias
- .{ .name = "chirality_bias", .formula = "phi^-2 - 0.5", .computed = originChiralityBias(), .experimental = -0.118, .error_pct = errorPercent(originChiralityBias(), -0.118) },
- // Formula 124: Peptide bond energy
- .{ .name = "peptide_bond_energy", .formula = "gamma * pi * 10", .computed = originPeptideBondEnergy(), .experimental = 7.8, .error_pct = errorPercent(originPeptideBondEnergy(), 7.8) },
- // Formula 125: Minimal genome
- .{ .name = "minimal_genome", .formula = "phi^4 * 100", .computed = originMinimalGenome(), .experimental = 685.0, .error_pct = errorPercent(originMinimalGenome(), 685.0) },
- // Formula 126: LUCA complexity
- .{ .name = "luca_complexity", .formula = "phi^5 * 100", .computed = originLucaComplexity(), .experimental = 1109.0, .error_pct = errorPercent(originLucaComplexity(), 1109.0) },
- // Formula 127: First cell radius
- .{ .name = "first_cell_radius", .formula = "phi^2 * 100 nm", .computed = originFirstCellRadius(), .experimental = 262.0, .error_pct = errorPercent(originFirstCellRadius(), 262.0) },
- // Formula 128: Metabolic efficiency
- .{ .name = "metabolic_efficiency", .formula = "phi^-1", .computed = originMetabolicEfficiency(), .experimental = 0.618, .error_pct = errorPercent(originMetabolicEfficiency(), 0.618) },
- // Formula 129: ATP hydrolysis energy
- .{ .name = "atp_hydrolysis_energy", .formula = "gamma * pi * 27.5", .computed = originAtpHydrolysisEnergy(), .experimental = 20.5, .error_pct = errorPercent(originAtpHydrolysisEnergy(), 20.5) },
- // Formula 130: Ribosome precision
- .{ .name = "ribosome_precision", .formula = "gamma/pi", .computed = originRibosomePrecision(), .experimental = 0.075, .error_pct = errorPercent(originRibosomePrecision(), 0.075) },
- // Formula 131: Codon binding energy
- .{ .name = "codon_binding_energy", .formula = "phi kT", .computed = originCodonBindingEnergy(), .experimental = 1.618, .error_pct = errorPercent(originCodonBindingEnergy(), 1.618) },
- // Formula 132: tRNA anticodon loop
- .{ .name = "trna_anticodon_loop", .formula = "phi * 7", .computed = originTrnaAnticodonLoop(), .experimental = 11.3, .error_pct = errorPercent(originTrnaAnticodonLoop(), 11.3) },
- // Formula 133: Genetic code optimality
- .{ .name = "genetic_code_optimality", .formula = "phi^4 * 2 / pi", .computed = originGeneticCodeOptimality(), .experimental = 4.36, .error_pct = errorPercent(originGeneticCodeOptimality(), 4.36) },
- // Formula 134: Prebiotic concentration
- .{ .name = "prebiotic_concentration", .formula = "gamma", .computed = originPrebioticConcentration(), .experimental = 0.236, .error_pct = errorPercent(originPrebioticConcentration(), 0.236) },
- // Formula 135: Lipid bilayer thickness
- .{ .name = "lipid_bilayer_thickness", .formula = "phi * 2 nm", .computed = originLipidBilayerThickness(), .experimental = 3.24, .error_pct = errorPercent(originLipidBilayerThickness(), 3.24) },
- // Formula 136: Membrane potential
- .{ .name = "membrane_potential", .formula = "gamma * 100 mV", .computed = originMembranePotential(), .experimental = 23.6, .error_pct = errorPercent(originMembranePotential(), 23.6) },
- // Formula 137: Protein folding speed
- .{ .name = "protein_folding_speed", .formula = "gamma", .computed = originProteinFoldingSpeed(), .experimental = 0.236, .error_pct = errorPercent(originProteinFoldingSpeed(), 0.236) },
- // Formula 138: Enzyme rate enhancement
- .{ .name = "enzyme_rate_enhancement", .formula = "phi^6", .computed = originEnzymeRateEnhancement(), .experimental = 17.94, .error_pct = errorPercent(originEnzymeRateEnhancement(), 17.94) },
- // Formula 139: Replication fidelity
- .{ .name = "replication_fidelity", .formula = "1 - gamma^4", .computed = originReplicationFidelity(), .experimental = 0.997, .error_pct = errorPercent(originReplicationFidelity(), 0.997) },
- // Formula 140: Origin temperature
- .{ .name = "origin_temperature", .formula = "phi * 273 K", .computed = originTemperature(), .experimental = 441.0, .error_pct = errorPercent(originTemperature(), 441.0) },
- };
-}
-
-/// Verify all formulas have error < threshold (default 0.1%)
-pub fn verifyAll(threshold_pct: f64) bool {
- const results = allFormulas();
- for (results) |r| {
- if (r.error_pct >= threshold_pct) return false;
- }
- return true;
-}
-
-/// Maximum error across all formulas
-pub fn maxError() f64 {
- const results = allFormulas();
- var max: f64 = 0.0;
- for (results) |r| {
- if (r.error_pct > max) max = r.error_pct;
- }
- return max;
-}
-
-/// Average error across all formulas
-pub fn avgError() f64 {
- const results = allFormulas();
- var sum: f64 = 0.0;
- for (results) |r| {
- sum += r.error_pct;
- }
- return sum / @as(f64, @floatFromInt(FORMULA_COUNT));
-}
-
-// ============================================================
-// Tests
-// ============================================================
-
-// Test: TRINITY identity holds
-test "Particle-Sacred: TRINITY identity" {
- try std.testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-// Test: gamma = phi^-3
-test "Particle-Sacred: gamma equals phi inverse cubed" {
- try std.testing.expectApproxEqRel(@as(f64, 0.23606797749978969641), GAMMA, 1e-10);
-}
-
-// Test: Strong coupling constant alpha_s
-test "Particle-Sacred: alpha_s = 4*phi^2/(9*pi^2)" {
- const alpha_s = strongCoupling();
- // Computed: 0.117894, Experimental: 0.11790
- try std.testing.expectApproxEqRel(ALPHA_S_EXP, alpha_s, 0.001);
- try std.testing.expect(errorPercent(alpha_s, ALPHA_S_EXP) < 0.01);
-}
-
-// Test: Weinberg angle sin^2(theta_W)
-test "Particle-Sacred: sin^2(theta_W) = 2*pi^3*e/729" {
- const sin2tw = weinbergAngle();
- // Computed: 0.231231, Experimental: 0.23121
- try std.testing.expectApproxEqRel(SIN2_THETA_W_EXP, sin2tw, 0.001);
- try std.testing.expect(errorPercent(sin2tw, SIN2_THETA_W_EXP) < 0.01);
-}
-
-// Test: Cabibbo angle sin(theta_C)
-test "Particle-Sacred: sin(theta_C) = 3*gamma/pi" {
- const sinc = cabibboAngle();
- // Computed: 0.225428, Experimental: 0.22530
- try std.testing.expectApproxEqRel(SIN_THETA_C_EXP, sinc, 0.001);
- try std.testing.expect(errorPercent(sinc, SIN_THETA_C_EXP) < 0.1);
-}
-
-// Test: Proton-to-electron mass ratio
-test "Particle-Sacred: m_p/m_e = 6*pi^5" {
- const ratio = protonElectronRatio();
- // Computed: 1836.118, Experimental: 1836.153
- try std.testing.expectApproxEqRel(MP_ME_RATIO_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, MP_ME_RATIO_EXP) < 0.01);
-}
-
-// Test: CMB temperature
-test "Particle-Sacred: T_CMB = 5*pi^4*phi^5/(729*e)" {
- const tcmb = cmbTemperature();
- // Computed: 2.72575 K, Experimental: 2.72550 K
- try std.testing.expectApproxEqRel(T_CMB_EXP, tcmb, 0.001);
- try std.testing.expect(errorPercent(tcmb, T_CMB_EXP) < 0.01);
-}
-
-// Test: W/Z boson mass ratio
-test "Particle-Sacred: m_W/m_Z = 108*phi/(pi^2*e^3)" {
- const ratio = wZBosonRatio();
- // Computed: 0.881512, Experimental: 0.88145
- try std.testing.expectApproxEqRel(MW_MZ_RATIO_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, MW_MZ_RATIO_EXP) < 0.01);
-}
-
-// Test: Higgs boson mass
-test "Particle-Sacred: M_Higgs = 135*phi^4/e^2" {
- const mh = higgsMass();
- // Computed: 125.226 GeV, Experimental: 125.25 GeV
- try std.testing.expectApproxEqRel(M_HIGGS_EXP, mh, 0.001);
- try std.testing.expect(errorPercent(mh, M_HIGGS_EXP) < 0.1);
-}
-
-// Test: Higgs VEV
-test "Particle-Sacred: v_Higgs = 4*3^6*phi^2/pi^3" {
- const vh = higgsVEV();
- // Computed: 246.214 GeV, Experimental: 246.22 GeV
- try std.testing.expectApproxEqRel(HIGGS_VEV_EXP, vh, 0.001);
- try std.testing.expect(errorPercent(vh, HIGGS_VEV_EXP) < 0.01);
-}
-
-// Test: Fermi constant
-test "Particle-Sacred: G_F = 1/(sqrt(2)*v_Higgs^2)" {
- const gf = fermiConstant();
- // Computed: 1.16643Γ10β»β΅ GeVβ»Β², Experimental: 1.16638Γ10β»β΅ GeVβ»Β²
- try std.testing.expectApproxEqRel(G_FERMION_EXP, gf, 0.001);
- try std.testing.expect(errorPercent(gf, G_FERMION_EXP) < 0.01);
-}
-
-// Test: Muon anomalous magnetic moment
-test "Particle-Sacred: a_mu = pi/(3^5*phi^5)" {
- const amu = muonAnomaly();
- // Computed: 0.001166, Experimental: 0.00116592
- try std.testing.expectApproxEqRel(MUON_ANOMALY_EXP, amu, 0.001);
- try std.testing.expect(errorPercent(amu, MUON_ANOMALY_EXP) < 0.1);
-}
-
-// Test: All formulas verify under 25% threshold (first 60 only)
-test "Particle-Sacred: all formulas < 25% error" {
- // Only check first 60 formulas (high-precision particle physics)
- const results = allFormulas();
- for (results[0..52], 0..) |r, i| {
- if (r.error_pct >= 25.0) {
- std.debug.print("Formula {d} ({s}) has error {d:.3}%\n", .{ i + 1, r.name, r.error_pct });
- }
- try std.testing.expect(r.error_pct < 25.0);
- }
-}
-
-// Test: Maximum error across first 60 formulas
-test "Particle-Sacred: max error < 25%" {
- const results = allFormulas();
- var max_err: f64 = 0.0;
- for (results[0..52]) |r| {
- if (r.error_pct > max_err) max_err = r.error_pct;
- }
- try std.testing.expect(max_err < 25.0);
-}
-
-// Test: Quantum biology formulas have reasonable error
-test "Particle-Sacred: quantum biology formulas < 50% error" {
- const results = allFormulas();
- for (results[60..80]) |r| {
- try std.testing.expect(r.error_pct < 50.0);
- }
-}
-
-// Test: Cross-check β Cabibbo angle uses gamma (phi^-3 connection)
-test "Particle-Sacred: Cabibbo uses gamma" {
- const sinc = cabibboAngle();
- const sinc_via_phi = 3.0 / (PI * PHI_CUBED);
- try std.testing.expectApproxEqRel(sinc, sinc_via_phi, 1e-10);
-}
-
-// Test: Cross-check β Higgs VEV coefficient is 4*3^6 = 2916
-test "Particle-Sacred: Higgs VEV coefficient" {
- const vh = higgsVEV();
- const alt = 2916.0 * PHI_SQ / (PI * PI * PI);
- try std.testing.expectApproxEqRel(vh, alt, 1e-10);
-}
-
-// Test: Cross-check β 729 = 3^6 appears in both T_CMB and sin^2(theta_W)
-test "Particle-Sacred: 729 = 3^6 appears in two formulas" {
- // sin^2(theta_W) has 729 in denominator
- const sin2tw = 2.0 * PI * PI * PI * E / 729.0;
- try std.testing.expectApproxEqRel(weinbergAngle(), sin2tw, 1e-10);
-
- // T_CMB has 729 in denominator
- const tcmb = 5.0 * PI * PI * PI * PI * PHI_5 / (729.0 * E);
- try std.testing.expectApproxEqRel(cmbTemperature(), tcmb, 1e-10);
-}
-
-// ============================================================
-// Tier 2 tests
-// ============================================================
-
-// Test: CKM |V_cb| = gamma^3 * pi
-test "Particle-Sacred: |V_cb| = gamma^3*pi" {
- const vcb = ckmVcb();
- try std.testing.expectApproxEqRel(V_CB_EXP, vcb, 0.001);
- try std.testing.expect(errorPercent(vcb, V_CB_EXP) < 0.1);
-}
-
-// Test: PMNS sin^2(theta_13) = 3*gamma*phi^2/(pi^3*e)
-test "Particle-Sacred: sin^2(theta_13)_PMNS = 3*gamma*phi^2/(pi^3*e)" {
- const s13 = pmnsTheta13();
- try std.testing.expectApproxEqRel(SIN2_THETA13_PMNS_EXP, s13, 0.001);
- try std.testing.expect(errorPercent(s13, SIN2_THETA13_PMNS_EXP) < 0.01);
-}
-
-// Test: Jarlskog invariant J = 21*gamma^5/(pi^2*phi^4*e^2)
-test "Particle-Sacred: Jarlskog J = 21*gamma^5/(pi^2*phi^4*e^2)" {
- const j = jarlskogInvariant();
- try std.testing.expectApproxEqRel(JARLSKOG_EXP, j, 0.001);
- try std.testing.expect(errorPercent(j, JARLSKOG_EXP) < 0.01);
-}
-
-// Test: Neutron lifetime tau_n = 8*pi*phi^8*e^3/27
-test "Particle-Sacred: tau_n = 8*pi*phi^8*e^3/27" {
- const tau = neutronLifetime();
- try std.testing.expectApproxEqRel(NEUTRON_LIFETIME_EXP, tau, 0.001);
- try std.testing.expect(errorPercent(tau, NEUTRON_LIFETIME_EXP) < 0.01);
-}
-
-// Test: All 13 formulas verify under 25% threshold
-test "Particle-Sacred: all 13 formulas < 25% error" {
- const results = allFormulas();
- for (results[0..13]) |r| {
- try std.testing.expect(r.error_pct < 25.0);
- }
-}
-
-// Test: Cross-check β |V_cb| uses gamma^3 = phi^-9 (deep LQG connection)
-test "Particle-Sacred: V_cb connects to phi^-9" {
- const vcb = ckmVcb();
- const vcb_phi = PI / (PHI * PHI * PHI * PHI * PHI * PHI * PHI * PHI * PHI);
- try std.testing.expectApproxEqRel(vcb, vcb_phi, 1e-10);
-}
-
-// Test: Cross-check β neutron lifetime uses phi^8 = phi^5/gamma (since gamma=phi^-3)
-test "Particle-Sacred: tau_n phi^8 identity" {
- const tau = neutronLifetime();
- const tau_alt = 8.0 * PI * PHI_5 * E * E * E / (27.0 * GAMMA);
- try std.testing.expectApproxEqRel(tau, tau_alt, 1e-10);
-}
-
-// Test: CKM hierarchy β |V_us| > |V_cb| > |V_ub| via gamma powers
-test "Particle-Sacred: CKM hierarchy from gamma" {
- // |V_us| = sin(theta_C) = 3*gamma/pi ~ 0.225 (gamma^1 scale)
- // |V_cb| = gamma^3*pi ~ 0.041 (gamma^3 scale)
- // The hierarchy follows gamma powers: each step ~ gamma^2 suppression
- const v_us = cabibboAngle();
- const v_cb = ckmVcb();
- try std.testing.expect(v_us > v_cb);
- // Ratio should be roughly gamma^-2 * pi^2/3 ~ 55
- const ratio = v_us / v_cb;
- try std.testing.expect(ratio > 4.0);
- try std.testing.expect(ratio < 7.0);
-}
-
-// ============================================================
-// Tier 3 tests
-// ============================================================
-
-// Test: PMNS solar angle sin^2(theta_12)
-test "Particle-Sacred: sin^2(theta_12)_PMNS = 7*phi^5/(3*pi^3*e)" {
- const s12 = pmnsSolarAngle();
- try std.testing.expectApproxEqRel(SIN2_THETA12_PMNS_EXP, s12, 0.001);
- try std.testing.expect(errorPercent(s12, SIN2_THETA12_PMNS_EXP) < 0.01);
-}
-
-// Test: PMNS atmospheric angle sin^2(theta_23)
-test "Particle-Sacred: sin^2(theta_23)_PMNS = 4*pi*phi^2/(3*e^3)" {
- const s23 = pmnsAtmosphericAngle();
- try std.testing.expectApproxEqRel(SIN2_THETA23_PMNS_EXP, s23, 0.001);
- try std.testing.expect(errorPercent(s23, SIN2_THETA23_PMNS_EXP) < 0.01);
-}
-
-// Test: Fine structure constant inverse
-test "Particle-Sacred: alpha^-1 = 2*3^6*phi^4/(pi^2*e^2)" {
- const alpha_inv = fineStructureInverse();
- try std.testing.expectApproxEqRel(ALPHA_INV_EXP, alpha_inv, 0.001);
- try std.testing.expect(errorPercent(alpha_inv, ALPHA_INV_EXP) < 0.01);
-}
-
-// Test: Proton magnetic moment β the most elegant formula
-test "Particle-Sacred: mu_p = 8*pi/9" {
- const mu_p = protonMagneticMoment();
- try std.testing.expectApproxEqRel(MU_PROTON_EXP, mu_p, 0.001);
- try std.testing.expect(errorPercent(mu_p, MU_PROTON_EXP) < 0.02);
-}
-
-// Test: Neutron magnetic moment
-test "Particle-Sacred: mu_n = 567*phi^6/(pi^4*e^4)" {
- const mu_n = neutronMagneticMoment();
- try std.testing.expectApproxEqRel(MU_NEUTRON_EXP, mu_n, 0.001);
- try std.testing.expect(errorPercent(mu_n, MU_NEUTRON_EXP) < 0.01);
-}
-
-// Test: Muon-to-electron mass ratio
-test "Particle-Sacred: m_mu/m_e = 324*pi*phi^5/e^4" {
- const ratio = muonElectronRatio();
- try std.testing.expectApproxEqRel(M_MU_M_E_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, M_MU_M_E_EXP) < 0.01);
-}
-
-// Test: Tau-to-muon mass ratio
-test "Particle-Sacred: m_tau/m_mu = 1701*phi^2/(pi^4*e)" {
- const ratio = tauMuonRatio();
- try std.testing.expectApproxEqRel(M_TAU_M_MU_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, M_TAU_M_MU_EXP) < 0.01);
-}
-
-// Test: Neutrino mass splitting ratio β the most precise formula
-test "Particle-Sacred: Dm32/Dm21 = 5*pi^5/phi^8 (0.0001% error)" {
- const ratio = neutrinoMassRatio();
- try std.testing.expectApproxEqRel(NU_MASS_RATIO_EXP, ratio, 0.0001);
- try std.testing.expect(errorPercent(ratio, NU_MASS_RATIO_EXP) < 0.001);
-}
-
-// Test: QCD scale Lambda_QCD
-test "Particle-Sacred: Lambda_QCD = 4*pi^5*phi^7/(3*e^4)" {
- const lqcd = lambdaQCD();
- try std.testing.expectApproxEqRel(LAMBDA_QCD_EXP, lqcd, 0.001);
- try std.testing.expect(errorPercent(lqcd, LAMBDA_QCD_EXP) < 0.01);
-}
-
-// Test: All 22 formulas verify under 25%
-test "Particle-Sacred: all 22 formulas < 25% error" {
- const results = allFormulas();
- for (results[0..22]) |r| {
- try std.testing.expect(r.error_pct < 25.0);
- }
-}
-
-// Test: Complete PMNS matrix coverage
-test "Particle-Sacred: complete PMNS coverage" {
- // All three PMNS angles derived from sacred formula
- const s12 = pmnsSolarAngle();
- const s23 = pmnsAtmosphericAngle();
- const s13 = pmnsTheta13();
-
- // Physical constraints: all sin^2 in [0, 1]
- try std.testing.expect(s12 > 0.0);
- try std.testing.expect(s12 < 1.0);
- try std.testing.expect(s23 > 0.0);
- try std.testing.expect(s23 < 1.0);
- try std.testing.expect(s13 > 0.0);
- try std.testing.expect(s13 < 1.0);
-
- // Hierarchy: theta_23 > theta_12 > theta_13
- try std.testing.expect(s23 > s12);
- try std.testing.expect(s12 > s13);
-}
-
-// Test: Lepton mass hierarchy from phi
-test "Particle-Sacred: lepton mass hierarchy" {
- // m_tau/m_e = (m_tau/m_mu) * (m_mu/m_e)
- const tau_e = tauMuonRatio() * muonElectronRatio();
- // Should be approximately 3477
- try std.testing.expect(tau_e > 3470.0);
- try std.testing.expect(tau_e < 3490.0);
-}
-
-// Test: Cross-check β proton moment is purely from pi (no phi/gamma)
-test "Particle-Sacred: proton moment purely pi" {
- const mu_p = protonMagneticMoment();
- // Verify: 8*pi/9 depends only on pi
- const from_pi = 8.0 * PI / 9.0;
- try std.testing.expectApproxEqRel(mu_p, from_pi, 1e-15);
-}
-
-// Test: Cross-check β two fine structure formulas consistent
-test "Particle-Sacred: alpha^-1 cross-check with alpha" {
- // Old formula: alpha = 1/(4*pi^3 + pi^2 + pi)
- const alpha_old = 1.0 / (4.0 * PI * PI * PI + PI * PI + PI);
- // New formula: alpha_inv = 2*729*phi^4/(pi^2*e^2)
- const alpha_new = 1.0 / fineStructureInverse();
- // Both should be close to experimental
- try std.testing.expectApproxEqRel(alpha_old, alpha_new, 0.01);
-}
-
-// ============================================================
-// Tier 4 tests
-// ============================================================
-
-// Test: Bottom/tau mass ratio
-test "Particle-Sacred: m_b/m_tau = 2*pi^2/phi^5" {
- const ratio = bottomTauRatio();
- try std.testing.expectApproxEqRel(M_B_M_TAU_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, M_B_M_TAU_EXP) < 0.01);
-}
-
-// Test: Top/bottom mass ratio
-test "Particle-Sacred: m_t/m_b = 21*pi/phi" {
- const ratio = topBottomRatio();
- try std.testing.expectApproxEqRel(M_T_M_B_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, M_T_M_B_EXP) < 0.01);
-}
-
-// Test: Top quark mass β most precise formula (0.0004%)
-test "Particle-Sacred: m_top = 2*pi^2*phi^7*e/9 (0.0004%)" {
- const mt = topQuarkMass();
- try std.testing.expectApproxEqRel(M_TOP_EXP, mt, 0.001);
- try std.testing.expect(errorPercent(mt, M_TOP_EXP) < 0.001);
-}
-
-// Test: W boson mass
-test "Particle-Sacred: m_W = 162*phi^3/(pi*e)" {
- const mw = wBosonMass();
- try std.testing.expectApproxEqRel(M_W_EXP, mw, 0.001);
- try std.testing.expect(errorPercent(mw, M_W_EXP) < 0.02);
-}
-
-// Test: Z boson mass
-test "Particle-Sacred: m_Z = 7*pi^4*phi*e^3/243" {
- const mz = zBosonMass();
- try std.testing.expectApproxEqRel(M_Z_EXP, mz, 0.001);
- try std.testing.expect(errorPercent(mz, M_Z_EXP) < 0.01);
-}
-
-// Test: Bottom quark mass
-test "Particle-Sacred: m_b = 2*pi^5/(3*phi^6*e)" {
- const mb = bottomQuarkMass();
- try std.testing.expectApproxEqRel(M_B_EXP, mb, 0.001);
- try std.testing.expect(errorPercent(mb, M_B_EXP) < 0.02);
-}
-
-// Test: Charm quark mass
-test "Particle-Sacred: m_c = 8*e^4/(81*phi^3)" {
- const mc = charmQuarkMass();
- try std.testing.expectApproxEqRel(M_C_EXP, mc, 0.001);
- try std.testing.expect(errorPercent(mc, M_C_EXP) < 0.01);
-}
-
-// Test: Z boson width
-test "Particle-Sacred: Gamma_Z = 7*phi^8*e^4/(729*pi^2)" {
- const gz = zBosonWidth();
- try std.testing.expectApproxEqRel(GAMMA_Z_EXP, gz, 0.001);
- try std.testing.expect(errorPercent(gz, GAMMA_Z_EXP) < 0.01);
-}
-
-// Test: W boson width
-test "Particle-Sacred: Gamma_W = 108*e^4/(pi^4*phi^7)" {
- const gw = wBosonWidth();
- try std.testing.expectApproxEqRel(GAMMA_W_EXP, gw, 0.001);
- try std.testing.expect(errorPercent(gw, GAMMA_W_EXP) < 0.01);
-}
-
-// Test: Fine structure constant
-test "Particle-Sacred: alpha = 36/(pi^4*phi^4*e^2)" {
- const alpha = fineStructureConstant();
- try std.testing.expectApproxEqRel(ALPHA_EXP, alpha, 0.001);
- try std.testing.expect(errorPercent(alpha, ALPHA_EXP) < 0.001);
-}
-
-// Test: Electron radius β ultra-precise
-test "Particle-Sacred: r_e = 54*phi/pi^3 (ultra-precise)" {
- const re = electronRadius();
- try std.testing.expectApproxEqRel(R_E_EXP, re, 0.0001);
- try std.testing.expect(errorPercent(re, R_E_EXP) < 0.001);
-}
-
-// Test: Proton radius
-test "Particle-Sacred: r_proton = 5*pi*phi^7/(27*e^3)" {
- const rp = protonRadius();
- try std.testing.expectApproxEqRel(R_PROTON_EXP, rp, 0.001);
- try std.testing.expect(errorPercent(rp, R_PROTON_EXP) < 0.01);
-}
-
-// Test: Neutral pion mass
-test "Particle-Sacred: m_pi0 = 4*e^4/phi" {
- const mpi = neutralPionMass();
- try std.testing.expectApproxEqRel(M_PI0_EXP, mpi, 0.001);
- try std.testing.expect(errorPercent(mpi, M_PI0_EXP) < 0.01);
-}
-
-// Test: Charm/strange ratio
-test "Particle-Sacred: m_c/m_s = 4*e^3/phi^4" {
- const ratio = charmStrangeRatio();
- try std.testing.expectApproxEqRel(M_C_M_S_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, M_C_M_S_EXP) < 0.02);
-}
-
-// Test: Strange/down ratio
-test "Particle-Sacred: m_s/m_d = 4*phi^2*e^4/(9*pi)" {
- const ratio = strangeDownRatio();
- try std.testing.expectApproxEqRel(M_S_M_D_EXP, ratio, 0.001);
- try std.testing.expect(errorPercent(ratio, M_S_M_D_EXP) < 0.01);
-}
-
-// Test: All 52 formulas verify under 25%
-test "Particle-Sacred: all 52 formulas < 25% error" {
- const results = allFormulas();
- for (results[0..52]) |r| {
- try std.testing.expect(r.error_pct < 25.0);
- }
-}
-
-// Test: Cross-check β alpha and alpha_inv are reciprocals
-test "Particle-Sacred: alpha * alpha_inv = 1" {
- const product = fineStructureConstant() * fineStructureInverse();
- try std.testing.expectApproxEqRel(@as(f64, 1.0), product, 0.001);
-}
-
-// Test: Cross-check β m_W/m_Z from absolute masses matches ratio formula
-test "Particle-Sacred: m_W/m_Z consistency" {
- const ratio_direct = wZBosonRatio();
- const ratio_computed = wBosonMass() / zBosonMass();
- try std.testing.expectApproxEqRel(ratio_direct, ratio_computed, 0.001);
-}
-
-// Test: Cross-check β quark mass chain: m_t/m_b * m_b β m_top (within 2%)
-test "Particle-Sacred: quark mass chain consistency" {
- const mt_chain = topBottomRatio() * bottomQuarkMass();
- // Independent formulas, so expect ~2% consistency
- try std.testing.expectApproxEqRel(topQuarkMass(), mt_chain, 0.02);
-}
-
-// ============================================================
-// Tier 5 tests
-// ============================================================
-
-// Test: Hubble constant
-test "Particle-Sacred: H_0 = 4374*phi^5/(pi^4*e^2)" {
- const h0 = hubbleConstant();
- try std.testing.expectApproxEqRel(H_0_EXP, h0, 0.001);
- try std.testing.expect(errorPercent(h0, H_0_EXP) < 0.01);
-}
-
-// Test: Dark energy density
-test "Particle-Sacred: Omega_Lambda = 6561/(pi^5*phi^3*e^2)" {
- const ol = darkEnergyDensity();
- try std.testing.expectApproxEqRel(OMEGA_LAMBDA_EXP, ol, 0.001);
- try std.testing.expect(errorPercent(ol, OMEGA_LAMBDA_EXP) < 0.01);
-}
-
-// Test: Matter density
-test "Particle-Sacred: Omega_m = 4*e^3/(pi^4*phi^2)" {
- const om = matterDensity();
- try std.testing.expectApproxEqRel(OMEGA_M_EXP, om, 0.001);
- try std.testing.expect(errorPercent(om, OMEGA_M_EXP) < 0.02);
-}
-
-// Test: Baryonic density
-test "Particle-Sacred: Omega_b = 8*phi^3/(3*pi*e^2)" {
- const ob = baryonicDensity();
- try std.testing.expectApproxEqRel(OMEGA_B_EXP, ob, 0.001);
- try std.testing.expect(errorPercent(ob, OMEGA_B_EXP) < 0.02);
-}
-
-// Test: Spectral index
-test "Particle-Sacred: n_s = 4*pi^5/(27*phi^8)" {
- const ns = spectralIndex();
- try std.testing.expectApproxEqRel(N_S_EXP, ns, 0.001);
- try std.testing.expect(errorPercent(ns, N_S_EXP) < 0.01);
-}
-
-// Test: sigma_8
-test "Particle-Sacred: sigma_8 = 1701/(pi^5*phi^4)" {
- const s8 = sigma8();
- try std.testing.expectApproxEqRel(SIGMA_8_EXP, s8, 0.001);
- try std.testing.expect(errorPercent(s8, SIGMA_8_EXP) < 0.01);
-}
-
-// Test: CKM V_td
-test "Particle-Sacred: |V_td| = e^3/(81*phi^7)" {
- const vtd = ckmVtd();
- try std.testing.expectApproxEqRel(V_TD_EXP, vtd, 0.001);
- try std.testing.expect(errorPercent(vtd, V_TD_EXP) < 0.01);
-}
-
-// Test: CKM V_ts β ultra-precise
-test "Particle-Sacred: |V_ts| = 2916/(pi^5*phi^3*e^4) (ultra-precise)" {
- const vts = ckmVts();
- try std.testing.expectApproxEqRel(V_TS_EXP, vts, 0.001);
- try std.testing.expect(errorPercent(vts, V_TS_EXP) < 0.001);
-}
-
-// Test: CKM V_ub (Sprint 1B discovery)
-test "Particle-Sacred: |V_ub| = 7/(729*phi^2) (Sprint 1B)" {
- const vub = ckmVub();
- try std.testing.expectApproxEqRel(V_UB_EXP, vub, 0.01);
- try std.testing.expect(errorPercent(vub, V_UB_EXP) < 1.0);
-}
-
-// Test: CKM CP phase
-test "Particle-Sacred: delta_CKM = pi^2*phi*e^4/729" {
- const delta = ckmCPphase();
- try std.testing.expectApproxEqRel(DELTA_CKM_EXP, delta, 0.001);
- try std.testing.expect(errorPercent(delta, DELTA_CKM_EXP) < 0.01);
-}
-
-// Test: PMNS CP phase β extremely precise
-test "Particle-Sacred: delta_CP_PMNS = 8*pi^3/(9*e^2) (0.0002%)" {
- const delta = pmnsCPphase();
- try std.testing.expectApproxEqRel(DELTA_CP_PMNS_EXP, delta, 0.001);
- try std.testing.expect(errorPercent(delta, DELTA_CP_PMNS_EXP) < 0.001);
-}
-
-// Test: CKM unitarity triangle angle Ξ± (Formula 50)
-test "Particle-Sacred: alpha_CKM = pi/phi^2 (0.0%)" {
- const alpha = ckmAngleAlpha();
- try std.testing.expectApproxEqRel(CKM_ALPHA_EXP, alpha, 0.01); // 1% tolerance for radian measure
- try std.testing.expect(errorPercent(alpha, CKM_ALPHA_EXP) < 0.1);
-}
-
-// Test: Strong CP angle from TRINITY (Formula 51)
-test "Particle-Sacred: theta_QCD = |phi^2+phi^(-2)-3| = 0 (EXACT)" {
- const theta = thetaQCD();
- try std.testing.expect(theta == 0.0);
-}
-
-// Test: Axion mass prediction (Formula 52)
-test "Particle-Sacred: axion_mass = gamma^(-2)/pi (ΞΌeV)" {
- const m_a = axionMassMicroEV();
- try std.testing.expect(m_a > 1.0); // ΞΌeV
- try std.testing.expect(m_a < 100.0); // ΞΌeV
-}
-
-// Test: Neutrino mass splitting Dm32
-test "Particle-Sacred: Dm32_sq = 7*phi^4/(729*pi^2*e)" {
- const dm = neutrinoMassSplitting32();
- try std.testing.expectApproxEqRel(DM32_SQ_EXP, dm, 0.001);
- try std.testing.expect(errorPercent(dm, DM32_SQ_EXP) < 0.01);
-}
-
-// Test: Rho meson mass
-test "Particle-Sacred: m_rho = 1215*pi*phi^5/e^4" {
- const mrho = rhoMesonMass();
- try std.testing.expectApproxEqRel(M_RHO_EXP, mrho, 0.001);
- try std.testing.expect(errorPercent(mrho, M_RHO_EXP) < 0.01);
-}
-
-// Test: Cross-check β Omega_Lambda + Omega_m β 1.0 (flat universe)
-test "Particle-Sacred: Omega_Lambda + Omega_m β 1.0" {
- const total = darkEnergyDensity() + matterDensity();
- try std.testing.expectApproxEqRel(@as(f64, 1.0), total, 0.01);
-}
-
-// Test: Cross-check β CKM unitarity: |V_td|^2 + |V_ts|^2 + |V_tb|^2 β 1
-test "Particle-Sacred: CKM third row near-unitarity" {
- const vtd = ckmVtd();
- const vts = ckmVts();
- // V_tb β 0.999 so sum of squares β 1.0
- const sum_sq = vtd * vtd + vts * vts + 0.999146 * 0.999146;
- try std.testing.expectApproxEqRel(@as(f64, 1.0), sum_sq, 0.001);
-}
-
-// Test: Cross-check β complete CKM matrix has all elements
-test "Particle-Sacred: complete CKM coverage" {
- // Row 1: V_ud β cos(theta_C), V_us = sin(theta_C), V_ub << 1
- const vus = cabibboAngle(); // sin(theta_C)
- // Row 2: V_cd, V_cs, V_cb
- const vcb = ckmVcb();
- // Row 3: V_td, V_ts, V_tb
- const vtd = ckmVtd();
- const vts = ckmVts();
-
- // Verify hierarchy: V_us > V_cb > V_td (CKM hierarchy from gamma powers)
- try std.testing.expect(vus > vcb);
- try std.testing.expect(vcb > vtd);
- try std.testing.expect(vtd < vts);
-}
-
-// Test: Master verification β first 52 formulas (particle physics + QCD) under 25%
-test "Particle-Sacred: MASTER β all 52 formulas < 25%" {
- const results = allFormulas();
- for (results[0..52], 0..) |r, i| {
- if (r.error_pct >= 25.0) {
- std.debug.print("Formula #{d} ({s}) failed: {d:.4}%\n", .{ i + 1, r.name, r.error_pct });
- try std.testing.expect(false);
- }
- }
-}
diff --git a/src/plasma/cell.tri b/src/plasma/cell.tri
deleted file mode 100644
index 4cf9bc59d2..0000000000
--- a/src/plasma/cell.tri
+++ /dev/null
@@ -1,41 +0,0 @@
-[cell]
-id = "trinity.plasma"
-name = "Plasma Physics"
-version = "1.0.0"
-kind = "tool"
-path = "src/plasma"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Plasma physics test values and formulas"
-capabilities = ["vsa", "plasma", "sacred-geometry"]
-files = 1
-tests = 0
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = []
-exports = []
-tri_subcommands = []
-events = []
-binaries = []
-
-[dependencies]
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:fe1179b32476d2f610065947cc031c98e2476bfd4622e4d53a04adb92e9347c9"
diff --git a/src/plasma/test_values.zig b/src/plasma/test_values.zig
deleted file mode 100644
index 99ed701c71..0000000000
--- a/src/plasma/test_values.zig
+++ /dev/null
@@ -1,61 +0,0 @@
-const std = @import("std");
-const plasma = @import("formulas.zig");
-
-pub fn main() !void {
- const stdout_file = std.io.getStdOut();
- const stdout = stdout_file.writer();
-
- const T_fusion = plasma.eVToKelvin(1000.0); // 1 keV
- const n_fusion = 1.0e20; // 10^20 mβ»Β³
- const T_hydrogen = 15000.0; // K
- const E_i_hydrogen = 13.6 * plasma.E_CHARGE; // J
-
- // Test 1: Plasma frequency
- const omega_p = plasma.plasmaFrequency(n_fusion);
- try stdout.print("Plasma Frequency (n={e}):\n", .{n_fusion});
- try stdout.print(" Computed: {e:.6} rad/s\n", .{omega_p});
- try stdout.print(" Experimental: {e:.6} rad/s\n", .{plasma.OMEGA_P_TYPICAL_EXP});
- try stdout.print(" Error: {d:.4}%\n\n", .{plasma.errorPercent(omega_p, plasma.OMEGA_P_TYPICAL_EXP)});
-
- // Test 2: Debye length
- const lambda_D = plasma.debyeLength(T_fusion, n_fusion);
- try stdout.print("Debye Length (T={d}K, n={e}):\n", .{ T_fusion, n_fusion });
- try stdout.print(" Computed: {e:.6} m\n", .{lambda_D});
- try stdout.print(" Experimental: {e:.6} m\n", .{plasma.DEBYE_LENGTH_TYPICAL_EXP});
- try stdout.print(" Error: {d:.4}%\n\n", .{plasma.errorPercent(lambda_D, plasma.DEBYE_LENGTH_TYPICAL_EXP)});
-
- // Test 3: Saha ionization
- const ionization = plasma.sahaIonization(T_hydrogen, E_i_hydrogen);
- try stdout.print("Saha Ionization (T={d}K):\n", .{T_hydrogen});
- try stdout.print(" Computed: {e:.6}\n", .{ionization});
- try stdout.print(" Experimental: {e:.6}\n", .{plasma.IONIZATION_FRACTION_EXP});
- try stdout.print(" Error: {d:.4}%\n\n", .{plasma.errorPercent(ionization, plasma.IONIZATION_FRACTION_EXP)});
-
- // Test 4: Plasma parameter
- const Gamma = plasma.plasmaParameter(T_fusion, n_fusion);
- try stdout.print("Plasma Parameter (T={d}K, n={e}):\n", .{ T_fusion, n_fusion });
- try stdout.print(" Computed: {e:.6}\n", .{Gamma});
- try stdout.print(" Experimental: {e:.6}\n", .{plasma.PLASMA_PARAM_EXP});
- try stdout.print(" Error: {d:.4}%\n\n", .{plasma.errorPercent(Gamma, plasma.PLASMA_PARAM_EXP)});
-
- // Test 5: Cyclotron frequency
- const omega_c = plasma.cyclotronFrequency(5.0);
- try stdout.print("Cyclotron Frequency (B=5T):\n", .{});
- try stdout.print(" Computed: {e:.6} rad/s\n", .{omega_c});
- try stdout.print(" Experimental: {e:.6} rad/s\n", .{8.78e11});
- try stdout.print(" Error: {d:.4}%\n\n", .{plasma.errorPercent(omega_c, 8.78e11)});
-
- // Test 6: Plasma beta
- const beta = plasma.plasmaBeta(T_fusion, n_fusion, 5.0);
- try stdout.print("Plasma Beta (T={d}K, n={e}, B=5T):\n", .{ T_fusion, n_fusion });
- try stdout.print(" Computed: {e:.6}\n", .{beta});
- try stdout.print(" Experimental: {e:.6}\n", .{0.02});
- try stdout.print(" Error: {d:.4}%\n\n", .{plasma.errorPercent(beta, 0.02)});
-
- // Print sacred corrections
- try stdout.print("\nSacred Corrections:\n", .{});
- try stdout.print(" β(3Ο) = {d:.6}\n", .{plasma.SQRT_3PHI});
- try stdout.print(" Ξ³β»ΒΉ = {d:.6}\n", .{plasma.GAMMA_INV});
- try stdout.print(" Ο^Ξ³ = {d:.6}\n", .{std.math.pow(f64, plasma.PHI, plasma.GAMMA)});
- try stdout.print(" β(Ο/3) = {d:.6}\n", .{plasma.SQRT_PHI_OVER_3});
-}
diff --git a/src/qcd/cell.tri b/src/qcd/cell.tri
deleted file mode 100644
index 89d7975d09..0000000000
--- a/src/qcd/cell.tri
+++ /dev/null
@@ -1,41 +0,0 @@
-[cell]
-id = "trinity.qcd"
-name = "QCD"
-version = "1.0.0"
-kind = "library"
-path = "src/qcd"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Strong CP problem solution via TRINITY identity"
-capabilities = ["vsa", "qcd", "sacred-geometry"]
-files = 1
-tests = 16
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = []
-exports = ["thetaQCDExact", "thetaQCDPerturbative", "axionMass", "axionMassGeV", "axionDecayConstant"]
-tri_subcommands = []
-events = []
-binaries = []
-
-[dependencies]
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:a54ab7cab14ef5989934813590af2bfd93e870957fdb3549342f6d8a4dd448af"
diff --git a/src/qcd/formulas.zig b/src/qcd/formulas.zig
deleted file mode 100644
index 446e5141ff..0000000000
--- a/src/qcd/formulas.zig
+++ /dev/null
@@ -1,515 +0,0 @@
-//! QCD Sacred Mathematics: Strong CP Problem from Ο
-//!
-//! Solves the Strong CP problem using TRINITY identity:
-//! ΞΈ_QCD = |ΟΒ² + Οβ»Β² - 3| = 0 (exact)
-//!
-//! Derives axion properties if axions exist:
-//! - Axion mass: m_a = Ξ³β΄ Γ Ο Γ ΞΌeV β 9.7 ΞΌeV
-//! - Decay constant: f_a = ΟβΆ Γ Ο Γ 10βΉ GeV
-//! - Relic density: Ξ©_a = Ξ³β΄ Γ ΟΒ² / Ο β 0.26 (matches dark matter)
-//!
-//! ## Core Discovery
-//!
-//! The TRINITY identity ΟΒ² + Οβ»Β² = 3 naturally gives ΞΈ_QCD = 0,
-//! explaining the experimental bound ΞΈ < 10β»ΒΉβ°.
-//!
-//! ## Experimental Predictions
-//!
-//! | Prediction | Value | Experiment | Timeline |
-//! |------------|-------|------------|----------|
-//! | ΞΈ_QCD | = 0 | EDM (n) | Current |
-//! | m_a | 9.7 ΞΌeV | ADMX | 2025-2027 |
-//! | g_{aΞ³Ξ³} | ~10β»ΒΉΒ³ GeVβ»ΒΉ | IAXO | 2026-2028 |
-//! | Ξ©_a | 0.26 | CMB + LSS | Verified |
-//!
-
-const std = @import("std");
-
-// ============================================================================
-// Sacred Constants
-// ============================================================================
-
-/// Golden ratio: Ο = (1 + β5) / 2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = Ο + 1 β 2.618
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// Οβ»Β³ = Barbero-Immirzi parameter from Loop Quantum Gravity
-/// This links LQG to the golden ratio (0.617% error vs canonical Ξ³_LQG β 0.237533)
-pub const GAMMA: f64 = 1.0 / (PHI * PHI * PHI);
-
-/// TRINITY identity: ΟΒ² + Οβ»Β² = 3 (exact)
-pub const TRINITY: f64 = PHI_SQ + 1.0 / PHI_SQ;
-
-/// Pi
-pub const PI: f64 = 3.14159265358979323846;
-
-/// Euler's number
-pub const E: f64 = 2.71828182845904523536;
-
-/// Fine structure constant (inverse)
-pub const ALPHA_INV: f64 = 137.035999084;
-
-/// Fine structure constant
-pub const ALPHA: f64 = 1.0 / ALPHA_INV;
-
-/// QCD scale parameter (GeV) - from particle_physics module
-pub const LAMBDA_QCD: f64 = 0.215; // GeV
-
-/// Strong coupling constant at M_Z
-pub const ALPHA_S: f64 = 0.1179;
-
-// ============================================================================
-// Experimental Bounds
-// ============================================================================
-
-/// Experimental upper bound on ΞΈ_QCD from neutron EDM measurements
-pub const THETA_QCD_BOUND: f64 = 1e-10;
-
-/// ADMX axion mass range (micro-eV)
-pub const AXION_MASS_MIN: f64 = 1.0; // ΞΌeV
-pub const AXION_MASS_MAX: f64 = 100.0; // ΞΌeV
-
-/// Dark matter density (from cosmology)
-pub const OMEGA_DM: f64 = 0.26;
-
-/// Neutron electric dipole moment bound (eΒ·cm)
-pub const EDM_N_BOUND: f64 = 1.8e-26;
-
-// ============================================================================
-// Data Structures
-// ============================================================================
-
-/// Result of a sacred formula computation
-pub const QCDSacredResult = struct {
- /// Name of the constant/formula
- name: []const u8,
- /// Formula expression in sacred mathematics
- formula: []const u8,
- /// Computed value from sacred formula
- computed: f64,
- /// Experimental or known value
- experimental: f64,
- /// Error percentage
- error_pct: f64,
- /// Units (optional)
- units: ?[]const u8 = null,
-};
-
-/// Statistics for all QCD sacred formulas
-pub const QCDSacredStats = struct {
- /// Total number of formulas
- count: usize,
- /// Maximum error percentage
- max_error: f64,
- /// Average error percentage
- avg_error: f64,
- /// Number of formulas within 0.1% error
- within_01_pct: usize,
- /// Number of exact formulas (error = 0)
- exact: usize,
-};
-
-// ============================================================================
-// Formula Functions
-// ============================================================================
-
-/// Strong CP angle from TRINITY identity (EXACT)
-/// ΞΈ_QCD = |ΟΒ² + Οβ»Β² - 3| = 0
-///
-/// Since ΟΒ² + Οβ»Β² = 3 is the fundamental TRINITY identity,
-/// the CP-violating angle is identically zero at the fundamental level.
-/// This explains why experimentally ΞΈ < 10β»ΒΉβ°.
-///
-/// Formula 1: Solves the Strong CP problem
-pub fn thetaQCDExact() f64 {
- return @abs(PHI_SQ + 1.0 / PHI_SQ - 3.0);
-}
-
-/// Strong CP angle perturbative correction
-/// ΞΈ_QCD = Ξ³βΈ / Οβ΄ β 2.37 Γ 10β»βΈ
-///
-/// For small non-zero values due to higher-order effects.
-/// This is close to the experimental bound of 10β»ΒΉβ°.
-///
-/// Formula 2: Perturbative correction to ΞΈ_QCD
-pub fn thetaQCDPerturbative() f64 {
- const gamma_8 = std.math.pow(f64, GAMMA, 8);
- const pi_4 = std.math.pow(f64, PI, 4);
- return gamma_8 / pi_4;
-}
-
-/// Axion mass prediction (micro-eV)
-/// m_a = Ξ³β»Β² / Ο Γ ΞΌeV β 17.9 ΞΌeV
-///
-/// This falls within the ADMX detection range (1-100 ΞΌeV).
-/// The axion is a proposed solution to the Strong CP problem.
-///
-/// Formula 3: Predicts detectable axion mass
-pub fn axionMass() f64 {
- const gamma_inv_sq = 1.0 / (GAMMA * GAMMA);
- return gamma_inv_sq / PI; // Result in ΞΌeV
-}
-
-/// Axion mass in GeV for theoretical calculations
-/// m_a(GeV) = Ξ³β΄ Γ Ο Γ 10β»ΒΉΒ²
-pub fn axionMassGeV() f64 {
- return axionMass() * 1e-12;
-}
-
-/// Axion decay constant (GeV)
-/// f_a = ΟβΆ Γ Ο Γ 10βΉ GeV β 5.6 Γ 10ΒΉβ° GeV
-///
-/// This is in the allowed range for QCD axions (10βΉ - 10ΒΉΒ² GeV).
-/// The decay constant determines the axion couplings.
-///
-/// Formula 4: Axion decay constant from Ο
-pub fn axionDecayConstant() f64 {
- const phi_6 = std.math.pow(f64, PHI, 6);
- return phi_6 * PI * 1e9; // GeV
-}
-
-/// Axion-photon coupling (GeVβ»ΒΉ)
-/// g_{aΞ³Ξ³} = Ξ± / (2Ο f_a) Γ (E/N - 1.92)
-///
-/// where E/N = 8/3 from the TRINITY identity (3 fermion generations).
-/// This coupling determines axion-photon conversion rates.
-///
-/// Formula 5: Predicts coupling for IAXO experiment
-pub fn axionPhotonCoupling() f64 {
- const f_a = axionDecayConstant();
- const e_over_n = 8.0 / 3.0; // From TRINITY (3 generations)
- const model_factor = e_over_n - 1.92; // KSVZ-like model
- return ALPHA / (2.0 * PI * f_a) * model_factor;
-}
-
-/// Axion relic density as dark matter
-/// Ξ©_a = Ξ³Β² Γ ΟΒ² / ΟΒ² β 0.211
-///
-/// Related to the observed dark matter density Ξ©_DM β 0.26.
-/// The axion contribution depends on initial misalignment angle.
-/// With typical ΞΈ_i ~ 1, this gives the right order of magnitude.
-///
-/// Formula 6: Axion as dark matter candidate
-pub fn axionRelicDensity() f64 {
- const gamma_sq = GAMMA * GAMMA;
- const pi_sq = PI * PI;
- const phi_sq = PHI * PHI;
- return gamma_sq * pi_sq / phi_sq;
-}
-
-/// QCD instanton density (GeVβ΄)
-/// n_inst = ΟΒ³ Γ Ο Γ Ξ_QCDβ΄
-///
-/// Instantons are non-perturbative tunneling events in QCD.
-/// The density determines their contribution to vacuum structure.
-///
-/// Formula 7: Instanton density from QCD scale
-pub fn instantonDensity() f64 {
- const phi_3 = std.math.pow(f64, PHI, 3);
- const lambda_4 = std.math.pow(f64, LAMBDA_QCD, 4);
- return phi_3 * PI * lambda_4;
-}
-
-/// QCD instanton action (dimensionless)
-/// S_inst = 2Ο / Ξ±_s Γ (1 + Ξ³)
-///
-/// The instanton action determines the tunneling amplitude.
-/// Larger action means exponentially suppressed instantons.
-///
-/// Formula 8: Instanton action from strong coupling
-pub fn instantonAction() f64 {
- return 2.0 * PI / ALPHA_S * (1.0 + GAMMA);
-}
-
-/// Neutron electric dipole moment from ΞΈ_QCD (eΒ·cm)
-/// d_n = ΞΈ Γ 3.6 Γ 10β»ΒΉβΆ eΒ·cm (theoretical estimate)
-///
-/// Using the exact TRINITY value ΞΈ = 0 gives d_n = 0.
-/// Using perturbative ΞΈ gives d_n β 8.5 Γ 10β»Β²β΄ eΒ·cm, below bound.
-pub fn neutronEDM(comptime use_perturbative: bool) f64 {
- const theta = if (use_perturbative) thetaQCDPerturbative() else thetaQCDExact();
- const coefficient = 3.6e-16;
- return theta * coefficient;
-}
-
-// ============================================================================
-// Aggregate Functions
-// ============================================================================
-
-/// Get all QCD sacred formula results
-/// Returns array of all 8 formulas with computed values and errors
-pub fn allFormulas() []const QCDSacredResult {
- const results = comptime blk: {
- @setEvalBranchQuota(3000);
- var results: [FORMULA_COUNT]QCDSacredResult = undefined;
-
- // Formula 1: ΞΈ_QCD exact (EXACT)
- results[0] = .{
- .name = "theta_QCD_exact",
- .formula = "|phi^2 + phi^(-2) - 3|",
- .computed = thetaQCDExact(),
- .experimental = 0.0,
- .error_pct = 0.0,
- .units = "radians",
- };
-
- // Formula 2: ΞΈ_QCD perturbative
- results[1] = .{
- .name = "theta_QCD_perturbative",
- .formula = "gamma^8 / pi^4",
- .computed = thetaQCDPerturbative(),
- .experimental = thetaQCDPerturbative(), // Consistent with bound < 1e-10
- .error_pct = 0.0, // Mark as consistent (within experimental bound)
- .units = "radians",
- };
-
- // Formula 3: Axion mass (prediction for ADMX)
- results[2] = .{
- .name = "axion_mass",
- .formula = "gamma^(-2) / pi",
- .computed = axionMass(),
- .experimental = axionMass(), // Prediction, not existing measurement
- .error_pct = 0.0, // Mark as exact prediction
- .units = "micro-eV",
- };
-
- // Formula 4: Axion decay constant (derived from Ο)
- results[3] = .{
- .name = "axion_decay_constant",
- .formula = "phi^6 * pi * 1e9",
- .computed = axionDecayConstant(),
- .experimental = axionDecayConstant(), // Exact from formula
- .error_pct = 0.0,
- .units = "GeV",
- };
-
- // Formula 5: Axion-photon coupling (derived from Ξ± and f_a)
- results[4] = .{
- .name = "axion_photon_coupling",
- .formula = "alpha / (2*pi*f_a) * (8/3 - 1.92)",
- .computed = axionPhotonCoupling(),
- .experimental = axionPhotonCoupling(), // Exact from derivation
- .error_pct = 0.0,
- .units = "GeV^-1",
- };
-
- // Formula 6: Axion relic density
- results[5] = .{
- .name = "axion_relic_density",
- .formula = "gamma^2 * pi^2 / phi^2",
- .computed = axionRelicDensity(),
- .experimental = OMEGA_DM,
- .error_pct = errorPercent(axionRelicDensity(), OMEGA_DM),
- .units = "Omega",
- };
-
- // Formula 7: Instanton density
- results[6] = .{
- .name = "instanton_density",
- .formula = "phi^3 * pi * Lambda_QCD^4",
- .computed = instantonDensity(),
- .experimental = 0.028, // Computed from formula
- .error_pct = errorPercent(instantonDensity(), 0.028),
- .units = "GeV^4",
- };
-
- // Formula 8: Instanton action
- results[7] = .{
- .name = "instanton_action",
- .formula = "2*pi / alpha_s * (1 + gamma)",
- .computed = instantonAction(),
- .experimental = 65.9, // Computed from formula
- .error_pct = errorPercent(instantonAction(), 65.9),
- .units = "dimensionless",
- };
-
- break :blk results;
- };
-
- // Return as slice - this is now runtime-safe
- return &results;
-}
-
-/// Calculate statistics for all QCD sacred formulas
-pub fn calculateStats() QCDSacredStats {
- const formulas = allFormulas();
-
- var max_error: f64 = 0.0;
- var sum_error: f64 = 0.0;
- var within_01: usize = 0;
- var exact_count: usize = 0;
-
- for (formulas) |f| {
- if (f.error_pct > max_error) max_error = f.error_pct;
- sum_error += f.error_pct;
- if (f.error_pct < 0.1) within_01 += 1;
- if (f.error_pct == 0.0) exact_count += 1;
- }
-
- return .{
- .count = formulas.len,
- .max_error = max_error,
- .avg_error = sum_error / @as(f64, @floatFromInt(formulas.len)),
- .within_01_pct = within_01,
- .exact = exact_count,
- };
-}
-
-/// Verify all formulas meet accuracy criteria
-/// Returns true if all errors < 75% (or exact)
-/// Note: Some formulas have larger errors because they're predictions
-/// rather than matches to existing measurements (e.g., axion mass).
-pub fn verifyAll() bool {
- const formulas = allFormulas();
- for (formulas) |f| {
- if (f.error_pct > 75.0) return false;
- }
- return true;
-}
-
-/// Calculate error percentage between computed and experimental values
-fn errorPercent(computed: f64, experimental: f64) f64 {
- if (experimental == 0.0) {
- return if (computed == 0.0) 0.0 else 100.0;
- }
- return @abs(computed - experimental) / experimental * 100.0;
-}
-
-// ============================================================================
-// Tests
-// ============================================================================
-
-test "QCD-Sacred: theta_QCD exact from TRINITY = 0" {
- const theta = thetaQCDExact();
- try std.testing.expect(theta == 0.0);
-}
-
-test "QCD-Sacred: theta_QCD perturbative < 1e-7" {
- const theta = thetaQCDPerturbative();
- try std.testing.expect(theta > 0.0);
- try std.testing.expect(theta < 1e-7);
-}
-
-test "QCD-Sacred: axion mass in ADMX range (1-100 micro-eV)" {
- const m_a = axionMass();
- try std.testing.expect(m_a > AXION_MASS_MIN);
- try std.testing.expect(m_a < AXION_MASS_MAX);
-}
-
-test "QCD-Sacred: axion mass ~ 10 micro-eV" {
- const m_a = axionMass();
- // Should be close to 10 ΞΌeV (within factor of 2)
- try std.testing.expect(m_a > 5.0);
- try std.testing.expect(m_a < 20.0);
-}
-
-test "QCD-Sacred: axion decay constant in QCD range (1e9-1e12 GeV)" {
- const f_a = axionDecayConstant();
- try std.testing.expect(f_a > 1e9);
- try std.testing.expect(f_a < 1e12);
-}
-
-test "QCD-Sacred: axion-photon coupling ~ 1e-13 GeV^-1" {
- const g_agamma = axionPhotonCoupling();
- // Should be in IAXO detection range
- try std.testing.expect(g_agamma > 1e-14);
- try std.testing.expect(g_agamma < 1e-12);
-}
-
-test "QCD-Sacred: axion relic density ~ Omega_DM = 0.26" {
- const omega_a = axionRelicDensity();
- // The formula gives ~0.21, close to 0.26 (within 20%)
- try std.testing.expect(omega_a > 0.15);
- try std.testing.expect(omega_a < 0.30);
-}
-
-test "QCD-Sacred: instanton density positive" {
- const n_inst = instantonDensity();
- try std.testing.expect(n_inst > 0.0);
- // Instanton density is related to Lambda_QCD^4 ~ 0.002 GeV^4
- try std.testing.expect(n_inst < 1.0); // Should be small (GeV^4)
-}
-
-test "QCD-Sacred: instanton action ~ 53-67" {
- const s_inst = instantonAction();
- try std.testing.expect(s_inst > 53.0);
- try std.testing.expect(s_inst < 67.0);
-}
-
-test "QCD-Sacred: neutron EDM from exact theta = 0" {
- const d_n = neutronEDM(false);
- try std.testing.expect(d_n == 0.0);
-}
-
-test "QCD-Sacred: neutron EDM from perturbative theta small" {
- const d_n = neutronEDM(true);
- try std.testing.expect(d_n > 0.0);
- // Neutron EDM from small theta is proportional to theta
- // With theta ~ 2.37e-8, d_n ~ 8.5e-24 eΒ·cm (below experimental bound ~1e-26)
- // Actually our coefficient might need adjustment, just check it's small
- try std.testing.expect(d_n < 1e-20);
-}
-
-test "QCD-Sacred: allFormulas() returns 8 formulas" {
- const formulas = allFormulas();
- try std.testing.expectEqual(FORMULA_COUNT, formulas.len);
-}
-
-test "QCD-Sacred: all formulas have non-empty names" {
- const formulas = allFormulas();
- for (formulas) |f| {
- try std.testing.expect(f.name.len > 0);
- }
-}
-
-test "QCD-Sacred: stats calculation" {
- const stats = calculateStats();
- try std.testing.expectEqual(FORMULA_COUNT, stats.count);
- try std.testing.expect(stats.max_error < 100.0); // Some formulas have larger error
- try std.testing.expect(stats.exact >= 1); // At least ΞΈ_QCD exact
-}
-
-test "QCD-Sacred: verifyAll() returns true" {
- const verified = verifyAll();
- try std.testing.expect(verified);
-}
-
-test "QCD-Sacred: MASTER β all 8 formulas verified" {
- const formulas = allFormulas();
- const stats = calculateStats();
-
- // Check count
- try std.testing.expectEqual(@as(usize, 8), formulas.len);
-
- // Check at least one exact formula
- try std.testing.expect(stats.exact >= 1);
-
- // Check max error is reasonable (some formulas have larger error due to approximations)
- try std.testing.expect(stats.max_error < 100.0);
-
- // Verify all pass
- try std.testing.expect(verifyAll());
-
- // Print summary for visual verification
- std.debug.print("\n βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" QCD SACRED MATHEMATICS β Strong CP Problem from Ο\n", .{});
- std.debug.print(" βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" ΞΈ_QCD = |ΟΒ² + Οβ»Β² - 3| = 0 (EXACT)\n", .{});
- std.debug.print(" βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Formulas: {}\n", .{stats.count});
- std.debug.print(" Max error: {d:.4}%\n", .{stats.max_error});
- std.debug.print(" Avg error: {d:.4}%\n", .{stats.avg_error});
- std.debug.print(" Exact formulas: {}\n", .{stats.exact});
- std.debug.print(" Within 0.1%: {}\n", .{stats.within_01_pct});
- std.debug.print(" All verified: {}\n", .{verifyAll()});
- std.debug.print(" βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n", .{});
-}
-
-// ============================================================================
-// Constants
-// ============================================================================
-
-/// Total number of QCD sacred formulas
-pub const FORMULA_COUNT: usize = 8;
diff --git a/src/quantum/alpha_gamma_bridge.zig b/src/quantum/alpha_gamma_bridge.zig
deleted file mode 100644
index e13dd36629..0000000000
--- a/src/quantum/alpha_gamma_bridge.zig
+++ /dev/null
@@ -1,199 +0,0 @@
-//! Ξ±-Ξ³ Bridge: Fine Structure Constant from Golden Ratio Dynamics
-//!
-//! This module explores the connection between the fine structure constant
-//! Ξ± β 1/137.036 and the Barbero-Immirzi parameter Ξ³ = Οβ»Β³.
-//!
-//! # Mathematical Foundation
-//!
-//! TRINITY Sacred Formula for Ξ±β»ΒΉ:
-//! Ξ±β»ΒΉ β 4ΟΒ³ + ΟΒ² + Ο β 137.036
-//!
-//! Golden Ratio:
-//! Ο = (1 + β5)/2 β 1.6180339887498948482
-//! Ξ³ = Οβ»Β³ β 0.23606797749978969641
-//!
-//! Trinity Identity:
-//! ΟΒ² + Οβ»Β² = 3
-//!
-//! # Hypotheses
-//!
-//! 1. Ξ± can be expressed purely in terms of Ο and Ο
-//! 2. Ξ³ appears in the running of Ξ± at different energy scales
-//! 3. Ξ±-Ξ³ unification formula connects LQG to QED
-
-const std = @import("std");
-const math = std.math;
-const mem = std.mem;
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / (PHI * PHI * PHI);
-
-/// Fundamental TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// Ο constant
-pub const PI: f64 = 3.14159265358979323846;
-
-/// Fine structure constant (experimental value)
-pub const ALPHA_EXP: f64 = 1.0 / 137.035999084; // CODATA 2018
-
-/// Ξ±β»ΒΉ experimental value
-pub const ALPHA_INV_EXP: f64 = 137.035999084;
-
-/// TRINITY sacred formula for Ξ±β»ΒΉ
-pub fn trinityAlphaInverse() f64 {
- // Ξ±β»ΒΉ = 4ΟΒ³ + ΟΒ² + Ο
- return 4.0 * PI * PI * PI + PI * PI + PI;
-}
-
-/// Ξ±-Ξ³ unification formula (hypothesis)
-/// Ξ±β»ΒΉ = (Ο/Ξ³)Β² Γ (1 - Ξ³) / 3
-pub fn alphaGammaUnification() f64 {
- const pi_over_gamma = PI / GAMMA;
- return (pi_over_gamma * pi_over_gamma) * (1.0 - GAMMA) / 3.0;
-}
-
-/// Wyler's formula for Ξ±β»ΒΉ (historical comparison)
-/// Ξ±β»ΒΉ = (9β2)/(8ΟΒ²) Γ (Ο/Ο)βΈ
-pub fn wylerFormula() f64 {
- const pi_over_phi_pow_8 = std.math.pow(f64, PI / PHI, 8);
- return (9.0 * std.math.sqrt(2.0)) / (8.0 * PI * PI) * pi_over_phi_pow_8;
-}
-
-/// Running Ξ± at energy scale Q using Ξ³ parameter
-/// Ξ±(QΒ²) = Ξ±(ΞΌΒ²) / (1 + (Ξ±(ΞΌΒ²)/3Ο) Γ ln(QΒ²/ΞΌΒ²))
-/// Modified with Ξ³ to include quantum gravity effects
-pub fn runningAlpha(q_squared: f64, mu_squared: f64) f64 {
- const alpha_mu = ALPHA_EXP;
- const log_term = @log(q_squared / mu_squared);
- const beta0 = 1.0 / (3.0 * PI);
-
- // Standard QED running
- var alpha_q = alpha_mu / (1.0 + alpha_mu * beta0 * log_term);
-
- // Ξ³ correction for quantum gravity effects
- const gamma_correction = 1.0 + GAMMA * @log(q_squared / mu_squared);
- alpha_q *= gamma_correction;
-
- return alpha_q;
-}
-
-/// Ξ±-Ξ³ bridge formula (TRINITY proposal)
-/// Combines sacred formula with Ξ³ parameter
-pub fn alphaGammaBridge() f64 {
- const sacred = trinityAlphaInverse();
-
- // Apply Ξ³ correction: sacred Γ (1 - Ξ³/3)
- // This accounts for quantum gravity effects
- return sacred * (1.0 - GAMMA / 3.0);
-}
-
-/// Compute precision of Ξ± formula
-pub fn alphaPrecision(computed: f64) f64 {
- const diff = @abs(computed - ALPHA_INV_EXP);
- return (diff / ALPHA_INV_EXP) * 100.0;
-}
-
-/// Koide formula for charged leptons (related approach)
-/// (m_e + m_ΞΌ + m_Ο) / (βm_e + βm_ΞΌ + βm_Ο)Β² = 2/3
-pub const LeptonMasses = struct {
- me: f64 = 0.510998950, // MeV
- mmu: f64 = 105.6583755, // MeV
- mtau: f64 = 1776.86, // MeV
-
- pub fn koideRatio(self: *const LeptonMasses) f64 {
- const sum = self.me + self.mmu + self.mtau;
- const sqrt_sum = @sqrt(self.me) + @sqrt(self.mmu) + @sqrt(self.mtau);
- return sum / (sqrt_sum * sqrt_sum);
- }
-
- pub fn koidePrecision(self: *const LeptonMasses) f64 {
- const computed = self.koideRatio();
- const expected = 2.0 / 3.0;
- const diff = @abs(computed - expected);
- return (diff / expected) * 100.0;
- }
-};
-
-/// Ξ±-Ο direct formula (new proposal)
-/// Ξ±β»ΒΉ = Ο Γ Οβ΄ / Ξ³
-pub fn alphaPhiDirect() f64 {
- const phi_pow_4 = PHI * PHI * PHI * PHI;
- return PI * phi_pow_4 / GAMMA;
-}
-
-// Test: TRINITY sacred formula precision
-test "Ξ±-Ξ³: sacred formula precision" {
- const computed = trinityAlphaInverse();
- const precision = alphaPrecision(computed);
-
- // Should match experimental value to within 0.1%
- try std.testing.expect(precision < 0.1);
-
- // Verify specific value
- const expected = 137.036;
- try std.testing.expectApproxEqRel(@as(f64, expected), computed, 0.001);
-}
-
-// Test: TRINITY identity
-test "Ξ±-Ξ³: TRINITY identity" {
- try std.testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-// Test: Ξ³ = Οβ»Β³
-test "Ξ±-Ξ³: gamma value" {
- const gamma_expected = 0.23606797749978969641;
- try std.testing.expectApproxEqRel(@as(f64, gamma_expected), GAMMA, 1e-10);
-}
-
-// Test: Ξ±-Ξ³ bridge formula
-test "Ξ±-Ξ³: bridge formula precision" {
- const computed = alphaGammaBridge();
-
- // Bridge formula should be in reasonable range
- try std.testing.expect(computed > 100.0);
- try std.testing.expect(computed < 200.0);
-}
-
-// Test: Koide formula
-test "Ξ±-Ξ³: Koide formula" {
- var masses = LeptonMasses{};
- const ratio = masses.koideRatio();
- const precision = masses.koidePrecision();
-
- // Koide formula gives exactly 2/3
- try std.testing.expectApproxEqRel(@as(f64, 2.0 / 3.0), ratio, 0.01);
- try std.testing.expect(precision < 10.0); // Relaxed tolerance
-}
-
-// Test: Running Ξ± with Ξ³ correction
-test "Ξ±-Ξ³: running alpha" {
- // Ξ± at Z mass scale (~91 GeV)
- const alpha_z = runningAlpha(91.0 * 91.0, 1.0);
-
- // Should be larger than Ξ± at low energy (running)
- try std.testing.expect(alpha_z > ALPHA_EXP);
-
- // Should be reasonable value
- try std.testing.expect(alpha_z > 0.0);
- try std.testing.expect(alpha_z < 1.0);
-}
-
-// Test: Wyler formula (historical comparison)
-test "Ξ±-Ξ³: Wyler formula" {
- const computed = wylerFormula();
-
- // Wyler's formula produces a value
- try std.testing.expect(computed > 0.0);
-}
-
-// Test: Ξ±-Ο direct formula
-test "Ξ±-Ξ³: alpha-phi direct" {
- const computed = alphaPhiDirect();
-
- // Direct Ξ±-Ο formula produces a value
- try std.testing.expect(computed > 0.0);
-}
diff --git a/src/quantum/cell.tri b/src/quantum/cell.tri
deleted file mode 100644
index bee6980090..0000000000
--- a/src/quantum/cell.tri
+++ /dev/null
@@ -1,43 +0,0 @@
-[cell]
-id = "trinity.quantum"
-name = "Quantum Simulator"
-version = "1.0.0"
-kind = "vsa_op"
-path = "src/quantum"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Quantum computing simulation with ternary state vectors"
-capabilities = ["quantum_sim", "vsa_op", "state_vector"]
-files = 12
-tests = 110
-owner = "agent:scholar"
-spec_version = 2
-api_version = "1.0.0"
-
-[tags]
-scope = "sacred"
-type = "library"
-
-[contributes]
-commands = ["simulate", "measure"]
-exports = ["collapseTime", "collapseProbability", "collapseThreshold", "collapseRate", "postCollapseEntropy"]
-tri_subcommands = []
-events = []
-binaries = ["quantum"]
-
-[dependencies]
-
-[permissions]
-level = "L2"
-filesystem = "write"
-network = "none"
-process = "spawn"
-
-ffi = "native"
-concurrency = "none"
-
-[biology]
-system = "body"
-[security]
-signed = true
-signature = "sha256:74795e74fdccb0389abb6b64944baf5be1c3193816f0171aeeecce7b7d35890a"
diff --git a/src/quantum/e8_gamma_deformation.zig b/src/quantum/e8_gamma_deformation.zig
deleted file mode 100644
index 46a55df746..0000000000
--- a/src/quantum/e8_gamma_deformation.zig
+++ /dev/null
@@ -1,500 +0,0 @@
-//! E8-Ξ³ Deformation: Ξ³ = Οβ»Β³ as E8 root system deformation parameter
-//!
-//! This module explores how the Barbero-Immirzi parameter Ξ³ = Οβ»Β³ deforms
-//! the E8 Lie Group root system to explain:
-//! - 3 fermion generations (via ΟΒ² + Οβ»Β² = 3)
-//! - Modified coupling constants
-//! - Connection to Standard Model parameters
-//!
-//! # Mathematical Foundation
-//!
-//! E8 Exceptional Group:
-//! - Dimension: 248 = 3β΅ + 5
-//! - Roots: 240 = 3β΅ - 3
-//! - Rank: 8
-//!
-//! Deformation parameter:
-//! - Ξ³ = Οβ»Β³ = (β5 - 1)Β³/8 β 0.23607
-//! - ΟΒ² + Οβ»Β² = 3 (TRINITY identity)
-//!
-//! # Hypothesis
-//!
-//! The Ξ³ deformation creates a natural 3-generation structure in E8:
-//! 1. Type I roots (112) β First generation
-//! 2. Type II roots with Ξ³ β Second generation
-//! 3. Type II roots with Ξ³Β² β Third generation
-//!
-
-const std = @import("std");
-const math = std.math;
-const mem = std.mem;
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA_PHI: f64 = 1.0 / (PHI * PHI * PHI);
-
-/// Fundamental TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY_IDENTITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// E8 dimension: 248 = 3β΅ + 5
-pub const E8_DIM: usize = 248;
-
-/// E8 roots: 240 = 3β΅ - 3
-pub const E8_ROOTS: usize = 240;
-
-/// E8 rank (dimension of Cartan subalgebra)
-pub const E8_RANK: usize = 8;
-
-/// 8-dimensional E8 root coordinates
-pub const E8Root = struct {
- /// 8 coordinates in ββΈ
- coords: [8]f64,
-
- /// Root type (I or II)
- root_type: RootType,
-
- /// Generation assignment (after Ξ³ deformation)
- generation: u2,
-};
-
-pub const RootType = enum(u1) {
- /// Type I: (Β±1, Β±1, 0, 0, 0, 0, 0, 0) with permutations
- type_i = 0,
- /// Type II: (Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½) with even parity
- type_ii = 1,
-};
-
-/// E8 Root System with Ξ³ deformation
-pub const E8System = struct {
- allocator: mem.Allocator,
- roots: std.ArrayList(E8Root),
- gamma: f64,
-
- pub fn init(allocator: mem.Allocator, gamma: f64) !E8System {
- return .{
- .allocator = allocator,
- .roots = try std.ArrayList(E8Root).initCapacity(allocator, E8_ROOTS),
- .gamma = gamma,
- };
- }
-
- pub fn deinit(self: *E8System) void {
- self.roots.deinit(self.allocator);
- }
-
- /// Generate all 240 E8 roots
- pub fn generateRoots(self: *E8System) !void {
- // Generate Type I roots: (Β±1, Β±1, 0, 0, 0, 0, 0, 0)
- try self.generateTypeIRoots();
-
- // Generate Type II roots: (Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½)
- try self.generateTypeIIRoots();
- }
-
- /// Generate Type I roots (112 total)
- fn generateTypeIRoots(self: *E8System) !void {
- const half: f64 = 1.0;
-
- // All permutations of (Β±1, Β±1, 0, 0, 0, 0, 0, 0)
- // Number of ways to choose 2 positions out of 8: C(8,2) = 28
- // For each pair: 4 combinations of signs: (Β±1, Β±1), (Β±1, β1), etc.
- // Total: 28 Γ 4 = 112
-
- const pos_pairs = [_][2]usize{
- .{ 0, 1 }, .{ 0, 2 }, .{ 0, 3 }, .{ 0, 4 }, .{ 0, 5 }, .{ 0, 6 }, .{ 0, 7 },
- .{ 1, 2 }, .{ 1, 3 }, .{ 1, 4 }, .{ 1, 5 }, .{ 1, 6 }, .{ 1, 7 }, .{ 2, 3 },
- .{ 2, 4 }, .{ 2, 5 }, .{ 2, 6 }, .{ 2, 7 }, .{ 3, 4 }, .{ 3, 5 }, .{ 3, 6 },
- .{ 3, 7 }, .{ 4, 5 }, .{ 4, 6 }, .{ 4, 7 }, .{ 5, 6 }, .{ 5, 7 }, .{ 6, 7 },
- };
-
- for (pos_pairs) |pair| {
- const i = pair[0];
- const j = pair[1];
-
- // Four sign combinations
- const signs: [4][2]f64 = .{
- .{ half, half },
- .{ half, -half },
- .{ -half, half },
- .{ -half, -half },
- };
-
- for (signs) |sign| {
- var root = E8Root{
- .coords = [_]f64{0.0} ** 8,
- .root_type = .type_i,
- .generation = 0, // Will be assigned by Ξ³ deformation
- };
-
- root.coords[i] = sign[0];
- root.coords[j] = sign[1];
-
- try self.roots.append(self.allocator, root);
- }
- }
- }
-
- /// Generate Type II roots (128 total)
- fn generateTypeIIRoots(self: *E8System) !void {
- _ = self.allocator;
- const half: f64 = 0.5;
-
- // All combinations of (Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½)
- // with even parity (even number of minus signs)
-
- var counter: usize = 0;
- while (counter < 256) : (counter += 1) {
- // counter represents 8-bit pattern
- // bit i = 1 means negative sign
-
- // Count parity (number of negative signs)
- var parity: usize = 0;
- var mask: usize = 1;
- for (0..8) |_| {
- if (counter & mask != 0) parity += 1;
- mask <<= 1;
- }
-
- // Only include even parity roots
- if (parity % 2 == 0) {
- var root = E8Root{
- .coords = [_]f64{undefined} ** 8,
- .root_type = .type_ii,
- .generation = 0,
- };
-
- mask = 1;
- for (0..8) |i| {
- if (counter & mask != 0) {
- root.coords[i] = -half;
- } else {
- root.coords[i] = half;
- }
- mask <<= 1;
- }
-
- try self.roots.append(self.allocator, root);
- }
- }
- }
-
- /// Apply Ξ³ deformation to assign generations
- /// Hypothesis: Ξ³ = Οβ»Β³ creates natural 3-generation structure
- ///
- /// E8 root coordinate sums:
- /// - Type I (112 roots): sum = |Β±1| + |Β±1| = 2
- /// - Type II (128 roots): sum = 8 Γ 0.5 = 4
- ///
- /// We use root type and a hash of coordinates to distribute
- /// Type II roots across all 3 generations using Ξ³-based thresholds
- pub fn applyGammaDeformation(self: *E8System) !void {
- const gamma = self.gamma;
-
- // Type I roots β First generation (112 roots)
- // Type II roots β Distributed across all 3 using Ξ³ hash
- for (self.roots.items) |*root| {
- if (root.root_type == .type_i) {
- // All Type I roots go to first generation
- root.generation = 0;
- } else {
- // For Type II roots, use Ξ³-weighted coordinate hash
- // to distribute across 3 generations
- var hash: f64 = 0;
- for (root.coords, 0..) |c, i| {
- // Create Ξ³-weighted hash based on position and sign
- const weight = @as(f64, @floatFromInt(i)) * gamma;
- hash += c * weight;
- }
-
- // Use absolute hash value modulo 3 to assign generation
- // This creates ~equal distribution: 128/3 β 43 roots per generation
- const gen_idx = @abs(@mod(@as(isize, @intFromFloat(hash * 1000)), 3));
- root.generation = @intCast(gen_idx);
- }
- }
- }
-
- /// Count roots per generation after Ξ³ deformation
- pub fn countGenerations(self: *const E8System) [3]usize {
- var counts = [_]usize{0} ** 3;
-
- for (self.roots.items) |root| {
- counts[root.generation] += 1;
- }
-
- return counts;
- }
-
- /// Calculate deformed root length with Ξ³ factor
- pub fn deformedNorm(self: *const E8System, root: E8Root) f64 {
- var sum: f64 = 0;
- for (root.coords, 0..) |c, i| {
- // Apply Ξ³ deformation based on position
- const gamma_factor = 1.0 + self.gamma * @as(f64, @floatFromInt(i));
- sum += c * c * gamma_factor * gamma_factor;
- }
- return @sqrt(sum);
- }
-
- /// Test if Ξ³ deformation preserves E8 structure
- pub fn verifyStructure(self: *const E8System) bool {
- // All E8 roots should have normΒ² = 2 in undeformed case
- // After Ξ³ deformation, we check if the structure is preserved
-
- var preserved_count: usize = 0;
- for (self.roots.items) |root| {
- const norm_sq = blk: {
- var sum: f64 = 0;
- for (root.coords) |c| {
- sum += c * c;
- }
- break :blk sum;
- };
-
- // Check if normΒ² β 2 (allowing for numerical error)
- if (@abs(norm_sq - 2.0) < 1e-10) {
- preserved_count += 1;
- }
- }
-
- return preserved_count == E8_ROOTS;
- }
-};
-
-/// Standard Model particle assignment via E8-Ξ³ deformation
-pub const SMParticle = struct {
- name: []const u8,
- generation: u2,
- charge: i3, // Changed from i2 to accommodate quark charge 2
- mass: f64,
- e8_root: ?E8Root,
-};
-
-/// Assign Standard Model particles to deformed E8 roots
-pub fn assignSMParticles(
- allocator: mem.Allocator,
- e8_system: *E8System,
-) !std.ArrayList(SMParticle) {
- var particles = try std.ArrayList(SMParticle).initCapacity(allocator, 12);
-
- // First generation (e, Ξ½e, u, d)
- try particles.append(allocator, .{
- .name = "electron",
- .generation = 0,
- .charge = -1,
- .mass = 0.511, // MeV
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "electron_neutrino",
- .generation = 0,
- .charge = 0,
- .mass = 0,
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "up_quark",
- .generation = 0,
- .charge = 2,
- .mass = 2.2, // MeV
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "down_quark",
- .generation = 0,
- .charge = -1,
- .mass = 4.7, // MeV
- .e8_root = null,
- });
-
- // Second generation (ΞΌ, Ξ½ΞΌ, c, s)
- try particles.append(allocator, .{
- .name = "muon",
- .generation = 1,
- .charge = -1,
- .mass = 105.66, // MeV
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "muon_neutrino",
- .generation = 1,
- .charge = 0,
- .mass = 0,
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "charm_quark",
- .generation = 1,
- .charge = 2,
- .mass = 1270, // MeV
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "strange_quark",
- .generation = 1,
- .charge = -1,
- .mass = 95, // MeV
- .e8_root = null,
- });
-
- // Third generation (Ο, Ξ½Ο, t, b)
- try particles.append(allocator, .{
- .name = "tau",
- .generation = 2,
- .charge = -1,
- .mass = 1776.86, // MeV
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "tau_neutrino",
- .generation = 2,
- .charge = 0,
- .mass = 0,
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "top_quark",
- .generation = 2,
- .charge = 2,
- .mass = 173000, // MeV
- .e8_root = null,
- });
- try particles.append(allocator, .{
- .name = "bottom_quark",
- .generation = 2,
- .charge = -1,
- .mass = 4180, // MeV
- .e8_root = null,
- });
-
- // Assign E8 roots to particles based on generation match
- var root_idx: usize = 0;
- for (particles.items) |*particle| {
- // Find matching E8 root
- for (e8_system.roots.items, 0..) |root, i| {
- if (root.generation == particle.generation) {
- particle.e8_root = root;
- root_idx = i + 1;
- break;
- }
- }
- }
-
- return particles;
-}
-
-/// Calculate coupling constant modification via Ξ³
-///
-/// Higher generations have stronger coupling (observed in nature:
-/// third generation particles have larger masses and stronger interactions).
-/// Uses Ο^n scaling to ensure g0 < g1 < g2.
-pub fn gammaCoupling(base_coupling: f64, generation: u2) f64 {
- const gamma = GAMMA_PHI;
-
- // Coupling constants increase with generation using Ξ³ as scaling factor
- // g0 = base * 1.0
- // g1 = base * (1 + Ξ³) β 1.236
- // g2 = base * (1 + 2Ξ³) β 1.472
- const scale = switch (generation) {
- 0 => 1.0,
- 1 => 1.0 + gamma,
- 2 => 1.0 + 2.0 * gamma,
- else => unreachable,
- };
-
- return base_coupling * scale;
-}
-
-/// TRINITY prediction for 3 generations
-/// Based on ΟΒ² + Οβ»Β² = 3
-pub fn predictThreeGenerations() bool {
- // The fundamental TRINITY identity
- const trinity_sum = PHI * PHI + 1.0 / (PHI * PHI);
-
- // Should be exactly 3
- return @abs(trinity_sum - 3.0) < 1e-15;
-}
-
-// Tests
-test "E8-Ξ³: fundamental constants" {
- const tol = 1e-10;
-
- // Test Ξ³ = Οβ»Β³
- const gamma_expected = 0.23606797749978969641;
- try std.testing.expectApproxEqRel(@as(f64, @floatCast(gamma_expected)), GAMMA_PHI, tol);
-
- // Test TRINITY identity
- try std.testing.expectApproxEqRel(@as(f64, 3.0), TRINITY_IDENTITY, tol);
-}
-
-test "E8-Ξ³: root generation" {
- var system = try E8System.init(std.testing.allocator, GAMMA_PHI);
- defer system.deinit();
-
- try system.generateRoots();
-
- // Should have exactly 240 roots
- try std.testing.expectEqual(E8_ROOTS, system.roots.items.len);
-
- // Verify structure preservation
- try std.testing.expect(system.verifyStructure());
-}
-
-test "E8-Ξ³: generation assignment" {
- var system = try E8System.init(std.testing.allocator, GAMMA_PHI);
- defer system.deinit();
-
- try system.generateRoots();
- try system.applyGammaDeformation();
-
- const counts = system.countGenerations();
-
- // All 240 roots should be assigned to some generation
- const total = counts[0] + counts[1] + counts[2];
- try std.testing.expectEqual(E8_ROOTS, total);
-
- // Each generation should have at least some roots
- try std.testing.expect(counts[0] > 0);
- try std.testing.expect(counts[1] > 0);
- try std.testing.expect(counts[2] > 0);
-}
-
-test "E8-Ξ³: TRINITY predicts 3 generations" {
- // The fundamental mathematical identity
- try std.testing.expect(predictThreeGenerations());
-}
-
-test "E8-Ξ³: SM particle assignment" {
- var system = try E8System.init(std.testing.allocator, GAMMA_PHI);
- defer system.deinit();
-
- try system.generateRoots();
- try system.applyGammaDeformation();
-
- var particles = try assignSMParticles(std.testing.allocator, &system);
- defer particles.deinit(std.testing.allocator);
-
- // Should have 12 fermions (3 generations Γ 4 particles each)
- try std.testing.expectEqual(@as(usize, 12), particles.items.len);
-
- // Verify each generation has 4 particles
- var gen_counts: [3]usize = .{0} ** 3;
- for (particles.items) |p| {
- gen_counts[p.generation] += 1;
- }
-
- try std.testing.expectEqual(@as(usize, 4), gen_counts[0]);
- try std.testing.expectEqual(@as(usize, 4), gen_counts[1]);
- try std.testing.expectEqual(@as(usize, 4), gen_counts[2]);
-}
-
-test "E8-Ξ³: coupling modification" {
- const g0 = gammaCoupling(0.1, 0); // No modification
- const g1 = gammaCoupling(0.1, 1); // Ξ³ modification
- const g2 = gammaCoupling(0.1, 2); // Ξ³Β² modification
-
- try std.testing.expect(g0 < g1);
- try std.testing.expect(g1 < g2);
-}
diff --git a/src/quantum/e8_integration.zig b/src/quantum/e8_integration.zig
deleted file mode 100644
index 258a89a160..0000000000
--- a/src/quantum/e8_integration.zig
+++ /dev/null
@@ -1,148 +0,0 @@
-//! E8 Integration Layer
-//!
-//! FFI bridge between Zig E8 implementation and Python modules.
-//! Provides C ABI for interoperability.
-
-const std = @import("std");
-const e8 = @import("e8_root_system.zig");
-
-//===========================================================================
-// C ABI Exports
-//===========================================================================
-
-export const e8_result_t = extern enum(c_int) {
- SUCCESS = 0,
- ERROR_INVALID_PARAM = -1,
- ERROR_ALLOC_FAILED = -2,
- ERROR_NOT_FOUND = -3,
-};
-
-export const e8_root_t = extern struct {
- components: [8]f64,
-};
-
-export const e8_system_t = opaque {};
-
-//===========================================================================
-// E8 Root System Functions
-//===========================================================================
-
-/// Create E8 root system
-export fn e8_system_create() ?*e8_system_t {
- const allocator = std.heap.c_allocator;
- const system = allocator.create(e8.E8RootSystem) catch return null;
- system.* = e8.E8RootSystem.generate(allocator) catch return null;
- return @ptrCast(system);
-}
-
-/// Destroy E8 root system
-export fn e8_system_destroy(system: ?*e8_system_t) void {
- if (system) |s| {
- const allocator = std.heap.c_allocator;
- allocator.destroy(@ptrCast(*e8.E8RootSystem, s));
- }
-}
-
-/// Get root by index
-export fn e8_system_get_root(
- system: ?*e8_system_t,
- index: c_uint,
- root: ?*e8_root_t,
-) e8_result_t {
- if (system == null or root == null) return .ERROR_INVALID_PARAM;
- if (index >= e8.E8_NUM_ROOTS) return .ERROR_INVALID_PARAM;
-
- const e8_sys = @ptrCast(*e8.E8RootSystem, system.?);
- const e8_root = e8_sys.getRoot(index);
-
- root.?.components = e8_root.components;
- return .SUCCESS;
-}
-
-/// Get number of roots
-export fn e8_system_get_num_roots() c_uint {
- return e8.E8_NUM_ROOTS;
-}
-
-/// Get dimension
-export fn e8_system_get_dim() c_uint {
- return e8.E8_DIM;
-}
-
-/// Verify root norm
-export fn e8_root_verify_norm(root: ?*const e8_root_t) e8_result_t {
- if (root == null) return .ERROR_INVALID_PARAM;
-
- const e8_root = e8.E8Root{
- .components = root.?.components,
- };
-
- if (e8_root.isValidE8Root()) {
- return .SUCCESS;
- } else {
- return .ERROR_INVALID_PARAM;
- }
-}
-
-/// Calculate root dot product
-export fn e8_root_dot(
- root1: ?*const e8_root_t,
- root2: ?*const e8_root_t,
-) f64 {
- if (root1 == null or root2 == null) return 0;
-
- const r1 = e8.E8Root{ .components = root1.?.components };
- const r2 = e8.E8Root{ .components = root2.?.components };
-
- return r1.dot(r2);
-}
-
-/// Get golden ratio constant
-export fn e8_get_golden_ratio() f64 {
- return e8.GOLDEN_RATIO;
-}
-
-/// Get 2Ο constant
-export fn e8_get_two_phi() f64 {
- return e8.TWO_PHI;
-}
-
-//===========================================================================
-// Tests
-//===========================================================================
-
-test "E8 C ABI - get golden ratio" {
- const phi = e8_get_golden_ratio();
- try std.testing.expectApproxEqAbs(f64, 1.618033988749895, phi, 1e-10);
-}
-
-test "E8 C ABI - get two phi" {
- const two_phi = e8_get_two_phi();
- try std.testing.expectApproxEqAbs(f64, 3.23606797749979, two_phi, 1e-10);
-}
-
-test "E8 C ABI - get dimensions" {
- try std.testing.expectEqual(@as(c_uint, 240), e8_system_get_num_roots());
- try std.testing.expectEqual(@as(c_uint, 248), e8_system_get_dim());
-}
-
-test "E8 C ABI - root verification" {
- var root = e8_root_t{
- .components = [_]f64{ 1, 1, 0, 0, 0, 0, 0, 0 },
- };
-
- const result = e8_root_verify_norm(&root);
- try std.testing.expectEqual(e8_result_t.SUCCESS, result);
-}
-
-test "E8 C ABI - root dot product" {
- const root1 = e8_root_t{
- .components = [_]f64{ 1, 1, 0, 0, 0, 0, 0, 0 },
- };
- const root2 = e8_root_t{
- .components = [_]f64{ 1, -1, 0, 0, 0, 0, 0, 0 },
- };
-
- const dot = e8_root_dot(&root1, &root2);
- try std.testing.expectApproxEqAbs(f64, 0.0, dot, 1e-10);
-}
diff --git a/src/quantum/e8_root_system.zig b/src/quantum/e8_root_system.zig
deleted file mode 100644
index 804d46a3ab..0000000000
--- a/src/quantum/e8_root_system.zig
+++ /dev/null
@@ -1,376 +0,0 @@
-//! E8 Root System Implementation for TRINITY v9.0 QUANTUM
-//!
-//! Mathematical foundation:
-//! - E8 is the largest exceptional Lie group
-//! - dim(E8) = 248 = rank + |roots| = 8 + 240
-//! - |roots| = 240 = 3^5 - 3 (TRINITY pattern)
-//! - Root norm: βΞ±βΒ² = 2Ο where Ο = (1 + β5)/2 β 1.618
-//!
-//! This implementation provides:
-//! - All 240 E8 roots with exact normΒ² = 2Ο
-//! - Weyl group reflections
-//! - Cartan matrix computation
-//! - Simple roots basis
-
-const std = @import("std");
-const math = std.math;
-
-//===========================================================================
-// Constants
-//===========================================================================
-
-pub const GOLDEN_RATIO: f64 = 1.618033988749895;
-pub const TWO_PHI: f64 = 2.0 * GOLDEN_RATIO; // β 3.23607
-pub const E8_DIM: usize = 248;
-pub const E8_RANK: usize = 8;
-pub const E8_NUM_ROOTS: usize = 240;
-pub const E8_ROOT_NORM_SQ: f64 = 2.0; // Standard E8 root norm squared
-
-//===========================================================================
-// Types
-//===========================================================================
-
-/// 8-dimensional root vector in E8 lattice
-pub const E8Root = struct {
- components: [E8_RANK]f64,
-
- /// Create new root from components
- pub fn init(components: [E8_RANK]f64) E8Root {
- return .{ .components = components };
- }
-
- /// Calculate squared norm βrootβΒ²
- pub fn normSquared(self: E8Root) f64 {
- var sum: f64 = 0;
- for (self.components) |c| {
- sum += c * c;
- }
- return sum;
- }
-
- /// Verify root has correct E8 norm (βΞ±βΒ² = 2)
- pub fn isValidE8Root(self: E8Root) bool {
- const ns = self.normSquared();
- return math.approxEqAbs(f64, ns, E8_ROOT_NORM_SQ, 1e-10);
- }
-
- /// Dot product with another root
- pub fn dot(self: E8Root, other: E8Root) f64 {
- var sum: f64 = 0;
- for (self.components, 0..) |a, i| {
- sum += a * other.components[i];
- }
- return sum;
- }
-
- /// Add two roots
- pub fn add(self: E8Root, other: E8Root) E8Root {
- var result: [E8_RANK]f64 = undefined;
- for (&result, 0..) |*r, i| {
- r.* = self.components[i] + other.components[i];
- }
- return E8Root{ .components = result };
- }
-
- /// Subtract two roots
- pub fn sub(self: E8Root, other: E8Root) E8Root {
- var result: [E8_RANK]f64 = undefined;
- for (&result, 0..) |*r, i| {
- r.* = self.components[i] - other.components[i];
- }
- return E8Root{ .components = result };
- }
-
- /// Scale by scalar
- pub fn scale(self: E8Root, s: f64) E8Root {
- var result: [E8_RANK]f64 = undefined;
- for (&result, 0..) |*r, i| {
- r.* = self.components[i] * s;
- }
- return E8Root{ .components = result };
- }
-
- /// Format root for display
- pub fn format(self: E8Root, allocator: std.mem.Allocator) ![]u8 {
- const components = self.components;
- return std.fmt.allocPrint(allocator, "[{d:.4},{d:.4},{d:.4},{d:.4},{d:.4},{d:.4},{d:.4},{d:.4}]", .{
- components[0], components[1], components[2], components[3],
- components[4], components[5], components[6], components[7],
- });
- }
-};
-
-/// Complete E8 root system (240 roots)
-pub const E8RootSystem = struct {
- roots: [E8_NUM_ROOTS]E8Root,
- simple_roots: [E8_RANK]E8Root,
- cartan_matrix: [E8_RANK][E8_RANK]i32,
-
- /// Generate complete E8 root system
- /// Uses the construction from 8D coordinate representation
- pub fn generate(allocator: std.mem.Allocator) !E8RootSystem {
- var system = E8RootSystem{
- .roots = undefined,
- .simple_roots = undefined,
- .cartan_matrix = undefined,
- };
-
- // Generate all 240 roots
- try system.generateRoots();
-
- // Extract 8 simple roots
- system.generateSimpleRoots();
-
- // Compute Cartan matrix
- system.computeCartanMatrix();
-
- // Verify all roots have correct norm
- system.verify(allocator) catch |err| {
- std.log.warn("e8_root_system: verification failed: {}", .{err});
- };
-
- return system;
- }
-
- /// Generate all 240 E8 roots
- /// Construction:
- /// 1. 112 roots: (Β±1, Β±1, 0, 0, 0, 0, 0, 0) with even permutations
- /// 2. 128 roots: (Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½) with odd number of - signs
- fn generateRoots(self: *E8RootSystem) !void {
- var root_idx: usize = 0;
-
- // Type 1: 112 roots from permutations of (Β±1, Β±1, 0, 0, 0, 0, 0, 0)
- // Each non-zero pair can be in any of 28 positions
- inline for (0..8) |i| {
- inline for (i + 1..8) |j| {
- // (1, 1, 0, 0, 0, 0, 0, 0) and permutations
- self.roots[root_idx] = makeRootTwoOnes(i, j);
- root_idx += 1;
- // (1, -1, 0, 0, 0, 0, 0, 0) and permutations
- self.roots[root_idx] = makeRootOneOne(i, j);
- root_idx += 1;
- // (-1, 1, 0, 0, 0, 0, 0, 0) and permutations
- self.roots[root_idx] = makeRootMinusOneOne(i, j);
- root_idx += 1;
- // (-1, -1, 0, 0, 0, 0, 0, 0) and permutations
- self.roots[root_idx] = makeRootTwoMinusOnes(i, j);
- root_idx += 1;
- }
- }
-
- // Type 2: 128 roots from (Β±Β½, ..., Β±Β½)
- // with an odd number of minus signs
- var pattern: u16 = 0;
- while (pattern < 256) : (pattern += 1) {
- // Count minus signs (bits set to 1)
- const minus_count = @popCount(pattern);
- // Only odd number of minus signs
- if (minus_count % 2 == 1) {
- if (root_idx < E8_NUM_ROOTS) {
- self.roots[root_idx] = makeRootHalfPattern(pattern);
- root_idx += 1;
- }
- }
- }
- }
-
- /// Generate 8 simple roots (Dynkin diagram basis)
- fn generateSimpleRoots(self: *E8RootSystem) void {
- // Standard simple roots for E8
- self.simple_roots[0] = E8Root.init(.{ 1, -1, 0, 0, 0, 0, 0, 0 });
- self.simple_roots[1] = E8Root.init(.{ 0, 1, -1, 0, 0, 0, 0, 0 });
- self.simple_roots[2] = E8Root.init(.{ 0, 0, 1, -1, 0, 0, 0, 0 });
- self.simple_roots[3] = E8Root.init(.{ 0, 0, 0, 1, -1, 0, 0, 0 });
- self.simple_roots[4] = E8Root.init(.{ 0, 0, 0, 0, 1, -1, 0, 0 });
- self.simple_roots[5] = E8Root.init(.{ 0, 0, 0, 0, 0, 1, -1, 0 });
- self.simple_roots[6] = E8Root.init(.{ 0, 0, 0, 0, 0, 0, 1, -1 });
- self.simple_roots[7] = E8Root.init(.{ -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5 });
- }
-
- /// Compute Cartan matrix A_ij = 2(Ξ±_iΒ·Ξ±_j)/(Ξ±_jΒ·Ξ±_j)
- fn computeCartanMatrix(self: *E8RootSystem) void {
- for (0..E8_RANK) |i| {
- for (0..E8_RANK) |j| {
- const alpha_i = self.simple_roots[i];
- const alpha_j = self.simple_roots[j];
- const dot_ij = alpha_i.dot(alpha_j);
- const norm_j = alpha_j.normSquared();
-
- // For simply-laced groups, all norms are equal
- // So A_ij = 2 * (Ξ±_iΒ·Ξ±_j) / βΞ±βΒ²
- const cartan_entry: f64 = 2.0 * dot_ij / norm_j;
-
- // Round to nearest integer (Cartan matrix is integer)
- self.cartan_matrix[i][j] = @intFromFloat(@round(cartan_entry));
- }
- }
- }
-
- /// Weyl group reflection: v' = v - 2(vΒ·Ξ±)/(Ξ±Β·Ξ±) Ξ±
- pub fn weylReflection(_: *const E8RootSystem, root: E8Root, target: E8Root) E8Root {
- const dot_va = target.dot(root);
- const dot_aa = root.normSquared();
- const coeff = 2.0 * dot_va / dot_aa;
- return target.sub(root.scale(coeff));
- }
-
- /// Verify all E8 properties
- pub fn verify(self: *const E8RootSystem, allocator: std.mem.Allocator) !void {
- // Check we have exactly 240 roots
- std.debug.assert(E8_NUM_ROOTS == 240);
-
- // Check dim(E8) = rank + roots = 8 + 240 = 248
- comptime {
- std.debug.assert(E8_DIM == E8_RANK + E8_NUM_ROOTS);
- }
-
- // Check |roots| = 3^5 - 3 = 240 (TRINITY pattern)
- comptime {
- std.debug.assert(E8_NUM_ROOTS == 243 - 3);
- }
-
- // Verify all roots have same norm (simply-laced)
- var valid_count: usize = 0;
- for (self.roots) |root| {
- if (root.isValidE8Root()) {
- valid_count += 1;
- }
- }
-
- if (valid_count != E8_NUM_ROOTS) {
- return error.InvalidRootNorm;
- }
-
- _ = allocator;
- }
-
- /// Get root by index
- pub fn getRoot(self: *const E8RootSystem, index: usize) E8Root {
- std.debug.assert(index < E8_NUM_ROOTS);
- return self.roots[index];
- }
-
- /// Get Cartan matrix entry
- pub fn getCartanEntry(self: *const E8RootSystem, i: usize, j: usize) i32 {
- std.debug.assert(i < E8_RANK and j < E8_RANK);
- return self.cartan_matrix[i][j];
- }
-};
-
-//===========================================================================
-// Helper Functions for Root Construction
-//===========================================================================
-
-/// Create root: (1, 1, 0, 0, 0, 0, 0, 0) at positions i, j
-fn makeRootTwoOnes(i: usize, j: usize) E8Root {
- var root: [E8_RANK]f64 = [_]f64{0} ** E8_RANK;
- root[i] = 1.0;
- root[j] = 1.0;
- return E8Root{ .components = root };
-}
-
-/// Create root: (1, -1, 0, 0, 0, 0, 0, 0) at positions i, j
-fn makeRootOneOne(i: usize, j: usize) E8Root {
- var root: [E8_RANK]f64 = [_]f64{0} ** E8_RANK;
- root[i] = 1.0;
- root[j] = -1.0;
- return E8Root{ .components = root };
-}
-
-/// Create root: (-1, 1, 0, 0, 0, 0, 0, 0) at positions i, j
-fn makeRootMinusOneOne(i: usize, j: usize) E8Root {
- var root: [E8_RANK]f64 = [_]f64{0} ** E8_RANK;
- root[i] = -1.0;
- root[j] = 1.0;
- return E8Root{ .components = root };
-}
-
-/// Create root: (-1, -1, 0, 0, 0, 0, 0, 0) at positions i, j
-fn makeRootTwoMinusOnes(i: usize, j: usize) E8Root {
- var root: [E8_RANK]f64 = [_]f64{0} ** E8_RANK;
- root[i] = -1.0;
- root[j] = -1.0;
- return E8Root{ .components = root };
-}
-
-/// Create root from 8-bit pattern (Β±Β½, ..., Β±Β½) with odd minus signs
-fn makeRootHalfPattern(pattern: u16) E8Root {
- var root: [E8_RANK]f64 = undefined;
- for (&root, 0..) |*r, i| {
- const bit = @as(u16, 1) << @as(u4, @intCast(i));
- const is_minus = (pattern & bit) != 0;
- r.* = if (is_minus) -0.5 else 0.5;
- }
- return E8Root{ .components = root };
-}
-
-//===========================================================================
-// Tests
-//===========================================================================
-
-test "E8 golden ratio constant" {
- const phi_sq: f64 = GOLDEN_RATIO * GOLDEN_RATIO;
- const one_over_phi_sq: f64 = 1.0 / phi_sq;
- // TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
- const actual = phi_sq + one_over_phi_sq;
- try std.testing.expectApproxEqAbs(3.0, actual, 1e-10);
-}
-
-test "E8 root norm equals 2 (standard E8)" {
- const root = E8Root.init(.{ 1, 1, 0, 0, 0, 0, 0, 0 });
- const norm_sq = root.normSquared();
- try std.testing.expectApproxEqAbs(E8_ROOT_NORM_SQ, norm_sq, 1e-10);
-}
-
-test "E8 root validity check" {
- const valid_root = E8Root.init(.{ 1, -1, 0, 0, 0, 0, 0, 0 });
- try std.testing.expect(valid_root.isValidE8Root());
-}
-
-test "E8 root dot product" {
- const root1 = E8Root.init(.{ 1, 1, 0, 0, 0, 0, 0, 0 });
- const root2 = E8Root.init(.{ 1, -1, 0, 0, 0, 0, 0, 0 });
- const dot = root1.dot(root2);
- try std.testing.expectApproxEqAbs(0.0, dot, 1e-10);
-}
-
-test "E8 dimensions" {
- comptime {
- try std.testing.expectEqual(@as(usize, 248), E8_DIM);
- try std.testing.expectEqual(@as(usize, 8), E8_RANK);
- try std.testing.expectEqual(@as(usize, 240), E8_NUM_ROOTS);
- }
-}
-
-test "E8 root count = 3^5 - 3 (TRINITY pattern)" {
- comptime {
- const trinity_pattern = 243 - 3;
- try std.testing.expectEqual(trinity_pattern, E8_NUM_ROOTS);
- }
-}
-
-test "Generate E8 root system" {
- const allocator = std.testing.allocator;
- const system = try E8RootSystem.generate(allocator);
- _ = system;
-
- // System should be valid (no error from verify)
- try std.testing.expect(true);
-}
-
-test "Weyl group reflection" {
- const root = E8Root.init(.{ 1, 0, 0, 0, 0, 0, 0, 0 });
- const target = E8Root.init(.{ 0, 1, 0, 0, 0, 0, 0, 0 });
-
- var system = E8RootSystem{
- .roots = undefined,
- .simple_roots = undefined,
- .cartan_matrix = undefined,
- };
-
- const reflected = system.weylReflection(root, target);
- // For orthogonal vectors (dot=0), reflection leaves target unchanged
- const expected = E8Root.init(.{ 0, 1, 0, 0, 0, 0, 0, 0 });
-
- try std.testing.expectApproxEqAbs(expected.components[1], reflected.components[1], 1e-10);
-}
diff --git a/src/quantum/golden_gates.zig b/src/quantum/golden_gates.zig
deleted file mode 100644
index 8802856f64..0000000000
--- a/src/quantum/golden_gates.zig
+++ /dev/null
@@ -1,333 +0,0 @@
-//! Golden Gates for Qutrit Quantum Simulation
-//!
-//! Based on TRINITY v8.0 ETERNAL framework:
-//! - ΟΒ² + 1/ΟΒ² = 3 (core identity)
-//! - Qutrits: {-1, 0, +1} (balanced ternary)
-//! - Golden angle: 137.507764Β° (related to Ο)
-//!
-//! Mathematical foundation:
-//! The golden angle ΞΈ = 360Β°/ΟΒ² = 137.507764Β°
-//! This angle appears in phyllotaxis (sunflower seeds) and
-//! provides optimal coverage of the unit circle.
-//!
-//! Reference: TRINITY v8.0 ETERNAL - E8 Root Embedding
-
-const std = @import("std");
-const math = std.math;
-
-//===========================================================================
-// Constants
-//===========================================================================
-
-pub const GOLDEN_RATIO: f64 = 1.618033988749895; // Ο
-pub const GOLDEN_ANGLE_DEG: f64 = 137.5077644087447; // 360Β°/ΟΒ²
-pub const GOLDEN_ANGLE_RAD: f64 = GOLDEN_ANGLE_DEG * math.pi / 180.0;
-
-/// TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-pub fn trinityIdentity() bool {
- const phi = GOLDEN_RATIO;
- const lhs = phi * phi + 1.0 / (phi * phi);
- return math.approxEqAbs(f64, lhs, 3.0, 1e-10);
-}
-
-//===========================================================================
-// Qutrit Definition
-//===========================================================================
-
-/// Balanced ternary qutrit: {-1, 0, +1}
-pub const Qutrit = enum(i2) {
- neg = -1,
- zero = 0,
- pos = 1,
-
- pub fn fromInt(value: i3) !Qutrit {
- return switch (value) {
- -1 => .neg,
- 0 => .zero,
- 1 => .pos,
- else => error.InvalidQutritValue,
- };
- }
-
- pub fn toFloat(self: Qutrit) f64 {
- return @floatFromInt(@intFromEnum(self));
- }
-
- pub fn format(self: Qutrit, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
- _ = fmt;
- _ = options;
- const symbol = switch (self) {
- .neg => "βΌ",
- .zero => "β",
- .pos => "β²",
- };
- try writer.writeAll(symbol);
- }
-};
-
-//===========================================================================
-// Qutrit State (3-level quantum system)
-//===========================================================================
-
-/// Quantum state of a single qutrit: Ξ±|-1β© + Ξ²|0β© + Ξ³|+1β©
-pub const QutritState = struct {
- amplitudes: [3]complex.Complex(f64),
-
- pub fn init(alpha: complex.Complex(f64), beta: complex.Complex(f64), gamma: complex.Complex(f64)) QutritState {
- return .{ .amplitudes = .{ alpha, beta, gamma } };
- }
-
- /// Create computational basis state |tritβ©
- pub fn basis(trit: Qutrit) QutritState {
- var result = QutritState{
- .amplitudes = .{
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- },
- };
- switch (trit) {
- .neg => result.amplitudes[2].re = 1,
- .zero => result.amplitudes[1].re = 1,
- .pos => result.amplitudes[0].re = 1,
- }
- return result;
- }
-
- /// Create equal superposition state
- pub fn superposition() QutritState {
- const inv_sqrt3 = 1.0 / math.sqrt(3.0);
- return .{
- .amplitudes = .{
- .{ .re = inv_sqrt3, .im = 0 },
- .{ .re = inv_sqrt3, .im = 0 },
- .{ .re = inv_sqrt3, .im = 0 },
- },
- };
- }
-
- /// Calculate measurement probability for each basis state
- pub fn probabilities(self: QutritState) [3]f64 {
- var result: [3]f64 = undefined;
- for (&self.amplitudes, 0..) |amp, i| {
- result[i] = amp.re * amp.re + amp.im * amp.im;
- }
- return result;
- }
-
- /// Normalize the state
- pub fn normalize(self: *QutritState) void {
- var norm: f64 = 0;
- for (self.amplitudes) |amp| {
- norm += amp.re * amp.re + amp.im * amp.im;
- }
- norm = math.sqrt(norm);
- for (&self.amplitudes) |*amp| {
- amp.re /= norm;
- amp.im /= norm;
- }
- }
-};
-
-//===========================================================================
-// Golden Gate Matrices
-//===========================================================================
-
-/// Golden rotation gate: rotation by golden angle in SU(3)
-/// Preserves sacred phase relationships from TRINITY framework
-pub const GoldenGate = struct {
- matrix: [3][3]complex.Complex(f64),
-
- pub fn init(angle_rad: f64) GoldenGate {
- _ = angle_rad; // Future: use for parametrized rotation
- // Use Qutrit Fourier Transform matrix (unitary)
- // F[j,k] = Ο^(jk) / sqrt(3) where Ο = exp(2Οi/3)
- // This is the "TRINITY gate" - the quantum Fourier transform for qutrits
- const omega_re = -0.5; // cos(2Ο/3)
- const omega_im = math.sqrt(3.0) / 2.0; // sin(2Ο/3)
- const inv_sqrt3 = 1.0 / math.sqrt(3.0);
-
- return .{
- .matrix = .{
- .{
- .{ .re = inv_sqrt3, .im = 0 },
- .{ .re = inv_sqrt3, .im = 0 },
- .{ .re = inv_sqrt3, .im = 0 },
- },
- .{
- .{ .re = inv_sqrt3, .im = 0 },
- .{ .re = omega_re * inv_sqrt3, .im = omega_im * inv_sqrt3 },
- .{ .re = omega_re * inv_sqrt3, .im = -omega_im * inv_sqrt3 },
- },
- .{
- .{ .re = inv_sqrt3, .im = 0 },
- .{ .re = omega_re * inv_sqrt3, .im = -omega_im * inv_sqrt3 },
- .{ .re = omega_re * inv_sqrt3, .im = omega_im * inv_sqrt3 },
- },
- },
- };
- }
-
- /// Apply gate to qutrit state
- pub fn apply(self: GoldenGate, state: QutritState) QutritState {
- var result: QutritState = undefined;
- for (0..3) |i| {
- var sum: complex.Complex(f64) = .{ .re = 0, .im = 0 };
- for (0..3) |j| {
- const prod = complex.mul(
- self.matrix[i][j],
- state.amplitudes[j],
- );
- sum.re += prod.re;
- sum.im += prod.im;
- }
- result.amplitudes[i] = sum;
- }
- return result;
- }
-};
-
-/// TRINITY phase gate: applies phase based on ΟΒ² + 1/ΟΒ² = 3
-pub const TrinityPhaseGate = struct {
- /// Phase = exp(2Οi/3) for each trit level
- /// This is the cube root of unity, related to TRINITY
- const OMEGA: complex.Complex(f64) = .{
- .re = -0.5,
- .im = math.sqrt(3.0) / 2.0,
- };
-
- pub fn apply(state: QutritState) QutritState {
- return .{
- .amplitudes = .{
- state.amplitudes[0], // |+1β©: phase 1
- complex.mul(OMEGA, state.amplitudes[1]), // |0β©: phase Ο
- complex.mul(OMEGA, complex.mul(OMEGA, state.amplitudes[2])), // |-1β©: phase ΟΒ²
- },
- };
- }
-};
-
-//===========================================================================
-// CGLMP Inequality (Bell Test for Qutrits)
-//===========================================================================
-
-/// Calculate CGLMP I3 parameter for Bell inequality violation
-/// Reference: Collins-Gisin-Linden-Massar-Popescu (2002)
-/// Classical bound: I3 β€ 2
-/// Quantum maximum: I3 β 2.872
-/// TRINITY v8.0 prediction: I3 = 2.4277 (violates classical)
-pub fn cglmpI3(theta_a: f64, theta_b: f64, theta_a_prime: f64, theta_b_prime: f64) f64 {
- // Simplified calculation for qutrit Bell test
- // Uses golden ratio angles for optimal violation
- _ = GOLDEN_RATIO; // Reference for future use
-
- // TRINITY-optimized measurement angles
- const alpha = theta_a;
- const alpha_prime = theta_a_prime;
- const beta = theta_b;
- const beta_prime = theta_b_prime;
-
- // Joint probabilities for qutrit measurements
- // Using analytic formula from CGLMP paper
- const p00 = probabilityCGLMP(alpha, beta, 0);
- const p01 = probabilityCGLMP(alpha, beta_prime, 1);
- const p10 = probabilityCGLMP(alpha_prime, beta, 0);
- const p11 = probabilityCGLMP(alpha_prime, beta_prime, 1);
-
- // CGLMP I3 expression
- return 3 * (p00 + p01 + p10 + p11) - 4;
-}
-
-fn probabilityCGLMP(theta1: f64, theta2: f64, k: i32) f64 {
- // Simplified probability for CGLMP test
- // Full calculation requires 3x3 joint probability matrix
- _ = k;
- const diff = theta1 - theta2;
- return 1.0 / 3.0 + (2.0 / (9.0 * math.pi)) * math.cos(3.0 * diff);
-}
-
-/// TRINITY-predicted CGLMP violation
-pub fn trinityViolation() f64 {
- // Using golden angle separation
- const golden_angle = GOLDEN_ANGLE_RAD;
- return cglmpI3(0, golden_angle / 2.0, math.pi / 4.0, 3.0 * golden_angle / 4.0);
-}
-
-//===========================================================================
-// Tests
-//===========================================================================
-
-test "TRINITY identity holds" {
- try std.testing.expect(trinityIdentity());
-}
-
-test "Qutrit basis states" {
- const pos_basis = QutritState.basis(.pos);
- const probs = pos_basis.probabilities();
- try std.testing.expectApproxEqAbs(1.0, probs[0], 1e-10);
- try std.testing.expectApproxEqAbs(0.0, probs[1], 1e-10);
- try std.testing.expectApproxEqAbs(0.0, probs[2], 1e-10);
-}
-
-test "Golden gate preserves normalization" {
- const gate = GoldenGate.init(GOLDEN_ANGLE_RAD);
- var state = QutritState.superposition();
- state = gate.apply(state);
-
- const probs = state.probabilities();
- var sum: f64 = 0;
- for (probs) |p| sum += p;
- try std.testing.expectApproxEqAbs(1.0, sum, 1e-10);
-}
-
-test "TRINITY phase gate applies cube roots of unity" {
- const state = QutritState.superposition();
- const transformed = TrinityPhaseGate.apply(state);
-
- // Check phase ratios
- const phase1 = complex.div(transformed.amplitudes[1], state.amplitudes[0]);
- _ = complex.div(transformed.amplitudes[2], state.amplitudes[0]); // For future phase2 check
-
- try std.testing.expectApproxEqAbs(-0.5, phase1.re, 1e-10);
- try std.testing.expectApproxEqAbs(math.sqrt(3.0) / 2.0, phase1.im, 1e-10);
-}
-
-test "CGLMP calculation runs without error" {
- // Note: Simplified formula may not produce accurate violation values
- // Full CGLMP test requires complete joint probability calculation
- const violation = trinityViolation();
-
- // Just verify the calculation completes
- _ = violation;
-
- // For accurate violation, need full numerical integration
- // Reference: Collins et al., PRL 88, 040404 (2002)
-}
-
-//===========================================================================
-// Complex Number Utilities
-//===========================================================================
-
-const complex = struct {
- pub fn mul(a: Complex(f64), b: Complex(f64)) Complex(f64) {
- return .{
- .re = a.re * b.re - a.im * b.im,
- .im = a.re * b.im + a.im * b.re,
- };
- }
-
- pub fn div(a: Complex(f64), b: Complex(f64)) Complex(f64) {
- const denom = b.re * b.re + b.im * b.im;
- return .{
- .re = (a.re * b.re + a.im * b.im) / denom,
- .im = (a.im * b.re - a.re * b.im) / denom,
- };
- }
-
- pub fn Complex(comptime T: type) type {
- return struct {
- re: T,
- im: T,
- };
- }
-};
diff --git a/src/quantum/main.zig b/src/quantum/main.zig
deleted file mode 100644
index aa25060bfb..0000000000
--- a/src/quantum/main.zig
+++ /dev/null
@@ -1,611 +0,0 @@
-// TERNARY QUANTUM VM β CLI Runner
-// Usage: quantum chsh [--trials N] [--sacred] [--entangled]
-// quantum cglmp [--trials N]
-// quantum demo
-// quantum bench
-// quantum weights [--entangled]
-//
-// phi^2 + 1/phi^2 = 3 = TRINITY
-
-const std = @import("std");
-const qvm = @import("ternary_qvm.zig");
-const print = std.debug.print;
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- const args = try std.process.argsAlloc(allocator);
- defer std.process.argsFree(allocator, args);
-
- const cmd = if (args.len > 1) args[1] else "demo";
-
- if (std.mem.eql(u8, cmd, "chsh")) {
- run_chsh(args);
- } else if (std.mem.eql(u8, cmd, "cglmp")) {
- run_cglmp(args);
- } else if (std.mem.eql(u8, cmd, "demo")) {
- run_demo();
- } else if (std.mem.eql(u8, cmd, "bench")) {
- run_bench();
- } else if (std.mem.eql(u8, cmd, "weights")) {
- run_weight_gen(args);
- } else {
- print(
- \\TERNARY QUANTUM VM β Trinity
- \\
- \\Commands:
- \\ chsh Run CHSH-like correlation test on qutrits
- \\ cglmp Run CGLMP inequality test with entangled pairs
- \\ demo Demonstrate qutrit gates and measurement
- \\ bench Benchmark gate operations
- \\ weights Generate quantum-derived weights for FPGA dot product
- \\
- \\Options:
- \\ --trials N Number of trials (default: 10000)
- \\ --sacred Use sacred golden angle phase
- \\ --entangled Use entangled qutrit pairs
- \\
- \\phi^2 + 1/phi^2 = 3 = TRINITY
- \\
- , .{});
- }
-}
-
-fn run_chsh(args: []const []const u8) void {
- var trials: u32 = 10000;
- var sacred = false;
- var entangled = false;
-
- var i: usize = 2;
- while (i < args.len) : (i += 1) {
- if (std.mem.eql(u8, args[i], "--trials") and i + 1 < args.len) {
- trials = std.fmt.parseInt(u32, args[i + 1], 10) catch 10000;
- i += 1;
- } else if (std.mem.eql(u8, args[i], "--sacred")) {
- sacred = true;
- } else if (std.mem.eql(u8, args[i], "--entangled")) {
- entangled = true;
- }
- }
-
- // If --entangled, redirect to CGLMP test
- if (entangled) {
- run_cglmp(args);
- return;
- }
-
- print(
- \\
- \\ =============================================
- \\ | CHSH CORRELATION TEST ON QUTRITS |
- \\ | phi^2 + 1/phi^2 = 3 = TRINITY |
- \\ =============================================
- \\
- \\ Trials: {d}
- \\ Sacred: {s}
- \\
- \\
- , .{ trials, if (sacred) "YES (golden angle phase)" else "standard" });
-
- const result = qvm.run_chsh_test(std.heap.page_allocator, trials) catch {
- print(" ERROR: CHSH test failed\n", .{});
- return;
- };
-
- print(
- \\ Results:
- \\ Correlation: {d:.6}
- \\ Classical bound: {d:.6}
- \\ Violation: {s}
- \\ Trials: {d}
- \\
- , .{
- result.correlation,
- result.classical_bound,
- if (result.violation) "YES β quantum advantage detected" else "NO β within classical bound",
- result.trials,
- });
-
- // Extended analysis
- print(
- \\
- \\ Extended Analysis:
- \\
- , .{});
-
- var prng = std.Random.DefaultPrng.init(137);
-
- var agree_h: u32 = 0;
- for (0..trials) |_| {
- var q1 = qvm.Qutrit.ZERO_STATE;
- var q2 = qvm.Qutrit.ZERO_STATE;
- q1 = qvm.Gate3.hadamard3().apply(q1);
- q2 = qvm.Gate3.hadamard3().apply(q2);
- const m1 = q1.measure(prng.random());
- const m2 = q2.measure(prng.random());
- if (m1 == m2) agree_h += 1;
- }
-
- var agree_sp: u32 = 0;
- for (0..trials) |_| {
- var q1 = qvm.Qutrit.ZERO_STATE;
- var q2 = qvm.Qutrit.ZERO_STATE;
- q1 = qvm.Gate3.hadamard3().apply(q1);
- q2 = qvm.Gate3.hadamard3().apply(q2);
- q2 = qvm.Gate3.sacred_phase().apply(q2);
- const m1 = q1.measure(prng.random());
- const m2 = q2.measure(prng.random());
- if (m1 == m2) agree_sp += 1;
- }
-
- var agree_x: u32 = 0;
- for (0..trials) |_| {
- var q1 = qvm.Qutrit.ZERO_STATE;
- var q2 = qvm.Qutrit.ZERO_STATE;
- q1 = qvm.Gate3.hadamard3().apply(q1);
- q2 = qvm.Gate3.hadamard3().apply(q2);
- q2 = qvm.Gate3.X3.apply(q2);
- const m1 = q1.measure(prng.random());
- const m2 = q2.measure(prng.random());
- if (m1 == m2) agree_x += 1;
- }
-
- const corr_h = @as(f64, @floatFromInt(agree_h)) / @as(f64, @floatFromInt(trials));
- const corr_sp = @as(f64, @floatFromInt(agree_sp)) / @as(f64, @floatFromInt(trials));
- const corr_x = @as(f64, @floatFromInt(agree_x)) / @as(f64, @floatFromInt(trials));
-
- print(
- \\ H|0> vs H|0>: {d:.6} (expect ~0.333)
- \\ H|0> vs SP(H|0>): {d:.6} (sacred phase shift)
- \\ H|0> vs X(H|0>): {d:.6} (cyclic shift)
- \\
- \\ Interpretation:
- \\ Classical random: 0.333333
- \\ Sacred phase deviation: {d:.6}
- \\
- , .{ corr_h, corr_sp, corr_x, @abs(corr_sp - 1.0 / 3.0) });
-
- // Quantum trit signature
- print(" Quantum-Derived Trit Signature: ", .{});
- var vm = qvm.TernaryQVM.init(8, 42);
- for (0..8) |qi| {
- vm.hadamard(@intCast(qi));
- if (sacred) vm.sacred_phase(@intCast(qi));
- const trit = vm.measure_qutrit(@intCast(qi));
- const sym: u8 = if (trit < 0) '-' else if (trit == 0) '0' else '+';
- print("{c}", .{sym});
- }
-
- print(
- \\
- \\
- \\ =============================================
- \\ CHSH TEST COMPLETE
- \\ phi^2 + 1/phi^2 = 3 = TRINITY
- \\ =============================================
- \\
- , .{});
-}
-
-fn run_cglmp(args: []const []const u8) void {
- _ = args;
-
- print(
- \\
- \\ ==========================================================
- \\ | CGLMP INEQUALITY TEST β ENTANGLED QUTRITS (d=3) |
- \\ | Collins-Gisin-Linden-Massar-Popescu 2002 |
- \\ | Measurement: R01(theta) Givens rotation gates |
- \\ | phi^2 + 1/phi^2 = 3 = TRINITY |
- \\ ==========================================================
- \\
- \\ Method: Analytical Born rule (exact probabilities)
- \\ Search: 2-phase grid optimization (coarse + refined)
- \\
- \\
- , .{});
-
- // Test 1: Entangled pair (should violate)
- print(" 1. ENTANGLED non-maximally entangled pair:\n", .{});
- const ent = qvm.run_cglmp_test(0, true);
- print(
- \\ I3 value: {d:.6}
- \\ Classical bound: {d:.6}
- \\ Quantum max: {d:.6}
- \\ VIOLATION: {s}
- \\ Corr (same): {d:.6}
- \\ Corr (diff): {d:.6}
- \\
- , .{
- ent.i3_value,
- ent.classical_bound,
- ent.quantum_max,
- if (ent.violation) "YES β QUANTUM ADVANTAGE DETECTED" else "NO",
- ent.correlation_same_basis,
- ent.correlation_diff_basis,
- });
-
- // Test 2: Separable pair (should NOT violate)
- print("\n 2. SEPARABLE product state H|0> x H|0>:\n", .{});
- const sep = qvm.run_cglmp_test(0, false);
- print(
- \\ I3 value: {d:.6}
- \\ Classical bound: {d:.6}
- \\ VIOLATION: {s}
- \\ Corr (same): {d:.6}
- \\ Corr (diff): {d:.6}
- \\
- , .{
- sep.i3_value,
- sep.classical_bound,
- if (sep.violation) "YES (unexpected!)" else "NO β as expected",
- sep.correlation_same_basis,
- sep.correlation_diff_basis,
- });
-
- // Entanglement-derived trit signature
- print("\n 3. Entanglement-Derived Trit Signature:\n ", .{});
- var prng = std.Random.DefaultPrng.init(137);
- for (0..16) |_| {
- var pair = qvm.EntangledPair.BELL;
- // Apply sacred phase to qutrit A
- pair = pair.apply_gate_a(qvm.Gate3.sacred_phase());
- const trit = pair.measure_a(prng.random());
- const sym: u8 = if (trit < 0) '-' else if (trit == 0) '0' else '+';
- print("{c}", .{sym});
- }
-
- const violation_pct = (ent.i3_value - 2.0) / 2.0 * 100.0;
- print(
- \\
- \\
- \\ ==========================================================
- \\ RESULTS SUMMARY
- \\ ==========================================================
- \\ Entangled I3: {d:.6} {s} classical bound 2.0
- \\ Separable I3: {d:.6} {s} classical bound 2.0
- \\ Quantum gap: {d:.6}
- \\ Violation: {d:.1}% above classical bound
- \\ Quantum max: 2.9149 (theoretical for d=3)
- \\
- \\ VERDICT: {s}
- \\ ==========================================================
- \\ phi^2 + 1/phi^2 = 3 = TRINITY
- \\ ==========================================================
- \\
- , .{
- ent.i3_value,
- if (ent.i3_value > 2.0 + 1e-6) ">" else "<=",
- sep.i3_value,
- if (sep.i3_value > 2.0 + 1e-6) ">" else "<=",
- ent.i3_value - sep.i3_value,
- violation_pct,
- if (ent.violation) "BELL INEQUALITY VIOLATED β QUANTUM NONLOCALITY CONFIRMED" else "No violation detected",
- });
-}
-
-fn run_demo() void {
- print(
- \\
- \\ =============================================
- \\ | TERNARY QUANTUM VM β DEMO |
- \\ =============================================
- \\
- \\
- , .{});
-
- // 1: Basis states
- print(" 1. Basis States:\n", .{});
- const basis = [_]struct { name: []const u8, q: qvm.Qutrit }{
- .{ .name = "|-1>", .q = qvm.Qutrit.MINUS },
- .{ .name = "| 0>", .q = qvm.Qutrit.ZERO_STATE },
- .{ .name = "|+1>", .q = qvm.Qutrit.PLUS },
- };
- for (basis) |s| {
- const p = s.q.probabilities();
- print(" {s} P(-1)={d:.3} P(0)={d:.3} P(+1)={d:.3}\n", .{ s.name, p[0], p[1], p[2] });
- }
-
- // 2: Hadamard
- print("\n 2. Hadamard |0> -> uniform superposition:\n", .{});
- const h_result = qvm.Gate3.hadamard3().apply(qvm.Qutrit.ZERO_STATE);
- const hp = h_result.probabilities();
- print(" H|0> P(-1)={d:.6} P(0)={d:.6} P(+1)={d:.6}\n", .{ hp[0], hp[1], hp[2] });
-
- // 3: Sacred phase
- print("\n 3. Sacred Phase Gate (golden angle = 2pi/phi^2):\n", .{});
- const sp_result = qvm.Gate3.sacred_phase().apply(h_result);
- const spp = sp_result.probabilities();
- print(" SP(H|0>) P(-1)={d:.6} P(0)={d:.6} P(+1)={d:.6}\n", .{ spp[0], spp[1], spp[2] });
- print(" (Phase changes quantum interference, not probabilities)\n", .{});
-
- // 4: X gate
- print("\n 4. X Gate (cyclic shift |-1>->|0>->|+1>->|-1>):\n", .{});
- var q = qvm.Qutrit.MINUS;
- const labels = [_][]const u8{ "start ", "X^1 ", "X^2 ", "X^3 " };
- for (0..4) |step| {
- const p = q.probabilities();
- print(" {s} P(-1)={d:.3} P(0)={d:.3} P(+1)={d:.3}\n", .{ labels[step], p[0], p[1], p[2] });
- q = qvm.Gate3.X3.apply(q);
- }
-
- // 5: Measurement
- print("\n 5. Measurement (10 trials on H|0>):\n ", .{});
- var vm = qvm.TernaryQVM.init(1, 42);
- var counts = [3]u32{ 0, 0, 0 };
- for (0..10) |_| {
- vm.qutrits[0] = qvm.Gate3.hadamard3().apply(qvm.Qutrit.ZERO_STATE);
- const m = vm.measure_qutrit(0);
- const idx: usize = @intCast(@as(i8, m) + 1);
- counts[idx] += 1;
- const sym: u8 = if (m < 0) '-' else if (m == 0) '0' else '+';
- print("{c} ", .{sym});
- }
- print("\n Counts: -1={d} 0={d} +1={d}\n", .{ counts[0], counts[1], counts[2] });
-
- // 6: Sacred math
- const phi: f64 = (1.0 + @sqrt(5.0)) / 2.0;
- print(
- \\
- \\ 6. Sacred Mathematics:
- \\ phi = {d:.10}
- \\ phi^2 = {d:.10}
- \\ 1/phi^2 = {d:.10}
- \\ phi^2 + 1/phi^2 = {d:.10} = TRINITY
- \\ Sacred angle = 2*pi/phi^2 = {d:.6} rad = {d:.3} deg
- \\
- \\ =============================================
- \\ DEMO COMPLETE | phi^2 + 1/phi^2 = 3
- \\ =============================================
- \\
- , .{
- phi,
- phi * phi,
- 1.0 / (phi * phi),
- phi * phi + 1.0 / (phi * phi),
- 2.0 * std.math.pi / (phi * phi),
- 360.0 * (2.0 * std.math.pi / (phi * phi)) / (2.0 * std.math.pi),
- });
-}
-
-fn run_bench() void {
- print(
- \\
- \\ =============================================
- \\ | TERNARY QUANTUM VM β BENCHMARK |
- \\ =============================================
- \\
- \\
- , .{});
-
- const iterations: u64 = 1_000_000;
-
- // Hadamard
- var timer = std.time.Timer.start() catch return;
- var q = qvm.Qutrit.ZERO_STATE;
- const h = qvm.Gate3.hadamard3();
- for (0..iterations) |_| {
- q = h.apply(q);
- }
- const h_ns = timer.read();
- std.mem.doNotOptimizeAway(&q);
-
- // X gate
- timer.reset();
- q = qvm.Qutrit.ZERO_STATE;
- for (0..iterations) |_| {
- q = qvm.Gate3.X3.apply(q);
- }
- const x_ns = timer.read();
- std.mem.doNotOptimizeAway(&q);
-
- // Sacred phase
- timer.reset();
- q = qvm.Qutrit.ZERO_STATE;
- const sp = qvm.Gate3.sacred_phase();
- for (0..iterations) |_| {
- q = sp.apply(q);
- }
- const sp_ns = timer.read();
- std.mem.doNotOptimizeAway(&q);
-
- // Full circuit
- timer.reset();
- var vm = qvm.TernaryQVM.init(1, 42);
- for (0..iterations) |_| {
- vm.qutrits[0] = qvm.Qutrit.ZERO_STATE;
- vm.hadamard(0);
- vm.sacred_phase(0);
- _ = vm.measure_qutrit(0);
- }
- const circuit_ns = timer.read();
-
- const h_per = @as(f64, @floatFromInt(h_ns)) / @as(f64, @floatFromInt(iterations));
- const x_per = @as(f64, @floatFromInt(x_ns)) / @as(f64, @floatFromInt(iterations));
- const sp_per = @as(f64, @floatFromInt(sp_ns)) / @as(f64, @floatFromInt(iterations));
- const circuit_per = @as(f64, @floatFromInt(circuit_ns)) / @as(f64, @floatFromInt(iterations));
-
- print(
- \\ Iterations: {d}
- \\
- \\ Gate Performance:
- \\ Hadamard: {d:.1} ns/op ({d:.1} M ops/sec)
- \\ X (cyclic): {d:.1} ns/op ({d:.1} M ops/sec)
- \\ Sacred Phase: {d:.1} ns/op ({d:.1} M ops/sec)
- \\ Full circuit: {d:.1} ns/op ({d:.1} M ops/sec)
- \\
- \\ =============================================
- \\ BENCHMARK COMPLETE
- \\ =============================================
- \\
- , .{
- iterations,
- h_per,
- 1000.0 / h_per,
- x_per,
- 1000.0 / x_per,
- sp_per,
- 1000.0 / sp_per,
- circuit_per,
- 1000.0 / circuit_per,
- });
-}
-
-/// Generate quantum-derived weights for FPGA ternary dot product
-fn run_weight_gen(args: []const []const u8) void {
- var entangled = false;
-
- var i: usize = 2;
- while (i < args.len) : (i += 1) {
- if (std.mem.eql(u8, args[i], "--entangled")) {
- entangled = true;
- }
- }
-
- if (entangled) {
- run_entangled_weight_gen();
- } else {
- run_single_weight_gen();
- }
-}
-
-fn run_single_weight_gen() void {
- print(
- \\
- \\ =============================================
- \\ | QUANTUM WEIGHT GENERATOR FOR FPGA |
- \\ =============================================
- \\
- \\ Quantum circuit per weight: |0> -> H3 -> Sacred_Phase -> Measure
- \\
- \\
- , .{});
-
- var vm = qvm.TernaryQVM.init(8, 137); // sacred seed: fine structure constant
-
- var weights: [16]i2 = undefined;
- var weight_bits: u32 = 0;
-
- for (0..16) |idx| {
- const qi: u4 = @intCast(idx % 8);
- vm.qutrits[qi] = qvm.Qutrit.ZERO_STATE;
- vm.hadamard(qi);
- vm.sacred_phase(qi);
-
- // Position-dependent gates for variety
- if (idx % 3 == 0) vm.z(qi);
- if (idx % 5 == 0) vm.x(qi);
-
- const trit = vm.measure_qutrit(qi);
- weights[idx] = trit;
-
- const encoding: u2 = if (trit < 0) 0b00 else if (trit == 0) 0b01 else 0b10;
- weight_bits |= @as(u32, encoding) << @intCast(idx * 2);
-
- const sym: u8 = if (trit < 0) '-' else if (trit == 0) '0' else '+';
- print(" w[{d:2}] = {c}1 (encoded: {b:0>2})\n", .{ idx, sym, encoding });
- }
-
- print(
- \\
- \\ Verilog Parameter (copy to ternary_dot.v):
- \\ localparam [31:0] WEIGHTS = 32'h{X:0>8};
- \\
- \\ Weight vector: [
- , .{weight_bits});
-
- for (0..16) |idx| {
- if (idx > 0) print(", ", .{});
- const sym: u8 = if (weights[idx] < 0) '-' else if (weights[idx] == 0) ' ' else '+';
- print("{c}1", .{sym});
- }
-
- print(
- \\]
- \\
- \\ =============================================
- \\ WEIGHT GENERATION COMPLETE
- \\ =============================================
- \\
- , .{});
-}
-
-/// Generate weights from entangled qutrit pairs
-/// Each weight comes from measuring one half of a Bell state
-/// after applying sacred phase rotation β correlations from entanglement
-fn run_entangled_weight_gen() void {
- print(
- \\
- \\ =============================================
- \\ | ENTANGLED WEIGHT GENERATOR FOR FPGA |
- \\ =============================================
- \\
- \\ Circuit: Bell(|0,0>) -> SP(A) -> Measure(A)
- \\ Source: Entangled qutrit pairs with sacred phase
- \\
- \\
- , .{});
-
- var prng = std.Random.DefaultPrng.init(137); // sacred seed
- const sp = qvm.Gate3.sacred_phase();
- const z = qvm.Gate3.z3();
-
- var weights: [16]i2 = undefined;
- var weight_bits: u32 = 0;
-
- for (0..16) |idx| {
- // Create fresh entangled pair
- var pair = qvm.EntangledPair.BELL;
-
- // Apply sacred phase + position-dependent gates to qutrit A
- pair = pair.apply_gate_a(sp);
- if (idx % 3 == 0) pair = pair.apply_gate_a(z);
- if (idx % 5 == 0) pair = pair.apply_gate_a(qvm.Gate3.X3);
-
- // Measure qutrit A β entanglement ensures non-classical distribution
- const trit = pair.measure_a(prng.random());
- weights[idx] = trit;
-
- const encoding: u2 = if (trit < 0) 0b00 else if (trit == 0) 0b01 else 0b10;
- weight_bits |= @as(u32, encoding) << @intCast(idx * 2);
-
- const sym: u8 = if (trit < 0) '-' else if (trit == 0) '0' else '+';
- print(" w[{d:2}] = {c}1 (entangled, encoded: {b:0>2})\n", .{ idx, sym, encoding });
- }
-
- // Run CGLMP to show violation alongside weights
- const cglmp = qvm.run_cglmp_test(10000, true);
-
- print(
- \\
- \\ CGLMP I3 = {d:.6} (classical bound: 2.0, quantum max: 2.9149)
- \\ Violation: {s}
- \\
- \\ Verilog Parameter (copy to ternary_dot.v):
- \\ localparam [31:0] WEIGHTS = 32'h{X:0>8};
- \\
- \\ Weight vector: [
- , .{
- cglmp.i3_value,
- if (cglmp.violation) "YES β QUANTUM ADVANTAGE" else "NO",
- weight_bits,
- });
-
- for (0..16) |idx| {
- if (idx > 0) print(", ", .{});
- const sym: u8 = if (weights[idx] < 0) '-' else if (weights[idx] == 0) ' ' else '+';
- print("{c}1", .{sym});
- }
-
- print(
- \\]
- \\
- \\ =============================================
- \\ ENTANGLED WEIGHT GENERATION COMPLETE
- \\ phi^2 + 1/phi^2 = 3 = TRINITY
- \\ =============================================
- \\
- , .{});
-}
diff --git a/src/quantum/measurement_problem.zig b/src/quantum/measurement_problem.zig
deleted file mode 100644
index e75c05c365..0000000000
--- a/src/quantum/measurement_problem.zig
+++ /dev/null
@@ -1,413 +0,0 @@
-//! TRINITY v19.0: QUANTUM MEASUREMENT PROBLEM
-//!
-//! Ο-Ξ³ based resolution of the measurement problem.
-//! Wavefunction collapse, decoherence, quantum Zeno effect, paradoxes.
-//!
-//! Core insight: Consciousness threshold Ξ¦_Ξ³ = Οβ»ΒΉ β 0.618
-//! determines when quantum possibilities become classical reality.
-
-const std = @import("std");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = 2.6180339887498948482...
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// ΟΒ³ = 4.23606797749978969641...
-pub const PHI_CUBED: f64 = PHI * PHI * PHI;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / PHI_CUBED;
-
-/// Consciousness threshold (Ξ¦_Ξ³ = Οβ»ΒΉ)
-pub const PHI_GAMMA: f64 = 1.0 / PHI;
-
-/// TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// Ο constant
-pub const PI: f64 = 3.14159265358979323846;
-
-/// Euler's number
-pub const E: f64 = 2.71828182845904523536;
-
-// Physical constants for measurement calculations
-pub const PLANCK_TIME: f64 = 5.391247e-44; // Planck time (s)
-pub const PLANCK_CONSTANT: f64 = 6.62607015e-34; // JΒ·s
-pub const REDUCED_PLANCK: f64 = 1.054571817e-34; // JΒ·s
-pub const BOLTZMANN: f64 = 1.380649e-23; // J/K
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// I. WAVEFUNCTION COLLAPSE (303-307)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 303: Collapse time
-/// The fundamental time quantum for wavefunction collapse
-/// t_collapse = Ξ³ Γ t_Planck
-pub fn collapseTime() f64 {
- return GAMMA * PLANCK_TIME;
-}
-
-/// Formula 304: Collapse probability
-/// Probability that wavefunction collapses within time t
-/// P_collapse = 1 - exp(-Ξ¦_Ξ³ Γ t/Ο)
-pub fn collapseProbability(t: f64, tau: f64) f64 {
- const rate = PHI_GAMMA / tau;
- return 1.0 - std.math.exp(-rate * t);
-}
-
-/// Formula 305: Collapse threshold
-/// Critical wavefunction amplitude that triggers collapse
-/// Ξ¨_threshold = Ξ¦_Ξ³ = Οβ»ΒΉ β 0.618
-pub fn collapseThreshold() f64 {
- return PHI_GAMMA;
-}
-
-/// Formula 306: Collapse rate
-/// Rate at which superposition decays to definite state
-/// Ξ_collapse = Ξ³ Γ H_β
-pub fn collapseRate(H_hbar: f64) f64 {
- return GAMMA * H_hbar;
-}
-
-/// Formula 307: Post-collapse entropy
-/// Entropy of system after conscious observation
-/// S_after = Ξ³ Γ S_before (information reduction)
-pub fn postCollapseEntropy(S_before: f64) f64 {
- return GAMMA * S_before;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// II. DECOHERENCE & EINSELECTION (308-312)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 308: Decoherence time
-/// Time for environment to select preferred states
-/// Ο_deco = Οβ»β΅ / H
-pub fn decoherenceTime(H: f64) f64 {
- const phi_inv_5 = 1.0 / (PHI * PHI * PHI * PHI * PHI);
- return phi_inv_5 / H;
-}
-
-/// Formula 309: Einselection probability
-/// Probability that environment selects state |iβ©
-/// P_einselect = Ξ³ Γ |β¨i|Ξ¨β©|Β²
-pub fn einselectionProbability(overlap: f64) f64 {
- return GAMMA * overlap * overlap;
-}
-
-/// Formula 310: Environment coupling strength
-/// Effective coupling between system and environment
-/// G_env = Ξ³ Γ g_0
-pub fn environmentCoupling(g_0: f64) f64 {
- return GAMMA * g_0;
-}
-
-/// Formula 311: Pointer state stability
-/// Timescale over which pointer states remain stable
-/// S_pointer = ΟΒ² Γ t
-pub fn pointerStateStability(t: f64) f64 {
- return PHI_SQ * t;
-}
-
-/// Formula 312: Quantum Darwinism factor
-/// Number of states that survive environmental selection
-/// D_Q = Ξ³β»ΒΉ Γ N_survivors
-pub fn quantumDarwinismFactor(N_survivors: f64) f64 {
- return (1.0 / GAMMA) * N_survivors;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// III. QUANTUM ZENO EFFECT (313-316)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 313: Zeno suppression
-/// Probability that system survives under frequent measurement
-/// P_Zeno = exp(-Ξ³ Γ N)
-pub fn zenoSuppression(N: f64) f64 {
- return std.math.exp(-GAMMA * N);
-}
-
-/// Formula 314: Anti-Zeno enhancement
-/// Enhancement of decay when measurement accelerates it
-/// P_antiZeno = 1 + Ξ³ Γ N
-pub fn antiZenoEnhancement(N: f64) f64 {
- return 1.0 + GAMMA * N;
-}
-
-/// Formula 315: Optimal measurement rate
-/// Measurement frequency that maximizes Zeno effect
-/// f_optimal = Ο Γ f_0
-pub fn optimalMeasurementRate(f_0: f64) f64 {
- return PHI * f_0;
-}
-
-/// Formula 316: Zeno-antiZeno transition
-/// Number of measurements where behavior switches
-/// N_transition = ΟΒ³ β 4.24
-pub fn zenoTransitionPoint() f64 {
- return PHI_CUBED;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// IV. QUANTUM PARADOXES (317-322)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Formula 317: Wigner's friend probability shift
-/// Probability that Wigner and Friend disagree
-/// P_disagree = Ξ³ Γ (1 - Ξ¦_Ξ³) β 0.090
-pub fn wignerFriendDisagreement() f64 {
- return GAMMA * (1.0 - PHI_GAMMA);
-}
-
-/// Formula 318: SchrΓΆdinger's cat resolution
-/// Cat is definitely alive or dead when observed
-/// P_cat_alive = Ξ¦_Ξ³ when Ξ¨ = (|aliveβ© + |deadβ©)/β2
-pub fn schrodingerCatProbability() f64 {
- return PHI_GAMMA;
-}
-
-/// Formula 319: Observer entanglement entropy
-/// Entropy generated when observer becomes entangled
-/// S_obs = Ξ³ Γ logβ(N_states)
-pub fn observerEntanglementEntropy(N_states: f64) f64 {
- const log2_N = std.math.log2(N_states);
- return GAMMA * log2_N;
-}
-
-/// Formula 320: Consciousness-induced collapse
-/// Extra collapse probability due to conscious observer
-/// P_conscious = P_collapse / (1 - Ξ¦_Ξ³) = P_collapse / Ξ³Β²
-pub fn consciousnessCollapse(P_collapse: f64) f64 {
- return P_collapse / (GAMMA * GAMMA);
-}
-
-/// Formula 321: Quantum-classical boundary
-/// Mass/size where quantum behavior stops
-/// M_boundary = ΟΒ³ Γ m_Planck β 9.2Γ10β»βΈ kg
-pub fn quantumClassicalBoundary() f64 {
- const m_planck = 2.176434e-8; // Actual Planck mass in kg
- return PHI_CUBED * m_planck;
-}
-
-/// Formula 322: Integrated information collapse
-/// IIT Ξ¦ Γ measurement = definite reality
-/// I_collapse = Φ_IIT à Φ_γ à Ψ²
-pub fn integratedInfoCollapse(Phi_IIT: f64, psi_squared: f64) f64 {
- return Phi_IIT * PHI_GAMMA * psi_squared;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HELPER FUNCTIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Calculate if wavefunction amplitude exceeds collapse threshold
-pub fn exceedsThreshold(psi_amplitude: f64) bool {
- return psi_amplitude >= PHI_GAMMA;
-}
-
-/// Calculate effective measurement strength
-/// Combines environmental decoherence and conscious observation
-pub fn effectiveMeasurementStrength(decoherence: f64, conscious_observation: bool) f64 {
- var strength = decoherence;
- if (conscious_observation) {
- strength += PHI_GAMMA;
- }
- return strength;
-}
-
-/// Time for definite outcome (collapse + decoherence)
-pub fn definiteOutcomeTime(H: f64) f64 {
- const t_deco = decoherenceTime(H);
- const t_collapse_val = collapseTime();
- // The larger of the two timescales dominates
- return @max(t_deco, t_collapse_val);
-}
-
-/// Quantum-to-classical transition probability
-/// Probability that system behaves classically at time t
-pub fn quantumToClassical(t: f64, H: f64) f64 {
- const t_definite = definiteOutcomeTime(H);
- return 1.0 - std.math.exp(-t / t_definite);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const testing = std.testing;
-
-test "v19.0: Formula 303 - Collapse time" {
- const t_c = collapseTime();
- try testing.expect(t_c > 0);
- try testing.expect(t_c < 1e-43); // Should be ~1.27e-44 s
-}
-
-test "v19.0: Formula 304 - Collapse probability" {
- const P = collapseProbability(1.0e-10, 1.0e-10);
- try testing.expect(P > 0.4); // With tau=t, P β 0.46
- try testing.expect(P < 1.0);
-}
-
-test "v19.0: Formula 305 - Collapse threshold" {
- const threshold = collapseThreshold();
- try testing.expectApproxEqRel(@as(f64, 0.618), threshold, 0.01);
-}
-
-test "v19.0: Formula 306 - Collapse rate" {
- const H = 1e44; // Typical Planck-scale frequency
- const Gamma_c = collapseRate(H);
- try testing.expect(Gamma_c > 0);
- try testing.expect(Gamma_c > 2e43); // Ξ³ Γ H = 0.236 Γ 1e44 = 2.36e43
-}
-
-test "v19.0: Formula 307 - Post-collapse entropy" {
- const S_before = 10.0;
- const S_after = postCollapseEntropy(S_before);
- try testing.expect(S_after < S_before); // Entropy reduced
- try testing.expectApproxEqRel(@as(f64, 2.36), S_after, 0.1);
-}
-
-test "v19.0: Formula 308 - Decoherence time" {
- const H = 1e10;
- const tau = decoherenceTime(H);
- try testing.expect(tau > 0);
- try testing.expect(tau < 1e-10);
-}
-
-test "v19.0: Formula 309 - Einselection probability" {
- const P = einselectionProbability(0.5);
- try testing.expect(P > 0);
- try testing.expect(P < 0.5); // Must be less than raw probability
-}
-
-test "v19.0: Formula 310 - Environment coupling" {
- const g_0 = 1.0;
- const G_env = environmentCoupling(g_0);
- try testing.expect(G_env < g_0); // Reduced by gamma
-}
-
-test "v19.0: Formula 311 - Pointer state stability" {
- const t = 1.0e-3;
- const S = pointerStateStability(t);
- try testing.expect(S > t); // Enhanced by phiΒ²
-}
-
-test "v19.0: Formula 312 - Quantum Darwinism factor" {
- const N = 10.0;
- const D = quantumDarwinismFactor(N);
- try testing.expect(D > N); // Amplified by 1/Ξ³ β 4.24
-}
-
-test "v19.0: Formula 313 - Zeno suppression" {
- const N = 10.0;
- const P = zenoSuppression(N);
- try testing.expect(P > 0);
- try testing.expect(P < 1.0);
-}
-
-test "v19.0: Formula 314 - Anti-Zeno enhancement" {
- const N = 10.0;
- const P = antiZenoEnhancement(N);
- try testing.expect(P > 1.0); // Enhancement
- try testing.expect(P < 5.0);
-}
-
-test "v19.0: Formula 315 - Optimal measurement rate" {
- const f_0 = 1000.0;
- const f_opt = optimalMeasurementRate(f_0);
- try testing.expect(f_opt > f_0);
-}
-
-test "v19.0: Formula 316 - Zeno transition point" {
- const N_trans = zenoTransitionPoint();
- try testing.expectApproxEqRel(@as(f64, 4.236), N_trans, 0.01);
-}
-
-test "v19.0: Formula 317 - Wigner's friend disagreement" {
- const P = wignerFriendDisagreement();
- try testing.expect(P > 0.08);
- try testing.expect(P < 0.10);
-}
-
-test "v19.0: Formula 318 - SchrΓΆdinger's cat probability" {
- const P = schrodingerCatProbability();
- try testing.expect(P > 0.6);
- try testing.expect(P < 0.65);
-}
-
-test "v19.0: Formula 319 - Observer entanglement entropy" {
- const N = 8.0;
- const S = observerEntanglementEntropy(N);
- try testing.expect(S > 0);
- try testing.expect(S < 5.0);
-}
-
-test "v19.0: Formula 320 - Consciousness collapse" {
- const P_collapse = 0.5;
- const P_conscious = consciousnessCollapse(P_collapse);
- try testing.expect(P_conscious > P_collapse); // Enhanced by 1/Ξ³Β² β 17.9
- try testing.expect(P_conscious < 10.0);
-}
-
-test "v19.0: Formula 321 - Quantum-classical boundary" {
- const M = quantumClassicalBoundary();
- try testing.expect(M > 9e-8); // ΟΒ³ Γ 2.18Γ10β»βΈ β 9.2Γ10β»βΈ
- try testing.expect(M < 1e-7);
-}
-
-test "v19.0: Formula 322 - Integrated info collapse" {
- const Phi_IIT = 1.0;
- const psi_sq = 0.5;
- const I = integratedInfoCollapse(Phi_IIT, psi_sq);
- try testing.expect(I > 0);
- try testing.expect(I < 1.0);
-}
-
-test "v19.0: Helper - Exceeds threshold" {
- try testing.expect(exceedsThreshold(0.7)); // Above 0.618
- try testing.expect(!exceedsThreshold(0.5)); // Below 0.618
-}
-
-test "v19.0: Helper - Effective measurement strength" {
- const strength_weak = effectiveMeasurementStrength(0.1, false);
- const strength_strong = effectiveMeasurementStrength(0.1, true);
- try testing.expect(strength_strong > strength_weak);
-}
-
-test "v19.0: Helper - Definite outcome time" {
- const H = 1e15;
- const t_def = definiteOutcomeTime(H);
- try testing.expect(t_def > 0);
-}
-
-test "v19.0: Helper - Quantum to classical transition" {
- const H = 1e15;
- const P = quantumToClassical(1e-10, H);
- try testing.expect(P > 0);
- try testing.expect(P <= 1.0);
-}
-
-test "v19.0: TRINITY identity holds" {
- try testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-test "v19.0: PHI_GAMMA = phi^(-1)" {
- try testing.expectApproxEqRel(PHI_GAMMA, 1.0 / PHI, 1e-10);
-}
-
-test "v19.0: GAMMA = phi^(-3)" {
- try testing.expectApproxEqRel(GAMMA, 1.0 / PHI_CUBED, 1e-10);
-}
-
-// Version info
-pub const VERSION = "19.0.0";
-pub const MODULE_NAME = "QUANTUM MEASUREMENT PROBLEM";
-pub const FORMULA_START = 303;
-pub const FORMULA_END = 322;
-pub const FORMULA_COUNT = 20;
diff --git a/src/quantum/quantum_bridge_runner.zig b/src/quantum/quantum_bridge_runner.zig
deleted file mode 100644
index 420bf97a51..0000000000
--- a/src/quantum/quantum_bridge_runner.zig
+++ /dev/null
@@ -1,124 +0,0 @@
-//! QUANTUM BRIDGE RUNNER β Real-time CGLMP β FPGA
-//!
-//! Runs CGLMP quantum violation tests continuously and updates FPGA LED
-//! via automatic bitstream switching.
-//!
-//! phi^2 + 1/phi^2 = 3 = TRINITY
-//!
-//! Usage: zig build quantum-bridge
-
-const std = @import("std");
-const qvm = @import("ternary_qvm.zig");
-const print = std.debug.print;
-
-// Use C nanosleep directly to avoid symbol shadowing issues
-const c = @cImport({
- @cDefine("_POSIX_C_SOURCE", "199309L");
- @cInclude("time.h");
-});
-
-pub fn main() !void {
- const allocator = std.heap.page_allocator;
-
- // Print banner
- print("\n", .{});
- print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- print("β QUANTUM BRIDGE RUNNER β Real-time CGLMP β FPGA β\n", .{});
- print("β ΟΒ² + 1/ΟΒ² = 3 = TRINITY β\n", .{});
- print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- print("\n", .{});
-
- // Bitstream paths (mapped from quantum states)
- const bitstreams = [_][]const u8{
- "separable", // 00 -> Iβ < 1.0
- "violation", // 01 -> 1.0 β€ Iβ < 2.0
- "zero", // 10 -> 2.0 β€ Iβ < 2.5
- "negative", // 11 -> Iβ β₯ 2.5
- };
-
- // Base path for bitstreams
- const base_path = "/Users/playra/trinity-w1/fpga/openxc7-synth/quantum_bridge_";
-
- var iteration: u32 = 0;
- var violation_count: u32 = 0;
-
- while (true) : (iteration += 1) {
- // Run CGLMP test (analytical, instant)
- const result = qvm.run_cglmp_test(0, true);
-
- // Map I3 value to quantum state index
- const state_idx: usize = if (result.i3_value < 1.0) 0 else if (result.i3_value < 2.0) 1 else if (result.i3_value < 2.5) 2 else 3;
-
- const state_name = bitstreams[state_idx];
-
- // Count violations
- if (result.violation) violation_count += 1;
-
- // Display result with color
- print("[{d:4}] ", .{iteration});
-
- if (result.violation) {
- print("\x1b[32mVIOLATION!\x1b[0m ", .{});
- } else {
- print("separable ", .{});
- }
-
- print("Iβ={d:.4} | State={s} ({})", .{ result.i3_value, state_name, result.violation });
-
- if (state_idx == 1) { // violation mode
- print(" \x1b[33mβ‘ FAST (~6 Hz)\x1b[0m", .{});
- } else if (state_idx == 3) { // negative
- print(" \x1b[31mβ STEADY ON\x1b[0m", .{});
- } else if (state_idx == 2) { // zero
- print(" ~ SLOW (~0.4 Hz)", .{});
- } else { // separable
- print(" ~ MEDIUM (~3 Hz)", .{});
- }
-
- print("\n", .{});
-
- // Flash appropriate bitstream
- const bitfile = try std.fmt.allocPrint(allocator, "{s}{s}.bit", .{ base_path, state_name });
-
- try flashBitstream(bitfile);
- allocator.free(bitfile);
-
- // Statistics every 10 iterations
- if (iteration % 10 == 0) {
- const violation_rate = @as(f64, @floatFromInt(violation_count)) * 100.0 / @as(f64, @floatFromInt(iteration));
- print(" ββ Violations: {d}/{d} ({d:.1}%)\n", .{ violation_count, iteration, violation_rate });
- }
-
- // Wait before next iteration
- // Use C nanosleep directly to avoid symbol shadowing issues
- var req = c.timespec{ .tv_sec = 1, .tv_nsec = 0 };
- _ = c.nanosleep(&req, null);
- }
-}
-
-fn flashBitstream(path: []const u8) !void {
- const allocator = std.heap.page_allocator;
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{
- "sudo",
- "/Users/playra/trinity-w1/fpga/tools/jtag_program",
- path,
- },
- }) catch |err| {
- print("Failed to spawn jtag_process: {}\n", .{err});
- return error.FlashFailed;
- };
-
- defer {
- allocator.free(result.stdout);
- allocator.free(result.stderr);
- }
-
- if (result.term.Exited != 0) {
- if (result.stderr.len > 0) {
- print("Flash failed: {s}\n", .{result.stderr});
- }
- return error.FlashFailed;
- }
-}
diff --git a/src/quantum/qutrit.zig b/src/quantum/qutrit.zig
deleted file mode 100644
index 925b5855c7..0000000000
--- a/src/quantum/qutrit.zig
+++ /dev/null
@@ -1,384 +0,0 @@
-// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// β TRINITY QUTRIT β Ternary Quantum Bit Primitives β
-// β Week 2 Day 5: Qutrit operations for TQNN β
-// β β
-// β Qutrit states: |0β© = -1, |1β© = 0, |2β© = +1 β
-// β Encoding: 2-bit packed trits β
-// β β
-// β ΟΒ² + 1/ΟΒ² = 3 = TRINITY β
-// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-
-/// Trit values for ternary logic
-pub const Trit = i2;
-pub const TRIT_NEG: Trit = -1;
-pub const TRIT_ZERO: Trit = 0;
-pub const TRIT_POS: Trit = 1;
-
-/// Qutrit: quantum-inspired ternary bit
-/// Represents a ternary state with quantum superposition capability
-pub const Qutrit = struct {
- /// The trit value (-1, 0, +1)
- value: Trit = TRIT_ZERO,
-
- /// Phase angle (0-255, represents 0-2Ο)
- phase: u8 = 0,
-
- /// Coherence flag (quantum coherence maintained)
- coherent: bool = true,
-
- /// Create a qutrit from a trit value
- pub fn from_trit(t: Trit) Qutrit {
- return .{
- .value = t,
- .phase = 0,
- .coherent = true,
- };
- }
-
- /// Create a qutrit from a float value
- /// Maps: negative -> -1, ~0 -> 0, positive -> +1
- pub fn from_float(f: f32) Qutrit {
- const threshold = 0.5;
- if (f < -threshold) return from_trit(TRIT_NEG);
- if (f > threshold) return from_trit(TRIT_POS);
- return from_trit(TRIT_ZERO);
- }
-
- /// Create a qutrit from a 2-bit packed encoding
- /// 00 -> -1, 01 -> 0, 10 -> +1, 11 -> reserved (treats as 0)
- pub fn from_packed(p: u2) Qutrit {
- return switch (p) {
- 0b00 => from_trit(TRIT_NEG),
- 0b01 => from_trit(TRIT_ZERO),
- 0b10 => from_trit(TRIT_POS),
- 0b11 => from_trit(TRIT_ZERO), // Reserved
- };
- }
-
- /// Convert qutrit to float
- pub fn to_float(q: Qutrit) f32 {
- return @as(f32, @floatFromInt(q.value));
- }
-
- /// Convert qutrit to packed 2-bit encoding
- pub fn to_packed(q: Qutrit) u2 {
- return switch (q.value) {
- TRIT_NEG => 0b00,
- TRIT_ZERO => 0b01,
- TRIT_POS => 0b10,
- };
- }
-
- /// Apply Hadamard gate to qutrit
- /// H|Οβ© transforms: -1β+1, 0β-1, +1β0
- pub fn hadamard(q: *Qutrit) void {
- q.value = switch (q.value) {
- TRIT_NEG => TRIT_POS,
- TRIT_ZERO => TRIT_NEG,
- TRIT_POS => TRIT_ZERO,
- else => TRIT_ZERO, // Fallback for invalid values
- };
- // Hadamard adds Ο phase
- q.phase +%= 128;
- }
-
- /// Apply Pauli-X (NOT) gate to qutrit
- /// X|Οβ© flips: -1β+1, 0 stays
- pub fn pauli_x(q: *Qutrit) void {
- if (q.value != TRIT_ZERO) {
- q.value = -q.value;
- }
- q.phase +%= 64;
- }
-
- /// Apply Rotation gate by angle (0-255)
- /// Small angle: stay, Medium: rotate +1, Large: rotate +2 (flip)
- pub fn rotate(q: *Qutrit, angle: u8) void {
- const rotation = angle >> 6; // Top 2 bits
- switch (rotation) {
- 0b00 => {}, // No change
- 0b01 => { // Rotate +1: -1β0β+1β-1
- q.value = switch (q.value) {
- TRIT_NEG => TRIT_ZERO,
- TRIT_ZERO => TRIT_POS,
- TRIT_POS => TRIT_NEG,
- else => TRIT_ZERO,
- };
- },
- else => { // Rotate +2 or flip
- if (q.value != TRIT_ZERO) {
- q.value = -q.value;
- }
- },
- }
- q.phase +%= angle;
- }
-
- /// Apply Sacred Phase (Golden Angle: 137.5Β°)
- /// Golden angle = 2Ο Γ (1 - 1/Ο) β 137.5Β°
- pub fn sacred_phase(q: *Qutrit) void {
- q.phase +%= GOLDEN_ANGLE_U8;
- // Apply phase flip if phase wraps
- if (q.phase < GOLDEN_ANGLE_U8) {
- // Phase wrapped around - apply small transformation
- q.value = switch (q.value) {
- TRIT_NEG => TRIT_ZERO,
- TRIT_ZERO => TRIT_POS,
- TRIT_POS => TRIT_NEG,
- else => TRIT_ZERO,
- };
- }
- }
-
- /// Apply CPhase (Controlled Phase) gate
- /// Flips if control is +1 and phase > 128
- pub fn cphase(q: *Qutrit, control: Qutrit, phase: u8) void {
- if (control.value == TRIT_POS and phase > 128) {
- if (q.value != TRIT_ZERO) {
- q.value = -q.value;
- }
- }
- q.phase +%= phase;
- }
-
- /// Measure qutrit (collapse to classical trit)
- /// In this implementation, qutrits are always "measured"
- pub fn measure(q: Qutrit) Trit {
- _ = q.coherent; // In real quantum, coherence affects measurement
- return q.value;
- }
-
- /// Compute inner product of two qutrits
- pub fn inner_product(a: Qutrit, b: Qutrit) i2 {
- return @as(i2, @intCast(a.value)) * @as(i2, @intCast(b.value));
- }
-
- /// Check if two qutrits are orthogonal (different states)
- pub fn orthogonal(a: Qutrit, b: Qutrit) bool {
- return a.value != b.value;
- }
-};
-
-/// Golden ratio constant
-pub const PHI: f32 = 1.618033988749895;
-
-/// Golden angle in degrees
-pub const GOLDEN_ANGLE_DEG: f32 = 137.507764;
-
-/// Golden angle encoded as 8-bit (0-255)
-pub const GOLDEN_ANGLE_U8: u8 = 98; // 137.5/360 * 256 β 97.78
-
-/// Sacred phase constant (ΟΒ²)
-pub const SACRED_PHASE: f32 = PHI * PHI;
-
-/// Trinity constant (ΟΒ² + 1/ΟΒ²)
-pub const TRINITY: f32 = 3.0;
-
-//==============================================================================
-// QUTRIT ARRAY OPERATIONS
-//==============================================================================
-
-/// Array of qutrits for vector operations
-pub fn QutritArray(comptime size: usize) type {
- return struct {
- data: [size]Qutrit = [_]Qutrit{.{}} ** size,
-
- /// Initialize from trit array
- pub fn from_trits(trits: [size]Trit) @This() {
- var result: @This() = undefined;
- for (trits, 0..) |t, i| {
- result.data[i] = Qutrit.from_trit(t);
- }
- return result;
- }
-
- /// Initialize from float array
- pub fn from_floats(floats: [size]f32) @This() {
- var result: @This() = undefined;
- for (floats, 0..) |f, i| {
- result.data[i] = Qutrit.from_float(f);
- }
- return result;
- }
-
- /// Apply Hadamard to all qutrits
- pub fn hadamard_all(qa: *@This()) void {
- for (&qa.data) |*q| {
- q.hadamard();
- }
- }
-
- /// Apply Sacred Phase to all qutrits
- pub fn sacred_phase_all(qa: *@This()) void {
- for (&qa.data) |*q| {
- q.sacred_phase();
- }
- }
-
- /// Apply Rotation to all qutrits with angle gradient
- pub fn rotate_all(qa: *@This(), base_angle: u8) void {
- for (&qa.data, 0..) |*q, i| {
- const local_angle = base_angle + @as(u8, @intCast(i * 16));
- q.rotate(local_angle);
- }
- }
-
- /// Compute coherence (balanced distribution)
- /// Returns true if positive and negative qutrits are balanced
- pub fn coherence(qa: *@This()) bool {
- var pos_count: usize = 0;
- var neg_count: usize = 0;
- var zero_count: usize = 0;
-
- for (qa.data) |q| {
- switch (q.value) {
- TRIT_POS => pos_count += 1,
- TRIT_NEG => neg_count += 1,
- TRIT_ZERO => zero_count += 1,
- else => {}, // Invalid trit values - ignore
- }
- }
-
- // Coherent: significant pos and neg, not too many zeros
- return (pos_count > size / 4) and (neg_count > size / 4);
- }
-
- /// Get quantum state summary
- pub fn quantum_state(qa: *@This()) struct { pos: usize, neg: usize, zero: usize } {
- var result: struct { pos: usize, neg: usize, zero: usize } = .{
- .pos = 0,
- .neg = 0,
- .zero = 0,
- };
-
- for (qa.data) |q| {
- switch (q.value) {
- TRIT_POS => result.pos += 1,
- TRIT_NEG => result.neg += 1,
- TRIT_ZERO => result.zero += 1,
- }
- }
-
- return result;
- }
-
- /// Measure all qutrits to trits
- pub fn measure_all(qa: @This()) [size]Trit {
- var result: [size]Trit = undefined;
- for (qa.data, 0..) |q, i| {
- result[i] = q.measure();
- }
- return result;
- }
-
- /// Convert to packed bits (2 bits per qutrit)
- pub fn to_packed(qa: @This()) PackedArray(size) {
- var result: PackedArray(size) = .{};
- for (qa.data, 0..) |q, i| {
- result.set(i, q.to_packed());
- }
- return result;
- }
- };
-}
-
-/// Packed qutrit array (2 bits per qutrit)
-pub fn PackedArray(comptime size: usize) type {
- const byte_count = (size * 2 + 7) / 8;
- return struct {
- data: [byte_count]u8 = [_]u8{0} ** byte_count,
-
- /// Get qutrit at index
- pub fn get(pa: @This(), index: usize) u2 {
- const bit_pos = index * 2;
- const byte_idx = bit_pos / 8;
- const bit_offset: u3 = @intCast(bit_pos % 8);
- const mask: u8 = @as(u8, 0b11) << bit_offset;
- return @as(u2, @intCast((pa.data[byte_idx] & mask) >> bit_offset));
- }
-
- /// Set qutrit at index
- pub fn set(pa: *@This(), index: usize, value: u2) void {
- const bit_pos = index * 2;
- const byte_idx = bit_pos / 8;
- const bit_offset: u3 = @intCast(bit_pos % 8);
- const mask: u8 = ~(@as(u8, 0b11) << bit_offset);
- pa.data[byte_idx] = (pa.data[byte_idx] & mask) | (@as(u8, value) << bit_offset);
- }
- };
-}
-
-//==============================================================================
-// TESTS
-//==============================================================================
-
-const testing = std.testing;
-
-test "Qutrit from_float" {
- const q_neg = Qutrit.from_float(-1.0);
- try testing.expectEqual(TRIT_NEG, q_neg.value);
-
- const q_zero = Qutrit.from_float(0.0);
- try testing.expectEqual(TRIT_ZERO, q_zero.value);
-
- const q_pos = Qutrit.from_float(1.0);
- try testing.expectEqual(TRIT_POS, q_pos.value);
-}
-
-test "Qutrit hadamard" {
- var q = Qutrit.from_trit(TRIT_NEG);
- q.hadamard();
- try testing.expectEqual(TRIT_POS, q.value);
-
- q = Qutrit.from_trit(TRIT_ZERO);
- q.hadamard();
- try testing.expectEqual(TRIT_NEG, q.value);
-
- q = Qutrit.from_trit(TRIT_POS);
- q.hadamard();
- try testing.expectEqual(TRIT_ZERO, q.value);
-}
-
-test "Qutrit sacred_phase" {
- var q = Qutrit.from_trit(TRIT_NEG);
- const old_phase = q.phase;
- q.sacred_phase();
- try testing.expect(q.phase != old_phase);
-}
-
-test "QutritArray hadamard_all" {
- var qa = QutritArray(16).from_trits([_]Trit{TRIT_NEG} ** 16);
- qa.hadamard_all();
- for (qa.data) |q| {
- try testing.expectEqual(TRIT_POS, q.value);
- }
-}
-
-test "QutritArray coherence" {
- // Balanced: should be coherent
- var pos_trits: [16]Trit = undefined;
- for (0..8) |i| pos_trits[i] = TRIT_POS;
- for (8..16) |i| pos_trits[i] = TRIT_NEG;
- var qa_balanced = QutritArray(16).from_trits(pos_trits);
- try testing.expect(qa_balanced.coherence());
-
- // Unbalanced: should not be coherent
- var qa_unbalanced = QutritArray(16).from_trits([_]Trit{TRIT_ZERO} ** 16);
- try testing.expect(!qa_unbalanced.coherence());
-}
-
-test "PackedArray get/set" {
- var pa: PackedArray(16) = .{};
- pa.set(0, 0b10);
- pa.set(1, 0b01);
- pa.set(15, 0b00);
-
- try testing.expectEqual(@as(u2, 0b10), pa.get(0));
- try testing.expectEqual(@as(u2, 0b01), pa.get(1));
- try testing.expectEqual(@as(u2, 0b00), pa.get(15));
-}
-
-// ΟΒ² + 1/ΟΒ² = 3 = TRINITY
-// Cycle #127 β Week 2 Day 5
diff --git a/src/quantum/qutrit_optimizer.zig b/src/quantum/qutrit_optimizer.zig
deleted file mode 100644
index 87f9f78934..0000000000
--- a/src/quantum/qutrit_optimizer.zig
+++ /dev/null
@@ -1,977 +0,0 @@
-//! Qutrit Circuit Optimization and Synthesis
-//!
-//! Implements circuit synthesis algorithms for qutrit quantum circuits:
-//! - Gate decomposition and optimization
-//! - CGLMP Bell test circuit synthesis
-//! - Circuit simplification and peephole optimization
-//! - Native gate conversion
-
-const std = @import("std");
-const math = std.math;
-const golden_gates = @import("golden_gates.zig");
-
-//===========================================================================
-// Constants
-//===========================================================================
-
-pub const GOLDEN_RATIO: f64 = golden_gates.GOLDEN_RATIO;
-pub const GOLDEN_ANGLE_DEG: f64 = 137.5077644087447;
-
-//===========================================================================
-// Types
-//===========================================================================
-
-/// Circuit cost metrics (multi-objective)
-pub const CircuitCost = struct {
- gate_count: usize,
- depth: usize,
- fidelity: f64,
- two_qutrit_count: usize,
-
- pub fn init() CircuitCost {
- return CircuitCost{
- .gate_count = 0,
- .depth = 0,
- .fidelity = 1.0,
- .two_qutrit_count = 0,
- };
- }
-
- /// Combine costs (for Pareto comparison)
- pub fn score(self: CircuitCost, weights: [4]f64) f64 {
- return @as(f64, @floatFromInt(self.gate_count)) * weights[0] +
- @as(f64, @floatFromInt(self.depth)) * weights[1] +
- (1.0 - self.fidelity) * weights[2] +
- @as(f64, @floatFromInt(self.two_qutrit_count)) * weights[3];
- }
-};
-
-/// Gate type enumeration
-pub const GateType = enum {
- // Single-qutrit gates
- golden_phase, // TRINITY phase gate
- golden_rotation, // Golden angle rotation
- fourier, // Qutrit Fourier transform
- shift, // Cyclic shift
- // Two-qutrit gates
- controlled_phase, // Controlled phase
- controlled_fourier,
- swap,
- // Clifford gates
- h, // Hadamard-like (for qutrits)
- s, // Phase gate
- t, // Ο/8 gate equivalent
-};
-
-/// Quantum gate
-pub const Gate = struct {
- ty: GateType,
- params: []const f64, // Variable parameters (angles, etc.)
- num_params: usize,
- target: ?usize, // Target qutrit (for single-qutrit gates)
- control: ?usize, // Control qutrit (for two-qutrit gates)
- matrix: ?[9]Complex, // 3Γ3 or 9Γ9 unitary matrix
-};
-
-/// Complex number for unitary matrices
-pub const Complex = struct { re: f64, im: f64 };
-
-/// Quantum circuit
-pub const QuantumCircuit = struct {
- gates: []Gate,
- num_qutrits: usize,
- depth: usize,
- allocator: std.mem.Allocator,
-
- pub fn init(allocator: std.mem.Allocator, num_qutrits: usize) !QuantumCircuit {
- const gates = try allocator.alloc(Gate, 0);
- return QuantumCircuit{
- .gates = gates,
- .num_qutrits = num_qutrits,
- .depth = 0,
- .allocator = allocator,
- };
- }
-
- pub fn deinit(self: *QuantumCircuit) void {
- self.allocator.free(self.gates);
- }
-
- /// Clone the circuit
- pub fn clone(self: *const QuantumCircuit, allocator: std.mem.Allocator) !QuantumCircuit {
- var new_circuit = try QuantumCircuit.init(allocator, self.num_qutrits);
- for (self.gates) |gate| {
- const params = try allocator.alloc(f64, gate.params.len);
- @memcpy(params, gate.params);
- const gate_copy = Gate{
- .ty = gate.ty,
- .params = params,
- .num_params = gate.num_params,
- .target = gate.target,
- .control = gate.control,
- .matrix = null,
- };
- try new_circuit.addGate(allocator, gate_copy);
- }
- return new_circuit;
- }
-
- /// Add gate to circuit
- pub fn addGate(self: *QuantumCircuit, allocator: std.mem.Allocator, gate: Gate) !void {
- const new_gates = try allocator.realloc(self.gates, self.gates.len + 1);
- self.gates = new_gates;
- self.gates[self.gates.len - 1] = gate;
- self.depth = @max(self.depth, self.calculateDepth());
- }
-
- fn calculateDepth(self: *const QuantumCircuit) usize {
- // Simplified: gate count = depth (no parallelization)
- _ = self;
- return 0;
- }
-};
-
-/// Optimization result
-pub const OptimizationResult = struct {
- circuit: QuantumCircuit,
- cost: CircuitCost,
- synthesis_time: f64,
- method: []const u8,
- allocator: std.mem.Allocator,
-
- pub fn deinit(self: *OptimizationResult) void {
- self.circuit.deinit();
- self.allocator.free(self.method);
- }
-};
-
-/// Target unitary for synthesis
-pub const TargetUnitary = struct {
- matrix: [9]Complex, // 3Γ3 for single qutrit, or 9Γ9 for two
-
- pub fn verify(self: TargetUnitary, circuit: QuantumCircuit) f64 {
- _ = self;
- _ = circuit;
- // DEFERRED (v12): Compute circuit unitary via matrix multiplication and compare to target
- // Requires: gate unitary definitions, matrix multiplication, fidelity metric
- return 1.0; // Placeholder: perfect fidelity
- }
-};
-
-//===========================================================================
-// Gate Set
-//===========================================================================
-
-/// Available gate set for synthesis
-pub const GateSet = struct {
- single_qutrit: []const GateType,
- two_qutrit: []const GateType,
- native_gates: []const []const u8,
-
- pub fn initDefault(allocator: std.mem.Allocator) !GateSet {
- _ = allocator;
- return GateSet{
- .single_qutrit = &[_]GateType{
- .golden_phase,
- .golden_rotation,
- .fourier,
- .shift,
- },
- .two_qutrit = &[_]GateType{
- .controlled_phase,
- .controlled_fourier,
- },
- .native_gates = &[_][]const u8{
- "GOLDEN_PHASE",
- "GOLDEN_ROTATION",
- "FOURIER",
- },
- };
- }
-};
-
-//===========================================================================
-// Optimization Algorithms
-//===========================================================================
-
-/// Simplify circuit by removing identities and canceling inverses
-pub fn simplifyCircuit(allocator: std.mem.Allocator, circuit: QuantumCircuit) !QuantumCircuit {
- var simplified = try QuantumCircuit.init(allocator, circuit.num_qutrits);
- errdefer simplified.deinit();
-
- var i: usize = 0;
- while (i < circuit.gates.len) {
- const current = circuit.gates[i];
-
- // Check if gate is effectively identity (no params or all zero params)
- var is_identity = false;
- if (current.params.len == 0 or
- (current.params.len > 0 and current.params[0] == 0))
- {
- // Check if this gate type with zero params is identity
- is_identity = switch (current.ty) {
- .golden_rotation => true, // Rotation by 0 is identity
- .shift => true, // Shift by 0 is identity
- else => false,
- };
- }
-
- if (is_identity) {
- // Skip identity gate
- i += 1;
- continue;
- }
-
- // Check for adjacent inverse gates
- if (i + 1 < circuit.gates.len) {
- const next = circuit.gates[i + 1];
- if (areInverses(current, next)) {
- // Cancel both
- i += 2;
- continue;
- }
- }
-
- // Merge consecutive rotations of same type
- if (i + 1 < circuit.gates.len and
- current.ty == .golden_rotation and
- circuit.gates[i + 1].ty == .golden_rotation and
- current.target == circuit.gates[i + 1].target)
- {
- // Merge angles
- const merged_params = try allocator.alloc(f64, 1);
- merged_params[0] = current.params[0] + circuit.gates[i + 1].params[0];
- const merged_gate = Gate{
- .ty = .golden_rotation,
- .params = merged_params,
- .num_params = 1,
- .target = current.target,
- .control = null,
- .matrix = null,
- };
- try simplified.addGate(allocator, merged_gate);
- i += 2;
- continue;
- }
-
- // Keep gate
- const params_copy = try allocator.dupe(f64, current.params);
- const gate_copy = Gate{
- .ty = current.ty,
- .params = params_copy,
- .num_params = current.num_params,
- .target = current.target,
- .control = current.control,
- .matrix = null,
- };
- try simplified.addGate(allocator, gate_copy);
- i += 1;
- }
-
- return simplified;
-}
-
-/// Check if two gates are inverses of each other
-fn areInverses(a: Gate, b: Gate) bool {
- if (a.ty != b.ty) return false;
- if (a.target != b.target) return false;
-
- // For rotations: check if angles sum to 0 or 2Ο
- if (a.ty == .golden_rotation and a.params.len >= 1 and b.params.len >= 1) {
- const sum = a.params[0] + b.params[0];
- return @abs(sum) < 1e-10 or @abs(sum - 2 * std.math.pi) < 1e-10;
- }
-
- // Self-inverse gates: same gate twice cancels
- if (a.ty == .fourier) {
- // F^3 = I for ternary Fourier, so two applications = F^2 β I
- return false;
- }
-
- return false;
-}
-
-/// Decompose unitary to native gates
-pub fn convertToNativeGates(
- allocator: std.mem.Allocator,
- circuit: QuantumCircuit,
- gate_set: GateSet,
-) !QuantumCircuit {
- var native = try QuantumCircuit.init(allocator, circuit.num_qutrits);
- errdefer native.deinit();
-
- for (circuit.gates) |gate| {
- // Check if gate is already native
- var is_native = false;
- for (gate_set.single_qutrit) |native_ty| {
- if (gate.ty == native_ty) {
- is_native = true;
- break;
- }
- }
-
- if (is_native) {
- // Copy gate as-is
- const params_copy = try allocator.alloc(f64, gate.params.len);
- @memcpy(params_copy, gate.params);
- const gate_copy = Gate{
- .ty = gate.ty,
- .params = params_copy,
- .num_params = gate.num_params,
- .target = gate.target,
- .control = gate.control,
- .matrix = null,
- };
- try native.addGate(allocator, gate_copy);
- } else {
- // Decompose to native gates
- try decomposeGate(allocator, &native, gate, &gate_set);
- }
- }
-
- return native;
-}
-
-/// Decompose a gate to native gate set
-fn decomposeGate(
- allocator: std.mem.Allocator,
- circuit: *QuantumCircuit,
- gate: Gate,
- gate_set: *const GateSet,
-) !void {
- _ = gate_set;
-
- // For qutrits, we can decompose most gates using:
- // 1. Any single-qutrit gate = sequence of rotations
- // 2. Use Gell-Mann matrices as basis
-
- switch (gate.ty) {
- .h => {
- // Hadamard-like: can use golden_rotation at Ο/2
- const params = try allocator.alloc(f64, 1);
- params[0] = std.math.pi / 2.0;
- const rot_gate = Gate{
- .ty = .golden_rotation,
- .params = params,
- .num_params = 1,
- .target = gate.target,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, rot_gate);
- },
- .s => {
- // Phase gate: golden_phase
- const params = try allocator.alloc(f64, 1);
- params[0] = std.math.pi / 2.0;
- const phase_gate = Gate{
- .ty = .golden_phase,
- .params = params,
- .num_params = 1,
- .target = gate.target,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, phase_gate);
- },
- .t => {
- // Ο/8 equivalent: sequence of two phase gates
- const params = try allocator.alloc(f64, 1);
- params[0] = std.math.pi / 4.0;
- const phase_gate = Gate{
- .ty = .golden_phase,
- .params = params,
- .num_params = 1,
- .target = gate.target,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, phase_gate);
- },
- else => {
- // For other gates, try to approximate with rotation
- if (gate.params.len > 0) {
- const params = try allocator.alloc(f64, 1);
- params[0] = gate.params[0];
- const rot_gate = Gate{
- .ty = .golden_rotation,
- .params = params,
- .num_params = 1,
- .target = gate.target,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, rot_gate);
- }
- },
- }
-}
-
-/// Optimize circuit synthesis (A* search)
-pub fn optimizeCircuit(
- allocator: std.mem.Allocator,
- target: TargetUnitary,
- gate_set: GateSet,
- max_depth: usize,
- tolerance: f64,
-) !OptimizationResult {
- const start_time = std.time.nanoTimestamp();
-
- // A* search for optimal circuit decomposition
- // State: (circuit, achieved_unitary, g_cost, h_cost)
-
- var best_circuit: ?QuantumCircuit = null;
- var best_fidelity: f64 = 0;
-
- // Try greedy search: build circuit gate by gate
- var circuit = try QuantumCircuit.init(allocator, 1);
- errdefer if (best_circuit) |*c| c.deinit();
-
- var iterations: usize = 0;
- const max_iterations = 1000;
-
- while (iterations < max_iterations) : (iterations += 1) {
- // Try adding each gate type
- for (gate_set.single_qutrit) |gate_ty| {
- // Create gate with random parameter
- const params = try allocator.alloc(f64, 1);
- params[0] = std.math.pi * (@as(f64, @floatFromInt(iterations % 100))) / 50.0;
-
- const test_gate = Gate{
- .ty = gate_ty,
- .params = params,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
-
- // Create test circuit with this gate added
- var test_circuit = try QuantumCircuit.init(allocator, 1);
- defer test_circuit.deinit();
-
- // Copy existing gates
- for (circuit.gates) |g| {
- const g_params = try allocator.alloc(f64, g.params.len);
- @memcpy(g_params, g.params);
- const g_copy = Gate{
- .ty = g.ty,
- .params = g_params,
- .num_params = g.num_params,
- .target = g.target,
- .control = g.control,
- .matrix = null,
- };
- try test_circuit.addGate(allocator, g_copy);
- }
-
- try test_circuit.addGate(allocator, test_gate);
-
- // Check fidelity
- const fidelity = target.verify(test_circuit);
-
- if (fidelity > best_fidelity) {
- best_fidelity = fidelity;
- if (best_circuit) |*bc| bc.deinit();
- best_circuit = try QuantumCircuit.init(allocator, 1);
-
- // Copy gates
- for (test_circuit.gates) |g| {
- const g_params = try allocator.alloc(f64, g.params.len);
- @memcpy(g_params, g.params);
- const g_copy = Gate{
- .ty = g.ty,
- .params = g_params,
- .num_params = g.num_params,
- .target = g.target,
- .control = g.control,
- .matrix = null,
- };
- try best_circuit.?.addGate(allocator, g_copy);
- }
-
- // Check if we've reached target
- if (best_fidelity >= 1.0 - tolerance) {
- break;
- }
- }
- }
-
- // Update current circuit with best found
- if (best_circuit) |*bc| {
- circuit.deinit();
- circuit = try QuantumCircuit.init(allocator, 1);
- for (bc.gates) |g| {
- const g_params = try allocator.alloc(f64, g.params.len);
- @memcpy(g_params, g.params);
- const g_copy = Gate{
- .ty = g.ty,
- .params = g_params,
- .num_params = g.num_params,
- .target = g.target,
- .control = g.control,
- .matrix = null,
- };
- try circuit.addGate(allocator, g_copy);
- }
- }
-
- if (circuit.gates.len >= max_depth) break;
- }
-
- const end_time = std.time.nanoTimestamp();
- const elapsed = @as(f64, @floatFromInt(end_time - start_time)) / 1e9;
-
- const result = OptimizationResult{
- .circuit = if (best_circuit) |*bc| try bc.clone(allocator) else try QuantumCircuit.init(allocator, 1),
- .cost = CircuitCost{
- .gate_count = if (best_circuit) |*bc| bc.gates.len else 0,
- .depth = if (best_circuit) |*bc| bc.gates.len else 0,
- .fidelity = best_fidelity,
- .two_qutrit_count = 0,
- },
- .synthesis_time = elapsed,
- .method = try allocator.dupe(u8, "greedy_a_star"),
- .allocator = allocator,
- };
-
- return result;
-}
-
-/// Synthesize CGLMP Bell test circuit
-/// Target: maximize I3 violation (classical bound β€ 2)
-pub fn synthesizeCGLMP(
- allocator: std.mem.Allocator,
- violation_target: f64,
- num_measurements: usize,
-) !OptimizationResult {
- _ = num_measurements;
- _ = violation_target; // Used for target optimization in full implementation
-
- const start_time = std.time.nanoTimestamp();
-
- // Create circuit for CGLMP test
- const circuit = try QuantumCircuit.init(allocator, 2); // 2 qutrits
- errdefer circuit.deinit();
-
- // Use golden angle rotations for optimal violation
- // TRINITY predicted I3 = 2.4277 (violates classical bound of 2)
-
- // Add measurement preparation gates
- // (simplified - actual implementation would be more complex)
-
- const end_time = std.time.nanoTimestamp();
- const elapsed = @as(f64, @floatFromInt(end_time - start_time)) / 1e9;
-
- const result = OptimizationResult{
- .circuit = try circuit.clone(allocator),
- .cost = CircuitCost{
- .gate_count = 4,
- .depth = 4,
- .fidelity = 0.99,
- .two_qutrit_count = 2,
- },
- .synthesis_time = elapsed,
- .method = try allocator.dupe(u8, "cglmp_golden_angle"),
- .allocator = allocator,
- };
-
- return result;
-}
-
-/// Qutrit KAK decomposition (for two-qutrit unitaries)
-pub fn qutritKAKDecomposition(
- allocator: std.mem.Allocator,
- unitary: [9]Complex,
-) !QuantumCircuit {
- _ = unitary;
-
- // KAK decomposition for qutrits: U = (A1 β A2) Β· C Β· (A3 β A4)
- // where C is entangling gate (using Fourier transform), A are single-qutrit gates
- // For qutrits, the canonical decomposition uses SU(3) Cartan subalgebra
-
- var circuit = try QuantumCircuit.init(allocator, 2);
- errdefer circuit.deinit();
-
- // Simplified KAK: use golden rotations and controlled phase gates
- // A1: rotation on qutrit 1
- const params1 = try allocator.alloc(f64, 1);
- params1[0] = GOLDEN_ANGLE_DEG * std.math.pi / 180.0;
- const gate1 = Gate{
- .ty = .golden_rotation,
- .params = params1,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, gate1);
-
- // A2: rotation on qutrit 2
- const params2 = try allocator.alloc(f64, 1);
- params2[0] = GOLDEN_ANGLE_DEG * std.math.pi / 180.0;
- const gate2 = Gate{
- .ty = .golden_rotation,
- .params = params2,
- .num_params = 1,
- .target = 1,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, gate2);
-
- // C: entangling gate (controlled phase)
- const params3 = try allocator.alloc(f64, 1);
- params3[0] = std.math.pi / 3.0; // qutrit phase
- const gate3 = Gate{
- .ty = .controlled_phase,
- .params = params3,
- .num_params = 1,
- .target = 1,
- .control = 0,
- .matrix = null,
- };
- try circuit.addGate(allocator, gate3);
-
- // A3: fourier on qutrit 1
- const params4 = try allocator.alloc(f64, 1);
- params4[0] = 0;
- const gate4 = Gate{
- .ty = .fourier,
- .params = params4,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, gate4);
-
- // A4: fourier on qutrit 2
- const params5 = try allocator.alloc(f64, 1);
- params5[0] = 0;
- const gate5 = Gate{
- .ty = .fourier,
- .params = params5,
- .num_params = 1,
- .target = 1,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(allocator, gate5);
-
- return circuit;
-}
-
-/// Find parallel gate schedule
-pub fn gateParallelization(allocator: std.mem.Allocator, circuit: QuantumCircuit) !QuantumCircuit {
- // Build dependency graph and schedule gates in parallel
- // Gates can be parallel if they act on different qutrits
-
- var parallel = try QuantumCircuit.init(allocator, circuit.num_qutrits);
- errdefer parallel.deinit();
-
- // Group gates by layer (gates that can execute in parallel)
- var layer: usize = 0;
- var i: usize = 0;
-
- while (i < circuit.gates.len) {
- const current_gate = circuit.gates[i];
-
- // Check if we can add this gate to current layer
- var can_parallel = true;
-
- // Check if any gate in current layer conflicts
- for (parallel.gates) |pg| {
- // Gates conflict if they share a qutrit
- const conflict =
- (pg.target != null and current_gate.target != null and
- pg.target.? == current_gate.target.?) or
- (pg.control != null and current_gate.target != null and
- pg.control.? == current_gate.target.?) or
- (pg.target != null and current_gate.control != null and
- pg.target.? == current_gate.control.?);
-
- if (conflict) {
- can_parallel = false;
- break;
- }
- }
-
- if (can_parallel) {
- // Add to current layer
- const params = try allocator.alloc(f64, current_gate.params.len);
- @memcpy(params, current_gate.params);
- const gate_copy = Gate{
- .ty = current_gate.ty,
- .params = params,
- .num_params = current_gate.num_params,
- .target = current_gate.target,
- .control = current_gate.control,
- .matrix = null,
- };
- try parallel.addGate(allocator, gate_copy);
- i += 1;
- } else {
- // Start new layer (conceptually - we just add sequentially)
- // In practice, depth is calculated differently
- layer += 1;
- }
- }
-
- // DEFERRED (v12): Calculate actual parallel depth by tracking qutrit usage across layers
- // Requires: layer assignment algorithm, resource conflict detection
- return parallel;
-}
-
-//===========================================================================
-// Circuit Verification
-//===========================================================================
-
-/// Verify unitary matches target (within global phase)
-pub fn verifyUnitary(
- target: TargetUnitary,
- circuit: QuantumCircuit,
-) f64 {
- return target.verify(circuit);
-}
-
-/// Check if circuit is valid (unitary gates)
-pub fn validateCircuit(circuit: QuantumCircuit) bool {
- _ = circuit;
- // DEFERRED (v12): Verify each gate is unitary (Uβ U = I)
- // Requires: gate unitary definitions, matrix multiplication
- return true;
-}
-
-//===========================================================================
-// Cost Metrics
-//===========================================================================
-
-/// Calculate circuit cost
-pub fn calculateCost(circuit: QuantumCircuit) CircuitCost {
- var cost = CircuitCost.init();
- cost.gate_count = circuit.gates.len;
- cost.depth = circuit.depth;
-
- // Count two-qutrit gates
- for (circuit.gates) |gate| {
- if (gate.control != null) {
- cost.two_qutrit_count += 1;
- }
- }
-
- // DEFERRED (v12): Calculate fidelity based on decomposition error
- // Requires: comparison to target unitary, global phase invariance
- cost.fidelity = 1.0;
-
- return cost;
-}
-
-//===========================================================================
-// Tests
-//===========================================================================
-
-test "CircuitCost initialization" {
- const cost = CircuitCost.init();
- try std.testing.expectEqual(@as(usize, 0), cost.gate_count);
- try std.testing.expectEqual(@as(usize, 0), cost.depth);
- try std.testing.expectApproxEqAbs(1.0, cost.fidelity, 1e-10);
-}
-
-test "CircuitCost score calculation" {
- const cost = CircuitCost{
- .gate_count = 10,
- .depth = 5,
- .fidelity = 0.95,
- .two_qutrit_count = 2,
- };
-
- const weights = [_]f64{ 1.0, 0.5, 10.0, 2.0 };
- const score = cost.score(weights);
-
- try std.testing.expect(score > 0);
-}
-
-test "QuantumCircuit initialization" {
- var circuit = try QuantumCircuit.init(std.testing.allocator, 2);
- defer circuit.deinit();
-
- try std.testing.expectEqual(@as(usize, 2), circuit.num_qutrits);
- try std.testing.expectEqual(@as(usize, 0), circuit.gates.len);
-}
-
-test "GateSet default initialization" {
- const gate_set = try GateSet.initDefault(std.testing.allocator);
- _ = gate_set;
- try std.testing.expect(true);
-}
-
-test "OptimizeCircuit returns result structure" {
- const target = TargetUnitary{
- .matrix = [_]Complex{
- .{ .re = 1, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 1, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 1, .im = 0 },
- },
- };
-
- const gate_set = try GateSet.initDefault(std.testing.allocator);
-
- var result = try optimizeCircuit(
- std.testing.allocator,
- target,
- gate_set,
- 10,
- 1e-6,
- );
- defer result.deinit();
-
- try std.testing.expect(result.synthesis_time >= 0);
-}
-
-test "SimplifyCircuit removes identity gates" {
- var circuit = try QuantumCircuit.init(std.testing.allocator, 1);
- defer circuit.deinit();
-
- // Add identity rotation (angle = 0)
- var params1 = try std.testing.allocator.alloc(f64, 1);
- params1[0] = 0;
- const gate1 = Gate{
- .ty = .golden_rotation,
- .params = params1,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(std.testing.allocator, gate1);
-
- // Add non-zero rotation
- var params2 = try std.testing.allocator.alloc(f64, 1);
- params2[0] = std.math.pi / 4.0;
- const gate2 = Gate{
- .ty = .golden_rotation,
- .params = params2,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(std.testing.allocator, gate2);
-
- var simplified = try simplifyCircuit(std.testing.allocator, circuit);
- defer simplified.deinit();
-
- // Should have only 1 gate (identity removed)
- try std.testing.expectEqual(@as(usize, 1), simplified.gates.len);
-}
-
-test "ConvertToNativeGates decomposes non-native gates" {
- var circuit = try QuantumCircuit.init(std.testing.allocator, 1);
- defer circuit.deinit();
-
- // Add H gate (not native)
- var params = try std.testing.allocator.alloc(f64, 1);
- params[0] = std.math.pi / 2.0;
- const gate = Gate{
- .ty = .h,
- .params = params,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(std.testing.allocator, gate);
-
- const gate_set = try GateSet.initDefault(std.testing.allocator);
- var native = try convertToNativeGates(std.testing.allocator, circuit, gate_set);
- defer native.deinit();
-
- // H should be converted to golden_rotation
- try std.testing.expect(native.gates.len > 0);
-}
-
-test "QutritKAKDecomposition creates valid circuit" {
- const unitary = [_]Complex{
- .{ .re = 1, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 1, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 0, .im = 0 },
- .{ .re = 1, .im = 0 },
- };
-
- var circuit = try qutritKAKDecomposition(std.testing.allocator, unitary);
- defer circuit.deinit();
-
- try std.testing.expectEqual(@as(usize, 2), circuit.num_qutrits);
- try std.testing.expect(circuit.gates.len >= 4); // A1, A2, C, A3, A4
-}
-
-test "GateParallelization handles independent gates" {
- var circuit = try QuantumCircuit.init(std.testing.allocator, 2);
- defer circuit.deinit();
-
- // Add gate on qutrit 0
- var params1 = try std.testing.allocator.alloc(f64, 1);
- params1[0] = std.math.pi / 4.0;
- const gate1 = Gate{
- .ty = .golden_rotation,
- .params = params1,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(std.testing.allocator, gate1);
-
- // Add gate on qutrit 1 (can parallelize)
- var params2 = try std.testing.allocator.alloc(f64, 1);
- params2[0] = std.math.pi / 4.0;
- const gate2 = Gate{
- .ty = .golden_rotation,
- .params = params2,
- .num_params = 1,
- .target = 1,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(std.testing.allocator, gate2);
-
- var parallel = try gateParallelization(std.testing.allocator, circuit);
- defer parallel.deinit();
-
- // Both gates should be in the circuit
- try std.testing.expect(parallel.gates.len >= 2);
-}
-
-test "Circuit clone produces independent copy" {
- var circuit = try QuantumCircuit.init(std.testing.allocator, 1);
- defer circuit.deinit();
-
- var params = try std.testing.allocator.alloc(f64, 1);
- params[0] = std.math.pi / 4.0;
- const gate = Gate{
- .ty = .golden_rotation,
- .params = params,
- .num_params = 1,
- .target = 0,
- .control = null,
- .matrix = null,
- };
- try circuit.addGate(std.testing.allocator, gate);
-
- var cloned = try circuit.clone(std.testing.allocator);
- defer cloned.deinit();
-
- try std.testing.expectEqual(circuit.gates.len, cloned.gates.len);
-}
diff --git a/src/quantum/sacred_wave.zig b/src/quantum/sacred_wave.zig
deleted file mode 100644
index 7828c47507..0000000000
--- a/src/quantum/sacred_wave.zig
+++ /dev/null
@@ -1,448 +0,0 @@
-//! SACRED WAVE FUNCTION β Bayesian Prior over Ξ_sacred
-//!
-//! Ο(ΞΈ) = Ξ£ Ξ±α΅’|configα΅’β© where Ξ±α΅’ = probability amplitude
-//!
-//! Interpretation:
-//! - Amplitudes Ο(ΞΈ) = posterior weights after measurements
-//! - measure_and_update = Bayesian update on categorical distribution
-//! - collapse = sampling from |Ο|Β² (Born rule)
-//! - Equivalent to classical Bayesian optimization on discrete lattice
-//!
-//! References:
-//! - [YouTube BO latent] β Bayesian Optimization in Latent Spaces
-//! - [arXiv 2510.27091 v1] β Prioritized Policy Optimization
-//! - [PMLR Deshwal23a] β Bayesian optimization for categorical spaces
-//!
-//! ΟΒ² + 1/ΟΒ² = 3 = TRINITY
-
-const std = @import("std");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// ΟΒ² = 2.6180339887498948482...
-pub const PHI_SQ: f64 = PHI * PHI;
-
-/// Οβ»ΒΉ = 0.6180339887498948...
-pub const PHI_INV: f64 = 1.0 / PHI;
-
-/// TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI_SQ + 1.0 / PHI_SQ;
-
-/// Number of sacred configurations (Ξ_sacred space size)
-/// For HSLM: 6.75M configurations (3^15 based on sacred params)
-pub const SACRED_SPACE_SIZE: usize = 6_750_000;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED WAVE FUNCTION
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Wave function over Ξ_sacred (6.75M sacred configurations)
-/// Ο(ΞΈ) = Ξ£ Ξ±α΅’|configα΅’β© where Ξ±α΅’ = probability amplitude
-///
-/// Interpretation:
-/// - Amplitudes Ο(ΞΈ) = posterior weights after measurements
-/// - measure_and_update = Bayesian update on categorical distribution
-/// - collapse = sampling from |Ο|Β² (Born rule)
-/// - Equivalent to classical Bayesian optimization on discrete lattice
-///
-/// References: [YouTube BO latent], [arXiv 2510.27091], [PMLR Deshwal23a]
-pub const SacredWaveFunction = struct {
- allocator: std.mem.Allocator,
- /// Probability amplitudes for each sacred config (|Ο|Β² sums to 1)
- amplitudes: []f64,
- /// Which configs have been measured (bitmask)
- measured: []bool,
- /// Total number of measurements performed
- measurements: usize = 0,
- /// Best PPL observed so far
- best_ppl: f64 = std.math.inf(f64),
- /// Index of best configuration
- best_config: usize = 0,
- /// Inverse temperature Ξ² for Bayesian updates
- /// Higher Ξ² = stronger response to PPL improvements
- beta: f64 = 1.0,
- /// Measured PPL values for likelihood computation
- measured_ppl: []f64,
-
- /// Initialize uniform superposition (all configs equally probable)
- pub fn initUniform(allocator: std.mem.Allocator, num_configs: usize) !SacredWaveFunction {
- const amplitudes = try allocator.alloc(f64, num_configs);
- const measured = try allocator.alloc(bool, num_configs);
- const measured_ppl = try allocator.alloc(f64, num_configs);
- const uniform_amp = 1.0 / @sqrt(@as(f64, @floatFromInt(num_configs)));
- @memset(amplitudes, uniform_amp);
- @memset(measured, false);
- @memset(measured_ppl, std.math.inf(f64));
-
- return .{
- .allocator = allocator,
- .amplitudes = amplitudes,
- .measured = measured,
- .measured_ppl = measured_ppl,
- .beta = 1.0,
- };
- }
-
- /// Initialize with prior beliefs (non-uniform amplitudes)
- pub fn initWithPrior(allocator: std.mem.Allocator, amplitudes: []f64) !SacredWaveFunction {
- const copied = try allocator.alloc(f64, amplitudes.len);
- const measured = try allocator.alloc(bool, amplitudes.len);
- const measured_ppl = try allocator.alloc(f64, amplitudes.len);
- @memcpy(copied, amplitudes);
- @memset(measured, false);
- @memset(measured_ppl, std.math.inf(f64));
-
- // Normalize amplitudes
- var total_prob: f64 = 0.0;
- for (amplitudes) |amp| {
- total_prob += amp * amp;
- }
- const norm_factor = if (total_prob > 0) 1.0 / @sqrt(total_prob) else 1.0;
-
- for (copied) |*amp| {
- amp.* *= norm_factor;
- }
-
- return .{
- .allocator = allocator,
- .amplitudes = copied,
- .measured = measured,
- .measured_ppl = measured_ppl,
- .beta = 1.0,
- };
- }
-
- /// Initialize from previous measurements (experience replay)
- pub fn initFromExperience(
- allocator: std.mem.Allocator,
- experiences: []const struct { config_idx: usize, ppl: f64 },
- num_configs: usize,
- ) !SacredWaveFunction {
- var wave = try initUniform(allocator, num_configs);
-
- // Update with all past experiences
- for (experiences) |exp| {
- _ = try wave.measureAndUpdate(exp.config_idx, exp.ppl);
- }
-
- return wave;
- }
-
- /// Collapse to single configuration via Born rule sampling
- /// Samples from |Ο|Β² distribution, returns chosen config index
- pub fn collapse(self: *const SacredWaveFunction, rng: anytype) usize {
- // Sample from categorical distribution defined by |Ο|Β²
- const u = rng.random().float(f64);
- var cumulative: f64 = 0.0;
- for (self.amplitudes, 0..) |amp, i| {
- cumulative += amp * amp; // |Ο|Β²
- if (u <= cumulative) return i;
- }
- return self.amplitudes.len - 1;
- }
-
- /// Collapse to best configuration (greedy, not stochastic)
- /// Always selects config with highest |Ο|Β² (most probable)
- pub fn collapseGreedy(self: *const SacredWaveFunction) usize {
- var max_prob: f64 = 0.0;
- var best_idx: usize = 0;
-
- for (self.amplitudes, 0..) |amp, i| {
- const prob = amp * amp;
- if (prob > max_prob) {
- max_prob = prob;
- best_idx = i;
- }
- }
-
- return best_idx;
- }
-
- /// Bayesian update after measurement
- /// P(ΞΈ|data) β P(data|ΞΈ) Γ P(ΞΈ)
- /// Lower PPL β higher amplitude (better config more probable)
- pub fn measureAndUpdate(self: *SacredWaveFunction, config_idx: usize, ppl: f64) !void {
- self.measurements += 1;
- self.measured[config_idx] = true;
- self.measured_ppl[config_idx] = ppl;
-
- // Update best if improved
- if (ppl < self.best_ppl or !std.math.isFinite(self.best_ppl)) {
- self.best_ppl = ppl;
- self.best_config = config_idx;
- }
-
- // Recalculate all amplitudes based on measured configs
- // Unmeasured configs get zero probability (or small exploration epsilon)
- const epsilon: f64 = 0.001; // Small probability for unmeasured configs
-
- var total_likelihood: f64 = 0.0;
- for (self.measured, self.measured_ppl) |is_measured, mppl| {
- if (is_measured) {
- total_likelihood += @exp(-self.beta * mppl);
- } else {
- total_likelihood += epsilon;
- }
- }
-
- const scale = 1.0 / @sqrt(total_likelihood);
- for (self.amplitudes, self.measured, self.measured_ppl) |*amp, is_measured, mppl| {
- if (is_measured) {
- amp.* = @exp(-self.beta * mppl) * scale;
- } else {
- amp.* = epsilon * scale;
- }
- }
- }
-
- /// Renormalize amplitudes so Ξ£|Ο|Β² = 1
- fn normalize(self: *SacredWaveFunction) !void {
- var total_prob: f64 = 0.0;
- for (self.amplitudes) |amp| {
- total_prob += amp * amp;
- }
-
- if (total_prob <= 0) {
- // Fallback: uniform distribution
- const uniform_amp = 1.0 / @sqrt(@as(f64, @floatFromInt(self.amplitudes.len)));
- @memset(self.amplitudes, uniform_amp);
- return;
- }
-
- const scale = 1.0 / @sqrt(total_prob);
- for (self.amplitudes) |*amp| {
- amp.* *= scale;
- }
- }
-
- /// Set inverse temperature Ξ² (controls exploration vs exploitation)
- /// Higher Ξ² = more greedy (exploit known good configs)
- /// Lower Ξ² = more explorative (try new configs)
- pub fn setTemperature(self: *SacredWaveFunction, beta: f64) void {
- self.beta = @max(0.01, beta);
- }
-
- /// Score structure for top configurations
- pub const ConfigScore = struct {
- idx: usize,
- prob: f64,
- };
-
- /// Get probability for a specific configuration
- /// P(ΞΈα΅’) = |Οα΅’|Β²
- pub fn probability(self: *const SacredWaveFunction, config_idx: usize) f64 {
- if (config_idx >= self.amplitudes.len) return 0.0;
- return self.amplitudes[config_idx] * self.amplitudes[config_idx];
- }
-
- /// Get top N configurations by probability
- /// Returns array of {idx, probability} tuples
- pub fn topConfigs(self: *const SacredWaveFunction, allocator: std.mem.Allocator, n: usize) ![]ConfigScore {
- var result = try allocator.alloc(ConfigScore, @min(n, self.amplitudes.len));
-
- for (self.amplitudes, 0..) |amp, i| {
- const prob = amp * amp;
-
- // Insert into result using insertion sort (small N)
- var j = @min(i, result.len);
- while (j > 0 and result[j - 1].prob < prob) : (j -= 1) {}
-
- if (j < result.len) {
- // Shift elements
- var k = j;
- while (k < result.len - 1) : (k += 1) {
- result[k + 1] = result[k];
- }
-
- result[j] = .{ .idx = i, .prob = prob };
- }
- }
-
- return result;
- }
-
- /// Compute Shannon entropy of current distribution
- /// S = -Ξ£ |Οα΅’|Β² logβ|Οα΅’|Β²
- pub fn entropy(self: *const SacredWaveFunction) f64 {
- var s: f64 = 0.0;
- for (self.amplitudes) |amp| {
- const prob = amp * amp;
- if (prob > 1e-10) {
- s -= prob * std.math.log2(prob);
- }
- }
- return s;
- }
-
- /// Check if wave function is collapsed (entropy near zero)
- /// Collapsed = single config dominates (entropy < threshold)
- pub fn isCollapsed(self: *const SacredWaveFunction, threshold: f64) bool {
- const ent = self.entropy();
- return ent < threshold;
- }
-
- /// Get collapse temperature (when wave function collapses due to repeated measurement)
- /// Higher measurements = higher collapse probability (Quantum Zeno)
- pub fn collapseTemperature(self: *const SacredWaveFunction) f64 {
- // Estimate based on measurements and entropy
- // More measurements with same config β lower entropy β more collapsed
- const max_entropy = std.math.log2(@as(f64, @floatFromInt(self.amplitudes.len)));
- const current_entropy = self.entropy();
- const collapse_ratio = 1.0 - (current_entropy / max_entropy);
-
- // Temperature drops as wave collapses
- return @max(0.01, 1.0 - collapse_ratio * PHI_INV);
- }
-
- /// Cleanup
- pub fn deinit(self: *SacredWaveFunction) void {
- self.allocator.free(self.amplitudes);
- self.allocator.free(self.measured);
- self.allocator.free(self.measured_ppl);
- }
-
- /// Format summary for display
- pub fn formatSummary(self: *const SacredWaveFunction, writer: anytype) !void {
- try writer.print("SacredWaveFunction Summary:\n", .{});
- try writer.print(" Total measurements: {d}\n", .{self.measurements});
- try writer.print(" Best PPL: {d:.2}\n", .{self.best_ppl});
- try writer.print(" Best config index: {d}\n", .{self.best_config});
- try writer.print(" Entropy: {d:.4} bits\n", .{self.entropy()});
- try writer.print(" Inverse temperature Ξ²: {d:.3}\n", .{self.beta});
- try writer.print(" Collapse temperature: {d:.4}\n", .{self.collapseTemperature()});
- try writer.print(" State: {s}\n", .{if (self.isCollapsed(0.1)) "COLLAPSED" else "SUPERPOSITION"});
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const testing = std.testing;
-
-test "SacredWaveFunction initUniform normalizes correctly" {
- const num_configs = 100;
- var wave = try SacredWaveFunction.initUniform(testing.allocator, num_configs);
- defer wave.deinit();
-
- // Check that |Ο|Β² sums to 1
- var total_prob: f64 = 0.0;
- for (wave.amplitudes) |amp| {
- total_prob += amp * amp;
- }
-
- try testing.expectApproxEqAbs(@as(f64, 1.0), total_prob, 1e-6);
-}
-
-test "SacredWaveFunction collapse samples correctly" {
- var wave = try SacredWaveFunction.initUniform(testing.allocator, 10);
- defer wave.deinit();
-
- var rng = std.Random.DefaultPrng.init(42);
- const idx = wave.collapse(&rng);
-
- try testing.expect(idx >= 0 and idx < 10);
-}
-
-test "SacredWaveFunction measureAndUpdate updates correctly" {
- var wave = try SacredWaveFunction.initUniform(testing.allocator, 10);
- defer wave.deinit();
-
- // Initial best is inf
- try testing.expect(!std.math.isFinite(wave.best_ppl));
-
- // Update with some measurements
- try wave.measureAndUpdate(0, 10.0);
- try testing.expectEqual(@as(usize, 1), wave.measurements);
- try testing.expectApproxEqAbs(@as(f64, 10.0), wave.best_ppl, 1e-6);
-
- try wave.measureAndUpdate(1, 20.0);
- try wave.measureAndUpdate(2, 5.0);
-
- // Config 2 should be best (lowest PPL)
- try testing.expectEqual(@as(usize, 3), wave.measurements);
- try testing.expectApproxEqAbs(@as(f64, 5.0), wave.best_ppl, 1e-6);
- try testing.expectEqual(@as(usize, 2), wave.best_config);
-}
-
-test "SacredWaveFunction entropy calculation" {
- var wave = try SacredWaveFunction.initUniform(testing.allocator, 4);
- defer wave.deinit();
-
- // Uniform distribution should have max entropy = log2(4) = 2
- const entropy = wave.entropy();
- try testing.expectApproxEqAbs(@as(f64, 2.0), entropy, 0.01);
-}
-
-test "SacredWaveFunction isCollapsed detection" {
- // Uniform = not collapsed
- var uniform = try SacredWaveFunction.initUniform(testing.allocator, 4);
- defer uniform.deinit();
-
- try testing.expect(!uniform.isCollapsed(0.1));
-
- // Peaked = collapsed
- var amplitudes = [_]f64{ 0.0, 0.0, 1.0, 0.0 };
- var peaked = try SacredWaveFunction.initWithPrior(testing.allocator, &litudes);
- defer peaked.deinit();
-
- try testing.expect(peaked.isCollapsed(0.1));
-}
-
-test "SacredWaveFunction topConfigs returns sorted" {
- var wave = try SacredWaveFunction.initUniform(testing.allocator, 10);
- defer wave.deinit();
-
- // Update configs: lower PPL should get higher probability
- try wave.measureAndUpdate(0, 5.0);
- try wave.measureAndUpdate(1, 3.0); // Best PPL
- try wave.measureAndUpdate(2, 7.0);
- try wave.measureAndUpdate(3, 10.0);
-
- const top3 = try wave.topConfigs(testing.allocator, 3);
- defer testing.allocator.free(top3);
-
- try testing.expectEqual(@as(usize, 3), top3.len);
-
- // Should be sorted by probability (descending)
- try testing.expect(top3[0].prob >= top3[1].prob);
- try testing.expect(top3[1].prob >= top3[2].prob);
-
- // Config 1 should be first (best PPL = 3.0)
- try testing.expectEqual(@as(usize, 1), top3[0].idx);
-}
-
-test "SacredWaveFunction setTemperature affects exploration" {
- var wave = try SacredWaveFunction.initUniform(testing.allocator, 10);
- defer wave.deinit();
-
- // Set high temperature (more explorative)
- wave.setTemperature(0.1);
- try testing.expectApproxEqAbs(@as(f64, 0.1), wave.beta, 1e-6);
-
- // Set low temperature (more greedy)
- wave.setTemperature(10.0);
- try testing.expectApproxEqAbs(@as(f64, 10.0), wave.beta, 1e-6);
-
- // Test min bound
- wave.setTemperature(0.001);
- try testing.expectApproxEqAbs(@as(f64, 0.01), wave.beta, 1e-6);
-}
-
-test "TRINITY identity holds" {
- try testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-test "PHI_INV calculation" {
- try testing.expectApproxEqRel(PHI_INV, 1.0 / PHI, 1e-10);
- try testing.expectApproxEqAbs(@as(f64, 0.618), PHI_INV, 0.001);
-}
-
-// Version info
-pub const VERSION = "1.0.0";
-pub const MODULE_NAME = "SACRED WAVE FUNCTION";
diff --git a/src/quantum/tensor_networks.zig b/src/quantum/tensor_networks.zig
deleted file mode 100644
index 035b984ed2..0000000000
--- a/src/quantum/tensor_networks.zig
+++ /dev/null
@@ -1,853 +0,0 @@
-//! Tensor Networks for Ternary Quantum States
-//!
-//! Implements Matrix Product States (MPS) and Projected Entangled Pair States (PEPS)
-//! for efficient representation of qutrit many-body states.
-//!
-//! Mathematical foundation:
-//! - Ternary tensors: elements in {-1, 0, +1}
-//! - MPS compression via SVD
-//! - TEBD time evolution
-//! - DMRG optimization
-
-const std = @import("std");
-const math = std.math;
-const e8 = @import("e8_root_system.zig");
-
-//===========================================================================
-// Constants
-//===========================================================================
-
-pub const TRIT_VALUES = [_]i2{ -1, 0, 1 };
-pub const NUM_TRIT_STATES: usize = 3;
-
-//===========================================================================
-// Types
-//===========================================================================
-
-/// Trit value (balanced ternary digit)
-pub const Trit = enum(i2) {
- neg = -1,
- zero = 0,
- pos = 1,
-
- pub fn toInt(self: Trit) i2 {
- return @intFromEnum(self);
- }
-
- pub fn toFloat(self: Trit) f64 {
- return @floatFromInt(self.toInt());
- }
-
- pub fn fromInt(value: i2) !Trit {
- return switch (value) {
- -1 => .neg,
- 0 => .zero,
- 1 => .pos,
- else => error.InvalidTrit,
- };
- }
-};
-
-/// Complex number (since std.math.Complex might not be available)
-pub const Complex = struct {
- re: f64,
- im: f64,
-
- pub fn init(re: f64, im: f64) Complex {
- return .{ .re = re, .im = im };
- }
-
- pub fn fromReal(r: f64) Complex {
- return .{ .re = r, .im = 0 };
- }
-
- pub fn add(a: Complex, b: Complex) Complex {
- return .{ .re = a.re + b.re, .im = a.im + b.im };
- }
-
- pub fn sub(a: Complex, b: Complex) Complex {
- return .{ .re = a.re - b.re, .im = a.im - b.im };
- }
-
- pub fn mul(a: Complex, b: Complex) Complex {
- return .{
- .re = a.re * b.re - a.im * b.im,
- .im = a.re * b.im + a.im * b.re,
- };
- }
-
- pub fn scale(c: Complex, s: f64) Complex {
- return .{ .re = c.re * s, .im = c.im * s };
- }
-
- pub fn conj(c: Complex) Complex {
- return .{ .re = c.re, .im = -c.im };
- }
-
- pub fn absSquared(c: Complex) f64 {
- return c.re * c.re + c.im * c.im;
- }
-
- pub fn abs(c: Complex) f64 {
- return math.sqrt(c.absSquared());
- }
-};
-
-/// Matrix Product State tensor A^{s}_{Ξ±Ξ²}
-/// Dimensions: (bond_dim, physical_dim=3, bond_dim)
-pub const MPSTensor = struct {
- data: []Complex,
- bond_dim: usize,
- allocator: std.mem.Allocator,
-
- pub fn init(allocator: std.mem.Allocator, bond_dim: usize) !MPSTensor {
- const size = bond_dim * NUM_TRIT_STATES * bond_dim;
- const data = try allocator.alloc(Complex, size);
- @memset(data, Complex.fromReal(0));
- return MPSTensor{
- .data = data,
- .bond_dim = bond_dim,
- .allocator = allocator,
- };
- }
-
- pub fn deinit(self: *MPSTensor) void {
- self.allocator.free(self.data);
- }
-
- pub fn index(self: *const MPSTensor, alpha: usize, s: usize, beta: usize) *Complex {
- const idx = (alpha * NUM_TRIT_STATES + s) * self.bond_dim + beta;
- return &self.data[idx];
- }
-
- pub fn get(self: *const MPSTensor, alpha: usize, s: usize, beta: usize) Complex {
- return self.index(alpha, s, beta).*;
- }
-
- pub fn set(self: *MPSTensor, alpha: usize, s: usize, beta: usize, value: Complex) void {
- self.index(alpha, s, beta).* = value;
- }
-};
-
-/// Matrix Product State
-pub const MPS = struct {
- tensors: []MPSTensor,
- num_sites: usize,
- bond_dim: usize,
- center: usize,
- allocator: std.mem.Allocator,
-
- pub fn init(allocator: std.mem.Allocator, num_sites: usize, bond_dim: usize) !MPS {
- const tensors = try allocator.alloc(MPSTensor, num_sites);
- errdefer allocator.free(tensors);
-
- for (tensors) |*t| {
- t.* = try MPSTensor.init(allocator, bond_dim);
- }
-
- return MPS{
- .tensors = tensors,
- .num_sites = num_sites,
- .bond_dim = bond_dim,
- .center = 0,
- .allocator = allocator,
- };
- }
-
- pub fn deinit(self: *MPS) void {
- for (self.tensors) |*t| {
- t.deinit();
- }
- self.allocator.free(self.tensors);
- }
-
- /// Initialize as product state |+1β©|+1β©...|+1β©
- pub fn initPlusState(self: *MPS) !void {
- for (self.tensors, 0..) |*tensor, site| {
- // Left boundary: A^{+1}_{00} = 1
- if (site == 0) {
- tensor.set(0, 2, 0, Complex.fromReal(1)); // |+1β© = index 2
- }
- // Right boundary: A^{+1}_{00} = 1
- else if (site == self.num_sites - 1) {
- tensor.set(0, 2, 0, Complex.fromReal(1));
- }
- // Bulk: identity
- else {
- tensor.set(0, 2, 0, Complex.fromReal(1));
- }
- }
- }
-
- /// Initialize as equal superposition |+++β© + |000β© + |---β© normalized
- pub fn initSuperposition(self: *MPS) !void {
- const amp = 1.0 / math.sqrt(3.0);
- for (self.tensors, 0..) |*tensor, site| {
- if (site == 0 or site == self.num_sites - 1) {
- // |+1β©
- tensor.set(0, 2, 0, Complex.fromReal(amp));
- // |0β©
- tensor.set(0, 1, 0, Complex.fromReal(amp));
- // |-1β©
- tensor.set(0, 0, 0, Complex.fromReal(amp));
- }
- }
- }
-
- /// Contract full MPS to state vector
- pub fn contract(self: *const MPS, allocator: std.mem.Allocator) ![]Complex {
- const dim = math.pow(usize, NUM_TRIT_STATES, self.num_sites);
- const state = try allocator.alloc(Complex, dim);
- errdefer allocator.free(state);
- @memset(state, Complex.fromReal(0));
-
- // For small systems, do full contraction
- if (self.num_sites <= 10) {
- try self.contractFull(state);
- }
-
- return state;
- }
-
- fn contractFull(self: *const MPS, state: []Complex) !void {
- const dim = state.len;
- for (0..dim) |idx| {
- var value = Complex.fromReal(1);
- var temp_idx = idx;
-
- for (0..self.num_sites) |site| {
- const trit_val = temp_idx % NUM_TRIT_STATES;
- temp_idx /= NUM_TRIT_STATES;
-
- // Get tensor element A^{trit_val}_{00} (bond dim 1)
- const tensor = &self.tensors[site];
- const elem = tensor.get(0, trit_val, 0);
- value = Complex.mul(value, elem);
- }
-
- state[idx] = value;
- }
- }
-};
-
-/// Singular Value Decomposition for MPS compression
-pub const SVDResult = struct {
- U: []Complex,
- S: []f64,
- V: []Complex,
- allocator: std.mem.Allocator,
-
- pub fn init(allocator: std.mem.Allocator, m: usize, n: usize) !SVDResult {
- const min_mn = if (m < n) m else n;
- const U = try allocator.alloc(Complex, m * min_mn);
- const S = try allocator.alloc(f64, min_mn);
- const V = try allocator.alloc(Complex, n * min_mn);
-
- return SVDResult{
- .U = U,
- .S = S,
- .V = V,
- .allocator = allocator,
- };
- }
-
- pub fn deinit(self: *SVDResult) void {
- self.allocator.free(self.U);
- self.allocator.free(self.S);
- self.allocator.free(self.V);
- }
-};
-
-/// MPS Compression via SVD
-/// Reshapes state vector into matrix and performs SVD for compression
-pub fn compressMPS(
- allocator: std.mem.Allocator,
- state: []Complex,
- num_sites: usize,
- bond_dim: usize,
- tolerance: f64,
-) !MPS {
- var mps = try MPS.init(allocator, num_sites, bond_dim);
- errdefer mps.deinit();
-
- // For small systems, use iterative SVD compression
- // Start from right and sweep left, then sweep right
- const state_copy = try allocator.alloc(Complex, state.len);
- defer allocator.free(state_copy);
- @memcpy(state_copy, state);
-
- // Right-to-left sweep (compress from right boundary)
- var current_dim: usize = 1;
- for (0..num_sites - 1) |site_idx| {
- const site = num_sites - 1 - site_idx;
-
- // Reshape: (3^(site+1)) β (3 Γ 3^site)
- const rows = NUM_TRIT_STATES;
- const cols = math.pow(usize, NUM_TRIT_STATES, @as(usize, @intCast(site)));
-
- // Extract matrix for this site
- var matrix = try allocator.alloc(Complex, rows * cols);
- defer allocator.free(matrix);
-
- const start_idx = state_copy.len - rows * cols;
- for (0..rows * cols) |i| {
- matrix[i] = state_copy[start_idx + i];
- }
-
- // Perform SVD
- var svd_result = try svd(allocator, matrix, rows, cols);
- defer svd_result.deinit();
-
- // Truncate to bond_dim
- const new_bond = @min(bond_dim, svd_result.S.len);
- var truncated = try truncateSVD(allocator, &svd_result, new_bond, tolerance);
- defer truncated.deinit();
-
- // Update current dimension
- current_dim = new_bond;
-
- // Update state size for next iteration
- // (simplified - in practice would reconstruct state)
- }
-
- // Initialize MPS with SVD-compressed tensors
- for (0..num_sites) |site| {
- const tensor = &mps.tensors[site];
-
- // For boundary sites, bond dim = 1
- const left_dim = if (site == 0) 1 else bond_dim;
- const right_dim = if (site == num_sites - 1) 1 else bond_dim;
-
- // Initialize from compressed state (simplified)
- const amp = 1.0 / @sqrt(@as(f64, @floatFromInt(NUM_TRIT_STATES)));
- for (0..left_dim) |alpha| {
- for (0..NUM_TRIT_STATES) |s| {
- for (0..right_dim) |beta| {
- // Initialize with equal superposition (will be replaced by actual SVD)
- tensor.set(alpha, s, beta, Complex.fromReal(amp));
- }
- }
- }
- }
-
- return mps;
-}
-
-/// Perform Singular Value Decomposition: A = UΒ·SΒ·Vβ
-/// Simplified SVD using power iteration with explicit orthogonalization
-pub fn svd(allocator: std.mem.Allocator, A: []Complex, m: usize, n: usize) !SVDResult {
- const min_mn = if (m < n) m else n;
- var result = try SVDResult.init(allocator, m, n);
- errdefer result.deinit();
-
- // Convert to real matrix (take real part - simplified for real symmetric matrices)
- var real_A = try allocator.alloc(f64, m * n);
- defer allocator.free(real_A);
-
- for (0..m * n) |i| {
- real_A[i] = A[i].re; // Use real part for SVD (sufficient for MPS)
- }
-
- // Store previous V vectors for orthogonalization
- var prev_Vs = try allocator.alloc([]f64, min_mn);
- defer {
- for (0..min_mn) |i| {
- if (i < result.S.len and result.S[i] > 1e-10) {
- allocator.free(prev_Vs[i]);
- }
- }
- allocator.free(prev_Vs);
- }
- @memset(prev_Vs, &[_]f64{});
-
- // For each singular value
- for (0..min_mn) |k| {
- // Initialize with different starting vector for each k
- var v = try allocator.alloc(f64, n);
- var v_owned = true; // Track ownership
- defer {
- if (v_owned) allocator.free(v);
- }
-
- const offset = @as(f64, @floatFromInt(k));
- for (0..n) |i| {
- v[i] = 1.0 + offset * 0.1 + @as(f64, @floatFromInt(i)) * 0.01;
- }
-
- // Orthogonalize against all previous V vectors
- for (0..k) |j| {
- if (prev_Vs[j].len > 0) {
- // Compute dot product
- var dot: f64 = 0;
- for (0..n) |i| {
- dot += v[i] * prev_Vs[j][i];
- }
- // Subtract projection
- for (0..n) |i| {
- v[i] -= dot * prev_Vs[j][i];
- }
- }
- }
-
- // Normalize
- {
- var norm_v: f64 = 0;
- for (v) |val| norm_v += val * val;
- norm_v = @sqrt(norm_v);
- if (norm_v < 1e-10) {
- // Vector became zero - all singular values extracted
- result.S[k] = 0;
- continue; // Continue to next iteration (defer will free v)
- }
- for (0..n) |i| v[i] /= norm_v;
- }
-
- // Power iteration to find dominant eigenvalue of A^T A
- var sigma: f64 = 0;
- var iter: usize = 0;
- const max_iter = 200;
-
- while (iter < max_iter) : (iter += 1) {
- // Compute A^T A v more efficiently
- // First compute Av
- var Av = try allocator.alloc(f64, m);
- defer allocator.free(Av);
-
- for (0..m) |i| {
- var sum: f64 = 0;
- for (0..n) |j| {
- sum += real_A[i * n + j] * v[j];
- }
- Av[i] = sum;
- }
-
- // Then compute A^T(Av)
- var AtAv = try allocator.alloc(f64, n);
- defer allocator.free(AtAv);
-
- for (0..n) |i| {
- var sum: f64 = 0;
- for (0..m) |j| {
- sum += real_A[j * n + i] * Av[j];
- }
- AtAv[i] = sum;
- }
-
- // Rayleigh quotient
- var numerator: f64 = 0;
- var denominator: f64 = 0;
- for (0..n) |i| {
- numerator += v[i] * AtAv[i];
- denominator += v[i] * v[i];
- }
- const new_sigma = if (denominator > 1e-15) @sqrt(@abs(numerator / denominator)) else 0;
-
- // Normalize and orthogonalize
- var norm: f64 = 0;
- for (AtAv) |val| norm += val * val;
- norm = @sqrt(norm);
-
- if (norm < 1e-10) {
- sigma = new_sigma;
- break;
- }
-
- // Update v
- for (0..n) |i| {
- v[i] = AtAv[i] / norm;
- }
-
- // Re-orthogonalize against previous vectors
- for (0..k) |j| {
- if (prev_Vs[j].len > 0) {
- var dot: f64 = 0;
- for (0..n) |i| {
- dot += v[i] * prev_Vs[j][i];
- }
- for (0..n) |i| {
- v[i] -= dot * prev_Vs[j][i];
- }
- }
- }
-
- // Renormalize
- {
- var norm_v: f64 = 0;
- for (v) |val| norm_v += val * val;
- norm_v = @sqrt(norm_v);
- if (norm_v > 1e-10) {
- for (0..n) |i| v[i] /= norm_v;
- }
- }
-
- // Check convergence
- if (@abs(new_sigma - sigma) < 1e-12) {
- sigma = new_sigma;
- break;
- }
-
- sigma = new_sigma;
- }
-
- // Ensure sigma is non-negative
- if (sigma < 0) sigma = 0;
- result.S[k] = sigma;
-
- // Store V column and save copy for orthogonalization
- for (0..n) |i| {
- result.V[i * min_mn + k] = Complex.fromReal(v[i]);
- }
-
- // Copy v for future orthogonalization
- if (sigma > 1e-10) {
- // Transfer ownership of v to prev_Vs (v won't be freed by defer)
- prev_Vs[k] = v;
- v_owned = false; // Ownership transferred
-
- // Note: we need to keep using the v values, so create an alias
- const v_for_compute = prev_Vs[k];
-
- // Compute U column: u = A * v / sigma
- for (0..m) |i| {
- var sum: f64 = 0;
- for (0..n) |j| {
- sum += real_A[i * n + j] * v_for_compute[j];
- }
- result.U[i * min_mn + k] = Complex.fromReal(sum / sigma);
- }
-
- // Deflate: A = A - sigma * u * v^T
- if (k < min_mn - 1) {
- for (0..m) |i| {
- for (0..n) |j| {
- const u_val = result.U[i * min_mn + k].re;
- real_A[i * n + j] -= sigma * u_val * v_for_compute[j];
- }
- }
- }
- }
- }
-
- return result;
-}
-
-/// Truncate SVD to given bond dimension or tolerance
-pub fn truncateSVD(allocator: std.mem.Allocator, svd_result: *const SVDResult, max_dim: usize, tol: f64) !SVDResult {
- // Find effective dimension based on tolerance
- var eff_dim: usize = 0;
- var total_sv: f64 = 0;
- for (svd_result.S) |s| total_sv += s;
-
- var cumsum: f64 = 0;
- for (svd_result.S, 0..) |s, i| {
- cumsum += s;
- eff_dim = i + 1;
- if (cumsum / total_sv > 1.0 - tol) break;
- }
-
- eff_dim = @min(eff_dim, max_dim);
- if (eff_dim == 0) eff_dim = 1;
-
- var result = try SVDResult.init(allocator, svd_result.U.len / svd_result.S.len, svd_result.V.len / svd_result.S.len);
- errdefer result.deinit();
-
- // Copy truncated values
- @memcpy(result.S[0..eff_dim], svd_result.S[0..eff_dim]);
-
- // Copy U and V columns
- const m = svd_result.U.len / svd_result.S.len;
- const n = svd_result.V.len / svd_result.S.len;
-
- for (0..m) |i| {
- for (0..eff_dim) |j| {
- result.U[i * eff_dim + j] = svd_result.U[i * svd_result.S.len + j];
- }
- }
-
- for (0..n) |i| {
- for (0..eff_dim) |j| {
- result.V[i * eff_dim + j] = svd_result.V[i * svd_result.S.len + j];
- }
- }
-
- return result;
-}
-
-/// Apply single-qutrit gate to MPS
-pub fn applySingleQutritGate(
- mps: *MPS,
- site: usize,
- gate: *const [NUM_TRIT_STATES][NUM_TRIT_STATES]Complex,
-) !void {
- if (site >= mps.num_sites) return error.InvalidSite;
-
- const tensor = &mps.tensors[site];
- var new_data = try mps.allocator.alloc(Complex, tensor.data.len);
- errdefer mps.allocator.free(new_data);
-
- // Contract gate with physical dimension
- for (0..mps.bond_dim) |alpha| {
- for (0..NUM_TRIT_STATES) |s| {
- for (0..mps.bond_dim) |beta| {
- var sum = Complex.fromReal(0);
- for (0..NUM_TRIT_STATES) |s_prime| {
- const gate_elem = gate[s][s_prime];
- const tensor_elem = tensor.get(alpha, s_prime, beta);
- sum = Complex.add(sum, Complex.mul(gate_elem, tensor_elem));
- }
- const idx = (alpha * NUM_TRIT_STATES + s) * mps.bond_dim + beta;
- new_data[idx] = sum;
- }
- }
- }
-
- // Copy back
- @memcpy(tensor.data, new_data);
- mps.allocator.free(new_data);
-}
-
-/// Golden gate for MPS evolution (SU(3) rotation)
-pub const GoldenGateMPS = struct {
- matrix: [NUM_TRIT_STATES][NUM_TRIT_STATES]Complex,
-
- pub fn init() GoldenGateMPS {
- const inv_sqrt3 = 1.0 / math.sqrt(3.0);
- const omega_re: f64 = -0.5;
- const omega_im: f64 = math.sqrt(3.0) / 2.0;
-
- return GoldenGateMPS{
- .matrix = [_][NUM_TRIT_STATES]Complex{
- [_]Complex{
- Complex.fromReal(inv_sqrt3),
- Complex.fromReal(inv_sqrt3),
- Complex.fromReal(inv_sqrt3),
- },
- [_]Complex{
- Complex.fromReal(inv_sqrt3),
- Complex.init(omega_re * inv_sqrt3, omega_im * inv_sqrt3),
- Complex.init(omega_re * inv_sqrt3, -omega_im * inv_sqrt3),
- },
- [_]Complex{
- Complex.fromReal(inv_sqrt3),
- Complex.init(omega_re * inv_sqrt3, -omega_im * inv_sqrt3),
- Complex.init(omega_re * inv_sqrt3, omega_im * inv_sqrt3),
- },
- },
- };
- }
-};
-
-/// TEBD time evolution step
-pub fn tebdStep(
- mps: *MPS,
- hamiltonian_term: anytype,
- dt: f64,
-) !void {
- _ = hamiltonian_term;
- _ = dt;
-
- // Apply Trotter-decomposed gates
- const gate = GoldenGateMPS.init();
-
- // Apply even bonds then odd bonds (second order)
- for (0..mps.num_sites - 1) |site| {
- if (site % 2 == 0) {
- // Two-qutrit gate (simplified to single for now)
- try applySingleQutritGate(mps, site, &gate.matrix);
- }
- }
-
- for (0..mps.num_sites - 1) |site| {
- if (site % 2 == 1) {
- try applySingleQutritGate(mps, site, &gate.matrix);
- }
- }
-}
-
-//===========================================================================
-// Tests
-//===========================================================================
-
-test "Trit enum values" {
- try std.testing.expectEqual(@as(i2, -1), Trit.neg.toInt());
- try std.testing.expectEqual(@as(i2, 0), Trit.zero.toInt());
- try std.testing.expectEqual(@as(i2, 1), Trit.pos.toInt());
-}
-
-test "Complex arithmetic" {
- const a = Complex.init(1, 2);
- const b = Complex.init(3, 4);
-
- const sum = Complex.add(a, b);
- try std.testing.expectEqual(@as(f64, 4), sum.re);
- try std.testing.expectEqual(@as(f64, 6), sum.im);
-
- const prod = Complex.mul(a, b);
- try std.testing.expectEqual(@as(f64, -5), prod.re);
- try std.testing.expectEqual(@as(f64, 10), prod.im);
-}
-
-test "MPS initialization" {
- var mps = try MPS.init(std.testing.allocator, 3, 2);
- defer mps.deinit();
-
- try mps.initSuperposition();
-
- // Check first tensor
- const t0 = mps.tensors[0];
- try std.testing.expectEqual(@as(usize, 2), t0.bond_dim);
-}
-
-test "MPS contract small system" {
- var mps = try MPS.init(std.testing.allocator, 2, 1);
- defer mps.deinit();
-
- try mps.initSuperposition();
-
- const state = try mps.contract(std.testing.allocator);
- defer std.testing.allocator.free(state);
-
- // 2 qutrits = 9 states
- try std.testing.expectEqual(@as(usize, 9), state.len);
-}
-
-test "Golden gate is unitary" {
- const gate = GoldenGateMPS.init();
-
- // Check Uβ U = I (simplified: check column normalization)
- for (0..NUM_TRIT_STATES) |j| {
- var sum: f64 = 0;
- for (0..NUM_TRIT_STATES) |i| {
- const elem = gate.matrix[i][j];
- sum += elem.absSquared();
- }
- try std.testing.expectApproxEqAbs(1.0, sum, 1e-10);
- }
-}
-
-test "SVD of identity matrix" {
- const m: usize = 3;
- const n: usize = 3;
-
- // Create identity matrix
- var A = try std.testing.allocator.alloc(Complex, m * n);
- defer std.testing.allocator.free(A);
-
- for (0..m) |i| {
- for (0..n) |j| {
- if (i == j) {
- A[i * n + j] = Complex.fromReal(1);
- } else {
- A[i * n + j] = Complex.fromReal(0);
- }
- }
- }
-
- var svd_result = try svd(std.testing.allocator, A, m, n);
- defer svd_result.deinit();
-
- // Identity should have dominant singular values close to 1
- // (Power iteration with deflation has numerical limits on smaller singular values)
- try std.testing.expectApproxEqAbs(1.0, svd_result.S[0], 1e-3); // First singular value
-
- // Sum of singular values should be close to trace for identity = 3
- // (Numerical limitations of power iteration with deflation)
- var sum_sv: f64 = 0;
- for (svd_result.S) |s| sum_sv += s;
- try std.testing.expect(sum_sv >= 1.5); // At least 50% of expected (conservative check)
- try std.testing.expect(sum_sv <= 3.5); // Not more than 117% of expected
-}
-
-test "SVD truncation respects bond dimension" {
- const m: usize = 4;
- const n: usize = 4;
-
- var A = try std.testing.allocator.alloc(Complex, m * n);
- defer std.testing.allocator.free(A);
-
- // Create matrix with decaying singular values
- for (0..m) |i| {
- for (0..n) |j| {
- const val = if (i == j) @as(f64, @floatFromInt(m - i)) else 0;
- A[i * n + j] = Complex.fromReal(val);
- }
- }
-
- var svd_result = try svd(std.testing.allocator, A, m, n);
- defer svd_result.deinit();
-
- // Truncate to 2 dimensions
- var truncated = try truncateSVD(std.testing.allocator, &svd_result, 2, 1e-10);
- defer truncated.deinit();
-
- // Should have only 2 singular values
- try std.testing.expectEqual(@as(usize, 4), svd_result.S.len);
- // (truncateSVD creates full arrays but only first 2 are meaningful)
-}
-
-test "MPS compression via SVD" {
- const num_sites: usize = 3;
- const bond_dim: usize = 2;
-
- // Create initial state (all +1)
- const dim = math.pow(usize, NUM_TRIT_STATES, num_sites);
- var state = try std.testing.allocator.alloc(Complex, dim);
- defer std.testing.allocator.free(state);
-
- for (0..dim) |i| {
- state[i] = Complex.fromReal(1.0 / @sqrt(@as(f64, @floatFromInt(dim))));
- }
-
- var mps = try compressMPS(std.testing.allocator, state, num_sites, bond_dim, 1e-10);
- defer mps.deinit();
-
- // MPS should be created
- try std.testing.expectEqual(num_sites, mps.num_sites);
- try std.testing.expectEqual(bond_dim, mps.bond_dim);
-}
-
-test "SVD reconstruction error" {
- const m: usize = 3;
- const n: usize = 3;
-
- // Create random-like matrix
- var A = try std.testing.allocator.alloc(Complex, m * n);
- defer std.testing.allocator.free(A);
-
- var rng = std.Random.DefaultPrng.init(42);
- for (0..m * n) |i| {
- const val = rng.random().float(f64);
- A[i] = Complex.fromReal(val);
- }
-
- var svd_result = try svd(std.testing.allocator, A, m, n);
- defer svd_result.deinit();
-
- // Reconstruct: A β UΒ·SΒ·Vβ
- var reconstructed = try std.testing.allocator.alloc(Complex, m * n);
- defer std.testing.allocator.free(reconstructed);
-
- for (0..m) |i| {
- for (0..n) |j| {
- var sum = Complex.fromReal(0);
- for (0..@min(m, n)) |k| {
- const u_elem = svd_result.U[i * @min(m, n) + k];
- const s_val = svd_result.S[k];
- const v_elem = Complex.conj(svd_result.V[j * @min(m, n) + k]);
- sum = Complex.add(sum, Complex.mul(u_elem, Complex.scale(v_elem, s_val)));
- }
- reconstructed[i * n + j] = sum;
- }
- }
-
- // Calculate reconstruction error
- var recon_error: f64 = 0;
- for (0..m * n) |i| {
- const diff = Complex.sub(A[i], reconstructed[i]);
- recon_error += diff.absSquared();
- }
- recon_error = @sqrt(recon_error);
-
- // Error should be small (< 1e-6 for power iteration)
- try std.testing.expect(recon_error < 0.1);
-}
diff --git a/src/quantum/ternary_qvm.zig b/src/quantum/ternary_qvm.zig
deleted file mode 100644
index d16b77afa6..0000000000
--- a/src/quantum/ternary_qvm.zig
+++ /dev/null
@@ -1,1109 +0,0 @@
-// TERNARY QUANTUM VM β Trinity v2.1
-// Qutrit-based quantum virtual machine for ternary computation
-//
-// A qutrit has 3 basis states: |β1β©, |0β©, |+1β©
-// State vector: 3 complex amplitudes [Ξ±ββ, Ξ±β, Ξ±ββ] where |Ξ±ββ|Β² + |Ξ±β|Β² + |Ξ±ββ|Β² = 1
-//
-// Gates operate as 3Γ3 unitary matrices over complex amplitudes
-// Measurement collapses to {-1, 0, +1} with probabilities |Ξ±α΅’|Β²
-//
-// phi^2 + 1/phi^2 = 3 = TRINITY (3 basis states = natural qutrit)
-
-const std = @import("std");
-const math = std.math;
-
-/// Complex number for quantum amplitudes
-pub const Complex = struct {
- re: f64,
- im: f64,
-
- pub const ZERO = Complex{ .re = 0, .im = 0 };
- pub const ONE = Complex{ .re = 1, .im = 0 };
- pub const I = Complex{ .re = 0, .im = 1 };
-
- pub fn init(re: f64, im: f64) Complex {
- return .{ .re = re, .im = im };
- }
-
- pub fn add(a: Complex, b: Complex) Complex {
- return .{ .re = a.re + b.re, .im = a.im + b.im };
- }
-
- pub fn sub(a: Complex, b: Complex) Complex {
- return .{ .re = a.re - b.re, .im = a.im - b.im };
- }
-
- pub fn mul(a: Complex, b: Complex) Complex {
- return .{
- .re = a.re * b.re - a.im * b.im,
- .im = a.re * b.im + a.im * b.re,
- };
- }
-
- pub fn scale(a: Complex, s: f64) Complex {
- return .{ .re = a.re * s, .im = a.im * s };
- }
-
- pub fn conj(a: Complex) Complex {
- return .{ .re = a.re, .im = -a.im };
- }
-
- pub fn norm_sq(a: Complex) f64 {
- return a.re * a.re + a.im * a.im;
- }
-
- pub fn abs(a: Complex) f64 {
- return @sqrt(a.norm_sq());
- }
-
- /// e^(i*theta)
- pub fn exp_i(theta: f64) Complex {
- return .{ .re = @cos(theta), .im = @sin(theta) };
- }
-};
-
-/// Qutrit state: 3 complex amplitudes for |β1β©, |0β©, |+1β©
-pub const Qutrit = struct {
- /// Amplitudes: [0]=|β1β©, [1]=|0β©, [2]=|+1β©
- amp: [3]Complex,
-
- /// |β1β© basis state
- pub const MINUS = Qutrit{ .amp = .{ Complex.ONE, Complex.ZERO, Complex.ZERO } };
- /// |0β© basis state
- pub const ZERO_STATE = Qutrit{ .amp = .{ Complex.ZERO, Complex.ONE, Complex.ZERO } };
- /// |+1β© basis state
- pub const PLUS = Qutrit{ .amp = .{ Complex.ZERO, Complex.ZERO, Complex.ONE } };
-
- /// Measurement probabilities: [P(β1), P(0), P(+1)]
- pub fn probabilities(self: Qutrit) [3]f64 {
- return .{
- self.amp[0].norm_sq(),
- self.amp[1].norm_sq(),
- self.amp[2].norm_sq(),
- };
- }
-
- /// Total probability (should be 1.0 for valid state)
- pub fn total_prob(self: Qutrit) f64 {
- const p = self.probabilities();
- return p[0] + p[1] + p[2];
- }
-
- /// Measure qutrit, returns {-1, 0, +1} and collapses state
- pub fn measure(self: *Qutrit, rng: std.Random) i2 {
- const p = self.probabilities();
- const r = rng.float(f64);
-
- var result: i2 = undefined;
- if (r < p[0]) {
- result = -1;
- self.* = MINUS;
- } else if (r < p[0] + p[1]) {
- result = 0;
- self.* = ZERO_STATE;
- } else {
- result = 1;
- self.* = PLUS;
- }
- return result;
- }
-
- /// Inner product β¨self|otherβ©
- pub fn inner(self: Qutrit, other: Qutrit) Complex {
- var result = Complex.ZERO;
- for (0..3) |i| {
- result = result.add(self.amp[i].conj().mul(other.amp[i]));
- }
- return result;
- }
-
- /// Normalize state vector
- pub fn normalize(self: *Qutrit) void {
- const norm = @sqrt(self.total_prob());
- if (norm > 1e-15) {
- for (0..3) |i| {
- self.amp[i] = self.amp[i].scale(1.0 / norm);
- }
- }
- }
-};
-
-/// 3x3 unitary gate for qutrit operations
-pub const Gate3 = struct {
- /// Row-major 3x3 complex matrix
- m: [3][3]Complex,
-
- /// Apply gate to qutrit
- pub fn apply(self: Gate3, q: Qutrit) Qutrit {
- var result: Qutrit = undefined;
- for (0..3) |i| {
- result.amp[i] = Complex.ZERO;
- for (0..3) |j| {
- result.amp[i] = result.amp[i].add(self.m[i][j].mul(q.amp[j]));
- }
- }
- return result;
- }
-
- /// Identity gate
- pub const I3 = Gate3{ .m = .{
- .{ Complex.ONE, Complex.ZERO, Complex.ZERO },
- .{ Complex.ZERO, Complex.ONE, Complex.ZERO },
- .{ Complex.ZERO, Complex.ZERO, Complex.ONE },
- } };
-
- /// Qutrit Hadamard (QFTβ β discrete Fourier transform on 3 states)
- /// Fβ[j,k] = (1/β3) * Ο^(jk) where Ο = e^(2Οi/3)
- /// Hβ = (1/β3) * [[1, 1, 1], [1, Ο, ΟΒ²], [1, ΟΒ², Ο]]
- /// Property: FβΒ³ = I (cube is identity)
- pub fn hadamard3() Gate3 {
- const s = 1.0 / @sqrt(3.0);
- const omega = Complex.exp_i(2.0 * math.pi / 3.0); // Ο = e^(2Οi/3)
- const omega2 = omega.mul(omega); // ΟΒ²
- // Οβ΄ = Ο^(4 mod 3) = ΟΒΉ = Ο
-
- return .{ .m = .{
- .{ Complex.init(s, 0), Complex.init(s, 0), Complex.init(s, 0) },
- .{ Complex.init(s, 0), omega.scale(s), omega2.scale(s) },
- .{ Complex.init(s, 0), omega2.scale(s), omega.scale(s) },
- } };
- }
-
- /// Phase gate: adds phase phi to |+1β© state
- /// P(Ο) = diag(1, 1, e^(iΟ))
- pub fn phase(phi_angle: f64) Gate3 {
- return .{ .m = .{
- .{ Complex.ONE, Complex.ZERO, Complex.ZERO },
- .{ Complex.ZERO, Complex.ONE, Complex.ZERO },
- .{ Complex.ZERO, Complex.ZERO, Complex.exp_i(phi_angle) },
- } };
- }
-
- /// Sacred phase gate using golden ratio
- /// Applies phase = 2Ο/ΟΒ² to |+1β© state
- /// Since ΟΒ² + 1/ΟΒ² = 3 = number of qutrit states, this is natural
- pub fn sacred_phase() Gate3 {
- const phi: f64 = (1.0 + @sqrt(5.0)) / 2.0;
- const angle = 2.0 * math.pi / (phi * phi);
- return phase(angle);
- }
-
- /// X gate (cyclic shift): |β1β©β|0β©β|+1β©β|β1β©
- pub const X3 = Gate3{ .m = .{
- .{ Complex.ZERO, Complex.ZERO, Complex.ONE },
- .{ Complex.ONE, Complex.ZERO, Complex.ZERO },
- .{ Complex.ZERO, Complex.ONE, Complex.ZERO },
- } };
-
- /// Z gate (phase): diagonal with Ο phases
- /// Zβ = diag(1, Ο, ΟΒ²) where Ο = e^(2Οi/3)
- pub fn z3() Gate3 {
- const omega = Complex.exp_i(2.0 * math.pi / 3.0);
- const omega2 = omega.mul(omega);
- return .{ .m = .{
- .{ Complex.ONE, Complex.ZERO, Complex.ZERO },
- .{ Complex.ZERO, omega, Complex.ZERO },
- .{ Complex.ZERO, Complex.ZERO, omega2 },
- } };
- }
-
- /// Compose two gates: (self β other) means apply other first, then self
- /// Result[i][j] = Ξ£_k self[i][k] * other[k][j]
- pub fn compose(self: Gate3, other: Gate3) Gate3 {
- var result: Gate3 = undefined;
- for (0..3) |i| {
- for (0..3) |j| {
- var sum = Complex.ZERO;
- for (0..3) |k| {
- sum = sum.add(self.m[i][k].mul(other.m[k][j]));
- }
- result.m[i][j] = sum;
- }
- }
- return result;
- }
-
- /// SWAP two qutrits (operates on 9-dim state)
- /// For single-qutrit VM we implement NOT: |β1β©β|+1β©, |0β©β|0β©
- pub const NOT3 = Gate3{ .m = .{
- .{ Complex.ZERO, Complex.ZERO, Complex.ONE },
- .{ Complex.ZERO, Complex.ONE, Complex.ZERO },
- .{ Complex.ONE, Complex.ZERO, Complex.ZERO },
- } };
-};
-
-/// Ternary Quantum Virtual Machine
-/// Operates on a register of qutrits with gate-based computation
-pub const TernaryQVM = struct {
- /// Qutrit registers (max 8 for single-qutrit operations)
- qutrits: [8]Qutrit,
- /// Number of active qutrits
- num_qutrits: u4,
- /// Measurement results (classical register)
- classical: [8]i2,
- /// Gate count (for circuit depth tracking)
- gate_count: u32,
- /// Pseudo-random number generator for measurement
- prng: std.Random.DefaultPrng,
-
- pub fn init(num_q: u4, seed: u64) TernaryQVM {
- var vm = TernaryQVM{
- .qutrits = undefined,
- .num_qutrits = num_q,
- .classical = [_]i2{0} ** 8,
- .gate_count = 0,
- .prng = std.Random.DefaultPrng.init(seed),
- };
- // Initialize all qutrits to |0β©
- for (0..8) |i| {
- vm.qutrits[i] = Qutrit.ZERO_STATE;
- }
- return vm;
- }
-
- /// Apply gate to qutrit at index
- pub fn apply_gate(self: *TernaryQVM, gate: Gate3, target: u4) void {
- if (target >= self.num_qutrits) return;
- self.qutrits[target] = gate.apply(self.qutrits[target]);
- self.gate_count += 1;
- }
-
- /// Apply Hadamard to qutrit
- pub fn hadamard(self: *TernaryQVM, target: u4) void {
- self.apply_gate(Gate3.hadamard3(), target);
- }
-
- /// Apply sacred phase gate (phi-based)
- pub fn sacred_phase(self: *TernaryQVM, target: u4) void {
- self.apply_gate(Gate3.sacred_phase(), target);
- }
-
- /// Apply X (cyclic shift) gate
- pub fn x(self: *TernaryQVM, target: u4) void {
- self.apply_gate(Gate3.X3, target);
- }
-
- /// Apply Z (phase) gate
- pub fn z(self: *TernaryQVM, target: u4) void {
- self.apply_gate(Gate3.z3(), target);
- }
-
- /// Apply NOT (|β1β©β|+1β©) gate
- pub fn not(self: *TernaryQVM, target: u4) void {
- self.apply_gate(Gate3.NOT3, target);
- }
-
- /// Measure qutrit, collapse state, store in classical register
- pub fn measure_qutrit(self: *TernaryQVM, target: u4) i2 {
- if (target >= self.num_qutrits) return 0;
- const result = self.qutrits[target].measure(self.prng.random());
- self.classical[target] = result;
- return result;
- }
-
- /// Reset qutrit to |0β©
- pub fn reset(self: *TernaryQVM, target: u4) void {
- if (target >= self.num_qutrits) return;
- self.qutrits[target] = Qutrit.ZERO_STATE;
- }
-
- /// Reset all qutrits
- pub fn reset_all(self: *TernaryQVM) void {
- for (0..self.num_qutrits) |i| {
- self.qutrits[i] = Qutrit.ZERO_STATE;
- }
- self.gate_count = 0;
- self.classical = [_]i2{0} ** 8;
- }
-
- /// Get state probabilities for a qutrit
- pub fn get_probs(self: TernaryQVM, target: u4) [3]f64 {
- if (target >= self.num_qutrits) return .{ 0, 0, 0 };
- return self.qutrits[target].probabilities();
- }
-};
-
-// ============================================================
-// ENTANGLED 2-QUTRIT SYSTEM (9-dimensional Hilbert space)
-// ============================================================
-
-/// 2-qutrit entangled state in 3β3 = 9 dimensional Hilbert space
-/// Basis: |β1,β1β©, |β1,0β©, |β1,+1β©, |0,β1β©, |0,0β©, |0,+1β©, |+1,β1β©, |+1,0β©, |+1,+1β©
-pub const EntangledPair = struct {
- /// 9 complex amplitudes for the joint state
- amp: [9]Complex,
-
- /// Map (a, b) indices to flat index: a*3 + b where a,b in {0,1,2}
- fn idx(a: usize, b: usize) usize {
- return a * 3 + b;
- }
-
- /// Product state |aβ©β|bβ©
- pub fn product(a: Qutrit, b: Qutrit) EntangledPair {
- var result: EntangledPair = undefined;
- for (0..3) |i| {
- for (0..3) |j| {
- result.amp[idx(i, j)] = a.amp[i].mul(b.amp[j]);
- }
- }
- return result;
- }
-
- /// |00β© state (both qutrits in |0β©)
- pub const ZERO_ZERO = blk: {
- var s: EntangledPair = .{ .amp = .{Complex.ZERO} ** 9 };
- s.amp[idx(1, 1)] = Complex.ONE; // |0,0β©
- break :blk s;
- };
-
- /// Maximally entangled state (qutrit Bell state):
- /// |Ξ¦+β© = (1/β3)(|β1,β1β© + |0,0β© + |+1,+1β©)
- pub const BELL = blk: {
- const s = 1.0 / @sqrt(3.0);
- var state: EntangledPair = .{ .amp = .{Complex.ZERO} ** 9 };
- state.amp[idx(0, 0)] = Complex.init(s, 0); // |β1,β1β©
- state.amp[idx(1, 1)] = Complex.init(s, 0); // |0,0β©
- state.amp[idx(2, 2)] = Complex.init(s, 0); // |+1,+1β©
- break :blk state;
- };
-
- /// Total probability (should be 1.0)
- pub fn total_prob(self: EntangledPair) f64 {
- var sum: f64 = 0;
- for (0..9) |i| {
- sum += self.amp[i].norm_sq();
- }
- return sum;
- }
-
- /// Apply single-qutrit gate to qubit A (first qutrit)
- /// G_A β I: applies G to first qutrit, identity to second
- pub fn apply_gate_a(self: EntangledPair, gate: Gate3) EntangledPair {
- var result: EntangledPair = .{ .amp = .{Complex.ZERO} ** 9 };
- for (0..3) |i_out| { // output row of A
- for (0..3) |j| { // B stays same
- for (0..3) |i_in| { // input row of A
- result.amp[idx(i_out, j)] = result.amp[idx(i_out, j)].add(
- gate.m[i_out][i_in].mul(self.amp[idx(i_in, j)]),
- );
- }
- }
- }
- return result;
- }
-
- /// Apply single-qutrit gate to qubit B (second qutrit)
- /// I β G_B: applies identity to first, G to second
- pub fn apply_gate_b(self: EntangledPair, gate: Gate3) EntangledPair {
- var result: EntangledPair = .{ .amp = .{Complex.ZERO} ** 9 };
- for (0..3) |i| { // A stays same
- for (0..3) |j_out| { // output row of B
- for (0..3) |j_in| { // input row of B
- result.amp[idx(i, j_out)] = result.amp[idx(i, j_out)].add(
- gate.m[j_out][j_in].mul(self.amp[idx(i, j_in)]),
- );
- }
- }
- }
- return result;
- }
-
- /// Controlled-SUM gate (qutrit CNOT equivalent)
- /// CSUM|a,bβ© = |a, (a+b) mod 3β©
- /// This creates entanglement from product states
- pub fn csum(self: EntangledPair) EntangledPair {
- var result: EntangledPair = .{ .amp = .{Complex.ZERO} ** 9 };
- for (0..3) |a| {
- for (0..3) |b| {
- const b_new = (a + b) % 3;
- result.amp[idx(a, b_new)] = result.amp[idx(a, b_new)].add(
- self.amp[idx(a, b)],
- );
- }
- }
- return result;
- }
-
- /// Controlled-Phase gate
- /// CPhase|a,bβ© = Ο^(a*b) |a,bβ© where Ο = e^(2Οi/3)
- pub fn cphase(self: EntangledPair) EntangledPair {
- var result = self;
- const omega = Complex.exp_i(2.0 * math.pi / 3.0);
- const omega2 = omega.mul(omega);
-
- // Only non-trivial phases when a*b mod 3 != 0
- // a=0(|-1β©) maps to value 0 in our 0-indexed scheme
- // But we need actual trit values: idx 0=-1, 1=0, 2=+1
- // Product of trit values: (-1)*(-1)=1, (-1)*0=0, etc.
- // Simpler: use idx directly, phase = Ο^(i*j) where i,j are 0-indexed
-
- // i=1,j=1: phase = Ο^1
- result.amp[idx(1, 1)] = self.amp[idx(1, 1)].mul(omega);
- // i=1,j=2: phase = Ο^2
- result.amp[idx(1, 2)] = self.amp[idx(1, 2)].mul(omega2);
- // i=2,j=1: phase = Ο^2
- result.amp[idx(2, 1)] = self.amp[idx(2, 1)].mul(omega2);
- // i=2,j=2: phase = Ο^4 = Ο^1
- result.amp[idx(2, 2)] = self.amp[idx(2, 2)].mul(omega);
-
- return result;
- }
-
- /// Measure qutrit A, return result and collapsed state
- /// Partial measurement: trace out B's state conditioned on A's result
- pub fn measure_a(self: *EntangledPair, rng: std.Random) i2 {
- // Compute marginal probabilities for A
- var prob_a: [3]f64 = .{ 0, 0, 0 };
- for (0..3) |i| {
- for (0..3) |j| {
- prob_a[i] += self.amp[idx(i, j)].norm_sq();
- }
- }
-
- // Sample
- const r = rng.float(f64);
- var result: usize = 2;
- if (r < prob_a[0]) {
- result = 0;
- } else if (r < prob_a[0] + prob_a[1]) {
- result = 1;
- }
-
- // Collapse: zero out all amplitudes where A != result, renormalize
- var norm: f64 = 0;
- for (0..3) |i| {
- for (0..3) |j| {
- if (i != result) {
- self.amp[idx(i, j)] = Complex.ZERO;
- } else {
- norm += self.amp[idx(i, j)].norm_sq();
- }
- }
- }
-
- // Renormalize
- if (norm > 1e-15) {
- const inv_norm = 1.0 / @sqrt(norm);
- for (0..3) |j| {
- self.amp[idx(result, j)] = self.amp[idx(result, j)].scale(inv_norm);
- }
- }
-
- // Convert index to trit: 0->-1, 1->0, 2->+1
- return @as(i2, @intCast(@as(i8, @intCast(result)) - 1));
- }
-
- /// Measure qutrit B
- pub fn measure_b(self: *EntangledPair, rng: std.Random) i2 {
- var prob_b: [3]f64 = .{ 0, 0, 0 };
- for (0..3) |j| {
- for (0..3) |i| {
- prob_b[j] += self.amp[idx(i, j)].norm_sq();
- }
- }
-
- const r = rng.float(f64);
- var result: usize = 2;
- if (r < prob_b[0]) {
- result = 0;
- } else if (r < prob_b[0] + prob_b[1]) {
- result = 1;
- }
-
- var norm: f64 = 0;
- for (0..3) |i| {
- for (0..3) |j| {
- if (j != result) {
- self.amp[idx(i, j)] = Complex.ZERO;
- } else {
- norm += self.amp[idx(i, j)].norm_sq();
- }
- }
- }
-
- if (norm > 1e-15) {
- const inv_norm = 1.0 / @sqrt(norm);
- for (0..3) |i| {
- self.amp[idx(i, result)] = self.amp[idx(i, result)].scale(inv_norm);
- }
- }
-
- return @as(i2, @intCast(@as(i8, @intCast(result)) - 1));
- }
-};
-
-// ============================================================
-// CGLMP INEQUALITY TEST (full Collins et al. 2002 for d=3)
-// ============================================================
-
-/// Compute joint probability P(a,b) for a Schmidt-form entangled state
-/// State: |Ξ¨β© = Ξ£_j c_j |j,jβ© where c_j are real coefficients
-/// After applying measurement gates G_A, G_B:
-/// P(a,b) = |Ξ£_j c_j Β· G_A[a,j] Β· G_B[b,j]|Β²
-fn entangled_joint_prob(a: usize, b: usize, ga: Gate3, gb: Gate3, coeffs: [3]f64) f64 {
- var amp = Complex.ZERO;
- for (0..3) |j| {
- amp = amp.add(ga.m[a][j].mul(gb.m[b][j]).scale(coeffs[j]));
- }
- return amp.norm_sq();
-}
-
-/// Compute P(A - B = k mod 3) analytically from Born rule
-fn entangled_correlation_prob(k: usize, ga: Gate3, gb: Gate3, coeffs: [3]f64) f64 {
- var prob: f64 = 0;
- for (0..3) |a| {
- const b = (a + 3 - k) % 3; // a - b = k mod 3, so b = a - k mod 3
- prob += entangled_joint_prob(a, b, ga, gb, coeffs);
- }
- return prob;
-}
-
-/// Build a CGLMP measurement gate using Givens rotation R01(ΞΈ).
-///
-/// Rotation in the |0β©-|1β© plane:
-/// R01(ΞΈ) = [[cos(ΞΈ), -sin(ΞΈ), 0],
-/// [sin(ΞΈ), cos(ΞΈ), 0],
-/// [0, 0, 1]]
-///
-/// Unlike QFT-based gates, rotation gates break the permutation symmetry
-/// of the maximally entangled state, producing non-uniform P(A-B = k mod 3)
-/// which is necessary for CGLMP violation.
-///
-/// QFT gates ALWAYS give uniform P(A-B=k) = 1/3 for ANY Schmidt-form state,
-/// making CGLMP violation impossible with QFT-based measurements alone.
-fn cglmp_gate(theta: f64) Gate3 {
- return Gate3{ .m = .{
- .{ Complex.init(@cos(theta), 0), Complex.init(-@sin(theta), 0), Complex.ZERO },
- .{ Complex.init(@sin(theta), 0), Complex.init(@cos(theta), 0), Complex.ZERO },
- .{ Complex.ZERO, Complex.ZERO, Complex.ONE },
- } };
-}
-
-/// Compute Iβ for given state coefficients and measurement angles
-fn compute_i3(coeffs: [3]f64, alpha1: f64, alpha2: f64, beta1: f64, beta2: f64) f64 {
- const ga1 = cglmp_gate(alpha1);
- const ga2 = cglmp_gate(alpha2);
- const gb1 = cglmp_gate(beta1);
- const gb2 = cglmp_gate(beta2);
-
- // CGLMP Iβ for d=3 (Collins et al. 2002, Phys. Rev. Lett. 88, 040404):
- //
- // Iβ = P(Aβ=Bβ) + P(Bβ=Aβ+1) + P(Aβ=Bβ) + P(Bβ=Aβ)
- // - P(Aβ=Bβ-1) - P(Bβ=Aβ) - P(Aβ=Bβ-1) - P(Bβ=Aβ-1) β€ 2
- //
- // In P(Aβ-Bα΅§ = k mod 3) notation:
- // P(Aβ=Bβ) = Pββ(0) P(Aβ=Bβ-1) = Pββ(2) [A-B = -1 mod 3 = 2]
- // P(Bβ=Aβ+1) = Pββ(2) P(Bβ=Aβ) = Pββ(0) [Aβ-Bβ = -1 mod 3 = 2 | Aβ-Bβ = 0]
- // P(Aβ=Bβ) = Pββ(0) P(Aβ=Bβ-1) = Pββ(2)
- // P(Bβ=Aβ) = Pββ(0) P(Bβ=Aβ-1) = Pββ(1) [Aβ-Bβ = 1]
- //
- // Iβ = [Pββ(0) - Pββ(2)] + [Pββ(2) - Pββ(0)]
- // + [Pββ(0) - Pββ(2)] + [Pββ(0) - Pββ(1)]
- const p11_0 = entangled_correlation_prob(0, ga1, gb1, coeffs);
- const p11_2 = entangled_correlation_prob(2, ga1, gb1, coeffs);
- const p21_0 = entangled_correlation_prob(0, ga2, gb1, coeffs);
- const p21_2 = entangled_correlation_prob(2, ga2, gb1, coeffs);
- const p22_0 = entangled_correlation_prob(0, ga2, gb2, coeffs);
- const p22_2 = entangled_correlation_prob(2, ga2, gb2, coeffs);
- const p12_0 = entangled_correlation_prob(0, ga1, gb2, coeffs);
- const p12_1 = entangled_correlation_prob(1, ga1, gb2, coeffs);
-
- return (p11_0 - p11_2) + (p21_2 - p21_0) + (p22_0 - p22_2) + (p12_0 - p12_1);
-}
-
-/// CGLMP inequality for qutrits (Collins-Gisin-Linden-Massar-Popescu 2002)
-/// Classical bound Iβ β€ 2
-/// Quantum maximum Iβ β 2.9149 (for d=3 non-maximally entangled pair)
-///
-/// Full formula for d=3 (Phys. Rev. Lett. 88, 040404):
-///
-/// Iβ = P(Aβ=Bβ) + P(Bβ=Aβ+1) + P(Aβ=Bβ) + P(Bβ=Aβ)
-/// - P(Aβ=Bβ-1) - P(Bβ=Aβ) - P(Aβ=Bβ-1) - P(Bβ=Aβ-1) β€ 2
-///
-/// In P(Aβ-Bα΅§ = k mod 3) notation:
-/// Iβ = [Pββ(0) - Pββ(2)] + [Pββ(2) - Pββ(0)]
-/// + [Pββ(0) - Pββ(2)] + [Pββ(0) - Pββ(1)]
-///
-/// Key insights:
-/// - Optimal state is NOT maximally entangled for dβ₯3 (AcΓn et al. 2002)
-/// - QFT-based measurement gates always give uniform P(A-B=k) = 1/3
-/// for ANY Schmidt-form state, making violation IMPOSSIBLE
-/// - Real rotation gates (Givens R01) break this symmetry,
-/// enabling genuine CGLMP violation Iβ > 2.0
-pub fn run_cglmp_test(num_trials: u32, use_entanglement: bool) struct {
- i3_value: f64,
- classical_bound: f64,
- quantum_max: f64,
- violation: bool,
- trials: u32,
- correlation_same_basis: f64,
- correlation_diff_basis: f64,
-} {
- _ = num_trials; // Analytical computation β no Monte Carlo needed
-
- if (use_entanglement) {
- // Grid search over state parameter Ξ³ and 4 independent rotation angles
- // State: |Οβ© = sin(Ξ³)/β2 |00β© + cos(Ξ³) |11β© + sin(Ξ³)/β2 |22β©
- // Measurements: R01(Ξ±β), R01(Ξ±β), R01(Ξ²β), R01(Ξ²β) β Givens rotations
- var best_i3: f64 = -100.0;
- var best_coeffs: [3]f64 = .{ 1.0 / @sqrt(3.0), 1.0 / @sqrt(3.0), 1.0 / @sqrt(3.0) };
- var best_p11_0: f64 = 0;
- var best_p21_0: f64 = 0;
-
- const N_g: usize = 20;
- const N_a: usize = 24;
-
- // Scan Ξ³ from 0.05 to Ο/3 (0 = product state, Ο/4 = max entangled)
- var gi: usize = 0;
- while (gi < N_g) : (gi += 1) {
- const gamma: f64 = 0.05 + @as(f64, @floatFromInt(gi)) * (math.pi / 3.0) / @as(f64, @floatFromInt(N_g));
- const c0 = @sin(gamma) / @sqrt(2.0);
- const c1 = @cos(gamma);
- const coeffs = [3]f64{ c0, c1, c0 };
-
- // Scan all 4 measurement angles independently
- var a1i: usize = 0;
- while (a1i < N_a) : (a1i += 1) {
- const a1 = @as(f64, @floatFromInt(a1i)) * math.pi / @as(f64, @floatFromInt(N_a));
- var a2i: usize = 0;
- while (a2i < N_a) : (a2i += 1) {
- const a2 = @as(f64, @floatFromInt(a2i)) * math.pi / @as(f64, @floatFromInt(N_a));
- var b1i: usize = 0;
- while (b1i < N_a) : (b1i += 1) {
- const b1 = @as(f64, @floatFromInt(b1i)) * math.pi / @as(f64, @floatFromInt(N_a));
- var b2i: usize = 0;
- while (b2i < N_a) : (b2i += 1) {
- const b2 = @as(f64, @floatFromInt(b2i)) * math.pi / @as(f64, @floatFromInt(N_a));
- const i3_val = compute_i3(coeffs, a1, a2, b1, b2);
- if (i3_val > best_i3) {
- best_i3 = i3_val;
- best_coeffs = coeffs;
- }
- }
- }
- }
- }
- }
-
- // Compute final probabilities with best settings
- best_p11_0 = entangled_correlation_prob(0, cglmp_gate(0.0), cglmp_gate(0.0), best_coeffs);
- best_p21_0 = entangled_correlation_prob(0, cglmp_gate(math.pi / 4.0), cglmp_gate(0.0), best_coeffs);
-
- return .{
- .i3_value = best_i3,
- .classical_bound = 2.0,
- .quantum_max = 2.9149,
- .violation = best_i3 > 2.0 + 1e-6, // tolerance for floating point
- .trials = 0,
- .correlation_same_basis = best_p11_0,
- .correlation_diff_basis = best_p21_0,
- };
- } else {
- // Separable state |0,0β© = |1,1β© in our indexing
- // c_j = Ξ΄_{j,1} β coeffs = {0, 1, 0}
- const sep_coeffs = [3]f64{ 0.0, 1.0, 0.0 };
-
- // Search for max Iβ with separable state β must stay β€ 2.0
- var best_i3: f64 = -100.0;
- const N_sep: usize = 24;
- var a1i: usize = 0;
- while (a1i < N_sep) : (a1i += 1) {
- const a1 = @as(f64, @floatFromInt(a1i)) * math.pi / @as(f64, @floatFromInt(N_sep));
- var a2i: usize = 0;
- while (a2i < N_sep) : (a2i += 1) {
- const a2 = @as(f64, @floatFromInt(a2i)) * math.pi / @as(f64, @floatFromInt(N_sep));
- var b1i: usize = 0;
- while (b1i < N_sep) : (b1i += 1) {
- const b1 = @as(f64, @floatFromInt(b1i)) * math.pi / @as(f64, @floatFromInt(N_sep));
- var b2i: usize = 0;
- while (b2i < N_sep) : (b2i += 1) {
- const b2 = @as(f64, @floatFromInt(b2i)) * math.pi / @as(f64, @floatFromInt(N_sep));
- const i3_sep = compute_i3(sep_coeffs, a1, a2, b1, b2);
- if (i3_sep > best_i3) best_i3 = i3_sep;
- }
- }
- }
- }
-
- return .{
- .i3_value = best_i3,
- .classical_bound = 2.0,
- .quantum_max = 2.9149,
- .violation = best_i3 > 2.0 + 1e-6, // tolerance for floating point
- .trials = 0,
- .correlation_same_basis = 0,
- .correlation_diff_basis = 0,
- };
- }
-}
-
-// ============================================================
-// TESTS
-// ============================================================
-
-/// Test: CHSH-like inequality for qutrits (CGLMP inequality)
-/// Classical bound = 2, quantum bound = 2(1 + 1/β3) β 3.154
-/// We verify qutrit superposition produces non-classical correlations
-pub fn run_chsh_test(allocator: std.mem.Allocator, num_trials: u32) !struct {
- correlation: f64,
- classical_bound: f64,
- violation: bool,
- trials: u32,
-} {
- _ = allocator;
- var prng = std.Random.DefaultPrng.init(42);
- const rng = prng.random();
-
- var agree_count: u32 = 0;
- var total: u32 = 0;
-
- for (0..num_trials) |_| {
- // Create two qutrits in superposition
- var q1 = Qutrit.ZERO_STATE;
- var q2 = Qutrit.ZERO_STATE;
-
- // Apply Hadamard to both (creates uniform superposition)
- q1 = Gate3.hadamard3().apply(q1);
- q2 = Gate3.hadamard3().apply(q2);
-
- // Apply sacred phase to q2 (golden ratio phase)
- q2 = Gate3.sacred_phase().apply(q2);
-
- // Measure both
- const m1 = q1.measure(rng);
- const m2 = q2.measure(rng);
-
- // Check correlation: agreement = same measurement outcome
- if (m1 == m2) agree_count += 1;
- total += 1;
- }
-
- const correlation = @as(f64, @floatFromInt(agree_count)) / @as(f64, @floatFromInt(total));
- const classical_bound: f64 = 1.0 / 3.0; // random correlation for 3 outcomes
-
- return .{
- .correlation = correlation,
- .classical_bound = classical_bound,
- .violation = correlation > classical_bound + 0.05, // significant deviation
- .trials = total,
- };
-}
-
-// ============================================================
-// UNIT TESTS
-// ============================================================
-
-test "qutrit basis states orthogonal" {
- const minus = Qutrit.MINUS;
- const zero = Qutrit.ZERO_STATE;
- const plus = Qutrit.PLUS;
-
- // β¨β1|0β© = 0
- try std.testing.expectApproxEqAbs(minus.inner(zero).abs(), 0.0, 1e-10);
- // β¨0|+1β© = 0
- try std.testing.expectApproxEqAbs(zero.inner(plus).abs(), 0.0, 1e-10);
- // β¨β1|+1β© = 0
- try std.testing.expectApproxEqAbs(minus.inner(plus).abs(), 0.0, 1e-10);
- // β¨0|0β© = 1
- try std.testing.expectApproxEqAbs(zero.inner(zero).abs(), 1.0, 1e-10);
-}
-
-test "qutrit normalization" {
- const q = Qutrit.ZERO_STATE;
- try std.testing.expectApproxEqAbs(q.total_prob(), 1.0, 1e-10);
-
- const minus = Qutrit.MINUS;
- try std.testing.expectApproxEqAbs(minus.total_prob(), 1.0, 1e-10);
-
- const plus = Qutrit.PLUS;
- try std.testing.expectApproxEqAbs(plus.total_prob(), 1.0, 1e-10);
-}
-
-test "hadamard creates uniform superposition" {
- const h = Gate3.hadamard3();
- const result = h.apply(Qutrit.ZERO_STATE);
- const probs = result.probabilities();
-
- // After Hadamard on |0β©, all 3 outcomes should have equal probability 1/3
- try std.testing.expectApproxEqAbs(probs[0], 1.0 / 3.0, 1e-10);
- try std.testing.expectApproxEqAbs(probs[1], 1.0 / 3.0, 1e-10);
- try std.testing.expectApproxEqAbs(probs[2], 1.0 / 3.0, 1e-10);
-}
-
-test "hadamard preserves norm" {
- const h = Gate3.hadamard3();
- const result = h.apply(Qutrit.MINUS);
- try std.testing.expectApproxEqAbs(result.total_prob(), 1.0, 1e-10);
-}
-
-test "X gate cyclic shift" {
- // X|β1β© = |0β©
- const r1 = Gate3.X3.apply(Qutrit.MINUS);
- try std.testing.expectApproxEqAbs(r1.amp[1].norm_sq(), 1.0, 1e-10);
-
- // X|0β© = |+1β©
- const r2 = Gate3.X3.apply(Qutrit.ZERO_STATE);
- try std.testing.expectApproxEqAbs(r2.amp[2].norm_sq(), 1.0, 1e-10);
-
- // X|+1β© = |β1β©
- const r3 = Gate3.X3.apply(Qutrit.PLUS);
- try std.testing.expectApproxEqAbs(r3.amp[0].norm_sq(), 1.0, 1e-10);
-}
-
-test "NOT gate swaps minus and plus" {
- // NOT|β1β© = |+1β©
- const r1 = Gate3.NOT3.apply(Qutrit.MINUS);
- try std.testing.expectApproxEqAbs(r1.amp[2].norm_sq(), 1.0, 1e-10);
-
- // NOT|0β© = |0β©
- const r2 = Gate3.NOT3.apply(Qutrit.ZERO_STATE);
- try std.testing.expectApproxEqAbs(r2.amp[1].norm_sq(), 1.0, 1e-10);
-
- // NOT|+1β© = |β1β©
- const r3 = Gate3.NOT3.apply(Qutrit.PLUS);
- try std.testing.expectApproxEqAbs(r3.amp[0].norm_sq(), 1.0, 1e-10);
-}
-
-test "phase gate preserves probabilities" {
- const p = Gate3.sacred_phase();
- const h = Gate3.hadamard3();
-
- // Apply H then P to |0β©
- var q = h.apply(Qutrit.ZERO_STATE);
- const probs_before = q.probabilities();
- q = p.apply(q);
- const probs_after = q.probabilities();
-
- // Phase gate only changes phases, not probabilities
- try std.testing.expectApproxEqAbs(probs_before[0], probs_after[0], 1e-10);
- try std.testing.expectApproxEqAbs(probs_before[1], probs_after[1], 1e-10);
- try std.testing.expectApproxEqAbs(probs_before[2], probs_after[2], 1e-10);
-}
-
-test "identity gate preserves state" {
- const q = Qutrit.PLUS;
- const result = Gate3.I3.apply(q);
- for (0..3) |i| {
- try std.testing.expectApproxEqAbs(result.amp[i].re, q.amp[i].re, 1e-10);
- try std.testing.expectApproxEqAbs(result.amp[i].im, q.amp[i].im, 1e-10);
- }
-}
-
-test "VM initialization" {
- const vm = TernaryQVM.init(3, 42);
- try std.testing.expectEqual(vm.num_qutrits, 3);
- try std.testing.expectEqual(vm.gate_count, 0);
- // All qutrits start in |0β©
- for (0..3) |i| {
- try std.testing.expectApproxEqAbs(vm.qutrits[i].amp[1].re, 1.0, 1e-10);
- }
-}
-
-test "VM gate application increments counter" {
- var vm = TernaryQVM.init(2, 42);
- vm.hadamard(0);
- try std.testing.expectEqual(vm.gate_count, 1);
- vm.x(1);
- try std.testing.expectEqual(vm.gate_count, 2);
- vm.sacred_phase(0);
- try std.testing.expectEqual(vm.gate_count, 3);
-}
-
-test "VM measurement produces valid trit" {
- var vm = TernaryQVM.init(1, 42);
- vm.hadamard(0);
- const result = vm.measure_qutrit(0);
- // Result must be -1, 0, or +1
- try std.testing.expect(result >= -1 and result <= 1);
- // After measurement, state is collapsed to basis state
- try std.testing.expectApproxEqAbs(vm.qutrits[0].total_prob(), 1.0, 1e-10);
-}
-
-test "VM reset restores zero state" {
- var vm = TernaryQVM.init(1, 42);
- vm.hadamard(0);
- vm.x(0);
- vm.reset(0);
- try std.testing.expectApproxEqAbs(vm.qutrits[0].amp[1].re, 1.0, 1e-10);
-}
-
-test "triple X returns to original" {
- // XΒ³ = I for qutrit X gate (cyclic)
- var q = Qutrit.MINUS;
- q = Gate3.X3.apply(q);
- q = Gate3.X3.apply(q);
- q = Gate3.X3.apply(q);
- try std.testing.expectApproxEqAbs(q.amp[0].norm_sq(), 1.0, 1e-10);
-}
-
-test "double hadamard not identity (qutrit)" {
- // HΒ² β I for qutrit Hadamard (unlike qubit)
- const h = Gate3.hadamard3();
- var q = Qutrit.ZERO_STATE;
- q = h.apply(q);
- q = h.apply(q);
- // For 3-dim QFT: HΒ³ = I, so HΒ² β I
- // Check that we're NOT back to |0β©
- const p0 = q.amp[1].norm_sq();
- // HΒ²|0β© should NOT have prob 1 at |0β©
- try std.testing.expect(p0 < 0.99);
-}
-
-test "hadamard is unitary (H*H_dagger = I)" {
- // Verify unitarity: Hβ H = I (each column has unit norm, columns orthogonal)
- const h = Gate3.hadamard3();
- // Apply H then check: for all basis states, total_prob == 1
- const states = [_]Qutrit{ Qutrit.MINUS, Qutrit.ZERO_STATE, Qutrit.PLUS };
- for (states) |s| {
- const result = h.apply(s);
- try std.testing.expectApproxEqAbs(result.total_prob(), 1.0, 1e-10);
- }
- // Check H applied to each basis state gives orthogonal results
- const h_minus = h.apply(Qutrit.MINUS);
- const h_zero = h.apply(Qutrit.ZERO_STATE);
- const h_plus = h.apply(Qutrit.PLUS);
- try std.testing.expectApproxEqAbs(h_minus.inner(h_zero).abs(), 0.0, 1e-10);
- try std.testing.expectApproxEqAbs(h_zero.inner(h_plus).abs(), 0.0, 1e-10);
- try std.testing.expectApproxEqAbs(h_minus.inner(h_plus).abs(), 0.0, 1e-10);
-}
-
-test "sacred phase angle uses golden ratio" {
- const phi: f64 = (1.0 + @sqrt(5.0)) / 2.0;
- const expected_angle = 2.0 * math.pi / (phi * phi);
- // phi^2 = phi + 1 β 2.618
- // angle β 2.400 rad β 137.5Β° (golden angle!)
- try std.testing.expectApproxEqAbs(phi * phi + 1.0 / (phi * phi), 3.0, 1e-10);
- try std.testing.expect(expected_angle > 2.0 and expected_angle < 3.0);
-}
-
-test "CHSH-like test runs" {
- const result = try run_chsh_test(std.testing.allocator, 1000);
- // Correlation should be a valid probability
- try std.testing.expect(result.correlation >= 0.0 and result.correlation <= 1.0);
- try std.testing.expectEqual(result.trials, 1000);
-}
-
-// ============================================================
-// ENTANGLEMENT TESTS
-// ============================================================
-
-test "Bell state normalization" {
- const bell = EntangledPair.BELL;
- var total: f64 = 0;
- for (0..9) |i| {
- total += bell.amp[i].norm_sq();
- }
- try std.testing.expectApproxEqAbs(total, 1.0, 1e-10);
-}
-
-test "Bell state has correct structure" {
- const bell = EntangledPair.BELL;
- const inv_sqrt3 = 1.0 / @sqrt(3.0);
- // |β1,β1β© = amp[0] should be 1/β3
- try std.testing.expectApproxEqAbs(bell.amp[0].re, inv_sqrt3, 1e-10);
- // |0,0β© = amp[4] should be 1/β3
- try std.testing.expectApproxEqAbs(bell.amp[4].re, inv_sqrt3, 1e-10);
- // |+1,+1β© = amp[8] should be 1/β3
- try std.testing.expectApproxEqAbs(bell.amp[8].re, inv_sqrt3, 1e-10);
- // All others zero
- try std.testing.expectApproxEqAbs(bell.amp[1].norm_sq(), 0.0, 1e-10);
- try std.testing.expectApproxEqAbs(bell.amp[2].norm_sq(), 0.0, 1e-10);
- try std.testing.expectApproxEqAbs(bell.amp[3].norm_sq(), 0.0, 1e-10);
- try std.testing.expectApproxEqAbs(bell.amp[5].norm_sq(), 0.0, 1e-10);
- try std.testing.expectApproxEqAbs(bell.amp[6].norm_sq(), 0.0, 1e-10);
- try std.testing.expectApproxEqAbs(bell.amp[7].norm_sq(), 0.0, 1e-10);
-}
-
-test "product state normalization" {
- const h = Gate3.hadamard3();
- const pair = EntangledPair.product(
- h.apply(Qutrit.ZERO_STATE),
- h.apply(Qutrit.ZERO_STATE),
- );
- var total: f64 = 0;
- for (0..9) |i| {
- total += pair.amp[i].norm_sq();
- }
- try std.testing.expectApproxEqAbs(total, 1.0, 1e-10);
-}
-
-test "CSUM creates entanglement from product state" {
- // Start with H|0β© β |0β© = (1/β3)(|0β©+|1β©+|2β©) β |1β© (|0β© = index 1)
- // CSUM: |a,bβ© β |a,(a+b)%3β©
- // a=0,b=1 β (0,1); a=1,b=1 β (1,2); a=2,b=1 β (2,0)
- // Result: (1/β3)(|0,1β© + |1,2β© + |2,0β©) β entangled!
- const h = Gate3.hadamard3();
- var pair = EntangledPair.product(h.apply(Qutrit.ZERO_STATE), Qutrit.ZERO_STATE);
- pair = pair.csum();
-
- // Entangled: 3 non-zero amplitudes, each with prob 1/3
- try std.testing.expectApproxEqAbs(pair.amp[EntangledPair.idx(0, 1)].norm_sq(), 1.0 / 3.0, 1e-10);
- try std.testing.expectApproxEqAbs(pair.amp[EntangledPair.idx(1, 2)].norm_sq(), 1.0 / 3.0, 1e-10);
- try std.testing.expectApproxEqAbs(pair.amp[EntangledPair.idx(2, 0)].norm_sq(), 1.0 / 3.0, 1e-10);
-
- // Total probability still 1
- var total: f64 = 0;
- for (0..9) |i| total += pair.amp[i].norm_sq();
- try std.testing.expectApproxEqAbs(total, 1.0, 1e-10);
-}
-
-test "entangled measurement correlation" {
- // Bell state: measuring A should always give same result as B
- var prng = std.Random.DefaultPrng.init(137);
- var agree: u32 = 0;
- const trials: u32 = 1000;
- for (0..trials) |_| {
- var pair = EntangledPair.BELL;
- const ma = pair.measure_a(prng.random());
- const mb = pair.measure_b(prng.random());
- if (ma == mb) agree += 1;
- }
- // For maximally entangled Bell state, A and B MUST always agree
- try std.testing.expectEqual(agree, trials);
-}
-
-test "CGLMP test produces valid result" {
- const result = run_cglmp_test(0, true);
- std.debug.print("\n CGLMP Iβ (entangled) = {d:.6}\n", .{result.i3_value});
- std.debug.print(" same_basis corr = {d:.6}, diff_basis = {d:.6}\n", .{ result.correlation_same_basis, result.correlation_diff_basis });
- // Analytical computation β Iβ must exceed classical bound 2.0
- try std.testing.expect(result.violation);
- try std.testing.expect(result.i3_value > 2.0);
- try std.testing.expect(result.i3_value < 3.0); // quantum max β 2.9149
- try std.testing.expectApproxEqAbs(result.classical_bound, 2.0, 1e-10);
-}
-
-test "CGLMP separable does not exceed classical bound with rotation gates" {
- // Verify separable state |0,0β© with rotation gates stays at classical bound
- const sep = [3]f64{ 0.0, 1.0, 0.0 };
- // Check specific angle where separable achieves max Iβ = 2.0
- // a1=0, a2=Ο/4, b1=Ο/4, b2=Ο/2
- const i3_at_max = compute_i3(sep, 0.0, math.pi / 4.0, math.pi / 4.0, math.pi / 2.0);
- try std.testing.expect(i3_at_max <= 2.0 + 1e-10);
-}
-
-test "CGLMP violation with known optimal angles" {
- // Verify CGLMP violation at known optimal parameters found by grid search:
- // Ξ³ β 0.8354 β c0=c2 β 0.526, c1 β 0.672 (non-maximally entangled)
- // a1=0, a2=3Ο/4, b1=Ο/8, b2=7Ο/8 (R01 rotation angles)
- const gamma: f64 = 0.8354;
- const c0 = @sin(gamma) / @sqrt(2.0);
- const c1 = @cos(gamma);
- const coeffs = [3]f64{ c0, c1, c0 };
-
- const i3_val = compute_i3(coeffs, 0.0, 3.0 * math.pi / 4.0, math.pi / 8.0, 7.0 * math.pi / 8.0);
-
- // Must exceed classical bound 2.0
- try std.testing.expect(i3_val > 2.0);
- // Must be below quantum maximum β 2.9149
- try std.testing.expect(i3_val < 3.0);
- // Specific value: Iβ β 2.4277
- try std.testing.expectApproxEqAbs(i3_val, 2.4277, 0.01);
-}
-
-test "separable state does not violate CGLMP" {
- const result = run_cglmp_test(0, false);
- // Product state MUST NOT violate classical bound
- try std.testing.expect(!result.violation);
- try std.testing.expect(result.i3_value <= 2.0 + 1e-10);
-}
diff --git a/src/quantum_gravity/cell.tri b/src/quantum_gravity/cell.tri
deleted file mode 100644
index 4bea3d9a1a..0000000000
--- a/src/quantum_gravity/cell.tri
+++ /dev/null
@@ -1,42 +0,0 @@
-[cell]
-id = "trinity.quantum-gravity"
-name = "Quantum Gravity"
-version = "1.0.0"
-kind = "library"
-path = "src/quantum_gravity"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "E8-quantum gravity bridge with holographic entropy"
-capabilities = ["vsa", "quantum-gravity", "e8"]
-files = 1
-tests = 9
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = []
-exports = ["normSquared", "isValid", "generateAll", "quantumProjection", "calculate"]
-tri_subcommands = []
-events = []
-binaries = []
-
-[dependencies]
-trinity.vsa = "^1.0.0"
-
-[permissions]
-level = "L0"
-filesystem = "read"
-network = "none"
-process = "none"
-ffi = "none"
-concurrency = "none"
-
-
-[biology]
-system = "body"
-[security]
-signed = "true"
-signature = "sha256:905a6fdb90fa488013dd063887e6e22e1e14f85a6df025c223d847d8a7e2dd7a"
diff --git a/src/quantum_gravity/e8_lqg_bridge.zig b/src/quantum_gravity/e8_lqg_bridge.zig
deleted file mode 100644
index 46312eaf1c..0000000000
--- a/src/quantum_gravity/e8_lqg_bridge.zig
+++ /dev/null
@@ -1,805 +0,0 @@
-//! TRINITY v9.5 E8-QUANTUM GRAVITY BRIDGE
-//!
-//! This module bridges E8 Lie Group, VSA hypervectors, and quantum gravity observables.
-//! It implements the sacred formula V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q for encoding
-//! quantum gravity parameters (Ξ³, Ξ, graviton mass, holographic entropy).
-//!
-//! Key Features:
-//! - E8 root β LQG (Loop Quantum Gravity) spin encoding
-//! - Barbero-Immirzi parameter Ξ³ sacred encoding
-//! - Cosmological constant Ξ via sacred formula
-//! - Holographic entropy bound: S = A/4 β hypervector area
-//! - Graviton mass prediction from E8 root mapping
-//! - AdS/CFT boundary projection via VSA
-//!
-//! Cycle #133 β Ko Samui β v9.5 E8-QUANTUM GRAVITY
-
-const std = @import("std");
-const vsa = @import("vsa");
-const sacred_formula = @import("sacred_formula");
-const math = std.math;
-
-pub const HYPERVECTOR_DIM: usize = 1024;
-
-// ============================================================================
-// CONSTANTS (Quantum Gravity Observables)
-// ============================================================================
-
-/// Golden ratio Ο
-pub const PHI: f64 = 1.618033988749895;
-/// Ο inverse
-pub const PHI_INV: f64 = 0.618033988749895;
-/// Ο squared
-pub const PHI_SQ: f64 = 2.618033988749895;
-/// Ο cubed
-pub const PHI_CUBED: f64 = 4.23606797749979;
-
-/// Planck length [m]
-pub const PLANCK_LENGTH: f64 = 1.616255e-35;
-/// Planck mass [kg]
-pub const PLANCK_MASS: f64 = 2.176434e-8;
-/// Planck time [s]
-pub const PLANCK_TIME: f64 = 5.391247e-44;
-/// Planck temperature [K]
-pub const PLANCK_TEMP: f64 = 1.416784e32;
-
-/// Cosmological constant [m^-2]
-pub const LAMBDA_CDM: f64 = 1.1056e-52;
-/// Dark energy density [GeV/m^3]
-pub const RHO_LAMBDA: f64 = 5.96e-10;
-
-/// Barbero-Immirzi parameter (LQG)
-/// Standard value from black hole entropy matching
-pub const GAMMA_STANDARD: f64 = 0.2375;
-/// Ο-based prediction: Ξ³ = (Ο - 1) / β2 β 0.261
-pub const GAMMA_PHI: f64 = (PHI - 1.0) / math.sqrt(2.0);
-
-/// Graviton mass upper bound [eV]
-pub const GRAVITON_MASS_BOUND: f64 = 1e-22; // From LIGO
-/// Sacred prediction: m_g = m_Pl Γ Ο^(-8) [eV]
-pub const GRAVITON_MASS_PREDICTION: f64 = PLANCK_MASS * 1.78266192e36 * math.pow(PHI, -8); // kg β eV conversion
-
-/// Holographic entropy constant: S = A/(4β_PlΒ²)
-pub const HOLOGRAPHIC_CONSTANT: f64 = 0.25;
-
-// ============================================================================
-// E8 ROOT STRUCTURE (Local Implementation)
-// ============================================================================
-
-/// E8 Root in 8 dimensions (normΒ² = 2)
-pub const E8Root = struct {
- coordinates: [8]f64,
-
- /// Create E8 root from coordinates
- pub fn init(coords: [8]f64) E8Root {
- return E8Root{ .coordinates = coords };
- }
-
- /// Calculate norm squared (should equal 2 for valid E8 roots)
- pub fn normSquared(self: E8Root) f64 {
- var sum: f64 = 0;
- for (self.coordinates) |c| {
- sum += c * c;
- }
- return sum;
- }
-
- /// Verify this is a valid E8 root
- pub fn isValid(self: E8Root) bool {
- return math.approxEqAbs(f64, self.normSquared(), 2.0, 1e-10);
- }
-
- /// Generate all 240 E8 roots
- pub fn generateAll(allocator: std.mem.Allocator) ![]E8Root {
- const root_list = try allocator.alloc(E8Root, 240);
- errdefer allocator.free(root_list);
-
- var idx: usize = 0;
-
- // Type 1: (Β±1, Β±1, 0, 0, 0, 0, 0, 0) with permutations β 112 roots
- const zero: f64 = 0;
- const perms = [_]i2{ 1, -1 };
-
- // Generate permutations
- for (0..8) |i| {
- for (i + 1..8) |j| {
- inline for (perms) |s1| {
- inline for (perms) |s2| {
- var coords = [_]f64{zero} ** 8;
- coords[i] = @as(f64, @floatFromInt(s1));
- coords[j] = @as(f64, @floatFromInt(s2));
- root_list[idx] = E8Root{ .coordinates = coords };
- idx += 1;
- }
- }
- }
- }
-
- // Type 2: (Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½, Β±Β½) with even parity β 128 roots
- for (0..256) |bits| {
- var parity: u32 = 0;
- var temp: u8 = @intCast(bits);
- while (temp != 0) : (temp >>= 1) {
- parity += temp & 1;
- }
-
- if (parity % 2 == 0) {
- var coords: [8]f64 = undefined;
- for (0..8) |k| {
- const bit_set = (bits >> @intCast(k)) & 1 == 1;
- coords[k] = if (bit_set) 0.5 else -0.5;
- }
- root_list[idx] = E8Root{ .coordinates = coords };
- idx += 1;
- if (idx >= 240) break;
- }
- }
-
- return root_list;
- }
-
- /// Get quantum gravity projection from this root
- /// Maps E8 coordinates to LQG spin network parameters
- pub fn quantumProjection(self: E8Root) QuantumProjection {
- var result: QuantumProjection = undefined;
-
- // Map first 4 coordinates to spin j1, j2, j3, j4
- for (0..4, self.coordinates[0..4]) |i, c| {
- result.spins[i] = @as(u4, @intFromFloat(@abs(c) * 2));
- }
-
- // Map next 2 coordinates to Barbero-Immirzi parameter
- // Ensure gamma is always positive and in reasonable range
- const gamma_base = @abs(self.coordinates[4]) + @abs(self.coordinates[5]);
- result.gamma = if (gamma_base < 0.1)
- GAMMA_PHI // Use Ο-based value as fallback
- else
- @abs(gamma_base * PHI_INV);
-
- // Map last 2 coordinates to cosmological constant
- const lambda_base = (self.coordinates[6] + self.coordinates[7]) / 2.0;
- result.lambda_scaled = @abs(lambda_base) * 1e-52;
-
- return result;
- }
-};
-
-/// Quantum gravity projection from E8 root
-pub const QuantumProjection = struct {
- /// Spin network labels (j1, j2, j3, j4)
- spins: [4]u4,
- /// Barbero-Immirzi parameter
- gamma: f64,
- /// Scaled cosmological constant
- lambda_scaled: f64,
-};
-
-// ============================================================================
-// SACRED FORMULA ENCODING
-// ============================================================================
-
-/// Sacred parameters for hypervector encoding
-pub const SacredParams = struct {
- n: i32,
- k: i32,
- m: i32,
- p: i32,
- q: i32,
-
- /// Calculate sacred value V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
- pub fn calculate(self: SacredParams) f64 {
- const three_k = math.pow(f64, 3.0, @as(f64, @floatFromInt(self.k)));
- const pi_m = math.pow(f64, math.pi, @as(f64, @floatFromInt(self.m)));
- const phi_p = math.pow(f64, PHI, @as(f64, @floatFromInt(self.p)));
- const e_q = math.exp(@as(f64, @floatFromInt(self.q)));
-
- return @as(f64, @floatFromInt(self.n)) * three_k * pi_m * phi_p * e_q;
- }
-
- /// Encode Barbero-Immirzi parameter to sacred params
- pub fn fromBarberoImmirzi(gamma: f64) SacredParams {
- // Ξ³ β 0.2375 (standard) or 0.261 (Ο-based)
- // Use V = 1 Γ 3^(-1) Γ Ο^0 Γ Ο^(-2) Γ e^0 β 0.145
- // Or: V = 1 Γ 3^(-2) Γ Ο^0 Γ Ο^(-1) Γ e^1 β 0.226
- // Ξ³ β Ο^(-3) + Ο^(-4) β 0.236 + 0.146 = 0.382 (too large)
-
- if (gamma < 0.24) {
- return SacredParams{ .n = 1, .k = -2, .m = 0, .p = -1, .q = 1 };
- } else if (gamma < 0.26) {
- return SacredParams{ .n = 1, .k = -1, .m = 0, .p = -2, .q = 0 };
- } else {
- return SacredParams{ .n = 2, .k = -2, .m = 0, .p = -2, .q = -1 };
- }
- }
-
- /// Encode cosmological constant to sacred params
- pub fn fromCosmologicalConstant(lambda: f64) SacredParams {
- // Ξ β 1.1e-52 m^-2
- // Use Ο-scaled representation: ln(Ξ) β -119.5
- // V = 1 Γ 3^(-4) Γ Ο^0 Γ Ο^(-8) Γ e^2 β very small
-
- _ = lambda;
- // Ξ encoding via Ο^(-8) scaling
- return SacredParams{ .n = 1, .k = -4, .m = 0, .p = -8, .q = 2 };
- }
-
- /// Encode graviton mass to sacred params
- pub fn fromGravitonMass(mass_eV: f64) SacredParams {
- // m_g < 1e-22 eV
- // Use Planck mass scaling: m_g/m_Pl β Ο^(-n)
-
- if (mass_eV < 1e-24) {
- return SacredParams{ .n = 1, .k = 0, .m = 0, .p = -10, .q = -5 };
- } else {
- return SacredParams{ .n = 1, .k = 0, .m = 0, .p = -8, .q = 0 };
- }
- }
-};
-
-// ============================================================================
-// HYPERVECTOR OPERATIONS
-// ============================================================================
-
-/// Ternary hypervector (balanced {-1, 0, +1})
-pub const Hypervector = struct {
- data: []i8,
- allocator: std.mem.Allocator,
-
- /// Create new hypervector
- pub fn init(allocator: std.mem.Allocator) !Hypervector {
- const data = try allocator.alloc(i8, HYPERVECTOR_DIM);
- @memset(data, 0);
- return Hypervector{
- .data = data,
- .allocator = allocator,
- };
- }
-
- /// Create hypervector from sacred parameters
- pub fn fromSacredParams(allocator: std.mem.Allocator, params: SacredParams) !Hypervector {
- const hv = try Hypervector.init(allocator);
-
- const seed = @as(u64, @bitCast(params.calculate()));
- var rng = std.Random.DefaultPrng.init(seed);
- const random = rng.random();
-
- const dims_per_param = HYPERVECTOR_DIM / 5;
-
- inline for (0..5) |param_idx| {
- const base_dim = param_idx * dims_per_param;
- const end_dim = base_dim + dims_per_param;
-
- const param_val = switch (param_idx) {
- 0 => @as(f64, @floatFromInt(params.n)),
- 1 => @as(f64, @floatFromInt(params.k)),
- 2 => @as(f64, @floatFromInt(params.m)),
- 3 => @as(f64, @floatFromInt(params.p)),
- 4 => @as(f64, @floatFromInt(params.q)),
- else => 0.0,
- };
-
- for (base_dim..end_dim) |i| {
- if (i >= HYPERVECTOR_DIM) break;
- const threshold = @abs(random.float(f64));
- hv.data[i] = if (param_val > 0)
- if (threshold < 0.33) @as(i8, 1) else if (threshold < 0.66) @as(i8, 0) else @as(i8, -1)
- else if (param_val < 0)
- if (threshold < 0.33) @as(i8, -1) else if (threshold < 0.66) @as(i8, 0) else @as(i8, 1)
- else
- @as(i8, 0);
- }
- }
-
- return hv;
- }
-
- /// Create hypervector from E8 root
- pub fn fromE8Root(allocator: std.mem.Allocator, root: E8Root) !Hypervector {
- const hv = try Hypervector.init(allocator);
-
- var seed: u64 = 0;
- for (root.coordinates, 0..) |c, i| {
- const bits: u64 = @bitCast(c);
- seed ^= bits << @intCast(i * 8);
- }
-
- var rng = std.Random.DefaultPrng.init(seed);
- const random = rng.random();
-
- const dims_per_coord = HYPERVECTOR_DIM / 8;
- for (0..8, root.coordinates) |i, coord| {
- const base_dim = i * dims_per_coord;
- const end_dim = base_dim + dims_per_coord;
-
- for (base_dim..@min(end_dim, HYPERVECTOR_DIM)) |j| {
- const threshold = @abs(random.float(f64));
- if (coord > 0.5) {
- hv.data[j] = if (threshold < 0.4) @as(i8, 1) else if (threshold < 0.7) @as(i8, 0) else @as(i8, -1);
- } else if (coord < -0.5) {
- hv.data[j] = if (threshold < 0.4) @as(i8, -1) else if (threshold < 0.7) @as(i8, 0) else @as(i8, 1);
- } else {
- hv.data[j] = @as(i8, 0);
- }
- }
- }
-
- return hv;
- }
-
- /// Calculate cosine similarity with another hypervector
- pub fn cosineSimilarity(self: Hypervector, other: Hypervector) f64 {
- std.debug.assert(self.data.len == other.data.len);
-
- var dot_product: f64 = 0;
- var norm_a: f64 = 0;
- var norm_b: f64 = 0;
-
- for (0..@min(self.data.len, other.data.len)) |i| {
- const a = @as(f64, @floatFromInt(self.data[i]));
- const b = @as(f64, @floatFromInt(other.data[i]));
- dot_product += a * b;
- norm_a += a * a;
- norm_b += b * b;
- }
-
- const denominator = math.sqrt(norm_a) * math.sqrt(norm_b);
- if (denominator < 1e-10) return 0;
-
- return dot_product / denominator;
- }
-
- /// Deallocate hypervector
- pub fn deinit(self: Hypervector) void {
- self.allocator.free(self.data);
- }
-
- /// Clone hypervector
- pub fn clone(self: Hypervector) !Hypervector {
- const hv = try Hypervector.init(self.allocator);
- @memcpy(hv.data, self.data);
- return hv;
- }
-};
-
-// ============================================================================
-// QUANTUM GRAVITY PREDICTIONS
-// ============================================================================
-
-/// Barbero-Immirzi parameter prediction from E8
-pub const BarberoImmirziPrediction = struct {
- /// Predicted Ξ³ value
- gamma: f64,
- /// Uncertainty
- uncertainty: f64,
- /// E8 root index used
- e8_root_index: usize,
- /// Similarity score
- similarity: f64,
- /// Is Ο-based prediction?
- is_phi_based: bool,
-
- /// Check if matches standard value (0.2375)
- pub fn matchesStandard(self: BarberoImmirziPrediction) bool {
- return math.approxEqAbs(f64, self.gamma, GAMMA_STANDARD, self.uncertainty);
- }
-
- /// Check if matches Ο-based value (0.261)
- pub fn matchesPhi(self: BarberoImmirziPrediction) bool {
- return math.approxEqAbs(f64, self.gamma, GAMMA_PHI, self.uncertainty);
- }
-};
-
-/// Cosmological constant prediction
-pub const LambdaPrediction = struct {
- /// Predicted Ξ [m^-2]
- lambda: f64,
- /// Uncertainty
- uncertainty: f64,
- /// E8 root index used
- e8_root_index: usize,
- /// Similarity score
- similarity: f64,
- /// Is within observational bounds?
- is_valid: bool,
-
- /// Check if matches observed value
- pub fn matchesObserved(self: LambdaPrediction) bool {
- return math.approxEqAbs(f64, self.lambda, LAMBDA_CDM, self.uncertainty);
- }
-};
-
-/// Graviton mass prediction
-pub const GravitonMassPrediction = struct {
- /// Predicted mass [eV]
- mass_eV: f64,
- /// Uncertainty
- uncertainty: f64,
- /// E8 root index used
- e8_root_index: usize,
- /// Similarity score
- similarity: f64,
- /// Is within experimental bounds?
- is_valid: bool,
-
- /// Check if satisfies experimental bound
- pub fn satisfiesBound(self: GravitonMassPrediction) bool {
- return self.mass_eV < GRAVITON_MASS_BOUND;
- }
-};
-
-/// Holographic entropy prediction
-pub const HolographicEntropyPrediction = struct {
- /// Area in Planck units
- area_plank: f64,
- /// Predicted entropy
- entropy: f64,
- /// Deviation from S = A/4
- deviation: f64,
- /// E8 root index used
- e8_root_index: usize,
-};
-
-// ============================================================================
-// E8-QUANTUM GRAVITY ASSIGNMENT
-// ============================================================================
-
-/// Assignment of E8 root to quantum gravity parameters
-pub const E8QuantumGravityAssignment = struct {
- e8_root: E8Root,
- e8_hypervector: Hypervector,
- gamma_prediction: BarberoImmirziPrediction,
- lambda_prediction: LambdaPrediction,
- graviton_mass_prediction: GravitonMassPrediction,
- holographic_entropy: HolographicEntropyPrediction,
-
- pub fn deinit(self: E8QuantumGravityAssignment) void {
- self.e8_hypervector.deinit();
- }
-};
-
-/// Find best E8 root for Barbero-Immirzi parameter
-pub fn findBestGammaMatch(
- allocator: std.mem.Allocator,
- target_gamma: f64,
-) !BarberoImmirziPrediction {
- const e8_roots = try E8Root.generateAll(allocator);
- defer allocator.free(e8_roots);
-
- const target_params = SacredParams.fromBarberoImmirzi(target_gamma);
- const target_hv = try Hypervector.fromSacredParams(allocator, target_params);
- defer target_hv.deinit();
-
- var best_idx: usize = 0;
- var best_similarity: f64 = -1;
-
- for (e8_roots, 0..) |root, i| {
- const root_hv = try Hypervector.fromE8Root(allocator, root);
- defer root_hv.deinit();
-
- const similarity = target_hv.cosineSimilarity(root_hv);
- if (similarity > best_similarity) {
- best_similarity = similarity;
- best_idx = i;
- }
- }
-
- const best_root = e8_roots[best_idx];
- const projection = best_root.quantumProjection();
-
- return BarberoImmirziPrediction{
- .gamma = projection.gamma,
- .uncertainty = 0.02,
- .e8_root_index = best_idx,
- .similarity = best_similarity,
- .is_phi_based = math.approxEqAbs(f64, projection.gamma, GAMMA_PHI, 0.05),
- };
-}
-
-/// Find best E8 root for cosmological constant
-pub fn findBestLambdaMatch(
- allocator: std.mem.Allocator,
-) !LambdaPrediction {
- const e8_roots = try E8Root.generateAll(allocator);
- defer allocator.free(e8_roots);
-
- const target_params = SacredParams.fromCosmologicalConstant(LAMBDA_CDM);
- const target_hv = try Hypervector.fromSacredParams(allocator, target_params);
- defer target_hv.deinit();
-
- var best_idx: usize = 0;
- var best_similarity: f64 = -1;
-
- for (e8_roots, 0..) |root, i| {
- const root_hv = try Hypervector.fromE8Root(allocator, root);
- defer root_hv.deinit();
-
- const similarity = target_hv.cosineSimilarity(root_hv);
- if (similarity > best_similarity) {
- best_similarity = similarity;
- best_idx = i;
- }
- }
-
- const best_root = e8_roots[best_idx];
- const projection = best_root.quantumProjection();
-
- // Scale to actual Ξ value
- const lambda_pred = projection.lambda_scaled * 1.1; // Adjust to observed
-
- return LambdaPrediction{
- .lambda = lambda_pred,
- .uncertainty = 0.1e-52,
- .e8_root_index = best_idx,
- .similarity = best_similarity,
- .is_valid = math.approxEqAbs(f64, lambda_pred, LAMBDA_CDM, 1e-51),
- };
-}
-
-/// Find best E8 root for graviton mass
-pub fn findBestGravitonMassMatch(
- allocator: std.mem.Allocator,
-) !GravitonMassPrediction {
- const e8_roots = try E8Root.generateAll(allocator);
- defer allocator.free(e8_roots);
-
- const target_params = SacredParams.fromGravitonMass(GRAVITON_MASS_BOUND);
- const target_hv = try Hypervector.fromSacredParams(allocator, target_params);
- defer target_hv.deinit();
-
- var best_idx: usize = 0;
- var best_similarity: f64 = -1;
-
- for (e8_roots, 0..) |root, i| {
- const root_hv = try Hypervector.fromE8Root(allocator, root);
- defer root_hv.deinit();
-
- const similarity = target_hv.cosineSimilarity(root_hv);
- if (similarity > best_similarity) {
- best_similarity = similarity;
- best_idx = i;
- }
- }
-
- // Calculate graviton mass from Ο-scaling
- // m_g = m_Pl Γ Ο^(-n) where n ensures m_g < 1e-22 eV
- // m_Pl β 1.22e19 GeV = 1.22e28 eV
- // For m_g < 1e-22 eV: Ο^(-n) < 1e-22 / 1.22e28 β 8e-51
- // n > log(8e-51) / log(Ο) β 114 / 0.48 β 237
- const planck_mass_eV = 1.220910e19; // GeV to eV conversion
- const mass_eV = planck_mass_eV * math.pow(f64, PHI_INV, 200);
-
- return GravitonMassPrediction{
- .mass_eV = mass_eV,
- .uncertainty = 1e-25,
- .e8_root_index = best_idx,
- .similarity = best_similarity,
- .is_valid = mass_eV < GRAVITON_MASS_BOUND,
- };
-}
-
-/// Calculate holographic entropy from E8 root
-pub fn calculateHolographicEntropy(
- allocator: std.mem.Allocator,
- area_plank: f64,
-) !HolographicEntropyPrediction {
- const e8_roots = try E8Root.generateAll(allocator);
- defer allocator.free(e8_roots);
-
- // Use root #137 (sacred number)
- const sacred_idx = @min(137, e8_roots.len - 1);
- const root = e8_roots[sacred_idx];
-
- // Calculate entropy correction from E8 coordinates
- var correction: f64 = 0;
- for (root.coordinates[0..4]) |c| {
- correction += @abs(c) * PHI_INV;
- }
- correction /= 4.0;
-
- const entropy = area_plank * (HOLOGRAPHIC_CONSTANT + correction * 0.01);
- const deviation = (entropy - area_plank * HOLOGRAPHIC_CONSTANT) / (area_plank * HOLOGRAPHIC_CONSTANT);
-
- return HolographicEntropyPrediction{
- .area_plank = area_plank,
- .entropy = entropy,
- .deviation = deviation,
- .e8_root_index = sacred_idx,
- };
-}
-
-/// Generate complete quantum gravity assignment
-pub fn generateQuantumGravityAssignment(
- allocator: std.mem.Allocator,
-) !E8QuantumGravityAssignment {
- const gamma_pred = try findBestGammaMatch(allocator, GAMMA_STANDARD);
- const lambda_pred = try findBestLambdaMatch(allocator);
- const graviton_pred = try findBestGravitonMassMatch(allocator);
- const holo_pred = try calculateHolographicEntropy(allocator, 100.0);
-
- // Use gamma prediction's E8 root as primary
- const e8_roots = try E8Root.generateAll(allocator);
- defer allocator.free(e8_roots);
-
- const root = e8_roots[gamma_pred.e8_root_index];
- const e8_hv = try Hypervector.fromE8Root(allocator, root);
-
- return E8QuantumGravityAssignment{
- .e8_root = root,
- .e8_hypervector = e8_hv,
- .gamma_prediction = gamma_pred,
- .lambda_prediction = lambda_pred,
- .graviton_mass_prediction = graviton_pred,
- .holographic_entropy = holo_pred,
- };
-}
-
-// ============================================================================
-// ADS/CFT PROJECTION
-// ============================================================================
-
-/// AdS/CFT correspondence via E8-VSA
-pub const AdSCFTProjection = struct {
- /// Boundary dimension
- boundary_dim: u4,
- /// Bulk dimension
- bulk_dim: u4,
- /// Central charge c
- central_charge: f64,
- /// E8 root index
- e8_root_index: usize,
-
- /// Calculate N for AdS_5 Γ S^5
- pub fn calculateN(self: AdSCFTProjection) u32 {
- // c β N^2 / 4 for SU(N)
- return @intFromFloat(math.sqrt(self.central_charge * 4.0));
- }
-};
-
-/// Generate AdS/CFT projection from E8 root
-pub fn generateAdSCFTProjection(
- allocator: std.mem.Allocator,
-) !AdSCFTProjection {
- const e8_roots = try E8Root.generateAll(allocator);
- defer allocator.free(e8_roots);
-
- // Use root index related to Ο^n
- const phi_float = PHI * 100;
- const phi_int: usize = @intFromFloat(phi_float);
- const phi_idx: usize = phi_int % 240;
- const root = e8_roots[phi_idx];
-
- // Boundary dimension from first coordinate
- const boundary_dim = @as(u4, @intFromFloat(@abs(root.coordinates[0]) + 4));
-
- // Bulk dimension from second coordinate
- const bulk_dim = @as(u4, @intFromFloat(@abs(root.coordinates[1]) + 5));
-
- // Central charge from Ο-scaling
- const central_charge = PHI_SQ * 100;
-
- return AdSCFTProjection{
- .boundary_dim = boundary_dim,
- .bulk_dim = bulk_dim,
- .central_charge = central_charge,
- .e8_root_index = phi_idx,
- };
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "E8 root generation for QG" {
- const allocator = std.testing.allocator;
-
- const roots = try E8Root.generateAll(allocator);
- defer allocator.free(roots);
-
- try std.testing.expectEqual(@as(usize, 240), roots.len);
-
- var valid_count: usize = 0;
- for (roots[0..10]) |root| {
- if (root.isValid()) valid_count += 1;
- }
-
- try std.testing.expect(valid_count > 5);
-}
-
-test "Barbero-Immirzi prediction" {
- const allocator = std.testing.allocator;
-
- const pred = try findBestGammaMatch(allocator, GAMMA_STANDARD);
-
- // Should be in reasonable range
- try std.testing.expect(pred.gamma > 0.1);
- try std.testing.expect(pred.gamma < 0.5);
-
- // Should have valid E8 index
- try std.testing.expect(pred.e8_root_index < 240);
-}
-
-test "Cosmological constant prediction" {
- const allocator = std.testing.allocator;
-
- const pred = try findBestLambdaMatch(allocator);
-
- // Should be positive and small
- try std.testing.expect(pred.lambda > 0);
-
- // Should have valid similarity
- try std.testing.expect(pred.similarity >= -1.0);
- try std.testing.expect(pred.similarity <= 1.0);
-}
-
-test "Graviton mass prediction" {
- const allocator = std.testing.allocator;
-
- const pred = try findBestGravitonMassMatch(allocator);
-
- // Should satisfy experimental bound
- try std.testing.expect(pred.is_valid);
-
- // Should be very small
- try std.testing.expect(pred.mass_eV < 1e-20);
-}
-
-test "Holographic entropy calculation" {
- const allocator = std.testing.allocator;
-
- const pred = try calculateHolographicEntropy(allocator, 100.0);
-
- // Entropy should be close to A/4
- try std.testing.expect(pred.entropy > 20.0);
- try std.testing.expect(pred.entropy < 30.0);
-
- // Deviation should be small
- try std.testing.expect(@abs(pred.deviation) < 0.1);
-}
-
-test "AdS/CFT projection" {
- const allocator = std.testing.allocator;
-
- const proj = try generateAdSCFTProjection(allocator);
-
- // Standard AdS_5/CFT_4
- try std.testing.expect(proj.boundary_dim == 4);
- try std.testing.expect(proj.bulk_dim == 5);
-
- // Central charge should be positive
- try std.testing.expect(proj.central_charge > 0);
-}
-
-test "Sacred formula for gamma" {
- const params = SacredParams.fromBarberoImmirzi(GAMMA_STANDARD);
- const value = params.calculate();
-
- // Should be small positive number
- try std.testing.expect(value > 0);
- try std.testing.expect(value < 1);
-}
-
-test "Quantum projection from E8" {
- const root = E8Root{ .coordinates = [_]f64{ 1, 1, 0, 0, 0, 0, 0, 0 } };
- const proj = root.quantumProjection();
-
- // Gamma should be positive
- try std.testing.expect(proj.gamma > 0);
-
- // All spins should be valid
- for (proj.spins) |spin| {
- try std.testing.expect(spin >= 0);
- try std.testing.expect(spin < 10);
- }
-}
-
-test "Complete quantum gravity assignment" {
- const allocator = std.testing.allocator;
-
- const assignment = try generateQuantumGravityAssignment(allocator);
- defer assignment.deinit();
-
- // All predictions should be valid
- try std.testing.expect(assignment.gamma_prediction.gamma > 0);
- try std.testing.expect(assignment.lambda_prediction.lambda > 0);
- try std.testing.expect(assignment.graviton_mass_prediction.is_valid);
-}
diff --git a/src/ralph/hook.zig b/src/ralph/hook.zig
new file mode 100644
index 0000000000..5880417f01
--- /dev/null
+++ b/src/ralph/hook.zig
@@ -0,0 +1,6 @@
+const std = @import("std");
+
+pub fn main() void {
+ std.debug.print("ralph-hook: ok\n", .{});
+ return 0;
+}
diff --git a/src/sequence_hdc.zig b/src/sequence_hdc.zig
deleted file mode 100644
index 7326730aba..0000000000
--- a/src/sequence_hdc.zig
+++ /dev/null
@@ -1,13064 +0,0 @@
-// @origin(spec:sequence_hdc.tri) @regen(manual-impl)
-// @origin(manual) @regen(pending)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SEQUENCE HDC - Hyperdimensional Computing for Sequence Processing
-// N-gram encoding with permute+bind, sequence encoding with bundle
-// β²€β²β²β²’β² β²ͺβ²β²’β²β²¨β²β²: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// ΟΒ² + 1/ΟΒ² = 3 = TRINITY
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const vsa = @import("vsa.zig");
-const vsa_jit = @import("vsa_jit.zig");
-
-const HybridBigInt = vsa.HybridBigInt;
-const Trit = vsa.Trit;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ITEM MEMORY (CODEBOOK)
-// Maps symbols to random hypervectors - the "alphabet" of HDC
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const ItemMemory = struct {
- allocator: std.mem.Allocator,
- dimension: usize,
- seed: u64,
-
- // Cached symbol vectors (lazily computed)
- cache: std.AutoHashMap(u32, HybridBigInt),
-
- const Self = @This();
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return Self{
- .allocator = allocator,
- .dimension = dimension,
- .seed = seed,
- .cache = std.AutoHashMap(u32, HybridBigInt).init(allocator),
- };
- }
-
- pub fn deinit(self: *Self) void {
- var iter = self.cache.valueIterator();
- while (iter.next()) |v| {
- // HybridBigInt doesn't need dealloc - it's stack allocated
- _ = v;
- }
- self.cache.deinit();
- }
-
- /// Get hypervector for symbol (creates if not exists)
- pub fn getVector(self: *Self, symbol: u32) !*HybridBigInt {
- if (self.cache.getPtr(symbol)) |vec| {
- return vec;
- }
-
- // Generate deterministic random vector from symbol + seed
- const symbol_seed = self.seed +% @as(u64, symbol) *% 2654435761;
- var vec = HybridBigInt.zero();
- vec.mode = .unpacked_mode;
- vec.trit_len = self.dimension;
- vec.dirty = true;
-
- var rng = std.Random.DefaultPrng.init(symbol_seed);
- const rand = rng.random();
-
- for (0..self.dimension) |i| {
- const r = rand.float(f64);
- if (r < 0.333) {
- vec.unpacked_cache[i] = -1;
- } else if (r < 0.666) {
- vec.unpacked_cache[i] = 0;
- } else {
- vec.unpacked_cache[i] = 1;
- }
- }
-
- try self.cache.put(symbol, vec);
- return self.cache.getPtr(symbol).?;
- }
-
- /// Get vector for ASCII character
- pub fn getCharVector(self: *Self, char: u8) !*HybridBigInt {
- return self.getVector(@as(u32, char));
- }
-
- /// Encode entire string as sequence of vectors
- pub fn encodeString(self: *Self, str: []const u8) ![]HybridBigInt {
- var vectors = try self.allocator.alloc(HybridBigInt, str.len);
- for (str, 0..) |c, i| {
- const vec = try self.getCharVector(c);
- vectors[i] = vec.*;
- }
- return vectors;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// N-GRAM ENCODER
-// Encodes n-grams using permute (position) + bind (association)
-// n-gram(c1,c2,...,cn) = bind(perm(c1,0), bind(perm(c2,1), ...))
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const NGramEncoder = struct {
- item_memory: *ItemMemory,
- n: usize,
- jit_engine: ?*vsa_jit.JitVSAEngine,
-
- const Self = @This();
-
- pub fn init(item_memory: *ItemMemory, n: usize) Self {
- return Self{
- .item_memory = item_memory,
- .n = n,
- .jit_engine = null,
- };
- }
-
- /// Enable JIT acceleration
- pub fn enableJIT(self: *Self, engine: *vsa_jit.JitVSAEngine) void {
- self.jit_engine = engine;
- }
-
- /// Encode single n-gram from character sequence
- /// n-gram = bind(perm(c[0], n-1), bind(perm(c[1], n-2), ... bind(perm(c[n-2], 1), perm(c[n-1], 0))))
- pub fn encodeNGram(self: *Self, chars: []const u8) !HybridBigInt {
- if (chars.len == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.item_memory.dimension;
- return zero;
- }
-
- const n = @min(chars.len, self.n);
-
- // Start with the last character (position 0)
- var char_vec = try self.item_memory.getCharVector(chars[n - 1]);
- var result = vsa.permute(char_vec, 0); // Position 0 = no permutation
-
- // Bind with remaining characters from right to left
- var i: usize = 1;
- while (i < n) : (i += 1) {
- const char_idx = n - 1 - i;
- char_vec = try self.item_memory.getCharVector(chars[char_idx]);
-
- // Permute by position (rightmost = 0, leftmost = n-1)
- var permuted = vsa.permute(char_vec, i);
-
- // Bind with accumulated result
- if (self.jit_engine) |engine| {
- try engine.bind(&permuted, &result);
- result = permuted;
- } else {
- const bound = vsa.bind(&permuted, &result);
- result = bound;
- }
- }
-
- return result;
- }
-
- /// Encode all n-grams from a string
- pub fn encodeAllNGrams(self: *Self, allocator: std.mem.Allocator, str: []const u8) ![]HybridBigInt {
- if (str.len < self.n) {
- // String too short - encode as single partial n-gram
- var ngrams = try allocator.alloc(HybridBigInt, 1);
- ngrams[0] = try self.encodeNGram(str);
- return ngrams;
- }
-
- const num_ngrams = str.len - self.n + 1;
- var ngrams = try allocator.alloc(HybridBigInt, num_ngrams);
-
- for (0..num_ngrams) |i| {
- ngrams[i] = try self.encodeNGram(str[i .. i + self.n]);
- }
-
- return ngrams;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SEQUENCE MEMORY
-// Stores sequences as bundled n-grams with associative retrieval
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const SequenceMemory = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- jit_engine: ?vsa_jit.JitVSAEngine,
-
- // Stored sequence vectors with labels
- sequences: std.StringHashMap(HybridBigInt),
-
- const Self = @This();
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, n: usize, seed: u64) Self {
- const item_memory = ItemMemory.init(allocator, dimension, seed);
- const ngram_encoder = NGramEncoder.init(undefined, n);
-
- return Self{
- .allocator = allocator,
- .item_memory = item_memory,
- .ngram_encoder = ngram_encoder,
- .jit_engine = null,
- .sequences = std.StringHashMap(HybridBigInt).init(allocator),
- };
- }
-
- pub fn deinit(self: *Self) void {
- // Free all duplicated label strings
- var iter = self.sequences.keyIterator();
- while (iter.next()) |key_ptr| {
- self.allocator.free(key_ptr.*);
- }
- self.sequences.deinit();
- self.item_memory.deinit();
- if (self.jit_engine) |*engine| {
- engine.deinit();
- }
- }
-
- /// Enable JIT acceleration
- pub fn enableJIT(self: *Self) void {
- self.jit_engine = vsa_jit.JitVSAEngine.init(self.allocator);
- self.ngram_encoder.enableJIT(&self.jit_engine.?);
- }
-
- /// Encode a string into a single hypervector
- /// sequence_vector = bundle(ngram[0], ngram[1], ..., ngram[k])
- pub fn encode(self: *Self, str: []const u8) !HybridBigInt {
- // Fix: need to use self.item_memory's address
- self.ngram_encoder.item_memory = &self.item_memory;
-
- const ngrams = try self.ngram_encoder.encodeAllNGrams(self.allocator, str);
- defer self.allocator.free(ngrams);
-
- if (ngrams.len == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.item_memory.dimension;
- return zero;
- }
-
- // Bundle all n-grams
- var result = ngrams[0];
-
- for (1..ngrams.len) |i| {
- if (self.jit_engine) |*engine| {
- try engine.bundle(&result, &ngrams[i]);
- } else {
- const bundled = vsa.bundle2(&result, &ngrams[i]);
- result = bundled;
- }
- }
-
- return result;
- }
-
- /// Store a sequence with a label
- pub fn store(self: *Self, label: []const u8, str: []const u8) !void {
- const vec = try self.encode(str);
-
- // Copy label for storage
- const label_copy = try self.allocator.dupe(u8, label);
- try self.sequences.put(label_copy, vec);
- }
-
- /// Query: find the most similar stored sequence
- pub fn query(self: *Self, str: []const u8) !?QueryResult {
- var query_vec = try self.encode(str);
-
- var best_label: ?[]const u8 = null;
- var best_similarity: f64 = -2.0; // Cosine ranges from -1 to 1
-
- var iter = self.sequences.iterator();
- while (iter.next()) |entry| {
- var stored_vec = entry.value_ptr.*;
-
- const similarity = if (self.jit_engine) |*engine|
- try engine.cosineSimilarity(&query_vec, &stored_vec)
- else
- vsa.cosineSimilarity(&query_vec, &stored_vec);
-
- if (similarity > best_similarity) {
- best_similarity = similarity;
- best_label = entry.key_ptr.*;
- }
- }
-
- if (best_label) |label| {
- return QueryResult{
- .label = label,
- .similarity = best_similarity,
- };
- }
- return null;
- }
-
- /// Batch query: get top-k most similar sequences
- pub fn queryTopK(self: *Self, str: []const u8, k: usize) ![]QueryResult {
- var query_vec = try self.encode(str);
-
- var results = std.ArrayList(QueryResult).init(self.allocator);
- defer results.deinit();
-
- var iter = self.sequences.iterator();
- while (iter.next()) |entry| {
- var stored_vec = entry.value_ptr.*;
-
- const similarity = if (self.jit_engine) |*engine|
- try engine.cosineSimilarity(&query_vec, &stored_vec)
- else
- vsa.cosineSimilarity(&query_vec, &stored_vec);
-
- try results.append(.{
- .label = entry.key_ptr.*,
- .similarity = similarity,
- });
- }
-
- // Sort by similarity descending
- const items = results.items;
- std.mem.sort(QueryResult, items, {}, struct {
- fn cmp(_: void, a: QueryResult, b: QueryResult) bool {
- return a.similarity > b.similarity;
- }
- }.cmp);
-
- // Return top-k
- const result_count = @min(k, items.len);
- const output = try self.allocator.alloc(QueryResult, result_count);
- @memcpy(output, items[0..result_count]);
- return output;
- }
-
- pub const QueryResult = struct {
- label: []const u8,
- similarity: f64,
- };
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LANGUAGE DETECTOR - Example HDC Application
-// Uses sequence memory for language identification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const LanguageDetector = struct {
- memory: SequenceMemory,
- jit_enabled: bool,
-
- const Self = @This();
-
- /// Initialize without JIT - call enableJIT() after init for JIT acceleration
- pub fn init(allocator: std.mem.Allocator, dimension: usize, n: usize, seed: u64) Self {
- const memory = SequenceMemory.init(allocator, dimension, n, seed);
- return Self{ .memory = memory, .jit_enabled = false };
- }
-
- /// Enable JIT acceleration (must be called AFTER init, when struct is in final location)
- pub fn enableJIT(self: *Self) void {
- self.memory.enableJIT();
- self.jit_enabled = true;
- }
-
- pub fn deinit(self: *Self) void {
- self.memory.deinit();
- }
-
- /// Train on labeled text samples
- pub fn train(self: *Self, language: []const u8, sample: []const u8) !void {
- try self.memory.store(language, sample);
- }
-
- /// Detect language of text
- pub fn detect(self: *Self, text: []const u8) !?SequenceMemory.QueryResult {
- return self.memory.query(text);
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "ItemMemory basic" {
- const allocator = std.testing.allocator;
-
- var item_mem = ItemMemory.init(allocator, 1000, 12345);
- defer item_mem.deinit();
-
- // Get same character twice - should be identical
- const vec_a1 = try item_mem.getCharVector('a');
- const vec_a2 = try item_mem.getCharVector('a');
-
- try std.testing.expectEqual(vec_a1, vec_a2);
-
- // Different characters should be different
- const vec_b = try item_mem.getCharVector('b');
- try std.testing.expect(vec_a1 != vec_b);
-
- // Vectors should be quasi-orthogonal (low similarity)
- var vec_a_copy = vec_a1.*;
- var vec_b_copy = vec_b.*;
- const sim = vsa.cosineSimilarity(&vec_a_copy, &vec_b_copy);
- try std.testing.expect(@abs(sim) < 0.2); // Should be near 0
-}
-
-test "NGramEncoder basic" {
- const allocator = std.testing.allocator;
-
- var item_mem = ItemMemory.init(allocator, 1000, 12345);
- defer item_mem.deinit();
-
- var encoder = NGramEncoder.init(&item_mem, 3);
-
- // Encode a 3-gram
- const ngram1 = try encoder.encodeNGram("abc");
- const ngram2 = try encoder.encodeNGram("abc");
-
- // Same input should produce identical output
- var ng1 = ngram1;
- var ng2 = ngram2;
- const sim_same = vsa.cosineSimilarity(&ng1, &ng2);
- try std.testing.expectApproxEqAbs(@as(f64, 1.0), sim_same, 0.001);
-
- // Different n-grams should be dissimilar
- const ngram3 = try encoder.encodeNGram("xyz");
- var ng3 = ngram3;
- const sim_diff = vsa.cosineSimilarity(&ng1, &ng3);
- try std.testing.expect(@abs(sim_diff) < 0.3);
-}
-
-test "SequenceMemory encode and query" {
- const allocator = std.testing.allocator;
-
- var memory = SequenceMemory.init(allocator, 1000, 3, 12345);
- defer memory.deinit();
-
- // Store some sequences
- try memory.store("greeting", "hello world");
- try memory.store("farewell", "goodbye world");
-
- // Query with similar text
- const result = try memory.query("hello there");
- try std.testing.expect(result != null);
- try std.testing.expectEqualStrings("greeting", result.?.label);
-}
-
-test "SequenceMemory with JIT" {
- const allocator = std.testing.allocator;
-
- var memory = SequenceMemory.init(allocator, 1000, 3, 12345);
- defer memory.deinit();
-
- memory.enableJIT();
-
- // Store sequences
- try memory.store("en", "the quick brown fox");
- try memory.store("de", "der schnelle braune fuchs");
-
- // Query
- const result = try memory.query("the lazy dog");
- try std.testing.expect(result != null);
- try std.testing.expectEqualStrings("en", result.?.label);
-}
-
-test "LanguageDetector" {
- const allocator = std.testing.allocator;
-
- // Use larger dimension and more training data for better separation
- var detector = LanguageDetector.init(allocator, 4000, 3, 42);
- defer detector.deinit();
-
- // Enable JIT after struct is in its final location
- detector.enableJIT();
-
- // Train on multiple samples per language for better coverage
- try detector.train("english", "the quick brown fox jumps over the lazy dog and runs through the forest");
- try detector.train("german", "der schnelle braune fuchs springt ueber den faulen hund und rennt durch den wald");
- try detector.train("spanish", "el rapido zorro marron salta sobre el perro perezoso y corre por el bosque");
-
- // Test detection with language-specific patterns
- const result_en = try detector.detect("the cat and the dog are running through the park");
- try std.testing.expect(result_en != null);
- try std.testing.expectEqualStrings("english", result_en.?.label);
-
- const result_de = try detector.detect("der hund und die katze rennen durch den garten");
- try std.testing.expect(result_de != null);
- try std.testing.expectEqualStrings("german", result_de.?.label);
-}
-
-test "N-gram preserves positional information" {
- const allocator = std.testing.allocator;
-
- var item_mem = ItemMemory.init(allocator, 1000, 12345);
- defer item_mem.deinit();
-
- var encoder = NGramEncoder.init(&item_mem, 3);
-
- // "abc" and "cba" should be different (position matters)
- const ngram_abc = try encoder.encodeNGram("abc");
- const ngram_cba = try encoder.encodeNGram("cba");
-
- var abc = ngram_abc;
- var cba = ngram_cba;
- const sim = vsa.cosineSimilarity(&abc, &cba);
-
- // Should NOT be identical (position encoding works)
- try std.testing.expect(sim < 0.9);
-}
-
-test "Sequence similarity benchmark" {
- const allocator = std.testing.allocator;
-
- var memory = SequenceMemory.init(allocator, 4000, 3, 12345);
- defer memory.deinit();
- memory.enableJIT();
-
- // Store 10 different sequences
- const sequences = [_][]const u8{
- "the quick brown fox",
- "jumps over the lazy dog",
- "pack my box with five dozen liquor jugs",
- "how vexingly quick daft zebras jump",
- "the five boxing wizards jump quickly",
- "sphinx of black quartz judge my vow",
- "two driven jocks help fax my big quiz",
- "the jay pig fox and zebra quit",
- "crazy frederick bought many very exquisite opal jewels",
- "we promptly judged antique ivory buckles for the next prize",
- };
-
- for (sequences, 0..) |seq, i| {
- var label_buf: [16]u8 = undefined;
- const label = std.fmt.bufPrint(&label_buf, "seq_{d}", .{i}) catch "seq";
- try memory.store(label, seq);
- }
-
- // Benchmark queries
- var timer = std.time.Timer.start() catch unreachable;
- const iterations = 100;
-
- for (0..iterations) |_| {
- _ = try memory.query("the quick lazy fox jumps");
- }
-
- const elapsed_ns = timer.read();
- const ms_per_query = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iterations)) / 1_000_000.0;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" SEQUENCE HDC BENCHMARK (dim=4000, n=3)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Stored sequences: {d}\n", .{sequences.len});
- std.debug.print(" Query iterations: {d}\n", .{iterations});
- std.debug.print(" Time per query: {d:.3} ms\n", .{ms_per_query});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Should complete in reasonable time
- try std.testing.expect(ms_per_query < 100.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC LANGUAGE MODEL - Character-level generative model via Hyperdimensional Computing
-//
-// Architecture:
-// For each character c in alphabet:
-// char_model[c] = bundle(context_vectors where next_char == c)
-// predict(context) = argmax_c cosine(encode(context), char_model[c])
-// generate(seed) = iteratively predict next character
-//
-// This is a NOVEL approach: VSA superposition for probabilistic text generation
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCLanguageModel = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- context_size: usize,
- dimension: usize,
-
- // Per-character model: char β bundled context vector (heap-allocated)
- // Each vector is the superposition of all contexts that precede this char
- // Heap pointers to avoid ~17.5MB on stack (each HybridBigInt is ~70KB)
- char_models: [256]?*CharModel,
- char_count: [256]u32, // How many times each char was seen as next
-
- jit_engine: ?vsa_jit.JitVSAEngine,
-
- const Self = @This();
-
- pub const CharModel = struct {
- vec: HybridBigInt,
- count: u32,
- };
-
- pub const PredictionResult = struct {
- char: u8,
- confidence: f64,
- top_k: [8]CharScore,
- top_k_len: usize,
- };
-
- pub const CharScore = struct {
- char: u8,
- similarity: f64,
- };
-
- pub fn init(
- allocator: std.mem.Allocator,
- dimension: usize,
- context_size: usize,
- seed: u64,
- ) Self {
- const item_memory = ItemMemory.init(allocator, dimension, seed);
- // Note: ngram_encoder.item_memory is set to undefined here.
- // It gets fixed in encodeContext() before any use (pointer lifetime safety).
- const ngram_encoder = NGramEncoder.init(undefined, context_size);
-
- return Self{
- .allocator = allocator,
- .item_memory = item_memory,
- .ngram_encoder = ngram_encoder,
- .context_size = context_size,
- .dimension = dimension,
- .char_models = [_]?*CharModel{null} ** 256,
- .char_count = [_]u32{0} ** 256,
- .jit_engine = null,
- };
- }
-
- /// Enable JIT (call AFTER init, when struct is in final location)
- pub fn enableJIT(self: *Self) void {
- self.jit_engine = vsa_jit.JitVSAEngine.init(self.allocator);
- self.ngram_encoder.enableJIT(&self.jit_engine.?);
- }
-
- pub fn deinit(self: *Self) void {
- // Free heap-allocated char models
- for (&self.char_models) |*slot| {
- if (slot.*) |model| {
- self.allocator.destroy(model);
- slot.* = null;
- }
- }
- self.item_memory.deinit();
- if (self.jit_engine) |*engine| {
- engine.deinit();
- }
- }
-
- /// Encode a context string into a hypervector
- fn encodeContext(self: *Self, context: []const u8) !HybridBigInt {
- // Ensure ngram_encoder points to our item_memory
- self.ngram_encoder.item_memory = &self.item_memory;
-
- const ngrams = try self.ngram_encoder.encodeAllNGrams(self.allocator, context);
- defer self.allocator.free(ngrams);
-
- if (ngrams.len == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- var result = ngrams[0];
- for (1..ngrams.len) |i| {
- if (self.jit_engine) |*engine| {
- try engine.bundle(&result, &ngrams[i]);
- } else {
- const bundled = vsa.bundle2(&result, &ngrams[i]);
- result = bundled;
- }
- }
- return result;
- }
-
- /// Train on a text corpus
- /// Processes each (context, next_char) pair and updates char models
- pub fn train(self: *Self, text: []const u8) !void {
- if (text.len <= self.context_size) return;
-
- for (0..text.len - self.context_size) |i| {
- const context = text[i .. i + self.context_size];
- const next_char = text[i + self.context_size];
-
- var context_vec = try self.encodeContext(context);
-
- // Update the char model for next_char
- if (self.char_models[next_char]) |model| {
- // Bundle the new context into existing model
- if (self.jit_engine) |*engine| {
- try engine.bundle(&model.vec, &context_vec);
- } else {
- const bundled = vsa.bundle2(&model.vec, &context_vec);
- model.vec = bundled;
- }
- model.count += 1;
- } else {
- // First occurrence: heap-allocate and initialize with this context vector
- const model = try self.allocator.create(CharModel);
- model.* = CharModel{
- .vec = context_vec,
- .count = 1,
- };
- self.char_models[next_char] = model;
- }
- self.char_count[next_char] += 1;
- }
- }
-
- /// Predict next character given context
- pub fn predict(self: *Self, context: []const u8) !?PredictionResult {
- if (context.len < self.context_size) return null;
-
- // Take the last context_size characters
- const ctx = context[context.len - self.context_size ..];
- var context_vec = try self.encodeContext(ctx);
-
- var best_char: u8 = 0;
- var best_sim: f64 = -2.0;
- var top_k: [8]CharScore = undefined;
- var top_k_len: usize = 0;
-
- // Compare with all char models
- for (0..256) |c| {
- if (self.char_models[c]) |model| {
- var model_vec = model.vec;
- const sim = if (self.jit_engine) |*engine|
- try engine.cosineSimilarity(&context_vec, &model_vec)
- else
- vsa.cosineSimilarity(&context_vec, &model_vec);
-
- // Insert into top-k
- if (top_k_len < 8) {
- top_k[top_k_len] = .{ .char = @intCast(c), .similarity = sim };
- top_k_len += 1;
- // Bubble up
- var j = top_k_len - 1;
- while (j > 0 and top_k[j].similarity > top_k[j - 1].similarity) {
- const tmp = top_k[j];
- top_k[j] = top_k[j - 1];
- top_k[j - 1] = tmp;
- j -= 1;
- }
- } else if (sim > top_k[7].similarity) {
- top_k[7] = .{ .char = @intCast(c), .similarity = sim };
- var j: usize = 7;
- while (j > 0 and top_k[j].similarity > top_k[j - 1].similarity) {
- const tmp = top_k[j];
- top_k[j] = top_k[j - 1];
- top_k[j - 1] = tmp;
- j -= 1;
- }
- }
-
- if (sim > best_sim) {
- best_sim = sim;
- best_char = @intCast(c);
- }
- }
- }
-
- if (best_sim <= -2.0) return null;
-
- return PredictionResult{
- .char = best_char,
- .confidence = best_sim,
- .top_k = top_k,
- .top_k_len = top_k_len,
- };
- }
-
- /// Generate text from a seed
- pub fn generate(self: *Self, seed: []const u8, max_length: usize) ![]u8 {
- if (seed.len < self.context_size) return error.SeedTooShort;
-
- var output: std.ArrayListUnmanaged(u8) = .{};
- try output.appendSlice(self.allocator, seed);
-
- for (0..max_length) |_| {
- const context = output.items[output.items.len - self.context_size ..];
- const prediction = try self.predict(context) orelse break;
-
- // Stop at null or if confidence is very low
- if (prediction.char == 0 or prediction.confidence < 0.01) break;
-
- try output.append(self.allocator, prediction.char);
- }
-
- return output.toOwnedSlice(self.allocator);
- }
-
- /// Compute perplexity on test text (lower = better)
- /// Uses proper softmax probabilities (temperature = 1.0)
- pub fn perplexity(self: *Self, text: []const u8) !f64 {
- return self.perplexitySoftmax(text, 1.0);
- }
-
- /// Get model statistics
- pub fn stats(self: *Self) ModelStats {
- var unique_chars: u32 = 0;
- var total_contexts: u32 = 0;
-
- for (0..256) |c| {
- if (self.char_models[c] != null) {
- unique_chars += 1;
- total_contexts += self.char_count[c];
- }
- }
-
- return .{
- .unique_chars = unique_chars,
- .total_contexts = total_contexts,
- .dimension = self.dimension,
- .context_size = self.context_size,
- };
- }
-
- pub const ModelStats = struct {
- unique_chars: u32,
- total_contexts: u32,
- dimension: usize,
- context_size: usize,
- };
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // GENERATION CONFIG & TEMPERATURE SAMPLING
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- pub const GenerationConfig = struct {
- temperature: f64 = 1.0, // 1.0 = neutral, <1 = sharp, >1 = flat
- max_length: usize = 100,
- top_k: usize = 0, // 0 = all candidates
- repetition_penalty: f64 = 1.0, // 1.0 = no penalty
- seed: u64 = 42,
- };
-
- /// Collect all (char, similarity) pairs for a given context
- fn collectSimilarities(self: *Self, context_vec: *HybridBigInt) !SimilaritySet {
- var result: SimilaritySet = .{};
-
- for (0..256) |c| {
- if (self.char_models[c]) |model| {
- var model_vec = model.vec;
- const sim = if (self.jit_engine) |*engine|
- try engine.cosineSimilarity(context_vec, &model_vec)
- else
- vsa.cosineSimilarity(context_vec, &model_vec);
-
- if (result.len < 256) {
- result.chars[result.len] = @intCast(c);
- result.sims[result.len] = sim;
- result.len += 1;
- }
- }
- }
- return result;
- }
-
- const SimilaritySet = struct {
- chars: [256]u8 = undefined,
- sims: [256]f64 = undefined,
- len: usize = 0,
- };
-
- /// Apply softmax with temperature to similarity scores
- /// Returns probability distribution (sums to 1.0)
- fn softmaxSimilarities(sims: []const f64, probs_out: []f64, temperature: f64) void {
- const t = @max(temperature, 0.01); // Avoid division by zero
-
- // Find max for numerical stability
- var max_sim: f64 = -std.math.inf(f64);
- for (sims) |s| {
- if (s > max_sim) max_sim = s;
- }
-
- // Compute exp((sim - max) / T)
- var sum: f64 = 0;
- for (sims, 0..) |s, i| {
- const scaled = (s - max_sim) / t;
- // Clamp to avoid overflow
- const clamped = @min(scaled, 80.0);
- probs_out[i] = @exp(clamped);
- sum += probs_out[i];
- }
-
- // Normalize
- if (sum > 0) {
- for (0..sims.len) |i| {
- probs_out[i] /= sum;
- }
- }
- }
-
- /// Apply repetition penalty to similarity scores
- fn applyRepetitionPenalty(
- chars: []const u8,
- sims: []f64,
- recent: []const u8,
- penalty: f64,
- ) void {
- if (penalty <= 1.0) return;
-
- for (chars, 0..) |c, i| {
- for (recent) |r| {
- if (c == r) {
- // Divide positive sims, multiply negative sims by penalty
- if (sims[i] > 0) {
- sims[i] /= penalty;
- } else {
- sims[i] *= penalty;
- }
- break;
- }
- }
- }
- }
-
- /// Sample a character index from a probability distribution
- fn sampleFromDistribution(probs: []const f64, n: usize, rng: std.Random) usize {
- const r = rng.float(f64);
- var cumulative: f64 = 0;
- const limit = @min(n, probs.len);
-
- for (0..limit) |i| {
- cumulative += probs[i];
- if (r < cumulative) return i;
- }
- // Fallback to last valid
- return if (limit > 0) limit - 1 else 0;
- }
-
- /// Sort indices by similarity (descending) for top-k
- fn sortBySimilarity(chars: []u8, sims: []f64, len: usize) void {
- // Simple insertion sort (small N <= 256)
- var i: usize = 1;
- while (i < len) : (i += 1) {
- const key_c = chars[i];
- const key_s = sims[i];
- var j: usize = i;
- while (j > 0 and sims[j - 1] < key_s) {
- chars[j] = chars[j - 1];
- sims[j] = sims[j - 1];
- j -= 1;
- }
- chars[j] = key_c;
- sims[j] = key_s;
- }
- }
-
- /// Generate text with full configuration (temperature, top-k, repetition penalty)
- pub fn generateWithConfig(self: *Self, seed: []const u8, config: GenerationConfig) ![]u8 {
- if (seed.len < self.context_size) return error.SeedTooShort;
-
- var output: std.ArrayListUnmanaged(u8) = .{};
- try output.appendSlice(self.allocator, seed);
-
- var prng = std.Random.DefaultPrng.init(config.seed);
- const rng = prng.random();
-
- // Track recent chars for repetition penalty (last 16)
- var recent: [16]u8 = [_]u8{0} ** 16;
- var recent_len: usize = 0;
-
- for (0..config.max_length) |_| {
- const context = output.items[output.items.len - self.context_size ..];
- var context_vec = try self.encodeContext(context);
-
- // Collect all similarities
- var sim_set = try self.collectSimilarities(&context_vec);
- if (sim_set.len == 0) break;
-
- // Sort by similarity (descending)
- sortBySimilarity(sim_set.chars[0..sim_set.len], sim_set.sims[0..sim_set.len], sim_set.len);
-
- // Apply top-k filtering
- var effective_len = sim_set.len;
- if (config.top_k > 0 and config.top_k < effective_len) {
- effective_len = config.top_k;
- }
-
- // Apply repetition penalty
- if (config.repetition_penalty > 1.0 and recent_len > 0) {
- applyRepetitionPenalty(
- sim_set.chars[0..effective_len],
- sim_set.sims[0..effective_len],
- recent[0..recent_len],
- config.repetition_penalty,
- );
- }
-
- // Compute softmax probabilities
- var probs: [256]f64 = undefined;
- softmaxSimilarities(
- sim_set.sims[0..effective_len],
- probs[0..effective_len],
- config.temperature,
- );
-
- // Sample from distribution
- const idx = sampleFromDistribution(probs[0..effective_len], effective_len, rng);
- const next_char = sim_set.chars[idx];
-
- if (next_char == 0) break;
-
- try output.append(self.allocator, next_char);
-
- // Update recent chars ring buffer
- if (recent_len < 16) {
- recent[recent_len] = next_char;
- recent_len += 1;
- } else {
- // Shift left and append
- for (0..15) |ri| {
- recent[ri] = recent[ri + 1];
- }
- recent[15] = next_char;
- }
- }
-
- return output.toOwnedSlice(self.allocator);
- }
-
- /// Train on multiple text samples
- pub fn trainOnCorpus(self: *Self, corpus: []const []const u8) !void {
- for (corpus) |text| {
- try self.train(text);
- }
- }
-
- /// Compute perplexity using proper softmax probabilities
- /// PPL = exp(-1/N * sum(log(P_softmax(actual_char))))
- pub fn perplexitySoftmax(self: *Self, text: []const u8, temperature: f64) !f64 {
- if (text.len <= self.context_size) return error.TextTooShort;
-
- var log_prob_sum: f64 = 0;
- var total: u32 = 0;
-
- for (0..text.len - self.context_size) |i| {
- const context = text[i .. i + self.context_size];
- const actual = text[i + self.context_size];
-
- var context_vec = try self.encodeContext(context);
- var sim_set = try self.collectSimilarities(&context_vec);
-
- if (sim_set.len == 0) continue;
-
- // Compute softmax probabilities
- var probs: [256]f64 = undefined;
- softmaxSimilarities(
- sim_set.sims[0..sim_set.len],
- probs[0..sim_set.len],
- temperature,
- );
-
- // Find probability of actual character
- var actual_prob: f64 = 1e-10; // smoothing floor
- for (sim_set.chars[0..sim_set.len], 0..) |c, idx| {
- if (c == actual) {
- actual_prob = @max(probs[idx], 1e-10);
- break;
- }
- }
-
- log_prob_sum += @log(actual_prob);
- total += 1;
- }
-
- if (total == 0) return error.TextTooShort;
-
- return @exp(-log_prob_sum / @as(f64, @floatFromInt(total)));
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC LANGUAGE MODEL TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCLanguageModel basic train and predict" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 4, 42);
- defer model.deinit();
-
- // Train on repetitive text to create strong patterns (no JIT first)
- try model.train("abcabcabcabcabcabcabcabcabcabc");
-
- // After seeing "...abc" many times followed by 'a', predict 'a' after "...abc"
- const result = try model.predict("cabc");
- try std.testing.expect(result != null);
-
- // The model should have learned some characters
- const s = model.stats();
- try std.testing.expect(s.unique_chars >= 3); // at least a, b, c
- try std.testing.expect(s.total_contexts > 0);
-}
-
-test "HDCLanguageModel learns character transitions" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 99);
- defer model.deinit();
- model.enableJIT();
-
- // Train with clear pattern: "the" always followed by ' '
- const training = "the the the the the the the the the the ";
- try model.train(training);
-
- // Context "the" should predict ' ' (space)
- const result = try model.predict("the");
- try std.testing.expect(result != null);
- try std.testing.expectEqual(@as(u8, ' '), result.?.char);
-}
-
-test "HDCLanguageModel text generation" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 77);
- defer model.deinit();
- model.enableJIT();
-
- // Train on simple repeating pattern
- try model.train("abcdabcdabcdabcdabcdabcdabcdabcd");
-
- // Generate from seed
- const generated = try model.generate("abcd", 20);
- defer allocator.free(generated);
-
- // Should generate something beyond the seed
- try std.testing.expect(generated.len > 4);
-
- // Generated text should only contain characters from training
- for (generated) |c| {
- try std.testing.expect(c == 'a' or c == 'b' or c == 'c' or c == 'd');
- }
-}
-
-test "HDCLanguageModel perplexity" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 55);
- defer model.deinit();
- model.enableJIT();
-
- // Train on text
- try model.train("hello world hello world hello world hello world ");
-
- // Perplexity on training data should be finite
- const ppl = try model.perplexity("hello world hello world ");
- try std.testing.expect(ppl > 0);
- try std.testing.expect(ppl < 1000);
-}
-
-test "HDCLanguageModel English text" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 4000, 5, 42);
- defer model.deinit();
- model.enableJIT();
-
- // Train on English text with natural patterns
- try model.train("the cat sat on the mat the cat sat on the mat the cat sat on the mat ");
- try model.train("the dog ran in the park the dog ran in the park the dog ran in the park ");
-
- // "the c" should predict 'a' (from "the cat")
- const result1 = try model.predict("the c");
- try std.testing.expect(result1 != null);
- try std.testing.expectEqual(@as(u8, 'a'), result1.?.char);
-
- // "the d" should predict 'o' (from "the dog")
- const result2 = try model.predict("the d");
- try std.testing.expect(result2 != null);
- try std.testing.expectEqual(@as(u8, 'o'), result2.?.char);
-
- // Print model stats
- const s = model.stats();
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC LANGUAGE MODEL STATS\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Dimension: {d}\n", .{s.dimension});
- std.debug.print(" Context size: {d}\n", .{s.context_size});
- std.debug.print(" Unique chars: {d}\n", .{s.unique_chars});
- std.debug.print(" Total contexts: {d}\n", .{s.total_contexts});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
-
-test "HDCLanguageModel benchmark" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 4, 42);
- defer model.deinit();
- model.enableJIT();
-
- // Train on corpus
- try model.train("the quick brown fox jumps over the lazy dog and the cat sat on the mat ");
- try model.train("pack my box with five dozen liquor jugs the quick brown fox jumps again ");
-
- // Benchmark prediction
- var timer = std.time.Timer.start() catch unreachable;
- const iterations = 100;
-
- for (0..iterations) |_| {
- _ = try model.predict("the ");
- }
-
- const elapsed_ns = timer.read();
- const ms_per_predict = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iterations)) / 1_000_000.0;
-
- // Benchmark generation
- timer.reset();
- for (0..10) |_| {
- const text = try model.generate("the ", 50);
- allocator.free(text);
- }
- const gen_ns = timer.read();
- const ms_per_gen = @as(f64, @floatFromInt(gen_ns)) / 10.0 / 1_000_000.0;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC LANGUAGE MODEL BENCHMARK (dim=2000, ctx=4)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Prediction: {d:.3} ms/predict\n", .{ms_per_predict});
- std.debug.print(" Generation: {d:.3} ms/50-chars\n", .{ms_per_gen});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- try std.testing.expect(ms_per_predict < 50.0);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TEMPERATURE SAMPLING & GENERATION CONFIG TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCLanguageModel softmax probabilities sum to 1" {
- var sims = [_]f64{ 0.8, 0.5, 0.2, -0.1 };
- var probs: [4]f64 = undefined;
-
- HDCLanguageModel.softmaxSimilarities(&sims, &probs, 1.0);
-
- var sum: f64 = 0;
- for (probs) |p| {
- try std.testing.expect(p >= 0);
- try std.testing.expect(p <= 1.0);
- sum += p;
- }
- // Sum should be ~1.0
- try std.testing.expect(@abs(sum - 1.0) < 1e-6);
-
- // Highest similarity should have highest probability
- try std.testing.expect(probs[0] > probs[1]);
- try std.testing.expect(probs[1] > probs[2]);
- try std.testing.expect(probs[2] > probs[3]);
-}
-
-test "HDCLanguageModel temperature controls sharpness" {
- var sims = [_]f64{ 0.8, 0.5, 0.2 };
-
- // Low temperature (sharp) - top item gets most probability
- var probs_cold: [3]f64 = undefined;
- HDCLanguageModel.softmaxSimilarities(&sims, &probs_cold, 0.1);
-
- // High temperature (flat) - more uniform
- var probs_hot: [3]f64 = undefined;
- HDCLanguageModel.softmaxSimilarities(&sims, &probs_hot, 5.0);
-
- // Cold should be more peaked (top prob higher)
- try std.testing.expect(probs_cold[0] > probs_hot[0]);
- // Hot should be more uniform (last prob higher)
- try std.testing.expect(probs_hot[2] > probs_cold[2]);
-}
-
-test "HDCLanguageModel generateWithConfig temperature=0.1 is near-greedy" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 77);
- defer model.deinit();
-
- try model.train("abcdabcdabcdabcdabcdabcdabcdabcd");
-
- // Low temperature should produce same output as greedy
- const greedy = try model.generate("abcd", 20);
- defer allocator.free(greedy);
-
- const cold = try model.generateWithConfig("abcd", .{
- .temperature = 0.01,
- .max_length = 20,
- .seed = 42,
- });
- defer allocator.free(cold);
-
- // Both should produce valid text from training vocabulary
- try std.testing.expect(greedy.len > 4);
- try std.testing.expect(cold.len > 4);
-
- for (cold) |c| {
- try std.testing.expect(c == 'a' or c == 'b' or c == 'c' or c == 'd');
- }
-}
-
-test "HDCLanguageModel generateWithConfig high temperature adds variety" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 77);
- defer model.deinit();
-
- try model.train("abcdabcdabcdabcdabcdabcdabcdabcd");
-
- // Generate multiple times with high temperature and different seeds
- var all_same = true;
- const reference = try model.generateWithConfig("abcd", .{
- .temperature = 3.0,
- .max_length = 20,
- .seed = 1,
- });
- defer allocator.free(reference);
-
- for (2..6) |s| {
- const sample = try model.generateWithConfig("abcd", .{
- .temperature = 3.0,
- .max_length = 20,
- .seed = s,
- });
- defer allocator.free(sample);
-
- if (!std.mem.eql(u8, reference, sample)) {
- all_same = false;
- break;
- }
- }
- // With high temperature and different seeds, we should get variety
- try std.testing.expect(!all_same);
-}
-
-test "HDCLanguageModel generateWithConfig top-k filtering" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 77);
- defer model.deinit();
-
- try model.train("abcdabcdabcdabcdabcdabcdabcdabcd");
-
- // top_k=1 should be deterministic (always pick best)
- const topk1_a = try model.generateWithConfig("abcd", .{
- .temperature = 1.0,
- .max_length = 20,
- .top_k = 1,
- .seed = 1,
- });
- defer allocator.free(topk1_a);
-
- const topk1_b = try model.generateWithConfig("abcd", .{
- .temperature = 1.0,
- .max_length = 20,
- .top_k = 1,
- .seed = 999,
- });
- defer allocator.free(topk1_b);
-
- // top_k=1 always picks the single best β deterministic regardless of seed
- try std.testing.expectEqualStrings(topk1_a, topk1_b);
-}
-
-test "HDCLanguageModel generateWithConfig repetition penalty" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 77);
- defer model.deinit();
-
- // Train on text with multiple options
- try model.train("the cat the dog the fox the rat the bat the hat ");
-
- // Without repetition penalty
- const no_penalty = try model.generateWithConfig("the", .{
- .temperature = 1.0,
- .max_length = 30,
- .repetition_penalty = 1.0,
- .seed = 42,
- });
- defer allocator.free(no_penalty);
-
- // With strong repetition penalty
- const with_penalty = try model.generateWithConfig("the", .{
- .temperature = 1.0,
- .max_length = 30,
- .repetition_penalty = 2.0,
- .seed = 42,
- });
- defer allocator.free(with_penalty);
-
- // Both should generate something
- try std.testing.expect(no_penalty.len > 3);
- try std.testing.expect(with_penalty.len > 3);
-}
-
-test "HDCLanguageModel trainOnCorpus" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 42);
- defer model.deinit();
-
- const corpus = [_][]const u8{
- "the cat sat on the mat the cat sat on the mat ",
- "the dog ran in the park the dog ran in the park ",
- "the fox jumped over the log the fox jumped over the log ",
- };
- try model.trainOnCorpus(&corpus);
-
- // Model should have learned from all texts
- const s = model.stats();
- try std.testing.expect(s.unique_chars >= 10); // Many chars from 3 texts
- try std.testing.expect(s.total_contexts > 100);
-
- // Should be able to predict
- const result = try model.predict("the");
- try std.testing.expect(result != null);
-}
-
-test "HDCLanguageModel perplexity is mathematically sound" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 3, 55);
- defer model.deinit();
-
- try model.train("abcabcabcabcabcabcabcabcabcabc");
-
- // Perplexity on training data
- const ppl_train = try model.perplexity("abcabcabcabc");
- try std.testing.expect(ppl_train > 0);
- try std.testing.expect(ppl_train < 100); // Should be low on training data
-
- // Perplexity with different temperatures
- const ppl_cold = try model.perplexitySoftmax("abcabcabcabc", 0.5);
- const ppl_hot = try model.perplexitySoftmax("abcabcabcabc", 2.0);
-
- // All should be positive and finite
- try std.testing.expect(ppl_cold > 0);
- try std.testing.expect(ppl_hot > 0);
- try std.testing.expect(!std.math.isNan(ppl_cold));
- try std.testing.expect(!std.math.isNan(ppl_hot));
-}
-
-test "HDCLanguageModel sampling benchmark" {
- const allocator = std.testing.allocator;
-
- var model = HDCLanguageModel.init(allocator, 2000, 4, 42);
- defer model.deinit();
- model.enableJIT();
-
- try model.train("the quick brown fox jumps over the lazy dog and the cat sat on the mat ");
- try model.train("pack my box with five dozen liquor jugs the quick brown fox jumps again ");
-
- var timer = std.time.Timer.start() catch unreachable;
- const iterations = 10;
-
- // Benchmark generateWithConfig
- for (0..iterations) |i| {
- const text = try model.generateWithConfig("the ", .{
- .temperature = 0.8,
- .max_length = 50,
- .top_k = 4,
- .repetition_penalty = 1.2,
- .seed = 42 + i,
- });
- allocator.free(text);
- }
-
- const elapsed_ns = timer.read();
- const ms_per_gen = @as(f64, @floatFromInt(elapsed_ns)) / @as(f64, @floatFromInt(iterations)) / 1_000_000.0;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" SAMPLING BENCHMARK (dim=2000, ctx=4, temp=0.8, top_k=4)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Generation: {d:.3} ms/50-chars\n", .{ms_per_gen});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- try std.testing.expect(ms_per_gen < 200.0); // Reasonable limit
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC ASSOCIATIVE MEMORY
-// Content-Addressable Key-Value Store using Hyperdimensional Computing
-//
-// pair_hv = bind(key_hv, value_hv)
-// memory_hv = bundle(all pair_hvs)
-// query: unbind(memory_hv, query_key_hv) β nearest value in codebook
-//
-// Capacity: O(sqrt(D)) pairs per memory vector
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCAssociativeMemory = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- dimension: usize,
-
- // The holographic memory vector (bundle of all bindings)
- memory_vec: ?*HybridBigInt,
-
- // Stored pairs for rebuild/cleanup
- pairs: std.ArrayListUnmanaged(*KVPair),
-
- // Value codebook: maps value strings to their hypervectors
- value_codebook: std.StringHashMapUnmanaged(*HybridBigInt),
-
- // Key index: fast lookup by key string
- key_index: std.StringHashMapUnmanaged(usize), // key β pair index
-
- jit_engine: ?vsa_jit.JitVSAEngine,
-
- const Self = @This();
-
- pub const KVPair = struct {
- key: []const u8, // owned (duped)
- value: []const u8, // owned (duped)
- key_hv: *HybridBigInt, // heap-allocated
- value_hv: *HybridBigInt, // heap-allocated (shared with codebook)
- binding_hv: *HybridBigInt, // heap-allocated: bind(key_hv, value_hv)
- };
-
- pub const QueryResult = struct {
- value: []const u8,
- similarity: f64,
- exact_match: bool,
- };
-
- pub const CapacityInfo = struct {
- num_pairs: usize,
- dimension: usize,
- estimated_max: usize,
- load_factor: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return Self{
- .allocator = allocator,
- .item_memory = ItemMemory.init(allocator, dimension, seed),
- .dimension = dimension,
- .memory_vec = null,
- .pairs = .{},
- .value_codebook = .{},
- .key_index = .{},
- .jit_engine = null,
- };
- }
-
- pub fn enableJIT(self: *Self) void {
- self.jit_engine = vsa_jit.JitVSAEngine.init(self.allocator);
- }
-
- pub fn deinit(self: *Self) void {
- // Free all pairs
- for (self.pairs.items) |pair| {
- self.allocator.free(pair.key);
- self.allocator.free(pair.value);
- self.allocator.destroy(pair.key_hv);
- self.allocator.destroy(pair.binding_hv);
- // value_hv is shared with codebook, freed below
- self.allocator.destroy(pair);
- }
- self.pairs.deinit(self.allocator);
-
- // Free codebook value HVs
- var cb_iter = self.value_codebook.iterator();
- while (cb_iter.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- self.allocator.destroy(entry.value_ptr.*);
- }
- self.value_codebook.deinit(self.allocator);
-
- // Free key index keys (same pointers as pair.key, already freed)
- self.key_index.deinit(self.allocator);
-
- // Free memory vector
- if (self.memory_vec) |mv| {
- self.allocator.destroy(mv);
- }
-
- self.item_memory.deinit();
- if (self.jit_engine) |*engine| {
- engine.deinit();
- }
- }
-
- /// Encode a string into a hypervector using positional binding
- /// hv = bind(perm(c[0], 0), bind(perm(c[1], 1), ...))
- fn encodeString(self: *Self, str: []const u8) !*HybridBigInt {
- const result = try self.allocator.create(HybridBigInt);
-
- if (str.len == 0) {
- result.* = HybridBigInt.zero();
- result.trit_len = self.dimension;
- return result;
- }
-
- // Start with first character
- const first_char_hv = try self.item_memory.getCharVector(str[0]);
- result.* = vsa.permute(first_char_hv, 0);
-
- // Bind with remaining characters at their positions
- for (1..str.len) |i| {
- const char_hv = try self.item_memory.getCharVector(str[i]);
- var permuted = vsa.permute(char_hv, i);
- const bound = vsa.bind(result, &permuted);
- result.* = bound;
- }
-
- return result;
- }
-
- /// Store a key-value pair
- pub fn store(self: *Self, key: []const u8, value: []const u8) !void {
- // Check if key already exists - update if so
- if (self.key_index.get(key)) |idx| {
- try self.updatePair(idx, value);
- return;
- }
-
- // Encode key
- const key_hv = try self.encodeString(key);
-
- // Get or create value HV in codebook
- const value_hv = try self.getOrCreateValueHV(value);
-
- // Create binding: pair_hv = bind(key_hv, value_hv)
- const binding_hv = try self.allocator.create(HybridBigInt);
- binding_hv.* = vsa.bind(key_hv, value_hv);
-
- // Create pair
- const pair = try self.allocator.create(KVPair);
- pair.* = .{
- .key = try self.allocator.dupe(u8, key),
- .value = try self.allocator.dupe(u8, value),
- .key_hv = key_hv,
- .value_hv = value_hv,
- .binding_hv = binding_hv,
- };
-
- // Store in key index (using pair's owned key)
- try self.key_index.put(self.allocator, pair.key, self.pairs.items.len);
-
- // Add to pairs list
- try self.pairs.append(self.allocator, pair);
-
- // Update memory vector
- try self.addToMemory(binding_hv);
- }
-
- /// Get or create a value hypervector in the codebook
- fn getOrCreateValueHV(self: *Self, value: []const u8) !*HybridBigInt {
- if (self.value_codebook.get(value)) |existing| {
- return existing;
- }
-
- // Create new value HV
- const value_hv = try self.encodeString(value);
-
- // Store in codebook with duped key
- const codebook_key = try self.allocator.dupe(u8, value);
- try self.value_codebook.put(self.allocator, codebook_key, value_hv);
-
- return value_hv;
- }
-
- /// Update an existing pair's value
- fn updatePair(self: *Self, idx: usize, new_value: []const u8) !void {
- const pair = self.pairs.items[idx];
-
- // Free old value string
- self.allocator.free(pair.value);
-
- // Get new value HV
- const new_value_hv = try self.getOrCreateValueHV(new_value);
-
- // Update pair with new binding BEFORE rebuild
- pair.binding_hv.* = vsa.bind(pair.key_hv, new_value_hv);
- pair.value = try self.allocator.dupe(u8, new_value);
- pair.value_hv = new_value_hv;
-
- // Single rebuild with updated binding
- try self.rebuildMemory();
- }
-
- /// Add a binding to the memory vector
- fn addToMemory(self: *Self, binding: *HybridBigInt) !void {
- if (self.memory_vec) |mv| {
- const bundled = vsa.bundle2(mv, binding);
- mv.* = bundled;
- } else {
- const mv = try self.allocator.create(HybridBigInt);
- mv.* = binding.*;
- self.memory_vec = mv;
- }
- }
-
- /// Remove a binding from memory (requires full rebuild)
- fn removeFromMemory(self: *Self, _: *HybridBigInt) !void {
- // Incremental removal is noisy; mark for cleanup
- // Full rebuild happens in cleanup()
- try self.rebuildMemory();
- }
-
- /// Query by exact key - returns best matching value from codebook
- pub fn query(self: *Self, key: []const u8) !?QueryResult {
- const mv = self.memory_vec orelse return null;
-
- // Encode query key
- const query_hv = try self.encodeString(key);
- defer self.allocator.destroy(query_hv);
-
- // Unbind: result_hv β value_hv (if key was stored)
- var result_hv = vsa.unbind(mv, query_hv);
-
- // Find nearest value in codebook
- return self.findNearestValue(&result_hv);
- }
-
- /// Query with approximate/partial key
- pub fn queryApproximate(self: *Self, partial_key: []const u8) !?QueryResult {
- // Same as query but caller provides noisy/partial key
- return self.query(partial_key);
- }
-
- /// Find nearest value in codebook by cosine similarity
- fn findNearestValue(self: *Self, query_hv: *HybridBigInt) ?QueryResult {
- var best_value: ?[]const u8 = null;
- var best_sim: f64 = -2.0;
-
- var cb_iter = self.value_codebook.iterator();
- while (cb_iter.next()) |entry| {
- var value_hv = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(query_hv, &value_hv);
-
- if (sim > best_sim) {
- best_sim = sim;
- best_value = entry.key_ptr.*;
- }
- }
-
- if (best_value) |val| {
- return QueryResult{
- .value = val,
- .similarity = best_sim,
- .exact_match = best_sim > 0.5,
- };
- }
- return null;
- }
-
- /// Remove a key-value pair
- pub fn remove(self: *Self, key: []const u8) !bool {
- const idx = self.key_index.get(key) orelse return false;
-
- const pair = self.pairs.items[idx];
-
- // Remove from key index
- _ = self.key_index.remove(key);
-
- // Free pair resources
- self.allocator.free(pair.key);
- self.allocator.free(pair.value);
- self.allocator.destroy(pair.key_hv);
- self.allocator.destroy(pair.binding_hv);
- // value_hv is shared with codebook, don't free
- self.allocator.destroy(pair);
-
- // Swap-remove from pairs list
- _ = self.pairs.swapRemove(idx);
-
- // Fix key_index for swapped element
- if (idx < self.pairs.items.len) {
- const swapped = self.pairs.items[idx];
- self.key_index.putAssumeCapacity(swapped.key, idx);
- }
-
- // Rebuild memory without the removed pair
- try self.rebuildMemory();
-
- return true;
- }
-
- /// Rebuild memory vector from all stored pairs (noise reduction)
- pub fn cleanup(self: *Self) !void {
- try self.rebuildMemory();
- }
-
- fn rebuildMemory(self: *Self) !void {
- if (self.pairs.items.len == 0) {
- if (self.memory_vec) |mv| {
- self.allocator.destroy(mv);
- self.memory_vec = null;
- }
- return;
- }
-
- // Bundle all pair bindings
- var bundled = self.pairs.items[0].binding_hv.*;
-
- for (1..self.pairs.items.len) |i| {
- const b = vsa.bundle2(&bundled, self.pairs.items[i].binding_hv);
- bundled = b;
- }
-
- if (self.memory_vec) |mv| {
- mv.* = bundled;
- } else {
- const mv = try self.allocator.create(HybridBigInt);
- mv.* = bundled;
- self.memory_vec = mv;
- }
- }
-
- /// Estimate memory capacity
- pub fn capacity(self: *Self) CapacityInfo {
- // Theoretical capacity β sqrt(D) for ternary VSA
- const d_f = @as(f64, @floatFromInt(self.dimension));
- const estimated_max: usize = @intFromFloat(@sqrt(d_f));
- const n = self.pairs.items.len;
- const load = if (estimated_max > 0)
- @as(f64, @floatFromInt(n)) / @as(f64, @floatFromInt(estimated_max))
- else
- 0.0;
-
- return .{
- .num_pairs = n,
- .dimension = self.dimension,
- .estimated_max = estimated_max,
- .load_factor = load,
- };
- }
-
- /// Get all stored key-value pairs
- pub fn getAll(self: *Self) []const *KVPair {
- return self.pairs.items;
- }
-
- /// Get number of stored pairs
- pub fn len(self: *Self) usize {
- return self.pairs.items.len;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC ASSOCIATIVE MEMORY TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCAssociativeMemory store and exact query" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 4000, 42);
- defer mem.deinit();
-
- try mem.store("color", "red");
- try mem.store("shape", "circle");
- try mem.store("size", "large");
-
- // Query each key
- const r1 = try mem.query("color");
- try std.testing.expect(r1 != null);
- try std.testing.expectEqualStrings("red", r1.?.value);
-
- const r2 = try mem.query("shape");
- try std.testing.expect(r2 != null);
- try std.testing.expectEqualStrings("circle", r2.?.value);
-
- const r3 = try mem.query("size");
- try std.testing.expect(r3 != null);
- try std.testing.expectEqualStrings("large", r3.?.value);
-}
-
-test "HDCAssociativeMemory update existing key" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 4000, 42);
- defer mem.deinit();
-
- try mem.store("color", "red");
-
- const r1 = try mem.query("color");
- try std.testing.expect(r1 != null);
- try std.testing.expectEqualStrings("red", r1.?.value);
-
- // Update value
- try mem.store("color", "blue");
-
- const r2 = try mem.query("color");
- try std.testing.expect(r2 != null);
- try std.testing.expectEqualStrings("blue", r2.?.value);
-}
-
-test "HDCAssociativeMemory remove key" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 4000, 42);
- defer mem.deinit();
-
- try mem.store("a", "alpha");
- try mem.store("b", "beta");
- try mem.store("c", "gamma");
-
- try std.testing.expectEqual(@as(usize, 3), mem.len());
-
- // Remove middle key
- const removed = try mem.remove("b");
- try std.testing.expect(removed);
- try std.testing.expectEqual(@as(usize, 2), mem.len());
-
- // Remaining keys should still work
- const ra = try mem.query("a");
- try std.testing.expect(ra != null);
- try std.testing.expectEqualStrings("alpha", ra.?.value);
-
- const rc = try mem.query("c");
- try std.testing.expect(rc != null);
- try std.testing.expectEqualStrings("gamma", rc.?.value);
-
- // Removed key should return something (holographic noise) but not exact
- // Actually after rebuild it should be clean
-}
-
-test "HDCAssociativeMemory remove nonexistent key returns false" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 4000, 42);
- defer mem.deinit();
-
- try mem.store("x", "y");
-
- const removed = try mem.remove("nonexistent");
- try std.testing.expect(!removed);
-}
-
-test "HDCAssociativeMemory capacity estimation" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 10000, 42);
- defer mem.deinit();
-
- const cap = mem.capacity();
- try std.testing.expectEqual(@as(usize, 10000), cap.dimension);
- try std.testing.expectEqual(@as(usize, 100), cap.estimated_max); // sqrt(10000) = 100
- try std.testing.expect(cap.load_factor == 0.0);
-
- try mem.store("test", "value");
- const cap2 = mem.capacity();
- try std.testing.expectEqual(@as(usize, 1), cap2.num_pairs);
- try std.testing.expect(cap2.load_factor > 0.0);
-}
-
-test "HDCAssociativeMemory cleanup reduces noise" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 4000, 42);
- defer mem.deinit();
-
- try mem.store("fruit", "apple");
- try mem.store("veggie", "carrot");
- try mem.store("grain", "wheat");
-
- // Query before cleanup
- const before = try mem.query("fruit");
- try std.testing.expect(before != null);
- const sim_before = before.?.similarity;
-
- // Cleanup (rebuild)
- try mem.cleanup();
-
- // Query after cleanup
- const after = try mem.query("fruit");
- try std.testing.expect(after != null);
- try std.testing.expectEqualStrings("apple", after.?.value);
-
- // After cleanup, similarity should be equal (clean rebuild)
- _ = sim_before;
-}
-
-test "HDCAssociativeMemory multiple pairs retrieval accuracy" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 8000, 42);
- defer mem.deinit();
-
- // Store multiple distinct pairs
- const keys = [_][]const u8{ "cat", "dog", "bird", "fish", "frog" };
- const vals = [_][]const u8{ "meow", "bark", "tweet", "blub", "croak" };
-
- for (keys, vals) |k, v| {
- try mem.store(k, v);
- }
-
- // All should be retrievable
- var correct: u32 = 0;
- for (keys, vals) |k, expected_v| {
- if (try mem.query(k)) |result| {
- if (std.mem.eql(u8, result.value, expected_v)) {
- correct += 1;
- }
- }
- }
-
- // With dim=8000 and 5 pairs, all should be correct
- try std.testing.expectEqual(@as(u32, 5), correct);
-}
-
-test "HDCAssociativeMemory getAll returns all pairs" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 2000, 42);
- defer mem.deinit();
-
- try mem.store("x", "1");
- try mem.store("y", "2");
- try mem.store("z", "3");
-
- const all = mem.getAll();
- try std.testing.expectEqual(@as(usize, 3), all.len);
-}
-
-test "HDCAssociativeMemory empty query returns null" {
- const allocator = std.testing.allocator;
-
- var mem = HDCAssociativeMemory.init(allocator, 2000, 42);
- defer mem.deinit();
-
- const result = try mem.query("anything");
- try std.testing.expect(result == null);
-}
-
-test "HDCAssociativeMemory stress test capacity" {
- const allocator = std.testing.allocator;
-
- // dim=4000, estimated capacity = sqrt(4000) β 63
- var mem = HDCAssociativeMemory.init(allocator, 4000, 42);
- defer mem.deinit();
-
- // Store 20 pairs (well within capacity)
- var buf_k: [8]u8 = undefined;
- var buf_v: [8]u8 = undefined;
-
- for (0..20) |i| {
- const k_len = std.fmt.bufPrint(&buf_k, "key_{d}", .{i}) catch unreachable;
- const v_len = std.fmt.bufPrint(&buf_v, "val_{d}", .{i}) catch unreachable;
- try mem.store(k_len, v_len);
- }
-
- try std.testing.expectEqual(@as(usize, 20), mem.len());
-
- // Check retrieval accuracy
- var correct: u32 = 0;
- for (0..20) |i| {
- const k_len = std.fmt.bufPrint(&buf_k, "key_{d}", .{i}) catch unreachable;
- const expected = std.fmt.bufPrint(&buf_v, "val_{d}", .{i}) catch unreachable;
-
- if (try mem.query(k_len)) |result| {
- if (std.mem.eql(u8, result.value, expected)) {
- correct += 1;
- }
- }
- }
-
- // At dim=4000 with 20 pairs, accuracy should be decent
- const accuracy = @as(f64, @floatFromInt(correct)) / 20.0;
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" ASSOCIATIVE MEMORY STRESS (dim=4000, pairs=20)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Correct: {d}/20 ({d:.1}%)\n", .{ correct, accuracy * 100.0 });
- std.debug.print(" Load factor: {d:.2}\n", .{mem.capacity().load_factor});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- try std.testing.expect(correct >= 15); // At least 75% accuracy
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC KNOWLEDGE GRAPH
-// (Subject, Relation, Object) triples via three-way bind
-//
-// triple_hv = bind(S_hv, R_hv, O_hv)
-// memory_hv = bundle(all triple_hvs)
-//
-// Query (S, R, ?) β unbind(memory, bind(S_hv, R_hv)) β decode O
-// Query (?, R, O) β unbind(memory, bind(R_hv, O_hv)) β decode S
-// Query (S, ?, O) β unbind(memory, bind(S_hv, O_hv)) β decode R
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCKnowledgeGraph = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- dimension: usize,
-
- // Three memory vectors for three query patterns
- // Uses positional permutation to break commutativity
- // memory_obj: (S,R,?) β O encoded as bind(perm(S,1), perm(R,2), O)
- // memory_sub: (?,R,O) β S encoded as bind(perm(R,3), perm(O,4), S)
- // memory_rel: (S,?,O) β R encoded as bind(perm(S,5), perm(O,6), R)
- memory_obj: ?*HybridBigInt,
- memory_sub: ?*HybridBigInt,
- memory_rel: ?*HybridBigInt,
-
- // Stored triples for rebuild
- triples: std.ArrayListUnmanaged(*Triple),
-
- // Codebooks for decoding query results
- entity_codebook: std.StringHashMapUnmanaged(*HybridBigInt),
- relation_codebook: std.StringHashMapUnmanaged(*HybridBigInt),
-
- jit_engine: ?vsa_jit.JitVSAEngine,
-
- const Self = @This();
-
- // Permutation offsets for role disambiguation
- const PERM_S_OBJ: usize = 100; // S position in memory_obj
- const PERM_R_OBJ: usize = 200; // R position in memory_obj
- const PERM_R_SUB: usize = 300; // R position in memory_sub
- const PERM_O_SUB: usize = 400; // O position in memory_sub
- const PERM_S_REL: usize = 500; // S position in memory_rel
- const PERM_O_REL: usize = 600; // O position in memory_rel
-
- pub const Triple = struct {
- subject: []const u8, // owned
- relation: []const u8, // owned
- object: []const u8, // owned
- };
-
- pub const QueryPattern = struct {
- subject: ?[]const u8 = null,
- relation: ?[]const u8 = null,
- object: ?[]const u8 = null,
- };
-
- pub const QueryResult = struct {
- value: []const u8,
- similarity: f64,
- };
-
- pub const GraphStats = struct {
- num_triples: usize,
- num_entities: usize,
- num_relations: usize,
- dimension: usize,
- estimated_capacity: usize,
- load_factor: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return Self{
- .allocator = allocator,
- .item_memory = ItemMemory.init(allocator, dimension, seed),
- .dimension = dimension,
- .memory_obj = null,
- .memory_sub = null,
- .memory_rel = null,
- .triples = .{},
- .entity_codebook = .{},
- .relation_codebook = .{},
- .jit_engine = null,
- };
- }
-
- pub fn enableJIT(self: *Self) void {
- self.jit_engine = vsa_jit.JitVSAEngine.init(self.allocator);
- }
-
- pub fn deinit(self: *Self) void {
- for (self.triples.items) |triple| {
- self.allocator.free(triple.subject);
- self.allocator.free(triple.relation);
- self.allocator.free(triple.object);
- self.allocator.destroy(triple);
- }
- self.triples.deinit(self.allocator);
-
- var e_iter = self.entity_codebook.iterator();
- while (e_iter.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- self.allocator.destroy(entry.value_ptr.*);
- }
- self.entity_codebook.deinit(self.allocator);
-
- var r_iter = self.relation_codebook.iterator();
- while (r_iter.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- self.allocator.destroy(entry.value_ptr.*);
- }
- self.relation_codebook.deinit(self.allocator);
-
- if (self.memory_obj) |m| self.allocator.destroy(m);
- if (self.memory_sub) |m| self.allocator.destroy(m);
- if (self.memory_rel) |m| self.allocator.destroy(m);
-
- self.item_memory.deinit();
- if (self.jit_engine) |*engine| engine.deinit();
- }
-
- fn encodeString(self: *Self, str: []const u8) !*HybridBigInt {
- const result = try self.allocator.create(HybridBigInt);
- if (str.len == 0) {
- result.* = HybridBigInt.zero();
- result.trit_len = self.dimension;
- return result;
- }
- const first_hv = try self.item_memory.getCharVector(str[0]);
- result.* = vsa.permute(first_hv, 0);
- for (1..str.len) |i| {
- const char_hv = try self.item_memory.getCharVector(str[i]);
- var permuted = vsa.permute(char_hv, i);
- const bound = vsa.bind(result, &permuted);
- result.* = bound;
- }
- return result;
- }
-
- fn getOrCreateEntity(self: *Self, name: []const u8) !*HybridBigInt {
- if (self.entity_codebook.get(name)) |existing| return existing;
- const hv = try self.encodeString(name);
- const key = try self.allocator.dupe(u8, name);
- try self.entity_codebook.put(self.allocator, key, hv);
- return hv;
- }
-
- fn getOrCreateRelation(self: *Self, name: []const u8) !*HybridBigInt {
- if (self.relation_codebook.get(name)) |existing| return existing;
- const hv = try self.encodeString(name);
- const key = try self.allocator.dupe(u8, name);
- try self.relation_codebook.put(self.allocator, key, hv);
- return hv;
- }
-
- /// Compute the three bindings for a triple (one per query pattern)
- fn computeBindings(s_hv: *HybridBigInt, r_hv: *HybridBigInt, o_hv: *HybridBigInt) struct {
- obj_binding: HybridBigInt, // for (S,R,?) β O
- sub_binding: HybridBigInt, // for (?,R,O) β S
- rel_binding: HybridBigInt, // for (S,?,O) β R
- } {
- // memory_obj: bind(perm(S, PERM_S_OBJ), perm(R, PERM_R_OBJ), O)
- var s_perm = vsa.permute(s_hv, PERM_S_OBJ);
- var r_perm = vsa.permute(r_hv, PERM_R_OBJ);
- var sr = vsa.bind(&s_perm, &r_perm);
- const obj_binding = vsa.bind(&sr, o_hv);
-
- // memory_sub: bind(perm(R, PERM_R_SUB), perm(O, PERM_O_SUB), S)
- var r_perm2 = vsa.permute(r_hv, PERM_R_SUB);
- var o_perm = vsa.permute(o_hv, PERM_O_SUB);
- var ro = vsa.bind(&r_perm2, &o_perm);
- const sub_binding = vsa.bind(&ro, s_hv);
-
- // memory_rel: bind(perm(S, PERM_S_REL), perm(O, PERM_O_REL), R)
- var s_perm2 = vsa.permute(s_hv, PERM_S_REL);
- var o_perm2 = vsa.permute(o_hv, PERM_O_REL);
- var so = vsa.bind(&s_perm2, &o_perm2);
- const rel_binding = vsa.bind(&so, r_hv);
-
- return .{
- .obj_binding = obj_binding,
- .sub_binding = sub_binding,
- .rel_binding = rel_binding,
- };
- }
-
- /// Bundle a binding into a memory vector
- fn bundleInto(self: *Self, mem_ptr: *?*HybridBigInt, binding: *const HybridBigInt) !void {
- if (mem_ptr.*) |mv| {
- var binding_mut = binding.*;
- const bundled = vsa.bundle2(mv, &binding_mut);
- mv.* = bundled;
- } else {
- const mv = try self.allocator.create(HybridBigInt);
- mv.* = binding.*;
- mem_ptr.* = mv;
- }
- }
-
- pub fn addTriple(self: *Self, subject: []const u8, relation: []const u8, object: []const u8) !void {
- // Check duplicate
- for (self.triples.items) |t| {
- if (std.mem.eql(u8, t.subject, subject) and
- std.mem.eql(u8, t.relation, relation) and
- std.mem.eql(u8, t.object, object))
- return;
- }
-
- const s_hv = try self.getOrCreateEntity(subject);
- const r_hv = try self.getOrCreateRelation(relation);
- const o_hv = try self.getOrCreateEntity(object);
-
- const bindings = computeBindings(s_hv, r_hv, o_hv);
-
- // Store triple
- const triple = try self.allocator.create(Triple);
- triple.* = .{
- .subject = try self.allocator.dupe(u8, subject),
- .relation = try self.allocator.dupe(u8, relation),
- .object = try self.allocator.dupe(u8, object),
- };
- try self.triples.append(self.allocator, triple);
-
- // Bundle into all three memories
- try self.bundleInto(&self.memory_obj, &bindings.obj_binding);
- try self.bundleInto(&self.memory_sub, &bindings.sub_binding);
- try self.bundleInto(&self.memory_rel, &bindings.rel_binding);
- }
-
- pub fn query(self: *Self, pattern: QueryPattern) !?QueryResult {
- const results = try self.queryTopK(pattern, 1);
- if (results.len > 0) {
- const r = results[0];
- self.allocator.free(results);
- return r;
- }
- self.allocator.free(results);
- return null;
- }
-
- pub fn queryTopK(self: *Self, pattern: QueryPattern, k: usize) ![]QueryResult {
- const s_known = pattern.subject != null;
- const r_known = pattern.relation != null;
- const o_known = pattern.object != null;
- const known_count = @as(u8, @intFromBool(s_known)) +
- @as(u8, @intFromBool(r_known)) +
- @as(u8, @intFromBool(o_known));
-
- if (known_count < 2 or known_count == 3) {
- return try self.allocator.alloc(QueryResult, 0);
- }
-
- var query_hv: HybridBigInt = undefined;
- var memory: *HybridBigInt = undefined;
- var codebook: *const std.StringHashMapUnmanaged(*HybridBigInt) = undefined;
-
- if (s_known and r_known and !o_known) {
- // (S, R, ?) β O from memory_obj
- const mv = self.memory_obj orelse return try self.allocator.alloc(QueryResult, 0);
- const s_hv = try self.getOrCreateEntity(pattern.subject.?);
- const r_hv = try self.getOrCreateRelation(pattern.relation.?);
- var s_perm = vsa.permute(s_hv, PERM_S_OBJ);
- var r_perm = vsa.permute(r_hv, PERM_R_OBJ);
- query_hv = vsa.bind(&s_perm, &r_perm);
- memory = mv;
- codebook = &self.entity_codebook;
- } else if (!s_known and r_known and o_known) {
- // (?, R, O) β S from memory_sub
- const mv = self.memory_sub orelse return try self.allocator.alloc(QueryResult, 0);
- const r_hv = try self.getOrCreateRelation(pattern.relation.?);
- const o_hv = try self.getOrCreateEntity(pattern.object.?);
- var r_perm = vsa.permute(r_hv, PERM_R_SUB);
- var o_perm = vsa.permute(o_hv, PERM_O_SUB);
- query_hv = vsa.bind(&r_perm, &o_perm);
- memory = mv;
- codebook = &self.entity_codebook;
- } else {
- // (S, ?, O) β R from memory_rel
- const mv = self.memory_rel orelse return try self.allocator.alloc(QueryResult, 0);
- const s_hv = try self.getOrCreateEntity(pattern.subject.?);
- const o_hv = try self.getOrCreateEntity(pattern.object.?);
- var s_perm = vsa.permute(s_hv, PERM_S_REL);
- var o_perm = vsa.permute(o_hv, PERM_O_REL);
- query_hv = vsa.bind(&s_perm, &o_perm);
- memory = mv;
- codebook = &self.relation_codebook;
- }
-
- // Unbind: result = bind(memory, query) [self-inverse]
- var result_hv = vsa.bind(memory, &query_hv);
- return self.findTopKInCodebook(&result_hv, codebook, k);
- }
-
- fn findTopKInCodebook(
- self: *Self,
- query_hv: *HybridBigInt,
- codebook: *const std.StringHashMapUnmanaged(*HybridBigInt),
- k: usize,
- ) ![]QueryResult {
- const Pair = struct { name: []const u8, sim: f64 };
- var candidates: std.ArrayListUnmanaged(Pair) = .{};
- defer candidates.deinit(self.allocator);
-
- var cb_iter = codebook.iterator();
- while (cb_iter.next()) |entry| {
- var val_hv = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(query_hv, &val_hv);
- try candidates.append(self.allocator, .{ .name = entry.key_ptr.*, .sim = sim });
- }
-
- // Sort descending by similarity
- const items = candidates.items;
- var i: usize = 1;
- while (i < items.len) : (i += 1) {
- const key_item = items[i];
- var j: usize = i;
- while (j > 0 and items[j - 1].sim < key_item.sim) {
- items[j] = items[j - 1];
- j -= 1;
- }
- items[j] = key_item;
- }
-
- const result_len = @min(k, items.len);
- var results = try self.allocator.alloc(QueryResult, result_len);
- for (0..result_len) |ri| {
- results[ri] = .{ .value = items[ri].name, .similarity = items[ri].sim };
- }
- return results;
- }
-
- pub fn removeTriple(self: *Self, subject: []const u8, relation: []const u8, object: []const u8) !bool {
- var found_idx: ?usize = null;
- for (self.triples.items, 0..) |t, idx| {
- if (std.mem.eql(u8, t.subject, subject) and
- std.mem.eql(u8, t.relation, relation) and
- std.mem.eql(u8, t.object, object))
- {
- found_idx = idx;
- break;
- }
- }
- const idx = found_idx orelse return false;
- const triple = self.triples.items[idx];
- self.allocator.free(triple.subject);
- self.allocator.free(triple.relation);
- self.allocator.free(triple.object);
- self.allocator.destroy(triple);
- _ = self.triples.swapRemove(idx);
- try self.rebuildAllMemories();
- return true;
- }
-
- pub fn hasTriple(self: *Self, subject: []const u8, relation: []const u8, object: []const u8) bool {
- for (self.triples.items) |t| {
- if (std.mem.eql(u8, t.subject, subject) and
- std.mem.eql(u8, t.relation, relation) and
- std.mem.eql(u8, t.object, object))
- return true;
- }
- return false;
- }
-
- pub fn getTriplesBySubject(self: *Self, subject: []const u8) ![]const *Triple {
- var matches: std.ArrayListUnmanaged(*Triple) = .{};
- for (self.triples.items) |t| {
- if (std.mem.eql(u8, t.subject, subject))
- try matches.append(self.allocator, t);
- }
- return matches.toOwnedSlice(self.allocator);
- }
-
- fn rebuildAllMemories(self: *Self) !void {
- // Free old memories
- if (self.memory_obj) |m| {
- self.allocator.destroy(m);
- self.memory_obj = null;
- }
- if (self.memory_sub) |m| {
- self.allocator.destroy(m);
- self.memory_sub = null;
- }
- if (self.memory_rel) |m| {
- self.allocator.destroy(m);
- self.memory_rel = null;
- }
-
- for (self.triples.items) |t| {
- const s_hv = self.entity_codebook.get(t.subject).?;
- const r_hv = self.relation_codebook.get(t.relation).?;
- const o_hv = self.entity_codebook.get(t.object).?;
-
- const bindings = computeBindings(s_hv, r_hv, o_hv);
- try self.bundleInto(&self.memory_obj, &bindings.obj_binding);
- try self.bundleInto(&self.memory_sub, &bindings.sub_binding);
- try self.bundleInto(&self.memory_rel, &bindings.rel_binding);
- }
- }
-
- pub fn stats(self: *Self) GraphStats {
- const d_f = @as(f64, @floatFromInt(self.dimension));
- const est_cap: usize = @intFromFloat(@sqrt(d_f));
- const n = self.triples.items.len;
- return .{
- .num_triples = n,
- .num_entities = self.entity_codebook.count(),
- .num_relations = self.relation_codebook.count(),
- .dimension = self.dimension,
- .estimated_capacity = est_cap,
- .load_factor = if (est_cap > 0) @as(f64, @floatFromInt(n)) / @as(f64, @floatFromInt(est_cap)) else 0,
- };
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // GRAPH TRAVERSAL & PATH QUERIES
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- pub const PathResult = struct {
- path: [][]const u8, // owned: [start, hop1, hop2, ..., end]
- final_entity: []const u8, // points into path
- final_similarity: f64,
- hops: usize,
- };
-
- pub const AnalogyResult = struct {
- value: []const u8,
- similarity: f64,
- };
-
- pub const SubgraphConstraint = struct {
- relation: []const u8,
- object: []const u8,
- };
-
- /// Multi-hop path query: start --r1--> e1 --r2--> e2 --> ... --> result
- /// Returns the full path and final entity
- pub fn pathQuery(self: *Self, start: []const u8, relations: []const []const u8) !?PathResult {
- if (relations.len == 0) return null;
-
- // Allocate path array (start + one entity per hop)
- var path = try self.allocator.alloc([]const u8, relations.len + 1);
- path[0] = start;
-
- var current = start;
- var last_sim: f64 = 0;
-
- for (relations, 0..) |rel, hop| {
- const result = try self.query(.{
- .subject = current,
- .relation = rel,
- }) orelse {
- // Dead end - free path and return null
- self.allocator.free(path);
- return null;
- };
-
- path[hop + 1] = result.value;
- current = result.value;
- last_sim = result.similarity;
- }
-
- return PathResult{
- .path = path,
- .final_entity = current,
- .final_similarity = last_sim,
- .hops = relations.len,
- };
- }
-
- /// Free a PathResult
- pub fn freePathResult(self: *Self, result: PathResult) void {
- self.allocator.free(result.path);
- }
-
- /// Multi-hop with beam search: keep top-k candidates at each hop
- pub fn pathQueryTopK(
- self: *Self,
- start: []const u8,
- relations: []const []const u8,
- beam_width: usize,
- ) ![]PathResult {
- if (relations.len == 0) return try self.allocator.alloc(PathResult, 0);
-
- const Beam = struct { entity: []const u8, cum_sim: f64, path: std.ArrayListUnmanaged([]const u8) };
-
- // Initialize beam with start entity
- var current_beam: std.ArrayListUnmanaged(Beam) = .{};
- defer current_beam.deinit(self.allocator);
-
- var initial_path: std.ArrayListUnmanaged([]const u8) = .{};
- try initial_path.append(self.allocator, start);
- try current_beam.append(self.allocator, .{
- .entity = start,
- .cum_sim = 1.0,
- .path = initial_path,
- });
-
- // Process each hop
- for (relations) |rel| {
- var next_beam: std.ArrayListUnmanaged(Beam) = .{};
-
- for (current_beam.items) |*beam| {
- const candidates = try self.queryTopK(.{
- .subject = beam.entity,
- .relation = rel,
- }, beam_width);
- defer self.allocator.free(candidates);
-
- for (candidates) |cand| {
- var new_path: std.ArrayListUnmanaged([]const u8) = .{};
- try new_path.appendSlice(self.allocator, beam.path.items);
- try new_path.append(self.allocator, cand.value);
-
- try next_beam.append(self.allocator, .{
- .entity = cand.value,
- .cum_sim = beam.cum_sim * @max(cand.similarity, 0.001),
- .path = new_path,
- });
- }
- }
-
- // Free old beam paths
- for (current_beam.items) |*b| {
- b.path.deinit(self.allocator);
- }
- current_beam.deinit(self.allocator);
- current_beam = next_beam;
-
- // Sort by cumulative similarity (descending) and keep top beam_width
- const items = current_beam.items;
- var si: usize = 1;
- while (si < items.len) : (si += 1) {
- const key_item = items[si];
- var sj: usize = si;
- while (sj > 0 and items[sj - 1].cum_sim < key_item.cum_sim) {
- items[sj] = items[sj - 1];
- sj -= 1;
- }
- items[sj] = key_item;
- }
-
- // Prune to beam_width
- while (current_beam.items.len > beam_width) {
- if (current_beam.pop()) |pruned| {
- var p = pruned;
- p.path.deinit(self.allocator);
- }
- }
- }
-
- // Convert beam to PathResults
- var results = try self.allocator.alloc(PathResult, current_beam.items.len);
- for (current_beam.items, 0..) |*beam, ri| {
- const path_slice = try beam.path.toOwnedSlice(self.allocator);
- results[ri] = PathResult{
- .path = path_slice,
- .final_entity = if (path_slice.len > 0) path_slice[path_slice.len - 1] else start,
- .final_similarity = beam.cum_sim,
- .hops = relations.len,
- };
- }
- // defer handles current_beam.deinit
-
- return results;
- }
-
- /// Free pathQueryTopK results
- pub fn freePathResults(self: *Self, results: []PathResult) void {
- for (results) |r| {
- self.allocator.free(r.path);
- }
- self.allocator.free(results);
- }
-
- /// Analogy query: "a is to b as c is to ?"
- /// Uses vector arithmetic: result_hv = b_hv - a_hv + c_hv
- /// In ternary VSA: result_hv = bundle(bind(b_hv, inv(a_hv)), c_hv)
- /// Simplified: result = bundle(unbind(b, a), c) β relation(aβb) applied to c
- pub fn analogyQuery(self: *Self, a: []const u8, b: []const u8, c: []const u8) !?AnalogyResult {
- const a_hv = self.entity_codebook.get(a) orelse return null;
- const b_hv = self.entity_codebook.get(b) orelse return null;
- const c_hv = self.entity_codebook.get(c) orelse return null;
-
- // Extract implicit relation: rel_hv = unbind(b, a) = bind(b, a) [self-inverse]
- var rel_hv = vsa.bind(b_hv, a_hv);
-
- // Apply relation to c: result_hv = bind(rel_hv, c_hv)
- var result_hv = vsa.bind(&rel_hv, c_hv);
-
- // Decode against entity codebook
- var best_name: ?[]const u8 = null;
- var best_sim: f64 = -2.0;
-
- var cb_iter = self.entity_codebook.iterator();
- while (cb_iter.next()) |entry| {
- // Skip the input entities
- if (std.mem.eql(u8, entry.key_ptr.*, a) or
- std.mem.eql(u8, entry.key_ptr.*, b) or
- std.mem.eql(u8, entry.key_ptr.*, c))
- continue;
-
- var val_hv = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(&result_hv, &val_hv);
- if (sim > best_sim) {
- best_sim = sim;
- best_name = entry.key_ptr.*;
- }
- }
-
- if (best_name) |name| {
- return AnalogyResult{ .value = name, .similarity = best_sim };
- }
- return null;
- }
-
- /// Subgraph match: find entity that satisfies all (relation, object) constraints
- /// Example: who has {parent_of: charlie, spouse_of: bob}?
- pub fn subgraphMatch(self: *Self, constraints: []const SubgraphConstraint) !?QueryResult {
- if (constraints.len == 0) return null;
-
- // For each constraint, query (?, relation, object) β get candidate subjects
- // Bundle all candidate HVs, decode against entity codebook
-
- var bundled_result: ?HybridBigInt = null;
-
- for (constraints) |constraint| {
- const mv = self.memory_sub orelse return null;
- const r_hv = self.relation_codebook.get(constraint.relation) orelse return null;
- const o_hv = self.entity_codebook.get(constraint.object) orelse return null;
-
- // Build query for (?, R, O) β S
- var r_perm = vsa.permute(r_hv, PERM_R_SUB);
- var o_perm = vsa.permute(o_hv, PERM_O_SUB);
- var query_hv = vsa.bind(&r_perm, &o_perm);
- var result_hv = vsa.bind(mv, &query_hv);
-
- if (bundled_result) |*existing| {
- // Intersect by binding (AND-like operation in VSA)
- const combined = vsa.bundle2(existing, &result_hv);
- existing.* = combined;
- } else {
- bundled_result = result_hv;
- }
- }
-
- if (bundled_result) |*result| {
- // Decode against entity codebook
- var best_name: ?[]const u8 = null;
- var best_sim: f64 = -2.0;
-
- var cb_iter = self.entity_codebook.iterator();
- while (cb_iter.next()) |entry| {
- var val_hv = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(result, &val_hv);
- if (sim > best_sim) {
- best_sim = sim;
- best_name = entry.key_ptr.*;
- }
- }
-
- if (best_name) |name| {
- return QueryResult{ .value = name, .similarity = best_sim };
- }
- }
- return null;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC KNOWLEDGE GRAPH TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCKnowledgeGraph add and query object" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("bob", "likes", "dogs");
- try kg.addTriple("alice", "works_at", "lab");
-
- // Query: (alice, likes, ?) β cats
- const r1 = try kg.query(.{ .subject = "alice", .relation = "likes" });
- try std.testing.expect(r1 != null);
- try std.testing.expectEqualStrings("cats", r1.?.value);
-
- // Query: (bob, likes, ?) β dogs
- const r2 = try kg.query(.{ .subject = "bob", .relation = "likes" });
- try std.testing.expect(r2 != null);
- try std.testing.expectEqualStrings("dogs", r2.?.value);
-}
-
-test "HDCKnowledgeGraph query subject" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("bob", "likes", "dogs");
-
- // Query: (?, likes, cats) β alice
- const r = try kg.query(.{ .relation = "likes", .object = "cats" });
- try std.testing.expect(r != null);
- try std.testing.expectEqualStrings("alice", r.?.value);
-}
-
-test "HDCKnowledgeGraph query relation" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("alice", "hates", "rain");
-
- // Query: (alice, ?, cats) β likes
- const r = try kg.query(.{ .subject = "alice", .object = "cats" });
- try std.testing.expect(r != null);
- try std.testing.expectEqualStrings("likes", r.?.value);
-}
-
-test "HDCKnowledgeGraph has and remove triple" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("bob", "likes", "dogs");
-
- try std.testing.expect(kg.hasTriple("alice", "likes", "cats"));
- try std.testing.expect(!kg.hasTriple("alice", "likes", "dogs"));
-
- const removed = try kg.removeTriple("alice", "likes", "cats");
- try std.testing.expect(removed);
- try std.testing.expect(!kg.hasTriple("alice", "likes", "cats"));
-
- // Bob's triple should still work
- const r = try kg.query(.{ .subject = "bob", .relation = "likes" });
- try std.testing.expect(r != null);
- try std.testing.expectEqualStrings("dogs", r.?.value);
-}
-
-test "HDCKnowledgeGraph duplicate triple ignored" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 4000, 42);
- defer kg.deinit();
-
- try kg.addTriple("a", "r", "b");
- try kg.addTriple("a", "r", "b"); // duplicate
-
- try std.testing.expectEqual(@as(usize, 1), kg.stats().num_triples);
-}
-
-test "HDCKnowledgeGraph getTriplesBySubject" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 4000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("alice", "works_at", "lab");
- try kg.addTriple("bob", "likes", "dogs");
-
- const alice_triples = try kg.getTriplesBySubject("alice");
- defer allocator.free(alice_triples);
-
- try std.testing.expectEqual(@as(usize, 2), alice_triples.len);
-}
-
-test "HDCKnowledgeGraph stats" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 10000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("bob", "likes", "dogs");
- try kg.addTriple("alice", "hates", "rain");
-
- const s = kg.stats();
- try std.testing.expectEqual(@as(usize, 3), s.num_triples);
- try std.testing.expectEqual(@as(usize, 100), s.estimated_capacity); // sqrt(10000)
- try std.testing.expect(s.num_entities >= 4); // alice, bob, cats, dogs, rain
- try std.testing.expect(s.num_relations >= 2); // likes, hates
-}
-
-test "HDCKnowledgeGraph queryTopK" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("alice", "likes", "dogs");
- try kg.addTriple("alice", "likes", "birds");
-
- // Query: (alice, likes, ?) β top 3
- const top3 = try kg.queryTopK(.{ .subject = "alice", .relation = "likes" }, 3);
- defer allocator.free(top3);
-
- try std.testing.expect(top3.len >= 1);
- // The top result should be one of the objects
- const top_val = top3[0].value;
- try std.testing.expect(
- std.mem.eql(u8, top_val, "cats") or
- std.mem.eql(u8, top_val, "dogs") or
- std.mem.eql(u8, top_val, "birds"),
- );
-}
-
-test "HDCKnowledgeGraph empty query returns null" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 4000, 42);
- defer kg.deinit();
-
- const r = try kg.query(.{ .subject = "x", .relation = "y" });
- try std.testing.expect(r == null);
-}
-
-test "HDCKnowledgeGraph multi-relation stress" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- // Family tree
- try kg.addTriple("alice", "parent_of", "charlie");
- try kg.addTriple("bob", "parent_of", "charlie");
- try kg.addTriple("alice", "spouse_of", "bob");
- try kg.addTriple("charlie", "friend_of", "dave");
- try kg.addTriple("dave", "works_at", "office");
-
- // Query relationships
- const r1 = try kg.query(.{ .subject = "alice", .relation = "parent_of" });
- try std.testing.expect(r1 != null);
- try std.testing.expectEqualStrings("charlie", r1.?.value);
-
- const r2 = try kg.query(.{ .subject = "alice", .relation = "spouse_of" });
- try std.testing.expect(r2 != null);
- try std.testing.expectEqualStrings("bob", r2.?.value);
-
- const r3 = try kg.query(.{ .subject = "dave", .relation = "works_at" });
- try std.testing.expect(r3 != null);
- try std.testing.expectEqualStrings("office", r3.?.value);
-
- // Reverse query: who is parent of charlie?
- const r4 = try kg.query(.{ .relation = "parent_of", .object = "charlie" });
- try std.testing.expect(r4 != null);
- // Should be alice or bob (both are parents)
- try std.testing.expect(
- std.mem.eql(u8, r4.?.value, "alice") or
- std.mem.eql(u8, r4.?.value, "bob"),
- );
-
- // Stats
- const s = kg.stats();
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" KNOWLEDGE GRAPH STATS (dim=8000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Triples: {d}\n", .{s.num_triples});
- std.debug.print(" Entities: {d}\n", .{s.num_entities});
- std.debug.print(" Relations: {d}\n", .{s.num_relations});
- std.debug.print(" Capacity: {d} (load: {d:.2})\n", .{ s.estimated_capacity, s.load_factor });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// GRAPH TRAVERSAL TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCKnowledgeGraph pathQuery single hop" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("cats", "eat", "fish");
-
- // Single hop: alice --likes--> cats
- const r = try kg.pathQuery("alice", &[_][]const u8{"likes"});
- try std.testing.expect(r != null);
- defer kg.freePathResult(r.?);
-
- try std.testing.expectEqualStrings("cats", r.?.final_entity);
- try std.testing.expectEqual(@as(usize, 1), r.?.hops);
- try std.testing.expectEqual(@as(usize, 2), r.?.path.len);
- try std.testing.expectEqualStrings("alice", r.?.path[0]);
- try std.testing.expectEqualStrings("cats", r.?.path[1]);
-}
-
-test "HDCKnowledgeGraph pathQuery multi-hop" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "parent_of", "charlie");
- try kg.addTriple("charlie", "friend_of", "dave");
- try kg.addTriple("dave", "works_at", "office");
-
- // Two hops: alice --parent_of--> charlie --friend_of--> dave
- const r = try kg.pathQuery("alice", &[_][]const u8{ "parent_of", "friend_of" });
- try std.testing.expect(r != null);
- defer kg.freePathResult(r.?);
-
- try std.testing.expectEqualStrings("dave", r.?.final_entity);
- try std.testing.expectEqual(@as(usize, 2), r.?.hops);
- try std.testing.expectEqual(@as(usize, 3), r.?.path.len);
-
- // Three hops: alice --parent_of--> charlie --friend_of--> dave --works_at--> office
- const r3 = try kg.pathQuery("alice", &[_][]const u8{ "parent_of", "friend_of", "works_at" });
- try std.testing.expect(r3 != null);
- defer kg.freePathResult(r3.?);
-
- try std.testing.expectEqualStrings("office", r3.?.final_entity);
- try std.testing.expectEqual(@as(usize, 3), r3.?.hops);
-}
-
-test "HDCKnowledgeGraph pathQuery dead end returns null" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 4000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
-
- // Dead end: cats has no "works_at" relation
- const r = try kg.pathQuery("alice", &[_][]const u8{ "likes", "works_at" });
- // May return null or a low-confidence result depending on noise
- if (r) |result| {
- kg.freePathResult(result);
- }
-}
-
-test "HDCKnowledgeGraph pathQueryTopK beam search" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "parent_of", "charlie");
- try kg.addTriple("charlie", "friend_of", "dave");
- try kg.addTriple("dave", "works_at", "office");
-
- const results = try kg.pathQueryTopK("alice", &[_][]const u8{ "parent_of", "friend_of" }, 3);
- defer kg.freePathResults(results);
-
- try std.testing.expect(results.len >= 1);
- try std.testing.expectEqualStrings("dave", results[0].final_entity);
-}
-
-test "HDCKnowledgeGraph analogyQuery" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- // Build a graph with parallel structure:
- // alice --parent_of--> charlie
- // bob --parent_of--> diana
- try kg.addTriple("alice", "parent_of", "charlie");
- try kg.addTriple("bob", "parent_of", "diana");
- try kg.addTriple("alice", "spouse_of", "bob");
-
- // Analogy: alice:charlie :: bob:?
- // Expected: diana (same relationship structure)
- const r = try kg.analogyQuery("alice", "charlie", "bob");
- try std.testing.expect(r != null);
-
- // The analogy result should be an entity (might not be diana due to noise)
- // Just verify we get a valid result
- try std.testing.expect(r.?.value.len > 0);
-}
-
-test "HDCKnowledgeGraph subgraphMatch" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "parent_of", "charlie");
- try kg.addTriple("alice", "spouse_of", "bob");
- try kg.addTriple("bob", "parent_of", "charlie");
- try kg.addTriple("dave", "friend_of", "charlie");
-
- // Who is parent_of charlie AND spouse_of bob? β alice
- const constraints = [_]HDCKnowledgeGraph.SubgraphConstraint{
- .{ .relation = "parent_of", .object = "charlie" },
- .{ .relation = "spouse_of", .object = "bob" },
- };
-
- const r = try kg.subgraphMatch(&constraints);
- try std.testing.expect(r != null);
- try std.testing.expectEqualStrings("alice", r.?.value);
-}
-
-test "HDCKnowledgeGraph subgraphMatch single constraint" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- try kg.addTriple("alice", "likes", "cats");
- try kg.addTriple("bob", "likes", "dogs");
-
- // Who likes cats? β alice
- const constraints = [_]HDCKnowledgeGraph.SubgraphConstraint{
- .{ .relation = "likes", .object = "cats" },
- };
-
- const r = try kg.subgraphMatch(&constraints);
- try std.testing.expect(r != null);
- try std.testing.expectEqualStrings("alice", r.?.value);
-}
-
-test "HDCKnowledgeGraph full traversal demo" {
- const allocator = std.testing.allocator;
-
- var kg = HDCKnowledgeGraph.init(allocator, 8000, 42);
- defer kg.deinit();
-
- // Build a small social graph
- try kg.addTriple("alice", "parent_of", "charlie");
- try kg.addTriple("bob", "parent_of", "charlie");
- try kg.addTriple("alice", "spouse_of", "bob");
- try kg.addTriple("charlie", "friend_of", "dave");
- try kg.addTriple("dave", "works_at", "office");
- try kg.addTriple("charlie", "studies_at", "school");
-
- // Path: alice β charlie β dave β office (3 hops)
- const path = try kg.pathQuery("alice", &[_][]const u8{
- "parent_of", "friend_of", "works_at",
- });
- try std.testing.expect(path != null);
- defer kg.freePathResult(path.?);
-
- try std.testing.expectEqualStrings("office", path.?.final_entity);
- try std.testing.expectEqual(@as(usize, 4), path.?.path.len);
-
- // Subgraph: who is parent_of charlie AND spouse_of bob? β alice
- const constraints = [_]HDCKnowledgeGraph.SubgraphConstraint{
- .{ .relation = "parent_of", .object = "charlie" },
- .{ .relation = "spouse_of", .object = "bob" },
- };
- const match = try kg.subgraphMatch(&constraints);
- try std.testing.expect(match != null);
- try std.testing.expectEqualStrings("alice", match.?.value);
-
- const s = kg.stats();
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" GRAPH TRAVERSAL DEMO (dim=8000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Triples: {d} | Entities: {d} | Relations: {d}\n", .{ s.num_triples, s.num_entities, s.num_relations });
- std.debug.print(" 3-hop path: aliceβcharlieβdaveβoffice OK\n", .{});
- std.debug.print(" Subgraph match: (parent_of:charlie β§ spouse_of:bob) β alice OK\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC TEXT ENCODER (shared)
-// Single source of truth for text β hypervector encoding.
-// Used by HDCClassifier, HDCClustering, HDCAnomalyDetector.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCTextEncoder = struct {
- allocator: std.mem.Allocator,
- item_memory: *ItemMemory,
- ngram_encoder: *NGramEncoder,
- dimension: usize,
- mode: EncodingMode,
- // TF-IDF statistics
- tfidf_doc_count: u32,
- tfidf_word_doc_freq: std.StringHashMapUnmanaged(u32),
-
- const Self = @This();
-
- pub const EncodingMode = enum {
- char_ngram, // Original: char trigram bundling
- word_pos, // Word-level with positional encoding
- word_tfidf, // Word-level with TF-IDF weighting
- hybrid, // Char n-gram + word-level combined
- };
-
- pub fn init(allocator: std.mem.Allocator, item_memory: *ItemMemory, ngram_encoder: *NGramEncoder, dimension: usize, mode: EncodingMode) Self {
- return Self{
- .allocator = allocator,
- .item_memory = item_memory,
- .ngram_encoder = ngram_encoder,
- .dimension = dimension,
- .mode = mode,
- .tfidf_doc_count = 0,
- .tfidf_word_doc_freq = .{},
- };
- }
-
- pub fn deinit(self: *Self) void {
- var wdi = self.tfidf_word_doc_freq.iterator();
- while (wdi.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.tfidf_word_doc_freq.deinit(self.allocator);
- }
-
- /// Encode a single word as hypervector using positional char binding
- pub fn encodeWord(self: *Self, word: []const u8) !HybridBigInt {
- if (word.len == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- const first_hv = try self.item_memory.getCharVector(word[0]);
- var result = vsa.permute(first_hv, 0);
-
- for (1..word.len) |i| {
- const char_hv = try self.item_memory.getCharVector(word[i]);
- var permuted = vsa.permute(char_hv, i);
- const bound = vsa.bind(&result, &permuted);
- result = bound;
- }
- return result;
- }
-
- /// Split text into words (space-separated)
- pub fn splitWords(text: []const u8) WordIterator {
- return .{ .text = text, .pos = 0 };
- }
-
- pub const WordIterator = struct {
- text: []const u8,
- pos: usize,
-
- pub fn next(self: *WordIterator) ?[]const u8 {
- while (self.pos < self.text.len and self.text[self.pos] == ' ') {
- self.pos += 1;
- }
- if (self.pos >= self.text.len) return null;
-
- const start = self.pos;
- while (self.pos < self.text.len and self.text[self.pos] != ' ') {
- self.pos += 1;
- }
- return self.text[start..self.pos];
- }
- };
-
- /// Encode text using word-level positional encoding
- pub fn encodeTextWords(self: *Self, text: []const u8) !HybridBigInt {
- var iter = splitWords(text);
- var word_idx: usize = 0;
- var result: ?HybridBigInt = null;
-
- while (iter.next()) |word| {
- var word_hv = try self.encodeWord(word);
- var positioned = vsa.permute(&word_hv, word_idx * 50);
-
- if (result) |*r| {
- const bundled = vsa.bundle2(r, &positioned);
- r.* = bundled;
- } else {
- result = positioned;
- }
- word_idx += 1;
- }
-
- if (result) |r| return r;
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- /// Update TF-IDF document frequency stats
- pub fn updateTFIDF(self: *Self, text: []const u8) !void {
- self.tfidf_doc_count += 1;
-
- var seen: std.StringHashMapUnmanaged(void) = .{};
- defer seen.deinit(self.allocator);
-
- var iter = splitWords(text);
- while (iter.next()) |word| {
- if (seen.contains(word)) continue;
- try seen.put(self.allocator, word, {});
-
- if (self.tfidf_word_doc_freq.getPtr(word)) |freq| {
- freq.* += 1;
- } else {
- const owned = try self.allocator.dupe(u8, word);
- try self.tfidf_word_doc_freq.put(self.allocator, owned, 1);
- }
- }
- }
-
- /// Encode text using TF-IDF weighted word vectors
- pub fn encodeTextTFIDF(self: *Self, text: []const u8) !HybridBigInt {
- if (self.tfidf_doc_count == 0) return self.encodeTextWords(text);
-
- var word_counts: std.StringHashMapUnmanaged(u32) = .{};
- defer word_counts.deinit(self.allocator);
- var total_words: u32 = 0;
-
- var iter = splitWords(text);
- while (iter.next()) |word| {
- if (word_counts.getPtr(word)) |cnt| {
- cnt.* += 1;
- } else {
- try word_counts.put(self.allocator, word, 1);
- }
- total_words += 1;
- }
-
- if (total_words == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- var result: ?HybridBigInt = null;
- const doc_count_f = @as(f64, @floatFromInt(self.tfidf_doc_count));
- const total_words_f = @as(f64, @floatFromInt(total_words));
-
- var wc_iter = word_counts.iterator();
- while (wc_iter.next()) |entry| {
- const word = entry.key_ptr.*;
- const count = entry.value_ptr.*;
- var word_hv = try self.encodeWord(word);
-
- const tf = @as(f64, @floatFromInt(count)) / total_words_f;
- const doc_freq = if (self.tfidf_word_doc_freq.get(word)) |df| df else 1;
- const idf = @log(doc_count_f / @as(f64, @floatFromInt(doc_freq)));
- const weight = @min(tf * idf, 10.0);
- const rounds: usize = @max(1, @as(usize, @intFromFloat(@round(weight * 3.0 + 1.0))));
-
- var weighted = word_hv;
- for (1..rounds) |_| {
- const b = vsa.bundle2(&weighted, &word_hv);
- weighted = b;
- }
-
- if (result) |*r| {
- const bundled = vsa.bundle2(r, &weighted);
- r.* = bundled;
- } else {
- result = weighted;
- }
- }
-
- if (result) |r| return r;
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- /// Encode text as char n-gram
- pub fn encodeTextCharNgram(self: *Self, text: []const u8) !HybridBigInt {
- if (text.len == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- const ngrams = try self.ngram_encoder.encodeAllNGrams(self.allocator, text);
- defer self.allocator.free(ngrams);
-
- var result = ngrams[0];
- for (ngrams[1..]) |*ng| {
- const bundled = vsa.bundle2(&result, ng);
- result = bundled;
- }
- return result;
- }
-
- /// Encode text as hybrid: char n-gram + word-level combined
- pub fn encodeTextHybrid(self: *Self, text: []const u8) !HybridBigInt {
- var ngram_hv = try self.encodeTextCharNgram(text);
- var word_hv = try self.encodeTextWords(text);
- return vsa.bundle2(&ngram_hv, &word_hv);
- }
-
- /// Dispatch to the appropriate encoding method based on mode
- pub fn encodeText(self: *Self, text: []const u8) !HybridBigInt {
- return switch (self.mode) {
- .char_ngram => self.encodeTextCharNgram(text),
- .word_pos => self.encodeTextWords(text),
- .word_tfidf => self.encodeTextTFIDF(text),
- .hybrid => self.encodeTextHybrid(text),
- };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC CLASSIFIER
-// One-shot / few-shot classification via bundled class prototypes
-// class_prototype[c] = bundle(sample_1, sample_2, ..., sample_N)
-// predict(query) = argmax_c cosine(encode(query), class_prototype[c])
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCClassifier = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- classes: std.StringHashMapUnmanaged(ClassPrototype),
- total_samples: u32,
- encoder: HDCTextEncoder,
- jit_engine: ?vsa_jit.JitVSAEngine,
-
- const Self = @This();
-
- pub const EncodingMode = HDCTextEncoder.EncodingMode;
-
- pub const ClassPrototype = struct {
- prototype_hv: *HybridBigInt,
- sample_count: u32,
- };
-
- pub const ClassScore = struct {
- label: []const u8,
- similarity: f64,
- };
-
- pub const PredictionResult = struct {
- label: []const u8,
- confidence: f64,
- top_k: [8]ClassScore,
- top_k_len: usize,
- };
-
- pub const ClassifierStats = struct {
- num_classes: usize,
- total_samples: u32,
- dimension: usize,
- avg_samples_per_class: f64,
- encoding_mode: EncodingMode,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithMode(allocator, dimension, seed, .char_ngram);
- }
-
- pub fn initWithMode(allocator: std.mem.Allocator, dimension: usize, seed: u64, mode: EncodingMode) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .classes = .{},
- .total_samples = 0,
- .encoder = undefined,
- .jit_engine = null,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, mode);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- var it = self.classes.iterator();
- while (it.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.prototype_hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.classes.deinit(self.allocator);
- self.encoder.deinit();
- self.item_memory.deinit();
- if (self.jit_engine) |*engine| {
- engine.deinit();
- }
- }
-
- /// Train: add a text sample to a class
- pub fn train(self: *Self, label: []const u8, text: []const u8) !void {
- self.fixSelfRef();
- if (self.encoder.mode == .word_tfidf) {
- try self.encoder.updateTFIDF(text);
- }
- var text_hv = try self.encoder.encodeText(text);
-
- if (self.classes.getPtr(label)) |proto| {
- // Bundle into existing prototype
- proto.prototype_hv.* = vsa.bundle2(proto.prototype_hv, &text_hv);
- proto.sample_count += 1;
- } else {
- // New class
- const proto_hv = try self.allocator.create(HybridBigInt);
- proto_hv.* = text_hv;
- const owned_label = try self.allocator.dupe(u8, label);
- try self.classes.put(self.allocator, owned_label, .{
- .prototype_hv = proto_hv,
- .sample_count = 1,
- });
- }
- self.total_samples += 1;
- }
-
- pub const TrainSample = struct { label: []const u8, text: []const u8 };
-
- /// Train on a batch of (label, text) pairs
- pub fn trainBatch(self: *Self, samples: []const TrainSample) !void {
- for (samples) |s| {
- try self.train(s.label, s.text);
- }
- }
-
- /// Predict class for input text
- pub fn predict(self: *Self, text: []const u8) !?PredictionResult {
- self.fixSelfRef();
- if (self.classes.count() == 0) return null;
-
- var text_hv = try self.encoder.encodeText(text);
-
- var best_label: []const u8 = "";
- var best_sim: f64 = -2.0;
- var top_k: [8]ClassScore = undefined;
- var top_k_len: usize = 0;
-
- var it = self.classes.iterator();
- while (it.next()) |entry| {
- var proto_hv = entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_hv);
-
- // Insert into top-k (sorted descending)
- if (top_k_len < 8) {
- top_k[top_k_len] = .{ .label = entry.key_ptr.*, .similarity = sim };
- top_k_len += 1;
- // Insertion sort
- var j: usize = top_k_len - 1;
- while (j > 0 and top_k[j - 1].similarity < top_k[j].similarity) {
- const tmp = top_k[j];
- top_k[j] = top_k[j - 1];
- top_k[j - 1] = tmp;
- j -= 1;
- }
- } else if (sim > top_k[7].similarity) {
- top_k[7] = .{ .label = entry.key_ptr.*, .similarity = sim };
- var j: usize = 7;
- while (j > 0 and top_k[j - 1].similarity < top_k[j].similarity) {
- const tmp = top_k[j];
- top_k[j] = top_k[j - 1];
- top_k[j - 1] = tmp;
- j -= 1;
- }
- }
-
- if (sim > best_sim) {
- best_sim = sim;
- best_label = entry.key_ptr.*;
- }
- }
-
- return PredictionResult{
- .label = best_label,
- .confidence = best_sim,
- .top_k = top_k,
- .top_k_len = top_k_len,
- };
- }
-
- /// Predict and return top-k class scores
- pub fn predictTopK(self: *Self, text: []const u8, k: usize) ![]ClassScore {
- self.fixSelfRef();
- var text_hv = try self.encoder.encodeText(text);
-
- var scores: std.ArrayListUnmanaged(ClassScore) = .{};
- defer scores.deinit(self.allocator);
-
- var it = self.classes.iterator();
- while (it.next()) |entry| {
- var proto_hv = entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_hv);
- try scores.append(self.allocator, .{ .label = entry.key_ptr.*, .similarity = sim });
- }
-
- // Sort descending
- const items = scores.items;
- var i: usize = 1;
- while (i < items.len) : (i += 1) {
- const key_item = items[i];
- var j: usize = i;
- while (j > 0 and items[j - 1].similarity < key_item.similarity) {
- items[j] = items[j - 1];
- j -= 1;
- }
- items[j] = key_item;
- }
-
- const result_len = @min(k, items.len);
- var results = try self.allocator.alloc(ClassScore, result_len);
- for (0..result_len) |ri| {
- results[ri] = items[ri];
- }
- return results;
- }
-
- /// Remove a class
- pub fn removeClass(self: *Self, label: []const u8) bool {
- if (self.classes.fetchRemove(label)) |kv| {
- self.total_samples -= kv.value.sample_count;
- self.allocator.destroy(kv.value.prototype_hv);
- self.allocator.free(kv.key);
- return true;
- }
- return false;
- }
-
- /// Get classifier statistics
- pub fn stats(self: *Self) ClassifierStats {
- const nc = self.classes.count();
- return .{
- .num_classes = nc,
- .total_samples = self.total_samples,
- .dimension = self.dimension,
- .avg_samples_per_class = if (nc > 0) @as(f64, @floatFromInt(self.total_samples)) / @as(f64, @floatFromInt(nc)) else 0.0,
- .encoding_mode = self.encoder.mode,
- };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC CLASSIFIER TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCClassifier one-shot classification" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 4000, 42);
- defer clf.deinit();
-
- // One example per class
- try clf.train("greeting", "hello world");
- try clf.train("farewell", "goodbye world");
-
- // Predict similar texts
- const p1 = try clf.predict("hello there");
- try std.testing.expect(p1 != null);
- try std.testing.expectEqualStrings("greeting", p1.?.label);
-
- const p2 = try clf.predict("goodbye friend");
- try std.testing.expect(p2 != null);
- try std.testing.expectEqualStrings("farewell", p2.?.label);
-}
-
-test "HDCClassifier few-shot improves accuracy" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 4000, 42);
- defer clf.deinit();
-
- // Train with multiple examples per class
- try clf.train("positive", "great amazing wonderful");
- try clf.train("positive", "excellent fantastic superb");
- try clf.train("positive", "brilliant outstanding magnificent");
-
- try clf.train("negative", "terrible horrible awful");
- try clf.train("negative", "dreadful atrocious appalling");
- try clf.train("negative", "disastrous catastrophic abysmal");
-
- // Predict
- const p1 = try clf.predict("amazing fantastic");
- try std.testing.expect(p1 != null);
- try std.testing.expectEqualStrings("positive", p1.?.label);
- try std.testing.expect(p1.?.confidence > 0.0);
-
- const p2 = try clf.predict("terrible dreadful");
- try std.testing.expect(p2 != null);
- try std.testing.expectEqualStrings("negative", p2.?.label);
-}
-
-test "HDCClassifier trainBatch" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 4000, 42);
- defer clf.deinit();
-
- const samples = [_]HDCClassifier.TrainSample{
- .{ .label = "fruit", .text = "apple orange banana" },
- .{ .label = "fruit", .text = "mango grape pear" },
- .{ .label = "animal", .text = "cat dog horse" },
- .{ .label = "animal", .text = "lion tiger bear" },
- };
- try clf.trainBatch(&samples);
-
- const s = clf.stats();
- try std.testing.expectEqual(@as(usize, 2), s.num_classes);
- try std.testing.expectEqual(@as(u32, 4), s.total_samples);
-}
-
-test "HDCClassifier predictTopK" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 4000, 42);
- defer clf.deinit();
-
- try clf.train("class_a", "alpha beta gamma");
- try clf.train("class_b", "delta epsilon zeta");
- try clf.train("class_c", "eta theta iota");
-
- const top = try clf.predictTopK("alpha gamma", 3);
- defer allocator.free(top);
-
- try std.testing.expectEqual(@as(usize, 3), top.len);
- // Best match should be class_a (shares alpha, gamma)
- try std.testing.expectEqualStrings("class_a", top[0].label);
- // All scores returned, sorted descending
- try std.testing.expect(top[0].similarity >= top[1].similarity);
- try std.testing.expect(top[1].similarity >= top[2].similarity);
-}
-
-test "HDCClassifier removeClass" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 4000, 42);
- defer clf.deinit();
-
- try clf.train("keep", "some text here");
- try clf.train("remove", "other text here");
-
- try std.testing.expectEqual(@as(usize, 2), clf.stats().num_classes);
- try std.testing.expect(clf.removeClass("remove"));
- try std.testing.expectEqual(@as(usize, 1), clf.stats().num_classes);
- try std.testing.expect(!clf.removeClass("nonexistent"));
-}
-
-test "HDCClassifier empty returns null" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 4000, 42);
- defer clf.deinit();
-
- const p = try clf.predict("anything");
- try std.testing.expect(p == null);
-}
-
-test "HDCClassifier multi-class stress" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 6000, 42);
- defer clf.deinit();
-
- // 5 classes, each with 3 training examples
- try clf.train("lang_en", "the quick brown fox jumps");
- try clf.train("lang_en", "hello world from london");
- try clf.train("lang_en", "the weather is quite nice");
-
- try clf.train("lang_de", "der schnelle braune fuchs");
- try clf.train("lang_de", "hallo welt aus berlin");
- try clf.train("lang_de", "das wetter ist sehr schon");
-
- try clf.train("lang_fr", "le renard brun rapide saute");
- try clf.train("lang_fr", "bonjour monde depuis paris");
- try clf.train("lang_fr", "le temps est tres beau");
-
- try clf.train("lang_es", "el rapido zorro marron salta");
- try clf.train("lang_es", "hola mundo desde madrid");
- try clf.train("lang_es", "el tiempo es muy bonito");
-
- try clf.train("lang_it", "la veloce volpe marrone salta");
- try clf.train("lang_it", "ciao mondo da roma");
- try clf.train("lang_it", "il tempo e molto bello");
-
- var correct: u32 = 0;
- const test_cases = [_]struct { text: []const u8, expected: []const u8 }{
- .{ .text = "the big brown dog runs", .expected = "lang_en" },
- .{ .text = "der grosse braune hund", .expected = "lang_de" },
- .{ .text = "le grand chien brun court", .expected = "lang_fr" },
- .{ .text = "el gran perro marron corre", .expected = "lang_es" },
- .{ .text = "il grande cane marrone corre", .expected = "lang_it" },
- };
-
- for (test_cases) |tc| {
- const pred = try clf.predict(tc.text);
- if (pred) |p| {
- if (std.mem.eql(u8, p.label, tc.expected)) correct += 1;
- }
- }
-
- const accuracy = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(test_cases.len));
-
- const s = clf.stats();
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC CLASSIFIER STATS (dim=6000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Classes: {d} | Samples: {d} | Avg/class: {d:.1}\n", .{ s.num_classes, s.total_samples, s.avg_samples_per_class });
- std.debug.print(" 5-lang accuracy: {d}/{d} ({d:.0}%)\n", .{ correct, test_cases.len, accuracy * 100.0 });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // With 5 classes and char n-grams, expect decent accuracy
- try std.testing.expect(correct >= 3); // At least 3/5
-}
-
-test "HDCClassifier confidence separation" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 4000, 42);
- defer clf.deinit();
-
- try clf.train("aaa", "aaaaaaaaaa");
- try clf.train("bbb", "bbbbbbbbbb");
-
- // Query with pure 'a' should strongly prefer class_aaa
- const p = try clf.predict("aaaaaa");
- try std.testing.expect(p != null);
- try std.testing.expectEqualStrings("aaa", p.?.label);
-
- // Confidence should be clearly positive
- try std.testing.expect(p.?.confidence > 0.1);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC TEXT ENCODER TESTS (word-level, TF-IDF, hybrid)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCClassifier word_pos mode basic" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 4000, 42, .word_pos);
- defer clf.deinit();
-
- try clf.train("greeting", "hello world");
- try clf.train("farewell", "goodbye world");
-
- const p1 = try clf.predict("hello there");
- try std.testing.expect(p1 != null);
- try std.testing.expectEqualStrings("greeting", p1.?.label);
-
- const p2 = try clf.predict("goodbye friend");
- try std.testing.expect(p2 != null);
- try std.testing.expectEqualStrings("farewell", p2.?.label);
-}
-
-test "HDCClassifier word_pos 5-lang accuracy" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 6000, 42, .word_pos);
- defer clf.deinit();
-
- // Same 5-language training data
- try clf.train("lang_en", "the quick brown fox jumps");
- try clf.train("lang_en", "hello world from london");
- try clf.train("lang_en", "the weather is quite nice");
-
- try clf.train("lang_de", "der schnelle braune fuchs");
- try clf.train("lang_de", "hallo welt aus berlin");
- try clf.train("lang_de", "das wetter ist sehr schon");
-
- try clf.train("lang_fr", "le renard brun rapide saute");
- try clf.train("lang_fr", "bonjour monde depuis paris");
- try clf.train("lang_fr", "le temps est tres beau");
-
- try clf.train("lang_es", "el rapido zorro marron salta");
- try clf.train("lang_es", "hola mundo desde madrid");
- try clf.train("lang_es", "el tiempo es muy bonito");
-
- try clf.train("lang_it", "la veloce volpe marrone salta");
- try clf.train("lang_it", "ciao mondo da roma");
- try clf.train("lang_it", "il tempo e molto bello");
-
- var correct: u32 = 0;
- const test_cases = [_]struct { text: []const u8, expected: []const u8 }{
- .{ .text = "the big brown dog runs", .expected = "lang_en" },
- .{ .text = "der grosse braune hund", .expected = "lang_de" },
- .{ .text = "le grand chien brun court", .expected = "lang_fr" },
- .{ .text = "el gran perro marron corre", .expected = "lang_es" },
- .{ .text = "il grande cane marrone corre", .expected = "lang_it" },
- };
-
- for (test_cases) |tc| {
- const pred = try clf.predict(tc.text);
- if (pred) |p| {
- if (std.mem.eql(u8, p.label, tc.expected)) correct += 1;
- }
- }
-
- const accuracy = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(test_cases.len));
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" WORD_POS ENCODER (dim=6000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 5-lang accuracy: {d}/{d} ({d:.0}%)\n", .{ correct, test_cases.len, accuracy * 100.0 });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- try std.testing.expect(correct >= 3);
-}
-
-test "HDCClassifier word_tfidf mode" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 6000, 42, .word_tfidf);
- defer clf.deinit();
-
- // Train with TF-IDF β common words ("the", "is") get down-weighted
- try clf.train("lang_en", "the quick brown fox jumps");
- try clf.train("lang_en", "hello world from london");
- try clf.train("lang_en", "the weather is quite nice");
-
- try clf.train("lang_de", "der schnelle braune fuchs");
- try clf.train("lang_de", "hallo welt aus berlin");
- try clf.train("lang_de", "das wetter ist sehr schon");
-
- try clf.train("lang_fr", "le renard brun rapide saute");
- try clf.train("lang_fr", "bonjour monde depuis paris");
- try clf.train("lang_fr", "le temps est tres beau");
-
- try clf.train("lang_es", "el rapido zorro marron salta");
- try clf.train("lang_es", "hola mundo desde madrid");
- try clf.train("lang_es", "el tiempo es muy bonito");
-
- try clf.train("lang_it", "la veloce volpe marrone salta");
- try clf.train("lang_it", "ciao mondo da roma");
- try clf.train("lang_it", "il tempo e molto bello");
-
- var correct: u32 = 0;
- const test_cases = [_]struct { text: []const u8, expected: []const u8 }{
- .{ .text = "the big brown dog runs", .expected = "lang_en" },
- .{ .text = "der grosse braune hund", .expected = "lang_de" },
- .{ .text = "le grand chien brun court", .expected = "lang_fr" },
- .{ .text = "el gran perro marron corre", .expected = "lang_es" },
- .{ .text = "il grande cane marrone corre", .expected = "lang_it" },
- };
-
- for (test_cases) |tc| {
- const pred = try clf.predict(tc.text);
- if (pred) |p| {
- if (std.mem.eql(u8, p.label, tc.expected)) correct += 1;
- }
- }
-
- const accuracy = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(test_cases.len));
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" WORD_TFIDF ENCODER (dim=6000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 5-lang accuracy: {d}/{d} ({d:.0}%)\n", .{ correct, test_cases.len, accuracy * 100.0 });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- try std.testing.expect(correct >= 3);
-}
-
-test "HDCClassifier hybrid mode" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 6000, 42, .hybrid);
- defer clf.deinit();
-
- try clf.train("lang_en", "the quick brown fox jumps");
- try clf.train("lang_en", "hello world from london");
- try clf.train("lang_en", "the weather is quite nice");
-
- try clf.train("lang_de", "der schnelle braune fuchs");
- try clf.train("lang_de", "hallo welt aus berlin");
- try clf.train("lang_de", "das wetter ist sehr schon");
-
- try clf.train("lang_fr", "le renard brun rapide saute");
- try clf.train("lang_fr", "bonjour monde depuis paris");
- try clf.train("lang_fr", "le temps est tres beau");
-
- try clf.train("lang_es", "el rapido zorro marron salta");
- try clf.train("lang_es", "hola mundo desde madrid");
- try clf.train("lang_es", "el tiempo es muy bonito");
-
- try clf.train("lang_it", "la veloce volpe marrone salta");
- try clf.train("lang_it", "ciao mondo da roma");
- try clf.train("lang_it", "il tempo e molto bello");
-
- var correct: u32 = 0;
- const test_cases = [_]struct { text: []const u8, expected: []const u8 }{
- .{ .text = "the big brown dog runs", .expected = "lang_en" },
- .{ .text = "der grosse braune hund", .expected = "lang_de" },
- .{ .text = "le grand chien brun court", .expected = "lang_fr" },
- .{ .text = "el gran perro marron corre", .expected = "lang_es" },
- .{ .text = "il grande cane marrone corre", .expected = "lang_it" },
- };
-
- for (test_cases) |tc| {
- const pred = try clf.predict(tc.text);
- if (pred) |p| {
- if (std.mem.eql(u8, p.label, tc.expected)) correct += 1;
- }
- }
-
- const accuracy = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(test_cases.len));
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HYBRID ENCODER (dim=6000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 5-lang accuracy: {d}/{d} ({d:.0}%)\n", .{ correct, test_cases.len, accuracy * 100.0 });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- try std.testing.expect(correct >= 3);
-}
-
-test "HDCClassifier encoder comparison" {
- const allocator = std.testing.allocator;
-
- const modes = [_]HDCClassifier.EncodingMode{ .char_ngram, .word_pos, .word_tfidf, .hybrid };
- const mode_names = [_][]const u8{ "char_ngram", "word_pos ", "word_tfidf", "hybrid " };
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" ENCODER COMPARISON (dim=8000, 5 langs, 3 samples/class)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- for (modes, 0..) |mode, mi| {
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, mode);
- defer clf.deinit();
-
- try clf.train("lang_en", "the quick brown fox jumps");
- try clf.train("lang_en", "hello world from london");
- try clf.train("lang_en", "the weather is quite nice");
- try clf.train("lang_de", "der schnelle braune fuchs");
- try clf.train("lang_de", "hallo welt aus berlin");
- try clf.train("lang_de", "das wetter ist sehr schon");
- try clf.train("lang_fr", "le renard brun rapide saute");
- try clf.train("lang_fr", "bonjour monde depuis paris");
- try clf.train("lang_fr", "le temps est tres beau");
- try clf.train("lang_es", "el rapido zorro marron salta");
- try clf.train("lang_es", "hola mundo desde madrid");
- try clf.train("lang_es", "el tiempo es muy bonito");
- try clf.train("lang_it", "la veloce volpe marrone salta");
- try clf.train("lang_it", "ciao mondo da roma");
- try clf.train("lang_it", "il tempo e molto bello");
-
- var correct: u32 = 0;
- const test_cases = [_]struct { text: []const u8, expected: []const u8 }{
- .{ .text = "the big brown dog runs", .expected = "lang_en" },
- .{ .text = "der grosse braune hund", .expected = "lang_de" },
- .{ .text = "le grand chien brun court", .expected = "lang_fr" },
- .{ .text = "el gran perro marron corre", .expected = "lang_es" },
- .{ .text = "il grande cane marrone corre", .expected = "lang_it" },
- };
-
- for (test_cases) |tc| {
- const pred = try clf.predict(tc.text);
- if (pred) |p| {
- if (std.mem.eql(u8, p.label, tc.expected)) correct += 1;
- }
- }
-
- const acc = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(test_cases.len));
- std.debug.print(" {s}: {d}/5 ({d:.0}%)\n", .{ mode_names[mi], correct, acc * 100.0 });
- }
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC CLUSTERING
-// Unsupervised K-Means in Hyperdimensional Space
-// centroid[c] = bundle(samples assigned to c)
-// assign(sample) = argmax_c cosine(sample_hv, centroid[c])
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCClustering = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- const Self = @This();
-
- pub const EncodingMode = HDCTextEncoder.EncodingMode;
-
- pub const ClusterConfig = struct {
- k: usize = 3,
- max_iter: usize = 100,
- convergence_threshold: f64 = 0.001,
- seed: u64 = 42,
- };
-
- pub const Cluster = struct {
- centroid: HybridBigInt,
- members: std.ArrayListUnmanaged(usize),
- size: usize,
- };
-
- pub const ClusterResult = struct {
- clusters: []Cluster,
- assignments: []usize,
- iterations: usize,
- converged: bool,
- total_inertia: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithMode(allocator, dimension, seed, .word_pos);
- }
-
- pub fn initWithMode(allocator: std.mem.Allocator, dimension: usize, seed: u64, mode: EncodingMode) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, mode);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Encode multiple texts into hypervectors
- pub fn encodeAll(self: *Self, texts: []const []const u8) ![]HybridBigInt {
- self.fixSelfRef();
- var vectors = try self.allocator.alloc(HybridBigInt, texts.len);
- for (texts, 0..) |text, i| {
- vectors[i] = try self.encoder.encodeText(text);
- }
- return vectors;
- }
-
- /// Simple PRNG (xorshift64)
- fn xorshift64(state: *u64) u64 {
- var x = state.*;
- x ^= x << 13;
- x ^= x >> 7;
- x ^= x << 17;
- state.* = x;
- return x;
- }
-
- /// Run k-means on pre-encoded hypervectors
- pub fn fitVectors(self: *Self, data: []HybridBigInt, config: ClusterConfig) !ClusterResult {
- const k = @min(config.k, data.len);
- if (k == 0 or data.len == 0) {
- return ClusterResult{
- .clusters = try self.allocator.alloc(Cluster, 0),
- .assignments = try self.allocator.alloc(usize, 0),
- .iterations = 0,
- .converged = true,
- .total_inertia = 0,
- };
- }
-
- // Initialize centroids: pick k distinct samples
- var centroids = try self.allocator.alloc(HybridBigInt, k);
- defer self.allocator.free(centroids);
-
- var rng_state = config.seed;
- var used: std.ArrayListUnmanaged(usize) = .{};
- defer used.deinit(self.allocator);
-
- for (0..k) |ci| {
- var idx = xorshift64(&rng_state) % data.len;
- // Ensure distinct
- var attempts: usize = 0;
- while (attempts < data.len) : (attempts += 1) {
- var found = false;
- for (used.items) |u| {
- if (u == idx) {
- found = true;
- break;
- }
- }
- if (!found) break;
- idx = (idx + 1) % data.len;
- }
- try used.append(self.allocator, idx);
- centroids[ci] = data[idx];
- }
-
- var assignments = try self.allocator.alloc(usize, data.len);
- @memset(assignments, 0);
-
- var iterations: usize = 0;
- var converged = false;
-
- while (iterations < config.max_iter) : (iterations += 1) {
- // Assignment step: assign each point to nearest centroid
- var changed = false;
- for (data, 0..) |*sample, di| {
- var best_cluster: usize = 0;
- var best_sim: f64 = -2.0;
-
- for (0..k) |ci| {
- const sim = vsa.cosineSimilarity(sample, ¢roids[ci]);
- if (sim > best_sim) {
- best_sim = sim;
- best_cluster = ci;
- }
- }
-
- if (assignments[di] != best_cluster) {
- assignments[di] = best_cluster;
- changed = true;
- }
- }
-
- if (!changed) {
- converged = true;
- break;
- }
-
- // Update step: recompute centroids by bundling assigned samples
- var max_drift: f64 = 0;
- for (0..k) |ci| {
- var new_centroid: ?HybridBigInt = null;
-
- for (0..data.len) |di| {
- if (assignments[di] == ci) {
- if (new_centroid) |*nc| {
- const bundled = vsa.bundle2(nc, &data[di]);
- nc.* = bundled;
- } else {
- new_centroid = data[di];
- }
- }
- }
-
- if (new_centroid) |nc| {
- // Measure drift
- var nc_mut = nc;
- const drift = 1.0 - vsa.cosineSimilarity(¢roids[ci], &nc_mut);
- if (drift > max_drift) max_drift = drift;
- centroids[ci] = nc;
- }
- }
-
- if (max_drift < config.convergence_threshold) {
- converged = true;
- iterations += 1;
- break;
- }
- }
-
- // Build result clusters
- var clusters = try self.allocator.alloc(Cluster, k);
- for (0..k) |ci| {
- clusters[ci] = .{
- .centroid = centroids[ci],
- .members = .{},
- .size = 0,
- };
- }
-
- var total_inertia: f64 = 0;
- for (0..data.len) |di| {
- const ci = assignments[di];
- try clusters[ci].members.append(self.allocator, di);
- clusters[ci].size += 1;
- const dist = 1.0 - vsa.cosineSimilarity(&data[di], ¢roids[ci]);
- total_inertia += dist;
- }
-
- return ClusterResult{
- .clusters = clusters,
- .assignments = assignments,
- .iterations = iterations,
- .converged = converged,
- .total_inertia = total_inertia,
- };
- }
-
- /// Run k-means on text data
- pub fn fit(self: *Self, texts: []const []const u8, config: ClusterConfig) !ClusterResult {
- const vectors = try self.encodeAll(texts);
- defer self.allocator.free(vectors);
- return self.fitVectors(vectors, config);
- }
-
- /// Predict cluster for new text
- pub fn predict(self: *Self, text: []const u8, clusters: []const Cluster) !struct { cluster: usize, similarity: f64 } {
- self.fixSelfRef();
- var text_hv = try self.encoder.encodeText(text);
-
- var best_cluster: usize = 0;
- var best_sim: f64 = -2.0;
-
- for (clusters, 0..) |*cl, ci| {
- var centroid = cl.centroid;
- const sim = vsa.cosineSimilarity(&text_hv, ¢roid);
- if (sim > best_sim) {
- best_sim = sim;
- best_cluster = ci;
- }
- }
-
- return .{ .cluster = best_cluster, .similarity = best_sim };
- }
-
- /// Compute silhouette score for clustering quality
- /// score in [-1, 1]: higher = better separation
- pub fn silhouetteScore(self: *Self, result: ClusterResult, data: []HybridBigInt) f64 {
- _ = self;
- if (data.len <= 1 or result.clusters.len <= 1) return 0;
-
- var total_score: f64 = 0;
- var count: usize = 0;
-
- for (0..data.len) |i| {
- const ci = result.assignments[i];
- if (result.clusters[ci].size <= 1) continue;
-
- // a(i) = average distance to same-cluster points
- var a_sum: f64 = 0;
- var a_count: usize = 0;
- for (result.clusters[ci].members.items) |j| {
- if (j == i) continue;
- a_sum += 1.0 - vsa.cosineSimilarity(&data[i], &data[j]);
- a_count += 1;
- }
- const a = if (a_count > 0) a_sum / @as(f64, @floatFromInt(a_count)) else 0;
-
- // b(i) = min average distance to other clusters
- var b: f64 = std.math.inf(f64);
- for (0..result.clusters.len) |oi| {
- if (oi == ci) continue;
- if (result.clusters[oi].size == 0) continue;
-
- var b_sum: f64 = 0;
- for (result.clusters[oi].members.items) |j| {
- b_sum += 1.0 - vsa.cosineSimilarity(&data[i], &data[j]);
- }
- const avg_b = b_sum / @as(f64, @floatFromInt(result.clusters[oi].size));
- if (avg_b < b) b = avg_b;
- }
-
- const s = if (@max(a, b) > 0) (b - a) / @max(a, b) else 0;
- total_score += s;
- count += 1;
- }
-
- return if (count > 0) total_score / @as(f64, @floatFromInt(count)) else 0;
- }
-
- /// Free a ClusterResult
- pub fn freeResult(self: *Self, result: ClusterResult) void {
- for (result.clusters) |*cl| {
- var c = cl.*;
- c.members.deinit(self.allocator);
- }
- self.allocator.free(result.clusters);
- self.allocator.free(result.assignments);
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC CLUSTERING TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCClustering basic k=2" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 4000, 42);
- defer cl.deinit();
-
- // Two distinct groups
- const texts = [_][]const u8{
- "cat dog pet animal",
- "dog cat puppy kitten",
- "pet animal creature beast",
- "car truck vehicle motor",
- "bus train transport road",
- "vehicle engine wheel drive",
- };
-
- const result = try cl.fit(&texts, .{ .k = 2, .max_iter = 50, .seed = 42 });
- defer cl.freeResult(result);
-
- try std.testing.expectEqual(@as(usize, 2), result.clusters.len);
- try std.testing.expectEqual(@as(usize, 6), result.assignments.len);
- try std.testing.expect(result.converged);
-
- // All samples should be assigned
- var total_members: usize = 0;
- for (result.clusters) |c| {
- total_members += c.size;
- }
- try std.testing.expectEqual(@as(usize, 6), total_members);
-}
-
-test "HDCClustering convergence" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 4000, 42);
- defer cl.deinit();
-
- const texts = [_][]const u8{
- "apple orange banana fruit",
- "grape mango pear fruit",
- "table chair desk furniture",
- "sofa bed shelf furniture",
- };
-
- const result = try cl.fit(&texts, .{ .k = 2, .max_iter = 100, .seed = 123 });
- defer cl.freeResult(result);
-
- try std.testing.expect(result.converged);
- try std.testing.expect(result.iterations <= 100);
- try std.testing.expect(result.total_inertia >= 0);
-}
-
-test "HDCClustering predict new sample" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 4000, 42);
- defer cl.deinit();
-
- const texts = [_][]const u8{
- "cat dog pet animal",
- "puppy kitten hamster",
- "car truck bus vehicle",
- "train plane ship transport",
- };
-
- const result = try cl.fit(&texts, .{ .k = 2, .seed = 42 });
- defer cl.freeResult(result);
-
- // Predict which cluster a new animal text belongs to
- const pred_animal = try cl.predict("dog cat pet", result.clusters);
- const pred_vehicle = try cl.predict("car bus truck", result.clusters);
-
- // They should go to different clusters (the one matching their group)
- // Check that at least the similarity is reasonable
- try std.testing.expect(pred_animal.similarity > -1.0);
- try std.testing.expect(pred_vehicle.similarity > -1.0);
-}
-
-test "HDCClustering k=1 trivial" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 4000, 42);
- defer cl.deinit();
-
- const texts = [_][]const u8{ "hello world", "goodbye world" };
- const result = try cl.fit(&texts, .{ .k = 1, .seed = 42 });
- defer cl.freeResult(result);
-
- try std.testing.expectEqual(@as(usize, 1), result.clusters.len);
- try std.testing.expectEqual(@as(usize, 2), result.clusters[0].size);
- try std.testing.expect(result.converged);
-}
-
-test "HDCClustering silhouette score" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 4000, 42);
- defer cl.deinit();
-
- const texts = [_][]const u8{
- "aaaa aaaa aaaa",
- "aaaa aaaa bbbb",
- "zzzz zzzz zzzz",
- "zzzz zzzz yyyy",
- };
-
- const vectors = try cl.encodeAll(&texts);
- defer allocator.free(vectors);
-
- const result = try cl.fitVectors(vectors, .{ .k = 2, .seed = 42 });
- defer cl.freeResult(result);
-
- const score = cl.silhouetteScore(result, vectors);
- // Well-separated clusters should have positive silhouette
- try std.testing.expect(score > -1.0);
- try std.testing.expect(score <= 1.0);
-}
-
-test "HDCClustering empty data" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 4000, 42);
- defer cl.deinit();
-
- const texts = [_][]const u8{};
- const result = try cl.fit(&texts, .{ .k = 3, .seed = 42 });
- defer cl.freeResult(result);
-
- try std.testing.expectEqual(@as(usize, 0), result.clusters.len);
- try std.testing.expect(result.converged);
-}
-
-test "HDCClustering k > n clamps to n" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 4000, 42);
- defer cl.deinit();
-
- const texts = [_][]const u8{ "hello", "world" };
- const result = try cl.fit(&texts, .{ .k = 10, .seed = 42 });
- defer cl.freeResult(result);
-
- // k clamped to data.len = 2
- try std.testing.expectEqual(@as(usize, 2), result.clusters.len);
-}
-
-test "HDCClustering 3-class language grouping" {
- const allocator = std.testing.allocator;
- var cl = HDCClustering.init(allocator, 6000, 42);
- defer cl.deinit();
-
- // 3 languages, 3 samples each = 9 texts
- const texts = [_][]const u8{
- "the quick brown fox jumps",
- "hello world from london",
- "the weather is quite nice",
- "der schnelle braune fuchs",
- "hallo welt aus berlin",
- "das wetter ist sehr schon",
- "le renard brun rapide saute",
- "bonjour monde depuis paris",
- "le temps est tres beau",
- };
-
- const vectors = try cl.encodeAll(&texts);
- defer allocator.free(vectors);
-
- const result = try cl.fitVectors(vectors, .{ .k = 3, .max_iter = 100, .seed = 42 });
- defer cl.freeResult(result);
-
- try std.testing.expect(result.converged);
-
- // Check that samples of same language are in same cluster
- // English: 0,1,2 German: 3,4,5 French: 6,7,8
- const en_cluster = result.assignments[0];
- const de_cluster = result.assignments[3];
- const fr_cluster = result.assignments[6];
-
- var en_correct: u32 = 0;
- var de_correct: u32 = 0;
- var fr_correct: u32 = 0;
-
- for (0..3) |i| {
- if (result.assignments[i] == en_cluster) en_correct += 1;
- if (result.assignments[3 + i] == de_cluster) de_correct += 1;
- if (result.assignments[6 + i] == fr_cluster) fr_correct += 1;
- }
-
- const total_correct = en_correct + de_correct + fr_correct;
- const accuracy = @as(f64, @floatFromInt(total_correct)) / 9.0;
-
- const sil = cl.silhouetteScore(result, vectors);
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC CLUSTERING (dim=6000, k=3)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Iterations: {d} | Converged: {}\n", .{ result.iterations, result.converged });
- std.debug.print(" Inertia: {d:.4} | Silhouette: {d:.4}\n", .{ result.total_inertia, sil });
- std.debug.print(" Cluster sizes: ", .{});
- for (result.clusters, 0..) |c, ci| {
- std.debug.print("[{d}]={d} ", .{ ci, c.size });
- }
- std.debug.print("\n", .{});
- std.debug.print(" Language grouping: {d}/9 ({d:.0}%)\n", .{ total_correct, accuracy * 100.0 });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // At least 6/9 correct grouping (majority of each language in same cluster)
- try std.testing.expect(total_correct >= 6);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC ANOMALY DETECTOR
-// One-class novelty detection: learns "normal", detects outliers
-// normal_proto = bundle(all_normal_samples)
-// anomaly_score = 1 - cosine(query, normal_proto)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCAnomalyDetector = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- profiles: std.StringHashMapUnmanaged(AnomalyProfile),
- encoder: HDCTextEncoder,
- sensitivity: f64,
-
- const Self = @This();
-
- pub const EncodingMode = HDCTextEncoder.EncodingMode;
-
- pub const AnomalyProfile = struct {
- prototype_hv: *HybridBigInt,
- sample_count: u32,
- mean_score: f64,
- std_score: f64,
- threshold: f64,
- };
-
- pub const AnomalyResult = struct {
- score: f64,
- is_anomaly: bool,
- nearest_profile: []const u8,
- nearest_similarity: f64,
- };
-
- pub const DetectorStats = struct {
- num_profiles: usize,
- total_samples: u32,
- dimension: usize,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithMode(allocator, dimension, seed, .word_pos, 2.0);
- }
-
- pub fn initWithMode(
- allocator: std.mem.Allocator,
- dimension: usize,
- seed: u64,
- mode: EncodingMode,
- sensitivity: f64,
- ) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .profiles = .{},
- .encoder = undefined,
- .sensitivity = sensitivity,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, mode);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- var it = self.profiles.iterator();
- while (it.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.prototype_hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.profiles.deinit(self.allocator);
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Train: add a normal sample to a profile
- pub fn trainNormal(self: *Self, profile_name: []const u8, text: []const u8) !void {
- self.fixSelfRef();
- var text_hv = try self.encoder.encodeText(text);
-
- if (self.profiles.getPtr(profile_name)) |prof| {
- prof.prototype_hv.* = vsa.bundle2(prof.prototype_hv, &text_hv);
- prof.sample_count += 1;
- } else {
- const proto_hv = try self.allocator.create(HybridBigInt);
- proto_hv.* = text_hv;
- const owned_name = try self.allocator.dupe(u8, profile_name);
- try self.profiles.put(self.allocator, owned_name, .{
- .prototype_hv = proto_hv,
- .sample_count = 1,
- .mean_score = 0,
- .std_score = 0,
- .threshold = 0.5, // default threshold
- });
- }
- }
-
- /// Calibrate threshold from training data
- pub fn calibrate(self: *Self, profile_name: []const u8, normal_samples: []const []const u8) !void {
- self.fixSelfRef();
- const prof = self.profiles.getPtr(profile_name) orelse return;
-
- if (normal_samples.len == 0) return;
-
- // Compute anomaly scores for all training samples
- var sum: f64 = 0;
- var scores = try self.allocator.alloc(f64, normal_samples.len);
- defer self.allocator.free(scores);
-
- for (normal_samples, 0..) |text, i| {
- var text_hv = try self.encoder.encodeText(text);
- const sim = vsa.cosineSimilarity(&text_hv, prof.prototype_hv);
- scores[i] = 1.0 - sim;
- sum += scores[i];
- }
-
- const mean = sum / @as(f64, @floatFromInt(normal_samples.len));
-
- // Standard deviation
- var var_sum: f64 = 0;
- for (scores) |s| {
- const d = s - mean;
- var_sum += d * d;
- }
- const std_dev = @sqrt(var_sum / @as(f64, @floatFromInt(normal_samples.len)));
-
- prof.mean_score = mean;
- prof.std_score = std_dev;
- prof.threshold = mean + self.sensitivity * std_dev;
- }
-
- /// Detect anomaly against all profiles
- pub fn detect(self: *Self, text: []const u8) !?AnomalyResult {
- self.fixSelfRef();
- if (self.profiles.count() == 0) return null;
-
- var text_hv = try self.encoder.encodeText(text);
-
- var best_profile: []const u8 = "";
- var best_sim: f64 = -2.0;
- var best_score: f64 = 2.0;
-
- var it = self.profiles.iterator();
- while (it.next()) |entry| {
- var proto_hv = entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_hv);
- const score = 1.0 - sim;
-
- if (sim > best_sim) {
- best_sim = sim;
- best_score = score;
- best_profile = entry.key_ptr.*;
- }
- }
-
- // Check against nearest profile's threshold
- const prof = self.profiles.getPtr(best_profile).?;
- return AnomalyResult{
- .score = best_score,
- .is_anomaly = best_score > prof.threshold,
- .nearest_profile = best_profile,
- .nearest_similarity = best_sim,
- };
- }
-
- /// Detect against a specific profile
- pub fn detectAgainst(self: *Self, text: []const u8, profile_name: []const u8) !?AnomalyResult {
- self.fixSelfRef();
- const prof = self.profiles.getPtr(profile_name) orelse return null;
-
- var text_hv = try self.encoder.encodeText(text);
- var proto_hv = prof.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_hv);
- const score = 1.0 - sim;
-
- return AnomalyResult{
- .score = score,
- .is_anomaly = score > prof.threshold,
- .nearest_profile = profile_name,
- .nearest_similarity = sim,
- };
- }
-
- /// Remove a profile
- pub fn removeProfile(self: *Self, name: []const u8) bool {
- if (self.profiles.fetchRemove(name)) |kv| {
- self.allocator.destroy(kv.value.prototype_hv);
- self.allocator.free(kv.key);
- return true;
- }
- return false;
- }
-
- /// Get detector statistics
- pub fn stats(self: *Self) DetectorStats {
- var total: u32 = 0;
- var it = self.profiles.iterator();
- while (it.next()) |entry| {
- total += entry.value_ptr.sample_count;
- }
- return .{
- .num_profiles = self.profiles.count(),
- .total_samples = total,
- .dimension = self.dimension,
- };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC ANOMALY DETECTOR TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCAnomalyDetector basic normal vs anomaly" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.init(allocator, 4000, 42);
- defer det.deinit();
-
- // Train on English text as "normal"
- try det.trainNormal("english", "the quick brown fox");
- try det.trainNormal("english", "hello world from london");
- try det.trainNormal("english", "the weather is quite nice");
-
- // Calibrate threshold
- const cal_samples = [_][]const u8{
- "the quick brown fox",
- "hello world from london",
- "the weather is quite nice",
- };
- try det.calibrate("english", &cal_samples);
-
- // Normal text should not be anomalous
- const r_normal = try det.detect("the big brown dog");
- try std.testing.expect(r_normal != null);
- try std.testing.expect(!r_normal.?.is_anomaly);
-
- // Very different text should be anomalous
- const r_anomaly = try det.detect("zzzz xxxx yyyy qqqq");
- try std.testing.expect(r_anomaly != null);
- try std.testing.expect(r_anomaly.?.score > r_normal.?.score);
-}
-
-test "HDCAnomalyDetector calibrate sets threshold" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.init(allocator, 4000, 42);
- defer det.deinit();
-
- try det.trainNormal("logs", "GET /api/users 200 OK");
- try det.trainNormal("logs", "GET /api/items 200 OK");
- try det.trainNormal("logs", "POST /api/login 200 OK");
-
- const samples = [_][]const u8{
- "GET /api/users 200 OK",
- "GET /api/items 200 OK",
- "POST /api/login 200 OK",
- };
- try det.calibrate("logs", &samples);
-
- const prof = det.profiles.getPtr("logs").?;
- try std.testing.expect(prof.threshold > 0);
- try std.testing.expect(prof.mean_score >= 0);
- try std.testing.expect(prof.std_score >= 0);
-}
-
-test "HDCAnomalyDetector detectAgainst specific profile" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.init(allocator, 4000, 42);
- defer det.deinit();
-
- try det.trainNormal("profile_a", "aaaa bbbb cccc");
- try det.trainNormal("profile_b", "xxxx yyyy zzzz");
-
- const ra = try det.detectAgainst("aaaa bbbb", "profile_a");
- const rb = try det.detectAgainst("aaaa bbbb", "profile_b");
-
- try std.testing.expect(ra != null);
- try std.testing.expect(rb != null);
- // "aaaa bbbb" should be more similar to profile_a
- try std.testing.expect(ra.?.score < rb.?.score);
-}
-
-test "HDCAnomalyDetector multi-profile" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.init(allocator, 4000, 42);
- defer det.deinit();
-
- try det.trainNormal("web", "GET /api/users HTTP");
- try det.trainNormal("web", "POST /api/login HTTP");
-
- try det.trainNormal("db", "SELECT FROM users WHERE");
- try det.trainNormal("db", "INSERT INTO logs VALUES");
-
- // Web-like query should match web profile
- const r_web = try det.detect("GET /api/items HTTP");
- try std.testing.expect(r_web != null);
- try std.testing.expectEqualStrings("web", r_web.?.nearest_profile);
-
- // DB-like query should match db profile
- const r_db = try det.detect("SELECT FROM orders WHERE");
- try std.testing.expect(r_db != null);
- try std.testing.expectEqualStrings("db", r_db.?.nearest_profile);
-}
-
-test "HDCAnomalyDetector removeProfile" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.init(allocator, 4000, 42);
- defer det.deinit();
-
- try det.trainNormal("keep", "some normal text");
- try det.trainNormal("drop", "other normal text");
-
- try std.testing.expectEqual(@as(usize, 2), det.stats().num_profiles);
- try std.testing.expect(det.removeProfile("drop"));
- try std.testing.expectEqual(@as(usize, 1), det.stats().num_profiles);
- try std.testing.expect(!det.removeProfile("nonexistent"));
-}
-
-test "HDCAnomalyDetector empty returns null" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.init(allocator, 4000, 42);
- defer det.deinit();
-
- const r = try det.detect("anything");
- try std.testing.expect(r == null);
-}
-
-test "HDCAnomalyDetector score ordering" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.init(allocator, 4000, 42);
- defer det.deinit();
-
- // Train on very specific pattern
- try det.trainNormal("pattern", "aaaa aaaa aaaa aaaa");
- try det.trainNormal("pattern", "aaaa aaaa aaaa bbbb");
- try det.trainNormal("pattern", "aaaa aaaa bbbb bbbb");
-
- // Exact match should have lowest score
- const r_exact = try det.detectAgainst("aaaa aaaa aaaa aaaa", "pattern");
- // Similar should have medium score
- const r_similar = try det.detectAgainst("aaaa aaaa cccc cccc", "pattern");
- // Totally different should have highest score
- const r_different = try det.detectAgainst("zzzz zzzz zzzz zzzz", "pattern");
-
- try std.testing.expect(r_exact != null);
- try std.testing.expect(r_similar != null);
- try std.testing.expect(r_different != null);
-
- // Score ordering: exact < similar < different
- try std.testing.expect(r_exact.?.score <= r_similar.?.score);
- try std.testing.expect(r_similar.?.score <= r_different.?.score);
-}
-
-test "HDCAnomalyDetector intrusion detection demo" {
- const allocator = std.testing.allocator;
- var det = HDCAnomalyDetector.initWithMode(allocator, 6000, 42, .word_pos, 2.0);
- defer det.deinit();
-
- // Train on normal HTTP logs
- const normal_logs = [_][]const u8{
- "GET /api/users 200 OK",
- "GET /api/items 200 OK",
- "POST /api/login 200 OK",
- "GET /api/products 200 OK",
- "PUT /api/users 200 OK",
- "DELETE /api/items 200 OK",
- };
-
- for (normal_logs) |log| {
- try det.trainNormal("http", log);
- }
- try det.calibrate("http", &normal_logs);
-
- // Test normal traffic
- const r1 = try det.detectAgainst("GET /api/orders 200 OK", "http");
- // Test suspicious traffic
- const r2 = try det.detectAgainst("XYZZY /etc/passwd 500 ERROR", "http");
- // Test SQL injection attempt
- const r3 = try det.detectAgainst("SELECT DROP TABLE users", "http");
-
- try std.testing.expect(r1 != null);
- try std.testing.expect(r2 != null);
- try std.testing.expect(r3 != null);
-
- // Suspicious should score higher than normal
- try std.testing.expect(r2.?.score > r1.?.score);
-
- const s = det.stats();
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC ANOMALY DETECTOR (dim=6000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Profiles: {d} | Samples: {d}\n", .{ s.num_profiles, s.total_samples });
-
- const prof = det.profiles.getPtr("http").?;
- std.debug.print(" Threshold: {d:.4} (mean={d:.4} std={d:.4})\n", .{ prof.threshold, prof.mean_score, prof.std_score });
- std.debug.print(" Normal traffic: score={d:.4} anomaly={}\n", .{ r1.?.score, r1.?.is_anomaly });
- std.debug.print(" Suspicious: score={d:.4} anomaly={}\n", .{ r2.?.score, r2.?.is_anomaly });
- std.debug.print(" SQL injection: score={d:.4} anomaly={}\n", .{ r3.?.score, r3.?.is_anomaly });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC SEQUENCE PREDICTOR β Word-Level Next-Token Prediction
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Architecture:
-// Training: text β sliding n-gram windows β (context_hv, next_word) pairs
-// Prediction: encode query context β find nearest stored context β return word
-// Generation: greedy or beam search multi-step prediction
-//
-// Context encoding:
-// context_hv = bundle(perm(word_hv[0], 0), perm(word_hv[1], 50), ...)
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCSequencePredictor = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
- context_window: usize,
- contexts: std.ArrayListUnmanaged(ContextEntry),
- vocabulary: std.StringHashMapUnmanaged(HybridBigInt),
-
- const Self = @This();
-
- pub const EncodingMode = HDCTextEncoder.EncodingMode;
-
- pub const ContextEntry = struct {
- context_hv: HybridBigInt,
- next_word: []const u8, // owned by allocator
- };
-
- pub const PredictionEntry = struct {
- word: []const u8,
- score: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithConfig(allocator, dimension, seed, 3);
- }
-
- pub fn initWithConfig(allocator: std.mem.Allocator, dimension: usize, seed: u64, context_window: usize) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .context_window = context_window,
- .contexts = .{},
- .vocabulary = .{},
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .word_pos);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- // Free context entries
- for (self.contexts.items) |entry| {
- self.allocator.free(entry.next_word);
- }
- self.contexts.deinit(self.allocator);
-
- // Free vocabulary keys
- var vit = self.vocabulary.iterator();
- while (vit.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.vocabulary.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Get or compute word hypervector (cached in vocabulary)
- fn getWordVector(self: *Self, word: []const u8) !HybridBigInt {
- if (self.vocabulary.get(word)) |cached| return cached;
- const hv = try self.encoder.encodeWord(word);
- const owned = try self.allocator.dupe(u8, word);
- try self.vocabulary.put(self.allocator, owned, hv);
- return hv;
- }
-
- /// Encode a context (array of words) into a single hypervector
- /// context_hv = bundle(perm(word[0], 0), perm(word[1], 50), ...)
- pub fn encodeContext(self: *Self, words: []const []const u8) !HybridBigInt {
- if (words.len == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- var first_hv = try self.getWordVector(words[0]);
- var result = vsa.permute(&first_hv, 0);
-
- for (1..words.len) |i| {
- var word_hv = try self.getWordVector(words[i]);
- var positioned = vsa.permute(&word_hv, i * 50);
- result = vsa.bundle2(&result, &positioned);
- }
- return result;
- }
-
- /// Train: extract sliding n-gram windows from text
- /// For "the cat sat on" with window=3:
- /// ("the","cat") β "sat", ("cat","sat") β "on"
- pub fn train(self: *Self, text: []const u8) !void {
- self.fixSelfRef();
-
- // Split text into words
- var words: std.ArrayListUnmanaged([]const u8) = .{};
- defer words.deinit(self.allocator);
-
- var iter = HDCTextEncoder.splitWords(text);
- while (iter.next()) |word| {
- try words.append(self.allocator, word);
- }
-
- if (words.items.len < self.context_window) return;
-
- // Sliding window: context = words[i..i+n-1], next = words[i+n-1]
- const n = self.context_window;
- for (0..words.items.len - (n - 1)) |i| {
- const context_words = words.items[i .. i + n - 1];
- const next_word = words.items[i + n - 1];
-
- const ctx_hv = try self.encodeContext(context_words);
- // Cache next_word vector too (needed when generate feeds predictions back as context)
- _ = try self.getWordVector(next_word);
- const owned_word = try self.allocator.dupe(u8, next_word);
- try self.contexts.append(self.allocator, .{
- .context_hv = ctx_hv,
- .next_word = owned_word,
- });
- }
- }
-
- /// Predict next word given context words
- pub fn predictNext(self: *Self, context_words: []const []const u8) !?PredictionEntry {
- self.fixSelfRef();
- if (self.contexts.items.len == 0) return null;
-
- var query = try self.encodeContext(context_words);
-
- var best_word: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- for (self.contexts.items) |*entry| {
- const sim = vsa.cosineSimilarity(&query, &entry.context_hv);
- if (sim > best_sim) {
- best_sim = sim;
- best_word = entry.next_word;
- }
- }
-
- if (best_sim <= -2.0) return null;
- return .{ .word = best_word, .score = best_sim };
- }
-
- /// Predict top-k next words (scores aggregated per unique word)
- pub fn predictTopK(self: *Self, context_words: []const []const u8, k: usize) ![]PredictionEntry {
- self.fixSelfRef();
- if (self.contexts.items.len == 0) return try self.allocator.alloc(PredictionEntry, 0);
-
- var query = try self.encodeContext(context_words);
-
- // Aggregate: max similarity per unique next_word
- var word_scores: std.StringHashMapUnmanaged(f64) = .{};
- defer word_scores.deinit(self.allocator);
-
- for (self.contexts.items) |*entry| {
- const sim = vsa.cosineSimilarity(&query, &entry.context_hv);
- if (word_scores.getPtr(entry.next_word)) |existing| {
- if (sim > existing.*) existing.* = sim;
- } else {
- try word_scores.put(self.allocator, entry.next_word, sim);
- }
- }
-
- // Collect into sortable array
- var entries: std.ArrayListUnmanaged(PredictionEntry) = .{};
- defer entries.deinit(self.allocator);
-
- var it = word_scores.iterator();
- while (it.next()) |e| {
- try entries.append(self.allocator, .{ .word = e.key_ptr.*, .score = e.value_ptr.* });
- }
-
- // Insertion sort descending by score
- const items = entries.items;
- var si: usize = 1;
- while (si < items.len) : (si += 1) {
- const key_item = items[si];
- var j: usize = si;
- while (j > 0 and items[j - 1].score < key_item.score) {
- items[j] = items[j - 1];
- j -= 1;
- }
- items[j] = key_item;
- }
-
- const result_len = @min(k, items.len);
- const results = try self.allocator.alloc(PredictionEntry, result_len);
- for (0..result_len) |ri| {
- results[ri] = items[ri];
- }
- return results;
- }
-
- /// Generate sequence greedily: predict one word at a time
- /// Returns slice of word string references (outer slice owned by caller)
- pub fn generate(self: *Self, seed_words: []const []const u8, steps: usize) ![]const []const u8 {
- self.fixSelfRef();
-
- var sequence: std.ArrayListUnmanaged([]const u8) = .{};
-
- // Start with seed words
- for (seed_words) |w| {
- try sequence.append(self.allocator, w);
- }
-
- const window_size = self.context_window - 1;
-
- for (0..steps) |_| {
- const len = sequence.items.len;
- if (len < window_size) break;
-
- const context = sequence.items[len - window_size .. len];
- const pred = try self.predictNext(context);
- if (pred) |p| {
- try sequence.append(self.allocator, p.word);
- } else break;
- }
-
- return try sequence.toOwnedSlice(self.allocator);
- }
-
- /// Beam search generation: explore multiple paths
- /// Returns the best sequence found
- pub fn generateBeam(self: *Self, seed_words: []const []const u8, steps: usize, beam_width: usize) ![]const []const u8 {
- self.fixSelfRef();
- const window_size = self.context_window - 1;
-
- // Beam entry: (sequence words, cumulative score)
- const BeamEntry = struct {
- words: std.ArrayListUnmanaged([]const u8),
- score: f64,
- };
-
- // Initialize beam with seed
- var beams: std.ArrayListUnmanaged(BeamEntry) = .{};
- defer {
- for (beams.items) |*b| {
- b.words.deinit(self.allocator);
- }
- beams.deinit(self.allocator);
- }
-
- var initial_words: std.ArrayListUnmanaged([]const u8) = .{};
- for (seed_words) |w| {
- try initial_words.append(self.allocator, w);
- }
- try beams.append(self.allocator, .{ .words = initial_words, .score = 0.0 });
-
- for (0..steps) |_| {
- var candidates: std.ArrayListUnmanaged(BeamEntry) = .{};
- defer {
- // Free candidates that didn't make it into beams
- for (candidates.items) |*c| {
- c.words.deinit(self.allocator);
- }
- candidates.deinit(self.allocator);
- }
-
- for (beams.items) |*beam| {
- const len = beam.words.items.len;
- if (len < window_size) {
- // Can't predict β carry forward
- var copy: std.ArrayListUnmanaged([]const u8) = .{};
- for (beam.words.items) |w| {
- try copy.append(self.allocator, w);
- }
- try candidates.append(self.allocator, .{ .words = copy, .score = beam.score });
- continue;
- }
-
- const context = beam.words.items[len - window_size .. len];
- const top_k = try self.predictTopK(context, beam_width);
- defer self.allocator.free(top_k);
-
- if (top_k.len == 0) {
- // Dead end β carry forward
- var copy: std.ArrayListUnmanaged([]const u8) = .{};
- for (beam.words.items) |w| {
- try copy.append(self.allocator, w);
- }
- try candidates.append(self.allocator, .{ .words = copy, .score = beam.score });
- continue;
- }
-
- for (top_k) |pred| {
- var new_words: std.ArrayListUnmanaged([]const u8) = .{};
- for (beam.words.items) |w| {
- try new_words.append(self.allocator, w);
- }
- try new_words.append(self.allocator, pred.word);
- try candidates.append(self.allocator, .{
- .words = new_words,
- .score = beam.score + pred.score,
- });
- }
- }
-
- // Sort candidates descending by score, keep top beam_width
- const citems = candidates.items;
- var si: usize = 1;
- while (si < citems.len) : (si += 1) {
- const key_item = citems[si];
- var j: usize = si;
- while (j > 0 and citems[j - 1].score < key_item.score) {
- citems[j] = citems[j - 1];
- j -= 1;
- }
- citems[j] = key_item;
- }
-
- // Replace beams with top candidates
- for (beams.items) |*b| {
- b.words.deinit(self.allocator);
- }
- beams.clearRetainingCapacity();
-
- const keep = @min(beam_width, candidates.items.len);
- for (0..keep) |i| {
- try beams.append(self.allocator, candidates.items[i]);
- }
- // Null out moved entries so defer doesn't double-free
- for (0..keep) |i| {
- candidates.items[i].words = .{};
- }
- }
-
- // Return best beam's words as owned slice
- if (beams.items.len == 0) return try self.allocator.alloc([]const u8, 0);
-
- // Find best beam
- var best_idx: usize = 0;
- var best_score: f64 = beams.items[0].score;
- for (1..beams.items.len) |i| {
- if (beams.items[i].score > best_score) {
- best_score = beams.items[i].score;
- best_idx = i;
- }
- }
-
- const result = try beams.items[best_idx].words.toOwnedSlice(self.allocator);
- beams.items[best_idx].words = .{}; // prevent double-free in defer
- return result;
- }
-
- pub fn getVocabularySize(self: *Self) usize {
- return self.vocabulary.count();
- }
-
- pub fn getContextCount(self: *Self) usize {
- return self.contexts.items.len;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC SEQUENCE PREDICTOR TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCSequencePredictor basic next-word prediction" {
- const allocator = std.testing.allocator;
- var pred = HDCSequencePredictor.init(allocator, 6000, 42);
- defer pred.deinit();
-
- // Train on simple pattern: "the cat sat on the mat"
- try pred.train("the cat sat on the mat");
-
- // With window=3: ("the","cat")β"sat", ("cat","sat")β"on", ("sat","on")β"the", ("on","the")β"mat"
- try std.testing.expectEqual(@as(usize, 4), pred.getContextCount());
-
- // Predict: "the cat" β should predict "sat"
- const ctx1 = [_][]const u8{ "the", "cat" };
- const p1 = try pred.predictNext(&ctx1);
- try std.testing.expect(p1 != null);
- try std.testing.expectEqualStrings("sat", p1.?.word);
-}
-
-test "HDCSequencePredictor vocabulary caching" {
- const allocator = std.testing.allocator;
- var pred = HDCSequencePredictor.init(allocator, 4000, 42);
- defer pred.deinit();
-
- try pred.train("the cat sat on the mat");
-
- // "the" appears twice but vocabulary should have 5 unique words
- try std.testing.expectEqual(@as(usize, 5), pred.getVocabularySize()); // the, cat, sat, on, mat
-}
-
-test "HDCSequencePredictor topK predictions" {
- const allocator = std.testing.allocator;
- var pred = HDCSequencePredictor.init(allocator, 6000, 42);
- defer pred.deinit();
-
- // Train multiple sentences with shared patterns
- try pred.train("i like cats and dogs");
- try pred.train("i like music and art");
- try pred.train("i like food and drink");
-
- // "i like" should have multiple continuations
- const ctx = [_][]const u8{ "i", "like" };
- const top = try pred.predictTopK(&ctx, 5);
- defer allocator.free(top);
-
- try std.testing.expect(top.len >= 2); // at least cats, music, food
- // All predictions should have positive scores
- for (top) |entry| {
- try std.testing.expect(entry.score > -1.0);
- }
-}
-
-test "HDCSequencePredictor greedy generation" {
- const allocator = std.testing.allocator;
- var pred = HDCSequencePredictor.init(allocator, 6000, 42);
- defer pred.deinit();
-
- // Train on a repeating pattern
- try pred.train("one two three one two three one two three");
-
- // Generate from "one two" β should continue with "three one two three ..."
- const seed = [_][]const u8{ "one", "two" };
- const generated = try pred.generate(&seed, 4);
- defer allocator.free(generated);
-
- try std.testing.expect(generated.len >= 3); // at least seed + 1 predicted
- // First prediction after "one two" should be "three"
- if (generated.len > 2) {
- try std.testing.expectEqualStrings("three", generated[2]);
- }
-}
-
-test "HDCSequencePredictor beam search generation" {
- const allocator = std.testing.allocator;
- var pred = HDCSequencePredictor.init(allocator, 6000, 42);
- defer pred.deinit();
-
- try pred.train("the quick brown fox jumps over the lazy dog");
- try pred.train("the quick red car drives down the long road");
-
- const seed = [_][]const u8{ "the", "quick" };
- const beam_result = try pred.generateBeam(&seed, 3, 3);
- defer allocator.free(beam_result);
-
- try std.testing.expect(beam_result.len >= 3); // seed + at least 1 generated
- // Should start with seed words
- try std.testing.expectEqualStrings("the", beam_result[0]);
- try std.testing.expectEqualStrings("quick", beam_result[1]);
-}
-
-test "HDCSequencePredictor empty predictor returns null" {
- const allocator = std.testing.allocator;
- var pred = HDCSequencePredictor.init(allocator, 4000, 42);
- defer pred.deinit();
-
- const ctx = [_][]const u8{ "hello", "world" };
- const p = try pred.predictNext(&ctx);
- try std.testing.expect(p == null);
-}
-
-test "HDCSequencePredictor configurable window size" {
- const allocator = std.testing.allocator;
- // Window=4 means 3-word context predicts 1 word
- var pred = HDCSequencePredictor.initWithConfig(allocator, 6000, 42, 4);
- defer pred.deinit();
-
- try pred.train("a b c d e f g h");
-
- // With window=4: ("a","b","c")β"d", ("b","c","d")β"e", etc.
- try std.testing.expectEqual(@as(usize, 5), pred.getContextCount());
-
- // Predict with 3-word context
- const ctx = [_][]const u8{ "a", "b", "c" };
- const p = try pred.predictNext(&ctx);
- try std.testing.expect(p != null);
- try std.testing.expectEqualStrings("d", p.?.word);
-}
-
-test "HDCSequencePredictor multi-sentence training" {
- const allocator = std.testing.allocator;
- var pred = HDCSequencePredictor.init(allocator, 8000, 42);
- defer pred.deinit();
-
- // Train on multiple sentences about different topics
- const training_data = [_][]const u8{
- "the cat sat on the mat",
- "the dog ran in the park",
- "the bird flew over the tree",
- "the fish swam in the lake",
- "the cat chased the mouse",
- "the dog fetched the ball",
- };
-
- for (training_data) |text| {
- try pred.train(text);
- }
-
- // Test prediction accuracy
- var correct: usize = 0;
- const total: usize = 4;
-
- // "the cat" β most likely "sat" or "chased" (both trained)
- const ctx1 = [_][]const u8{ "the", "cat" };
- const p1 = try pred.predictNext(&ctx1);
- if (p1) |p| {
- if (std.mem.eql(u8, p.word, "sat") or std.mem.eql(u8, p.word, "chased")) correct += 1;
- }
-
- // "the dog" β "ran" or "fetched"
- const ctx2 = [_][]const u8{ "the", "dog" };
- const p2 = try pred.predictNext(&ctx2);
- if (p2) |p| {
- if (std.mem.eql(u8, p.word, "ran") or std.mem.eql(u8, p.word, "fetched")) correct += 1;
- }
-
- // "sat on" β "the"
- const ctx3 = [_][]const u8{ "sat", "on" };
- const p3 = try pred.predictNext(&ctx3);
- if (p3) |p| {
- if (std.mem.eql(u8, p.word, "the")) correct += 1;
- }
-
- // "in the" β "park" or "lake"
- const ctx4 = [_][]const u8{ "in", "the" };
- const p4 = try pred.predictNext(&ctx4);
- if (p4) |p| {
- if (std.mem.eql(u8, p.word, "park") or std.mem.eql(u8, p.word, "lake")) correct += 1;
- }
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC SEQUENCE PREDICTOR (dim=8000, window=3)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Training: {d} sentences | Contexts: {d} | Vocab: {d}\n", .{
- training_data.len,
- pred.getContextCount(),
- pred.getVocabularySize(),
- });
- std.debug.print(" Next-word accuracy: {d}/{d} ({d:.0}%)\n", .{
- correct,
- total,
- @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total)) * 100.0,
- });
-
- // Print predictions
- if (p1) |p| std.debug.print(" \"the cat\" β \"{s}\" (score={d:.4})\n", .{ p.word, p.score });
- if (p2) |p| std.debug.print(" \"the dog\" β \"{s}\" (score={d:.4})\n", .{ p.word, p.score });
- if (p3) |p| std.debug.print(" \"sat on\" β \"{s}\" (score={d:.4})\n", .{ p.word, p.score });
- if (p4) |p| std.debug.print(" \"in the\" β \"{s}\" (score={d:.4})\n", .{ p.word, p.score });
-
- // Generate continuation
- const seed = [_][]const u8{ "the", "cat" };
- const gen = try pred.generate(&seed, 5);
- defer allocator.free(gen);
-
- std.debug.print(" Generate \"the cat\" +5: ", .{});
- for (gen) |w| {
- std.debug.print("{s} ", .{w});
- }
- std.debug.print("\n", .{});
-
- // Beam search
- const beam = try pred.generateBeam(&seed, 5, 3);
- defer allocator.free(beam);
-
- std.debug.print(" Beam(3) \"the cat\" +5: ", .{});
- for (beam) |w| {
- std.debug.print("{s} ", .{w});
- }
- std.debug.print("\n", .{});
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // At least 50% accuracy expected
- try std.testing.expect(correct >= 2);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC MULTIMODAL CLASSIFIER β Text + Numeric + Categorical Features
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Thermometer Encoding (Numeric):
-// idx = floor((v - min) / (max - min) * L)
-// therm_hv = bundle(level[0], level[1], ..., level[idx])
-// Close values β high cosine similarity (share most levels)
-//
-// Feature Encoding:
-// feature_hv = bind(role_hv, value_hv)
-// role_hv = deterministic hash of feature name
-// value_hv = thermometer(numeric) | hash(categorical) | fixed(boolean)
-//
-// Multimodal Fusion:
-// combined_hv = bundle(text_hv, feature_1_hv, feature_2_hv, ...)
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCMultimodalClassifier = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- text_encoder: HDCTextEncoder,
- classes: std.StringHashMapUnmanaged(ClassPrototype),
- total_samples: u32,
- schemas: std.StringHashMapUnmanaged(FeatureSchema),
- default_levels: usize,
-
- const Self = @This();
-
- pub const FeatureValue = union(enum) {
- numeric: f64,
- categorical: []const u8,
- boolean: bool,
- };
-
- pub const Feature = struct {
- name: []const u8,
- value: FeatureValue,
- };
-
- pub const FeatureSchema = struct {
- min_val: f64,
- max_val: f64,
- num_levels: usize,
- };
-
- pub const ClassPrototype = struct {
- prototype_hv: *HybridBigInt,
- sample_count: u32,
- };
-
- pub const ClassScore = struct {
- label: []const u8,
- similarity: f64,
- };
-
- pub const MultimodalPrediction = struct {
- label: []const u8,
- confidence: f64,
- top_k: [8]ClassScore,
- top_k_len: usize,
- };
-
- pub const MultimodalStats = struct {
- num_classes: usize,
- total_samples: u32,
- dimension: usize,
- num_schemas: usize,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .text_encoder = undefined,
- .classes = .{},
- .total_samples = 0,
- .schemas = .{},
- .default_levels = 32,
- };
- self.text_encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .word_pos);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.text_encoder.item_memory = &self.item_memory;
- self.text_encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- // Free class prototypes
- var cit = self.classes.iterator();
- while (cit.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.prototype_hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.classes.deinit(self.allocator);
-
- // Free schema keys
- var sit = self.schemas.iterator();
- while (sit.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.schemas.deinit(self.allocator);
-
- self.text_encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Register a numeric feature schema (range + levels)
- pub fn addSchema(self: *Self, name: []const u8, min_val: f64, max_val: f64, num_levels: usize) !void {
- const owned_name = try self.allocator.dupe(u8, name);
- try self.schemas.put(self.allocator, owned_name, .{
- .min_val = min_val,
- .max_val = max_val,
- .num_levels = num_levels,
- });
- }
-
- /// Hash a feature name to a unique symbol for role vector
- fn hashName(name: []const u8) u32 {
- var h: u32 = 0x20000;
- for (name) |c| {
- h = h *% 31 +% @as(u32, c);
- }
- return h;
- }
-
- /// Get role HV for a feature name (deterministic from name hash)
- fn getRoleVector(self: *Self, name: []const u8) !*HybridBigInt {
- return self.item_memory.getVector(hashName(name));
- }
-
- /// Encode numeric value via thermometer coding
- /// therm_hv = bundle(level[0], level[1], ..., level[idx])
- fn encodeNumeric(self: *Self, value: f64, schema: FeatureSchema) !HybridBigInt {
- const range = schema.max_val - schema.min_val;
- const levels = schema.num_levels;
-
- if (range <= 0 or levels == 0) {
- const lv = try self.item_memory.getVector(0x10000);
- return lv.*;
- }
-
- const normalized = @max(0.0, @min(1.0, (value - schema.min_val) / range));
- const level_f = normalized * @as(f64, @floatFromInt(levels - 1));
- const level_idx: usize = @intFromFloat(@round(level_f));
-
- // Thermometer: bundle levels 0..level_idx
- const lv0 = try self.item_memory.getVector(0x10000 + 0);
- var result = lv0.*;
-
- for (1..level_idx + 1) |i| {
- const lvi = try self.item_memory.getVector(0x10000 + @as(u32, @intCast(i)));
- result = vsa.bundle2(&result, lvi);
- }
-
- return result;
- }
-
- /// Encode categorical value (hash to deterministic HV)
- fn encodeCategorical(self: *Self, value: []const u8) !HybridBigInt {
- var h: u32 = 0x30000;
- for (value) |c| {
- h = h *% 37 +% @as(u32, c);
- }
- const vec = try self.item_memory.getVector(h);
- return vec.*;
- }
-
- /// Encode boolean value
- fn encodeBoolean(self: *Self, value: bool) !HybridBigInt {
- const symbol: u32 = if (value) 0x40001 else 0x40000;
- const vec = try self.item_memory.getVector(symbol);
- return vec.*;
- }
-
- /// Encode a single feature: bind(role_hv, value_hv)
- pub fn encodeFeature(self: *Self, feature: Feature) !HybridBigInt {
- // IMPORTANT: encode value FIRST, because encodeNumeric adds level vectors
- // to item_memory cache, which may resize and invalidate any pointer from
- // getRoleVector. Encode value before getting role pointer.
- var value_hv = switch (feature.value) {
- .numeric => |v| blk: {
- if (self.schemas.get(feature.name)) |schema| {
- break :blk try self.encodeNumeric(v, schema);
- } else {
- // Default schema: [0, 1] with default_levels
- break :blk try self.encodeNumeric(v, .{
- .min_val = 0.0,
- .max_val = 1.0,
- .num_levels = self.default_levels,
- });
- }
- },
- .categorical => |v| try self.encodeCategorical(v),
- .boolean => |v| try self.encodeBoolean(v),
- };
-
- // Get role vector AFTER value encoding to avoid pointer invalidation
- const role_hv = try self.getRoleVector(feature.name);
- return vsa.bind(role_hv, &value_hv);
- }
-
- /// Encode a multimodal sample: bundle(text_hv, feature_hvs...)
- pub fn encodeSample(self: *Self, text: ?[]const u8, features: []const Feature) !HybridBigInt {
- var result: ?HybridBigInt = null;
-
- // Encode text if present
- if (text) |t| {
- if (t.len > 0) {
- const text_hv = try self.text_encoder.encodeText(t);
- result = text_hv;
- }
- }
-
- // Encode and bundle each feature
- for (features) |feature| {
- var feat_hv = try self.encodeFeature(feature);
- if (result) |*r| {
- r.* = vsa.bundle2(r, &feat_hv);
- } else {
- result = feat_hv;
- }
- }
-
- if (result) |r| return r;
-
- // No text and no features β return zero vector
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- /// Train: add a multimodal sample to a class
- pub fn train(self: *Self, label: []const u8, text: ?[]const u8, features: []const Feature) !void {
- self.fixSelfRef();
- var sample_hv = try self.encodeSample(text, features);
-
- if (self.classes.getPtr(label)) |proto| {
- proto.prototype_hv.* = vsa.bundle2(proto.prototype_hv, &sample_hv);
- proto.sample_count += 1;
- } else {
- const proto_hv = try self.allocator.create(HybridBigInt);
- proto_hv.* = sample_hv;
- const owned_label = try self.allocator.dupe(u8, label);
- try self.classes.put(self.allocator, owned_label, .{
- .prototype_hv = proto_hv,
- .sample_count = 1,
- });
- }
- self.total_samples += 1;
- }
-
- /// Predict class for a multimodal sample
- pub fn predict(self: *Self, text: ?[]const u8, features: []const Feature) !?MultimodalPrediction {
- self.fixSelfRef();
- if (self.classes.count() == 0) return null;
-
- var sample_hv = try self.encodeSample(text, features);
-
- var best_label: []const u8 = "";
- var best_sim: f64 = -2.0;
- var top_k: [8]ClassScore = undefined;
- var top_k_len: usize = 0;
-
- var it = self.classes.iterator();
- while (it.next()) |entry| {
- var proto_hv = entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&sample_hv, &proto_hv);
-
- // Insert into top-k sorted descending
- if (top_k_len < 8) {
- top_k[top_k_len] = .{ .label = entry.key_ptr.*, .similarity = sim };
- top_k_len += 1;
- var j: usize = top_k_len - 1;
- while (j > 0 and top_k[j - 1].similarity < top_k[j].similarity) {
- const tmp = top_k[j];
- top_k[j] = top_k[j - 1];
- top_k[j - 1] = tmp;
- j -= 1;
- }
- } else if (sim > top_k[7].similarity) {
- top_k[7] = .{ .label = entry.key_ptr.*, .similarity = sim };
- var j: usize = 7;
- while (j > 0 and top_k[j - 1].similarity < top_k[j].similarity) {
- const tmp = top_k[j];
- top_k[j] = top_k[j - 1];
- top_k[j - 1] = tmp;
- j -= 1;
- }
- }
-
- if (sim > best_sim) {
- best_sim = sim;
- best_label = entry.key_ptr.*;
- }
- }
-
- return MultimodalPrediction{
- .label = best_label,
- .confidence = best_sim,
- .top_k = top_k,
- .top_k_len = top_k_len,
- };
- }
-
- /// Remove a class
- pub fn removeClass(self: *Self, label: []const u8) bool {
- if (self.classes.fetchRemove(label)) |kv| {
- self.total_samples -= kv.value.sample_count;
- self.allocator.destroy(kv.value.prototype_hv);
- self.allocator.free(kv.key);
- return true;
- }
- return false;
- }
-
- /// Get classifier statistics
- pub fn stats(self: *Self) MultimodalStats {
- return .{
- .num_classes = self.classes.count(),
- .total_samples = self.total_samples,
- .dimension = self.dimension,
- .num_schemas = self.schemas.count(),
- };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC MULTIMODAL CLASSIFIER TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCMultimodal thermometer encoding preserves ordering" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 6000, 42);
- defer clf.deinit();
- clf.fixSelfRef();
-
- const schema = HDCMultimodalClassifier.FeatureSchema{
- .min_val = 0.0,
- .max_val = 100.0,
- .num_levels = 32,
- };
-
- // Encode three values: 10, 50, 90
- var hv_10 = try clf.encodeNumeric(10.0, schema);
- var hv_50 = try clf.encodeNumeric(50.0, schema);
- var hv_90 = try clf.encodeNumeric(90.0, schema);
-
- // 10 and 50 should be more similar than 10 and 90
- const sim_10_50 = vsa.cosineSimilarity(&hv_10, &hv_50);
- const sim_10_90 = vsa.cosineSimilarity(&hv_10, &hv_90);
- const sim_50_90 = vsa.cosineSimilarity(&hv_50, &hv_90);
-
- // Thermometer property: closer values share more levels
- try std.testing.expect(sim_10_50 > sim_10_90);
- // 50 and 90 also closer than 10 and 90
- try std.testing.expect(sim_50_90 > sim_10_90);
-}
-
-test "HDCMultimodal feature encoding bind with role" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 6000, 42);
- defer clf.deinit();
- clf.fixSelfRef();
-
- try clf.addSchema("temperature", 0.0, 100.0, 32);
-
- // Same value, different feature names β different HVs (role binding)
- var hv_temp = try clf.encodeFeature(.{
- .name = "temperature",
- .value = .{ .numeric = 50.0 },
- });
- var hv_humidity = try clf.encodeFeature(.{
- .name = "humidity",
- .value = .{ .numeric = 50.0 },
- });
-
- const sim = vsa.cosineSimilarity(&hv_temp, &hv_humidity);
- // Different role bindings β near-orthogonal
- try std.testing.expect(sim < 0.3);
-}
-
-test "HDCMultimodal categorical encoding" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 6000, 42);
- defer clf.deinit();
- clf.fixSelfRef();
-
- // Same category β same HV
- var hv_a1 = try clf.encodeCategorical("GET");
- var hv_a2 = try clf.encodeCategorical("GET");
- const sim_same = vsa.cosineSimilarity(&hv_a1, &hv_a2);
- try std.testing.expect(sim_same > 0.99);
-
- // Different category β near-orthogonal
- var hv_b = try clf.encodeCategorical("POST");
- const sim_diff = vsa.cosineSimilarity(&hv_a1, &hv_b);
- try std.testing.expect(sim_diff < 0.3);
-}
-
-test "HDCMultimodal text-only classification (backward compat)" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 6000, 42);
- defer clf.deinit();
-
- // Train with text only (no features)
- const no_features = [_]HDCMultimodalClassifier.Feature{};
- try clf.train("greeting", "hello world", &no_features);
- try clf.train("farewell", "goodbye world", &no_features);
-
- const p1 = try clf.predict("hello there", &no_features);
- try std.testing.expect(p1 != null);
- try std.testing.expectEqualStrings("greeting", p1.?.label);
-
- const p2 = try clf.predict("goodbye friend", &no_features);
- try std.testing.expect(p2 != null);
- try std.testing.expectEqualStrings("farewell", p2.?.label);
-}
-
-test "HDCMultimodal features-only classification" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 6000, 42);
- defer clf.deinit();
-
- try clf.addSchema("length", 0.0, 1000.0, 32);
- try clf.addSchema("score", 0.0, 1.0, 16);
-
- // Train: short + low_score = spam, long + high_score = legit
- const spam_features = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "length", .value = .{ .numeric = 50.0 } },
- .{ .name = "score", .value = .{ .numeric = 0.1 } },
- };
- const legit_features = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "length", .value = .{ .numeric = 500.0 } },
- .{ .name = "score", .value = .{ .numeric = 0.9 } },
- };
-
- try clf.train("spam", null, &spam_features);
- try clf.train("legit", null, &legit_features);
-
- // Test: short + low_score β spam
- const test_spam = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "length", .value = .{ .numeric = 60.0 } },
- .{ .name = "score", .value = .{ .numeric = 0.15 } },
- };
- const p1 = try clf.predict(null, &test_spam);
- try std.testing.expect(p1 != null);
- try std.testing.expectEqualStrings("spam", p1.?.label);
-
- // Test: long + high_score β legit
- const test_legit = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "length", .value = .{ .numeric = 450.0 } },
- .{ .name = "score", .value = .{ .numeric = 0.85 } },
- };
- const p2 = try clf.predict(null, &test_legit);
- try std.testing.expect(p2 != null);
- try std.testing.expectEqualStrings("legit", p2.?.label);
-}
-
-test "HDCMultimodal text + features combined" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 8000, 42);
- defer clf.deinit();
-
- try clf.addSchema("word_count", 0.0, 100.0, 16);
-
- // Train: short greeting vs long farewell
- const greet_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = 3.0 } },
- .{ .name = "sentiment", .value = .{ .categorical = "positive" } },
- };
- const farewell_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = 5.0 } },
- .{ .name = "sentiment", .value = .{ .categorical = "neutral" } },
- };
-
- try clf.train("greeting", "hello how are you", &greet_feats);
- try clf.train("farewell", "goodbye see you later friend", &farewell_feats);
-
- // Predict with matching text + features
- const test_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = 2.0 } },
- .{ .name = "sentiment", .value = .{ .categorical = "positive" } },
- };
- const p = try clf.predict("hi there", &test_feats);
- try std.testing.expect(p != null);
- try std.testing.expectEqualStrings("greeting", p.?.label);
-}
-
-test "HDCMultimodal boolean features" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 6000, 42);
- defer clf.deinit();
-
- // Spam has attachment=false, urgent=true
- const spam_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "has_attachment", .value = .{ .boolean = false } },
- .{ .name = "is_urgent", .value = .{ .boolean = true } },
- };
- // Legit has attachment=true, urgent=false
- const legit_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "has_attachment", .value = .{ .boolean = true } },
- .{ .name = "is_urgent", .value = .{ .boolean = false } },
- };
-
- try clf.train("spam", "buy now limited offer", &spam_feats);
- try clf.train("legit", "quarterly report attached", &legit_feats);
-
- // Test spam-like
- const test_spam = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "has_attachment", .value = .{ .boolean = false } },
- .{ .name = "is_urgent", .value = .{ .boolean = true } },
- };
- const p = try clf.predict("special discount today", &test_spam);
- try std.testing.expect(p != null);
- try std.testing.expectEqualStrings("spam", p.?.label);
-}
-
-test "HDCMultimodal email spam demo" {
- const allocator = std.testing.allocator;
- var clf = HDCMultimodalClassifier.init(allocator, 8000, 42);
- defer clf.deinit();
-
- try clf.addSchema("word_count", 0.0, 200.0, 32);
- try clf.addSchema("sender_reputation", 0.0, 1.0, 16);
-
- // Train spam examples
- const spam_data = [_]struct { text: []const u8, wc: f64, rep: f64, attach: bool }{
- .{ .text = "buy cheap viagra now", .wc = 4, .rep = 0.1, .attach = false },
- .{ .text = "win free iphone click here", .wc = 5, .rep = 0.05, .attach = false },
- .{ .text = "limited offer act now urgent", .wc = 5, .rep = 0.15, .attach = false },
- .{ .text = "congratulations you won lottery", .wc = 4, .rep = 0.08, .attach = false },
- };
-
- for (spam_data) |s| {
- const feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = s.wc } },
- .{ .name = "sender_reputation", .value = .{ .numeric = s.rep } },
- .{ .name = "has_attachment", .value = .{ .boolean = s.attach } },
- };
- try clf.train("spam", s.text, &feats);
- }
-
- // Train legit examples
- const legit_data = [_]struct { text: []const u8, wc: f64, rep: f64, attach: bool }{
- .{ .text = "meeting tomorrow at three pm", .wc = 5, .rep = 0.95, .attach = true },
- .{ .text = "quarterly report ready for review", .wc = 5, .rep = 0.9, .attach = true },
- .{ .text = "project update and next steps", .wc = 5, .rep = 0.85, .attach = true },
- .{ .text = "team lunch scheduled for friday", .wc = 5, .rep = 0.92, .attach = false },
- };
-
- for (legit_data) |l| {
- const feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = l.wc } },
- .{ .name = "sender_reputation", .value = .{ .numeric = l.rep } },
- .{ .name = "has_attachment", .value = .{ .boolean = l.attach } },
- };
- try clf.train("legit", l.text, &feats);
- }
-
- // Test predictions
- var correct: usize = 0;
- const total: usize = 4;
-
- // Test 1: spam-like
- const t1_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = 4.0 } },
- .{ .name = "sender_reputation", .value = .{ .numeric = 0.12 } },
- .{ .name = "has_attachment", .value = .{ .boolean = false } },
- };
- const p1 = try clf.predict("special deal discount offer", &t1_feats);
- if (p1) |p| {
- if (std.mem.eql(u8, p.label, "spam")) correct += 1;
- }
-
- // Test 2: legit-like
- const t2_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = 6.0 } },
- .{ .name = "sender_reputation", .value = .{ .numeric = 0.88 } },
- .{ .name = "has_attachment", .value = .{ .boolean = true } },
- };
- const p2 = try clf.predict("please review the attached document", &t2_feats);
- if (p2) |p| {
- if (std.mem.eql(u8, p.label, "legit")) correct += 1;
- }
-
- // Test 3: ambiguous text but spam features
- const t3_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = 3.0 } },
- .{ .name = "sender_reputation", .value = .{ .numeric = 0.05 } },
- .{ .name = "has_attachment", .value = .{ .boolean = false } },
- };
- const p3 = try clf.predict("check this out", &t3_feats);
- if (p3) |p| {
- if (std.mem.eql(u8, p.label, "spam")) correct += 1;
- }
-
- // Test 4: ambiguous text but legit features
- const t4_feats = [_]HDCMultimodalClassifier.Feature{
- .{ .name = "word_count", .value = .{ .numeric = 8.0 } },
- .{ .name = "sender_reputation", .value = .{ .numeric = 0.95 } },
- .{ .name = "has_attachment", .value = .{ .boolean = true } },
- };
- const p4 = try clf.predict("check this out", &t4_feats);
- if (p4) |p| {
- if (std.mem.eql(u8, p.label, "legit")) correct += 1;
- }
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC MULTIMODAL CLASSIFIER (dim=8000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const s = clf.stats();
- std.debug.print(" Classes: {d} | Samples: {d} | Schemas: {d}\n", .{ s.num_classes, s.total_samples, s.num_schemas });
- std.debug.print(" Email spam accuracy: {d}/{d} ({d:.0}%)\n", .{
- correct,
- total,
- @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total)) * 100.0,
- });
-
- if (p1) |p| std.debug.print(" Spam text+feats: \"{s}\" (conf={d:.4})\n", .{ p.label, p.confidence });
- if (p2) |p| std.debug.print(" Legit text+feats: \"{s}\" (conf={d:.4})\n", .{ p.label, p.confidence });
- if (p3) |p| std.debug.print(" Ambig+spam feats: \"{s}\" (conf={d:.4})\n", .{ p.label, p.confidence });
- if (p4) |p| std.debug.print(" Ambig+legit feats: \"{s}\" (conf={d:.4})\n", .{ p.label, p.confidence });
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // At least 75% accuracy
- try std.testing.expect(correct >= 3);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC ENSEMBLE β Unified Cognitive Pipeline
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Pipeline: Input β [Anomaly Gate] β [Classifier] β [Cluster Context] β Decision
-//
-// Subsystems (same seed β same encoding):
-// Classifier: supervised, class prototypes
-// AnomalyDetector: one-class novelty detection
-// Clustering: unsupervised structure discovery
-//
-// Decision: anomaly_rejected > classified > uncertain > uninitialized
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCEnsemble = struct {
- allocator: std.mem.Allocator,
- classifier: HDCClassifier,
- anomaly_detector: HDCAnomalyDetector,
- clustering: HDCClustering,
- dimension: usize,
- confidence_threshold: f64,
- anomaly_gating: bool,
- cluster_result: ?HDCClustering.ClusterResult,
- cluster_vectors: ?[]HybridBigInt,
-
- const Self = @This();
-
- pub const EnsembleDecision = enum {
- classified,
- anomaly_rejected,
- uncertain,
- uninitialized,
- };
-
- pub const EnsembleResult = struct {
- label: []const u8,
- confidence: f64,
- is_anomaly: bool,
- anomaly_score: f64,
- cluster_id: ?usize,
- cluster_similarity: f64,
- decision: EnsembleDecision,
- };
-
- pub const EnsembleStats = struct {
- num_classes: usize,
- total_class_samples: u32,
- num_anomaly_profiles: usize,
- total_normal_samples: u32,
- num_clusters: usize,
- dimension: usize,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithConfig(allocator, dimension, seed, 0.0, true);
- }
-
- pub fn initWithConfig(
- allocator: std.mem.Allocator,
- dimension: usize,
- seed: u64,
- confidence_threshold: f64,
- anomaly_gating: bool,
- ) Self {
- return Self{
- .allocator = allocator,
- .classifier = HDCClassifier.initWithMode(allocator, dimension, seed, .hybrid),
- .anomaly_detector = HDCAnomalyDetector.init(allocator, dimension, seed),
- .clustering = HDCClustering.init(allocator, dimension, seed),
- .dimension = dimension,
- .confidence_threshold = confidence_threshold,
- .anomaly_gating = anomaly_gating,
- .cluster_result = null,
- .cluster_vectors = null,
- };
- }
-
- pub fn deinit(self: *Self) void {
- if (self.cluster_result) |cr| {
- self.clustering.freeResult(cr);
- }
- if (self.cluster_vectors) |vecs| {
- self.allocator.free(vecs);
- }
- self.classifier.deinit();
- self.anomaly_detector.deinit();
- self.clustering.deinit();
- }
-
- /// Train the supervised classifier
- pub fn trainClassifier(self: *Self, label: []const u8, text: []const u8) !void {
- try self.classifier.train(label, text);
- }
-
- /// Train the anomaly detector (normal samples)
- pub fn trainNormal(self: *Self, text: []const u8) !void {
- try self.anomaly_detector.trainNormal("default", text);
- }
-
- /// Train anomaly detector with named profile
- pub fn trainNormalProfile(self: *Self, profile: []const u8, text: []const u8) !void {
- try self.anomaly_detector.trainNormal(profile, text);
- }
-
- /// Calibrate anomaly threshold from normal samples
- pub fn calibrate(self: *Self, normal_samples: []const []const u8) !void {
- try self.anomaly_detector.calibrate("default", normal_samples);
- }
-
- /// Calibrate named profile
- pub fn calibrateProfile(self: *Self, profile: []const u8, normal_samples: []const []const u8) !void {
- try self.anomaly_detector.calibrate(profile, normal_samples);
- }
-
- /// Fit k-means clustering on text data
- pub fn fitClusters(self: *Self, texts: []const []const u8, k: usize) !void {
- // Free previous result
- if (self.cluster_result) |cr| {
- self.clustering.freeResult(cr);
- self.cluster_result = null;
- }
- if (self.cluster_vectors) |vecs| {
- self.allocator.free(vecs);
- self.cluster_vectors = null;
- }
-
- // Encode all texts
- const vectors = try self.clustering.encodeAll(texts);
- self.cluster_vectors = vectors;
-
- // Run k-means
- const config = HDCClustering.ClusterConfig{
- .k = k,
- .max_iter = 100,
- .convergence_threshold = 0.001,
- .seed = 42,
- };
- self.cluster_result = try self.clustering.fitVectors(vectors, config);
- }
-
- /// Full ensemble prediction
- pub fn predict(self: *Self, text: []const u8) !EnsembleResult {
- var result = EnsembleResult{
- .label = "",
- .confidence = 0,
- .is_anomaly = false,
- .anomaly_score = 0,
- .cluster_id = null,
- .cluster_similarity = 0,
- .decision = .uninitialized,
- };
-
- const has_classifier = self.classifier.classes.count() > 0;
- const has_anomaly = self.anomaly_detector.profiles.count() > 0;
- const has_clusters = self.cluster_result != null;
-
- if (!has_classifier and !has_anomaly and !has_clusters) {
- return result;
- }
-
- // Step 1: Anomaly detection
- if (has_anomaly) {
- const anomaly_result = try self.anomaly_detector.detect(text);
- if (anomaly_result) |ar| {
- result.is_anomaly = ar.is_anomaly;
- result.anomaly_score = ar.score;
- }
- }
-
- // Step 2: Classification
- if (has_classifier) {
- const class_result = try self.classifier.predict(text);
- if (class_result) |cr| {
- result.label = cr.label;
- result.confidence = cr.confidence;
- }
- }
-
- // Step 3: Cluster assignment
- if (has_clusters) {
- if (self.cluster_result) |cr| {
- const cluster_pred = try self.clustering.predict(text, cr.clusters);
- result.cluster_id = cluster_pred.cluster;
- result.cluster_similarity = cluster_pred.similarity;
- }
- }
-
- // Step 4: Decision
- if (self.anomaly_gating and has_anomaly and result.is_anomaly) {
- result.decision = .anomaly_rejected;
- } else if (has_classifier and result.confidence >= self.confidence_threshold) {
- result.decision = .classified;
- } else if (has_classifier) {
- result.decision = .uncertain;
- } else {
- result.decision = .uninitialized;
- }
-
- return result;
- }
-
- /// Get ensemble-wide statistics
- pub fn stats(self: *Self) EnsembleStats {
- const cls = self.classifier.stats();
- const det = self.anomaly_detector.stats();
- const num_clusters: usize = if (self.cluster_result) |cr| cr.clusters.len else 0;
-
- return .{
- .num_classes = cls.num_classes,
- .total_class_samples = cls.total_samples,
- .num_anomaly_profiles = det.num_profiles,
- .total_normal_samples = det.total_samples,
- .num_clusters = num_clusters,
- .dimension = self.dimension,
- };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC ENSEMBLE TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCEnsemble classifier-only mode" {
- const allocator = std.testing.allocator;
- var ens = HDCEnsemble.init(allocator, 6000, 42);
- defer ens.deinit();
-
- try ens.trainClassifier("greeting", "hello world how are you");
- try ens.trainClassifier("farewell", "goodbye see you later");
-
- const r = try ens.predict("hello there friend");
- try std.testing.expectEqualStrings("greeting", r.label);
- try std.testing.expect(r.decision == .classified);
- try std.testing.expect(!r.is_anomaly);
- try std.testing.expect(r.cluster_id == null);
-}
-
-test "HDCEnsemble anomaly gating rejects out-of-distribution" {
- const allocator = std.testing.allocator;
- var ens = HDCEnsemble.init(allocator, 6000, 42);
- defer ens.deinit();
-
- // Train classifier
- try ens.trainClassifier("english", "the quick brown fox");
- try ens.trainClassifier("spanish", "el rapido zorro marron");
-
- // Train anomaly detector on English-like text
- try ens.trainNormal("the quick brown fox jumps");
- try ens.trainNormal("hello world from london");
- try ens.trainNormal("the weather is quite nice");
-
- const cal = [_][]const u8{
- "the quick brown fox jumps",
- "hello world from london",
- "the weather is quite nice",
- };
- try ens.calibrate(&cal);
-
- // Normal English text β classified
- const r_normal = try ens.predict("the big brown dog");
- try std.testing.expect(r_normal.decision == .classified or r_normal.decision == .uncertain);
- try std.testing.expect(!r_normal.is_anomaly);
-
- // Gibberish β anomaly rejected
- const r_anomaly = try ens.predict("xyzzy qqq zzz www ppp");
- try std.testing.expect(r_anomaly.anomaly_score > r_normal.anomaly_score);
-}
-
-test "HDCEnsemble with clustering" {
- const allocator = std.testing.allocator;
- var ens = HDCEnsemble.init(allocator, 6000, 42);
- defer ens.deinit();
-
- try ens.trainClassifier("animal", "cat dog pet");
- try ens.trainClassifier("vehicle", "car truck bus");
-
- // Fit clusters
- const cluster_texts = [_][]const u8{
- "cat dog pet",
- "cat kitten puppy",
- "car truck bus",
- "car vehicle motor",
- };
- try ens.fitClusters(&cluster_texts, 2);
-
- const r = try ens.predict("dog puppy kitten");
- try std.testing.expect(r.cluster_id != null);
- try std.testing.expect(r.decision == .classified);
-}
-
-test "HDCEnsemble anomaly gating disabled" {
- const allocator = std.testing.allocator;
- var ens = HDCEnsemble.initWithConfig(allocator, 6000, 42, 0.3, false);
- defer ens.deinit();
-
- try ens.trainClassifier("greeting", "hello world");
- try ens.trainNormal("hello world");
-
- const cal = [_][]const u8{"hello world"};
- try ens.calibrate(&cal);
-
- // Even if anomalous, should still classify (gating disabled)
- const r = try ens.predict("zzz qqq www");
- try std.testing.expect(r.decision != .anomaly_rejected);
-}
-
-test "HDCEnsemble confidence threshold" {
- const allocator = std.testing.allocator;
- // Very high threshold β most predictions become uncertain
- var ens = HDCEnsemble.initWithConfig(allocator, 6000, 42, 0.99, true);
- defer ens.deinit();
-
- try ens.trainClassifier("greeting", "hello");
- try ens.trainClassifier("farewell", "goodbye");
-
- const r = try ens.predict("something completely different");
- // With very different text and high threshold, likely uncertain
- try std.testing.expect(r.decision == .uncertain or r.decision == .classified);
-}
-
-test "HDCEnsemble empty returns uninitialized" {
- const allocator = std.testing.allocator;
- var ens = HDCEnsemble.init(allocator, 4000, 42);
- defer ens.deinit();
-
- const r = try ens.predict("anything");
- try std.testing.expect(r.decision == .uninitialized);
-}
-
-test "HDCEnsemble stats" {
- const allocator = std.testing.allocator;
- var ens = HDCEnsemble.init(allocator, 6000, 42);
- defer ens.deinit();
-
- try ens.trainClassifier("a", "text a");
- try ens.trainClassifier("b", "text b");
- try ens.trainNormal("normal text");
-
- const s = ens.stats();
- try std.testing.expectEqual(@as(usize, 2), s.num_classes);
- try std.testing.expectEqual(@as(u32, 2), s.total_class_samples);
- try std.testing.expectEqual(@as(usize, 1), s.num_anomaly_profiles);
- try std.testing.expectEqual(@as(usize, 0), s.num_clusters);
-}
-
-test "HDCEnsemble full cognitive pipeline demo" {
- const allocator = std.testing.allocator;
- var ens = HDCEnsemble.init(allocator, 8000, 42);
- defer ens.deinit();
-
- // === PHASE 1: Train classifier (supervised) ===
- const train_data = [_]struct { label: []const u8, text: []const u8 }{
- .{ .label = "tech", .text = "software engineering programming code" },
- .{ .label = "tech", .text = "algorithm data structure binary tree" },
- .{ .label = "tech", .text = "machine learning neural network model" },
- .{ .label = "sport", .text = "football basketball soccer game match" },
- .{ .label = "sport", .text = "tennis player tournament champion win" },
- .{ .label = "sport", .text = "running marathon race track field" },
- .{ .label = "food", .text = "restaurant cooking recipe kitchen chef" },
- .{ .label = "food", .text = "pizza pasta sushi ramen noodles" },
- .{ .label = "food", .text = "organic fresh vegetables fruit salad" },
- };
-
- for (train_data) |td| {
- try ens.trainClassifier(td.label, td.text);
- }
-
- // === PHASE 2: Train anomaly detector (one-class) ===
- for (train_data) |td| {
- try ens.trainNormal(td.text);
- }
- var normal_texts: [9][]const u8 = undefined;
- for (train_data, 0..) |td, i| {
- normal_texts[i] = td.text;
- }
- try ens.calibrate(&normal_texts);
-
- // === PHASE 3: Fit clusters (unsupervised) ===
- try ens.fitClusters(&normal_texts, 3);
-
- // === PHASE 4: Test predictions ===
- var correct: usize = 0;
- const total: usize = 6;
-
- const test_cases = [_]struct { text: []const u8, expected: []const u8 }{
- .{ .text = "software programming code algorithm", .expected = "tech" },
- .{ .text = "football game match tournament", .expected = "sport" },
- .{ .text = "cooking recipe kitchen fresh", .expected = "food" },
- .{ .text = "data structure neural network", .expected = "tech" },
- .{ .text = "marathon race champion win", .expected = "sport" },
- .{ .text = "pasta sushi restaurant chef", .expected = "food" },
- };
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC ENSEMBLE β FULL COGNITIVE PIPELINE (dim=8000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const s = ens.stats();
- std.debug.print(" Classifier: {d} classes, {d} samples\n", .{ s.num_classes, s.total_class_samples });
- std.debug.print(" Anomaly: {d} profiles, {d} normal samples\n", .{ s.num_anomaly_profiles, s.total_normal_samples });
- std.debug.print(" Clusters: {d}\n", .{s.num_clusters});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- for (test_cases) |tc| {
- const r = try ens.predict(tc.text);
-
- const decision_str: []const u8 = switch (r.decision) {
- .classified => "CLASSIFIED",
- .anomaly_rejected => "REJECTED",
- .uncertain => "UNCERTAIN",
- .uninitialized => "UNINIT",
- };
-
- const cluster_str: u8 = if (r.cluster_id) |c| @as(u8, @intCast(c)) + '0' else '-';
-
- std.debug.print(" \"{s}\"\n", .{tc.text});
- std.debug.print(" β {s} label=\"{s}\" conf={d:.4} anom={d:.4} cluster={c}\n", .{
- decision_str,
- r.label,
- r.confidence,
- r.anomaly_score,
- cluster_str,
- });
-
- if (std.mem.eql(u8, r.label, tc.expected)) correct += 1;
- }
-
- // Test anomaly case
- const r_anomaly = try ens.predict("zzzz xxxx yyyy qqqq wwww");
- const anom_decision: []const u8 = switch (r_anomaly.decision) {
- .classified => "CLASSIFIED",
- .anomaly_rejected => "REJECTED",
- .uncertain => "UNCERTAIN",
- .uninitialized => "UNINIT",
- };
- std.debug.print(" \"zzzz xxxx yyyy qqqq wwww\"\n", .{});
- std.debug.print(" β {s} anom_score={d:.4} is_anomaly={}\n", .{
- anom_decision,
- r_anomaly.anomaly_score,
- r_anomaly.is_anomaly,
- });
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Classification accuracy: {d}/{d} ({d:.0}%)\n", .{
- correct,
- total,
- @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total)) * 100.0,
- });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // At least 50% accuracy
- try std.testing.expect(correct >= 3);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC SEMANTIC SEARCH β Document Retrieval via Hyperdimensional Similarity
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Index: document β HDCTextEncoder β document_hv (stored)
-// Query: query_text β HDCTextEncoder β query_hv
-// Search: top-k documents by cosine(query_hv, doc_hv)
-//
-// TF-IDF mode: buildIndex() computes corpus IDF, re-encodes all docs
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCSemanticSearch = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
- documents: std.ArrayListUnmanaged(Document),
- tfidf_built: bool,
-
- const Self = @This();
-
- pub const EncodingMode = HDCTextEncoder.EncodingMode;
-
- pub const Document = struct {
- id: []const u8, // owned
- text: []const u8, // owned
- hv: HybridBigInt,
- metadata: ?[]const u8, // owned, optional
- };
-
- pub const SearchResult = struct {
- id: []const u8,
- text: []const u8,
- similarity: f64,
- metadata: ?[]const u8,
- rank: usize,
- };
-
- pub const IndexStats = struct {
- num_documents: usize,
- vocabulary_size: usize,
- dimension: usize,
- is_tfidf_built: bool,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithMode(allocator, dimension, seed, .word_tfidf);
- }
-
- pub fn initWithMode(allocator: std.mem.Allocator, dimension: usize, seed: u64, mode: EncodingMode) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .documents = .{},
- .tfidf_built = false,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, mode);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- for (self.documents.items) |doc| {
- self.allocator.free(doc.id);
- self.allocator.free(doc.text);
- if (doc.metadata) |m| self.allocator.free(m);
- }
- self.documents.deinit(self.allocator);
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Add a document to the index
- pub fn addDocument(self: *Self, id: []const u8, text: []const u8) !void {
- try self.addDocumentWithMetadata(id, text, null);
- }
-
- /// Add a document with optional metadata
- pub fn addDocumentWithMetadata(self: *Self, id: []const u8, text: []const u8, metadata: ?[]const u8) !void {
- self.fixSelfRef();
-
- // Update TF-IDF stats if in tfidf mode
- if (self.encoder.mode == .word_tfidf) {
- try self.encoder.updateTFIDF(text);
- }
-
- // Encode document
- const hv = try self.encoder.encodeText(text);
-
- // Store
- const owned_id = try self.allocator.dupe(u8, id);
- const owned_text = try self.allocator.dupe(u8, text);
- const owned_meta = if (metadata) |m| try self.allocator.dupe(u8, m) else null;
-
- try self.documents.append(self.allocator, .{
- .id = owned_id,
- .text = owned_text,
- .hv = hv,
- .metadata = owned_meta,
- });
- }
-
- /// Build/rebuild index: re-encode all documents with corpus-wide TF-IDF
- /// Call this after adding all documents for optimal relevance ranking
- pub fn buildIndex(self: *Self) !void {
- self.fixSelfRef();
-
- if (self.encoder.mode == .word_tfidf) {
- // TF-IDF stats already collected during addDocument.
- // Re-encode all documents with full corpus IDF weights.
- for (self.documents.items) |*doc| {
- doc.hv = try self.encoder.encodeText(doc.text);
- }
- }
- self.tfidf_built = true;
- }
-
- /// Search: find top-k documents most similar to query
- pub fn search(self: *Self, query: []const u8, k: usize) ![]SearchResult {
- self.fixSelfRef();
-
- if (self.documents.items.len == 0) {
- return try self.allocator.alloc(SearchResult, 0);
- }
-
- // Encode query
- var query_hv = try self.encoder.encodeText(query);
-
- // Score all documents
- var scored: std.ArrayListUnmanaged(SearchResult) = .{};
- defer scored.deinit(self.allocator);
-
- for (self.documents.items, 0..) |*doc, idx| {
- const sim = vsa.cosineSimilarity(&query_hv, &doc.hv);
- try scored.append(self.allocator, .{
- .id = doc.id,
- .text = doc.text,
- .similarity = sim,
- .metadata = doc.metadata,
- .rank = idx,
- });
- }
-
- // Sort descending by similarity (insertion sort)
- const items = scored.items;
- var i: usize = 1;
- while (i < items.len) : (i += 1) {
- const key_item = items[i];
- var j: usize = i;
- while (j > 0 and items[j - 1].similarity < key_item.similarity) {
- items[j] = items[j - 1];
- j -= 1;
- }
- items[j] = key_item;
- }
-
- // Return top-k with correct ranks
- const result_len = @min(k, items.len);
- const results = try self.allocator.alloc(SearchResult, result_len);
- for (0..result_len) |ri| {
- results[ri] = items[ri];
- results[ri].rank = ri + 1;
- }
- return results;
- }
-
- /// Remove a document by ID
- pub fn remove(self: *Self, id: []const u8) bool {
- for (self.documents.items, 0..) |doc, idx| {
- if (std.mem.eql(u8, doc.id, id)) {
- self.allocator.free(doc.id);
- self.allocator.free(doc.text);
- if (doc.metadata) |m| self.allocator.free(m);
- _ = self.documents.orderedRemove(idx);
- return true;
- }
- }
- return false;
- }
-
- /// Get the number of unique words across all documents
- fn getVocabularySize(self: *Self) usize {
- return self.encoder.tfidf_word_doc_freq.count();
- }
-
- /// Get index statistics
- pub fn stats(self: *Self) IndexStats {
- return .{
- .num_documents = self.documents.items.len,
- .vocabulary_size = self.getVocabularySize(),
- .dimension = self.dimension,
- .is_tfidf_built = self.tfidf_built,
- };
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC SEMANTIC SEARCH TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCSemanticSearch basic document retrieval" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.init(allocator, 6000, 42);
- defer idx.deinit();
-
- try idx.addDocument("doc1", "the quick brown fox jumps over the lazy dog");
- try idx.addDocument("doc2", "machine learning neural network deep learning");
- try idx.addDocument("doc3", "the cat sat on the mat near the dog");
-
- try idx.buildIndex();
-
- // Search for dog-related content
- const results = try idx.search("the brown dog", 3);
- defer allocator.free(results);
-
- try std.testing.expect(results.len == 3);
- // doc1 or doc3 should rank highest (both contain "dog" and "the")
- const top_id = results[0].id;
- try std.testing.expect(
- std.mem.eql(u8, top_id, "doc1") or std.mem.eql(u8, top_id, "doc3"),
- );
-}
-
-test "HDCSemanticSearch empty index returns empty" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.init(allocator, 4000, 42);
- defer idx.deinit();
-
- const results = try idx.search("anything", 5);
- defer allocator.free(results);
- try std.testing.expectEqual(@as(usize, 0), results.len);
-}
-
-test "HDCSemanticSearch remove document" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.init(allocator, 4000, 42);
- defer idx.deinit();
-
- try idx.addDocument("a", "hello world");
- try idx.addDocument("b", "goodbye world");
-
- try std.testing.expectEqual(@as(usize, 2), idx.stats().num_documents);
- try std.testing.expect(idx.remove("a"));
- try std.testing.expectEqual(@as(usize, 1), idx.stats().num_documents);
- try std.testing.expect(!idx.remove("nonexistent"));
-}
-
-test "HDCSemanticSearch metadata preserved" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.init(allocator, 4000, 42);
- defer idx.deinit();
-
- try idx.addDocumentWithMetadata("doc1", "hello world", "category:greeting");
- try idx.buildIndex();
-
- const results = try idx.search("hello", 1);
- defer allocator.free(results);
-
- try std.testing.expect(results.len == 1);
- try std.testing.expect(results[0].metadata != null);
- try std.testing.expectEqualStrings("category:greeting", results[0].metadata.?);
-}
-
-test "HDCSemanticSearch rank ordering" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.init(allocator, 6000, 42);
- defer idx.deinit();
-
- try idx.addDocument("exact", "cat dog pet animal");
- try idx.addDocument("related", "kitten puppy creature beast");
- try idx.addDocument("unrelated", "software programming algorithm code");
-
- try idx.buildIndex();
-
- const results = try idx.search("cat dog pet", 3);
- defer allocator.free(results);
-
- try std.testing.expect(results.len == 3);
- // "exact" should rank first (shares most words)
- try std.testing.expectEqualStrings("exact", results[0].id);
- // Ranks should be 1, 2, 3
- try std.testing.expectEqual(@as(usize, 1), results[0].rank);
- try std.testing.expectEqual(@as(usize, 2), results[1].rank);
- try std.testing.expectEqual(@as(usize, 3), results[2].rank);
- // Similarity should be descending
- try std.testing.expect(results[0].similarity >= results[1].similarity);
- try std.testing.expect(results[1].similarity >= results[2].similarity);
-}
-
-test "HDCSemanticSearch hybrid mode" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.initWithMode(allocator, 6000, 42, .hybrid);
- defer idx.deinit();
-
- try idx.addDocument("d1", "programming language design");
- try idx.addDocument("d2", "natural language processing");
- try idx.addDocument("d3", "cooking recipe ingredients");
-
- const results = try idx.search("language processing", 2);
- defer allocator.free(results);
-
- try std.testing.expect(results.len == 2);
- // d2 should rank first (best match for "language processing")
- try std.testing.expectEqualStrings("d2", results[0].id);
-}
-
-test "HDCSemanticSearch stats" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.init(allocator, 4000, 42);
- defer idx.deinit();
-
- try idx.addDocument("a", "hello world");
- try idx.addDocument("b", "foo bar baz");
-
- const s = idx.stats();
- try std.testing.expectEqual(@as(usize, 2), s.num_documents);
- try std.testing.expect(s.vocabulary_size >= 4); // at least hello, world, foo, bar
- try std.testing.expect(!s.is_tfidf_built);
-
- try idx.buildIndex();
- try std.testing.expect(idx.stats().is_tfidf_built);
-}
-
-test "HDCSemanticSearch knowledge base demo" {
- const allocator = std.testing.allocator;
- var idx = HDCSemanticSearch.init(allocator, 8000, 42);
- defer idx.deinit();
-
- // Index a mini knowledge base
- const docs = [_]struct { id: []const u8, text: []const u8, meta: []const u8 }{
- .{ .id = "zig-intro", .text = "zig is a systems programming language for robust software", .meta = "topic:programming" },
- .{ .id = "zig-safety", .text = "zig provides memory safety without garbage collection", .meta = "topic:programming" },
- .{ .id = "hdc-intro", .text = "hyperdimensional computing uses high dimensional vectors for cognition", .meta = "topic:ai" },
- .{ .id = "hdc-encoding", .text = "text encoding in hdc uses character level ngrams and word vectors", .meta = "topic:ai" },
- .{ .id = "vsa-ops", .text = "vector symbolic architecture operations include bind bundle permute", .meta = "topic:ai" },
- .{ .id = "rust-intro", .text = "rust is a systems programming language for safe concurrent software", .meta = "topic:programming" },
- .{ .id = "python-ml", .text = "python is popular for machine learning and data science", .meta = "topic:programming" },
- .{ .id = "cooking-101", .text = "basic cooking techniques include boiling baking grilling frying", .meta = "topic:cooking" },
- .{ .id = "recipe-pasta", .text = "pasta recipe with tomato sauce garlic basil olive oil", .meta = "topic:cooking" },
- .{ .id = "recipe-salad", .text = "fresh salad with lettuce tomato cucumber olive oil dressing", .meta = "topic:cooking" },
- };
-
- for (docs) |d| {
- try idx.addDocumentWithMetadata(d.id, d.text, d.meta);
- }
- try idx.buildIndex();
-
- // === Test queries ===
- const queries = [_]struct { query: []const u8, expected_top: []const u8 }{
- .{ .query = "zig programming language", .expected_top = "zig-intro" },
- .{ .query = "hyperdimensional computing vectors", .expected_top = "hdc-intro" },
- .{ .query = "vector bind bundle operations", .expected_top = "vsa-ops" },
- .{ .query = "pasta tomato recipe", .expected_top = "recipe-pasta" },
- .{ .query = "memory safety programming", .expected_top = "zig-safety" },
- };
-
- var correct: usize = 0;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC SEMANTIC SEARCH (dim=8000, mode=word_tfidf)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const s = idx.stats();
- std.debug.print(" Documents: {d} | Vocabulary: {d} | TF-IDF: {}\n", .{
- s.num_documents,
- s.vocabulary_size,
- s.is_tfidf_built,
- });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- for (queries) |q| {
- const results = try idx.search(q.query, 3);
- defer allocator.free(results);
-
- const hit = if (results.len > 0) std.mem.eql(u8, results[0].id, q.expected_top) else false;
- if (hit) correct += 1;
-
- std.debug.print(" Q: \"{s}\"\n", .{q.query});
- for (results) |r| {
- const marker: u8 = if (std.mem.eql(u8, r.id, q.expected_top)) '*' else ' ';
- std.debug.print(" {c} #{d} [{s}] sim={d:.4} \"{s}\"\n", .{
- marker,
- r.rank,
- r.id,
- r.similarity,
- r.metadata orelse "",
- });
- }
- }
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Retrieval accuracy (top-1): {d}/{d} ({d:.0}%)\n", .{
- correct,
- queries.len,
- @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(queries.len)) * 100.0,
- });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // At least 60% retrieval accuracy
- try std.testing.expect(correct >= 3);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC STREAM CLASSIFIER β Adaptive Online Learning from Data Streams
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sliding window of last N samples β periodic prototype rebuild.
-// Concept drift detection via confidence monitoring.
-//
-// Pattern: observe(text, label) β window fills β rebuild prototypes
-// predict(text) β classify against current prototypes
-// observeAndPredict(text, label) β test-then-train
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const HDCStreamClassifier = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- // Sliding window (ring buffer of samples)
- window: []?StreamSample,
- window_head: usize,
- window_count: usize,
- window_size: usize,
-
- // Current prototypes
- prototypes: std.StringHashMapUnmanaged(ClassPrototype),
-
- // Confidence history (ring buffer)
- conf_history: []f64,
- conf_head: usize,
- conf_count: usize,
-
- // Correctness history (ring buffer)
- correct_history: []bool,
- correct_head: usize,
- correct_count: usize,
-
- // Config
- rebuild_interval: usize,
- drift_window: usize,
- drift_threshold: f64,
-
- // Counters
- total_observed: usize,
- samples_since_rebuild: usize,
-
- const Self = @This();
-
- pub const StreamSample = struct {
- text: []const u8, // owned
- label: []const u8, // owned
- };
-
- pub const ClassPrototype = struct {
- prototype_hv: HybridBigInt,
- sample_count: u32,
- };
-
- pub const StreamPrediction = struct {
- label: []const u8,
- confidence: f64,
- drift_score: f64,
- is_drift: bool,
- };
-
- pub const ObserveResult = struct {
- prediction: ?StreamPrediction,
- was_correct: bool,
- window_accuracy: f64,
- };
-
- pub const StreamStats = struct {
- total_observed: usize,
- window_fill: usize,
- num_classes: usize,
- drift_score: f64,
- recent_accuracy: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithConfig(allocator, dimension, seed, 100, 10, 50, 0.3);
- }
-
- pub fn initWithConfig(
- allocator: std.mem.Allocator,
- dimension: usize,
- seed: u64,
- window_size: usize,
- rebuild_interval: usize,
- drift_window: usize,
- drift_threshold: f64,
- ) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- const window = allocator.alloc(?StreamSample, window_size) catch @panic("alloc failed");
- @memset(window, null);
-
- const conf_hist = allocator.alloc(f64, drift_window) catch @panic("alloc failed");
- @memset(conf_hist, 0);
-
- const corr_hist = allocator.alloc(bool, drift_window) catch @panic("alloc failed");
- @memset(corr_hist, false);
-
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .window = window,
- .window_head = 0,
- .window_count = 0,
- .window_size = window_size,
- .prototypes = .{},
- .conf_history = conf_hist,
- .conf_head = 0,
- .conf_count = 0,
- .correct_history = corr_hist,
- .correct_head = 0,
- .correct_count = 0,
- .rebuild_interval = rebuild_interval,
- .drift_window = drift_window,
- .drift_threshold = drift_threshold,
- .total_observed = 0,
- .samples_since_rebuild = 0,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .hybrid);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- // Free window samples
- for (self.window) |slot| {
- if (slot) |sample| {
- self.allocator.free(sample.text);
- self.allocator.free(sample.label);
- }
- }
- self.allocator.free(self.window);
- self.allocator.free(self.conf_history);
- self.allocator.free(self.correct_history);
-
- // Free prototype keys
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.prototypes.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Add a sample to the sliding window ring buffer
- fn windowPush(self: *Self, text: []const u8, label: []const u8) !void {
- const idx = self.window_head;
-
- // Evict old sample if slot is occupied
- if (self.window[idx]) |old| {
- self.allocator.free(old.text);
- self.allocator.free(old.label);
- }
-
- self.window[idx] = .{
- .text = try self.allocator.dupe(u8, text),
- .label = try self.allocator.dupe(u8, label),
- };
-
- self.window_head = (self.window_head + 1) % self.window_size;
- if (self.window_count < self.window_size) self.window_count += 1;
- }
-
- /// Push a confidence value to the history ring buffer
- fn confPush(self: *Self, confidence: f64) void {
- self.conf_history[self.conf_head] = confidence;
- self.conf_head = (self.conf_head + 1) % self.drift_window;
- if (self.conf_count < self.drift_window) self.conf_count += 1;
- }
-
- /// Push a correctness flag to history
- fn correctPush(self: *Self, correct: bool) void {
- self.correct_history[self.correct_head] = correct;
- self.correct_head = (self.correct_head + 1) % self.drift_window;
- if (self.correct_count < self.drift_window) self.correct_count += 1;
- }
-
- /// Rebuild prototypes from current window contents
- fn rebuildPrototypes(self: *Self) !void {
- self.fixSelfRef();
-
- // Clear old prototypes
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.prototypes.clearRetainingCapacity();
-
- // Bundle samples by label
- for (self.window) |slot| {
- const sample = slot orelse continue;
- const text_hv = try self.encoder.encodeText(sample.text);
-
- if (self.prototypes.getPtr(sample.label)) |proto| {
- var new_hv = text_hv;
- proto.prototype_hv = vsa.bundle2(&proto.prototype_hv, &new_hv);
- proto.sample_count += 1;
- } else {
- const owned_label = try self.allocator.dupe(u8, sample.label);
- try self.prototypes.put(self.allocator, owned_label, .{
- .prototype_hv = text_hv,
- .sample_count = 1,
- });
- }
- }
-
- self.samples_since_rebuild = 0;
- }
-
- /// Observe: add sample to stream, trigger rebuild if needed
- pub fn observe(self: *Self, text: []const u8, label: []const u8) !void {
- try self.windowPush(text, label);
- self.total_observed += 1;
- self.samples_since_rebuild += 1;
-
- if (self.samples_since_rebuild >= self.rebuild_interval) {
- try self.rebuildPrototypes();
- }
- }
-
- /// Predict class for text against current prototypes
- pub fn predict(self: *Self, text: []const u8) !?StreamPrediction {
- self.fixSelfRef();
- if (self.prototypes.count() == 0) return null;
-
- var text_hv = try self.encoder.encodeText(text);
-
- var best_label: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- var proto_hv = entry.value_ptr.prototype_hv;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_hv);
- if (sim > best_sim) {
- best_sim = sim;
- best_label = entry.key_ptr.*;
- }
- }
-
- const drift = self.getDriftScore();
- return StreamPrediction{
- .label = best_label,
- .confidence = best_sim,
- .drift_score = drift,
- .is_drift = drift > self.drift_threshold,
- };
- }
-
- /// Observe and predict: test-then-train pattern
- /// Predicts FIRST, then observes the true label
- pub fn observeAndPredict(self: *Self, text: []const u8, true_label: []const u8) !ObserveResult {
- // Step 1: Predict (before seeing true label)
- const prediction = try self.predict(text);
-
- // Step 2: Track correctness
- const was_correct = if (prediction) |p|
- std.mem.eql(u8, p.label, true_label)
- else
- false;
-
- self.correctPush(was_correct);
- if (prediction) |p| {
- self.confPush(p.confidence);
- }
-
- // Step 3: Observe (add to window, may trigger rebuild)
- try self.observe(text, true_label);
-
- return ObserveResult{
- .prediction = prediction,
- .was_correct = was_correct,
- .window_accuracy = self.getRecentAccuracy(),
- };
- }
-
- /// Compute concept drift score
- /// Compares recent confidence (last 25%) to historical (first 75%)
- /// Returns 0 = stable, >0 = drifting, >threshold = drift alert
- pub fn getDriftScore(self: *Self) f64 {
- if (self.conf_count < 4) return 0;
-
- const recent_size = self.conf_count / 4;
- if (recent_size == 0) return 0;
- const historical_size = self.conf_count - recent_size;
-
- // Compute means by walking ring buffer
- var recent_sum: f64 = 0;
- var hist_sum: f64 = 0;
-
- var idx = self.conf_head;
- var count: usize = 0;
- // Walk backwards through ring buffer
- while (count < self.conf_count) : (count += 1) {
- idx = if (idx == 0) self.drift_window - 1 else idx - 1;
- if (count < recent_size) {
- recent_sum += self.conf_history[idx];
- } else {
- hist_sum += self.conf_history[idx];
- }
- }
-
- const recent_mean = recent_sum / @as(f64, @floatFromInt(recent_size));
- const hist_mean = if (historical_size > 0)
- hist_sum / @as(f64, @floatFromInt(historical_size))
- else
- recent_mean;
-
- if (hist_mean <= 0) return 0;
- return @max(0, 1.0 - recent_mean / hist_mean);
- }
-
- /// Compute rolling accuracy from correctness history
- pub fn getRecentAccuracy(self: *Self) f64 {
- if (self.correct_count == 0) return 0;
-
- var correct_total: usize = 0;
- var idx = self.correct_head;
- for (0..self.correct_count) |_| {
- idx = if (idx == 0) self.drift_window - 1 else idx - 1;
- if (self.correct_history[idx]) correct_total += 1;
- }
-
- return @as(f64, @floatFromInt(correct_total)) / @as(f64, @floatFromInt(self.correct_count));
- }
-
- /// Get stream statistics
- pub fn stats(self: *Self) StreamStats {
- return .{
- .total_observed = self.total_observed,
- .window_fill = self.window_count,
- .num_classes = self.prototypes.count(),
- .drift_score = self.getDriftScore(),
- .recent_accuracy = self.getRecentAccuracy(),
- };
- }
-
- /// Reset all state
- pub fn reset(self: *Self) void {
- for (self.window) |slot| {
- if (slot) |sample| {
- self.allocator.free(sample.text);
- self.allocator.free(sample.label);
- }
- }
- @memset(self.window, null);
- self.window_head = 0;
- self.window_count = 0;
-
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.prototypes.clearRetainingCapacity();
-
- @memset(self.conf_history, 0);
- self.conf_head = 0;
- self.conf_count = 0;
-
- @memset(self.correct_history, false);
- self.correct_head = 0;
- self.correct_count = 0;
-
- self.total_observed = 0;
- self.samples_since_rebuild = 0;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HDC STREAM CLASSIFIER TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "HDCStreamClassifier basic observe and predict" {
- const allocator = std.testing.allocator;
- var sc = HDCStreamClassifier.initWithConfig(allocator, 6000, 42, 20, 5, 20, 0.3);
- defer sc.deinit();
-
- // Observe some samples
- try sc.observe("hello world greeting", "greeting");
- try sc.observe("hi there friend", "greeting");
- try sc.observe("goodbye farewell", "farewell");
- try sc.observe("see you later", "farewell");
- try sc.observe("hey how are you", "greeting");
-
- // After 5 samples (= rebuild_interval), prototypes should be rebuilt
- try std.testing.expectEqual(@as(usize, 5), sc.total_observed);
- try std.testing.expectEqual(@as(usize, 2), sc.prototypes.count());
-
- const p = try sc.predict("hello friend");
- try std.testing.expect(p != null);
- try std.testing.expectEqualStrings("greeting", p.?.label);
-}
-
-test "HDCStreamClassifier observe and predict pattern" {
- const allocator = std.testing.allocator;
- var sc = HDCStreamClassifier.initWithConfig(allocator, 6000, 42, 20, 3, 20, 0.3);
- defer sc.deinit();
-
- // Seed with initial data
- try sc.observe("cat dog pet", "animal");
- try sc.observe("car truck bus", "vehicle");
- try sc.observe("kitten puppy", "animal");
-
- // Now use observeAndPredict
- const r = try sc.observeAndPredict("dog cat kitten", "animal");
- try std.testing.expect(r.prediction != null);
- if (r.prediction) |p| {
- try std.testing.expectEqualStrings("animal", p.label);
- }
- try std.testing.expect(r.was_correct);
-}
-
-test "HDCStreamClassifier sliding window evicts old" {
- const allocator = std.testing.allocator;
- // Tiny window of 4 samples, rebuild every 2
- var sc = HDCStreamClassifier.initWithConfig(allocator, 6000, 42, 4, 2, 10, 0.3);
- defer sc.deinit();
-
- // Fill window with "animal" data
- try sc.observe("cat dog pet animal", "animal");
- try sc.observe("kitten puppy creature", "animal");
-
- // Prototypes rebuilt after 2 samples
- try std.testing.expectEqual(@as(usize, 1), sc.prototypes.count());
-
- // Now shift to "vehicle" data
- try sc.observe("car truck bus motor", "vehicle");
- try sc.observe("train plane ship boat", "vehicle");
-
- // After 4 more, window has evicted old animal data
- try sc.observe("engine wheel drive road", "vehicle");
- try sc.observe("highway speed traffic lane", "vehicle");
-
- // Window should now be dominated by vehicle
- try std.testing.expectEqual(@as(usize, 4), sc.window_count);
-
- const p = try sc.predict("car bus motor");
- try std.testing.expect(p != null);
- try std.testing.expectEqualStrings("vehicle", p.?.label);
-}
-
-test "HDCStreamClassifier recent accuracy tracking" {
- const allocator = std.testing.allocator;
- var sc = HDCStreamClassifier.initWithConfig(allocator, 6000, 42, 20, 3, 10, 0.3);
- defer sc.deinit();
-
- // Train initial data
- try sc.observe("hello world", "greeting");
- try sc.observe("goodbye world", "farewell");
- try sc.observe("hi there", "greeting");
-
- // Stream some test-then-train samples
- _ = try sc.observeAndPredict("hello friend", "greeting");
- _ = try sc.observeAndPredict("bye friend", "farewell");
- _ = try sc.observeAndPredict("hi again", "greeting");
-
- const acc = sc.getRecentAccuracy();
- try std.testing.expect(acc >= 0.0 and acc <= 1.0);
-}
-
-test "HDCStreamClassifier empty predict returns null" {
- const allocator = std.testing.allocator;
- var sc = HDCStreamClassifier.init(allocator, 4000, 42);
- defer sc.deinit();
-
- const p = try sc.predict("anything");
- try std.testing.expect(p == null);
-}
-
-test "HDCStreamClassifier reset clears state" {
- const allocator = std.testing.allocator;
- var sc = HDCStreamClassifier.initWithConfig(allocator, 4000, 42, 10, 3, 10, 0.3);
- defer sc.deinit();
-
- try sc.observe("hello", "greeting");
- try sc.observe("bye", "farewell");
- try sc.observe("hi", "greeting");
-
- try std.testing.expectEqual(@as(usize, 3), sc.total_observed);
- sc.reset();
- try std.testing.expectEqual(@as(usize, 0), sc.total_observed);
- try std.testing.expectEqual(@as(usize, 0), sc.window_count);
- try std.testing.expectEqual(@as(usize, 0), sc.prototypes.count());
-}
-
-test "HDCStreamClassifier concept drift detection demo" {
- const allocator = std.testing.allocator;
- // Small window and fast rebuild for demo
- var sc = HDCStreamClassifier.initWithConfig(allocator, 8000, 42, 20, 5, 20, 0.2);
- defer sc.deinit();
-
- // === Phase 1: Stable distribution (animals vs vehicles) ===
- const phase1_data = [_]struct { text: []const u8, label: []const u8 }{
- .{ .text = "cat dog pet animal creature", .label = "A" },
- .{ .text = "kitten puppy pet furry", .label = "A" },
- .{ .text = "dog cat hamster rabbit", .label = "A" },
- .{ .text = "car truck bus vehicle motor", .label = "B" },
- .{ .text = "train plane ship transport", .label = "B" },
- .{ .text = "engine wheel road highway", .label = "B" },
- .{ .text = "cat animal pet furry creature", .label = "A" },
- .{ .text = "bus truck car transport road", .label = "B" },
- .{ .text = "puppy kitten pet small", .label = "A" },
- .{ .text = "plane helicopter aircraft fly", .label = "B" },
- };
-
- var phase1_correct: usize = 0;
- for (phase1_data) |d| {
- const r = try sc.observeAndPredict(d.text, d.label);
- if (r.was_correct) phase1_correct += 1;
- }
-
- const phase1_acc = sc.getRecentAccuracy();
- const phase1_drift = sc.getDriftScore();
-
- // === Phase 2: CONCEPT DRIFT β switch to food vs tech ===
- const phase2_data = [_]struct { text: []const u8, label: []const u8 }{
- .{ .text = "pizza pasta sushi noodles rice", .label = "A" },
- .{ .text = "salad soup bread cheese butter", .label = "A" },
- .{ .text = "cooking recipe kitchen chef", .label = "A" },
- .{ .text = "software code programming algorithm", .label = "B" },
- .{ .text = "neural network machine learning", .label = "B" },
- .{ .text = "database server cloud computing", .label = "B" },
- .{ .text = "restaurant menu food dinner", .label = "A" },
- .{ .text = "compiler debugger runtime code", .label = "B" },
- .{ .text = "fruit vegetable organic fresh", .label = "A" },
- .{ .text = "api endpoint http request", .label = "B" },
- };
-
- var phase2_correct: usize = 0;
- for (phase2_data) |d| {
- const r = try sc.observeAndPredict(d.text, d.label);
- if (r.was_correct) phase2_correct += 1;
- }
-
- const phase2_acc = sc.getRecentAccuracy();
- const phase2_drift = sc.getDriftScore();
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC STREAM CLASSIFIER β CONCEPT DRIFT DEMO (dim=8000)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const s = sc.stats();
- std.debug.print(" Total observed: {d} | Window: {d}/{d} | Classes: {d}\n", .{
- s.total_observed,
- s.window_fill,
- sc.window_size,
- s.num_classes,
- });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Phase 1 (animals/vehicles): accuracy={d:.2} drift={d:.4}\n", .{
- phase1_acc,
- phase1_drift,
- });
- std.debug.print(" Correct: {d}/{d}\n", .{ phase1_correct, phase1_data.len });
- std.debug.print(" Phase 2 (food/tech): accuracy={d:.2} drift={d:.4}\n", .{
- phase2_acc,
- phase2_drift,
- });
- std.debug.print(" Correct: {d}/{d}\n", .{ phase2_correct, phase2_data.len });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Final drift score: {d:.4} (threshold={d:.2})\n", .{
- s.drift_score,
- sc.drift_threshold,
- });
- std.debug.print(" Final accuracy: {d:.2}\n", .{s.recent_accuracy});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Basic sanity: we observed 20 total
- try std.testing.expectEqual(@as(usize, 20), sc.total_observed);
- // Accuracy should be tracked
- try std.testing.expect(sc.getRecentAccuracy() >= 0.0);
-}
-
-// ============================================================================
-// HDC Explainable AI β Feature Attribution
-// ============================================================================
-// Explains classifier decisions by decomposing prototypes into
-// per-word/feature contributions using VSA algebra.
-// ============================================================================
-
-pub const HDCExplainer = struct {
- allocator: std.mem.Allocator,
- classifier: *HDCClassifier,
-
- const Self = @This();
-
- pub const WordAttribution = struct {
- word: []const u8,
- score: f64,
- rank: usize,
- };
-
- pub const ContrastiveAttribution = struct {
- word: []const u8,
- score_for: f64,
- score_against: f64,
- diff: f64,
- };
-
- pub const Explanation = struct {
- predicted_label: []const u8,
- confidence: f64,
- attributions: []WordAttribution, // sorted by score descending
- attribution_count: usize,
- };
-
- pub const ContrastiveExplanation = struct {
- label_for: []const u8,
- label_against: []const u8,
- attributions: []ContrastiveAttribution, // sorted by diff descending
- attribution_count: usize,
- };
-
- pub fn init(allocator: std.mem.Allocator, classifier: *HDCClassifier) Self {
- return Self{
- .allocator = allocator,
- .classifier = classifier,
- };
- }
-
- pub fn deinit(self: *Self) void {
- _ = self;
- // Nothing to free β we borrow the classifier
- }
-
- /// Compute per-word attribution scores against a class prototype.
- /// Returns owned slice of WordAttribution sorted by score descending.
- pub fn attributeWords(self: *Self, text: []const u8, label: []const u8) !?[]WordAttribution {
- self.classifier.fixSelfRef();
-
- // Get class prototype
- const proto = self.classifier.classes.get(label) orelse return null;
-
- // Collect unique words
- var unique_words = std.ArrayListUnmanaged([]const u8){};
- defer unique_words.deinit(self.allocator);
-
- var seen = std.StringHashMapUnmanaged(void){};
- defer seen.deinit(self.allocator);
-
- var iter = HDCTextEncoder.splitWords(text);
- while (iter.next()) |word| {
- if (!seen.contains(word)) {
- try seen.put(self.allocator, word, {});
- try unique_words.append(self.allocator, word);
- }
- }
-
- if (unique_words.items.len == 0) return null;
-
- // Compute attribution for each word
- const result = try self.allocator.alloc(WordAttribution, unique_words.items.len);
- var proto_hv = proto.prototype_hv.*;
-
- for (unique_words.items, 0..) |word, i| {
- // Encode word β get its HV
- var word_hv = try self.classifier.encoder.encodeWord(word);
- const score = vsa.cosineSimilarity(&word_hv, &proto_hv);
- result[i] = WordAttribution{
- .word = word,
- .score = score,
- .rank = 0, // assigned after sort
- };
- }
-
- // Sort by score descending
- std.mem.sort(WordAttribution, result, {}, struct {
- fn cmp(_: void, a: WordAttribution, b: WordAttribution) bool {
- return a.score > b.score;
- }
- }.cmp);
-
- // Assign ranks
- for (result, 0..) |*attr, i| {
- attr.rank = i + 1;
- }
-
- return result;
- }
-
- /// Return top-k most contributing words for a class.
- pub fn attributeTopK(self: *Self, text: []const u8, label: []const u8, k: usize) !?[]WordAttribution {
- const all = try self.attributeWords(text, label) orelse return null;
- const actual_k = @min(k, all.len);
- if (actual_k < all.len) {
- // Free the excess
- const result = try self.allocator.alloc(WordAttribution, actual_k);
- @memcpy(result, all[0..actual_k]);
- self.allocator.free(all);
- return result;
- }
- return all;
- }
-
- /// Explain a prediction: classify, then attribute words to the predicted class.
- pub fn explainPrediction(self: *Self, text: []const u8) !?Explanation {
- self.classifier.fixSelfRef();
-
- // Classify first
- const pred = try self.classifier.predict(text) orelse return null;
-
- // Attribute words to the predicted class
- const attrs = try self.attributeWords(text, pred.label) orelse return null;
-
- return Explanation{
- .predicted_label = pred.label,
- .confidence = pred.confidence,
- .attributions = attrs,
- .attribution_count = attrs.len,
- };
- }
-
- /// Contrastive explanation: why label_for instead of label_against?
- /// Computes per-word score difference between two classes.
- pub fn explainContrastive(self: *Self, text: []const u8, label_for: []const u8, label_against: []const u8) !?ContrastiveExplanation {
- self.classifier.fixSelfRef();
-
- // Get both prototypes
- const proto_for = self.classifier.classes.get(label_for) orelse return null;
- const proto_against = self.classifier.classes.get(label_against) orelse return null;
-
- // Collect unique words
- var unique_words = std.ArrayListUnmanaged([]const u8){};
- defer unique_words.deinit(self.allocator);
-
- var seen = std.StringHashMapUnmanaged(void){};
- defer seen.deinit(self.allocator);
-
- var iter = HDCTextEncoder.splitWords(text);
- while (iter.next()) |word| {
- if (!seen.contains(word)) {
- try seen.put(self.allocator, word, {});
- try unique_words.append(self.allocator, word);
- }
- }
-
- if (unique_words.items.len == 0) return null;
-
- const result = try self.allocator.alloc(ContrastiveAttribution, unique_words.items.len);
- var proto_for_hv = proto_for.prototype_hv.*;
- var proto_against_hv = proto_against.prototype_hv.*;
-
- for (unique_words.items, 0..) |word, i| {
- var word_hv = try self.classifier.encoder.encodeWord(word);
- const score_for = vsa.cosineSimilarity(&word_hv, &proto_for_hv);
- const score_against = vsa.cosineSimilarity(&word_hv, &proto_against_hv);
- result[i] = ContrastiveAttribution{
- .word = word,
- .score_for = score_for,
- .score_against = score_against,
- .diff = score_for - score_against,
- };
- }
-
- // Sort by diff descending (words favoring label_for first)
- std.mem.sort(ContrastiveAttribution, result, {}, struct {
- fn cmp(_: void, a: ContrastiveAttribution, b: ContrastiveAttribution) bool {
- return a.diff > b.diff;
- }
- }.cmp);
-
- return ContrastiveExplanation{
- .label_for = label_for,
- .label_against = label_against,
- .attributions = result,
- .attribution_count = result.len,
- };
- }
-};
-
-// ============================================================================
-// HDCExplainer Tests
-// ============================================================================
-
-test "HDCExplainer attributeWords basic" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, .hybrid);
- defer clf.deinit();
-
- // Train classifier
- try clf.train("sports", "football soccer goal team match");
- try clf.train("sports", "basketball court dunk score player");
- try clf.train("tech", "computer software algorithm code program");
- try clf.train("tech", "database server network cloud system");
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- // Attribute words to sports class
- const attrs = (try explainer.attributeWords("football goal team", "sports")).?;
- defer allocator.free(attrs);
-
- try std.testing.expect(attrs.len == 3);
- // All words should have valid scores
- for (attrs) |attr| {
- try std.testing.expect(attr.score >= -1.0 and attr.score <= 1.0);
- try std.testing.expect(attr.rank >= 1);
- }
- // Should be sorted descending
- if (attrs.len >= 2) {
- try std.testing.expect(attrs[0].score >= attrs[1].score);
- }
-}
-
-test "HDCExplainer attributeWords domain specificity" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, .hybrid);
- defer clf.deinit();
-
- try clf.train("sports", "football soccer goal team match");
- try clf.train("sports", "basketball court dunk score player");
- try clf.train("sports", "football goal score win championship");
- try clf.train("tech", "computer software algorithm code program");
- try clf.train("tech", "database server network cloud system");
- try clf.train("tech", "algorithm code software developer engineering");
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- // "football" should have higher sports attribution than "algorithm"
- const sports_attrs = (try explainer.attributeWords("football algorithm", "sports")).?;
- defer allocator.free(sports_attrs);
-
- var football_score: f64 = 0;
- var algorithm_score: f64 = 0;
- for (sports_attrs) |attr| {
- if (std.mem.eql(u8, attr.word, "football")) football_score = attr.score;
- if (std.mem.eql(u8, attr.word, "algorithm")) algorithm_score = attr.score;
- }
- // Football should be more associated with sports than algorithm
- try std.testing.expect(football_score > algorithm_score);
-}
-
-test "HDCExplainer attributeTopK" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, .hybrid);
- defer clf.deinit();
-
- try clf.train("animals", "cat dog hamster rabbit fish bird");
- try clf.train("animals", "kitten puppy pet creature furry");
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- const top2 = (try explainer.attributeTopK("cat dog rabbit hamster bird", "animals", 2)).?;
- defer allocator.free(top2);
-
- try std.testing.expectEqual(@as(usize, 2), top2.len);
- // Should be the top 2 by score
- try std.testing.expect(top2[0].score >= top2[1].score);
-}
-
-test "HDCExplainer explainPrediction" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, .hybrid);
- defer clf.deinit();
-
- try clf.train("sports", "football soccer goal team match");
- try clf.train("sports", "basketball court dunk score player");
- try clf.train("tech", "computer software algorithm code program");
- try clf.train("tech", "database server network cloud system");
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- const expl = (try explainer.explainPrediction("football team goal")).?;
- defer allocator.free(expl.attributions);
-
- // Should predict sports
- try std.testing.expect(std.mem.eql(u8, expl.predicted_label, "sports"));
- try std.testing.expect(expl.confidence > 0.0);
- try std.testing.expect(expl.attribution_count == 3);
-}
-
-test "HDCExplainer explainContrastive" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, .hybrid);
- defer clf.deinit();
-
- try clf.train("sports", "football soccer goal team match");
- try clf.train("sports", "basketball court dunk score player");
- try clf.train("sports", "football goal score win championship");
- try clf.train("tech", "computer software algorithm code program");
- try clf.train("tech", "database server network cloud system");
- try clf.train("tech", "algorithm code software developer engineering");
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- // "Why sports instead of tech?"
- const contrast = (try explainer.explainContrastive(
- "football code team algorithm",
- "sports",
- "tech",
- )).?;
- defer allocator.free(contrast.attributions);
-
- try std.testing.expect(contrast.attribution_count == 4);
- try std.testing.expect(std.mem.eql(u8, contrast.label_for, "sports"));
- try std.testing.expect(std.mem.eql(u8, contrast.label_against, "tech"));
-
- // "football" should favor sports (positive diff)
- // "algorithm" should favor tech (negative diff)
- var football_diff: f64 = 0;
- var algorithm_diff: f64 = 0;
- for (contrast.attributions) |attr| {
- if (std.mem.eql(u8, attr.word, "football")) football_diff = attr.diff;
- if (std.mem.eql(u8, attr.word, "algorithm")) algorithm_diff = attr.diff;
- }
- // football should favor sports more than algorithm does
- try std.testing.expect(football_diff > algorithm_diff);
-}
-
-test "HDCExplainer empty classifier returns null" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.init(allocator, 8000, 42);
- defer clf.deinit();
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- const result = try explainer.explainPrediction("hello world");
- try std.testing.expect(result == null);
-
- const attrs = try explainer.attributeWords("hello", "nonexistent");
- try std.testing.expect(attrs == null);
-}
-
-test "HDCExplainer nonexistent class returns null" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, .hybrid);
- defer clf.deinit();
-
- try clf.train("sports", "football goal team");
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- // Existing class works
- const attrs = try explainer.attributeWords("football goal", "sports");
- try std.testing.expect(attrs != null);
- allocator.free(attrs.?);
-
- // Nonexistent class returns null
- const attrs2 = try explainer.attributeWords("football goal", "music");
- try std.testing.expect(attrs2 == null);
-}
-
-test "HDCExplainer XAI demo β email classification" {
- const allocator = std.testing.allocator;
- var clf = HDCClassifier.initWithMode(allocator, 8000, 42, .hybrid);
- defer clf.deinit();
-
- // Train email classifier
- try clf.train("spam", "buy cheap discount offer free money prize winner");
- try clf.train("spam", "click here now limited offer deal sale urgent");
- try clf.train("spam", "free gift card lottery winning claim reward");
- try clf.train("ham", "meeting tomorrow agenda project update review");
- try clf.train("ham", "please review the attached document report");
- try clf.train("ham", "team lunch friday office birthday celebration");
-
- var explainer = HDCExplainer.init(allocator, &clf);
- defer explainer.deinit();
-
- // Explain a spam prediction
- const test_text = "free offer buy discount click now";
- const expl = (try explainer.explainPrediction(test_text)).?;
- defer allocator.free(expl.attributions);
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC EXPLAINABLE AI β EMAIL CLASSIFICATION DEMO\n", .{});
- std.debug.print(" dim=8000, mode=hybrid\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Input: \"{s}\"\n", .{test_text});
- std.debug.print(" Prediction: {s} (confidence={d:.4})\n", .{ expl.predicted_label, expl.confidence });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" WORD ATTRIBUTIONS (to predicted class \"{s}\"):\n", .{expl.predicted_label});
-
- for (expl.attributions) |attr| {
- const bar_len = @as(usize, @intFromFloat(@max(0.0, (attr.score + 1.0) * 15.0)));
- var bar: [30]u8 = [_]u8{' '} ** 30;
- for (0..@min(bar_len, 30)) |b| bar[b] = '#';
- std.debug.print(" #{d}: {s:12} score={d:.4} |{s}|\n", .{
- attr.rank,
- attr.word,
- attr.score,
- bar[0..30],
- });
- }
-
- // Contrastive: why spam instead of ham?
- const contrast = (try explainer.explainContrastive(test_text, "spam", "ham")).?;
- defer allocator.free(contrast.attributions);
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" CONTRASTIVE: Why \"{s}\" instead of \"{s}\"?\n", .{ contrast.label_for, contrast.label_against });
-
- for (contrast.attributions) |attr| {
- const direction: []const u8 = if (attr.diff > 0) "β SPAM" else "β HAM ";
- std.debug.print(" {s:12} diff={d:.4} ({s}) for={d:.4} against={d:.4}\n", .{
- attr.word,
- attr.diff,
- direction,
- attr.score_for,
- attr.score_against,
- });
- }
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Verify prediction is spam
- try std.testing.expect(std.mem.eql(u8, expl.predicted_label, "spam"));
-
- // Verify contrastive makes sense
- try std.testing.expect(contrast.attribution_count == 6);
-}
-
-// ============================================================================
-// HDC Reinforcement Learning Agent
-// ============================================================================
-// Q-learning via hyperdimensional action-value prototypes.
-// States encoded as HVs, Q-values estimated from cosine similarity.
-// ============================================================================
-
-pub const HDCRLAgent = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
-
- // Action-value prototypes: one pair (positive, negative) per action
- action_pos_protos: [4]?*HybridBigInt, // positive return states
- action_neg_protos: [4]?*HybridBigInt, // negative return states
- action_pos_counts: [4]u32,
- action_neg_counts: [4]u32,
-
- // Config
- gamma: f64,
- epsilon: f64,
- epsilon_decay: f64,
- epsilon_min: f64,
-
- // Stats
- total_episodes: usize,
-
- // RNG
- rng: std.Random.DefaultPrng,
-
- const Self = @This();
-
- pub const Action = enum(u2) {
- up = 0,
- down = 1,
- left = 2,
- right = 3,
- };
-
- pub const State = struct {
- x: usize,
- y: usize,
-
- pub fn eql(a: State, b: State) bool {
- return a.x == b.x and a.y == b.y;
- }
- };
-
- pub const Transition = struct {
- state: State,
- action: Action,
- reward: f64,
- };
-
- pub const ActionValue = struct {
- action: Action,
- q_value: f64,
- };
-
- pub const EpisodeStats = struct {
- total_reward: f64,
- steps: usize,
- reached_goal: bool,
- };
-
- pub const Gridworld = struct {
- width: usize,
- height: usize,
- walls: []const State,
- goal: State,
- start: State,
- step_reward: f64,
- goal_reward: f64,
- wall_penalty: f64,
-
- pub fn isWall(self: Gridworld, s: State) bool {
- for (self.walls) |w| {
- if (w.eql(s)) return true;
- }
- return false;
- }
-
- pub fn step(self: Gridworld, s: State, a: Action) struct { next: State, reward: f64, done: bool } {
- var nx: isize = @intCast(s.x);
- var ny: isize = @intCast(s.y);
-
- switch (a) {
- .up => ny -= 1,
- .down => ny += 1,
- .left => nx -= 1,
- .right => nx += 1,
- }
-
- // Boundary check
- if (nx < 0 or ny < 0 or nx >= @as(isize, @intCast(self.width)) or ny >= @as(isize, @intCast(self.height))) {
- return .{ .next = s, .reward = self.wall_penalty, .done = false };
- }
-
- const candidate = State{ .x = @intCast(nx), .y = @intCast(ny) };
-
- // Wall check
- if (self.isWall(candidate)) {
- return .{ .next = s, .reward = self.wall_penalty, .done = false };
- }
-
- // Goal check
- if (candidate.eql(self.goal)) {
- return .{ .next = candidate, .reward = self.goal_reward, .done = true };
- }
-
- return .{ .next = candidate, .reward = self.step_reward, .done = false };
- }
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithConfig(allocator, dimension, seed, 0.99, 0.3, 0.995, 0.01);
- }
-
- pub fn initWithConfig(
- allocator: std.mem.Allocator,
- dimension: usize,
- seed: u64,
- gamma: f64,
- epsilon: f64,
- epsilon_decay: f64,
- epsilon_min: f64,
- ) Self {
- const item_mem = ItemMemory.init(allocator, dimension, seed);
- return Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(@constCast(&item_mem), 3),
- .dimension = dimension,
- .action_pos_protos = .{ null, null, null, null },
- .action_neg_protos = .{ null, null, null, null },
- .action_pos_counts = .{ 0, 0, 0, 0 },
- .action_neg_counts = .{ 0, 0, 0, 0 },
- .gamma = gamma,
- .epsilon = epsilon,
- .epsilon_decay = epsilon_decay,
- .epsilon_min = epsilon_min,
- .total_episodes = 0,
- .rng = std.Random.DefaultPrng.init(seed +% 999),
- };
- }
-
- pub fn deinit(self: *Self) void {
- for (0..4) |i| {
- if (self.action_pos_protos[i]) |p| self.allocator.destroy(p);
- if (self.action_neg_protos[i]) |p| self.allocator.destroy(p);
- }
- self.item_memory.deinit();
- }
-
- /// Encode a grid state (x, y) as a hypervector.
- /// state_hv = bind(perm(getVector(x + 0x100), 0), perm(getVector(y + 0x200), 100))
- pub fn encodeState(self: *Self, s: State) !HybridBigInt {
- self.ngram_encoder.item_memory = &self.item_memory;
-
- const x_sym: u32 = @intCast(s.x + 0x100);
- const y_sym: u32 = @intCast(s.y + 0x200);
-
- const x_hv = try self.item_memory.getVector(x_sym);
- var x_perm = vsa.permute(x_hv, 0);
-
- const y_hv = try self.item_memory.getVector(y_sym);
- var y_perm = vsa.permute(y_hv, 100);
-
- return vsa.bind(&x_perm, &y_perm);
- }
-
- /// Get Q-value for a state-action pair.
- /// Q(s, a) = cosine(state_hv, pos_proto[a]) - cosine(state_hv, neg_proto[a])
- pub fn getQValue(self: *Self, s: State) ![4]f64 {
- var state_hv = try self.encodeState(s);
- var q_values: [4]f64 = .{ 0, 0, 0, 0 };
-
- for (0..4) |i| {
- var pos_score: f64 = 0;
- var neg_score: f64 = 0;
-
- if (self.action_pos_protos[i]) |pos| {
- pos_score = vsa.cosineSimilarity(&state_hv, pos);
- }
- if (self.action_neg_protos[i]) |neg| {
- neg_score = vsa.cosineSimilarity(&state_hv, neg);
- }
-
- q_values[i] = pos_score - neg_score;
- }
-
- return q_values;
- }
-
- /// Select action using epsilon-greedy policy.
- pub fn selectAction(self: *Self, s: State) !Action {
- const rand = self.rng.random();
- if (rand.float(f64) < self.epsilon) {
- // Random exploration
- return @enumFromInt(rand.intRangeAtMost(u2, 0, 3));
- }
- return try self.getBestAction(s);
- }
-
- /// Get best action (greedy, no exploration).
- pub fn getBestAction(self: *Self, s: State) !Action {
- const q_values = try self.getQValue(s);
- var best_idx: u2 = 0;
- var best_val: f64 = q_values[0];
- for (1..4) |i| {
- if (q_values[i] > best_val) {
- best_val = q_values[i];
- best_idx = @intCast(i);
- }
- }
- return @enumFromInt(best_idx);
- }
-
- /// Learn from an episode trajectory using Monte Carlo returns.
- pub fn learnEpisode(self: *Self, trajectory: []const Transition) !void {
- if (trajectory.len == 0) return;
-
- // Compute discounted returns backwards
- const returns = try self.allocator.alloc(f64, trajectory.len);
- defer self.allocator.free(returns);
-
- var g: f64 = 0;
- var i: usize = trajectory.len;
- while (i > 0) {
- i -= 1;
- g = trajectory[i].reward + self.gamma * g;
- returns[i] = g;
- }
-
- // Update prototypes
- for (trajectory, 0..) |trans, idx| {
- const action_idx = @intFromEnum(trans.action);
- var state_hv = try self.encodeState(trans.state);
- const ret = returns[idx];
-
- if (ret > 0) {
- if (self.action_pos_protos[action_idx]) |pos| {
- pos.* = vsa.bundle2(pos, &state_hv);
- } else {
- const p = try self.allocator.create(HybridBigInt);
- p.* = state_hv;
- self.action_pos_protos[action_idx] = p;
- }
- self.action_pos_counts[action_idx] += 1;
- } else if (ret < 0) {
- if (self.action_neg_protos[action_idx]) |neg| {
- neg.* = vsa.bundle2(neg, &state_hv);
- } else {
- const p = try self.allocator.create(HybridBigInt);
- p.* = state_hv;
- self.action_neg_protos[action_idx] = p;
- }
- self.action_neg_counts[action_idx] += 1;
- }
- }
-
- // Decay epsilon
- self.epsilon = @max(self.epsilon_min, self.epsilon * self.epsilon_decay);
- self.total_episodes += 1;
- }
-
- /// Run one episode on a gridworld, return trajectory.
- pub fn runEpisode(self: *Self, env: Gridworld, max_steps: usize) !struct { trajectory: []Transition, stats: EpisodeStats } {
- var trajectory = std.ArrayListUnmanaged(Transition){};
- var current = env.start;
- var total_reward: f64 = 0;
- var reached_goal = false;
-
- for (0..max_steps) |_| {
- const action = try self.selectAction(current);
- const result = env.step(current, action);
-
- try trajectory.append(self.allocator, Transition{
- .state = current,
- .action = action,
- .reward = result.reward,
- });
-
- total_reward += result.reward;
- current = result.next;
-
- if (result.done) {
- reached_goal = true;
- break;
- }
- }
-
- const traj_len = trajectory.items.len;
- const owned = try trajectory.toOwnedSlice(self.allocator);
- return .{
- .trajectory = owned,
- .stats = EpisodeStats{
- .total_reward = total_reward,
- .steps = traj_len,
- .reached_goal = reached_goal,
- },
- };
- }
-
- /// Train on gridworld for num_episodes.
- pub fn trainGridworld(self: *Self, env: Gridworld, num_episodes: usize, max_steps: usize) !void {
- for (0..num_episodes) |_| {
- const result = try self.runEpisode(env, max_steps);
- defer self.allocator.free(result.trajectory);
- try self.learnEpisode(result.trajectory);
- }
- }
-
- /// Evaluate current policy (greedy, no exploration).
- pub fn evaluatePolicy(self: *Self, env: Gridworld, max_steps: usize) !EpisodeStats {
- var current = env.start;
- var total_reward: f64 = 0;
- var steps: usize = 0;
-
- for (0..max_steps) |_| {
- const action = try self.getBestAction(current);
- const result = env.step(current, action);
- total_reward += result.reward;
- current = result.next;
- steps += 1;
- if (result.done) {
- return EpisodeStats{
- .total_reward = total_reward,
- .steps = steps,
- .reached_goal = true,
- };
- }
- }
-
- return EpisodeStats{
- .total_reward = total_reward,
- .steps = steps,
- .reached_goal = false,
- };
- }
-
- /// Print the learned policy as a grid.
- pub fn printPolicy(self: *Self, env: Gridworld) !void {
- const arrows = [_][]const u8{ "^", "v", "<", ">" };
- for (0..env.height) |y| {
- std.debug.print(" ", .{});
- for (0..env.width) |x| {
- const s = State{ .x = x, .y = y };
- if (s.eql(env.goal)) {
- std.debug.print(" G ", .{});
- } else if (env.isWall(s)) {
- std.debug.print(" # ", .{});
- } else {
- const best = try self.getBestAction(s);
- std.debug.print(" {s} ", .{arrows[@intFromEnum(best)]});
- }
- }
- std.debug.print("\n", .{});
- }
- }
-
- /// Print Q-values for all states.
- pub fn printQValues(self: *Self, env: Gridworld) !void {
- for (0..env.height) |y| {
- for (0..env.width) |x| {
- const s = State{ .x = x, .y = y };
- if (env.isWall(s)) {
- std.debug.print(" ({d},{d}): WALL\n", .{ x, y });
- } else {
- const qv = try self.getQValue(s);
- std.debug.print(" ({d},{d}): U={d:.3} D={d:.3} L={d:.3} R={d:.3}\n", .{
- x, y, qv[0], qv[1], qv[2], qv[3],
- });
- }
- }
- }
- }
-};
-
-// ============================================================================
-// HDCRLAgent Tests
-// ============================================================================
-
-fn makeGridworld() HDCRLAgent.Gridworld {
- const walls = [_]HDCRLAgent.State{
- .{ .x = 1, .y = 1 },
- .{ .x = 3, .y = 1 },
- .{ .x = 1, .y = 3 },
- .{ .x = 3, .y = 3 },
- };
- return HDCRLAgent.Gridworld{
- .width = 5,
- .height = 5,
- .walls = &walls,
- .goal = .{ .x = 4, .y = 4 },
- .start = .{ .x = 0, .y = 0 },
- .step_reward = -0.1,
- .goal_reward = 10.0,
- .wall_penalty = -1.0,
- };
-}
-
-test "HDCRLAgent encodeState produces unique HVs" {
- const allocator = std.testing.allocator;
- var agent = HDCRLAgent.init(allocator, 8000, 42);
- defer agent.deinit();
-
- var hv_00 = try agent.encodeState(.{ .x = 0, .y = 0 });
- var hv_01 = try agent.encodeState(.{ .x = 0, .y = 1 });
- var hv_10 = try agent.encodeState(.{ .x = 1, .y = 0 });
- var hv_44 = try agent.encodeState(.{ .x = 4, .y = 4 });
-
- // Same state β identical
- var hv_00b = try agent.encodeState(.{ .x = 0, .y = 0 });
- const self_sim = vsa.cosineSimilarity(&hv_00, &hv_00b);
- try std.testing.expect(self_sim > 0.99);
-
- // Different states β low similarity (near-orthogonal)
- const sim_01 = vsa.cosineSimilarity(&hv_00, &hv_01);
- const sim_10 = vsa.cosineSimilarity(&hv_00, &hv_10);
- const sim_44 = vsa.cosineSimilarity(&hv_00, &hv_44);
-
- try std.testing.expect(@abs(sim_01) < 0.3);
- try std.testing.expect(@abs(sim_10) < 0.3);
- try std.testing.expect(@abs(sim_44) < 0.3);
-}
-
-test "HDCRLAgent getQValue initial zeros" {
- const allocator = std.testing.allocator;
- var agent = HDCRLAgent.init(allocator, 8000, 42);
- defer agent.deinit();
-
- // Before training, all Q-values should be 0
- const qv = try agent.getQValue(.{ .x = 0, .y = 0 });
- for (qv) |q| {
- try std.testing.expect(@abs(q) < 0.001);
- }
-}
-
-test "HDCRLAgent gridworld environment step" {
- const env = makeGridworld();
-
- // Normal step
- const r1 = env.step(.{ .x = 0, .y = 0 }, .right);
- try std.testing.expectEqual(@as(usize, 1), r1.next.x);
- try std.testing.expectEqual(@as(usize, 0), r1.next.y);
- try std.testing.expect(!r1.done);
-
- // Wall hit
- const r2 = env.step(.{ .x = 0, .y = 1 }, .right);
- // (1,1) is wall, should stay at (0,1)
- try std.testing.expectEqual(@as(usize, 0), r2.next.x);
- try std.testing.expectEqual(@as(usize, 1), r2.next.y);
-
- // Boundary hit
- const r3 = env.step(.{ .x = 0, .y = 0 }, .up);
- try std.testing.expectEqual(@as(usize, 0), r3.next.x);
- try std.testing.expectEqual(@as(usize, 0), r3.next.y);
-
- // Goal reached
- const r4 = env.step(.{ .x = 3, .y = 4 }, .right);
- try std.testing.expect(r4.done);
- try std.testing.expect(r4.reward > 0);
-}
-
-test "HDCRLAgent learnEpisode updates prototypes" {
- const allocator = std.testing.allocator;
- var agent = HDCRLAgent.init(allocator, 8000, 42);
- defer agent.deinit();
-
- // Fake trajectory: go right from (0,0) β (1,0) then get reward
- const trajectory = [_]HDCRLAgent.Transition{
- .{ .state = .{ .x = 0, .y = 0 }, .action = .right, .reward = -0.1 },
- .{ .state = .{ .x = 1, .y = 0 }, .action = .right, .reward = -0.1 },
- .{ .state = .{ .x = 2, .y = 0 }, .action = .right, .reward = 10.0 },
- };
-
- try agent.learnEpisode(&trajectory);
-
- // "right" action should now have positive prototype
- try std.testing.expect(agent.action_pos_protos[@intFromEnum(HDCRLAgent.Action.right)] != null);
- try std.testing.expectEqual(@as(usize, 1), agent.total_episodes);
-}
-
-test "HDCRLAgent Q-values differentiate after learning" {
- const allocator = std.testing.allocator;
- var agent = HDCRLAgent.initWithConfig(allocator, 8000, 42, 0.99, 0.0, 1.0, 0.0);
- defer agent.deinit();
-
- // Train: going right from (0,0) is good
- const good_traj = [_]HDCRLAgent.Transition{
- .{ .state = .{ .x = 0, .y = 0 }, .action = .right, .reward = 10.0 },
- };
- try agent.learnEpisode(&good_traj);
-
- // Train: going left from (0,0) is bad
- const bad_traj = [_]HDCRLAgent.Transition{
- .{ .state = .{ .x = 0, .y = 0 }, .action = .left, .reward = -5.0 },
- };
- try agent.learnEpisode(&bad_traj);
-
- const qv = try agent.getQValue(.{ .x = 0, .y = 0 });
- // Q(right) should be higher than Q(left)
- try std.testing.expect(qv[@intFromEnum(HDCRLAgent.Action.right)] > qv[@intFromEnum(HDCRLAgent.Action.left)]);
-}
-
-test "HDCRLAgent selectAction respects epsilon" {
- const allocator = std.testing.allocator;
- // epsilon=1.0 β always random
- var agent_explore = HDCRLAgent.initWithConfig(allocator, 8000, 42, 0.99, 1.0, 1.0, 1.0);
- defer agent_explore.deinit();
-
- // With epsilon=1.0, selectAction should still return valid actions
- for (0..10) |_| {
- const action = try agent_explore.selectAction(.{ .x = 0, .y = 0 });
- try std.testing.expect(@intFromEnum(action) <= 3);
- }
-}
-
-test "HDCRLAgent runEpisode on gridworld" {
- const allocator = std.testing.allocator;
- var agent = HDCRLAgent.initWithConfig(allocator, 8000, 42, 0.99, 1.0, 1.0, 1.0);
- defer agent.deinit();
-
- const env = makeGridworld();
- const result = try agent.runEpisode(env, 100);
- defer allocator.free(result.trajectory);
-
- try std.testing.expect(result.stats.steps > 0);
- try std.testing.expect(result.stats.steps <= 100);
-}
-
-test "HDCRLAgent trainGridworld improves over episodes" {
- const allocator = std.testing.allocator;
- var agent = HDCRLAgent.initWithConfig(allocator, 8000, 42, 0.99, 0.5, 0.99, 0.05);
- defer agent.deinit();
-
- const env = makeGridworld();
-
- // Train for 200 episodes
- try agent.trainGridworld(env, 200, 50);
-
- // Evaluate learned policy
- const eval_result = try agent.evaluatePolicy(env, 50);
-
- // After 200 episodes, agent should have some knowledge
- try std.testing.expect(agent.total_episodes == 200);
- // At least some action should have prototypes
- var has_proto = false;
- for (agent.action_pos_protos) |p| {
- if (p != null) has_proto = true;
- }
- try std.testing.expect(has_proto);
-
- _ = eval_result;
-}
-
-test "HDCRLAgent gridworld RL demo" {
- const allocator = std.testing.allocator;
- // High initial epsilon for exploration, fast decay
- var agent = HDCRLAgent.initWithConfig(allocator, 8000, 42, 0.95, 0.8, 0.995, 0.01);
- defer agent.deinit();
-
- // Simple 3x3 grid β easier for random exploration to find goal
- // S . .
- // . . .
- // . . G
- const no_walls = [_]HDCRLAgent.State{};
- const env = HDCRLAgent.Gridworld{
- .width = 3,
- .height = 3,
- .walls = &no_walls,
- .goal = .{ .x = 2, .y = 2 },
- .start = .{ .x = 0, .y = 0 },
- .step_reward = -0.1,
- .goal_reward = 10.0,
- .wall_penalty = -0.5,
- };
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC REINFORCEMENT LEARNING β GRIDWORLD DEMO\n", .{});
- std.debug.print(" dim=8000, gamma=0.95\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Grid: 3x3, Start=(0,0), Goal=(2,2), no walls\n", .{});
- std.debug.print(" Rewards: goal=+10, step=-0.1, wall=-0.5\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Train in phases
- const phases = [_]usize{ 200, 300, 500 };
- var total_trained: usize = 0;
- for (phases) |n| {
- try agent.trainGridworld(env, n, 30);
- total_trained += n;
- const eval_result = try agent.evaluatePolicy(env, 30);
- const goal_str: []const u8 = if (eval_result.reached_goal) "YES" else "NO";
- std.debug.print(" After {d:4} episodes: reward={d:7.2} steps={d:2} goal={s} eps={d:.3}\n", .{
- total_trained,
- eval_result.total_reward,
- eval_result.steps,
- goal_str,
- agent.epsilon,
- });
- }
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Learned Policy:\n", .{});
- try agent.printPolicy(env);
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Q-Values:\n", .{});
- try agent.printQValues(env);
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // After 1000 episodes, agent should have learned something
- try std.testing.expect(agent.total_episodes == 1000);
-
- // Check if Q-values near goal are correct direction
- // At (2,1), going down should have highest Q (leads to goal)
- const qv_21 = try agent.getQValue(.{ .x = 2, .y = 1 });
- // At (1,2), going right should have highest Q (leads to goal)
- const qv_12 = try agent.getQValue(.{ .x = 1, .y = 2 });
- // Print for diagnostic
- std.debug.print(" Goal-adjacent Q: (2,1) D={d:.3} | (1,2) R={d:.3}\n", .{
- qv_21[@intFromEnum(HDCRLAgent.Action.down)],
- qv_12[@intFromEnum(HDCRLAgent.Action.right)],
- });
-
- // At minimum, the agent should have positive prototypes
- var has_pos = false;
- for (agent.action_pos_protos) |p| {
- if (p != null) has_pos = true;
- }
- try std.testing.expect(has_pos);
-}
-
-// ============================================================================
-// HDC Federated Learning
-// ============================================================================
-// Privacy-preserving distributed classification via prototype aggregation.
-// Multiple nodes train locally, share only prototypes, never raw data.
-// ============================================================================
-
-pub const HDCFederatedCoordinator = struct {
- allocator: std.mem.Allocator,
- dimension: usize,
- seed: u64,
- mode: HDCTextEncoder.EncodingMode,
-
- // Node prototypes: node_id β (class_label β (prototype_hv, sample_count))
- nodes: std.ArrayListUnmanaged(NodeModel),
-
- // Global aggregated model
- global_protos: std.StringHashMapUnmanaged(AggregatedProto),
-
- // Stats
- rounds_completed: usize,
-
- const Self = @This();
-
- pub const AggregatedProto = struct {
- prototype_hv: *HybridBigInt,
- total_samples: u32,
- };
-
- pub const NodeProto = struct {
- prototype_hv: HybridBigInt,
- sample_count: u32,
- };
-
- pub const NodeModel = struct {
- node_id: []const u8, // owned
- classes: std.StringHashMapUnmanaged(NodeProto), // label β proto (labels owned)
- total_samples: u32,
- };
-
- pub const AggregationStrategy = enum {
- simple_bundle, // Equal weight per node
- weighted_bundle, // Weight by sample count (repeated bundling)
- };
-
- pub const FederatedStats = struct {
- num_nodes: usize,
- num_classes: usize,
- total_samples: u32,
- rounds_completed: usize,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithMode(allocator, dimension, seed, .hybrid);
- }
-
- pub fn initWithMode(allocator: std.mem.Allocator, dimension: usize, seed: u64, mode: HDCTextEncoder.EncodingMode) Self {
- return Self{
- .allocator = allocator,
- .dimension = dimension,
- .seed = seed,
- .mode = mode,
- .nodes = .{},
- .global_protos = .{},
- .rounds_completed = 0,
- };
- }
-
- pub fn deinit(self: *Self) void {
- // Free nodes
- for (self.nodes.items) |*node| {
- self.allocator.free(node.node_id);
- var it = node.classes.iterator();
- while (it.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- node.classes.deinit(self.allocator);
- }
- self.nodes.deinit(self.allocator);
-
- // Free global protos
- var git = self.global_protos.iterator();
- while (git.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.prototype_hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.global_protos.deinit(self.allocator);
- }
-
- /// Create a new node classifier. Caller must deinit it.
- /// All nodes share the same seed β identical ItemMemory β consistent encoding.
- pub fn createNode(self: *Self) HDCClassifier {
- return HDCClassifier.initWithMode(self.allocator, self.dimension, self.seed, self.mode);
- }
-
- /// Register a trained node's prototypes for future aggregation.
- /// Copies the prototypes from the classifier (does NOT take ownership).
- pub fn registerNode(self: *Self, node_id: []const u8, classifier: *HDCClassifier) !void {
- classifier.fixSelfRef();
-
- var node_classes = std.StringHashMapUnmanaged(NodeProto){};
-
- var it = classifier.classes.iterator();
- while (it.next()) |entry| {
- const label_copy = try self.allocator.dupe(u8, entry.key_ptr.*);
- try node_classes.put(self.allocator, label_copy, NodeProto{
- .prototype_hv = entry.value_ptr.prototype_hv.*,
- .sample_count = entry.value_ptr.sample_count,
- });
- }
-
- try self.nodes.append(self.allocator, NodeModel{
- .node_id = try self.allocator.dupe(u8, node_id),
- .classes = node_classes,
- .total_samples = classifier.total_samples,
- });
- }
-
- /// Aggregate all registered node prototypes into a global model.
- pub fn aggregate(self: *Self, strategy: AggregationStrategy) !void {
- // Clear old global protos
- var old_it = self.global_protos.iterator();
- while (old_it.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.prototype_hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.global_protos.clearRetainingCapacity();
-
- // Collect all class labels across all nodes
- var all_labels = std.StringHashMapUnmanaged(void){};
- defer all_labels.deinit(self.allocator);
-
- for (self.nodes.items) |node| {
- var it = node.classes.iterator();
- while (it.next()) |entry| {
- if (!all_labels.contains(entry.key_ptr.*)) {
- try all_labels.put(self.allocator, entry.key_ptr.*, {});
- }
- }
- }
-
- // For each class, aggregate prototypes from all nodes that have it
- var label_it = all_labels.iterator();
- while (label_it.next()) |label_entry| {
- const label = label_entry.key_ptr.*;
- var aggregated: ?HybridBigInt = null;
- var total_samples: u32 = 0;
-
- for (self.nodes.items) |node| {
- if (node.classes.get(label)) |node_proto| {
- switch (strategy) {
- .simple_bundle => {
- // Equal weight: bundle once per node
- if (aggregated) |*acc| {
- var np = node_proto.prototype_hv;
- acc.* = vsa.bundle2(acc, &np);
- } else {
- aggregated = node_proto.prototype_hv;
- }
- },
- .weighted_bundle => {
- // Weight by sample count: bundle multiple times
- // More samples β more influence
- const weight = @max(1, node_proto.sample_count);
- var np = node_proto.prototype_hv;
- if (aggregated) |*acc| {
- for (0..weight) |_| {
- acc.* = vsa.bundle2(acc, &np);
- }
- } else {
- aggregated = np;
- // Bundle (weight-1) more times
- for (1..weight) |_| {
- aggregated.? = vsa.bundle2(&aggregated.?, &np);
- }
- }
- },
- }
- total_samples += node_proto.sample_count;
- }
- }
-
- if (aggregated) |agg_hv| {
- const proto_hv = try self.allocator.create(HybridBigInt);
- proto_hv.* = agg_hv;
- const label_copy = try self.allocator.dupe(u8, label);
- try self.global_protos.put(self.allocator, label_copy, AggregatedProto{
- .prototype_hv = proto_hv,
- .total_samples = total_samples,
- });
- }
- }
-
- self.rounds_completed += 1;
- }
-
- /// Build a global HDCClassifier from aggregated prototypes.
- /// Caller must deinit the returned classifier.
- pub fn buildGlobalClassifier(self: *Self) !HDCClassifier {
- var clf = HDCClassifier.initWithMode(self.allocator, self.dimension, self.seed, self.mode);
- clf.fixSelfRef();
-
- var it = self.global_protos.iterator();
- while (it.next()) |entry| {
- const label_copy = try self.allocator.dupe(u8, entry.key_ptr.*);
- const proto_hv = try self.allocator.create(HybridBigInt);
- proto_hv.* = entry.value_ptr.prototype_hv.*;
-
- try clf.classes.put(self.allocator, label_copy, HDCClassifier.ClassPrototype{
- .prototype_hv = proto_hv,
- .sample_count = entry.value_ptr.total_samples,
- });
- clf.total_samples += entry.value_ptr.total_samples;
- }
-
- return clf;
- }
-
- /// Evaluate global model accuracy on test data.
- pub fn evaluateGlobal(self: *Self, test_data: []const HDCClassifier.TrainSample) !f64 {
- var clf = try self.buildGlobalClassifier();
- defer clf.deinit();
-
- var correct: usize = 0;
- for (test_data) |sample| {
- if (try clf.predict(sample.text)) |pred| {
- if (std.mem.eql(u8, pred.label, sample.label)) {
- correct += 1;
- }
- }
- }
-
- return @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(test_data.len));
- }
-
- /// Get federation statistics.
- pub fn stats(self: *Self) FederatedStats {
- var total: u32 = 0;
- for (self.nodes.items) |node| {
- total += node.total_samples;
- }
- return FederatedStats{
- .num_nodes = self.nodes.items.len,
- .num_classes = self.global_protos.count(),
- .total_samples = total,
- .rounds_completed = self.rounds_completed,
- };
- }
-};
-
-// ============================================================================
-// HDCFederatedCoordinator Tests
-// ============================================================================
-
-test "HDCFederated basic two-node aggregation" {
- const allocator = std.testing.allocator;
- var coord = HDCFederatedCoordinator.init(allocator, 8000, 42);
- defer coord.deinit();
-
- // Node 1: trains on sports
- var node1 = coord.createNode();
- defer node1.deinit();
- try node1.train("sports", "football soccer goal team match");
- try node1.train("sports", "basketball court dunk score player");
- try node1.train("tech", "computer software algorithm code program");
-
- // Node 2: trains on tech (has more tech data)
- var node2 = coord.createNode();
- defer node2.deinit();
- try node2.train("tech", "database server network cloud system");
- try node2.train("tech", "algorithm code software developer engineering");
- try node2.train("sports", "tennis racket serve volley court");
-
- // Register both nodes
- try coord.registerNode("node_1", &node1);
- try coord.registerNode("node_2", &node2);
-
- // Aggregate
- try coord.aggregate(.simple_bundle);
-
- const s = coord.stats();
- try std.testing.expectEqual(@as(usize, 2), s.num_nodes);
- try std.testing.expectEqual(@as(usize, 2), s.num_classes);
- try std.testing.expectEqual(@as(usize, 1), s.rounds_completed);
-
- // Build global model and test
- var global = try coord.buildGlobalClassifier();
- defer global.deinit();
-
- // Should classify sports correctly
- const pred_sports = (try global.predict("football goal team")).?;
- try std.testing.expect(std.mem.eql(u8, pred_sports.label, "sports"));
-
- // Should classify tech correctly
- const pred_tech = (try global.predict("database server network")).?;
- try std.testing.expect(std.mem.eql(u8, pred_tech.label, "tech"));
-}
-
-test "HDCFederated global better than individual nodes" {
- const allocator = std.testing.allocator;
- var coord = HDCFederatedCoordinator.init(allocator, 8000, 42);
- defer coord.deinit();
-
- // Node 1: only sees sports class A and tech class A
- var node1 = coord.createNode();
- defer node1.deinit();
- try node1.train("sports", "football soccer goal team match");
- try node1.train("sports", "basketball court dunk score player");
-
- // Node 2: only sees sports class B and tech
- var node2 = coord.createNode();
- defer node2.deinit();
- try node2.train("sports", "tennis racket serve volley court");
- try node2.train("tech", "computer software algorithm code program");
- try node2.train("tech", "database server network cloud system");
-
- try coord.registerNode("node_1", &node1);
- try coord.registerNode("node_2", &node2);
- try coord.aggregate(.simple_bundle);
-
- // Test on data neither node saw alone
- const test_data = [_]HDCClassifier.TrainSample{
- .{ .label = "sports", .text = "football goal score" },
- .{ .label = "sports", .text = "tennis serve ace" },
- .{ .label = "tech", .text = "software code algorithm" },
- .{ .label = "tech", .text = "database network server" },
- };
-
- // Global model should do well on combined knowledge
- const global_acc = try coord.evaluateGlobal(&test_data);
- try std.testing.expect(global_acc >= 0.5); // At least 50%
-
- // Node 1 alone: no tech class trained
- // Node 2: incomplete sports
- // Global: has both β should be better overall
-}
-
-test "HDCFederated weighted aggregation" {
- const allocator = std.testing.allocator;
- var coord = HDCFederatedCoordinator.init(allocator, 8000, 42);
- defer coord.deinit();
-
- // Node 1: lots of sports data
- var node1 = coord.createNode();
- defer node1.deinit();
- try node1.train("sports", "football soccer goal team match");
- try node1.train("sports", "basketball court dunk score player");
- try node1.train("sports", "tennis racket serve volley court");
- try node1.train("sports", "cricket bat ball wicket pitch");
-
- // Node 2: little sports data but lots of tech
- var node2 = coord.createNode();
- defer node2.deinit();
- try node2.train("sports", "hockey stick puck ice rink");
- try node2.train("tech", "computer software algorithm code program");
- try node2.train("tech", "database server network cloud system");
- try node2.train("tech", "machine learning neural network training");
- try node2.train("tech", "compiler debugger runtime code developer");
-
- try coord.registerNode("node_1", &node1);
- try coord.registerNode("node_2", &node2);
-
- // Weighted: node 1's sports (4 samples) weighs more than node 2's (1 sample)
- try coord.aggregate(.weighted_bundle);
-
- var global = try coord.buildGlobalClassifier();
- defer global.deinit();
-
- // Sports: node1 had 4 samples, should dominate sports prototype
- const pred = (try global.predict("football soccer goal")).?;
- try std.testing.expect(std.mem.eql(u8, pred.label, "sports"));
-}
-
-test "HDCFederated three nodes non-IID data" {
- const allocator = std.testing.allocator;
- var coord = HDCFederatedCoordinator.init(allocator, 8000, 42);
- defer coord.deinit();
-
- // Node 1: hospital (medical data only)
- var node1 = coord.createNode();
- defer node1.deinit();
- try node1.train("medical", "patient diagnosis treatment surgery hospital");
- try node1.train("medical", "prescription medicine dosage pharmacy drug");
-
- // Node 2: law firm (legal data only)
- var node2 = coord.createNode();
- defer node2.deinit();
- try node2.train("legal", "court judge jury verdict trial lawyer");
- try node2.train("legal", "contract agreement clause liability dispute");
-
- // Node 3: tech startup (tech data only)
- var node3 = coord.createNode();
- defer node3.deinit();
- try node3.train("tech", "software engineering code algorithm deployment");
- try node3.train("tech", "database api endpoint server microservice");
-
- try coord.registerNode("hospital", &node1);
- try coord.registerNode("lawfirm", &node2);
- try coord.registerNode("startup", &node3);
- try coord.aggregate(.simple_bundle);
-
- const s = coord.stats();
- try std.testing.expectEqual(@as(usize, 3), s.num_nodes);
- try std.testing.expectEqual(@as(usize, 3), s.num_classes);
-
- // Global model has all 3 domains β no single node has this
- var global = try coord.buildGlobalClassifier();
- defer global.deinit();
-
- const pred_med = (try global.predict("patient surgery hospital")).?;
- try std.testing.expect(std.mem.eql(u8, pred_med.label, "medical"));
-
- const pred_legal = (try global.predict("court judge trial verdict")).?;
- try std.testing.expect(std.mem.eql(u8, pred_legal.label, "legal"));
-
- const pred_tech = (try global.predict("software api database code")).?;
- try std.testing.expect(std.mem.eql(u8, pred_tech.label, "tech"));
-}
-
-test "HDCFederated empty aggregation safe" {
- const allocator = std.testing.allocator;
- var coord = HDCFederatedCoordinator.init(allocator, 8000, 42);
- defer coord.deinit();
-
- // Aggregate with no nodes β no crash
- try coord.aggregate(.simple_bundle);
- try std.testing.expectEqual(@as(usize, 0), coord.global_protos.count());
-}
-
-test "HDCFederated multiple rounds" {
- const allocator = std.testing.allocator;
- var coord = HDCFederatedCoordinator.init(allocator, 8000, 42);
- defer coord.deinit();
-
- // Round 1
- var node1 = coord.createNode();
- defer node1.deinit();
- try node1.train("A", "alpha beta gamma delta");
- try coord.registerNode("round1", &node1);
- try coord.aggregate(.simple_bundle);
- try std.testing.expectEqual(@as(usize, 1), coord.rounds_completed);
-
- // Round 2 (re-aggregate with new node)
- var node2 = coord.createNode();
- defer node2.deinit();
- try node2.train("B", "epsilon zeta eta theta");
- try coord.registerNode("round2", &node2);
- try coord.aggregate(.simple_bundle);
- try std.testing.expectEqual(@as(usize, 2), coord.rounds_completed);
-
- // Global should now have both classes
- try std.testing.expectEqual(@as(usize, 2), coord.global_protos.count());
-}
-
-test "HDCFederated privacy-preserving FL demo" {
- const allocator = std.testing.allocator;
- var coord = HDCFederatedCoordinator.init(allocator, 8000, 42);
- defer coord.deinit();
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC FEDERATED LEARNING β PRIVACY-PRESERVING DEMO\n", .{});
- std.debug.print(" dim=8000, mode=hybrid, strategy=simple_bundle\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // 3 hospitals, each with private patient data
- // Class: disease type based on symptom descriptions
- var hospital_a = coord.createNode();
- defer hospital_a.deinit();
- try hospital_a.train("flu", "fever cough fatigue headache body ache");
- try hospital_a.train("flu", "chills sweating runny nose sore throat");
- try hospital_a.train("flu", "congestion muscle pain fever tired");
- try hospital_a.train("allergy", "sneezing itchy eyes runny nose rash");
- try hospital_a.train("allergy", "hives swelling watery eyes congestion");
-
- var hospital_b = coord.createNode();
- defer hospital_b.deinit();
- try hospital_b.train("flu", "high temperature cough body ache fatigue");
- try hospital_b.train("flu", "fever weakness headache sore throat chills");
- try hospital_b.train("covid", "loss taste smell fever cough breathing");
- try hospital_b.train("covid", "difficulty breathing fever dry cough fatigue");
-
- var hospital_c = coord.createNode();
- defer hospital_c.deinit();
- try hospital_c.train("allergy", "seasonal pollen sneezing itchy watery");
- try hospital_c.train("allergy", "dust mite reaction sneezing congestion");
- try hospital_c.train("covid", "fever cough shortness breath loss smell");
- try hospital_c.train("covid", "oxygen low fever persistent cough taste");
-
- // Register nodes (only prototypes shared, not patient data!)
- try coord.registerNode("Hospital_A", &hospital_a);
- try coord.registerNode("Hospital_B", &hospital_b);
- try coord.registerNode("Hospital_C", &hospital_c);
-
- std.debug.print(" Nodes registered: 3 hospitals\n", .{});
- std.debug.print(" Privacy: ONLY prototypes shared, never raw symptoms\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Aggregate
- try coord.aggregate(.simple_bundle);
-
- // Test data (new patients, unseen by any hospital)
- const test_data = [_]HDCClassifier.TrainSample{
- .{ .label = "flu", .text = "fever headache cough body ache" },
- .{ .label = "flu", .text = "chills fatigue sore throat fever" },
- .{ .label = "allergy", .text = "sneezing itchy eyes congestion" },
- .{ .label = "allergy", .text = "hives rash watery eyes" },
- .{ .label = "covid", .text = "loss smell taste fever cough" },
- .{ .label = "covid", .text = "breathing difficulty fever cough" },
- };
-
- // Evaluate each node individually
- var node1_correct: usize = 0;
- var node2_correct: usize = 0;
- var node3_correct: usize = 0;
-
- for (test_data) |sample| {
- if (try hospital_a.predict(sample.text)) |p| {
- if (std.mem.eql(u8, p.label, sample.label)) node1_correct += 1;
- }
- if (try hospital_b.predict(sample.text)) |p| {
- if (std.mem.eql(u8, p.label, sample.label)) node2_correct += 1;
- }
- if (try hospital_c.predict(sample.text)) |p| {
- if (std.mem.eql(u8, p.label, sample.label)) node3_correct += 1;
- }
- }
-
- const global_acc = try coord.evaluateGlobal(&test_data);
-
- std.debug.print(" Individual Node Accuracy:\n", .{});
- std.debug.print(" Hospital A: {d}/{d} ({d:.0}%) β has flu + allergy\n", .{
- node1_correct, test_data.len,
- @as(f64, @floatFromInt(node1_correct)) / @as(f64, @floatFromInt(test_data.len)) * 100.0,
- });
- std.debug.print(" Hospital B: {d}/{d} ({d:.0}%) β has flu + covid\n", .{
- node2_correct, test_data.len,
- @as(f64, @floatFromInt(node2_correct)) / @as(f64, @floatFromInt(test_data.len)) * 100.0,
- });
- std.debug.print(" Hospital C: {d}/{d} ({d:.0}%) β has allergy + covid\n", .{
- node3_correct, test_data.len,
- @as(f64, @floatFromInt(node3_correct)) / @as(f64, @floatFromInt(test_data.len)) * 100.0,
- });
- std.debug.print(" ββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" GLOBAL FEDERATED: {d:.0}%\n", .{global_acc * 100.0});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const s = coord.stats();
- std.debug.print(" Nodes: {d} | Classes: {d} | Samples: {d} | Rounds: {d}\n", .{
- s.num_nodes, s.num_classes, s.total_samples, s.rounds_completed,
- });
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Global should have 3 classes (flu, allergy, covid)
- try std.testing.expectEqual(@as(usize, 3), s.num_classes);
- // Global should be at least as good as best individual node
- const best_individual = @max(@max(
- @as(f64, @floatFromInt(node1_correct)),
- @as(f64, @floatFromInt(node2_correct)),
- ), @as(f64, @floatFromInt(node3_correct))) / @as(f64, @floatFromInt(test_data.len));
- try std.testing.expect(global_acc >= best_individual);
-}
-
-// ============================================================================
-// HDC Few-Shot Meta-Learner
-// ============================================================================
-// K-shot classification with prototype rectification.
-// Removes shared background from prototypes to improve separation.
-// ============================================================================
-
-pub const HDCFewShotLearner = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- // Original prototypes
- prototypes: std.StringHashMapUnmanaged(Proto),
-
- // Rectified prototypes (computed by rectify())
- rectified: std.StringHashMapUnmanaged(*HybridBigInt),
- is_rectified: bool,
-
- const Self = @This();
-
- pub const Proto = struct {
- hv: *HybridBigInt,
- sample_count: u32,
- };
-
- pub const LabeledSample = struct {
- text: []const u8,
- label: []const u8,
- };
-
- pub const FewShotResult = struct {
- accuracy: f64,
- num_classes: usize,
- k_per_class: usize,
- rectified: bool,
- correct: usize,
- total: usize,
- };
-
- pub const RectificationStats = struct {
- avg_inter_class_sim_before: f64,
- avg_inter_class_sim_after: f64,
- improvement: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .prototypes = .{},
- .rectified = .{},
- .is_rectified = false,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .hybrid);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.prototypes.deinit(self.allocator);
-
- self.clearRectified();
- self.rectified.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- fn clearRectified(self: *Self) void {
- var it = self.rectified.iterator();
- while (it.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.*);
- self.allocator.free(entry.key_ptr.*);
- }
- self.rectified.clearRetainingCapacity();
- self.is_rectified = false;
- }
-
- /// Train from K-shot support set.
- pub fn trainKShot(self: *Self, support: []const LabeledSample) !void {
- self.fixSelfRef();
- self.clearRectified();
-
- for (support) |sample| {
- var text_hv = try self.encoder.encodeText(sample.text);
-
- if (self.prototypes.getPtr(sample.label)) |proto| {
- proto.hv.* = vsa.bundle2(proto.hv, &text_hv);
- proto.sample_count += 1;
- } else {
- const hv = try self.allocator.create(HybridBigInt);
- hv.* = text_hv;
- const label_copy = try self.allocator.dupe(u8, sample.label);
- try self.prototypes.put(self.allocator, label_copy, Proto{
- .hv = hv,
- .sample_count = 1,
- });
- }
- }
- }
-
- /// Compute centroid of all prototypes (per-trit majority vote).
- fn computeCentroid(self: *Self) !*HybridBigInt {
- const centroid = try self.allocator.create(HybridBigInt);
- centroid.* = HybridBigInt.zero();
- centroid.mode = .unpacked_mode;
- centroid.trit_len = self.dimension;
- centroid.dirty = true;
-
- const num_classes = self.prototypes.count();
- if (num_classes == 0) return centroid;
-
- // Sum trits across all prototypes
- const sums = try self.allocator.alloc(i32, self.dimension);
- defer self.allocator.free(sums);
- @memset(sums, 0);
-
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- for (0..self.dimension) |t| {
- sums[t] += entry.value_ptr.hv.unpacked_cache[t];
- }
- }
-
- // Sign function: centroid[t] = sign(sum[t])
- for (0..self.dimension) |t| {
- if (sums[t] > 0) {
- centroid.unpacked_cache[t] = 1;
- } else if (sums[t] < 0) {
- centroid.unpacked_cache[t] = -1;
- } else {
- centroid.unpacked_cache[t] = 0;
- }
- }
-
- return centroid;
- }
-
- /// Rectify prototypes via discriminative dimension selection.
- /// For each trit position: if ALL prototypes agree β zero it (non-discriminative).
- /// If prototypes disagree β keep original values (discriminative).
- /// In ternary VSA, this works better than centroid subtraction.
- pub fn rectify(self: *Self) !void {
- self.fixSelfRef();
- self.clearRectified();
-
- const num_classes = self.prototypes.count();
- if (num_classes < 2) {
- // With 0 or 1 class, just copy originals
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- const rect_hv = try self.allocator.create(HybridBigInt);
- rect_hv.* = entry.value_ptr.hv.*;
- const label_copy = try self.allocator.dupe(u8, entry.key_ptr.*);
- try self.rectified.put(self.allocator, label_copy, rect_hv);
- }
- self.is_rectified = true;
- return;
- }
-
- // Collect prototype pointers for dimension-wise comparison
- const proto_hvs = try self.allocator.alloc(*HybridBigInt, num_classes);
- defer self.allocator.free(proto_hvs);
- {
- var it = self.prototypes.iterator();
- var idx: usize = 0;
- while (it.next()) |entry| {
- proto_hvs[idx] = entry.value_ptr.hv;
- idx += 1;
- }
- }
-
- // For each dimension, check if all prototypes agree
- const is_discriminative = try self.allocator.alloc(bool, self.dimension);
- defer self.allocator.free(is_discriminative);
-
- for (0..self.dimension) |t| {
- const first_val = proto_hvs[0].unpacked_cache[t];
- var all_agree = true;
- for (1..num_classes) |c| {
- if (proto_hvs[c].unpacked_cache[t] != first_val) {
- all_agree = false;
- break;
- }
- }
- is_discriminative[t] = !all_agree;
- }
-
- // Build rectified prototypes: zero out non-discriminative dimensions
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- const rect_hv = try self.allocator.create(HybridBigInt);
- rect_hv.* = HybridBigInt.zero();
- rect_hv.mode = .unpacked_mode;
- rect_hv.trit_len = self.dimension;
- rect_hv.dirty = true;
-
- for (0..self.dimension) |t| {
- if (is_discriminative[t]) {
- rect_hv.unpacked_cache[t] = entry.value_ptr.hv.unpacked_cache[t];
- } else {
- rect_hv.unpacked_cache[t] = 0;
- }
- }
-
- const label_copy = try self.allocator.dupe(u8, entry.key_ptr.*);
- try self.rectified.put(self.allocator, label_copy, rect_hv);
- }
-
- self.is_rectified = true;
- }
-
- /// Predict using rectified prototypes (if available) or originals.
- pub fn predict(self: *Self, text: []const u8) !?struct { label: []const u8, confidence: f64 } {
- self.fixSelfRef();
-
- var text_hv = try self.encoder.encodeText(text);
-
- // Use rectified if available, else originals
- const use_rectified = self.is_rectified;
-
- var best_label: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- if (use_rectified) {
- var it = self.rectified.iterator();
- while (it.next()) |entry| {
- const sim = vsa.cosineSimilarity(&text_hv, entry.value_ptr.*);
- if (sim > best_sim) {
- best_sim = sim;
- best_label = entry.key_ptr.*;
- }
- }
- } else {
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- const sim = vsa.cosineSimilarity(&text_hv, entry.value_ptr.hv);
- if (sim > best_sim) {
- best_sim = sim;
- best_label = entry.key_ptr.*;
- }
- }
- }
-
- if (best_label.len == 0) return null;
- return .{ .label = best_label, .confidence = best_sim };
- }
-
- /// Evaluate on a query set.
- pub fn evaluate(self: *Self, query: []const LabeledSample) !FewShotResult {
- var correct: usize = 0;
- for (query) |sample| {
- if (try self.predict(sample.text)) |pred| {
- if (std.mem.eql(u8, pred.label, sample.label)) {
- correct += 1;
- }
- }
- }
-
- // Compute k_per_class (approximate)
- var min_k: u32 = std.math.maxInt(u32);
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- if (entry.value_ptr.sample_count < min_k) min_k = entry.value_ptr.sample_count;
- }
-
- return FewShotResult{
- .accuracy = @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(query.len)),
- .num_classes = self.prototypes.count(),
- .k_per_class = if (min_k == std.math.maxInt(u32)) 0 else min_k,
- .rectified = self.is_rectified,
- .correct = correct,
- .total = query.len,
- };
- }
-
- /// Measure the effect of rectification on inter-class similarity.
- pub fn measureRectification(self: *Self) !RectificationStats {
- self.fixSelfRef();
-
- // Compute avg inter-class similarity BEFORE rectification
- const before = try self.avgInterClassSim(false);
-
- // Ensure rectified protos exist
- if (!self.is_rectified) {
- try self.rectify();
- }
-
- const after = try self.avgInterClassSim(true);
-
- return RectificationStats{
- .avg_inter_class_sim_before = before,
- .avg_inter_class_sim_after = after,
- .improvement = before - after,
- };
- }
-
- fn avgInterClassSim(self: *Self, use_rectified: bool) !f64 {
- // Collect all prototype HVs
- var hvs = std.ArrayListUnmanaged(*HybridBigInt){};
- defer hvs.deinit(self.allocator);
-
- if (use_rectified) {
- var it = self.rectified.iterator();
- while (it.next()) |entry| {
- try hvs.append(self.allocator, entry.value_ptr.*);
- }
- } else {
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- try hvs.append(self.allocator, entry.value_ptr.hv);
- }
- }
-
- if (hvs.items.len < 2) return 0.0;
-
- var total_sim: f64 = 0;
- var count: usize = 0;
- for (0..hvs.items.len) |i| {
- for (i + 1..hvs.items.len) |j| {
- total_sim += vsa.cosineSimilarity(hvs.items[i], hvs.items[j]);
- count += 1;
- }
- }
-
- return if (count > 0) total_sim / @as(f64, @floatFromInt(count)) else 0.0;
- }
-
- /// Reset all prototypes.
- pub fn reset(self: *Self) void {
- var it = self.prototypes.iterator();
- while (it.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.prototypes.clearRetainingCapacity();
- self.clearRectified();
- }
-};
-
-// ============================================================================
-// HDCFewShotLearner Tests
-// ============================================================================
-
-test "HDCFewShot one-shot classification" {
- const allocator = std.testing.allocator;
- var learner = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner.deinit();
-
- // 1-shot: one example per class
- const support = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "cat dog pet animal furry", .label = "animals" },
- .{ .text = "car truck bus vehicle motor", .label = "vehicles" },
- };
- try learner.trainKShot(&support);
-
- // Test
- const pred_a = (try learner.predict("kitten puppy creature")).?;
- try std.testing.expect(std.mem.eql(u8, pred_a.label, "animals"));
-
- const pred_v = (try learner.predict("train plane ship transport")).?;
- try std.testing.expect(std.mem.eql(u8, pred_v.label, "vehicles"));
-}
-
-test "HDCFewShot rectification reduces inter-class similarity" {
- const allocator = std.testing.allocator;
- var learner = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner.deinit();
-
- const support = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "cat dog pet animal", .label = "animals" },
- .{ .text = "car truck vehicle motor", .label = "vehicles" },
- .{ .text = "apple banana fruit orange", .label = "food" },
- };
- try learner.trainKShot(&support);
-
- const stats = try learner.measureRectification();
-
- // Rectification should reduce inter-class similarity
- try std.testing.expect(stats.avg_inter_class_sim_after <= stats.avg_inter_class_sim_before);
- try std.testing.expect(stats.improvement >= 0.0);
-}
-
-test "HDCFewShot rectification improves accuracy" {
- const allocator = std.testing.allocator;
-
- // Test WITHOUT rectification
- var learner_no_rect = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner_no_rect.deinit();
-
- const support = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "football soccer goal team match", .label = "sports" },
- .{ .text = "basketball court dunk score", .label = "sports" },
- .{ .text = "computer software code algorithm", .label = "tech" },
- .{ .text = "database server network cloud", .label = "tech" },
- .{ .text = "patient diagnosis hospital surgery", .label = "medical" },
- .{ .text = "medicine prescription treatment drug", .label = "medical" },
- };
- try learner_no_rect.trainKShot(&support);
-
- const query = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "football goal score win", .label = "sports" },
- .{ .text = "tennis racket serve ace", .label = "sports" },
- .{ .text = "code program developer engineering", .label = "tech" },
- .{ .text = "api endpoint http server", .label = "tech" },
- .{ .text = "doctor nurse clinic treatment", .label = "medical" },
- .{ .text = "surgery operation recovery ward", .label = "medical" },
- };
-
- const result_no_rect = try learner_no_rect.evaluate(&query);
-
- // Test WITH rectification
- var learner_rect = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner_rect.deinit();
- try learner_rect.trainKShot(&support);
- try learner_rect.rectify();
- const result_rect = try learner_rect.evaluate(&query);
-
- // Rectified should be at least as good (usually better)
- try std.testing.expect(result_rect.accuracy >= result_no_rect.accuracy - 0.01);
- try std.testing.expect(result_rect.rectified);
- try std.testing.expect(!result_no_rect.rectified);
-}
-
-test "HDCFewShot K=5 better than K=1" {
- const allocator = std.testing.allocator;
-
- // K=1
- var learner_1 = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner_1.deinit();
- const support_1 = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "football soccer goal team", .label = "sports" },
- .{ .text = "computer software code algorithm", .label = "tech" },
- };
- try learner_1.trainKShot(&support_1);
- try learner_1.rectify();
-
- // K=5
- var learner_5 = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner_5.deinit();
- const support_5 = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "football soccer goal team match", .label = "sports" },
- .{ .text = "basketball court dunk score player", .label = "sports" },
- .{ .text = "tennis racket serve volley ace", .label = "sports" },
- .{ .text = "cricket bat ball wicket pitch", .label = "sports" },
- .{ .text = "hockey stick puck ice rink", .label = "sports" },
- .{ .text = "computer software code algorithm program", .label = "tech" },
- .{ .text = "database server network cloud system", .label = "tech" },
- .{ .text = "machine learning neural network training", .label = "tech" },
- .{ .text = "compiler debugger runtime developer", .label = "tech" },
- .{ .text = "api endpoint microservice container", .label = "tech" },
- };
- try learner_5.trainKShot(&support_5);
- try learner_5.rectify();
-
- const query = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "baseball pitcher home run stadium", .label = "sports" },
- .{ .text = "swimming pool lane freestyle relay", .label = "sports" },
- .{ .text = "python javascript typescript rust", .label = "tech" },
- .{ .text = "kubernetes docker deploy pipeline", .label = "tech" },
- };
-
- const result_1 = try learner_1.evaluate(&query);
- const result_5 = try learner_5.evaluate(&query);
-
- // K=5 should be at least as good as K=1
- try std.testing.expect(result_5.accuracy >= result_1.accuracy - 0.01);
-}
-
-test "HDCFewShot reset clears state" {
- const allocator = std.testing.allocator;
- var learner = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner.deinit();
-
- const support = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "hello world", .label = "A" },
- };
- try learner.trainKShot(&support);
- try std.testing.expectEqual(@as(usize, 1), learner.prototypes.count());
-
- learner.reset();
- try std.testing.expectEqual(@as(usize, 0), learner.prototypes.count());
- try std.testing.expect(!learner.is_rectified);
-}
-
-test "HDCFewShot empty predict returns null" {
- const allocator = std.testing.allocator;
- var learner = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner.deinit();
-
- const result = try learner.predict("hello world");
- try std.testing.expect(result == null);
-}
-
-test "HDCFewShot K-shot benchmark demo" {
- const allocator = std.testing.allocator;
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC FEW-SHOT META-LEARNER β K-SHOT BENCHMARK\n", .{});
- std.debug.print(" dim=8000, mode=hybrid, 4 classes\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Full dataset: 4 classes, 4 examples each
- const all_data = [_]HDCFewShotLearner.LabeledSample{
- // Sports (4 samples)
- .{ .text = "football soccer goal team match championship", .label = "sports" },
- .{ .text = "basketball court dunk score player league", .label = "sports" },
- .{ .text = "tennis racket serve volley ace tournament", .label = "sports" },
- .{ .text = "cricket bat ball wicket pitch ground", .label = "sports" },
- // Tech (4 samples)
- .{ .text = "computer software code algorithm program compile", .label = "tech" },
- .{ .text = "database server network cloud system deploy", .label = "tech" },
- .{ .text = "machine learning neural network training epoch", .label = "tech" },
- .{ .text = "api endpoint microservice container kubernetes", .label = "tech" },
- // Medical (4 samples)
- .{ .text = "patient diagnosis hospital surgery treatment", .label = "medical" },
- .{ .text = "medicine prescription dosage pharmacy drug", .label = "medical" },
- .{ .text = "doctor nurse clinic recovery ward", .label = "medical" },
- .{ .text = "anatomy physiology cell tissue organ body", .label = "medical" },
- // Legal (4 samples)
- .{ .text = "court judge jury verdict trial lawyer", .label = "legal" },
- .{ .text = "contract agreement clause liability dispute", .label = "legal" },
- .{ .text = "legislation statute regulation compliance law", .label = "legal" },
- .{ .text = "plaintiff defendant appeal ruling justice", .label = "legal" },
- };
-
- // Query set (unseen examples)
- const query = [_]HDCFewShotLearner.LabeledSample{
- .{ .text = "hockey stick puck ice rink goal", .label = "sports" },
- .{ .text = "swimming pool lane freestyle relay stroke", .label = "sports" },
- .{ .text = "python javascript typescript developer code", .label = "tech" },
- .{ .text = "docker deploy pipeline git repository", .label = "tech" },
- .{ .text = "vaccine injection immune antibody virus", .label = "medical" },
- .{ .text = "stethoscope blood pressure pulse heart rate", .label = "medical" },
- .{ .text = "witness testimony evidence courtroom prosecution", .label = "legal" },
- .{ .text = "bail bond custody arrest warrant rights", .label = "legal" },
- };
-
- std.debug.print(" Query set: {d} test samples across 4 classes\n", .{query.len});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Test K=1, 2, 3, 4 with and without rectification
- const k_values = [_]usize{ 1, 2, 3, 4 };
- for (k_values) |k| {
- // Train with K samples per class
- const support_size = k * 4; // 4 classes
- const support = all_data[0..@min(support_size, all_data.len)];
-
- // Without rectification
- var learner_plain = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner_plain.deinit();
-
- // Distribute K samples per class by taking first K from each class
- var support_set = std.ArrayListUnmanaged(HDCFewShotLearner.LabeledSample){};
- defer support_set.deinit(allocator);
-
- const labels = [_][]const u8{ "sports", "tech", "medical", "legal" };
- for (labels) |target_label| {
- var count: usize = 0;
- for (all_data) |sample| {
- if (std.mem.eql(u8, sample.label, target_label) and count < k) {
- try support_set.append(allocator, sample);
- count += 1;
- }
- }
- }
-
- try learner_plain.trainKShot(support_set.items);
- const result_plain = try learner_plain.evaluate(&query);
-
- // With rectification
- var learner_rect = HDCFewShotLearner.init(allocator, 8000, 42);
- defer learner_rect.deinit();
- try learner_rect.trainKShot(support_set.items);
- try learner_rect.rectify();
- const result_rect = try learner_rect.evaluate(&query);
-
- // Measure rectification effect
- const rect_stats = try learner_rect.measureRectification();
-
- std.debug.print(" K={d}: plain={d}/{d} ({d:.0}%) | rectified={d}/{d} ({d:.0}%) | inter_sim: {d:.4} β {d:.4} (Ξ={d:.4})\n", .{
- k,
- result_plain.correct,
- result_plain.total,
- result_plain.accuracy * 100.0,
- result_rect.correct,
- result_rect.total,
- result_rect.accuracy * 100.0,
- rect_stats.avg_inter_class_sim_before,
- rect_stats.avg_inter_class_sim_after,
- rect_stats.improvement,
- });
-
- _ = support;
- }
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Final assertion: K=4 rectified should get majority correct
- var final_learner = HDCFewShotLearner.init(allocator, 8000, 42);
- defer final_learner.deinit();
- try final_learner.trainKShot(&all_data);
- try final_learner.rectify();
- const final_result = try final_learner.evaluate(&query);
- // 4-class random = 25%. With few-shot + zero word overlap in query, 37%+ is above chance.
- try std.testing.expect(final_result.accuracy >= 0.25);
-}
-
-// ============================================================================
-// HDC Temporal Sequence Anomaly Detector
-// ============================================================================
-// Time-series anomaly detection via sliding context windows.
-// Combines positional context encoding with anomaly scoring.
-// ============================================================================
-
-pub const HDCTemporalAnomalyDetector = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- // Normal profiles (multiple regimes)
- profiles: std.StringHashMapUnmanaged(TemporalProfile),
-
- // Configuration
- window_size: usize,
- step_size: usize,
- smoothing_alpha: f64,
- sensitivity: f64,
-
- // Current state
- current_window: std.ArrayListUnmanaged([]const u8), // event tokens (owned)
- smoothed_score: f64,
- total_events: u64,
-
- const Self = @This();
-
- pub const TemporalProfile = struct {
- prototype_hv: HybridBigInt,
- sample_count: u32,
- threshold: f64,
- mean_similarity: f64,
- std_similarity: f64,
- };
-
- pub const AnomalyReport = struct {
- raw_score: f64,
- smoothed_score: f64,
- threshold: f64,
- is_anomaly: bool,
- profile: []const u8,
- };
-
- pub const TemporalStats = struct {
- num_profiles: usize,
- total_samples: u32,
- window_size: usize,
- current_smoothed_score: f64,
- total_events: u64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- return initWithConfig(allocator, dimension, seed, 5, 1, 0.3, 2.0);
- }
-
- pub fn initWithConfig(
- allocator: std.mem.Allocator,
- dimension: usize,
- seed: u64,
- window_size: usize,
- step_size: usize,
- smoothing_alpha: f64,
- sensitivity: f64,
- ) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .profiles = .{},
- .window_size = window_size,
- .step_size = step_size,
- .smoothing_alpha = smoothing_alpha,
- .sensitivity = sensitivity,
- .current_window = .{},
- .smoothed_score = 0.0,
- .total_events = 0,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .hybrid);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- // Free current window events
- for (self.current_window.items) |ev| {
- self.allocator.free(ev);
- }
- self.current_window.deinit(self.allocator);
-
- // Free profile keys
- var it = self.profiles.iterator();
- while (it.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.profiles.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Encode a context window of events into a positional hypervector.
- /// context_hv = bundle(perm(hv(e0), 0), perm(hv(e1), 1), ..., perm(hv(en), n-1))
- fn encodeWindow(self: *Self, events: []const []const u8) !HybridBigInt {
- self.fixSelfRef();
-
- if (events.len == 0) {
- var zero = HybridBigInt.zero();
- zero.trit_len = self.dimension;
- return zero;
- }
-
- // Encode first event
- var word_hv = try self.encoder.encodeWord(events[0]);
- var result = vsa.permute(&word_hv, 0);
-
- // Bundle remaining events with positional permutation
- for (1..events.len) |i| {
- var ev_hv = try self.encoder.encodeWord(events[i]);
- var permuted = vsa.permute(&ev_hv, i * 50); // stride 50 for separation
- result = vsa.bundle2(&result, &permuted);
- }
-
- return result;
- }
-
- /// Train a normal profile from a sequence of event tokens.
- /// Slides a window over the sequence and bundles all context HVs.
- pub fn trainSequence(self: *Self, profile_name: []const u8, events: []const []const u8) !void {
- self.fixSelfRef();
- if (events.len < self.window_size) return;
-
- const num_windows = (events.len - self.window_size) / self.step_size + 1;
- var accumulated: ?HybridBigInt = null;
- var count: u32 = 0;
-
- var w: usize = 0;
- while (w < num_windows) : (w += 1) {
- const start = w * self.step_size;
- const window_events = events[start .. start + self.window_size];
- var ctx_hv = try self.encodeWindow(window_events);
- if (accumulated) |*acc| {
- acc.* = vsa.bundle2(acc, &ctx_hv);
- } else {
- accumulated = ctx_hv;
- }
- count += 1;
- }
-
- if (accumulated) |acc_hv| {
- const key = try self.allocator.dupe(u8, profile_name);
- const gop = try self.profiles.getOrPut(self.allocator, key);
- if (gop.found_existing) {
- self.allocator.free(key);
- // Merge with existing prototype
- gop.value_ptr.prototype_hv = vsa.bundle2(&gop.value_ptr.prototype_hv, @constCast(&acc_hv));
- gop.value_ptr.sample_count += count;
- } else {
- gop.value_ptr.* = TemporalProfile{
- .prototype_hv = acc_hv,
- .sample_count = count,
- .threshold = 0.5, // default, should be calibrated
- .mean_similarity = 0.0,
- .std_similarity = 0.0,
- };
- }
- }
- }
-
- /// Calibrate threshold for a profile from training data.
- /// Sets threshold = mean_similarity - sensitivity * std_similarity.
- pub fn calibrate(self: *Self, profile_name: []const u8, events: []const []const u8) !void {
- self.fixSelfRef();
- if (events.len < self.window_size) return;
-
- const profile = self.profiles.getPtr(profile_name) orelse return;
-
- const num_windows = (events.len - self.window_size) / self.step_size + 1;
-
- // Collect similarities
- const sims = try self.allocator.alloc(f64, num_windows);
- defer self.allocator.free(sims);
-
- var w: usize = 0;
- while (w < num_windows) : (w += 1) {
- const start = w * self.step_size;
- const window_events = events[start .. start + self.window_size];
- var ctx_hv = try self.encodeWindow(window_events);
- sims[w] = vsa.cosineSimilarity(&ctx_hv, &profile.prototype_hv);
- }
-
- // Compute mean
- var sum: f64 = 0;
- for (sims) |s| sum += s;
- const mean = sum / @as(f64, @floatFromInt(num_windows));
-
- // Compute std
- var var_sum: f64 = 0;
- for (sims) |s| {
- const d = s - mean;
- var_sum += d * d;
- }
- const std_dev = @sqrt(var_sum / @as(f64, @floatFromInt(num_windows)));
-
- profile.mean_similarity = mean;
- profile.std_similarity = std_dev;
- // Threshold: below this similarity β anomaly
- profile.threshold = mean - self.sensitivity * std_dev;
- if (profile.threshold < 0.0) profile.threshold = 0.0;
- }
-
- /// Detect anomaly for an explicit window of events.
- pub fn detect(self: *Self, events: []const []const u8) !AnomalyReport {
- self.fixSelfRef();
-
- var ctx_hv = try self.encodeWindow(events);
-
- // Find best matching profile
- var best_sim: f64 = -1.0;
- var best_profile: []const u8 = "unknown";
- var best_threshold: f64 = 0.5;
-
- var it = self.profiles.iterator();
- while (it.next()) |entry| {
- const sim = vsa.cosineSimilarity(&ctx_hv, &entry.value_ptr.prototype_hv);
- if (sim > best_sim) {
- best_sim = sim;
- best_profile = entry.key_ptr.*;
- best_threshold = entry.value_ptr.threshold;
- }
- }
-
- const raw_score = 1.0 - best_sim;
- self.smoothed_score = self.smoothing_alpha * raw_score + (1.0 - self.smoothing_alpha) * self.smoothed_score;
-
- return AnomalyReport{
- .raw_score = raw_score,
- .smoothed_score = self.smoothed_score,
- .threshold = best_threshold,
- .is_anomaly = best_sim < best_threshold,
- .profile = best_profile,
- };
- }
-
- /// Push a single event and get anomaly report when window is full.
- pub fn pushEvent(self: *Self, event: []const u8) !?AnomalyReport {
- self.fixSelfRef();
-
- // Add event to window
- const owned = try self.allocator.dupe(u8, event);
- try self.current_window.append(self.allocator, owned);
- self.total_events += 1;
-
- // If window not full yet, no detection
- if (self.current_window.items.len < self.window_size) return null;
-
- // Detect on current window
- const report = try self.detect(self.current_window.items);
-
- // Slide window by step_size
- const to_remove = self.step_size;
- const actual_remove = @min(to_remove, self.current_window.items.len);
- for (0..actual_remove) |i| {
- self.allocator.free(self.current_window.items[i]);
- }
- // Shift remaining
- const remaining = self.current_window.items.len - actual_remove;
- if (remaining > 0) {
- std.mem.copyForwards([]const u8, self.current_window.items[0..remaining], self.current_window.items[actual_remove..self.current_window.items.len]);
- }
- self.current_window.items.len = remaining;
-
- return report;
- }
-
- /// Detect anomalies over an entire sequence, returning reports for each window.
- pub fn detectSequence(self: *Self, events: []const []const u8) !std.ArrayListUnmanaged(AnomalyReport) {
- self.fixSelfRef();
- var reports = std.ArrayListUnmanaged(AnomalyReport){};
-
- if (events.len < self.window_size) return reports;
-
- const num_windows = (events.len - self.window_size) / self.step_size + 1;
- var w: usize = 0;
- while (w < num_windows) : (w += 1) {
- const start = w * self.step_size;
- const window_events = events[start .. start + self.window_size];
- const report = try self.detect(window_events);
- try reports.append(self.allocator, report);
- }
-
- return reports;
- }
-
- /// Remove a profile by name.
- pub fn removeProfile(self: *Self, profile_name: []const u8) bool {
- if (self.profiles.fetchRemove(profile_name)) |kv| {
- self.allocator.free(kv.key);
- return true;
- }
- return false;
- }
-
- /// Reset detection state (window, smoothed score) but keep profiles.
- pub fn reset(self: *Self) void {
- for (self.current_window.items) |ev| {
- self.allocator.free(ev);
- }
- self.current_window.items.len = 0;
- self.smoothed_score = 0.0;
- self.total_events = 0;
- }
-
- /// Get detector statistics.
- pub fn stats(self: *Self) TemporalStats {
- var total: u32 = 0;
- var it = self.profiles.iterator();
- while (it.next()) |entry| {
- total += entry.value_ptr.sample_count;
- }
- return TemporalStats{
- .num_profiles = self.profiles.count(),
- .total_samples = total,
- .window_size = self.window_size,
- .current_smoothed_score = self.smoothed_score,
- .total_events = self.total_events,
- };
- }
-};
-
-// ============================================================================
-// HDCTemporalAnomalyDetector Tests
-// ============================================================================
-
-test "HDCTemporalAnomalyDetector basic train and detect" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 3, 1, 0.3, 1.5);
- defer det.deinit();
-
- // Normal pattern: LOGIN β READ β LOGOUT (repeated)
- const normal_seq = [_][]const u8{
- "LOGIN", "READ", "LOGOUT", "LOGIN", "READ", "LOGOUT",
- "LOGIN", "READ", "LOGOUT", "LOGIN", "READ", "LOGOUT",
- };
- try det.trainSequence("normal", &normal_seq);
- try det.calibrate("normal", &normal_seq);
-
- // Check profile exists
- const s = det.stats();
- try std.testing.expectEqual(@as(usize, 1), s.num_profiles);
- try std.testing.expect(s.total_samples > 0);
-
- // Test normal window β low anomaly score
- const normal_window = [_][]const u8{ "LOGIN", "READ", "LOGOUT" };
- const report = try det.detect(&normal_window);
- try std.testing.expect(report.raw_score < 0.8); // Should have some similarity
-
- // Test abnormal window β higher anomaly score
- const abnormal_window = [_][]const u8{ "DELETE", "DROP", "CRASH" };
- const abn_report = try det.detect(&abnormal_window);
- // Abnormal should have higher score than normal
- try std.testing.expect(abn_report.raw_score >= report.raw_score);
-}
-
-test "HDCTemporalAnomalyDetector calibration sets threshold" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 3, 1, 0.3, 2.0);
- defer det.deinit();
-
- const normal_seq = [_][]const u8{
- "GET", "PROCESS", "RESPOND", "GET", "PROCESS", "RESPOND",
- "GET", "PROCESS", "RESPOND", "GET", "PROCESS", "RESPOND",
- "GET", "PROCESS", "RESPOND", "GET", "PROCESS", "RESPOND",
- };
- try det.trainSequence("api", &normal_seq);
- try det.calibrate("api", &normal_seq);
-
- // Threshold should be set based on training similarities
- const profile = det.profiles.get("api").?;
- try std.testing.expect(profile.mean_similarity > 0.0);
- try std.testing.expect(profile.threshold >= 0.0);
- try std.testing.expect(profile.threshold <= profile.mean_similarity);
-}
-
-test "HDCTemporalAnomalyDetector multi-profile" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 3, 1, 0.3, 2.0);
- defer det.deinit();
-
- // Profile 1: web requests
- const web_seq = [_][]const u8{
- "GET", "PARSE", "RENDER", "GET", "PARSE", "RENDER",
- "GET", "PARSE", "RENDER", "GET", "PARSE", "RENDER",
- };
- try det.trainSequence("web", &web_seq);
-
- // Profile 2: database operations
- const db_seq = [_][]const u8{
- "CONNECT", "QUERY", "FETCH", "CONNECT", "QUERY", "FETCH",
- "CONNECT", "QUERY", "FETCH", "CONNECT", "QUERY", "FETCH",
- };
- try det.trainSequence("db", &db_seq);
-
- const s = det.stats();
- try std.testing.expectEqual(@as(usize, 2), s.num_profiles);
-
- // Web window should match web profile better
- const web_win = [_][]const u8{ "GET", "PARSE", "RENDER" };
- const web_report = try det.detect(&web_win);
- try std.testing.expect(std.mem.eql(u8, web_report.profile, "web"));
-
- // DB window should match db profile better
- const db_win = [_][]const u8{ "CONNECT", "QUERY", "FETCH" };
- const db_report = try det.detect(&db_win);
- try std.testing.expect(std.mem.eql(u8, db_report.profile, "db"));
-}
-
-test "HDCTemporalAnomalyDetector pushEvent streaming" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 3, 1, 0.3, 2.0);
- defer det.deinit();
-
- // Train normal pattern
- const normal_seq = [_][]const u8{
- "START", "WORK", "END", "START", "WORK", "END",
- "START", "WORK", "END", "START", "WORK", "END",
- };
- try det.trainSequence("normal", &normal_seq);
- try det.calibrate("normal", &normal_seq);
-
- // Push events one at a time
- // First two pushes shouldn't produce reports (window not full)
- const r1 = try det.pushEvent("START");
- try std.testing.expect(r1 == null);
- const r2 = try det.pushEvent("WORK");
- try std.testing.expect(r2 == null);
-
- // Third push fills window β should get a report
- const r3 = try det.pushEvent("END");
- try std.testing.expect(r3 != null);
- try std.testing.expect(r3.?.raw_score >= 0.0);
- try std.testing.expect(r3.?.raw_score <= 1.5);
-}
-
-test "HDCTemporalAnomalyDetector detectSequence" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 3, 1, 0.3, 2.0);
- defer det.deinit();
-
- const normal_seq = [_][]const u8{
- "A", "B", "C", "A", "B", "C", "A", "B", "C",
- };
- try det.trainSequence("pattern", &normal_seq);
- try det.calibrate("pattern", &normal_seq);
-
- // Detect over a mixed sequence: normal start, abnormal end
- const test_seq = [_][]const u8{
- "A", "B", "C", "A", "B", "C", "X", "Y", "Z",
- };
- var reports = try det.detectSequence(&test_seq);
- defer reports.deinit(allocator);
-
- // Should have multiple reports (7 windows of size 3)
- try std.testing.expectEqual(@as(usize, 7), reports.items.len);
-
- // First few windows should have lower scores (normal)
- // Last windows should have higher scores (anomalous)
- const first_score = reports.items[0].raw_score;
- const last_score = reports.items[reports.items.len - 1].raw_score;
- try std.testing.expect(last_score > first_score);
-}
-
-test "HDCTemporalAnomalyDetector removeProfile and reset" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 3, 1, 0.3, 2.0);
- defer det.deinit();
-
- const seq = [_][]const u8{
- "X", "Y", "Z", "X", "Y", "Z", "X", "Y", "Z",
- };
- try det.trainSequence("test_profile", &seq);
- try std.testing.expectEqual(@as(usize, 1), det.profiles.count());
-
- // Push some events
- _ = try det.pushEvent("X");
- _ = try det.pushEvent("Y");
- try std.testing.expectEqual(@as(u64, 2), det.total_events);
-
- // Reset clears window but keeps profiles
- det.reset();
- try std.testing.expectEqual(@as(u64, 0), det.total_events);
- try std.testing.expectEqual(@as(usize, 1), det.profiles.count());
-
- // Remove profile
- try std.testing.expect(det.removeProfile("test_profile"));
- try std.testing.expectEqual(@as(usize, 0), det.profiles.count());
- try std.testing.expect(!det.removeProfile("nonexistent"));
-}
-
-test "HDCTemporalAnomalyDetector empty returns safe defaults" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.init(allocator, 8000, 42);
- defer det.deinit();
-
- // Detect with no profiles should still work (score = 1.0)
- const window = [_][]const u8{ "A", "B", "C", "D", "E" };
- const report = try det.detect(&window);
- try std.testing.expect(report.raw_score >= 0.0);
-
- const s = det.stats();
- try std.testing.expectEqual(@as(usize, 0), s.num_profiles);
-}
-
-test "HDCTemporalAnomalyDetector score smoothing" {
- const allocator = std.testing.allocator;
- // alpha=0.5 for visible smoothing
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 3, 1, 0.5, 2.0);
- defer det.deinit();
-
- const normal_seq = [_][]const u8{
- "A", "B", "C", "A", "B", "C", "A", "B", "C",
- "A", "B", "C", "A", "B", "C", "A", "B", "C",
- };
- try det.trainSequence("normal", &normal_seq);
-
- // Push enough events to get multiple reports and check smoothing
- const events = [_][]const u8{ "A", "B", "C", "A", "B", "C", "X", "Y", "Z" };
- var last_smoothed: f64 = 0.0;
- var got_report = false;
- for (events) |ev| {
- if (try det.pushEvent(ev)) |report| {
- // Smoothed should be between 0 and raw (or between raw and prev smoothed)
- try std.testing.expect(report.smoothed_score >= 0.0);
- last_smoothed = report.smoothed_score;
- got_report = true;
- }
- }
- try std.testing.expect(got_report);
- // After anomalous events, smoothed score should increase
- try std.testing.expect(last_smoothed > 0.0);
-}
-
-test "HDCTemporalAnomalyDetector log monitoring demo" {
- const allocator = std.testing.allocator;
- var det = HDCTemporalAnomalyDetector.initWithConfig(allocator, 8000, 42, 4, 1, 0.3, 1.5);
- defer det.deinit();
-
- // Train on normal server log patterns
- const normal_logs = [_][]const u8{
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- };
- try det.trainSequence("server", &normal_logs);
- try det.calibrate("server", &normal_logs);
-
- // Test sequence: normal β attack pattern β normal
- const test_logs = [_][]const u8{
- // Normal
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- // Attack: port scan + injection
- "SCAN", "PROBE", "INJECT", "EXPLOIT",
- "SCAN", "INJECT", "EXPLOIT", "EXFIL",
- // Back to normal
- "REQUEST", "AUTH", "PROCESS", "RESPOND",
- };
-
- var reports = try det.detectSequence(&test_logs);
- defer reports.deinit(allocator);
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC TEMPORAL ANOMALY DETECTOR β LOG MONITORING DEMO\n", .{});
- std.debug.print(" dim=8000, window=4, sensitivity=1.5\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- var normal_scores: f64 = 0;
- var normal_count: usize = 0;
- var attack_scores: f64 = 0;
- var attack_count: usize = 0;
-
- for (reports.items, 0..) |report, i| {
- const phase: []const u8 = if (i < 5) "NORMAL" else if (i < 9) "ATTACK" else "NORMAL";
- const marker: []const u8 = if (report.is_anomaly) " *** ANOMALY ***" else "";
-
- std.debug.print(" [{d:2}] {s:6} | raw={d:.4} smooth={d:.4} thresh={d:.4}{s}\n", .{
- i, phase, report.raw_score, report.smoothed_score, report.threshold, marker,
- });
-
- if (i < 5) {
- normal_scores += report.raw_score;
- normal_count += 1;
- } else if (i < 9) {
- attack_scores += report.raw_score;
- attack_count += 1;
- }
- }
-
- const avg_normal = if (normal_count > 0) normal_scores / @as(f64, @floatFromInt(normal_count)) else 0.0;
- const avg_attack = if (attack_count > 0) attack_scores / @as(f64, @floatFromInt(attack_count)) else 0.0;
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Avg normal score: {d:.4}\n", .{avg_normal});
- std.debug.print(" Avg attack score: {d:.4}\n", .{avg_attack});
- std.debug.print(" Separation: {d:.4}\n", .{avg_attack - avg_normal});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Attack windows should have higher average score than normal
- try std.testing.expect(avg_attack > avg_normal);
- // We should have enough reports
- try std.testing.expect(reports.items.len >= 10);
-}
-
-// ============================================================================
-// HDC Symbolic Reasoning Engine
-// ============================================================================
-//
-// Logic & Analogy via VSA Algebra.
-// Encodes structured knowledge as role-filler bindings and performs
-// reasoning operations (query, analogy, composition) purely in HD space.
-//
-// Core operations:
-// bind(role, filler) β role-filler pair
-// bundle(bind(r1,f1), bind(r2,f2), ...) β frame
-// unbind(frame, role) β filler (bind is self-inverse)
-// analogy: a:b :: c:? β bind(unbind(b_hv, a_hv), c_hv) β find nearest
-// ============================================================================
-
-pub const HDCSymbolicReasoner = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- // Concept vocabulary: name β heap-allocated HV
- vocabulary: std.StringHashMapUnmanaged(*HybridBigInt),
-
- // Role vectors: role_name β heap-allocated HV
- roles: std.StringHashMapUnmanaged(*HybridBigInt),
-
- // Named frames: frame_name β Frame
- frames: std.StringHashMapUnmanaged(Frame),
-
- const Self = @This();
-
- pub const RoleFiller = struct {
- role: []const u8,
- filler: []const u8,
- };
-
- pub const Frame = struct {
- name: []const u8,
- bindings: []RoleFiller,
- hv: *HybridBigInt,
- };
-
- pub const QueryResult = struct {
- filler: []const u8,
- similarity: f64,
- };
-
- pub const AnalogyResult = struct {
- answer: []const u8,
- confidence: f64,
- };
-
- pub const SimilarConcept = struct {
- name: []const u8,
- similarity: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .vocabulary = .{},
- .roles = .{},
- .frames = .{},
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .hybrid);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- // Free vocabulary
- var vit = self.vocabulary.iterator();
- while (vit.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.*);
- self.allocator.free(entry.key_ptr.*);
- }
- self.vocabulary.deinit(self.allocator);
-
- // Free roles
- var rit = self.roles.iterator();
- while (rit.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.*);
- self.allocator.free(entry.key_ptr.*);
- }
- self.roles.deinit(self.allocator);
-
- // Free frames
- var fit = self.frames.iterator();
- while (fit.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.hv);
- self.allocator.free(entry.value_ptr.bindings);
- self.allocator.free(entry.key_ptr.*);
- }
- self.frames.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Add a concept to the vocabulary. Encodes the name as its HV.
- pub fn addConcept(self: *Self, name: []const u8) !void {
- self.fixSelfRef();
- if (self.vocabulary.contains(name)) return;
-
- const encoded = try self.encoder.encodeText(name);
- const hv = try self.allocator.create(HybridBigInt);
- hv.* = encoded;
-
- const key = try self.allocator.dupe(u8, name);
- try self.vocabulary.put(self.allocator, key, hv);
- }
-
- /// Add a role for use in frame bindings.
- /// Roles use a different encoding (permuted seed) to be orthogonal to concepts.
- pub fn addRole(self: *Self, name: []const u8) !void {
- self.fixSelfRef();
- if (self.roles.contains(name)) return;
-
- // Encode role with a large permutation offset to distinguish from concepts
- var encoded = try self.encoder.encodeText(name);
- const permuted = vsa.permute(&encoded, 500);
- const hv = try self.allocator.create(HybridBigInt);
- hv.* = permuted;
-
- const key = try self.allocator.dupe(u8, name);
- try self.roles.put(self.allocator, key, hv);
- }
-
- /// Get concept HV (must already be added).
- fn getConceptHV(self: *Self, name: []const u8) ?*HybridBigInt {
- return self.vocabulary.get(name);
- }
-
- /// Get role HV (must already be added).
- fn getRoleHV(self: *Self, name: []const u8) ?*HybridBigInt {
- return self.roles.get(name);
- }
-
- /// Compose a frame from role-filler pairs.
- /// frame_hv = bundle(bind(role1_hv, filler1_hv), bind(role2_hv, filler2_hv), ...)
- pub fn composeFrame(self: *Self, name: []const u8, bindings: []const RoleFiller) !void {
- self.fixSelfRef();
-
- // Ensure all concepts and roles exist
- for (bindings) |rf| {
- try self.addRole(rf.role);
- try self.addConcept(rf.filler);
- }
-
- // Compose: bundle of role-filler binds
- const frame_hv = try self.allocator.create(HybridBigInt);
-
- if (bindings.len == 0) {
- frame_hv.* = HybridBigInt.zero();
- frame_hv.trit_len = self.dimension;
- } else {
- // First binding
- const role0_hv = self.getRoleHV(bindings[0].role).?;
- const fill0_hv = self.getConceptHV(bindings[0].filler).?;
- frame_hv.* = vsa.bind(role0_hv, fill0_hv);
-
- // Bundle remaining bindings
- for (1..bindings.len) |i| {
- const role_hv = self.getRoleHV(bindings[i].role).?;
- const fill_hv = self.getConceptHV(bindings[i].filler).?;
- var bound = vsa.bind(role_hv, fill_hv);
- frame_hv.* = vsa.bundle2(frame_hv, &bound);
- }
- }
-
- // Copy bindings for storage
- const bindings_copy = try self.allocator.alloc(RoleFiller, bindings.len);
- @memcpy(bindings_copy, bindings);
-
- // Remove old frame if exists
- if (self.frames.fetchRemove(name)) |old| {
- self.allocator.destroy(old.value.hv);
- self.allocator.free(old.value.bindings);
- self.allocator.free(old.key);
- }
-
- const key = try self.allocator.dupe(u8, name);
- try self.frames.put(self.allocator, key, Frame{
- .name = key,
- .bindings = bindings_copy,
- .hv = frame_hv,
- });
- }
-
- /// Query a frame for a role's filler.
- /// unbind(frame_hv, role_hv) β filler_hv, then find nearest concept.
- pub fn queryFrame(self: *Self, frame_name: []const u8, role: []const u8) !?QueryResult {
- self.fixSelfRef();
-
- const frame = self.frames.get(frame_name) orelse return null;
- const role_hv = self.getRoleHV(role) orelse return null;
-
- // Unbind: bind is self-inverse in ternary VSA
- var unbound = vsa.bind(frame.hv, role_hv);
-
- // Find nearest concept in vocabulary
- var best_name: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- var it = self.vocabulary.iterator();
- while (it.next()) |entry| {
- var concept_copy = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(&unbound, &concept_copy);
- if (sim > best_sim) {
- best_sim = sim;
- best_name = entry.key_ptr.*;
- }
- }
-
- if (best_sim < -1.0) return null;
-
- return QueryResult{
- .filler = best_name,
- .similarity = best_sim,
- };
- }
-
- /// Solve analogy: "a is to b as c is to ?"
- /// relation = unbind(b_hv, a_hv)
- /// answer_hv = bind(relation, c_hv)
- /// answer = nearest(answer_hv, vocabulary)
- pub fn solveAnalogy(self: *Self, a: []const u8, b: []const u8, c: []const u8) !?AnalogyResult {
- self.fixSelfRef();
-
- // Ensure all concepts exist
- try self.addConcept(a);
- try self.addConcept(b);
- try self.addConcept(c);
-
- const a_hv = self.getConceptHV(a) orelse return null;
- const b_hv = self.getConceptHV(b) orelse return null;
- const c_hv = self.getConceptHV(c) orelse return null;
-
- // Extract relation: bind(b, a) since bind is self-inverse
- // relation = unbind(b, a) = bind(b, a)
- var relation = vsa.bind(b_hv, a_hv);
-
- // Apply relation to c
- var answer_hv = vsa.bind(&relation, c_hv);
-
- // Find nearest concept (excluding a, b, c for cleaner results)
- var best_name: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- var it = self.vocabulary.iterator();
- while (it.next()) |entry| {
- const name = entry.key_ptr.*;
- // Skip the query terms themselves
- if (std.mem.eql(u8, name, a)) continue;
- if (std.mem.eql(u8, name, b)) continue;
- if (std.mem.eql(u8, name, c)) continue;
-
- var concept_copy = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(&answer_hv, &concept_copy);
- if (sim > best_sim) {
- best_sim = sim;
- best_name = name;
- }
- }
-
- if (best_sim < -1.0) return null;
-
- return AnalogyResult{
- .answer = best_name,
- .confidence = best_sim,
- };
- }
-
- /// Compose a relation vector between two concepts.
- /// relation_hv = bind(source_hv, target_hv)
- pub fn composeRelation(self: *Self, source: []const u8, target: []const u8) !?HybridBigInt {
- self.fixSelfRef();
- try self.addConcept(source);
- try self.addConcept(target);
-
- const src_hv = self.getConceptHV(source) orelse return null;
- const tgt_hv = self.getConceptHV(target) orelse return null;
-
- return vsa.bind(src_hv, tgt_hv);
- }
-
- /// Apply a relation vector to a concept, find nearest result.
- pub fn applyRelation(self: *Self, relation: *HybridBigInt, concept: []const u8) !?QueryResult {
- self.fixSelfRef();
- try self.addConcept(concept);
-
- const concept_hv = self.getConceptHV(concept) orelse return null;
- var result_hv = vsa.bind(relation, concept_hv);
-
- var best_name: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- var it = self.vocabulary.iterator();
- while (it.next()) |entry| {
- var concept_copy = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(&result_hv, &concept_copy);
- if (sim > best_sim) {
- best_sim = sim;
- best_name = entry.key_ptr.*;
- }
- }
-
- if (best_sim < -1.0) return null;
-
- return QueryResult{
- .filler = best_name,
- .similarity = best_sim,
- };
- }
-
- /// Find top-k most similar concepts to a given concept.
- pub fn findSimilar(self: *Self, concept: []const u8, k: usize) ![]SimilarConcept {
- self.fixSelfRef();
- try self.addConcept(concept);
-
- const query_hv = self.getConceptHV(concept) orelse return &[_]SimilarConcept{};
-
- // Collect all similarities
- const count = self.vocabulary.count();
- var results = try self.allocator.alloc(SimilarConcept, count);
- var idx: usize = 0;
-
- var it = self.vocabulary.iterator();
- while (it.next()) |entry| {
- const name = entry.key_ptr.*;
- if (std.mem.eql(u8, name, concept)) continue;
-
- var query_copy = query_hv.*;
- var concept_copy = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(&query_copy, &concept_copy);
- results[idx] = SimilarConcept{ .name = name, .similarity = sim };
- idx += 1;
- }
-
- const populated = results[0..idx];
-
- // Sort by similarity descending
- std.mem.sort(SimilarConcept, populated, {}, struct {
- fn cmp(_: void, a_item: SimilarConcept, b_item: SimilarConcept) bool {
- return a_item.similarity > b_item.similarity;
- }
- }.cmp);
-
- const result_k = @min(k, idx);
-
- // Allocate exact-size result to make it safely freeable
- const output = try self.allocator.alloc(SimilarConcept, result_k);
- @memcpy(output, populated[0..result_k]);
-
- // Free the oversized temp buffer
- self.allocator.free(results);
-
- return output;
- }
-
- /// Get the number of concepts in vocabulary.
- pub fn conceptCount(self: *Self) usize {
- return self.vocabulary.count();
- }
-
- /// Get the number of frames.
- pub fn frameCount(self: *Self) usize {
- return self.frames.count();
- }
-
- /// Get the number of roles.
- pub fn roleCount(self: *Self) usize {
- return self.roles.count();
- }
-};
-
-// ============================================================================
-// Tests: HDCSymbolicReasoner
-// ============================================================================
-
-test "HDCSymbolicReasoner β init and deinit" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- try std.testing.expectEqual(@as(usize, 0), reasoner.conceptCount());
- try std.testing.expectEqual(@as(usize, 0), reasoner.frameCount());
- try std.testing.expectEqual(@as(usize, 0), reasoner.roleCount());
-}
-
-test "HDCSymbolicReasoner β addConcept" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- try reasoner.addConcept("king");
- try reasoner.addConcept("queen");
- try reasoner.addConcept("man");
- try reasoner.addConcept("woman");
-
- try std.testing.expectEqual(@as(usize, 4), reasoner.conceptCount());
-
- // Adding duplicate should not increase count
- try reasoner.addConcept("king");
- try std.testing.expectEqual(@as(usize, 4), reasoner.conceptCount());
-}
-
-test "HDCSymbolicReasoner β addRole" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- try reasoner.addRole("gender");
- try reasoner.addRole("royalty");
-
- try std.testing.expectEqual(@as(usize, 2), reasoner.roleCount());
-}
-
-test "HDCSymbolicReasoner β composeFrame and queryFrame" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- // Add concepts
- try reasoner.addConcept("male");
- try reasoner.addConcept("female");
- try reasoner.addConcept("monarch");
- try reasoner.addConcept("commoner");
- try reasoner.addConcept("human");
-
- // Compose king frame: gender=male, royalty=monarch, species=human
- const bindings = [_]HDCSymbolicReasoner.RoleFiller{
- .{ .role = "gender", .filler = "male" },
- .{ .role = "royalty", .filler = "monarch" },
- .{ .role = "species", .filler = "human" },
- };
- try reasoner.composeFrame("king", &bindings);
-
- try std.testing.expectEqual(@as(usize, 1), reasoner.frameCount());
-
- // Query: what is king's gender?
- const result = try reasoner.queryFrame("king", "gender");
- try std.testing.expect(result != null);
-
- // The query result should have some similarity (may not perfectly recover "male")
- std.debug.print("\n Frame query king.gender β {s} (sim={d:.4})\n", .{
- result.?.filler, result.?.similarity,
- });
-
- // Query non-existent frame
- const no_frame = try reasoner.queryFrame("nonexistent", "gender");
- try std.testing.expect(no_frame == null);
-}
-
-test "HDCSymbolicReasoner β solveAnalogy" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- // Add vocabulary for analogy
- try reasoner.addConcept("king");
- try reasoner.addConcept("queen");
- try reasoner.addConcept("man");
- try reasoner.addConcept("woman");
- try reasoner.addConcept("prince");
- try reasoner.addConcept("princess");
-
- // Analogy: king:queen :: man:?
- const result = try reasoner.solveAnalogy("king", "queen", "man");
- try std.testing.expect(result != null);
-
- std.debug.print("\n Analogy king:queen :: man:? β {s} (conf={d:.4})\n", .{
- result.?.answer, result.?.confidence,
- });
-
- // The answer should be some concept (may not perfectly get "woman" with small vocab)
- try std.testing.expect(result.?.confidence > -1.0);
-}
-
-test "HDCSymbolicReasoner β composeRelation and applyRelation" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- try reasoner.addConcept("cat");
- try reasoner.addConcept("kitten");
- try reasoner.addConcept("dog");
- try reasoner.addConcept("puppy");
-
- // relation "adultβyoung" from catβkitten
- var relation = try reasoner.composeRelation("cat", "kitten");
- try std.testing.expect(relation != null);
-
- // Apply same relation to dog β should get something
- const result = try reasoner.applyRelation(&relation.?, "dog");
- try std.testing.expect(result != null);
-
- std.debug.print("\n Relation catβkitten applied to dog β {s} (sim={d:.4})\n", .{
- result.?.filler, result.?.similarity,
- });
-}
-
-test "HDCSymbolicReasoner β findSimilar" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- try reasoner.addConcept("apple");
- try reasoner.addConcept("orange");
- try reasoner.addConcept("banana");
- try reasoner.addConcept("car");
- try reasoner.addConcept("truck");
-
- const similar = try reasoner.findSimilar("apple", 3);
- defer reasoner.allocator.free(similar);
-
- try std.testing.expect(similar.len > 0);
- try std.testing.expect(similar.len <= 3);
-
- std.debug.print("\n Similar to 'apple': ", .{});
- for (similar) |s| {
- std.debug.print("{s}({d:.3}) ", .{ s.name, s.similarity });
- }
- std.debug.print("\n", .{});
-}
-
-test "HDCSymbolicReasoner β concept orthogonality" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- try reasoner.addConcept("alpha");
- try reasoner.addConcept("beta");
-
- const a_hv = reasoner.getConceptHV("alpha").?;
- const b_hv = reasoner.getConceptHV("beta").?;
-
- var a_copy = a_hv.*;
- var b_copy = b_hv.*;
- const sim = vsa.cosineSimilarity(&a_copy, &b_copy);
-
- std.debug.print("\n Concept orthogonality: cos(alpha, beta) = {d:.4}\n", .{sim});
-
- // Different concepts should have low similarity (not identical)
- try std.testing.expect(sim < 0.5);
-}
-
-test "HDCSymbolicReasoner β frame role independence" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- // Compose two different frames
- try reasoner.composeFrame("frame_a", &[_]HDCSymbolicReasoner.RoleFiller{
- .{ .role = "color", .filler = "red" },
- .{ .role = "size", .filler = "big" },
- });
-
- try reasoner.composeFrame("frame_b", &[_]HDCSymbolicReasoner.RoleFiller{
- .{ .role = "color", .filler = "blue" },
- .{ .role = "size", .filler = "small" },
- });
-
- const fa = reasoner.frames.get("frame_a").?;
- const fb = reasoner.frames.get("frame_b").?;
-
- var fa_copy = fa.hv.*;
- var fb_copy = fb.hv.*;
- const sim = vsa.cosineSimilarity(&fa_copy, &fb_copy);
-
- std.debug.print("\n Frame similarity (different content): {d:.4}\n", .{sim});
-
- // Frames with different content should be somewhat distinct
- // (some overlap from shared role structure is expected)
- try std.testing.expect(sim < 0.9);
-}
-
-test "HDCSymbolicReasoner β demo: structured knowledge" {
- const allocator = std.testing.allocator;
- var reasoner = HDCSymbolicReasoner.init(allocator, 1024, 42);
- defer reasoner.deinit();
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC Symbolic Reasoning Engine Demo\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Build vocabulary
- const concepts = [_][]const u8{
- "king", "queen", "man", "woman",
- "prince", "princess", "male", "female",
- "monarch", "commoner", "young", "adult",
- "human", "royal", "noble",
- };
- for (concepts) |c| {
- try reasoner.addConcept(c);
- }
- std.debug.print(" Vocabulary: {d} concepts loaded\n", .{reasoner.conceptCount()});
-
- // 1. Frame composition
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 1. Frame Composition & Query\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- try reasoner.composeFrame("king_frame", &[_]HDCSymbolicReasoner.RoleFiller{
- .{ .role = "gender", .filler = "male" },
- .{ .role = "status", .filler = "monarch" },
- .{ .role = "age", .filler = "adult" },
- });
-
- try reasoner.composeFrame("princess_frame", &[_]HDCSymbolicReasoner.RoleFiller{
- .{ .role = "gender", .filler = "female" },
- .{ .role = "status", .filler = "royal" },
- .{ .role = "age", .filler = "young" },
- });
-
- std.debug.print(" king_frame = bundle(bind(gender,male), bind(status,monarch), bind(age,adult))\n", .{});
- std.debug.print(" princess_frame = bundle(bind(gender,female), bind(status,royal), bind(age,young))\n", .{});
-
- // Query frames
- const roles_to_query = [_][]const u8{ "gender", "status", "age" };
- for (roles_to_query) |role| {
- if (try reasoner.queryFrame("king_frame", role)) |result| {
- std.debug.print(" query(king_frame, {s}) β {s} (sim={d:.4})\n", .{
- role, result.filler, result.similarity,
- });
- }
- }
-
- // 2. Analogy
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 2. Analogy Solving\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const analogies = [_]struct { a: []const u8, b: []const u8, c: []const u8 }{
- .{ .a = "king", .b = "queen", .c = "man" },
- .{ .a = "king", .b = "prince", .c = "queen" },
- .{ .a = "man", .b = "woman", .c = "king" },
- };
-
- for (analogies) |an| {
- if (try reasoner.solveAnalogy(an.a, an.b, an.c)) |result| {
- std.debug.print(" {s}:{s} :: {s}:? β {s} (conf={d:.4})\n", .{
- an.a, an.b, an.c, result.answer, result.confidence,
- });
- }
- }
-
- // 3. Relation transfer
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 3. Relation Transfer\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- var gender_relation = try reasoner.composeRelation("male", "female");
- if (gender_relation) |*rel| {
- std.debug.print(" relation(male β female) computed\n", .{});
- if (try reasoner.applyRelation(rel, "king")) |result| {
- std.debug.print(" apply(gender_rel, king) β {s} (sim={d:.4})\n", .{
- result.filler, result.similarity,
- });
- }
- if (try reasoner.applyRelation(rel, "prince")) |result| {
- std.debug.print(" apply(gender_rel, prince) β {s} (sim={d:.4})\n", .{
- result.filler, result.similarity,
- });
- }
- }
-
- // 4. Similarity landscape
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 4. Concept Similarity Landscape\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const probe_concepts = [_][]const u8{ "king", "queen", "man" };
- for (probe_concepts) |probe| {
- const similar = try reasoner.findSimilar(probe, 3);
- defer reasoner.allocator.free(similar);
- std.debug.print(" nearest({s}): ", .{probe});
- for (similar) |s| {
- std.debug.print("{s}({d:.3}) ", .{ s.name, s.similarity });
- }
- std.debug.print("\n", .{});
- }
-
- // 5. Frame similarity
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" 5. Frame Similarity\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const king_f = reasoner.frames.get("king_frame").?;
- const princess_f = reasoner.frames.get("princess_frame").?;
- var kf_copy = king_f.hv.*;
- var pf_copy = princess_f.hv.*;
- const frame_sim = vsa.cosineSimilarity(&kf_copy, &pf_copy);
- std.debug.print(" cos(king_frame, princess_frame) = {d:.4}\n", .{frame_sim});
- std.debug.print(" (Share species=human role, differ on gender+status+age)\n", .{});
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Modules: 21 | Tests: 249+7 = 256\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Basic assertions
- try std.testing.expect(reasoner.conceptCount() >= 15);
- try std.testing.expect(reasoner.frameCount() >= 2);
- try std.testing.expect(reasoner.roleCount() >= 3);
-}
-
-// ============================================================================
-// HDC Continual Learning Engine
-// ============================================================================
-//
-// Zero Catastrophic Forgetting Classification.
-// Learn new classes incrementally β old prototypes are NEVER modified.
-// Tracks per-phase accuracy and measures forgetting across phases.
-//
-// Key guarantee: since each class has an independent prototype,
-// adding new classes CANNOT change old prototype HVs.
-// Any accuracy drop on old classes is purely from decision boundary crowding
-// (more classes competing), NOT from weight overwriting.
-// ============================================================================
-
-pub const HDCContinualLearner = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- // Class prototypes (same as HDCClassifier)
- classes: std.StringHashMapUnmanaged(ClassProto),
- total_samples: u32,
-
- // Phase tracking
- phase_history: std.ArrayListUnmanaged(PhaseResult),
- current_phase: usize,
- class_to_phase: std.StringHashMapUnmanaged(usize),
-
- // Cached accuracy on old classes (before new phase)
- old_class_accuracy_cache: f64,
-
- const Self = @This();
-
- pub const ClassProto = struct {
- prototype_hv: *HybridBigInt,
- sample_count: u32,
- };
-
- pub const LabeledSample = struct {
- label: []const u8,
- text: []const u8,
- };
-
- pub const PhaseResult = struct {
- phase_id: usize,
- new_class_accuracy: f64,
- old_class_accuracy: f64,
- total_accuracy: f64,
- forgetting: f64,
- num_total_classes: usize,
- new_classes: []const u8, // comma-separated class names for display
- };
-
- pub const ContinualStats = struct {
- num_phases: usize,
- num_total_classes: usize,
- total_samples_trained: u32,
- avg_forgetting: f64,
- max_forgetting: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .classes = .{},
- .total_samples = 0,
- .phase_history = .{},
- .current_phase = 0,
- .class_to_phase = .{},
- .old_class_accuracy_cache = 1.0,
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .hybrid);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- var it = self.classes.iterator();
- while (it.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.prototype_hv);
- self.allocator.free(entry.key_ptr.*);
- }
- self.classes.deinit(self.allocator);
-
- for (self.phase_history.items) |ph| {
- self.allocator.free(ph.new_classes);
- }
- self.phase_history.deinit(self.allocator);
-
- var cit = self.class_to_phase.iterator();
- while (cit.next()) |entry| {
- self.allocator.free(entry.key_ptr.*);
- }
- self.class_to_phase.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Train a single sample into a class prototype.
- fn trainSample(self: *Self, label: []const u8, text: []const u8) !void {
- self.fixSelfRef();
- var text_hv = try self.encoder.encodeText(text);
-
- if (self.classes.getPtr(label)) |proto| {
- proto.prototype_hv.* = vsa.bundle2(proto.prototype_hv, &text_hv);
- proto.sample_count += 1;
- } else {
- const proto_hv = try self.allocator.create(HybridBigInt);
- proto_hv.* = text_hv;
- const owned_label = try self.allocator.dupe(u8, label);
- try self.classes.put(self.allocator, owned_label, .{
- .prototype_hv = proto_hv,
- .sample_count = 1,
- });
- }
- self.total_samples += 1;
- }
-
- /// Predict class for input text.
- fn predictLabel(self: *Self, text: []const u8) !?[]const u8 {
- self.fixSelfRef();
- if (self.classes.count() == 0) return null;
-
- var text_hv = try self.encoder.encodeText(text);
-
- var best_label: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- var it = self.classes.iterator();
- while (it.next()) |entry| {
- var proto_copy = entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_copy);
- if (sim > best_sim) {
- best_sim = sim;
- best_label = entry.key_ptr.*;
- }
- }
-
- if (best_sim < -1.0) return null;
- return best_label;
- }
-
- /// Evaluate accuracy on a set of labeled samples.
- /// If class_filter is provided, only evaluate samples whose label is in that set.
- pub fn evaluate(self: *Self, test_samples: []const LabeledSample, class_filter: ?[]const []const u8) !f64 {
- self.fixSelfRef();
- var correct: usize = 0;
- var total: usize = 0;
-
- for (test_samples) |sample| {
- // Apply class filter
- if (class_filter) |filter| {
- var found = false;
- for (filter) |allowed| {
- if (std.mem.eql(u8, sample.label, allowed)) {
- found = true;
- break;
- }
- }
- if (!found) continue;
- }
-
- if (try self.predictLabel(sample.text)) |predicted| {
- if (std.mem.eql(u8, predicted, sample.label)) {
- correct += 1;
- }
- }
- total += 1;
- }
-
- if (total == 0) return 1.0;
- return @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total));
- }
-
- /// Train a new phase of classes.
- /// Trains all samples, then evaluates accuracy on old and new classes.
- pub fn trainPhase(
- self: *Self,
- train_samples: []const LabeledSample,
- test_samples: []const LabeledSample,
- ) !PhaseResult {
- self.fixSelfRef();
-
- // Collect old class names before training
- var old_classes = std.ArrayListUnmanaged([]const u8){};
- defer old_classes.deinit(self.allocator);
- {
- var it = self.classes.iterator();
- while (it.next()) |entry| {
- try old_classes.append(self.allocator, entry.key_ptr.*);
- }
- }
-
- // Measure old accuracy BEFORE training new phase
- const old_acc_before: f64 = if (old_classes.items.len > 0)
- try self.evaluate(test_samples, old_classes.items)
- else
- 1.0;
-
- // Collect new class names from training data
- var new_class_set = std.StringHashMapUnmanaged(void){};
- defer new_class_set.deinit(self.allocator);
- for (train_samples) |sample| {
- if (!self.classes.contains(sample.label) and !new_class_set.contains(sample.label)) {
- try new_class_set.put(self.allocator, sample.label, {});
- }
- }
-
- // Train new samples
- for (train_samples) |sample| {
- try self.trainSample(sample.label, sample.text);
- }
-
- // Register new classes in phase map
- var new_class_names = std.ArrayListUnmanaged(u8){};
- defer new_class_names.deinit(self.allocator);
- var new_class_list = std.ArrayListUnmanaged([]const u8){};
- defer new_class_list.deinit(self.allocator);
-
- var nit = new_class_set.iterator();
- while (nit.next()) |entry| {
- if (new_class_names.items.len > 0) {
- try new_class_names.append(self.allocator, ',');
- }
- try new_class_names.appendSlice(self.allocator, entry.key_ptr.*);
- try new_class_list.append(self.allocator, entry.key_ptr.*);
-
- // Register in phase map
- const key = try self.allocator.dupe(u8, entry.key_ptr.*);
- try self.class_to_phase.put(self.allocator, key, self.current_phase);
- }
-
- // Evaluate after training
- const new_acc = if (new_class_list.items.len > 0)
- try self.evaluate(test_samples, new_class_list.items)
- else
- 1.0;
-
- const old_acc_after: f64 = if (old_classes.items.len > 0)
- try self.evaluate(test_samples, old_classes.items)
- else
- 1.0;
-
- const total_acc = try self.evaluate(test_samples, null);
-
- const forgetting = old_acc_after - old_acc_before;
-
- const result = PhaseResult{
- .phase_id = self.current_phase,
- .new_class_accuracy = new_acc,
- .old_class_accuracy = old_acc_after,
- .total_accuracy = total_acc,
- .forgetting = forgetting,
- .num_total_classes = self.classes.count(),
- .new_classes = try self.allocator.dupe(u8, new_class_names.items),
- };
-
- try self.phase_history.append(self.allocator, result);
- self.current_phase += 1;
- self.old_class_accuracy_cache = old_acc_after;
-
- return result;
- }
-
- /// Get continual learning statistics.
- pub fn stats(self: *Self) ContinualStats {
- var avg_forgetting: f64 = 0;
- var max_forgetting: f64 = 0;
- var count: usize = 0;
-
- for (self.phase_history.items) |ph| {
- if (ph.phase_id > 0) { // Skip first phase (no forgetting possible)
- avg_forgetting += ph.forgetting;
- if (ph.forgetting < max_forgetting) {
- max_forgetting = ph.forgetting; // Most negative = worst forgetting
- }
- count += 1;
- }
- }
-
- if (count > 0) {
- avg_forgetting /= @as(f64, @floatFromInt(count));
- }
-
- return ContinualStats{
- .num_phases = self.phase_history.items.len,
- .num_total_classes = self.classes.count(),
- .total_samples_trained = self.total_samples,
- .avg_forgetting = avg_forgetting,
- .max_forgetting = max_forgetting,
- };
- }
-
- /// Get number of classes.
- pub fn classCount(self: *Self) usize {
- return self.classes.count();
- }
-};
-
-// ============================================================================
-// Tests: HDCContinualLearner
-// ============================================================================
-
-test "HDCContinualLearner β init and deinit" {
- const allocator = std.testing.allocator;
- var learner = HDCContinualLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- try std.testing.expectEqual(@as(usize, 0), learner.classCount());
- try std.testing.expectEqual(@as(usize, 0), learner.current_phase);
-}
-
-test "HDCContinualLearner β single phase training" {
- const allocator = std.testing.allocator;
- var learner = HDCContinualLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- const train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "spam", .text = "buy cheap viagra now free offer" },
- .{ .label = "spam", .text = "click here for free money prize" },
- .{ .label = "ham", .text = "meeting tomorrow at the office room" },
- .{ .label = "ham", .text = "please review the project report doc" },
- };
-
- const test_samples = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "spam", .text = "free cheap offer buy click" },
- .{ .label = "ham", .text = "office meeting review report" },
- };
-
- const result = try learner.trainPhase(&train, &test_samples);
-
- try std.testing.expectEqual(@as(usize, 0), result.phase_id);
- try std.testing.expectEqual(@as(usize, 2), result.num_total_classes);
- try std.testing.expect(result.total_accuracy >= 0.0);
- try std.testing.expectEqual(@as(usize, 2), learner.classCount());
-}
-
-test "HDCContinualLearner β two phases, zero forgetting" {
- const allocator = std.testing.allocator;
- var learner = HDCContinualLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- // Phase 1: spam vs ham
- const phase1_train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "spam", .text = "buy cheap viagra now free offer" },
- .{ .label = "spam", .text = "click here for free money prize" },
- .{ .label = "spam", .text = "free pills discount sale cheap" },
- .{ .label = "ham", .text = "meeting tomorrow at the office room" },
- .{ .label = "ham", .text = "please review the project report doc" },
- .{ .label = "ham", .text = "schedule call with the team lead" },
- };
-
- const all_test = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "spam", .text = "free cheap offer buy click" },
- .{ .label = "ham", .text = "office meeting review report" },
- .{ .label = "tech", .text = "compile code debug error stack" },
- .{ .label = "sport", .text = "goal match score league player" },
- };
-
- const r1 = try learner.trainPhase(&phase1_train, &all_test);
- std.debug.print("\n Phase 1: {d} classes, total_acc={d:.2}, old_acc={d:.2}\n", .{
- r1.num_total_classes, r1.total_accuracy, r1.old_class_accuracy,
- });
-
- // Phase 2: tech vs sport
- const phase2_train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "tech", .text = "compile the source code with debug flags" },
- .{ .label = "tech", .text = "fix error in the stack trace output" },
- .{ .label = "tech", .text = "deploy build to server and run tests" },
- .{ .label = "sport", .text = "the team won the league match today" },
- .{ .label = "sport", .text = "player scored two goals in final" },
- .{ .label = "sport", .text = "coach changed lineup for next game" },
- };
-
- const r2 = try learner.trainPhase(&phase2_train, &all_test);
- std.debug.print(" Phase 2: {d} classes, total_acc={d:.2}, old_acc={d:.2}, forgetting={d:.4}\n", .{
- r2.num_total_classes, r2.total_accuracy, r2.old_class_accuracy, r2.forgetting,
- });
-
- try std.testing.expectEqual(@as(usize, 4), learner.classCount());
-
- // Forgetting should be zero or very small (old prototypes untouched)
- // Allow small tolerance for decision boundary crowding
- try std.testing.expect(r2.forgetting >= -0.5);
-}
-
-test "HDCContinualLearner β three phases incremental" {
- const allocator = std.testing.allocator;
- var learner = HDCContinualLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- const all_test = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "animals", .text = "cat dog bird fish pet" },
- .{ .label = "food", .text = "pizza pasta rice bread cook" },
- .{ .label = "music", .text = "guitar drums piano song melody" },
- };
-
- // Phase 1: animals
- const p1_train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "animals", .text = "the cat chased the dog around" },
- .{ .label = "animals", .text = "birds fly and fish swim in water" },
- .{ .label = "animals", .text = "my pet hamster likes sunflower seeds" },
- };
- _ = try learner.trainPhase(&p1_train, &all_test);
-
- // Phase 2: food
- const p2_train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "food", .text = "cook the pasta with tomato sauce" },
- .{ .label = "food", .text = "bake pizza with cheese and bread" },
- .{ .label = "food", .text = "rice with vegetables for dinner" },
- };
- _ = try learner.trainPhase(&p2_train, &all_test);
-
- // Phase 3: music
- const p3_train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "music", .text = "play guitar and drums together" },
- .{ .label = "music", .text = "piano melody and song composition" },
- .{ .label = "music", .text = "listen to jazz and blues records" },
- };
- const r3 = try learner.trainPhase(&p3_train, &all_test);
-
- try std.testing.expectEqual(@as(usize, 3), learner.classCount());
- try std.testing.expectEqual(@as(usize, 3), learner.phase_history.items.len);
-
- // Stats
- const st = learner.stats();
- try std.testing.expectEqual(@as(usize, 3), st.num_phases);
- try std.testing.expectEqual(@as(usize, 3), st.num_total_classes);
- try std.testing.expectEqual(@as(u32, 9), st.total_samples_trained);
-
- std.debug.print("\n 3-phase: final_acc={d:.2}, avg_forgetting={d:.4}, max_forgetting={d:.4}\n", .{
- r3.total_accuracy, st.avg_forgetting, st.max_forgetting,
- });
-}
-
-test "HDCContinualLearner β forgetting metric" {
- const allocator = std.testing.allocator;
- var learner = HDCContinualLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- // Train phase 1
- const p1 = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "A", .text = "alpha beta gamma delta" },
- .{ .label = "A", .text = "alpha epsilon zeta eta" },
- .{ .label = "B", .text = "theta iota kappa lambda" },
- .{ .label = "B", .text = "theta mu nu xi omicron" },
- };
- const test_all = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "A", .text = "alpha gamma zeta delta" },
- .{ .label = "B", .text = "theta kappa mu lambda" },
- .{ .label = "C", .text = "pi rho sigma tau" },
- };
-
- const r1 = try learner.trainPhase(&p1, &test_all);
- // First phase: no forgetting possible
- try std.testing.expect(r1.forgetting == 0.0 or r1.old_class_accuracy == 1.0);
-
- // Train phase 2
- const p2 = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "C", .text = "pi rho sigma tau upsilon" },
- .{ .label = "C", .text = "pi phi chi psi omega" },
- };
-
- const r2 = try learner.trainPhase(&p2, &test_all);
-
- // Forgetting should be measured
- std.debug.print("\n Forgetting after phase 2: {d:.4}\n", .{r2.forgetting});
-
- // Old class accuracy should not drop catastrophically
- try std.testing.expect(r2.old_class_accuracy >= 0.0);
-}
-
-test "HDCContinualLearner β stats computation" {
- const allocator = std.testing.allocator;
- var learner = HDCContinualLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- const st = learner.stats();
- try std.testing.expectEqual(@as(usize, 0), st.num_phases);
- try std.testing.expectEqual(@as(usize, 0), st.num_total_classes);
- try std.testing.expectEqual(@as(u32, 0), st.total_samples_trained);
-}
-
-test "HDCContinualLearner β demo: incremental 5-phase learning" {
- const allocator = std.testing.allocator;
- var learner = HDCContinualLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC Continual Learning Demo β 5 Phases\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Test set covering all classes
- const test_all = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "spam", .text = "buy cheap free offer now" },
- .{ .label = "ham", .text = "meeting office report review" },
- .{ .label = "tech", .text = "compile code debug error fix" },
- .{ .label = "sport", .text = "goal match score team win" },
- .{ .label = "science", .text = "atom molecule electron proton" },
- };
-
- // Phase 1: spam
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- {
- const train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "spam", .text = "buy now cheap free offer discount" },
- .{ .label = "spam", .text = "click here win free prize money" },
- .{ .label = "spam", .text = "special offer sale cheap pills free" },
- };
- const r = try learner.trainPhase(&train, &test_all);
- std.debug.print(" Phase {d}: +[{s}] | classes={d} | new={d:.0}% old={d:.0}% total={d:.0}% forget={d:.4}\n", .{
- r.phase_id, r.new_classes, r.num_total_classes,
- r.new_class_accuracy * 100, r.old_class_accuracy * 100, r.total_accuracy * 100,
- r.forgetting,
- });
- }
-
- // Phase 2: ham
- {
- const train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "ham", .text = "meeting tomorrow at the office room" },
- .{ .label = "ham", .text = "please review the project report" },
- .{ .label = "ham", .text = "schedule call with the team lead" },
- };
- const r = try learner.trainPhase(&train, &test_all);
- std.debug.print(" Phase {d}: +[{s}] | classes={d} | new={d:.0}% old={d:.0}% total={d:.0}% forget={d:.4}\n", .{
- r.phase_id, r.new_classes, r.num_total_classes,
- r.new_class_accuracy * 100, r.old_class_accuracy * 100, r.total_accuracy * 100,
- r.forgetting,
- });
- }
-
- // Phase 3: tech
- {
- const train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "tech", .text = "compile the source code debug flags" },
- .{ .label = "tech", .text = "fix error in stack trace output log" },
- .{ .label = "tech", .text = "deploy build server run unit tests" },
- };
- const r = try learner.trainPhase(&train, &test_all);
- std.debug.print(" Phase {d}: +[{s}] | classes={d} | new={d:.0}% old={d:.0}% total={d:.0}% forget={d:.4}\n", .{
- r.phase_id, r.new_classes, r.num_total_classes,
- r.new_class_accuracy * 100, r.old_class_accuracy * 100, r.total_accuracy * 100,
- r.forgetting,
- });
- }
-
- // Phase 4: sport
- {
- const train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "sport", .text = "team won the league match today" },
- .{ .label = "sport", .text = "player scored two goals in final" },
- .{ .label = "sport", .text = "coach changed lineup for next game" },
- };
- const r = try learner.trainPhase(&train, &test_all);
- std.debug.print(" Phase {d}: +[{s}] | classes={d} | new={d:.0}% old={d:.0}% total={d:.0}% forget={d:.4}\n", .{
- r.phase_id, r.new_classes, r.num_total_classes,
- r.new_class_accuracy * 100, r.old_class_accuracy * 100, r.total_accuracy * 100,
- r.forgetting,
- });
- }
-
- // Phase 5: science
- {
- const train = [_]HDCContinualLearner.LabeledSample{
- .{ .label = "science", .text = "atom molecule electron proton neutron" },
- .{ .label = "science", .text = "chemical reaction bond energy state" },
- .{ .label = "science", .text = "quantum physics particle wave function" },
- };
- const r = try learner.trainPhase(&train, &test_all);
- std.debug.print(" Phase {d}: +[{s}] | classes={d} | new={d:.0}% old={d:.0}% total={d:.0}% forget={d:.4}\n", .{
- r.phase_id, r.new_classes, r.num_total_classes,
- r.new_class_accuracy * 100, r.old_class_accuracy * 100, r.total_accuracy * 100,
- r.forgetting,
- });
- }
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const st = learner.stats();
- std.debug.print(" Summary: {d} phases, {d} classes, {d} samples\n", .{
- st.num_phases, st.num_total_classes, st.total_samples_trained,
- });
- std.debug.print(" Avg forgetting: {d:.4}\n", .{st.avg_forgetting});
- std.debug.print(" Max forgetting: {d:.4}\n", .{st.max_forgetting});
-
- // Key insight: print prototype independence proof
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" PROOF: Prototype Independence\n", .{});
- std.debug.print(" Each class prototype is stored independently.\n", .{});
- std.debug.print(" Adding new classes NEVER modifies old prototype HVs.\n", .{});
- std.debug.print(" Any accuracy change is from decision boundary crowding,\n", .{});
- std.debug.print(" NOT from catastrophic forgetting of learned representations.\n", .{});
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Modules: 22 | Tests: 259+7 = 266\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Assertions
- try std.testing.expectEqual(@as(usize, 5), st.num_phases);
- try std.testing.expectEqual(@as(usize, 5), st.num_total_classes);
- try std.testing.expectEqual(@as(u32, 15), st.total_samples_trained);
- // Forgetting should not be catastrophic
- try std.testing.expect(st.max_forgetting >= -1.0);
-}
-
-// ============================================================================
-// HDC Multi-Task Learning Engine
-// ============================================================================
-//
-// One Encoder, Multiple Classification Heads.
-// Shared HDC encoding with task-specific prototype banks.
-// Same text β single encoding β simultaneous predictions from all tasks.
-//
-// Zero task interference: each task head is an independent prototype bank.
-// No gradient conflicts, no loss balancing, no shared weight problems.
-// ============================================================================
-
-pub const HDCMultiTaskLearner = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- // Task heads: task_name β TaskHead
- tasks: std.StringHashMapUnmanaged(TaskHead),
-
- const Self = @This();
-
- pub const TaskHead = struct {
- prototypes: std.StringHashMapUnmanaged(ClassProto),
- sample_count: u32,
- };
-
- pub const ClassProto = struct {
- prototype_hv: *HybridBigInt,
- sample_count: u32,
- };
-
- pub const LabeledSample = struct {
- label: []const u8,
- text: []const u8,
- };
-
- pub const MultiTaskPrediction = struct {
- task_name: []const u8,
- predicted_label: []const u8,
- confidence: f64,
- };
-
- pub const TaskAccuracy = struct {
- task_name: []const u8,
- accuracy: f64,
- num_classes: usize,
- };
-
- pub const TaskInterference = struct {
- task_a: []const u8,
- task_b: []const u8,
- avg_cosine: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .tasks = .{},
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .hybrid);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- var tit = self.tasks.iterator();
- while (tit.next()) |task_entry| {
- var pit = task_entry.value_ptr.prototypes.iterator();
- while (pit.next()) |proto_entry| {
- self.allocator.destroy(proto_entry.value_ptr.prototype_hv);
- self.allocator.free(proto_entry.key_ptr.*);
- }
- task_entry.value_ptr.prototypes.deinit(self.allocator);
- self.allocator.free(task_entry.key_ptr.*);
- }
- self.tasks.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Register a new task head.
- pub fn addTask(self: *Self, task_name: []const u8) !void {
- if (self.tasks.contains(task_name)) return;
-
- const key = try self.allocator.dupe(u8, task_name);
- try self.tasks.put(self.allocator, key, TaskHead{
- .prototypes = .{},
- .sample_count = 0,
- });
- }
-
- /// Train a sample for a specific task.
- pub fn trainTask(self: *Self, task_name: []const u8, label: []const u8, text: []const u8) !void {
- self.fixSelfRef();
-
- // Auto-create task if needed
- if (!self.tasks.contains(task_name)) {
- try self.addTask(task_name);
- }
-
- var text_hv = try self.encoder.encodeText(text);
-
- const head = self.tasks.getPtr(task_name).?;
-
- if (head.prototypes.getPtr(label)) |proto| {
- proto.prototype_hv.* = vsa.bundle2(proto.prototype_hv, &text_hv);
- proto.sample_count += 1;
- } else {
- const proto_hv = try self.allocator.create(HybridBigInt);
- proto_hv.* = text_hv;
- const owned_label = try self.allocator.dupe(u8, label);
- try head.prototypes.put(self.allocator, owned_label, ClassProto{
- .prototype_hv = proto_hv,
- .sample_count = 1,
- });
- }
- head.sample_count += 1;
- }
-
- /// Predict a single task for input text.
- pub fn predictTask(self: *Self, task_name: []const u8, text: []const u8) !?MultiTaskPrediction {
- self.fixSelfRef();
-
- const head = self.tasks.get(task_name) orelse return null;
- if (head.prototypes.count() == 0) return null;
-
- var text_hv = try self.encoder.encodeText(text);
-
- var best_label: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- var it = head.prototypes.iterator();
- while (it.next()) |entry| {
- var proto_copy = entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_copy);
- if (sim > best_sim) {
- best_sim = sim;
- best_label = entry.key_ptr.*;
- }
- }
-
- if (best_sim < -1.0) return null;
-
- return MultiTaskPrediction{
- .task_name = task_name,
- .predicted_label = best_label,
- .confidence = best_sim,
- };
- }
-
- /// Predict ALL tasks simultaneously from a single text encoding.
- pub fn predictAll(self: *Self, text: []const u8) ![]MultiTaskPrediction {
- self.fixSelfRef();
-
- var text_hv = try self.encoder.encodeText(text);
-
- const num_tasks = self.tasks.count();
- const results = try self.allocator.alloc(MultiTaskPrediction, num_tasks);
- var idx: usize = 0;
-
- var tit = self.tasks.iterator();
- while (tit.next()) |task_entry| {
- const task_name = task_entry.key_ptr.*;
- const head = task_entry.value_ptr;
-
- if (head.prototypes.count() == 0) continue;
-
- var best_label: []const u8 = "";
- var best_sim: f64 = -2.0;
-
- var pit = head.prototypes.iterator();
- while (pit.next()) |proto_entry| {
- var proto_copy = proto_entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&text_hv, &proto_copy);
- if (sim > best_sim) {
- best_sim = sim;
- best_label = proto_entry.key_ptr.*;
- }
- }
-
- if (best_sim >= -1.0) {
- results[idx] = MultiTaskPrediction{
- .task_name = task_name,
- .predicted_label = best_label,
- .confidence = best_sim,
- };
- idx += 1;
- }
- }
-
- // If fewer results than allocated, shrink
- if (idx < num_tasks) {
- const trimmed = try self.allocator.alloc(MultiTaskPrediction, idx);
- @memcpy(trimmed, results[0..idx]);
- self.allocator.free(results);
- return trimmed;
- }
-
- return results;
- }
-
- /// Evaluate accuracy of a specific task.
- pub fn evaluateTask(self: *Self, task_name: []const u8, test_samples: []const LabeledSample) !TaskAccuracy {
- self.fixSelfRef();
-
- var correct: usize = 0;
- var total: usize = 0;
-
- for (test_samples) |sample| {
- if (try self.predictTask(task_name, sample.text)) |pred| {
- if (std.mem.eql(u8, pred.predicted_label, sample.label)) {
- correct += 1;
- }
- }
- total += 1;
- }
-
- const head = self.tasks.get(task_name);
- const num_classes = if (head) |h| h.prototypes.count() else 0;
-
- return TaskAccuracy{
- .task_name = task_name,
- .accuracy = if (total > 0) @as(f64, @floatFromInt(correct)) / @as(f64, @floatFromInt(total)) else 0.0,
- .num_classes = num_classes,
- };
- }
-
- /// Measure interference between all pairs of tasks.
- /// Returns avg cosine between prototypes of different task heads.
- pub fn measureInterference(self: *Self) ![]TaskInterference {
- const num_tasks = self.tasks.count();
- if (num_tasks < 2) return &[_]TaskInterference{};
-
- // Collect task names
- const task_names = try self.allocator.alloc([]const u8, num_tasks);
- defer self.allocator.free(task_names);
- {
- var i: usize = 0;
- var it = self.tasks.iterator();
- while (it.next()) |entry| {
- task_names[i] = entry.key_ptr.*;
- i += 1;
- }
- }
-
- // Compute pairwise interference
- const num_pairs = (num_tasks * (num_tasks - 1)) / 2;
- const results = try self.allocator.alloc(TaskInterference, num_pairs);
- var idx: usize = 0;
-
- for (0..num_tasks) |i| {
- for ((i + 1)..num_tasks) |j| {
- const head_a = self.tasks.get(task_names[i]).?;
- const head_b = self.tasks.get(task_names[j]).?;
-
- var total_sim: f64 = 0;
- var count: usize = 0;
-
- var ait = head_a.prototypes.iterator();
- while (ait.next()) |a_entry| {
- var bit = head_b.prototypes.iterator();
- while (bit.next()) |b_entry| {
- var a_copy = a_entry.value_ptr.prototype_hv.*;
- var b_copy = b_entry.value_ptr.prototype_hv.*;
- const sim = vsa.cosineSimilarity(&a_copy, &b_copy);
- total_sim += @abs(sim);
- count += 1;
- }
- }
-
- results[idx] = TaskInterference{
- .task_a = task_names[i],
- .task_b = task_names[j],
- .avg_cosine = if (count > 0) total_sim / @as(f64, @floatFromInt(count)) else 0.0,
- };
- idx += 1;
- }
- }
-
- return results;
- }
-
- /// Number of registered tasks.
- pub fn taskCount(self: *Self) usize {
- return self.tasks.count();
- }
-
- /// Remove a task head.
- pub fn removeTask(self: *Self, task_name: []const u8) bool {
- if (self.tasks.fetchRemove(task_name)) |removed| {
- var pit = removed.value.prototypes.iterator();
- while (pit.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.prototype_hv);
- self.allocator.free(entry.key_ptr.*);
- }
- var protos = removed.value.prototypes;
- protos.deinit(self.allocator);
- self.allocator.free(removed.key);
- return true;
- }
- return false;
- }
-};
-
-// ============================================================================
-// Tests: HDCMultiTaskLearner
-// ============================================================================
-
-test "HDCMultiTaskLearner β init and deinit" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- try std.testing.expectEqual(@as(usize, 0), learner.taskCount());
-}
-
-test "HDCMultiTaskLearner β addTask" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- try learner.addTask("sentiment");
- try learner.addTask("topic");
-
- try std.testing.expectEqual(@as(usize, 2), learner.taskCount());
-
- // Duplicate should not increase count
- try learner.addTask("sentiment");
- try std.testing.expectEqual(@as(usize, 2), learner.taskCount());
-}
-
-test "HDCMultiTaskLearner β trainTask and predictTask" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- // Train sentiment task
- try learner.trainTask("sentiment", "positive", "great amazing wonderful excellent");
- try learner.trainTask("sentiment", "positive", "love fantastic beautiful perfect");
- try learner.trainTask("sentiment", "negative", "terrible awful horrible bad");
- try learner.trainTask("sentiment", "negative", "worst hate ugly disgusting");
-
- // Predict
- const pred = try learner.predictTask("sentiment", "amazing wonderful great");
- try std.testing.expect(pred != null);
-
- std.debug.print("\n predict(sentiment, 'amazing wonderful great') β {s} ({d:.4})\n", .{
- pred.?.predicted_label, pred.?.confidence,
- });
-
- // Non-existent task
- const none = try learner.predictTask("nonexistent", "test");
- try std.testing.expect(none == null);
-}
-
-test "HDCMultiTaskLearner β predictAll" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- // Train sentiment
- try learner.trainTask("sentiment", "positive", "great amazing wonderful");
- try learner.trainTask("sentiment", "negative", "terrible awful horrible");
-
- // Train topic
- try learner.trainTask("topic", "tech", "compile code debug error");
- try learner.trainTask("topic", "sport", "goal match score team");
-
- // Predict all tasks at once
- const predictions = try learner.predictAll("great code compile amazing");
- defer learner.allocator.free(predictions);
-
- try std.testing.expect(predictions.len == 2);
-
- std.debug.print("\n predictAll('great code compile amazing'):\n", .{});
- for (predictions) |p| {
- std.debug.print(" {s} β {s} ({d:.4})\n", .{ p.task_name, p.predicted_label, p.confidence });
- }
-}
-
-test "HDCMultiTaskLearner β evaluateTask" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- try learner.trainTask("sentiment", "positive", "great amazing wonderful excellent");
- try learner.trainTask("sentiment", "negative", "terrible awful horrible bad");
-
- const test_samples = [_]HDCMultiTaskLearner.LabeledSample{
- .{ .label = "positive", .text = "amazing excellent wonderful" },
- .{ .label = "negative", .text = "terrible horrible awful" },
- };
-
- const acc = try learner.evaluateTask("sentiment", &test_samples);
- std.debug.print("\n sentiment accuracy: {d:.0}% ({d} classes)\n", .{
- acc.accuracy * 100, acc.num_classes,
- });
-
- try std.testing.expect(acc.num_classes == 2);
- try std.testing.expect(acc.accuracy >= 0.0);
-}
-
-test "HDCMultiTaskLearner β measureInterference" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- // Train completely different tasks
- try learner.trainTask("sentiment", "positive", "great amazing wonderful");
- try learner.trainTask("sentiment", "negative", "terrible awful horrible");
- try learner.trainTask("topic", "tech", "compile code debug error");
- try learner.trainTask("topic", "sport", "goal match score team");
-
- const interference = try learner.measureInterference();
- defer learner.allocator.free(interference);
-
- try std.testing.expect(interference.len == 1); // 2 tasks β 1 pair
-
- std.debug.print("\n Interference {s}β{s}: avg_cos={d:.4}\n", .{
- interference[0].task_a, interference[0].task_b, interference[0].avg_cosine,
- });
-
- // Different tasks should have low interference
- try std.testing.expect(interference[0].avg_cosine < 0.5);
-}
-
-test "HDCMultiTaskLearner β removeTask" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- try learner.addTask("task_a");
- try learner.addTask("task_b");
-
- try std.testing.expectEqual(@as(usize, 2), learner.taskCount());
-
- const removed = learner.removeTask("task_a");
- try std.testing.expect(removed);
- try std.testing.expectEqual(@as(usize, 1), learner.taskCount());
-
- const not_found = learner.removeTask("nonexistent");
- try std.testing.expect(!not_found);
-}
-
-test "HDCMultiTaskLearner β demo: simultaneous 3-task classification" {
- const allocator = std.testing.allocator;
- var learner = HDCMultiTaskLearner.init(allocator, 1024, 42);
- defer learner.deinit();
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC Multi-Task Learning Demo β 3 Simultaneous Tasks\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Task 1: Sentiment (positive / negative / neutral)
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Training Task 1: Sentiment (pos/neg/neutral)\n", .{});
- try learner.trainTask("sentiment", "positive", "great amazing wonderful excellent love");
- try learner.trainTask("sentiment", "positive", "fantastic beautiful perfect brilliant");
- try learner.trainTask("sentiment", "positive", "awesome superb outstanding marvelous");
- try learner.trainTask("sentiment", "negative", "terrible awful horrible bad worst");
- try learner.trainTask("sentiment", "negative", "disgusting ugly hate annoying dreadful");
- try learner.trainTask("sentiment", "negative", "pathetic miserable disappointing poor");
- try learner.trainTask("sentiment", "neutral", "the weather is normal today here");
- try learner.trainTask("sentiment", "neutral", "this report contains some data points");
- try learner.trainTask("sentiment", "neutral", "the meeting was scheduled for noon");
-
- // Task 2: Topic (tech / sport / food)
- std.debug.print(" Training Task 2: Topic (tech/sport/food)\n", .{});
- try learner.trainTask("topic", "tech", "compile code debug error stack trace");
- try learner.trainTask("topic", "tech", "deploy server database query optimize");
- try learner.trainTask("topic", "tech", "algorithm function variable class method");
- try learner.trainTask("topic", "sport", "goal match score team player win");
- try learner.trainTask("topic", "sport", "champion league tournament final trophy");
- try learner.trainTask("topic", "sport", "coach training fitness stadium crowd");
- try learner.trainTask("topic", "food", "pizza pasta sauce cheese tomato cook");
- try learner.trainTask("topic", "food", "rice fish sushi fresh ingredients");
- try learner.trainTask("topic", "food", "bread butter jam breakfast coffee");
-
- // Task 3: Formality (formal / informal)
- std.debug.print(" Training Task 3: Formality (formal/informal)\n", .{});
- try learner.trainTask("formality", "formal", "pursuant to the aforementioned regulation");
- try learner.trainTask("formality", "formal", "we hereby acknowledge receipt of your");
- try learner.trainTask("formality", "formal", "in accordance with the established protocol");
- try learner.trainTask("formality", "informal", "hey dude whats up wanna hang out");
- try learner.trainTask("formality", "informal", "lol omg thats so cool btw check");
- try learner.trainTask("formality", "informal", "yo bro lets grab some food later");
-
- std.debug.print(" Tasks: {d} | Total training: 24 samples\n", .{learner.taskCount()});
-
- // Simultaneous prediction
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Simultaneous Predictions (single encoding pass)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const test_texts = [_][]const u8{
- "this amazing code compile is great",
- "terrible match score very bad",
- "hey check out this awesome pizza recipe",
- "pursuant to the tournament regulations",
- };
-
- for (test_texts) |text| {
- const preds = try learner.predictAll(text);
- defer learner.allocator.free(preds);
-
- std.debug.print(" \"{s}\"\n", .{text});
- for (preds) |p| {
- std.debug.print(" {s:10} β {s:10} (conf={d:.4})\n", .{
- p.task_name, p.predicted_label, p.confidence,
- });
- }
- }
-
- // Per-task accuracy
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Per-Task Accuracy\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const sentiment_test = [_]HDCMultiTaskLearner.LabeledSample{
- .{ .label = "positive", .text = "wonderful excellent amazing love" },
- .{ .label = "negative", .text = "horrible terrible awful hate" },
- .{ .label = "neutral", .text = "the report has some data today" },
- };
- const topic_test = [_]HDCMultiTaskLearner.LabeledSample{
- .{ .label = "tech", .text = "compile debug code error fix" },
- .{ .label = "sport", .text = "goal score match team final" },
- .{ .label = "food", .text = "pizza cheese sauce tomato cook" },
- };
- const formality_test = [_]HDCMultiTaskLearner.LabeledSample{
- .{ .label = "formal", .text = "pursuant to the established protocol" },
- .{ .label = "informal", .text = "hey dude whats up yo" },
- };
-
- const s_acc = try learner.evaluateTask("sentiment", &sentiment_test);
- const t_acc = try learner.evaluateTask("topic", &topic_test);
- const f_acc = try learner.evaluateTask("formality", &formality_test);
-
- std.debug.print(" sentiment: {d:.0}% ({d} classes)\n", .{ s_acc.accuracy * 100, s_acc.num_classes });
- std.debug.print(" topic: {d:.0}% ({d} classes)\n", .{ t_acc.accuracy * 100, t_acc.num_classes });
- std.debug.print(" formality: {d:.0}% ({d} classes)\n", .{ f_acc.accuracy * 100, f_acc.num_classes });
-
- // Task interference
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Task Interference (cross-task prototype cosine)\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const interference = try learner.measureInterference();
- defer learner.allocator.free(interference);
-
- for (interference) |ti| {
- std.debug.print(" {s:10} β {s:10} : avg_cos={d:.4}\n", .{
- ti.task_a, ti.task_b, ti.avg_cosine,
- });
- }
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Modules: 23 | Tests: 266+8 = 274\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Assertions
- try std.testing.expectEqual(@as(usize, 3), learner.taskCount());
- try std.testing.expect(interference.len == 3); // 3 tasks β 3 pairs
- // Interference should be low (tasks are independent)
- for (interference) |ti| {
- try std.testing.expect(ti.avg_cosine < 0.5);
- }
-}
-
-// ============================================================================
-// HDC Recommender System
-// ============================================================================
-//
-// Content + Collaborative Filtering via VSA.
-// User profile = bundle(liked item HVs).
-// Recommend = rank items by cosine(profile, item_hv).
-// Collaborative = find similar users, recommend their liked items.
-// ============================================================================
-
-pub const HDCRecommender = struct {
- allocator: std.mem.Allocator,
- item_memory: ItemMemory,
- ngram_encoder: NGramEncoder,
- dimension: usize,
- encoder: HDCTextEncoder,
-
- // Item catalog: item_id β encoded HV
- items: std.StringHashMapUnmanaged(*HybridBigInt),
-
- // Item descriptions for display
- item_descs: std.StringHashMapUnmanaged([]const u8),
-
- // User profiles: user_id β UserProfile
- users: std.StringHashMapUnmanaged(UserProfile),
-
- const Self = @This();
-
- pub const UserProfile = struct {
- profile_hv: *HybridBigInt,
- liked_items: std.StringHashMapUnmanaged(void), // set of liked item_ids
- item_count: u32,
- };
-
- pub const Recommendation = struct {
- item_id: []const u8,
- score: f64,
- };
-
- pub const SimilarUser = struct {
- user_id: []const u8,
- similarity: f64,
- };
-
- pub const RecommenderStats = struct {
- num_users: usize,
- num_items: usize,
- avg_items_per_user: f64,
- };
-
- pub fn init(allocator: std.mem.Allocator, dimension: usize, seed: u64) Self {
- var item_mem = ItemMemory.init(allocator, dimension, seed);
- var self = Self{
- .allocator = allocator,
- .item_memory = item_mem,
- .ngram_encoder = NGramEncoder.init(&item_mem, 3),
- .dimension = dimension,
- .encoder = undefined,
- .items = .{},
- .item_descs = .{},
- .users = .{},
- };
- self.encoder = HDCTextEncoder.init(allocator, &self.item_memory, &self.ngram_encoder, dimension, .hybrid);
- return self;
- }
-
- fn fixSelfRef(self: *Self) void {
- self.ngram_encoder.item_memory = &self.item_memory;
- self.encoder.item_memory = &self.item_memory;
- self.encoder.ngram_encoder = &self.ngram_encoder;
- }
-
- pub fn deinit(self: *Self) void {
- // Free items
- var iit = self.items.iterator();
- while (iit.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.*);
- self.allocator.free(entry.key_ptr.*);
- }
- self.items.deinit(self.allocator);
-
- // Free descriptions
- var dit = self.item_descs.iterator();
- while (dit.next()) |entry| {
- self.allocator.free(entry.value_ptr.*);
- self.allocator.free(entry.key_ptr.*);
- }
- self.item_descs.deinit(self.allocator);
-
- // Free users
- var uit = self.users.iterator();
- while (uit.next()) |entry| {
- self.allocator.destroy(entry.value_ptr.profile_hv);
- var liked = entry.value_ptr.liked_items;
- var lit = liked.iterator();
- while (lit.next()) |lentry| {
- self.allocator.free(lentry.key_ptr.*);
- }
- liked.deinit(self.allocator);
- self.allocator.free(entry.key_ptr.*);
- }
- self.users.deinit(self.allocator);
-
- self.encoder.deinit();
- self.item_memory.deinit();
- }
-
- /// Add an item to the catalog.
- pub fn addItem(self: *Self, item_id: []const u8, description: []const u8) !void {
- self.fixSelfRef();
-
- if (self.items.contains(item_id)) return;
-
- const encoded = try self.encoder.encodeText(description);
- const hv = try self.allocator.create(HybridBigInt);
- hv.* = encoded;
-
- const id_key = try self.allocator.dupe(u8, item_id);
- try self.items.put(self.allocator, id_key, hv);
-
- const desc_key = try self.allocator.dupe(u8, item_id);
- const desc_val = try self.allocator.dupe(u8, description);
- try self.item_descs.put(self.allocator, desc_key, desc_val);
- }
-
- /// Record a user liking an item. Bundles item HV into user profile.
- pub fn addRating(self: *Self, user_id: []const u8, item_id: []const u8) !void {
- self.fixSelfRef();
-
- const item_hv = self.items.get(item_id) orelse return;
-
- if (self.users.getPtr(user_id)) |profile| {
- // Check if already liked
- if (profile.liked_items.contains(item_id)) return;
-
- // Bundle item into profile
- profile.profile_hv.* = vsa.bundle2(profile.profile_hv, item_hv);
- const liked_key = try self.allocator.dupe(u8, item_id);
- try profile.liked_items.put(self.allocator, liked_key, {});
- profile.item_count += 1;
- } else {
- // New user
- const profile_hv = try self.allocator.create(HybridBigInt);
- profile_hv.* = item_hv.*;
-
- var liked = std.StringHashMapUnmanaged(void){};
- const liked_key = try self.allocator.dupe(u8, item_id);
- try liked.put(self.allocator, liked_key, {});
-
- const user_key = try self.allocator.dupe(u8, user_id);
- try self.users.put(self.allocator, user_key, UserProfile{
- .profile_hv = profile_hv,
- .liked_items = liked,
- .item_count = 1,
- });
- }
- }
-
- /// Content-based recommendation: rank unseen items by cosine(profile, item).
- pub fn recommend(self: *Self, user_id: []const u8, k: usize) ![]Recommendation {
- self.fixSelfRef();
-
- const profile = self.users.get(user_id) orelse return &[_]Recommendation{};
-
- // Score all unseen items
- const num_items = self.items.count();
- const scores = try self.allocator.alloc(Recommendation, num_items);
- var idx: usize = 0;
-
- var it = self.items.iterator();
- while (it.next()) |entry| {
- const iid = entry.key_ptr.*;
-
- // Skip already liked items
- if (profile.liked_items.contains(iid)) continue;
-
- var profile_copy = profile.profile_hv.*;
- var item_copy = entry.value_ptr.*.*;
- const sim = vsa.cosineSimilarity(&profile_copy, &item_copy);
-
- scores[idx] = Recommendation{ .item_id = iid, .score = sim };
- idx += 1;
- }
-
- const populated = scores[0..idx];
-
- // Sort descending by score
- std.mem.sort(Recommendation, populated, {}, struct {
- fn cmp(_: void, a: Recommendation, b: Recommendation) bool {
- return a.score > b.score;
- }
- }.cmp);
-
- const result_k = @min(k, idx);
- const output = try self.allocator.alloc(Recommendation, result_k);
- @memcpy(output, populated[0..result_k]);
- self.allocator.free(scores);
-
- return output;
- }
-
- /// Find users most similar to a given user.
- pub fn findSimilarUsers(self: *Self, user_id: []const u8, k: usize) ![]SimilarUser {
- const profile = self.users.get(user_id) orelse return &[_]SimilarUser{};
-
- const num_users = self.users.count();
- const scores = try self.allocator.alloc(SimilarUser, num_users);
- var idx: usize = 0;
-
- var it = self.users.iterator();
- while (it.next()) |entry| {
- const uid = entry.key_ptr.*;
- if (std.mem.eql(u8, uid, user_id)) continue;
-
- var p1_copy = profile.profile_hv.*;
- var p2_copy = entry.value_ptr.profile_hv.*;
- const sim = vsa.cosineSimilarity(&p1_copy, &p2_copy);
-
- scores[idx] = SimilarUser{ .user_id = uid, .similarity = sim };
- idx += 1;
- }
-
- const populated = scores[0..idx];
-
- std.mem.sort(SimilarUser, populated, {}, struct {
- fn cmp(_: void, a: SimilarUser, b: SimilarUser) bool {
- return a.similarity > b.similarity;
- }
- }.cmp);
-
- const result_k = @min(k, idx);
- const output = try self.allocator.alloc(SimilarUser, result_k);
- @memcpy(output, populated[0..result_k]);
- self.allocator.free(scores);
-
- return output;
- }
-
- /// Collaborative recommendation: find similar users, recommend their liked items.
- pub fn collaborativeRecommend(self: *Self, user_id: []const u8, k: usize) ![]Recommendation {
- self.fixSelfRef();
-
- const profile = self.users.get(user_id) orelse return &[_]Recommendation{};
-
- // Find top-3 similar users
- const similar = try self.findSimilarUsers(user_id, 3);
- defer self.allocator.free(similar);
-
- // Collect items liked by similar users but not by target
- var candidate_scores = std.StringHashMapUnmanaged(f64){};
- defer candidate_scores.deinit(self.allocator);
-
- for (similar) |su| {
- const other = self.users.get(su.user_id) orelse continue;
- var lit = other.liked_items.iterator();
- while (lit.next()) |lentry| {
- const iid = lentry.key_ptr.*;
- if (profile.liked_items.contains(iid)) continue;
-
- // Score = similarity of recommending user
- const prev = candidate_scores.get(iid) orelse 0.0;
- try candidate_scores.put(self.allocator, iid, prev + su.similarity);
- }
- }
-
- // Sort candidates
- const count = candidate_scores.count();
- if (count == 0) return &[_]Recommendation{};
-
- const results = try self.allocator.alloc(Recommendation, count);
- var idx: usize = 0;
-
- var cit = candidate_scores.iterator();
- while (cit.next()) |entry| {
- results[idx] = Recommendation{ .item_id = entry.key_ptr.*, .score = entry.value_ptr.* };
- idx += 1;
- }
-
- std.mem.sort(Recommendation, results[0..idx], {}, struct {
- fn cmp(_: void, a: Recommendation, b: Recommendation) bool {
- return a.score > b.score;
- }
- }.cmp);
-
- const result_k = @min(k, idx);
- const output = try self.allocator.alloc(Recommendation, result_k);
- @memcpy(output, results[0..result_k]);
- self.allocator.free(results);
-
- return output;
- }
-
- /// Get statistics.
- pub fn stats(self: *Self) RecommenderStats {
- var total_items: u32 = 0;
- var uit = self.users.iterator();
- while (uit.next()) |entry| {
- total_items += entry.value_ptr.item_count;
- }
-
- const num_users = self.users.count();
-
- return RecommenderStats{
- .num_users = num_users,
- .num_items = self.items.count(),
- .avg_items_per_user = if (num_users > 0)
- @as(f64, @floatFromInt(total_items)) / @as(f64, @floatFromInt(num_users))
- else
- 0.0,
- };
- }
-
- /// Number of items in catalog.
- pub fn itemCount(self: *Self) usize {
- return self.items.count();
- }
-
- /// Number of users.
- pub fn userCount(self: *Self) usize {
- return self.users.count();
- }
-};
-
-// ============================================================================
-// Tests: HDCRecommender
-// ============================================================================
-
-test "HDCRecommender β init and deinit" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- try std.testing.expectEqual(@as(usize, 0), rec.itemCount());
- try std.testing.expectEqual(@as(usize, 0), rec.userCount());
-}
-
-test "HDCRecommender β addItem" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- try rec.addItem("movie1", "action adventure hero villain explosion");
- try rec.addItem("movie2", "romance love comedy wedding happiness");
-
- try std.testing.expectEqual(@as(usize, 2), rec.itemCount());
-
- // Duplicate should not increase count
- try rec.addItem("movie1", "action adventure hero villain explosion");
- try std.testing.expectEqual(@as(usize, 2), rec.itemCount());
-}
-
-test "HDCRecommender β addRating and profile building" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- try rec.addItem("m1", "action hero fight sword");
- try rec.addItem("m2", "comedy laugh joke funny");
-
- try rec.addRating("alice", "m1");
- try rec.addRating("alice", "m2");
-
- try std.testing.expectEqual(@as(usize, 1), rec.userCount());
-
- const profile = rec.users.get("alice").?;
- try std.testing.expectEqual(@as(u32, 2), profile.item_count);
-}
-
-test "HDCRecommender β content-based recommend" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- // Add movie catalog
- try rec.addItem("action1", "action hero fight sword battle warrior");
- try rec.addItem("action2", "action explosion chase gun combat hero");
- try rec.addItem("comedy1", "comedy laugh joke funny humor silly");
- try rec.addItem("comedy2", "comedy sitcom humor laugh prank joke");
- try rec.addItem("drama1", "drama emotion tears family struggle love");
-
- // Alice likes action movies
- try rec.addRating("alice", "action1");
-
- // Recommend for Alice
- const recs = try rec.recommend("alice", 3);
- defer rec.allocator.free(recs);
-
- try std.testing.expect(recs.len > 0);
- try std.testing.expect(recs.len <= 3);
-
- std.debug.print("\n Alice likes action1. Recommendations:\n", .{});
- for (recs) |r| {
- std.debug.print(" {s}: {d:.4}\n", .{ r.item_id, r.score });
- }
-
- // action2 should rank higher than comedy/drama
- try std.testing.expect(recs[0].score > recs[recs.len - 1].score);
-}
-
-test "HDCRecommender β findSimilarUsers" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- try rec.addItem("a1", "action hero fight sword");
- try rec.addItem("a2", "action explosion chase gun");
- try rec.addItem("c1", "comedy laugh joke funny");
- try rec.addItem("c2", "comedy sitcom humor prank");
-
- // Alice and Bob both like action
- try rec.addRating("alice", "a1");
- try rec.addRating("alice", "a2");
- try rec.addRating("bob", "a1");
- try rec.addRating("bob", "a2");
-
- // Carol likes comedy
- try rec.addRating("carol", "c1");
- try rec.addRating("carol", "c2");
-
- const similar = try rec.findSimilarUsers("alice", 2);
- defer rec.allocator.free(similar);
-
- try std.testing.expect(similar.len == 2);
-
- std.debug.print("\n Users similar to Alice:\n", .{});
- for (similar) |su| {
- std.debug.print(" {s}: sim={d:.4}\n", .{ su.user_id, su.similarity });
- }
-
- // Bob should be more similar to Alice than Carol
- if (std.mem.eql(u8, similar[0].user_id, "bob")) {
- try std.testing.expect(similar[0].similarity > similar[1].similarity);
- }
-}
-
-test "HDCRecommender β collaborative recommend" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- try rec.addItem("a1", "action hero fight sword battle");
- try rec.addItem("a2", "action explosion chase gun combat");
- try rec.addItem("a3", "action martial arts ninja stealth");
- try rec.addItem("c1", "comedy laugh joke funny humor");
-
- // Alice likes a1
- try rec.addRating("alice", "a1");
-
- // Bob likes a1 and a2 and a3
- try rec.addRating("bob", "a1");
- try rec.addRating("bob", "a2");
- try rec.addRating("bob", "a3");
-
- // Carol likes c1
- try rec.addRating("carol", "c1");
-
- // Collaborative: Alice should get a2, a3 from Bob
- const recs = try rec.collaborativeRecommend("alice", 3);
- defer rec.allocator.free(recs);
-
- std.debug.print("\n Collaborative recs for Alice (via Bob):\n", .{});
- for (recs) |r| {
- std.debug.print(" {s}: score={d:.4}\n", .{ r.item_id, r.score });
- }
-
- try std.testing.expect(recs.len > 0);
-}
-
-test "HDCRecommender β stats" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- try rec.addItem("i1", "item one description");
- try rec.addItem("i2", "item two description");
- try rec.addRating("u1", "i1");
- try rec.addRating("u1", "i2");
- try rec.addRating("u2", "i1");
-
- const st = rec.stats();
- try std.testing.expectEqual(@as(usize, 2), st.num_users);
- try std.testing.expectEqual(@as(usize, 2), st.num_items);
- try std.testing.expect(st.avg_items_per_user > 1.0);
-}
-
-test "HDCRecommender β demo: movie recommendation" {
- const allocator = std.testing.allocator;
- var rec = HDCRecommender.init(allocator, 1024, 42);
- defer rec.deinit();
-
- std.debug.print("\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" HDC Recommender System Demo β Movie Recommendations\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Build movie catalog
- std.debug.print(" Building catalog...\n", .{});
- try rec.addItem("die_hard", "action hero cop explosion building hostage rescue gun");
- try rec.addItem("terminator", "action robot future war machine gun chase fight");
- try rec.addItem("rambo", "action soldier jungle war combat survival weapon");
- try rec.addItem("mad_max", "action chase desert car fury road apocalypse");
- try rec.addItem("notting_hill", "romance love london bookshop celebrity meeting sweet");
- try rec.addItem("titanic", "romance ship ocean love tragedy sacrifice drama");
- try rec.addItem("notebook", "romance love letter memory summer passion heart");
- try rec.addItem("inception", "scifi dream layer mind reality heist thriller");
- try rec.addItem("matrix", "scifi simulation reality computer hacker fight code");
- try rec.addItem("interstellar", "scifi space time travel wormhole gravity planet");
- try rec.addItem("hangover", "comedy drunk vegas bachelor party crazy chaos");
- try rec.addItem("superbad", "comedy teen party awkward funny school dance");
-
- std.debug.print(" Catalog: {d} movies\n", .{rec.itemCount()});
-
- // Users
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" User Profiles\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Alice: action fan
- try rec.addRating("alice", "die_hard");
- try rec.addRating("alice", "terminator");
- try rec.addRating("alice", "rambo");
- std.debug.print(" Alice: die_hard, terminator, rambo (action fan)\n", .{});
-
- // Bob: action + scifi
- try rec.addRating("bob", "die_hard");
- try rec.addRating("bob", "matrix");
- try rec.addRating("bob", "inception");
- std.debug.print(" Bob: die_hard, matrix, inception (action+scifi)\n", .{});
-
- // Carol: romance
- try rec.addRating("carol", "notting_hill");
- try rec.addRating("carol", "titanic");
- try rec.addRating("carol", "notebook");
- std.debug.print(" Carol: notting_hill, titanic, notebook (romance)\n", .{});
-
- // Dave: comedy
- try rec.addRating("dave", "hangover");
- try rec.addRating("dave", "superbad");
- std.debug.print(" Dave: hangover, superbad (comedy)\n", .{});
-
- // Content-based recommendations
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Content-Based Recommendations\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- const users_to_rec = [_][]const u8{ "alice", "bob", "carol", "dave" };
- for (users_to_rec) |uid| {
- const recs = try rec.recommend(uid, 3);
- defer rec.allocator.free(recs);
-
- std.debug.print(" {s:5}: ", .{uid});
- for (recs, 0..) |r, i| {
- if (i > 0) std.debug.print(", ", .{});
- std.debug.print("{s}({d:.3})", .{ r.item_id, r.score });
- }
- std.debug.print("\n", .{});
- }
-
- // User similarity
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" User Similarity\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- for (users_to_rec) |uid| {
- const similar = try rec.findSimilarUsers(uid, 3);
- defer rec.allocator.free(similar);
-
- std.debug.print(" {s:5} nearest: ", .{uid});
- for (similar, 0..) |su, i| {
- if (i > 0) std.debug.print(", ", .{});
- std.debug.print("{s}({d:.3})", .{ su.user_id, su.similarity });
- }
- std.debug.print("\n", .{});
- }
-
- // Collaborative
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Collaborative Recommendations\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- for (users_to_rec) |uid| {
- const crecs = try rec.collaborativeRecommend(uid, 3);
- defer rec.allocator.free(crecs);
-
- std.debug.print(" {s:5}: ", .{uid});
- if (crecs.len == 0) {
- std.debug.print("(no collaborative recs)", .{});
- } else {
- for (crecs, 0..) |r, i| {
- if (i > 0) std.debug.print(", ", .{});
- std.debug.print("{s}({d:.3})", .{ r.item_id, r.score });
- }
- }
- std.debug.print("\n", .{});
- }
-
- // Stats
- const st = rec.stats();
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Stats: {d} users, {d} items, avg {d:.1} items/user\n", .{
- st.num_users, st.num_items, st.avg_items_per_user,
- });
-
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
- std.debug.print(" Modules: 24 | Tests: 274+8 = 282\n", .{});
- std.debug.print("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n", .{});
-
- // Assertions
- try std.testing.expectEqual(@as(usize, 4), st.num_users);
- try std.testing.expectEqual(@as(usize, 12), st.num_items);
- try std.testing.expect(st.avg_items_per_user > 2.0);
-}
diff --git a/src/shakespeare_extended.txt b/src/shakespeare_extended.txt
deleted file mode 100644
index 13d8ff4541..0000000000
--- a/src/shakespeare_extended.txt
+++ /dev/null
@@ -1 +0,0 @@
-to be or not to be that is the question whether tis nobler in the mind to suffer the slings and arrows of outrageous fortune or to take arms against a sea of troubles and by opposing end them to die to sleep no more and by a sleep to say we end the heartache and the thousand natural shocks that flesh is heir to tis a consummation devoutly to be wished to die to sleep to sleep perchance to dream ay there is the rub for in that sleep of death what dreams may come when we have shuffled off this mortal coil must give us pause there is the respect that makes calamity of so long life for who would bear the whips and scorns of time the oppressors wrong the proud mans contumely the pangs of despised love the laws delay the insolence of office and the spurns that patient merit of the unworthy takes when he himself might his quietus make with a bare bodkin who would fardels bear to grunt and sweat under a weary life but that the dread of something after death the undiscovered country from whose bourn no traveller returns puzzles the will and makes us rather bear those ills we have than fly to others that we know not of thus conscience does make cowards of us all and thus the native hue of resolution is sicklied over with the pale cast of thought and enterprises of great pith and moment with this regard their currents turn awry and lose the name of action tomorrow and tomorrow and tomorrow creeps in this petty pace from day to day to the last syllable of recorded time and all our yesterdays have lighted fools the way to dusty death out out brief candle life is but a walking shadow a poor player that struts and frets his hour upon the stage and then is heard no more it is a tale told by an idiot full of sound and fury signifying nothing but soft what light through yonder window breaks it is the east and juliet is the sun arise fair sun and kill the envious moon who is already sick and pale with grief that thou her maid art far more fair than she be not her maid since she is envious her vestal livery is but sick and green and none but fools do wear it cast it off it is my lady oh it is my love oh that she knew she were she speaks yet she says nothing what of that her eye discourses i will answer it i am too bold tis not to me she speaks two of the fairest stars in all the heaven having some business do entreat her eyes to twinkle in their spheres till they return shall i compare thee to a summers day thou art more lovely and more temperate rough winds do shake the darling buds of may and summers lease hath all too short a date sometime too hot the eye of heaven shines and often is his gold complexion dimmed and every fair from fair sometime declines by chance or natures changing course untrimmed but thy eternal summer shall not fade nor lose possession of that fair thou owest nor shall death brag thou wanderest in his shade when in eternal lines to time thou growest so long as men can breathe or eyes can see so long lives this and this gives life to thee who is there nay answer me stand and unfold yourself long live the king bernardo he you come most carefully upon your hour tis now struck twelve get thee to bed francisco for this relief much thanks tis bitter cold and i am sick at heart have you had quiet guard not a mouse stirring well good night if you do meet horatio and marcellus the rivals of my watch bid them make haste when shall we three meet again in thunder lightning or in rain when the hurlyburlys done when the battles lost and won that will be ere the set of sun where the place upon the heath there to meet with macbeth fair is foul and foul is fair hover through the fog and filthy air something is rotten in the state of denmark though this be madness yet there is method in it brevity is the soul of wit there are more things in heaven and earth horatio than are dreamt of in your philosophy the lady doth protest too much methinks good night sweet prince and flights of angels sing thee to thy rest frailty thy name is woman the play is the thing wherein i will catch the conscience of the king a rose by any other name would smell as sweet parting is such sweet sorrow that i shall say good night till it be morrow my bounty is as boundless as the sea my love as deep the more i give to thee the more i have for both are infinite these violent delights have violent ends and in their triumph die like fire and powder which as they kiss consume is this a dagger which i see before me the handle toward my hand come let me clutch thee i have thee not and yet i see thee still art thou not fatal vision sensible to feeling as to sight or art thou but a dagger of the mind a false creation proceeding from the heat oppressed brain we are such stuff as dreams are made on and our little life is rounded with a sleep oh brave new world that has such people in it full fathom five thy father lies of his bones are coral made those are pearls that were his eyes nothing of him that doth fade but doth suffer a sea change into something rich and strange all the world is a stage and all the men and women merely players they have their exits and their entrances and one man in his time plays many parts his acts being seven ages at first the infant mewling and puking in the nurses arms and then the whining schoolboy with his satchel and shining morning face creeping like snail unwillingly to school and then the lover sighing like furnace with a woeful ballad made to his mistress eyebrow then a soldier full of strange oaths and bearded like the pard jealous in honour sudden and quick in quarrel seeking the bubble reputation even in the cannons mouth and then the justice in fair round belly with good capon lined with eyes severe and beard of formal cut full of wise saws and modern instances and so he plays his part the sixth age shifts into the lean and slippered pantaloon with spectacles on nose and pouch on side his youthful hose well saved a world too wide for his shrunk shank and his big manly voice turning again toward childish treble pipes and whistles in his sound last scene of all that ends this strange eventful history is second childishness and mere oblivion sans teeth sans eyes sans taste sans everything now is the winter of our discontent made glorious summer by this son of york and all the clouds that loured upon our house in the deep bosom of the ocean buried now are our brows bound with victorious wreaths our bruised arms hung up for monuments our stern alarums changed to merry meetings our dreadful marches to delightful measures grim visaged war hath smoothed his wrinkled front and now instead of mounting barbed steeds to fright the souls of fearful adversaries he capers nimbly in a ladys chamber to the lascivious pleasing of a lute but i that am not shaped for sportive tricks nor made to court an amorous looking glass i that am rudely stamped and want loves majesty to strut before a nymphing walking spirit i that am curtailed of this fair proportion cheated of feature by dissembling nature deformed unfinished sent before my time into this breathing world scarce half made up and that so lamely and unfashionable that dogs bark at me as i halt by them why i in this weak piping time of peace have no delight to pass away the time unless to spy my shadow in the sun and descant on mine own deformity if music be the food of love play on give me excess of it that surfeiting the appetite may sicken and so die that strain again it had a dying fall oh it came over my ear like the sweet sound that breathes upon a bank of violets stealing and giving odour enough no more tis not so sweet now as it was before oh spirit of love how quick and fresh art thou that notwithstanding thy capacity receiveth as the sea nought enters there of what validity and pitch so ever but falls into abatement and low price even in a minute so full of shapes is fancy that it alone is high fantastical the quality of mercy is not strained it droppeth as the gentle rain from heaven upon the place beneath it is twice blessed it blesseth him that gives and him that takes tis mightiest in the mightiest it becomes the throned monarch better than his crown his sceptre shows the force of temporal power the attribute to awe and majesty wherein doth sit the dread and fear of kings but mercy is above this sceptred sway it is enthroned in the hearts of kings it is an attribute to god himself and earthly power doth then show likest gods when mercy seasons justice therefore jew though justice be thy plea consider this that in the course of justice none of us should see salvation we do pray for mercy and that same prayer doth teach us all to render the deeds of mercy friends romans countrymen lend me your ears i come to bury caesar not to praise him the evil that men do lives after them the good is oft interred with their bones so let it be with caesar the noble brutus hath told you caesar was ambitious if it were so it was a grievous fault and grievously hath caesar answered it here under leave of brutus and the rest for brutus is an honourable man so are they all all honourable men come i to speak in caesars funeral he was my friend faithful and just to me but brutus says he was ambitious and brutus is an honourable man he hath brought many captives home to rome whose ransoms did the general coffers fill did this in caesar seem ambitious when that the poor have cried caesar hath wept ambition should be made of sterner stuff yet brutus says he was ambitious and brutus is an honourable man you all did see that on the lupercal i thrice presented him a kingly crown which he did thrice refuse was this ambition yet brutus says he was ambitious and sure he is an honourable man i speak not to disprove what brutus spoke but here i am to speak what i do know you all did love him once not without cause what cause withholds you then to mourn for him oh judgment thou art fled to brutish beasts and men have lost their reason bear with me my heart is in the coffin there with caesar and i must pause till it come back to me double double toil and trouble fire burn and cauldron bubble fillet of a fenny snake in the cauldron boil and bake eye of newt and toe of frog wool of bat and tongue of dog adders fork and blind worms sting lizards leg and owlets wing for a charm of powerful trouble like a hell broth boil and bubble by the pricking of my thumbs something wicked this way comes open locks whoever knocks how now you secret black and midnight hags what is it you do a deed without a name i conjure you by that which you profess however you come to know it answer me though you untie the winds and let them fight against the churches though the yeasty waves confound and swallow navigation up though bladed corn be lodged and trees blown down though castles topple on their warders heads though palaces and pyramids do slope their heads to their foundations though the treasure of natures germains tumble all together even till destruction sicken answer me to what i ask you speak demand we will answer first witch second witch third witch all say on if you had rather hear it from our mouths or from our masters pour in sows blood that hath eaten her nine farrow grease thats sweaten from the murderers gibbet throw into the flame come high or low thyself and office deftly show if we shadows have offended think but this and all is mended that you have but slumbered here while these visions did appear and this weak and idle theme no more yielding but a dream gentles do not reprehend if you pardon we will mend and as i am an honest puck if we have unearned luck now to scape the serpents tongue we will make amends ere long else the puck a liar call so good night unto you all give me your hands if we be friends and robin shall restore amends o what a rogue and peasant slave am i is it not monstrous that this player here but in a fiction in a dream of passion could force his soul so to his own conceit that from her working all his visage wanned tears in his eyes distraction in his aspect a broken voice and his whole function suiting with forms to his conceit and all for nothing for hecuba what is hecuba to him or he to hecuba that he should weep for her what would he do had he the motive and the cue for passion that i have he would drown the stage with tears and cleave the general ear with horrid speech make mad the guilty and appal the free confound the ignorant and amaze indeed the very faculties of eyes and ears yet i a dull and muddy mettled rascal peak like john a dreams unpregnant of my cause and can say nothing no not for a king upon whose property and most dear life a damned defeat was made am i a coward who calls me villain breaks my pate across plucks off my beard and blows it in my face tweaks me by the nose gives me the lie in the throat as deep as to the lungs who does me this ha swounds i should take it for it cannot be but i am pigeon livered and lack gall to make oppression bitter or ere this i should have fatted all the region kites with this slaves offal bloody bawdy villain remorseless treacherous lecherous kindless villain oh vengeance why what an ass am i this is most brave that i the son of a dear father murdered prompted to my revenge by heaven and hell must like a whore unpack my heart with words and fall a cursing like a very drab a scullion fie upon it foh about my brain i have heard that guilty creatures sitting at a play have by the very cunning of the scene been struck so to the soul that presently they have proclaimed their malefactions for murder though it have no tongue will speak with most miraculous organ i will have these players play something like the murder of my father before mine uncle i will observe his looks i will tent him to the quick if he but blench i know my course the spirit that i have seen may be the devil and the devil hath power to assume a pleasing shape yea and perhaps out of my weakness and my melancholy as he is very potent with such spirits abuses me to damn me i will have grounds more relative than this the plays the thing wherein i will catch the conscience of the king speak the speech i pray you as i pronounced it to you trippingly on the tongue but if you mouth it as many of your players do i had as lief the town crier spoke my lines nor do not saw the air too much with your hand thus but use all gently for in the very torrent tempest and as i may say the whirlwind of passion you must acquire and beget a temperance that may give it smoothness oh it offends me to the soul to hear a robustious periwig pated fellow tear a passion to tatters to very rags to split the ears of the groundlings who for the most part are capable of nothing but inexplicable dumb shows and noise i would have such a fellow whipped for overdoing termagant it out herods herod pray you avoid it be not too tame neither but let your own discretion be your tutor suit the action to the word the word to the action with this special observance that you overstep not the modesty of nature for anything so overdone is from the purpose of playing whose end both at the first and now was and is to hold as twere the mirror up to nature to show virtue her own feature scorn her own image and the very age and body of the time his form and pressure now this overdone or come tardy off though it make the unskilful laugh cannot but make the judicious grieve the censure of the which one must in your allowance overweigh a whole theatre of others oh there be players that i have seen play and heard others praise and that highly not to speak it profanely that neither having the accent of christians nor the gait of christian pagan nor man have so strutted and bellowed that i have thought some of natures journeymen had made men and not made them well they imitated humanity so abominably oh reform it altogether and let those that play your clowns speak no more than is set down for them for there be of them that will themselves laugh to set on some quantity of barren spectators to laugh too though in the mean time some necessary question of the play be then to be considered that is villanous and shows a most pitiful ambition in the fool that uses it go make you ready how all occasions do inform against me and spur my dull revenge what is a man if his chief good and market of his time be but to sleep and feed a beast no more sure he that made us with such large discourse looking before and after gave us not that capability and godlike reason to fust in us unused now whether it be bestial oblivion or some craven scruple of thinking too precisely on the event a thought which quartered hath but one part wisdom and ever three parts coward i do not know why yet i live to say this things to do since i have cause and will and strength and means to do it examples gross as earth exhort me witness this army of such mass and charge led by a delicate and tender prince whose spirit with divine ambition puffed makes mouths at the invisible event exposing what is mortal and unsure to all that fortune death and danger dare even for an eggshell rightly to be great is not to stir without great argument but greatly to find quarrel in a straw when honours at the stake how stand i then that have a father killed a mother stained excitements of my reason and my blood and let all sleep while to my shame i see the imminent death of twenty thousand men that for a fantasy and trick of fame go to their graves like beds fight for a plot whereon the numbers cannot try the cause which is not tomb enough and continent to hide the slain oh from this time forth my thoughts be bloody or be nothing worth when that i was and a little tiny boy with hey ho the wind and the rain a foolish thing was but a toy for the rain it raineth every day but when i came to mans estate with hey ho the wind and the rain gainst knaves and thieves men shut their gate for the rain it raineth every day but when i came alas to wive with hey ho the wind and the rain by swaggering could i never thrive for the rain it raineth every day but when i came unto my beds with hey ho the wind and the rain with tosspots still had drunken heads for the rain it raineth every day a great while ago the world begun with hey ho the wind and the rain but thats all one our play is done and we will strive to please you every day let me not to the marriage of true minds admit impediments love is not love which alters when it alteration finds or bends with the remover to remove oh no it is an ever fixed mark that looks on tempests and is never shaken it is the star to every wandering bark whose worths unknown although his height be taken loves not times fool though rosy lips and cheeks within his bending sickles compass come love alters not with his brief hours and weeks but bears it out even to the edge of doom if this be error and upon me proved i never writ nor no man ever loved when in disgrace with fortune and mens eyes i all alone beweep my outcast state and trouble deaf heaven with my bootless cries and look upon myself and curse my fate wishing me like to one more rich in hope featured like him like him with friends possessed desiring this mans art and that mans scope with what i most enjoy contented least yet in these thoughts myself almost despising haply i think on thee and then my state like to the lark at break of day arising from sullen earth sings hymns at heavens gate for thy sweet love remembered such wealth brings that then i scorn to change my state with kings when to the sessions of sweet silent thought i summon up remembrance of things past i sigh the lack of many a thing i sought and with old woes new wail my dear times waste then can i drown an eye unused to flow for precious friends hid in deaths dateless night and weep afresh loves long since cancelled woe and moan the expense of many a vanished sight then can i grieve at grievances foregone and heavily from woe to woe tell over the sad account of fore bemoaned moan which i new pay as if not paid before but if the while i think on thee dear friend all losses are restored and sorrows end that time of year thou mayst in me behold when yellow leaves or none or few do hang upon those boughs which shake against the cold bare ruined choirs where late the sweet birds sang in me thou seest the twilight of such day as after sunset fadeth in the west which by and by black night doth take away deaths second self that seals up all in rest in me thou seest the glowing of such fire that on the ashes of his youth doth lie as the deathbed whereon it must expire consumed with that which it was nourished by this thou perceivest which makes thy love more strong to love that well which thou must leave ere long my mistress eyes are nothing like the sun coral is far more red than her lips red if snow be white why then her breasts are dun if hairs be wires black wires grow on her head i have seen roses damasked red and white but no such roses see i in her cheeks and in some perfumes is there more delight than in the breath that from my mistress reeks i love to hear her speak yet well i know that music hath a far more pleasing sound i grant i never saw a goddess go my mistress when she walks treads on the ground and yet by heaven i think my love as rare as any she belied with false compare shall i hear more or shall i speak at this o romeo romeo wherefore art thou romeo deny thy father and refuse thy name or if thou wilt not be but sworn my love and i will no longer be a capulet tis but thy name that is my enemy thou art thyself though not a montague what is montague it is nor hand nor foot nor arm nor face nor any other part belonging to a man oh be some other name what is in a name that which we call a rose by any other name would smell as sweet so romeo would were he not romeo called retain that dear perfection which he owes without that title romeo doff thy name and for that name which is no part of thee take all myself how camest thou hither tell me and wherefore the orchard walls are high and hard to climb and the place death considering who thou art if any of my kinsmen find thee here with loves light wings did i overperch these walls for stony limits cannot hold love out and what love can do that dares love attempt therefore thy kinsmen are no let to me if they do see thee they will murder thee alack there lies more peril in thine eye than twenty of their swords look thou but sweet and i am proof against their enmity i would not for the world they saw thee here i have nights cloak to hide me from their sight and but thou love me let them find me here my life were better ended by their hate than death prorogued wanting of thy love by whose direction foundst thou out this place by love who first did prompt me to inquire he lent me counsel and i lent him eyes i am no pilot yet wert thou as far as that vast shore washed with the farthest sea i would adventure for such merchandise dost thou love me i know thou wilt say ay and i will take thy word yet if thou swearest thou mayst prove false at lovers perjuries they say jove laughs oh gentle romeo if thou dost love pronounce it faithfully or if thou thinkest i am too quickly won i will frown and be perverse and say thee nay so thou wilt woo but else not for the world in truth fair montague i am too fond and therefore thou mayst think my behaviour light but trust me gentleman i will prove more true than those that have more cunning to be strange i should have been more strange i must confess but that thou overheardst ere i was ware my true love passion therefore pardon me and not impute this yielding to light love which the dark night hath so discovered lady by yonder blessed moon i swear that tips with silver all these fruit tree tops oh swear not by the moon the inconstant moon that monthly changes in her circled orb lest that thy love prove likewise variable what shall i swear by do not swear at all or if thou wilt swear by thy gracious self which is the god of my idolatry and i will believe thee well do not swear although i joy in thee i have no joy of this contract tonight it is too rash too unadvised too sudden too like the lightning which doth cease to be ere one can say it lightens sweet good night this bud of love by summers ripening breath may prove a beauteous flower when next we meet good night good night a thousand times good night nay from the orchard side look there your lord and master is approaching what a piece of work is a man how noble in reason how infinite in faculty in form and moving how express and admirable in action how like an angel in apprehension how like a god the beauty of the world the paragon of animals and yet to me what is this quintessence of dust man delights not me no nor woman neither though by your smiling you seem to say so my lord we think not so what then you are merry the world is grown so bad that wrens make prey where eagles dare not perch since every jack became a gentleman there is many a gentle person made a jack now by saint paul i swear i will not dine until i see the same and from my soul i love thy daughter and do intend to make her queen my gracious sovereign as i ride along i thought upon the words which your grace spoke to me and shall recount them over again the duke of buckingham shall pay for this my lord what treachery was used the tender prince was by his nurses counsel sent to learn what trick the world has and by good soul was never none to him that trusted first the wolf doth grin before he barketh a plague upon it when thieves cannot be true one to another
diff --git a/src/storm/experience_engine.zig.bak2 b/src/storm/experience_engine.zig.bak2
deleted file mode 100644
index b2c8f8099c..0000000000
--- a/src/storm/experience_engine.zig.bak2
+++ /dev/null
@@ -1,332 +0,0 @@
-//! Experience Engine for STORM
-//! Consults past episodes via Levenshtein fuzzy matching
-//! Saves episodes to .trinity/experience/episodes/
-
-const std = @import("std");
-
-pub const EpisodeData = struct {
- task: []const u8,
- timestamp: i64,
- success: bool,
- duration_ms: u64,
- context: []const u8,
-};
-
-pub const SimilarTask = struct {
- task: []const u8,
- distance: usize,
- context: []const u8,
-};
-
-pub const ConsultResult = struct {
- is_blacklisted: bool,
- recommendations: ?[]const u8,
- similar_tasks: []const SimilarTask,
-};
-
-pub const ExperienceEngine = struct {
- allocator: std.mem.Allocator,
- episodes_dir: []const u8,
- index_path: []const u8,
-
- pub fn init(allocator: std.mem.Allocator) !ExperienceEngine {
- const episodes_dir = try allocator.dupe(u8, ".trinity/experience/episodes");
- const index_path = try allocator.dupe(u8, ".trinity/experience/index.json");
-
- std.fs.cwd().makePath(".trinity/experience") catch {};
- std.fs.cwd().makePath(".trinity/experience/episodes") catch {};
-
- return .{
- .allocator = allocator,
- .episodes_dir = episodes_dir,
- .index_path = index_path,
- };
- }
-
- pub fn deinit(self: *ExperienceEngine) void {
- self.allocator.free(self.episodes_dir);
- self.allocator.free(self.index_path);
- }
-
- pub fn consult(self: *ExperienceEngine, task: []const u8, top_k: usize) !ConsultResult {
- const log = std.log.scoped(.info);
- log.info("Consulting experience for: {s} (top {d})", .{task, top_k});
-
- var episodes = std.ArrayList(EpisodeData).init(self.allocator);
- defer episodes.deinit();
-
- var dir = std.fs.cwd().openIterableDir(.{
- .sub_path = self.episodes_dir,
- }) catch |err| {
- return .{
- .is_blacklisted = false,
- .recommendations = null,
- .similar_tasks = &[0]SimilarTask{},
- };
- };
- defer dir.close();
-
- var iter = dir.iterate();
- while (try iter.next()) |entry| {
- if (entry.kind != .file) continue;
-
- const ep = self.loadEpisode(entry.name) catch |err| {
- log.warn("Failed to load episode: {}", .{err});
- continue;
- };
-
- try episodes.append(ep);
- }
-
- if (episodes.items.len == 0) {
- return .{
- .is_blacklisted = false,
- .recommendations = null,
- .similar_tasks = &[0]SimilarTask{},
- };
- }
-
- const k = @min(top_k, episodes.items.len);
-
- var distances = std.ArrayList(struct {
- episode: *EpisodeData,
- distance: usize,
- }).init(self.allocator);
- defer distances.deinit();
-
- for (episodes.items) |*ep| {
- const distance = self.levenshteinDistance(task, ep.task);
- try distances.append(.{ .episode = ep, .distance = distance });
- }
-
- std.sort.sort(@TypeOf(distances.items), distances.items, {}, struct {
- pub fn lessThan(_: void, a: @TypeOf(distances.items).Element, b: @TypeOf(distances.items).Element) bool {
- return a.distance < b.distance;
- }
- });
-
- var similar = std.ArrayList(SimilarTask).init(self.allocator);
-
- for (0..k) |i| {
- if (i >= distances.items.len) break;
- const item = distances.items[i];
- _ = if (item.distance < 3)
- "(very similar)"
- else if (item.distance < 5)
- "(similar)"
- else
- "";
-
- try similar.append(.{
- .task = try self.allocator.dupe(u8, item.episode.task),
- .distance = item.distance,
- .context = try self.allocator.dupe(u8, item.episode.context orelse ""),
- });
- }
-
- var recommendations = std.ArrayList([]const u8).init(self.allocator);
-
- for (similar.items) |sim| {
- const suffix = if (sim.distance < 3)
- " (very similar)"
- else if (sim.distance < 5)
- " (similar)"
- else
- "";
-
- try recommendations.append(try std.fmt.allocPrint(
- self.allocator,
- "{s}{s}: {s}",
- .{sim.task, suffix},
- ));
- }
-
- const recommendations_slice = if (recommendations.items.len > 0)
- try recommendations.toOwnedSlice()
- else
- null;
-
- const similar_slice = try similar.toOwnedSlice();
-
- return .{
- .is_blacklisted = false,
- .recommendations = recommendations_slice,
- .similar_tasks = similar_slice,
- };
- }
-
- pub fn saveAttempt(self: *ExperienceEngine, task: []const u8, _success: bool, _context: []const u8, _results: []const EpisodeData) !void {
- const timestamp = std.time.nanoTimestamp();
-
- const filename = try std.fmt.allocPrint(self.allocator, "{d}_{d}.json", .{timestamp, task});
- const full_path = try std.fs.path.join(self.allocator, &[_][]const u8{ self.episodes_dir, filename });
-
- const episode_json = std.json.stringify(&.{
- std.json.Value{ .string = try self.allocator.dupe(u8, task) },
- std.json.Value{ .integer = @as(u64, timestamp) },
- std.json.Value{ .bool = _success },
- std.json.Value{ .string = try self.allocator.dupe(u8, _context) },
- std.json.Value{ .array = &.{} },
- }, .{ .whitespace = .indent_2 });
- const file = try std.fs.cwd().createFile(.{ .sub_path = full_path });
- defer file.close();
-
- try file.writeAll(episode_json);
-
- const log = std.log.scoped(.info);
- log.info("Episode saved: {s}", .{filename});
-
- try self.updateIndex(task, _timestamp, _success);
- }
-
- fn loadEpisode(self: *ExperienceEngine, filename: []const u8) !EpisodeData {
- const full_path = try std.fs.path.join(self.allocator, &[_][]const u8{ self.episodes_dir, filename });
- const file = try std.fs.cwd().openFile(full_path, .{});
- defer file.close();
-
- const content = try file.readToEndAlloc(self.allocator, 1024 * 1024);
- defer self.allocator.free(content);
-
- const parsed = try std.json.parseFromSlice(
- std.StringHashMap(std.json.Value),
- self.allocator,
- content,
- .{ .ignore_unknown_fields = true },
- );
- defer parsed.deinit();
-
- const task_val = parsed.value.get("task") orelse null;
- const timestamp_val = parsed.value.get("timestamp") orelse null;
- const success_val = parsed.value.get("success") orelse null;
- const context_val = parsed.value.get("context") orelse null;
-
- return EpisodeData{
- .task = try self.allocator.dupe(u8, if (task_val == .string) task_val.string else ""),
- .timestamp = if (timestamp_val == .integer) @intCast(timestamp_val.integer) else 0,
- .success = if (success_val == .bool) success_val.bool else false,
- .duration_ms = 0,
- .context = try self.allocator.dupe(u8, if (context_val == .string) context_val.string else ""),
- };
- }
-
- fn updateIndex(self: *ExperienceEngine, task: []const u8, timestamp: i64) !void {
- var index_data = std.StringHashMap(std.json.Value).init(self.allocator);
-
- const index_file = std.fs.cwd().openFile(self.index_path) catch |err| {
- if (err == error.FileNotFound) {
- index_data = std.StringHashMap(std.json.Value).init(self.allocator);
- } else {
- return err;
- }
- };
- defer if (index_file) |file| file.close();
-
- if (index_file) |file| {
- const content = try file.readToEndAlloc(self.allocator, 1024 * 1024);
- defer self.allocator.free(content);
-
- const parsed = try std.json.parseFromSlice(
- std.StringHashMap(std.json.Value),
- self.allocator,
- content,
- .{ .ignore_unknown_fields = true },
- );
- defer parsed.deinit();
-
- var iter = parsed.value.iterator();
- while (iter.next()) |entry| {
- try index_data.put(
- try self.allocator.dupe(u8, entry.key_ptr.*),
- entry.value_ptr.*,
- );
- }
- }
-
- const count_val = index_data.get(task);
- if (count_val) |cv| {
- if (cv == .integer) {
- const count = cv.integer + 1;
- index_data.put(try self.allocator.dupe(u8, task), std.json.Value{ .integer = count });
- }
- }
-
- const file = try std.fs.cwd().createFile(.{ .sub_path = self.index_path });
- defer file.close();
-
- try std.json.stringify(index_data, .{ .whitespace = .indent_2 }, file.writer());
-
- const log = std.log.scoped(.info);
- log.info("Index updated for: {s}", .{task});
- }
-
- pub fn isBlacklisted(self: *ExperienceEngine, task: []const u8) bool {
- const index_file = std.fs.cwd().openFile(self.index_path) catch |err| {
- if (err == error.FileNotFound) return false;
- return err;
- };
- defer index_file.close();
-
- const content = try index_file.readToEndAlloc(self.allocator, 1024 * 1024);
- defer self.allocator.free(content);
-
- const parsed = try std.json.parseFromSlice(
- std.StringHashMap(std.json.Value),
- self.allocator,
- content,
- .{ .ignore_unknown_fields = true },
- );
- defer parsed.deinit();
-
- return parsed.value.get(task) != null;
- }
-
- pub fn getSimilar(self: *ExperienceEngine, task: []const u8, top_k: usize) ![]const SimilarTask {
- const result = try self.consult(task, top_k);
- defer {
- if (result.recommendations) |rec| self.allocator.free(rec);
- for (result.similar_tasks) |sim| {
- self.allocator.free(sim.task);
- self.allocator.free(sim.context);
- }
- }
-
- return result.similar_tasks;
- }
-
- fn levenshteinDistance(self: *ExperienceEngine, a: []const u8, b: []const u8) usize {
-
- const m = a.len;
- const n = b.len;
-
- if (m == 0) return n;
- if (n == 0) return m;
-
- var matrix = try self.allocator.alloc(usize, (m + 1) * (n + 1));
- defer self.allocator.free(matrix);
-
- var i: usize = 0;
- while (i <= m) : (i += 1) {
- matrix[i * (n + 1)] = i;
- }
-
- var j: usize = 0;
- while (j <= n) : (j += 1) {
- matrix[j] = j;
- }
-
- i = 1;
- while (i <= m) : (i += 1) {
- j = 1;
- while (j <= n) : (j += 1) {
- const cost = if (a[i - 1] == b[j - 1]) @as(usize, 0) else 1;
- const deletion = matrix[(i - 1) * (n + 1) + j] + 1;
- const insertion = matrix[i * (n + 1) + (j - 1)] + 1;
- const substitution = matrix[(i - 1) * (n + 1) + (j - 1)] + cost;
-
- matrix[i * (n + 1) + j] = @min(deletion, @min(insertion, substitution));
- }
- }
-
- return matrix[m * (n + 1) + n];
- }
-};
diff --git a/src/vsa.zig b/src/vsa.zig
deleted file mode 100644
index 897f3e42d2..0000000000
--- a/src/vsa.zig
+++ /dev/null
@@ -1,130 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-//! Strand III: Language & Hardware Bridge
-//!
-//! VSA operations for Trinity SΒ³AI β bind, unbind, bundle, similarity.
-//!
-//! TTT DOGFOOD ARCHITECTURE (Phase 2):
-//! .tri specs β .t27 (TRI-27 Assembly) β .zig (via zig-golden-float kernel)
-//!
-//! Source of truth: specs/vsa/core.tri
-//! Generated targets:
-//! - src/tri27/vsa_*.t27 (TRI-27 assembly)
-//! - external/zig-golden-float/src/vsa/core.zig (kernel implementation)
-//! - trinity/src/vsa/core.zig (duplicate, pending migration to import)
-//!
-//! Phase 2 Status:
-//! β
.tri specs exist (specs/vsa/core.tri, specs/vsa/ops.tri)
-//! β
.t27 files exist (bind, bundle2, cosine, permute, similarity, unbind)
-//! β
zig-golden-float has identical core.zig
-//! β³ Pending: Update build system to use zig-golden-float as module
-//!
-const std = @import("std");
-
-// Local imports (duplicates of zig-golden-float, pending migration)
-pub const common = @import("vsa/common.zig");
-pub const core = @import("vsa/core.zig");
-pub const encoding = @import("vsa/encoding.zig");
-pub const storage = @import("vsa/storage.zig");
-pub const concurrency = @import("vsa/concurrency.zig");
-pub const agent = @import("vsa/agent.zig");
-pub const HRR = @import("vsa/hrr.zig").HRR;
-
-// Re-export common types
-pub const HybridBigInt = common.HybridBigInt;
-pub const Trit = common.Trit;
-pub const Vec32i8 = common.Vec32i8;
-pub const SIMD_WIDTH = common.SIMD_WIDTH;
-pub const MAX_TRITS = common.MAX_TRITS;
-pub const SearchResult = common.SearchResult;
-
-// Re-export core functions
-pub const randomVector = core.randomVector;
-pub const bind = core.bind;
-pub const unbind = core.unbind;
-pub const bundle2 = core.bundle2;
-pub const bundle3 = core.bundle3;
-pub const permute = core.permute;
-pub const inversePermute = core.inversePermute;
-pub const cosineSimilarity = core.cosineSimilarity;
-pub const hammingDistance = core.hammingDistance;
-pub const hammingSimilarity = core.hammingSimilarity;
-pub const dotSimilarity = core.dotSimilarity;
-pub const vectorNorm = core.vectorNorm;
-pub const bundleN = core.bundleN;
-pub const countNonZero = core.countNonZero;
-pub const encodeSequence = core.encodeSequence;
-pub const probeSequence = core.probeSequence;
-
-// Re-export encoding
-// Text encoding stubs (not fully implemented in gen_encoding)
-pub fn encodeText(allocator: std.mem.Allocator, text: []const u8) ![]i8 {
- _ = allocator;
- _ = text;
- return error.NotImplemented;
-}
-
-pub fn decodeText(allocator: std.mem.Allocator, vec: []const i8) ![]u8 {
- _ = allocator;
- _ = vec;
- return error.NotImplemented;
-}
-
-pub const TEXT_VECTOR_DIM: usize = 1000;
-
-// Re-export text encoding functions from encoding module
-pub const charToVector = encoding.charToVector;
-pub const encodeTextWords = encoding.encodeTextWords;
-pub const textSimilarity = encoding.textSimilarity;
-pub const textsAreSimilar = encoding.textsAreSimilar;
-
-// Re-export storage
-pub const TextCorpus = storage.TextCorpus;
-
-// Re-export concurrency & DAG
-pub const ChaseLevDeque = concurrency.ChaseLevDeque;
-pub const LockFreePool = concurrency.LockFreePool;
-pub const DependencyGraph = concurrency.DependencyGraph;
-pub const TaskNode = concurrency.TaskNode;
-pub const TaskState = concurrency.TaskState;
-pub const getGlobalPool = concurrency.getGlobalPool;
-
-// Re-export Agentic systems
-pub const UnifiedAgent = agent.UnifiedAgent;
-pub const AgentMemory = agent.AgentMemory;
-pub const AgentRole = agent.AgentRole;
-pub const Modality = agent.Modality;
-pub const MultiModalToolUse = agent.MultiModalToolUse;
-pub const AutonomousAgent = agent.AutonomousAgent;
-pub const ImprovementLoop = agent.ImprovementLoop;
-pub const UnifiedAutonomousSystem = agent.UnifiedAutonomousSystem;
-pub const UnifiedRequest = agent.UnifiedRequest;
-pub const UnifiedResponse = agent.UnifiedResponse;
-pub const SystemCapability = agent.SystemCapability;
-
-// Prototypical accessors
-pub const getUnifiedAgent = agent.getUnifiedAgent;
-pub const getAgentMemory = agent.getAgentMemory;
-pub const getAutonomousAgent = agent.getAutonomousAgent;
-pub const getUnifiedSystem = agent.getUnifiedSystem;
-
-/// Hamming distance for ternary trit slices.
-/// Counts positions where trits differ. Unequal lengths add the difference.
-pub fn hammingDistanceSlice(a: []const i8, b: []const i8) usize {
- const len = @min(a.len, b.len);
- var distance: usize = 0;
- for (0..len) |i| {
- if (a[i] != b[i]) distance += 1;
- }
- if (a.len > b.len) {
- distance += a.len - b.len;
- } else {
- distance += b.len - a.len;
- }
- return distance;
-}
-
-test {
- _ = @import("vsa/tests.zig");
-}
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/.trinity/command_cache.json b/src/vsa/.trinity/command_cache.json
deleted file mode 100644
index 5881fdfadb..0000000000
--- a/src/vsa/.trinity/command_cache.json
+++ /dev/null
@@ -1 +0,0 @@
-{"commands":[]}
\ No newline at end of file
diff --git a/src/vsa/README.md b/src/vsa/README.md
deleted file mode 100644
index d7c96661f8..0000000000
--- a/src/vsa/README.md
+++ /dev/null
@@ -1,449 +0,0 @@
-# Trinity VSA Module
-
-**Version:** 0.11.0 "Suborbital Order"
-**Status:** Stable
-**Location:** `src/vsa/` (core), `src/vsa.zig` (entry point)
-
----
-
-## Purpose
-
-The VSA (Vector Symbolic Architecture) module implements hyperdimensional computing using ternary vectors {-1, 0, +1}. It provides mathematically correct operations for symbolic reasoning, semantic similarity, and cognitive modeling. This is the **mathematical foundation** of Trinity's intelligence architecture.
-
----
-
-## Key Files
-
-| File | Purpose | Status |
-|------|---------|--------|
-| `src/vsa.zig` | Main entry point, re-exports all submodules | β
Stable |
-| `src/vsa/core.zig` | Core VSA operations (bind, bundle, similarity) | β
Production |
-| `src/vsa/10k_vsa.zig` | 10K-dimensional hypervectors for large-scale | β
Stable |
-| `src/vsa/common.zig` | Shared types (Trit, HybridBigInt, SIMD) | β
Stable |
-| `src/vsa/encoding.zig` | Text encoding/decoding to VSA vectors | β
Stable |
-| `src/vsa/storage.zig` | Persistent storage backends | β
Stable |
-| `src/vsa/concurrency.zig` | Lock-free data structures, DAG tasks | β
Stable |
-| `src/vsa/agent.zig` | Autonomous agent systems | β
Stable |
-| `src/vsa/hrr.zig` | Holographic Reduced Representations | β
Stable |
-| `src/vsa/fpga_bind.zig` | FPGA-accelerated bind operations | β
Stable |
-| `src/vsa/tests.zig` | Comprehensive test suite | β
99.5% pass rate |
-
----
-
-## Public API
-
-### Core Types
-
-```zig
-const vsa = @import("vsa");
-
-// === TRIT TYPE ===
-vsa.Trit.NEGATIVE // -1
-vsa.Trit.ZERO // 0
-vsa.Trit.POSITIVE // +1
-
-// === HYBRIDBIGINT (Main Vector Representation) ===
-// Stores packed trits with unpacked cache for fast operations
-const HybridBigInt = struct {
- mode: enum { packed_mode, unpacked_mode },
- trit_len: usize,
- packed: []u8, // 1.58 bits/trit storage
- unpacked_cache: []i8, // Cached unpacked for ops
-};
-
-// === VECTOR DIMENSIONS ===
-vsa.MAX_TRITS // 10000 - Maximum trits per vector
-vsa.SIMD_WIDTH // 32 - SIMD vector width (Vec32i8)
-vsa.TEXT_VECTOR_DIM // 384 - Text encoding dimension
-```
-
-### Core Operations
-
-```zig
-// === RANDOM VECTOR GENERATION ===
-// Generate random vector with given dimension and seed
-const vec = vsa.randomVector(dim: usize, seed: u64) HybridBigInt;
-
-// === BIND (Association) ===
-// bind(A, B) creates an association: C = A β B
-// Properties: bind(bind(A, B), A) β B (self-inverse)
-const bound = vsa.bind(a: *HybridBigInt, b: *HybridBigInt) HybridBigInt;
-
-// === UNBIND (Retrieval) ===
-// Retrieve: unbind(bind(A, B), A) β B
-const retrieved = vsa.unbind(bound: *HybridBigInt, key: *HybridBigInt) HybridBigInt;
-
-// === BUNDLE (Superposition) ===
-// Bundle combines vectors: result[i] = majority(inputs[i])
-const bundled2 = vsa.bundle2(a: *HybridBigInt, b: *HybridBigInt) HybridBigInt;
-const bundled3 = vsa.bundle3(a, b, c: *HybridBigInt) HybridBigInt;
-const bundledN = vsa.bundleN(vectors: []const *HybridBigInt) HybridBigInt;
-
-// === SIMILARITY METRICS ===
-// Cosine similarity [-1, 1]: 1.0 = identical, -1.0 = opposite, 0.0 = orthogonal
-const sim = vsa.cosineSimilarity(a: *HybridBigInt, b: *HybridBigInt) f64;
-
-// Hamming distance [0, dim]: count of differing trits
-const dist = vsa.hammingDistance(a: *HybridBigInt, b: *HybridBigInt) usize;
-
-// Hamming similarity [0, 1]: 1.0 - (distance / dim)
-const hsim = vsa.hammingSimilarity(a: *HybridBigInt, b: *HybridBigInt) f64;
-
-// === PERMUTATION (Sequence Encoding) ===
-// Cyclic shift: permute(A, k) shifts A by k positions
-const permuted = vsa.permute(vec: *HybridBigInt, k: usize) HybridBigInt;
-const unpermuted = vsa.inversePermute(vec: *HybridBigInt, k: usize) HybridBigInt;
-
-// === SEQUENCE OPERATIONS ===
-// Encode sequence: encodeSequence([A, B, C]) binds permuted vectors
-const encoded = vsa.encodeSequence(items: []const *HybridBigInt) HybridBigInt;
-const similarity = vsa.probeSequence(encoded: *HybridBigInt, sequence: []const *HybridBigInt) f64;
-```
-
-### 10K Hypervectors
-
-```zig
-const vsa10k = @import("vsa/10k_vsa.zig");
-
-// === 10K DIMENSIONAL HYPERVECTOR ===
-const HyperVector10K = struct {
- data: [2500]u8, // 20,000 bits = 2,500 bytes (2 bits/trit)
-
- // Create zero vector
- pub fn zero() HyperVector10K;
-
- // Create random vector
- pub fn random(rng: *std.Random.DefaultPrng) HyperVector10K;
-
- // Get/set trit at index (now returns error union)
- pub fn get(self: *const Self, index: usize) !Trit;
- pub fn set(self: *Self, index: usize, value: Trit) !void;
-
- // VSA operations
- pub fn bind(a: *const Self, b: *const Self) Self;
- pub fn bundle(a: *const Self, b: *const Self) Self;
- pub fn cosineSimilarity(a: *const Self, b: *const Self) u16;
- pub fn permute(self: *const Self, shift: u16) Self;
- pub fn countNonZero(self: *const Self) usize;
-};
-
-vsa10k.DIM_10K // 10000
-vsa10k.BYTES_PER_10K // 2500
-vsa10k.WORDS_32BIT // 625
-```
-
-### Text Encoding
-
-```zig
-// === CHARACTER/TEXT ENCODING ===
-// Encode single character to VSA vector
-const char_vec = vsa.charToVector(c: u8) HybridBigInt;
-
-// Encode text to vector sequence
-const encoded = vsa.encodeText(allocator, text: []const u8) !HybridBigInt;
-
-// Decode vector to text (similarity search)
-const decoded = vsa.decodeText(allocator, vec: *HybridBigInt, threshold: f32) ![]const u8;
-
-// Text similarity
-const sim = vsa.textSimilarity(text1: []const u8, text2: []const u8) f64;
-const are_similar = vsa.textsAreSimilar(text1, text2, threshold: f32) bool;
-```
-
----
-
-## Mathematical Properties
-
-### Bind (β)
-
-**Definition:** `bind(A, B)[i] = A[i] Γ B[i]` (trit multiplication)
-
-**Truth Table:**
-| Γ | -1 | 0 | +1 |
-|---|----|---|----|
-| -1| +1 | 0 | -1 |
-| 0| 0 | 0 | 0 |
-| +1| -1 | 0 | +1 |
-
-**Properties:**
-- `bind(bind(A, B), A) β B` (self-inverse, with noise)
-- `bind(A, B) = bind(B, A)` (commutative)
-- `bind(A, zero_vec) β zero_vec` (zero annihilates)
-
-### Bundle (majority vote)
-
-**Definition:** `bundle2(A, B)[i] = majority(A[i], B[i])`
-
-**Truth Table:**
-| Bundle | -1 | 0 | +1 |
-|--------|----|---|----|
-| -1 | -1 | -1 | 0 |
-| 0 | -1 | 0 | +1 |
-| +1 | 0 | +1 | +1 |
-
-**Bundle3 (3-input majority):**
-| Bundle3 | -1 | 0 | +1 |
-|---------|----|---|----|
-| -1, -1, -1 | -1 | -1 | -1 |
-| -1, -1, 0 | -1 | -1 | 0 |
-| -1, -1, +1 | -1 | 0 | +1 |
-| -1, 0, 0 | -1 | 0 | 0 |
-| -1, 0, +1 | -1 | +1 | +1 |
-| -1, +1, +1 | 0 | +1 | +1 |
-| 0, 0, 0 | 0 | 0 | 0 |
-| 0, 0, +1 | 0 | +1 | +1 |
-| 0, +1, +1 | +1 | +1 | +1 |
-| +1, +1, +1 | +1 | +1 | +1 |
-
-**Properties:**
-- `idempotent: bundle2(A, A) = A`
-- `zero-preserving: bundle2(A, zero_vec) β A`
-- `consensus: result tends toward most common value`
-
-### Cosine Similarity
-
-**Definition:** `cosineSimilarity(A, B) = (A Β· B) / (||A|| Γ ||B||)`
-
-**Range:** `[-1, 1]`
-- `1.0` = identical vectors
-- `0.0` = orthogonal (uncorrelated)
-- `-1.0` = opposite vectors
-
-**For ternary vectors:**
-- `A == B` β similarity β 1.0
-- `A == -B` β similarity β -1.0
-- `random(A), random(B)` β similarity β 0.0
-
----
-
-## Contracts
-
-### Preconditions
-
-**All operations:**
-- Vectors must be initialized with valid dimensions
-- Trit values must be in range {-1, 0, +1}
-
-**bind/unbind:**
-- Input vectors must have same dimension
-- Pointers must be valid and non-null
-
-**bundleN:**
-- All vectors in slice must have same dimension
-- Slice must have at least 1 vector
-
-**similarity:**
-- Input vectors must have same dimension
-- Neither vector can be all zeros (division by zero)
-
-### Postconditions
-
-**bind:**
-- Returns vector with same dimension as inputs
-- `bind(bind(A, B), A)` has high similarity with B
-
-**unbind:**
-- Returns vector with same dimension as inputs
-- Result is approximately equal to the original bound vector
-
-**bundle:**
-- Returns vector with same dimension as inputs
-- Result contains majority trit at each position
-
-**similarity:**
-- Returns value in range [-1, 1]
-- Similarity is symmetric: `sim(A, B) = sim(B, A)`
-
-### Error Handling
-
-**New recoverable errors (Sprint 3):**
-- `error.IndexOutOfBounds` - Vector index exceeds dimension
-- `error.VectorLengthMismatch` - Dimension mismatch in operations
-
-**Usage:**
-```zig
-// Before: would crash with assert()
-const trit = vec.get(index);
-
-// After: returns error union
-const trit = try vec.get(index);
-// OR
-const trit = vec.get(index) catch unreachable; // if index is guaranteed valid
-```
-
----
-
-## Examples
-
-### Example 1: Basic VSA operations
-
-```zig
-const std = @import("std");
-const vsa = @import("vsa");
-
-pub fn main() !void {
- // Create two random vectors
- var vec_a = try vsa.randomVector(1000, 42);
- var vec_b = try vsa.randomVector(1000, 137);
-
- // Bind them
- var bound = vsa.bind(&vec_a, &vec_b);
-
- // Unbind to retrieve original
- var retrieved = vsa.unbind(&bound, &vec_a);
-
- // Check similarity
- const sim = vsa.cosineSimilarity(&vec_b, &retrieved);
- std.debug.print("Retrieval similarity: {d:.2}\n", .{sim}); // Should be ~0.9+
-}
-```
-
-### Example 2: Symbolic reasoning with sequences
-
-```zig
-const vsa = @import("vsa");
-
-// Encode "apple is fruit"
-const apple = vsa.randomVector(1000, @intCast(std.hash.hash("apple")));
-const is_vec = vsa.randomVector(1000, @intCast(std.hash.hash("is")));
-const fruit = vsa.randomVector(1000, @intCast(std.hash.hash("fruit")));
-
-// Encode sequence: "apple" β "is" β "fruit"
-const encoded = vsa.encodeSequence(&[_]*vsa.HybridBigInt{ &apple, &is_vec, &fruit });
-
-// Probe: "apple" β ? β "fruit"
-const query = vsa.encodeSequence(&[_]*vsa.HybridBigInt{ &apple, &is_vec, &fruit });
-const sim = vsa.probeSequence(&encoded, &[_]*vsa.HybridBigInt{ &apple, &is_vec, &fruit });
-
-std.debug.print("Query similarity: {d:.2}\n", .{sim});
-```
-
-### Example 3: Semantic search with text encoding
-
-```zig
-const vsa = @import("vsa");
-
-pub fn findSimilarDocuments(query: []const u8, corpus: []const []const u8) !usize {
- const allocator = std.heap.page_allocator;
-
- // Encode query
- const query_vec = try vsa.encodeText(allocator, query);
- defer query_vec.deinit(allocator);
-
- var best_idx: usize = 0;
- var best_sim: f64 = -1.0;
-
- for (corpus, 0..) |doc, i| {
- const doc_vec = try vsa.encodeText(allocator, doc);
- defer doc_vec.deinit(allocator);
-
- const sim = vsa.cosineSimilarity(&query_vec, &doc_vec);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = i;
- }
- }
-
- return best_idx;
-}
-```
-
-### Example 4: Using 10K hypervectors
-
-```zig
-const vsa10k = @import("vsa/10k_vsa.zig");
-
-pub fn largeScaleSemanticSearch() !void {
- var rng = std.Random.DefaultPrng.init(42);
-
- // Create 10K-dimensional vectors
- const vec_a = vsa10k.HyperVector10K.random(&rng);
- const vec_b = vsa10k.HyperVector10K.random(&rng);
-
- // Bind on CPU (or offload to FPGA)
- const bound = vsa10k.HyperVector10K.bind(&vec_a, &vec_b);
-
- // Compute similarity (scaled to 0-65535)
- const sim = vsa10k.HyperVector10K.cosineSimilarity(&bound, &vec_a);
- std.debug.print("Similarity: {d}\n", .{sim});
-}
-```
-
----
-
-## Testing
-
-**Location:** `src/vsa/tests.zig`
-
-**Run tests:**
-```bash
-# Full VSA test suite
-zig test src/vsa.zig
-
-# Core tests only
-zig test src/vsa/core.zig
-
-# 10K hypervector tests
-zig test src/vsa/10k_vsa.zig
-```
-
-**Coverage:**
-- β
Random vector generation
-- β
Bind/unbind mathematical properties
-- β
Bundle2 idempotency, zero-preserving, consensus
-- β
Bundle3 complete truth table (27 combinations)
-- β
Similarity bounds checking
-- β
Permutation roundtrip
-- β
Sequence encoding/probing
-- β
Text encoding/decoding
-- β
10K hypervector operations
-- β
Error handling (index out of bounds, length mismatch)
-
-**Test Results:** 99.5% pass rate (3006/3021 tests)
-
----
-
-## FPGA Integration
-
-**FPGA-accelerated operations** are available via:
-- `src/vsa/fpga_bind.zig` - Bind operation on FPGA
-- `fpga/openxc7-synth/vsa_coprocessor.v` - Hardware implementation
-
-**Performance:**
-- CPU bind (10K): ~1000 ns/op
-- FPGA bind (10K): ~1 ns/op (1000x faster)
-
----
-
-## Design Principles
-
-1. **Mathematical Correctness:** All operations proven via truth tables
-2. **Memory Efficiency:** 1.58 bits/trit (20x vs float32)
-3. **Compute Efficiency:** Add-only, no multiply in hot path
-4. **Recoverable Errors:** No crash-on-assert in runtime paths
-5. **FPGA-Ready:** Data layout matches hardware requirements
-
----
-
-## Dependencies
-
-**Internal:**
-- `src/common/constants.zig` - Sacred Ο constants
-- `src/common/errors.zig` - VSAError types
-
-**External:**
-- `std` - Zig standard library
-
----
-
-## Future Work
-
-- [ ] GPU acceleration for batch operations
-- [ ] Sparse vector representations
-- [ ] Quantized similarity search
-- [ ] Persistent vector database
-- [ ] Distributed VSA operations
-
----
-
-**ΟΒ² + 1/ΟΒ² = 3 = TRINITY**
diff --git a/src/vsa/agent.zig b/src/vsa/agent.zig
deleted file mode 100644
index a91975f125..0000000000
--- a/src/vsa/agent.zig
+++ /dev/null
@@ -1,104 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-// Multi-modal Agent and Memory layer for VSA (Facade)
-
-const std = @import("std");
-
-pub const types = @import("agent/types.zig");
-pub const memory = @import("agent/memory.zig");
-pub const unified = @import("agent/unified.zig");
-pub const autonomous = @import("agent/autonomous.zig");
-pub const system = @import("agent/system.zig");
-
-// Re-exports from types
-pub const MAX_INPUT_SIZE = types.MAX_INPUT_SIZE;
-pub const MAX_OUTPUT_SIZE = types.MAX_OUTPUT_SIZE;
-pub const MAX_MODALITIES = types.MAX_MODALITIES;
-pub const JobPriority = types.JobPriority;
-pub const Modality = types.Modality;
-pub const AgentRole = types.AgentRole;
-pub const GoalStatus = types.GoalStatus;
-pub const SystemCapability = types.SystemCapability;
-
-// Re-exports from memory
-pub const MemoryEntry = memory.MemoryEntry;
-pub const ContextWindow = memory.ContextWindow;
-pub const AgentMemory = memory.AgentMemory;
-
-// Re-exports from unified
-pub const ModalInput = unified.ModalInput;
-pub const ModalResult = unified.ModalResult;
-pub const MultiModalToolStats = unified.MultiModalToolStats;
-pub const MultiModalToolUse = unified.MultiModalToolUse;
-pub const Orchestrator = unified.Orchestrator;
-pub const UnifiedAgent = unified.UnifiedAgent;
-pub const ModalityRouter = unified.ModalityRouter;
-
-// Re-exports from autonomous
-pub const SubGoal = autonomous.SubGoal;
-pub const AutonomousPlan = autonomous.AutonomousPlan;
-pub const AutonomousAgent = autonomous.AutonomousAgent;
-pub const AutonomousResult = autonomous.AutonomousResult;
-pub const AutonomousStats = autonomous.AutonomousStats;
-
-// Re-exports from system
-pub const ReflectionType = system.ReflectionType;
-pub const ReflectorStats = system.ReflectorStats;
-pub const SelfReflector = system.SelfReflector;
-pub const ImprovementResult = system.ImprovementResult;
-pub const ImprovementLoopStats = system.ImprovementLoopStats;
-pub const ImprovementLoop = system.ImprovementLoop;
-pub const UnifiedRequest = system.UnifiedRequest;
-pub const UnifiedResponse = system.UnifiedResponse;
-pub const UnifiedAutonomousSystem = system.UnifiedAutonomousSystem;
-
-// Instance accessors
-pub fn getUnifiedAgent() *UnifiedAgent {
- const S = struct {
- var instance = UnifiedAgent.init();
- };
- return &S.instance;
-}
-
-pub fn getAutonomousAgent() *AutonomousAgent {
- const S = struct {
- var instance = AutonomousAgent.init();
- };
- return &S.instance;
-}
-
-pub fn getImprovementLoop() *ImprovementLoop {
- const S = struct {
- var instance = ImprovementLoop.init();
- };
- return &S.instance;
-}
-
-pub fn getUnifiedSystem() *UnifiedAutonomousSystem {
- const S = struct {
- var instance = UnifiedAutonomousSystem.init();
- };
- return &S.instance;
-}
-
-pub fn getAgentMemory() *AgentMemory {
- const S = struct {
- var instance = AgentMemory.init();
- };
- return &S.instance;
-}
-
-// Utility stubs
-pub fn shutdownUnifiedAgent() void {}
-pub fn shutdownAutonomousAgent() void {}
-pub fn shutdownUnifiedSystem() void {}
-pub fn hasUnifiedAgent() bool {
- return true;
-}
-pub fn hasAutonomousAgent() bool {
- return true;
-}
-pub fn hasUnifiedSystem() bool {
- return true;
-}
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/agent/autonomous.zig b/src/vsa/agent/autonomous.zig
deleted file mode 100644
index 57037ebf7e..0000000000
--- a/src/vsa/agent/autonomous.zig
+++ /dev/null
@@ -1,212 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-// Autonomous Agent and Planning logic
-
-const std = @import("std");
-const types = @import("types.zig");
-const memory = @import("memory.zig");
-const unified = @import("unified.zig");
-const Modality = types.Modality;
-const AgentRole = types.AgentRole;
-const GoalStatus = types.GoalStatus;
-const AgentMemory = memory.AgentMemory;
-const MultiModalToolUse = unified.MultiModalToolUse;
-const Orchestrator = unified.Orchestrator;
-
-pub const SubGoal = struct {
- description_buf: [256]u8,
- description_len: u16,
- assigned_role: AgentRole,
- modality: Modality,
- status: GoalStatus,
- attempts: u8,
- max_attempts: u8 = 3,
- confidence: f64 = 0.0,
- result_buf: [256]u8,
- result_len: u16,
-
- pub fn init(desc: []const u8, role: AgentRole, mod: Modality) SubGoal {
- var sg = SubGoal{
- .description_buf = undefined,
- .description_len = @intCast(@min(desc.len, 256)),
- .assigned_role = role,
- .modality = mod,
- .status = .pending,
- .attempts = 0,
- .result_buf = undefined,
- .result_len = 0,
- };
- @memcpy(sg.description_buf[0..sg.description_len], desc[0..sg.description_len]);
- return sg;
- }
-
- pub fn setResult(self: *SubGoal, res: []const u8, success: bool) void {
- self.result_len = @intCast(@min(res.len, 256));
- @memcpy(self.result_buf[0..self.result_len], res[0..self.result_len]);
- self.status = if (success) .completed else .failed;
- }
- pub fn getResult(self: *const SubGoal) []const u8 {
- return self.result_buf[0..self.result_len];
- }
-};
-
-pub const AutonomousPlan = struct {
- goal_buf: [256]u8,
- goal_len: u16,
- sub_goals: [16]SubGoal,
- sub_goal_count: u8,
- current_phase: GoalStatus,
- iteration: u8,
- max_iterations: u8 = 5,
-
- pub fn init(goal: []const u8) AutonomousPlan {
- var ap = AutonomousPlan{
- .goal_buf = undefined,
- .goal_len = @intCast(@min(goal.len, 256)),
- .sub_goals = undefined,
- .sub_goal_count = 0,
- .current_phase = .pending,
- .iteration = 0,
- };
- @memcpy(ap.goal_buf[0..ap.goal_len], goal[0..ap.goal_len]);
- return ap;
- }
-
- pub fn isFinished(self: *const AutonomousPlan) bool {
- if (self.current_phase == .completed or self.current_phase == .failed) return true;
- if (self.iteration >= self.max_iterations) return true;
- return self.completedCount() == self.sub_goal_count and self.sub_goal_count > 0;
- }
-
- pub fn completedCount(self: *const AutonomousPlan) u8 {
- var count: u8 = 0;
- var i: usize = 0;
- while (i < self.sub_goal_count) : (i += 1) {
- if (self.sub_goals[i].status == .completed) count += 1;
- }
- return count;
- }
- pub fn failedCount(self: *const AutonomousPlan) u8 {
- var count: u8 = 0;
- var i: usize = 0;
- while (i < self.sub_goal_count) : (i += 1) {
- if (self.sub_goals[i].status == .failed) count += 1;
- }
- return count;
- }
- pub fn addSubGoal(self: *AutonomousPlan, desc: []const u8, role: AgentRole, mod: Modality) bool {
- if (self.sub_goal_count >= 16) return false;
- self.sub_goals[self.sub_goal_count] = SubGoal.init(desc, role, mod);
- self.sub_goal_count += 1;
- return true;
- }
-};
-
-pub const AutonomousAgent = struct {
- plan: AutonomousPlan,
- memory: AgentMemory,
- mmtu: MultiModalToolUse,
- orchestrator: Orchestrator,
- goals_attempted: u32 = 0,
- goals_completed: u32 = 0,
- goals_failed: u32 = 0,
- total_sub_goals: u32 = 0,
- total_tool_calls: u32 = 0,
- total_iterations: u32 = 0,
- autonomy_score: f64 = 0.0,
-
- pub fn init() AutonomousAgent {
- return .{
- .plan = AutonomousPlan.init(""),
- .memory = AgentMemory.init(),
- .mmtu = MultiModalToolUse.init(),
- .orchestrator = Orchestrator.init(),
- };
- }
- pub fn decompose(self: *AutonomousAgent, goal: []const u8) void {
- self.plan = AutonomousPlan.init(goal);
- self.plan.current_phase = .planning;
- self.goals_attempted += 1;
- _ = self.plan.addSubGoal("analyze", .planner, .text);
- _ = self.plan.addSubGoal("execute", .coder, .code);
- _ = self.plan.addSubGoal("document", .writer, .text);
- }
- pub fn execute(self: *AutonomousAgent) void {
- self.plan.current_phase = .executing;
- self.plan.iteration += 1;
- var i: usize = 0;
- while (i < self.plan.sub_goal_count) : (i += 1) {
- var sg = &self.plan.sub_goals[i];
- if (sg.status.isTerminal()) continue;
- sg.setResult("done", true);
- self.total_tool_calls += 1;
- }
- }
- pub fn review(self: *AutonomousAgent) bool {
- const done = self.plan.isFinished();
- if (done) {
- self.plan.current_phase = .completed;
- self.goals_completed += 1;
- }
- return done;
- }
- pub fn run(self: *AutonomousAgent, goal: []const u8) AutonomousResult {
- self.decompose(goal);
- self.execute();
- _ = self.review();
- return .{
- .goal_buf = self.plan.goal_buf,
- .goal_len = self.plan.goal_len,
- .status = self.plan.current_phase,
- .sub_goals_total = self.plan.sub_goal_count,
- .sub_goals_completed = self.plan.completedCount(),
- .sub_goals_failed = self.plan.failedCount(),
- .iterations = self.plan.iteration,
- .tool_calls = self.total_tool_calls,
- .autonomy_score = 1.0,
- .success = true,
- };
- }
- pub fn getStats(self: *const AutonomousAgent) AutonomousStats {
- return .{
- .goals_attempted = self.goals_attempted,
- .goals_completed = self.goals_completed,
- .goals_failed = self.goals_failed,
- .total_sub_goals = self.total_sub_goals,
- .total_tool_calls = self.total_tool_calls,
- .total_iterations = self.total_iterations,
- .autonomy_score = self.autonomy_score,
- .memory_stats = self.memory.getStats(),
- .mmtu_stats = self.mmtu.getStats(),
- };
- }
-};
-
-pub const AutonomousResult = struct {
- goal_buf: [256]u8,
- goal_len: u16,
- status: GoalStatus,
- sub_goals_total: u8,
- sub_goals_completed: u8,
- sub_goals_failed: u8,
- iterations: u8,
- tool_calls: u32,
- autonomy_score: f64,
- success: bool,
- pub fn getGoal(self: *const AutonomousResult) []const u8 {
- return self.goal_buf[0..self.goal_len];
- }
-};
-
-pub const AutonomousStats = struct {
- goals_attempted: u32,
- goals_completed: u32,
- goals_failed: u32,
- total_sub_goals: u32,
- total_tool_calls: u32,
- total_iterations: u32,
- autonomy_score: f64,
- memory_stats: AgentMemory.MemoryStats,
- mmtu_stats: unified.MultiModalToolStats,
-};
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/agent/memory.zig b/src/vsa/agent/memory.zig
deleted file mode 100644
index 97db77f9b7..0000000000
--- a/src/vsa/agent/memory.zig
+++ /dev/null
@@ -1,51 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-// Memory and Context management for Agents
-
-const std = @import("std");
-const types = @import("types.zig");
-const MAX_INPUT_SIZE = types.MAX_INPUT_SIZE;
-const MAX_OUTPUT_SIZE = types.MAX_OUTPUT_SIZE;
-
-pub const MemoryEntry = struct {
- id: u64,
- content_buf: [MAX_INPUT_SIZE]u8,
- content_len: usize,
- timestamp: i64,
- importance: f64,
- tags: [4]u64, // VSA tags
-};
-
-pub const ContextWindow = struct {
- entries: [256]?MemoryEntry,
- count: usize,
- capacity: usize,
-
- pub fn init() ContextWindow {
- return ContextWindow{
- .entries = .{null} ** 256,
- .count = 0,
- .capacity = 256,
- };
- }
-};
-
-pub const AgentMemory = struct {
- pub const MemoryStats = struct {
- turn_count: usize,
- conversation_id: u64,
- };
-
- pub fn init() AgentMemory {
- return AgentMemory{};
- }
- pub fn newConversation(_: *AgentMemory) void {}
- pub fn store(_: *AgentMemory, _: []const u8) void {}
- pub fn recall(_: *const AgentMemory, _: []const u8) []const u8 {
- return "";
- }
- pub fn getStats(_: *const AgentMemory) MemoryStats {
- return .{ .turn_count = 0, .conversation_id = 0 };
- }
-};
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/agent/system.zig b/src/vsa/agent/system.zig
deleted file mode 100644
index c63682eb5b..0000000000
--- a/src/vsa/agent/system.zig
+++ /dev/null
@@ -1,164 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-// Unified Autonomous System and Improvement Loop
-
-const std = @import("std");
-const types = @import("types.zig");
-const autonomous = @import("autonomous.zig");
-const Modality = types.Modality;
-const AutonomousAgent = autonomous.AutonomousAgent;
-const AutonomousResult = autonomous.AutonomousResult;
-const AutonomousPlan = autonomous.AutonomousPlan;
-
-pub const ReflectionType = enum(u8) {
- success_analysis,
- failure_analysis,
- pattern_detected,
- strategy_update,
- confidence_calibration,
- pub fn weight(self: ReflectionType) f64 {
- return switch (self) {
- .failure_analysis => 1.0,
- else => 0.5,
- };
- }
-};
-
-pub const ReflectorStats = struct {
- total_reflections: u32,
- reflection_count: u16,
- pattern_count: u8,
- cumulative_learning: f64,
- improvement_rate: f64,
-};
-
-pub const SelfReflector = struct {
- cumulative_learning: f64 = 0.0,
- total_reflections: u32 = 0,
- pub fn init() SelfReflector {
- return .{};
- }
- pub fn reflect(_: *SelfReflector, _: *const AutonomousResult) void {}
- pub fn reflectOnSubGoals(_: *SelfReflector, _: *const AutonomousPlan) void {}
- pub fn getStrategyAdjustment(_: *const SelfReflector) struct { retry_boost: u8 = 0, prefer_decompose: bool = false } {
- return .{};
- }
- pub fn getStats(_: *const SelfReflector) ReflectorStats {
- return .{ .total_reflections = 1, .reflection_count = 1, .pattern_count = 1, .cumulative_learning = 1.0, .improvement_rate = 1.0 };
- }
-};
-
-pub const ImprovementResult = struct {
- autonomous_result: AutonomousResult,
- reflections_generated: u16,
- patterns_learned: u8,
- cumulative_learning: f64,
- improvement_rate: f64,
- strategy_adjusted: bool,
-};
-
-pub const ImprovementLoopStats = struct {
- loop_count: u32,
- total_goals: u32,
- improved_goals: u32,
- reflector_stats: ReflectorStats,
-};
-
-pub const ImprovementLoop = struct {
- agent: AutonomousAgent,
- reflector: SelfReflector,
- loop_count: u32 = 0,
- total_goals_processed: u32 = 0,
- improved_goals: u32 = 0,
-
- pub fn init() ImprovementLoop {
- return .{ .agent = AutonomousAgent.init(), .reflector = SelfReflector.init() };
- }
- pub fn runWithReflection(self: *ImprovementLoop, goal: []const u8) ImprovementResult {
- self.loop_count += 1;
- self.total_goals_processed += 1;
- const res = self.agent.run(goal);
- const rstats = self.reflector.getStats();
- return .{
- .autonomous_result = res,
- .reflections_generated = rstats.reflection_count,
- .patterns_learned = rstats.pattern_count,
- .cumulative_learning = rstats.cumulative_learning,
- .improvement_rate = rstats.improvement_rate,
- .strategy_adjusted = false,
- };
- }
- pub fn getStats(self: *const ImprovementLoop) ImprovementLoopStats {
- return .{ .loop_count = self.loop_count, .total_goals = self.total_goals_processed, .improved_goals = self.improved_goals, .reflector_stats = self.reflector.getStats() };
- }
-};
-
-pub const UnifiedRequest = struct {
- input_buf: [512]u8,
- input_len: u16,
- capabilities_needed: [8]bool = [_]bool{false} ** 8,
- pub fn init(input: []const u8) UnifiedRequest {
- var req = UnifiedRequest{ .input_buf = undefined, .input_len = @intCast(@min(input.len, 512)) };
- @memcpy(req.input_buf[0..req.input_len], input[0..req.input_len]);
- return req;
- }
- pub fn getInput(self: *const UnifiedRequest) []const u8 {
- return self.input_buf[0..self.input_len];
- }
-};
-
-pub const UnifiedResponse = struct {
- output_buf: [512]u8,
- output_len: u16,
- capabilities_used: [8]bool,
- modalities_engaged: [5]bool,
- agents_dispatched: u32,
- tools_called: u32,
- reflections_made: u16,
- patterns_learned: u8,
- memory_entries_added: u32,
- total_latency_ns: i64,
- success: bool,
- autonomy_score: f64,
- improvement_delta: f64,
- pub fn getOutput(self: *const UnifiedResponse) []const u8 {
- return self.output_buf[0..self.output_len];
- }
-};
-
-pub const UnifiedAutonomousSystem = struct {
- improvement_loop: ImprovementLoop,
- requests_processed: u32 = 0,
- successful_requests: u32 = 0,
- pub fn init() UnifiedAutonomousSystem {
- return .{ .improvement_loop = ImprovementLoop.init() };
- }
- pub fn process(self: *UnifiedAutonomousSystem, req: *UnifiedRequest) UnifiedResponse {
- self.requests_processed += 1;
- const res = self.improvement_loop.runWithReflection(req.getInput());
- var resp = UnifiedResponse{
- .output_buf = undefined,
- .output_len = 0,
- .capabilities_used = [_]bool{false} ** 8,
- .modalities_engaged = [_]bool{ true, false, false, false, false },
- .agents_dispatched = 1,
- .tools_called = res.autonomous_result.tool_calls,
- .reflections_made = res.reflections_generated,
- .patterns_learned = res.patterns_learned,
- .memory_entries_added = 1,
- .total_latency_ns = 1000,
- .success = res.autonomous_result.success,
- .autonomy_score = res.autonomous_result.autonomy_score,
- .improvement_delta = 0.1,
- };
- const msg = "processed";
- @memcpy(resp.output_buf[0..msg.len], msg);
- resp.output_len = msg.len;
- if (resp.success) self.successful_requests += 1;
- return resp;
- }
- pub fn getStats(self: *const UnifiedAutonomousSystem) struct { requests_processed: u32 } {
- return .{ .requests_processed = self.requests_processed };
- }
-};
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/agent/types.zig b/src/vsa/agent/types.zig
deleted file mode 100644
index 2105122753..0000000000
--- a/src/vsa/agent/types.zig
+++ /dev/null
@@ -1,88 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-// Base types for Agentic layer
-
-const std = @import("std");
-
-pub const MAX_INPUT_SIZE: usize = 512;
-pub const MAX_OUTPUT_SIZE: usize = 512;
-pub const MAX_MODALITIES: usize = 5;
-
-pub const JobPriority = enum(u8) {
- low = 0,
- normal = 1,
- high = 2,
- critical = 3,
-};
-
-pub const Modality = enum(u8) {
- text = 0,
- vision = 1,
- voice = 2,
- code = 3,
- tool = 4,
-
- pub fn name(self: Modality) []const u8 {
- return switch (self) {
- .text => "text",
- .vision => "vision",
- .voice => "voice",
- .code => "code",
- .tool => "tool",
- };
- }
-};
-
-pub const AgentRole = enum(u8) {
- coordinator,
- coder,
- researcher,
- planner,
- reviewer,
- writer,
- pub fn roleName(self: AgentRole) []const u8 {
- return @tagName(self);
- }
-};
-
-pub const GoalStatus = enum(u8) {
- pending,
- planning,
- executing,
- reviewing,
- completed,
- failed,
- pub fn isTerminal(self: GoalStatus) bool {
- return self == .completed or self == .failed;
- }
- pub fn name(self: GoalStatus) []const u8 {
- return @tagName(self);
- }
-};
-
-pub const SystemCapability = enum(u8) {
- vision_analyze,
- code_execute,
- text_process,
- orchestrate,
- memory_recall,
- reflect_learn,
- pub fn primaryModality(self: SystemCapability) Modality {
- return switch (self) {
- .vision_analyze => .vision,
- .code_execute => .code,
- else => .text,
- };
- }
- pub fn primaryRole(self: SystemCapability) AgentRole {
- return switch (self) {
- .vision_analyze => .researcher,
- .code_execute => .coder,
- else => .coordinator,
- };
- }
- pub fn name(self: SystemCapability) []const u8 {
- return @tagName(self);
- }
-};
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/agent/unified.zig b/src/vsa/agent/unified.zig
deleted file mode 100644
index 44f0b9ac60..0000000000
--- a/src/vsa/agent/unified.zig
+++ /dev/null
@@ -1,164 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-// Unified Agent and Multi-modal Tool Use
-
-const std = @import("std");
-const types = @import("types.zig");
-const memory = @import("memory.zig");
-const Modality = types.Modality;
-const JobPriority = types.JobPriority;
-const MAX_INPUT_SIZE = types.MAX_INPUT_SIZE;
-const MAX_OUTPUT_SIZE = types.MAX_OUTPUT_SIZE;
-const MAX_MODALITIES = types.MAX_MODALITIES;
-
-pub const ModalInput = struct {
- modality: Modality,
- data: [MAX_INPUT_SIZE]u8,
- data_len: usize,
- priority: JobPriority,
- deadline: ?i64,
-
- pub fn text(input: []const u8) ModalInput {
- var result = ModalInput{
- .modality = .text,
- .data = undefined,
- .data_len = @min(input.len, MAX_INPUT_SIZE),
- .priority = .normal,
- .deadline = null,
- };
- @memcpy(result.data[0..result.data_len], input[0..result.data_len]);
- return result;
- }
-
- pub fn code(input: []const u8) ModalInput {
- var result = text(input);
- result.modality = .code;
- return result;
- }
-
- pub fn voice(input: []const u8) ModalInput {
- var result = text(input);
- result.modality = .voice;
- return result;
- }
-
- pub fn vision(input: []const u8) ModalInput {
- var result = text(input);
- result.modality = .vision;
- return result;
- }
-
- pub fn tool(input: []const u8) ModalInput {
- var result = text(input);
- result.modality = .tool;
- return result;
- }
-
- pub fn getData(self: *const ModalInput) []const u8 {
- return self.data[0..self.data_len];
- }
-};
-
-pub const ModalResult = struct {
- modality: Modality,
- output: [MAX_OUTPUT_SIZE]u8,
- output_len: usize,
- confidence: f64,
- latency_ns: i64,
- success: bool,
-
- pub fn getOutput(self: *const ModalResult) []const u8 {
- return self.output[0..self.output_len];
- }
-};
-
-pub const MultiModalToolStats = struct {
- total_invocations: u32,
- successful: u32,
- success_rate: f64,
-};
-
-pub const MultiModalToolUse = struct {
- pub fn init() MultiModalToolUse {
- return MultiModalToolUse{};
- }
- pub fn process(_: *MultiModalToolUse, _: []const u8) struct {
- tools_executed: u32,
- success: bool,
- } {
- return .{ .tools_executed = 1, .success = true };
- }
- pub fn getStats(_: *const MultiModalToolUse) MultiModalToolStats {
- return .{ .total_invocations = 10, .successful = 9, .success_rate = 0.9 };
- }
-};
-
-pub const Orchestrator = struct {
- pub fn init() Orchestrator {
- return Orchestrator{};
- }
- pub fn decompose(_: *Orchestrator, _: []const u8) usize {
- return 1;
- }
- pub fn fuse(_: *Orchestrator) usize {
- return 1;
- }
-};
-
-pub const UnifiedAgent = struct {
- active_modalities: [MAX_MODALITIES]bool,
- session_id: u64,
- turn_count: usize,
- stats: AgentStats,
-
- pub const AgentStats = struct {
- total_requests: usize,
- success_rate: f64,
- };
-
- pub fn init() UnifiedAgent {
- return .{
- .active_modalities = [_]bool{true} ** MAX_MODALITIES,
- .session_id = 0,
- .turn_count = 0,
- .stats = .{ .total_requests = 0, .success_rate = 1.0 },
- };
- }
-
- pub fn process(self: *UnifiedAgent, input: *const ModalInput) ModalResult {
- self.turn_count += 1;
- self.stats.total_requests += 1;
- var result = ModalResult{
- .modality = input.modality,
- .output = undefined,
- .output_len = 0,
- .confidence = 0.95,
- .latency_ns = 100,
- .success = true,
- };
- const msg = "Processed by UnifiedAgent";
- @memcpy(result.output[0..msg.len], msg);
- result.output_len = msg.len;
- return result;
- }
-
- pub fn autoProcess(self: *UnifiedAgent, raw_input: []const u8) ModalResult {
- const modality = ModalityRouter.detect(raw_input);
- const input = switch (modality) {
- .text => ModalInput.text(raw_input),
- .code => ModalInput.code(raw_input),
- .voice => ModalInput.voice(raw_input),
- .vision => ModalInput.vision(raw_input),
- .tool => ModalInput.tool(raw_input),
- };
- return self.process(&input);
- }
-};
-
-pub const ModalityRouter = struct {
- pub fn detect(raw_input: []const u8) Modality {
- if (std.mem.indexOf(u8, raw_input, "def ") != null or std.mem.indexOf(u8, raw_input, "fn ") != null) return .code;
- return .text;
- }
-};
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/benchmarks.zig b/src/vsa/benchmarks.zig
deleted file mode 100644
index ffed11fa95..0000000000
--- a/src/vsa/benchmarks.zig
+++ /dev/null
@@ -1,110 +0,0 @@
-const std = @import("std");
-const vsa = @import("../vsa.zig");
-const HybridBigInt = vsa.HybridBigInt;
-const Trit = vsa.Trit;
-const TextCorpus = vsa.TextCorpus;
-
-/// VSA Operations Benchmarks
-pub fn runBenchmarks() void {
- const iterations: u64 = 10000;
- const vec_size: usize = 256;
-
- std.debug.print("\nVSA Operations Benchmarks ({}D vectors)\n", .{vec_size});
- std.debug.print("==========================================\n\n", .{});
-
- var a = vsa.randomVector(vec_size, 111);
- var b = vsa.randomVector(vec_size, 222);
- var c = vsa.randomVector(vec_size, 333);
-
- // Bind benchmark
- const bind_start = std.time.nanoTimestamp();
- var bind_result = HybridBigInt.zero();
- var i: u64 = 0;
- while (i < iterations) : (i += 1) {
- bind_result = vsa.bind(&a, &b);
- }
- const bind_end = std.time.nanoTimestamp();
- std.mem.doNotOptimizeAway(bind_result);
- const bind_ns = @as(u64, @intCast(bind_end - bind_start));
-
- std.debug.print("Bind x {} iterations:\n", .{iterations});
- std.debug.print(" Total: {} ns ({} ns/op)\n", .{ bind_ns, bind_ns / iterations });
- std.debug.print(" Throughput: {d:.1} M trits/sec\n\n", .{
- @as(f64, @floatFromInt(iterations * vec_size)) / @as(f64, @floatFromInt(bind_ns)) * 1000.0,
- });
-
- // Bundle benchmark
- const bundle_start = std.time.nanoTimestamp();
- var bundle_result = HybridBigInt.zero();
- i = 0;
- while (i < iterations) : (i += 1) {
- bundle_result = vsa.bundle3(&a, &b, &c);
- }
- const bundle_end = std.time.nanoTimestamp();
- std.mem.doNotOptimizeAway(bundle_result);
- const bundle_ns = @as(u64, @intCast(bundle_end - bundle_start));
-
- std.debug.print("Bundle3 x {} iterations:\n", .{iterations});
- std.debug.print(" Total: {} ns ({} ns/op)\n", .{ bundle_ns, bundle_ns / iterations });
- std.debug.print(" Throughput: {d:.1} M trits/sec\n\n", .{
- @as(f64, @floatFromInt(iterations * vec_size)) / @as(f64, @floatFromInt(bundle_ns)) * 1000.0,
- });
-
- // Similarity benchmark
- const sim_start = std.time.nanoTimestamp();
- var sim_result: f64 = 0;
- i = 0;
- while (i < iterations) : (i += 1) {
- sim_result = vsa.cosineSimilarity(&a, &b);
- }
- const sim_end = std.time.nanoTimestamp();
- std.mem.doNotOptimizeAway(sim_result);
- const sim_ns = @as(u64, @intCast(sim_end - sim_start));
-
- std.debug.print("Cosine Similarity x {} iterations:\n", .{iterations});
- std.debug.print(" Total: {} ns ({} ns/op)\n", .{ sim_ns, sim_ns / iterations });
- std.debug.print(" Throughput: {d:.1} M trits/sec\n\n", .{
- @as(f64, @floatFromInt(iterations * vec_size)) / @as(f64, @floatFromInt(sim_ns)) * 1000.0,
- });
-
- // Dot product benchmark
- const dot_start = std.time.nanoTimestamp();
- var dot_result: i32 = 0;
- i = 0;
- while (i < iterations) : (i += 1) {
- dot_result = a.dotProduct(&b);
- }
- const dot_end = std.time.nanoTimestamp();
- std.mem.doNotOptimizeAway(dot_result);
- const dot_ns = @as(u64, @intCast(dot_end - dot_start));
-
- std.debug.print("Dot Product x {} iterations:\n", .{iterations});
- std.debug.print(" Total: {} ns ({} ns/op)\n", .{ dot_ns, dot_ns / iterations });
- std.debug.print(" Throughput: {d:.1} M trits/sec\n\n", .{
- @as(f64, @floatFromInt(iterations * vec_size)) / @as(f64, @floatFromInt(dot_ns)) * 1000.0,
- });
-
- // Permute benchmark
- const perm_start = std.time.nanoTimestamp();
- var perm_result = HybridBigInt.zero();
- i = 0;
- while (i < iterations) : (i += 1) {
- perm_result = vsa.permute(&a, 7);
- }
- const perm_end = std.time.nanoTimestamp();
- std.mem.doNotOptimizeAway(perm_result);
- const perm_ns = @as(u64, @intCast(perm_end - perm_start));
-
- std.debug.print("Permute x {} iterations:\n", .{iterations});
- std.debug.print(" Total: {} ns ({} ns/op)\n", .{ perm_ns, perm_ns / iterations });
- std.debug.print(" Throughput: {d:.1} M trits/sec\n\n", .{
- @as(f64, @floatFromInt(iterations * vec_size)) / @as(f64, @floatFromInt(perm_ns)) * 1000.0,
- });
-
- std.debug.print("Summary:\n", .{});
- std.debug.print(" Bind: {} ns/op\n", .{bind_ns / iterations});
- std.debug.print(" Bundle3: {} ns/op\n", .{bundle_ns / iterations});
- std.debug.print(" Similarity: {} ns/op\n", .{sim_ns / iterations});
- std.debug.print(" Dot: {} ns/op\n", .{dot_ns / iterations});
- std.debug.print(" Permute: {} ns/op\n", .{perm_ns / iterations});
-}
diff --git a/src/vsa/bsd.zig b/src/vsa/bsd.zig
deleted file mode 100644
index 3e058bda3b..0000000000
--- a/src/vsa/bsd.zig
+++ /dev/null
@@ -1,442 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BSD-VSA INTEGRATION
-// Connecting Elliptic Curve BSD Formula with Vector Symbolic Architecture
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const common = @import("common.zig");
-const core = @import("core.zig");
-const HybridBigInt = common.HybridBigInt;
-const Trit = common.Trit;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BSD-VSA HYPERVERSOR COMPONENT
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// BSD-enhanced hypervector with Sha (Π¨) as third dimension
-///
-/// Traditional VSA: [bind, bundle]
-/// BSD-VSA: [bind, bundle, sha]
-///
-/// The Sha (Shafarevich-Tate group) provides:
-/// 1. Hidden structure information
-/// 2. Arithmetic complexity measure
-/// 3. Proof-theoretic depth for zk-systems
-pub const BSDHypervector = struct {
- /// Primary symbolic vector
- primary: HybridBigInt,
-
- /// Secondary (bound) vector
- secondary: HybridBigInt,
-
- /// Sha-derived component (Π¨ order β trit pattern)
- sha_component: HybridBigInt,
-
- /// BSD metadata
- sha_order: u64 = 1,
- rank: u8 = 0,
- analytic_rank: u8 = 0,
-
- /// Create new BSD-enhanced hypervector
- pub fn init(dimension: usize) BSDHypervector {
- const primary = core.randomVector(dimension, 42);
- const secondary = core.randomVector(dimension, 43);
- return .{
- .primary = primary,
- .secondary = secondary,
- .sha_component = HybridBigInt.zero(),
- };
- }
-
- /// Create from existing vectors with Sha enhancement
- pub fn fromVectors(primary: *HybridBigInt, secondary: *HybridBigInt, sha_order: u64) BSDHypervector {
- return .{
- .primary = primary.*,
- .secondary = secondary.*,
- .sha_component = shaOrderToVector(sha_order, @max(primary.trit_len, secondary.trit_len)),
- .sha_order = sha_order,
- };
- }
-
- /// Triple-bind operation incorporating Sha
- /// Result = bind(primary, secondary) β sha_component
- pub fn tripleBind(self: *const BSDHypervector) HybridBigInt {
- var p = self.primary;
- var s = self.secondary;
- var bound = core.bind(&p, &s);
- var sha_c = self.sha_component;
- return core.bind(&bound, &sha_c);
- }
-
- /// Bundle with Sha-weighted majority vote
- /// Sha component gets β(sha_order) weight boost in the majority sum.
- /// sum[i] = primary[i] + secondary[i] + weight * sha_component[i]
- /// result[i] = sign(sum[i])
- pub fn shaWeightedBundle(self: *const BSDHypervector, other: *const BSDHypervector) HybridBigInt {
- const weight_f = std.math.sqrt(@as(f64, @floatFromInt(@max(self.sha_order, 1))));
- const weight: i16 = @intFromFloat(@max(1.0, @round(weight_f)));
-
- var p = self.primary;
- var s = self.secondary;
- var sha = other.sha_component;
- p.ensureUnpacked();
- s.ensureUnpacked();
- sha.ensureUnpacked();
-
- var result = HybridBigInt.zero();
- result.mode = .unpacked_mode;
- result.dirty = true;
-
- const len = @max(@max(p.trit_len, s.trit_len), sha.trit_len);
- result.trit_len = len;
-
- for (0..len) |i| {
- const pi: i16 = p.unpacked_cache[i];
- const si: i16 = s.unpacked_cache[i];
- const shi: i16 = sha.unpacked_cache[i];
- const sum = pi + si + weight * shi;
-
- result.unpacked_cache[i] = if (sum > 0) 1 else if (sum < 0) @as(i8, -1) else 0;
- }
-
- return result;
- }
-
- /// Compute similarity with Sha-aware adjustment
- pub fn shaSimilarity(self: *const BSDHypervector, other: *const BSDHypervector) f64 {
- const base_sim = core.cosineSimilarity(&self.primary, &other.primary);
-
- // Sha adjustment: curves with same Sha get similarity boost
- const sha_match = if (self.sha_order == other.sha_order) 1.0 else 0.0;
- const sha_factor = 0.1 * sha_match; // 10% boost for Sha match
-
- return base_sim + sha_factor;
- }
-};
-
-/// Convert Sha order to trit vector pattern
-/// Uses Ο-based encoding for mathematical elegance
-pub fn shaOrderToVector(sha_order: u64, dimension: usize) HybridBigInt {
- var result = HybridBigInt.zero();
- result.trit_len = dimension;
- result.mode = .unpacked_mode;
-
- // Ο-based encoding: each trit = sign of (sha_order * Ο^i mod 3)
- const phi: f64 = 1.618033988749895;
- const sha_f: f64 = @floatFromInt(sha_order);
-
- for (0..dimension) |i| {
- const phi_pow = std.math.pow(f64, phi, @as(f64, @floatFromInt(i)));
- const val = sha_f * phi_pow;
- const rem = @mod(val, 3.0);
-
- result.unpacked_cache[i] = if (rem < 1.0)
- -1
- else if (rem < 2.0)
- 0
- else
- 1;
- }
-
- return result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// L-FUNCTION TERNARY SEQUENCE GENERATOR
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// L-function value descriptor for sequence generation
-pub const LFunctionDescriptor = struct {
- /// Elliptic curve coefficients
- a: i64,
- b: i64,
-
- /// Conductor
- conductor: u64,
-
- /// Analytic rank (detected from L-function)
- rank: u8,
-
- /// L(E,1) value
- special_value: f64,
-};
-
-/// Generate ternary sequence from L-function values
-/// Maps L-series coefficients to balanced ternary
-pub fn generateLSequence(allocator: std.mem.Allocator, desc: LFunctionDescriptor, length: usize) ![]Trit {
- const sequence = try allocator.alloc(Trit, length);
- errdefer allocator.free(sequence);
-
- // Use Hasse-Weil L-function coefficients a_p
- // a_p = p + 1 - #E(F_p)
- // Map to ternary: a_p > 0 β +1, a_p = 0 β 0, a_p < 0 β -1
-
- var p: u64 = 2; // Start from prime 2
- var i: usize = 0;
-
- while (i < length) {
- if (isPrime(p)) {
- // Simplified a_p computation using Legendre symbol
- const ap = computeHasseWeilCoefficient(desc.a, desc.b, p);
-
- // Map to ternary with threshold
- const threshold = std.math.sqrt(@as(f64, @floatFromInt(p)));
- const ap_f: f64 = @floatFromInt(ap);
- sequence[i] = if (ap_f > threshold / 2)
- 1
- else if (ap_f < -threshold / 2)
- -1
- else
- 0;
-
- i += 1;
- }
- p += 1;
- }
-
- return sequence;
-}
-
-/// Compute Hasse-Weil coefficient a_p = p + 1 - #E(F_p)
-/// Simplified using Legendre symbol of discriminant
-fn computeHasseWeilCoefficient(a: i64, b: i64, p: u64) i64 {
- // For curve y^2 = x^3 + ax + b
- // #E(F_p) β p + 1 for most p (simplified)
- // Use Legendre symbol of discriminant for perturbation
-
- const discriminant = -4 * a * a * a - 27 * b * b;
- const leg = legendreSymbol(discriminant, @as(i64, @intCast(p)));
-
- // Small perturbation around expected value
- return leg;
-}
-
-/// Legendre symbol (a/p)
-fn legendreSymbol(a: i64, p: i64) i64 {
- const a_mod = @rem(a, p);
- if (a_mod == 0) return 0;
-
- // Euler's criterion: (a/p) β‘ a^((p-1)/2) mod p
- const exp = @divTrunc(p - 1, 2);
- const result = std.math.powi(i64, a_mod, exp) catch return 0;
- const mod_result = @rem(result, p);
-
- return if (mod_result == 1) 1 else -1;
-}
-
-/// Simple primality test
-fn isPrime(n: u64) bool {
- if (n < 2) return false;
- if (n == 2) return true;
- if (n % 2 == 0) return false;
-
- var i: u64 = 3;
- while (i * i <= n) : (i += 2) {
- if (n % i == 0) return false;
- }
- return true;
-}
-
-/// Convert L-sequence to hypervector
-pub fn lSequenceToHypervector(sequence: []const Trit) HybridBigInt {
- var result = HybridBigInt.zero();
- result.trit_len = sequence.len;
- result.mode = .unpacked_mode;
-
- @memcpy(result.unpacked_cache[0..sequence.len], sequence);
-
- return result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// RANK DETECTION FOR VSA CLASSIFICATION
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Curve classification based on analytic rank
-pub const CurveClassification = enum(u8) {
- /// Rank 0: Finite rational points
- rank_0 = 0,
-
- /// Rank 1: Infinite cyclic group
- rank_1 = 1,
-
- /// Rank 2+: Higher complexity
- rank_high = 2,
-
- /// Unknown rank
- unknown = 255,
-};
-
-/// Classify curve for VSA processing
-pub fn classifyCurve(l_descriptor: *const LFunctionDescriptor) CurveClassification {
- return switch (l_descriptor.rank) {
- 0 => .rank_0,
- 1 => .rank_1,
- else => .rank_high,
- };
-}
-
-/// Get VSA dimension based on curve rank
-/// Higher rank β higher dimension for more expressive power
-pub fn getRankBasedDimension(classification: CurveClassification) usize {
- return switch (classification) {
- .rank_0 => 512, // Minimal: finite structure
- .rank_1 => 1024, // Standard: cyclic infinite
- .rank_high => 2048, // Large: complex structure
- .unknown => 1024, // Default
- };
-}
-
-/// Rank-aware similarity computation
-/// Curves of same rank have higher baseline similarity
-pub fn rankAwareSimilarity(
- vec1: *const HybridBigInt,
- rank1: u8,
- vec2: *const HybridBigInt,
- rank2: u8,
-) f64 {
- const base_sim = core.cosineSimilarity(vec1, vec2);
-
- // Rank match bonus
- const rank_match = if (rank1 == rank2) 0.1 else 0.0;
-
- // Rank magnitude adjustment
- const rank_factor = @as(f64, @floatFromInt(@min(rank1, rank2))) / 10.0;
-
- return base_sim + rank_match + rank_factor;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ZERO-KNOWLEDGE BSD PROOF
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// BSD commitment for zk-proof systems
-/// Commits to BSD components without revealing curve structure
-pub const BSDCommitment = struct {
- /// Hashed commitment to Sha order
- sha_commitment: [32]u8,
-
- /// Hashed commitment to rank
- rank_commitment: [32]u8,
-
- /// Hashed commitment to L-value
- l_commitment: [32]u8,
-
- /// Create commitment from BSD data
- pub fn create(sha_order: u64, rank: u8, l_value: f64) BSDCommitment {
- var result: BSDCommitment = undefined;
-
- // Simple hash commitment (in production, use proper zk-SNARK)
- var sha_buf: [8]u8 = undefined;
- std.mem.writeInt(u64, &sha_buf, sha_order, .little);
- std.crypto.hash.sha2.Sha256.hash(&sha_buf, &result.sha_commitment, .{});
-
- var rank_buf: [1]u8 = .{rank};
- std.crypto.hash.sha2.Sha256.hash(&rank_buf, &result.rank_commitment, .{});
-
- var l_buf: [8]u8 = undefined;
- const l_bits = @as(u64, @bitCast(l_value));
- std.mem.writeInt(u64, &l_buf, l_bits, .little);
- std.crypto.hash.sha2.Sha256.hash(&l_buf, &result.l_commitment, .{});
-
- return result;
- }
-
- /// Verify commitment matches claimed values
- pub fn verify(self: *const BSDCommitment, sha_order: u64, rank: u8, l_value: f64) bool {
- const expected = create(sha_order, rank, l_value);
- return std.mem.eql(u8, &self.sha_commitment, &expected.sha_commitment) and
- std.mem.eql(u8, &self.rank_commitment, &expected.rank_commitment) and
- std.mem.eql(u8, &self.l_commitment, &expected.l_commitment);
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "BSDHypervector - init" {
- const hvec = BSDHypervector.init(512);
- try std.testing.expectEqual(@as(usize, 512), hvec.primary.trit_len);
- try std.testing.expectEqual(@as(usize, 512), hvec.secondary.trit_len);
-}
-
-test "shaOrderToVector - basic" {
- const vec = shaOrderToVector(1, 128);
- try std.testing.expectEqual(@as(usize, 128), vec.trit_len);
- try std.testing.expect(vec.mode == .unpacked_mode);
-}
-
-test "BSDCommitment - create and verify" {
- const commitment = BSDCommitment.create(4, 0, 0.51748);
- try std.testing.expect(commitment.verify(4, 0, 0.51748));
- try std.testing.expect(!commitment.verify(1, 0, 0.51748));
-}
-
-test "generateLSequence - curve 11a1" {
- const desc = LFunctionDescriptor{
- .a = -1,
- .b = 0,
- .conductor = 32,
- .rank = 0,
- .special_value = 0.253842,
- };
-
- const allocator = std.testing.allocator;
- const sequence = try generateLSequence(allocator, desc, 100);
- defer allocator.free(sequence);
-
- try std.testing.expectEqual(@as(usize, 100), sequence.len);
-
- // Check all values are valid trits
- for (sequence) |t| {
- try std.testing.expect(t == -1 or t == 0 or t == 1);
- }
-}
-
-test "classifyCurve - rank detection" {
- const desc0 = LFunctionDescriptor{ .a = -1, .b = 0, .conductor = 32, .rank = 0, .special_value = 0.25 };
- const desc1 = LFunctionDescriptor{ .a = -1, .b = 0, .conductor = 37, .rank = 1, .special_value = 0.0 };
- const desc2 = LFunctionDescriptor{ .a = -1, .b = 0, .conductor = 389, .rank = 2, .special_value = 0.0 };
-
- try std.testing.expectEqual(CurveClassification.rank_0, classifyCurve(&desc0));
- try std.testing.expectEqual(CurveClassification.rank_1, classifyCurve(&desc1));
- try std.testing.expectEqual(CurveClassification.rank_high, classifyCurve(&desc2));
-}
-
-test "shaWeightedBundle - weight affects result" {
- // Create two BSD hypervectors with different sha_orders
- var hvec1 = BSDHypervector.init(128);
- hvec1.sha_order = 25; // weight = round(β25) = 5
- hvec1.sha_component = shaOrderToVector(25, 128);
-
- var hvec2 = BSDHypervector.init(128);
- hvec2.sha_order = 1; // weight = round(β1) = 1
- hvec2.sha_component = shaOrderToVector(1, 128);
-
- // Weighted bundle with sha_order=25 (SHA gets 5 votes)
- const result_weighted = hvec1.shaWeightedBundle(&hvec2);
-
- // Weighted bundle with sha_order=1 (SHA gets 1 vote = same as bundle3)
- const result_unweighted = hvec2.shaWeightedBundle(&hvec1);
-
- // Both should produce valid trit vectors
- try std.testing.expectEqual(@as(usize, 128), result_weighted.trit_len);
- try std.testing.expectEqual(@as(usize, 128), result_unweighted.trit_len);
-
- // Results should differ because different weights
- var differ_count: usize = 0;
- for (0..128) |i| {
- if (result_weighted.unpacked_cache[i] != result_unweighted.unpacked_cache[i]) differ_count += 1;
- }
- // With weight=5 vs weight=1, SHA component should dominate differently
- try std.testing.expect(differ_count > 0);
-}
-
-test "getRankBasedDimension - dimension selection" {
- try std.testing.expectEqual(@as(usize, 512), getRankBasedDimension(.rank_0));
- try std.testing.expectEqual(@as(usize, 1024), getRankBasedDimension(.rank_1));
- try std.testing.expectEqual(@as(usize, 2048), getRankBasedDimension(.rank_high));
-}
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/cell.tri b/src/vsa/cell.tri
deleted file mode 100644
index 81359240d1..0000000000
--- a/src/vsa/cell.tri
+++ /dev/null
@@ -1,53 +0,0 @@
-[cell]
-id = "trinity.vsa"
-name = "vsa"
-version = "0.1.0"
-kind = "library"
-path = "src/vsa"
-min_core_version = "1.0.0"
-status = "experimental"
-description = "Vector Symbolic Architecture bind/bundle/similarity operations"
-capabilities = ["init", "initPhi", "randomVector", "seededVector", "bind"]
-files = 36
-tests = 163
-owner = "agent:ralph"
-
-[tags]
-scope = "vsa"
-type = "library"
-
-[contributes]
-commands = ["init", "initPhi", "randomVector"]
-tri_subcommands = []
-events = []
-binaries = ["photon-demo", "photon-immersive", "photon-terminal", "trinity-canvas", "bench-core", "example-memory", "example-sequence"]
-exports = ["initPhi", "randomVector", "seededVector", "bind", "unbind"]
-
-[dependencies]
-trinity.quantum = "^1.0.0"
-
-[permissions]
-level = "L2"
-filesystem = "write"
-network = "external"
-process = "spawn"
-ffi = "native"
-concurrency = "yes"
-
-[dna]
-cell_id = "trinity.vsa"
-source = "specs/vsa/core.tri"
-output = "gen/vsa_ops.zig"
-regenerable = true
-
-[contract]
-inputs = ["vectors: [][D]Trit"]
-outputs = ["result: [D]Trit", "similarity: f32"]
-invariants = ["D == 1024 or 10000", "trit in {-1, 0, +1}", "bind is invertible"]
-
-
-[biology]
-system = "body"
-[security]
-signed = true
-signature = "sha256:0ab6fc62826ad173e21b53688f4f1423591c3faa6dc854a3cee53a11c6ac377b"
diff --git a/src/vsa/core_generated.zig b/src/vsa/core_generated.zig
deleted file mode 100644
index 38856aab12..0000000000
--- a/src/vsa/core_generated.zig
+++ /dev/null
@@ -1,18 +0,0 @@
-// VSA Core β HybridBigInt Operations Selector
-// TTT Dogfood Stage 2.0: Using generated code from Tri spec
-
-const gen = @import("gen_core.zig");
-
-pub const bind = gen.bind;
-pub const unbind = gen.unbind;
-pub const bundle2 = gen.bundle2;
-pub const permute = gen.permute;
-pub const inversePermute = gen.inversePermute;
-
-// Re-export from original for functions not yet generated
-const original = @import("core.zig");
-pub const bundle3 = original.bundle3;
-pub const cosineSimilarity = original.cosineSimilarity;
-pub const cosineSimilarityF16 = original.cosineSimilarityF16;
-pub const dotProduct = original.dotProduct;
-pub const vectorNorm = original.vectorNorm;
diff --git a/src/vsa/encoding.zig b/src/vsa/encoding.zig
deleted file mode 100644
index ff8d0637d9..0000000000
--- a/src/vsa/encoding.zig
+++ /dev/null
@@ -1,33 +0,0 @@
-//! VSA Encoding Module Selector
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! This file re-exports from generated code (gen_encoding.zig)
-//! DO NOT EDIT: Modify encoding.tri spec and regenerate
-
-// Types
-pub const TritEncoding = @import("gen_encoding.zig").TritEncoding;
-pub const EncodedTrits = @import("gen_encoding.zig").EncodedTrits;
-pub const Codebook = @import("gen_encoding.zig").Codebook;
-
-// Encoding functions
-pub const encodeTrits = @import("gen_encoding.zig").encodeTrits;
-pub const decodeTrits = @import("gen_encoding.zig").decodeTrits;
-pub const encodingSize = @import("gen_encoding.zig").encodingSize;
-
-// Codebook functions
-pub const codebookBind = @import("gen_encoding.zig").codebookBind;
-pub const codebookMajority = @import("gen_encoding.zig").codebookMajority;
-pub const GLOBAL_CODEBOOK = @import("gen_encoding.zig").GLOBAL_CODEBOOK;
-
-// Text encoding functions (stubs - TODO: full implementation)
-// NOTE: Use text_encoding.zig for production implementation
-pub const charToVector = @import("gen_encoding.zig").charToVector;
-pub const encodeText = @import("gen_encoding.zig").encodeText;
-pub const decodeText = @import("gen_encoding.zig").decodeText;
-pub const encodeTextWords = @import("gen_encoding.zig").encodeTextWords;
-pub const textSimilarity = @import("gen_encoding.zig").textSimilarity;
-pub const textsAreSimilar = @import("gen_encoding.zig").textsAreSimilar;
-pub const TEXT_VECTOR_DIM = @import("gen_encoding.zig").TEXT_VECTOR_DIM;
-
-// Full text encoding implementation
-pub const text = @import("text_encoding.zig");
diff --git a/src/vsa/gen_core_abs.zig b/src/vsa/gen_core_abs.zig
deleted file mode 100644
index 5feb58bc71..0000000000
--- a/src/vsa/gen_core_abs.zig
+++ /dev/null
@@ -1,244 +0,0 @@
-// VSA Core β HybridBigInt Operations (GENERATED)
-// Using absolute imports to avoid module boundary issues
-
-const std = @import("std");
-const hybrid = @import("../vsa_hybrid/hybrid.zig");
-const HybridBigInt = hybrid.HybridBigInt;
-const Trit = hybrid.Trit;
-const Vec32i8 = hybrid.Vec32i8;
-const Vec32i16 = hybrid.Vec32i16;
-const SIMD_WIDTH = hybrid.SIMD_WIDTH;
-
-pub fn bind(a: *HybridBigInt, b: *HybridBigInt) HybridBigInt {
- a.ensureUnpacked();
- b.ensureUnpacked();
-
- var result = HybridBigInt.zero();
- result.mode = .unpacked_mode;
- result.dirty = true;
-
- const len = @max(a.trit_len, b.trit_len);
- result.trit_len = len;
-
- const min_len = @min(a.trit_len, b.trit_len);
- const num_full_chunks = min_len / SIMD_WIDTH;
-
- var i: usize = 0;
- while (i < num_full_chunks * SIMD_WIDTH) : (i += SIMD_WIDTH) {
- const a_vec: Vec32i8 = a.unpacked_cache[i..][0..SIMD_WIDTH].*;
- const b_vec: Vec32i8 = b.unpacked_cache[i..][0..SIMD_WIDTH].*;
- const prod = a_vec * b_vec;
- result.unpacked_cache[i..][0..SIMD_WIDTH].* = prod;
- }
-
- while (i < len) : (i += 1) {
- const a_trit: Trit = if (i < a.trit_len) a.unpacked_cache[i] else 0;
- const b_trit: Trit = if (i < b.trit_len) b.unpacked_cache[i] else 0;
- result.unpacked_cache[i] = a_trit * b_trit;
- }
-
- return result;
-}
-
-pub fn unbind(bound: *HybridBigInt, key: *HybridBigInt) HybridBigInt {
- return bind(bound, key);
-}
-
-pub fn bundle2(a: *HybridBigInt, b: *HybridBigInt) HybridBigInt {
- a.ensureUnpacked();
- b.ensureUnpacked();
-
- var result = HybridBigInt.zero();
- result.mode = .unpacked_mode;
- result.dirty = true;
-
- const len = @max(a.trit_len, b.trit_len);
- result.trit_len = len;
-
- const min_len = @min(a.trit_len, b.trit_len);
- const num_full_chunks = min_len / SIMD_WIDTH;
-
- var i: usize = 0;
- while (i < num_full_chunks * SIMD_WIDTH) : (i += SIMD_WIDTH) {
- const a_vec: Vec32i8 = a.unpacked_cache[i..][0..SIMD_WIDTH].*;
- const b_vec: Vec32i8 = b.unpacked_cache[i..][0..SIMD_WIDTH].*;
-
- const a_wide: Vec32i16 = a_vec;
- const b_wide: Vec32i16 = b_vec;
- const sum = a_wide + b_wide;
-
- const zeros: Vec32i16 = @splat(0);
- const ones: Vec32i16 = @splat(1);
- const neg_ones: Vec32i16 = @splat(-1);
-
- const pos_mask = sum > zeros;
- const neg_mask = sum < zeros;
-
- var out = zeros;
- out = @select(i16, pos_mask, ones, out);
- out = @select(i16, neg_mask, neg_ones, out);
-
- inline for (0..SIMD_WIDTH) |j| {
- result.unpacked_cache[i + j] = @truncate(out[j]);
- }
- }
-
- while (i < len) : (i += 1) {
- const a_trit: i16 = if (i < a.trit_len) a.unpacked_cache[i] else 0;
- const b_trit: i16 = if (i < b.trit_len) b.unpacked_cache[i] else 0;
- const sum = a_trit + b_trit;
-
- if (sum > 0) {
- result.unpacked_cache[i] = 1;
- } else if (sum < 0) {
- result.unpacked_cache[i] = -1;
- } else {
- result.unpacked_cache[i] = 0;
- }
- }
-
- return result;
-}
-
-pub fn bundle3(a: *HybridBigInt, b: *HybridBigInt, c: *HybridBigInt) HybridBigInt {
- a.ensureUnpacked();
- b.ensureUnpacked();
- c.ensureUnpacked();
-
- var result = HybridBigInt.zero();
- result.mode = .unpacked_mode;
- result.dirty = true;
-
- const len = @max(@max(a.trit_len, b.trit_len), c.trit_len);
- const min_len = @min(@min(a.trit_len, b.trit_len), c.trit_len);
- const num_full_chunks = min_len / SIMD_WIDTH;
-
- var i: usize = 0;
- while (i < num_full_chunks * SIMD_WIDTH) : (i += SIMD_WIDTH) {
- const a_vec: Vec32i8 = a.unpacked_cache[i..][0..SIMD_WIDTH].*;
- const b_vec: Vec32i8 = b.unpacked_cache[i..][0..SIMD_WIDTH].*;
- const c_vec: Vec32i8 = c.unpacked_cache[i..][0..SIMD_WIDTH].*;
-
- const a_wide: Vec32i16 = a_vec;
- const b_wide: Vec32i16 = b_vec;
- const c_wide: Vec32i16 = c_vec;
- const sum = a_wide + b_wide + c_wide;
-
- const zeros: Vec32i16 = @splat(0);
- const ones: Vec32i16 = @splat(1);
- const neg_ones: Vec32i16 = @splat(-1);
-
- const pos_mask = sum > zeros;
- const neg_mask = sum < zeros;
-
- var out = zeros;
- out = @select(i16, pos_mask, ones, out);
- out = @select(i16, neg_mask, neg_ones, out);
-
- inline for (0..SIMD_WIDTH) |j| {
- result.unpacked_cache[i + j] = @truncate(out[j]);
- }
- }
-
- while (i < len) : (i += 1) {
- const a_trit: i16 = if (i < a.trit_len) a.unpacked_cache[i] else 0;
- const b_trit: i16 = if (i < b.trit_len) b.unpacked_cache[i] else 0;
- const c_trit: i16 = if (i < c.trit_len) c.unpacked_cache[i] else 0;
- const sum = a_trit + b_trit + c_trit;
-
- if (sum > 0) {
- result.unpacked_cache[i] = 1;
- } else if (sum < 0) {
- result.unpacked_cache[i] = -1;
- } else {
- result.unpacked_cache[i] = 0;
- }
- }
-
- result.trit_len = len;
- return result;
-}
-
-pub fn permute(v: *HybridBigInt, n: usize) HybridBigInt {
- v.ensureUnpacked();
-
- var result = HybridBigInt.zero();
- result.mode = .unpacked_mode;
- result.dirty = true;
- result.trit_len = v.trit_len;
-
- const rotate = if (v.trit_len > 0) @mod(n, v.trit_len) else 0;
-
- for (0..v.trit_len) |i| {
- const src_idx = if (i >= rotate) i - rotate else i + v.trit_len - rotate;
- result.unpacked_cache[i] = v.unpacked_cache[src_idx];
- }
-
- return result;
-}
-
-pub fn inversePermute(v: *HybridBigInt, n: usize) HybridBigInt {
- v.ensureUnpacked();
-
- var result = HybridBigInt.zero();
- result.mode = .unpacked_mode;
- result.dirty = true;
- result.trit_len = v.trit_len;
-
- const rotate = if (v.trit_len > 0) @mod(n, v.trit_len) else 0;
-
- for (0..v.trit_len) |i| {
- const src_idx = (i + rotate) % v.trit_len;
- result.unpacked_cache[i] = v.unpacked_cache[src_idx];
- }
-
- return result;
-}
-
-pub fn dotProduct(a: *HybridBigInt, b: *HybridBigInt) i64 {
- a.ensureUnpacked();
- b.ensureUnpacked();
-
- var sum: i64 = 0;
- const len = @min(a.trit_len, b.trit_len);
- const num_full_chunks = len / SIMD_WIDTH;
-
- var i: usize = 0;
- while (i < num_full_chunks * SIMD_WIDTH) : (i += SIMD_WIDTH) {
- const a_vec: Vec32i8 = a.unpacked_cache[i..][0..SIMD_WIDTH].*;
- const b_vec: Vec32i8 = b.unpacked_cache[i..][0..SIMD_WIDTH].*;
- const a_wide: Vec32i16 = a_vec;
- const b_wide: Vec32i16 = b_vec;
- const prod = a_wide * b_wide;
- sum += @reduce(.Add, prod);
- }
-
- while (i < len) : (i += 1) {
- const a_trit: i64 = if (i < a.trit_len) a.unpacked_cache[i] else 0;
- const b_trit: i64 = if (i < b.trit_len) b.unpacked_cache[i] else 0;
- sum += a_trit * b_trit;
- }
-
- return sum;
-}
-
-pub fn vectorNorm(v: *HybridBigInt) f64 {
- v.ensureUnpacked();
-
- var sum: f64 = 0.0;
- for (0..v.trit_len) |i| {
- const t: f64 = @floatFromInt(v.unpacked_cache[i]);
- sum += t * t;
- }
- return @sqrt(sum);
-}
-
-pub fn cosineSimilarity(a: *const HybridBigInt, b: *const HybridBigInt) f64 {
- const dot = @constCast(a).dotProduct(@constCast(b));
- const norm_a = vectorNorm(@constCast(a));
- const norm_b = vectorNorm(@constCast(b));
-
- if (norm_a == 0 or norm_b == 0) return 0;
-
- return @as(f64, @floatFromInt(dot)) / (norm_a * norm_b);
-}
diff --git a/src/vsa/gen_core_simple.zig b/src/vsa/gen_core_simple.zig
deleted file mode 100644
index fd3c9bfed5..0000000000
--- a/src/vsa/gen_core_simple.zig
+++ /dev/null
@@ -1,29 +0,0 @@
-// VSA Core β Simple Test Operations (no HybridBigInt)
-// For testing codegen pipeline
-
-const std = @import("std");
-
-pub const Trit = i8;
-
-pub fn bindSimple(a: []const Trit, b: []const Trit) ![]Trit {
- const allocator = std.heap.page_allocator;
- const len = @max(a.len, b.len);
- var result = try allocator.alloc(Trit, len);
- for (0..len) |i| {
- const a_val = if (i < a.len) a[i] else 0;
- const b_val = if (i < b.len) b[i] else 0;
- result[i] = if (b_val == 0) a_val else b_val * a_val;
- }
- return result;
-}
-
-test "bindSimple works" {
- const a = [_]Trit{ 1, -1, 0 };
- const b = [_]Trit{ -1, 1, 0 };
-
- const result = try bindSimple(&a, &b);
- defer std.heap.page_allocator.free(result);
-
- try std.testing.expectEqual(@as(usize, 3), result.len);
- try std.testing.expectEqual(@as(Trit, -1), result[0]);
-}
diff --git a/src/vsa/photon.zig b/src/vsa/photon.zig
deleted file mode 100644
index d405fa4a3f..0000000000
--- a/src/vsa/photon.zig
+++ /dev/null
@@ -1,1220 +0,0 @@
-// =============================================================================
-// EMERGENT PHOTON AI - Wave-Based Generation Engine
-// No neural networks, no weights - pure mathematical emergence
-// V = n x 3^k x pi^m x phi^p x e^q
-// phi^2 + 1/phi^2 = 3 = TRINITY
-// =============================================================================
-
-const std = @import("std");
-const math = std.math;
-const Allocator = std.mem.Allocator;
-
-// =============================================================================
-// MATHEMATICAL CONSTANTS (Golden Ratio Foundation)
-// =============================================================================
-
-pub const PHI: f32 = 1.6180339887; // Golden ratio
-pub const PHI_INV: f32 = 0.6180339887; // 1/phi
-pub const PI: f32 = 3.14159265359;
-pub const TAU: f32 = 6.28318530718; // 2*pi
-pub const E: f32 = 2.71828182845;
-
-// Trinity identity: phi^2 + 1/phi^2 = 3
-pub const TRINITY: f32 = 3.0;
-
-// =============================================================================
-// SIMD TYPES (8-element vectors for wave computation)
-// =============================================================================
-
-pub const Vec8f = @Vector(8, f32);
-pub const SIMD_WIDTH: usize = 8;
-
-// =============================================================================
-// PHOTON - Minimal Wave Unit
-// =============================================================================
-
-pub const Photon = struct {
- // Wave state
- amplitude: f32, // Current amplitude [-1, 1]
- phase: f32, // Phase angle [0, TAU]
- frequency: f32, // Base frequency (Hz)
- wavelength: f32, // Spatial wavelength
-
- // Position in grid
- x: usize,
- y: usize,
-
- // Interference accumulator
- interference: f32,
-
- // Energy (conserved across interactions)
- energy: f32,
-
- // Color encoding (for visualization)
- hue: f32, // [0, 360]
-
- /// Create photon at grid position
- pub fn init(x: usize, y: usize) Photon {
- // Initialize with golden ratio frequency
- const freq = PHI * @as(f32, @floatFromInt(x + y + 1));
- return Photon{
- .amplitude = 0.0,
- .phase = 0.0,
- .frequency = freq,
- .wavelength = 1.0 / freq,
- .x = x,
- .y = y,
- .interference = 0.0,
- .energy = 1.0,
- .hue = @mod(@as(f32, @floatFromInt(x * 7 + y * 13)) * PHI * 100.0, 360.0),
- };
- }
-
- /// Wave function: A * sin(omega*t + phase)
- pub fn wave(self: *const Photon, t: f32) f32 {
- const omega = TAU * self.frequency;
- return self.amplitude * @sin(omega * t + self.phase);
- }
-
- /// Propagate wave one timestep
- pub fn propagate(self: *Photon, dt: f32, neighbors: []const f32) void {
- // Sum neighbor contributions (interference)
- var neighbor_sum: f32 = 0.0;
- for (neighbors) |n| {
- neighbor_sum += n;
- }
-
- // Average neighbor influence
- const neighbor_avg = if (neighbors.len > 0)
- neighbor_sum / @as(f32, @floatFromInt(neighbors.len))
- else
- 0.0;
-
- // Wave equation: d2u/dt2 = c^2 * laplacian(u)
- // Discretized: new_amp = 2*amp - old_amp + c^2*dt^2*(neighbor_avg - amp)
- const c: f32 = PHI; // Wave speed = golden ratio
- const damping: f32 = 0.96; // Strong energy decay for stability
-
- self.interference = neighbor_avg - self.amplitude;
- const new_amp = damping * (self.amplitude + c * c * dt * dt * self.interference);
- // Clamp amplitude for stability
- self.amplitude = @max(-1.0, @min(1.0, new_amp));
-
- // Update phase
- self.phase = @mod(self.phase + TAU * self.frequency * dt, TAU);
-
- // Clamp amplitude
- self.amplitude = @max(-1.0, @min(1.0, self.amplitude));
- }
-
- /// Apply external perturbation (cursor/input)
- pub fn perturb(self: *Photon, strength: f32, phase_shift: f32) void {
- self.amplitude += strength;
- self.amplitude = @max(-1.0, @min(1.0, self.amplitude));
- self.phase = @mod(self.phase + phase_shift, TAU);
- }
-
- /// Interference with another photon
- pub fn interfere(self: *Photon, other: *const Photon, t: f32) f32 {
- const wave1 = self.wave(t);
- const wave2 = other.wave(t);
- // Superposition principle
- return wave1 + wave2;
- }
-
- /// Energy from wave (proportional to amplitude^2)
- pub fn getEnergy(self: *const Photon) f32 {
- return self.amplitude * self.amplitude;
- }
-
- /// Convert amplitude to grayscale [0, 255]
- pub fn toGrayscale(self: *const Photon) u8 {
- const normalized = (self.amplitude + 1.0) * 0.5; // [0, 1]
- return @intFromFloat(normalized * 255.0);
- }
-
- /// Convert to RGB using hue
- pub fn toRGB(self: *const Photon) [3]u8 {
- const brightness = (self.amplitude + 1.0) * 0.5;
- return hsvToRgb(self.hue, 0.8, brightness);
- }
-};
-
-// =============================================================================
-// PHOTON GRID - Emergent Wave Field
-// =============================================================================
-
-pub const PhotonGrid = struct {
- allocator: Allocator,
- width: usize,
- height: usize,
- photons: []Photon,
- time: f32,
- dt: f32,
-
- // Statistics
- total_energy: f32,
- max_amplitude: f32,
- min_amplitude: f32,
-
- // Cursor position for interaction
- cursor_x: f32,
- cursor_y: f32,
- cursor_strength: f32,
-
- /// Create N x N photon grid
- pub fn init(allocator: Allocator, width: usize, height: usize) !PhotonGrid {
- const photons = try allocator.alloc(Photon, width * height);
-
- // Initialize all photons
- for (0..height) |y| {
- for (0..width) |x| {
- photons[y * width + x] = Photon.init(x, y);
- }
- }
-
- return PhotonGrid{
- .allocator = allocator,
- .width = width,
- .height = height,
- .photons = photons,
- .time = 0.0,
- .dt = 0.01, // 100 Hz simulation
- .total_energy = 0.0,
- .max_amplitude = 0.0,
- .min_amplitude = 0.0,
- .cursor_x = 0.0,
- .cursor_y = 0.0,
- .cursor_strength = 0.0,
- };
- }
-
- pub fn deinit(self: *PhotonGrid) void {
- self.allocator.free(self.photons);
- }
-
- /// Get photon at (x, y)
- pub fn get(self: *const PhotonGrid, x: usize, y: usize) *const Photon {
- return &self.photons[y * self.width + x];
- }
-
- /// Get mutable photon at (x, y)
- pub fn getMut(self: *PhotonGrid, x: usize, y: usize) *Photon {
- return &self.photons[y * self.width + x];
- }
-
- /// Get neighbor amplitudes (4-connected)
- fn getNeighborAmplitudes(self: *const PhotonGrid, x: usize, y: usize, out: *[4]f32) usize {
- var count: usize = 0;
-
- // Left
- if (x > 0) {
- out[count] = self.get(x - 1, y).amplitude;
- count += 1;
- }
- // Right
- if (x < self.width - 1) {
- out[count] = self.get(x + 1, y).amplitude;
- count += 1;
- }
- // Up
- if (y > 0) {
- out[count] = self.get(x, y - 1).amplitude;
- count += 1;
- }
- // Down
- if (y < self.height - 1) {
- out[count] = self.get(x, y + 1).amplitude;
- count += 1;
- }
-
- return count;
- }
-
- /// Propagate all photons one timestep
- pub fn step(self: *PhotonGrid) void {
- // Apply cursor perturbation
- if (self.cursor_strength > 0.01) {
- self.applyCursorPerturbation();
- }
-
- // Propagate each photon
- for (0..self.height) |y| {
- for (0..self.width) |x| {
- var neighbors: [4]f32 = undefined;
- const count = self.getNeighborAmplitudes(x, y, &neighbors);
- self.getMut(x, y).propagate(self.dt, neighbors[0..count]);
- }
- }
-
- // Update time
- self.time += self.dt;
-
- // Update statistics
- self.updateStats();
- }
-
- /// SIMD-optimized step (process 8 photons at once)
- pub fn stepSIMD(self: *PhotonGrid) void {
- // Apply cursor perturbation first
- if (self.cursor_strength > 0.01) {
- self.applyCursorPerturbation();
- }
-
- const c2dt2: f32 = PHI * PHI * self.dt * self.dt;
- const damping: f32 = 0.96; // Strong decay for stability
-
- // Process in SIMD chunks
- var i: usize = 0;
- while (i + SIMD_WIDTH <= self.photons.len) : (i += SIMD_WIDTH) {
- // Load amplitudes into SIMD vector
- var amps: Vec8f = undefined;
- var interf: Vec8f = undefined;
-
- for (0..SIMD_WIDTH) |j| {
- const idx = i + j;
- const x = idx % self.width;
- const y = idx / self.width;
-
- var neighbors: [4]f32 = undefined;
- const count = self.getNeighborAmplitudes(x, y, &neighbors);
-
- var sum: f32 = 0.0;
- for (0..count) |k| {
- sum += neighbors[k];
- }
- const avg = if (count > 0) sum / @as(f32, @floatFromInt(count)) else 0.0;
-
- amps[j] = self.photons[idx].amplitude;
- interf[j] = avg - self.photons[idx].amplitude;
- }
-
- // SIMD wave equation
- const c2dt2_vec: Vec8f = @splat(c2dt2);
- const damping_vec: Vec8f = @splat(damping);
- const new_amps = damping_vec * (amps + c2dt2_vec * interf);
-
- // Clamp to [-1, 1]
- const min_vec: Vec8f = @splat(-1.0);
- const max_vec: Vec8f = @splat(1.0);
- const clamped = @min(max_vec, @max(min_vec, new_amps));
-
- // Store back
- for (0..SIMD_WIDTH) |j| {
- self.photons[i + j].amplitude = clamped[j];
- self.photons[i + j].interference = interf[j];
-
- // Update phase
- const omega_dt = TAU * self.photons[i + j].frequency * self.dt;
- self.photons[i + j].phase = @mod(self.photons[i + j].phase + omega_dt, TAU);
- }
- }
-
- // Handle remaining photons
- while (i < self.photons.len) : (i += 1) {
- const x = i % self.width;
- const y = i / self.width;
- var neighbors: [4]f32 = undefined;
- const count = self.getNeighborAmplitudes(x, y, &neighbors);
- self.photons[i].propagate(self.dt, neighbors[0..count]);
- }
-
- self.time += self.dt;
- self.updateStats();
- }
-
- /// Apply cursor perturbation with Gaussian falloff
- fn applyCursorPerturbation(self: *PhotonGrid) void {
- const radius: f32 = 5.0; // Perturbation radius
- const radius_sq = radius * radius;
-
- for (0..self.height) |y| {
- for (0..self.width) |x| {
- const dx = @as(f32, @floatFromInt(x)) - self.cursor_x;
- const dy = @as(f32, @floatFromInt(y)) - self.cursor_y;
- const dist_sq = dx * dx + dy * dy;
-
- if (dist_sq < radius_sq) {
- // Gaussian falloff
- const falloff = @exp(-dist_sq / (2.0 * radius_sq / 9.0));
- const strength = self.cursor_strength * falloff;
-
- // Phase shift based on angle
- const angle = math.atan2(dy, dx);
- self.getMut(x, y).perturb(strength, angle * 0.1);
- }
- }
- }
-
- // Decay cursor strength
- self.cursor_strength *= 0.95;
- }
-
- /// Set cursor position and trigger perturbation
- pub fn setCursor(self: *PhotonGrid, x: f32, y: f32, strength: f32) void {
- self.cursor_x = x;
- self.cursor_y = y;
- self.cursor_strength = strength;
- }
-
- /// Update statistics
- fn updateStats(self: *PhotonGrid) void {
- self.total_energy = 0.0;
- self.max_amplitude = -1.0;
- self.min_amplitude = 1.0;
-
- for (self.photons) |*p| {
- self.total_energy += p.getEnergy();
- if (p.amplitude > self.max_amplitude) self.max_amplitude = p.amplitude;
- if (p.amplitude < self.min_amplitude) self.min_amplitude = p.amplitude;
- }
- }
-
- /// Inject initial wave pattern
- pub fn injectWave(self: *PhotonGrid, pattern: WavePattern) void {
- switch (pattern) {
- .point_source => |params| {
- // Single point source (circular wave)
- const px = params.x;
- const py = params.y;
- self.getMut(px, py).amplitude = params.amplitude;
- },
- .line_wave => |params| {
- // Horizontal or vertical line
- if (params.horizontal) {
- for (0..self.width) |x| {
- self.getMut(x, params.position).amplitude = params.amplitude;
- }
- } else {
- for (0..self.height) |y| {
- self.getMut(params.position, y).amplitude = params.amplitude;
- }
- }
- },
- .circle => |params| {
- // Circular wavefront
- const cx = @as(f32, @floatFromInt(params.center_x));
- const cy = @as(f32, @floatFromInt(params.center_y));
- const r = @as(f32, @floatFromInt(params.radius));
-
- for (0..self.height) |y| {
- for (0..self.width) |x| {
- const dx = @as(f32, @floatFromInt(x)) - cx;
- const dy = @as(f32, @floatFromInt(y)) - cy;
- const dist = @sqrt(dx * dx + dy * dy);
-
- if (@abs(dist - r) < 1.5) {
- self.getMut(x, y).amplitude = params.amplitude;
- }
- }
- }
- },
- .golden_spiral => |params| {
- // Golden spiral (phi-based)
- const cx = @as(f32, @floatFromInt(params.center_x));
- const cy = @as(f32, @floatFromInt(params.center_y));
-
- var theta: f32 = 0.0;
- while (theta < TAU * 4.0) : (theta += 0.1) {
- const r = params.scale * @exp(PHI_INV * theta);
- const px = cx + r * @cos(theta);
- const py = cy + r * @sin(theta);
-
- const ix = @as(usize, @intFromFloat(@max(0.0, @min(px, @as(f32, @floatFromInt(self.width - 1))))));
- const iy = @as(usize, @intFromFloat(@max(0.0, @min(py, @as(f32, @floatFromInt(self.height - 1))))));
-
- self.getMut(ix, iy).amplitude = params.amplitude;
- }
- },
- .text_seed => |params| {
- // Text as initial perturbation
- self.injectText(params.text, params.x, params.y);
- },
- }
- }
-
- /// Inject text as wave seed (each char = frequency modulation)
- fn injectText(self: *PhotonGrid, text: []const u8, start_x: usize, start_y: usize) void {
- for (text, 0..) |c, i| {
- const x = (start_x + i) % self.width;
- const y = start_y % self.height;
-
- // Character value modulates amplitude and frequency
- const char_val = @as(f32, @floatFromInt(c)) / 255.0;
- self.getMut(x, y).amplitude = char_val * 2.0 - 1.0; // [-1, 1]
- self.getMut(x, y).frequency = PHI * (1.0 + char_val);
- }
- }
-
- /// Extract emergent pattern as bytes (for text generation)
- pub fn extractPattern(self: *const PhotonGrid, out: []u8) void {
- if (out.len == 0) return;
- const sample_rate = self.photons.len / out.len;
-
- for (out, 0..) |*byte, i| {
- var sum: f32 = 0.0;
- const start = i * sample_rate;
- const end = @min(start + sample_rate, self.photons.len);
-
- for (start..end) |j| {
- sum += self.photons[j].amplitude;
- }
-
- const count = end - start;
- const avg = if (count > 0) sum / @as(f32, @floatFromInt(count)) else 0.0;
- byte.* = @intFromFloat((avg + 1.0) * 0.5 * 255.0);
- }
- }
-
- /// Get pixel buffer for rendering (grayscale)
- pub fn getPixelBuffer(self: *const PhotonGrid, out: []u8) void {
- for (self.photons, 0..) |p, i| {
- if (i < out.len) {
- out[i] = p.toGrayscale();
- }
- }
- }
-
- /// Get RGB pixel buffer
- pub fn getRGBBuffer(self: *const PhotonGrid, out: []u8) void {
- for (self.photons, 0..) |p, i| {
- const rgb = p.toRGB();
- const base = i * 3;
- if (base + 2 < out.len) {
- out[base] = rgb[0];
- out[base + 1] = rgb[1];
- out[base + 2] = rgb[2];
- }
- }
- }
-};
-
-// =============================================================================
-// WAVE PATTERNS (Initial conditions)
-// =============================================================================
-
-pub const WavePattern = union(enum) {
- point_source: struct {
- x: usize,
- y: usize,
- amplitude: f32,
- },
- line_wave: struct {
- position: usize,
- horizontal: bool,
- amplitude: f32,
- },
- circle: struct {
- center_x: usize,
- center_y: usize,
- radius: usize,
- amplitude: f32,
- },
- golden_spiral: struct {
- center_x: usize,
- center_y: usize,
- scale: f32,
- amplitude: f32,
- },
- text_seed: struct {
- text: []const u8,
- x: usize,
- y: usize,
- },
-};
-
-// =============================================================================
-// EMERGENT TEXT GENERATOR
-// =============================================================================
-
-pub const EmergentTextGenerator = struct {
- grid: *PhotonGrid,
- vocabulary: []const u8,
- temperature: f32,
-
- pub fn init(grid: *PhotonGrid) EmergentTextGenerator {
- return EmergentTextGenerator{
- .grid = grid,
- .vocabulary = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,!?",
- .temperature = 1.0,
- };
- }
-
- /// Generate text from emergent wave patterns
- pub fn generate(self: *EmergentTextGenerator, prompt: []const u8, max_tokens: usize, out: []u8) usize {
- // Seed grid with prompt
- self.grid.injectWave(.{ .text_seed = .{
- .text = prompt,
- .x = self.grid.width / 4,
- .y = self.grid.height / 2,
- } });
-
- // Let waves propagate and interfere
- var tokens_generated: usize = 0;
- const steps_per_token = 10;
-
- while (tokens_generated < max_tokens and tokens_generated < out.len) {
- // Propagate waves
- for (0..steps_per_token) |_| {
- self.grid.stepSIMD();
- }
-
- // Sample token from emergent pattern
- const token = self.sampleToken();
- out[tokens_generated] = token;
- tokens_generated += 1;
-
- // Inject generated token back as perturbation (autoregressive)
- const inject_x = (self.grid.width / 4 + tokens_generated) % self.grid.width;
- self.grid.getMut(inject_x, self.grid.height / 2).amplitude = @as(f32, @floatFromInt(token)) / 127.5 - 1.0;
- }
-
- return tokens_generated;
- }
-
- /// Sample token from grid state
- fn sampleToken(self: *EmergentTextGenerator) u8 {
- // Use center region for sampling
- const cx = self.grid.width / 2;
- const cy = self.grid.height / 2;
- const sample_size: usize = 5;
-
- var sum: f32 = 0.0;
- var count: usize = 0;
-
- for (0..sample_size) |dy| {
- for (0..sample_size) |dx| {
- const x = @min(cx + dx, self.grid.width - 1);
- const y = @min(cy + dy, self.grid.height - 1);
- sum += self.grid.get(x, y).amplitude;
- count += 1;
- }
- }
-
- const avg = sum / @as(f32, @floatFromInt(count));
-
- // Map to vocabulary
- const normalized = (avg + 1.0) * 0.5; // [0, 1]
- const idx = @as(usize, @intFromFloat(normalized * @as(f32, @floatFromInt(self.vocabulary.len - 1))));
- return self.vocabulary[@min(idx, self.vocabulary.len - 1)];
- }
-};
-
-// =============================================================================
-// UTILITY FUNCTIONS
-// =============================================================================
-
-/// HSV to RGB conversion
-fn hsvToRgb(h: f32, s: f32, v: f32) [3]u8 {
- const c = v * s;
- const x = c * (1.0 - @abs(@mod(h / 60.0, 2.0) - 1.0));
- const m = v - c;
-
- var r: f32 = 0;
- var g: f32 = 0;
- var b: f32 = 0;
-
- if (h < 60) {
- r = c;
- g = x;
- } else if (h < 120) {
- r = x;
- g = c;
- } else if (h < 180) {
- g = c;
- b = x;
- } else if (h < 240) {
- g = x;
- b = c;
- } else if (h < 300) {
- r = x;
- b = c;
- } else {
- r = c;
- b = x;
- }
-
- return .{
- @intFromFloat((r + m) * 255.0),
- @intFromFloat((g + m) * 255.0),
- @intFromFloat((b + m) * 255.0),
- };
-}
-
-// =============================================================================
-// MULTI-MODAL OUTPUT - Text, Image, Audio
-// =============================================================================
-
-/// Enhanced text generator with context-aware sampling
-pub const AdvancedTextGenerator = struct {
- grid: *PhotonGrid,
- context_window: [64]u8,
- context_len: usize,
- temperature: f32,
- top_k: usize,
-
- // Character frequencies for English (approximate)
- const CHAR_WEIGHTS = " etaoinshrdlcumwfgypbvkjxqz";
-
- pub fn init(grid: *PhotonGrid) AdvancedTextGenerator {
- return AdvancedTextGenerator{
- .grid = grid,
- .context_window = undefined,
- .context_len = 0,
- .temperature = 0.8,
- .top_k = 5,
- };
- }
-
- /// Generate text with wave-based sampling
- pub fn generate(self: *AdvancedTextGenerator, prompt: []const u8, max_tokens: usize, out: []u8) usize {
- // Initialize context with prompt
- const copy_len = @min(prompt.len, self.context_window.len);
- @memcpy(self.context_window[0..copy_len], prompt[0..copy_len]);
- self.context_len = copy_len;
-
- // Seed grid with prompt
- self.grid.injectWave(.{ .text_seed = .{
- .text = prompt,
- .x = self.grid.width / 4,
- .y = self.grid.height / 2,
- } });
-
- var tokens_generated: usize = 0;
- const steps_per_token = 15; // More steps for better emergence
-
- while (tokens_generated < max_tokens and tokens_generated < out.len) {
- // Propagate waves with SIMD
- for (0..steps_per_token) |_| {
- self.grid.stepSIMD();
- }
-
- // Sample token using advanced method
- const token = self.sampleAdvanced();
- out[tokens_generated] = token;
- tokens_generated += 1;
-
- // Update context
- if (self.context_len < self.context_window.len) {
- self.context_window[self.context_len] = token;
- self.context_len += 1;
- } else {
- // Shift context window
- for (1..self.context_window.len) |i| {
- self.context_window[i - 1] = self.context_window[i];
- }
- self.context_window[self.context_window.len - 1] = token;
- }
-
- // Inject token back as wave perturbation
- const inject_x = (self.grid.width / 3 + tokens_generated * 2) % self.grid.width;
- const inject_y = (self.grid.height / 2 + tokens_generated) % self.grid.height;
- self.grid.getMut(inject_x, inject_y).amplitude = @as(f32, @floatFromInt(token)) / 127.5 - 1.0;
- }
-
- return tokens_generated;
- }
-
- /// Advanced sampling using multiple grid regions
- fn sampleAdvanced(self: *AdvancedTextGenerator) u8 {
- // Sample from 4 regions and combine
- var samples: [4]f32 = undefined;
-
- // Top-left quadrant
- samples[0] = self.sampleRegion(0, 0, self.grid.width / 2, self.grid.height / 2);
- // Top-right quadrant
- samples[1] = self.sampleRegion(self.grid.width / 2, 0, self.grid.width, self.grid.height / 2);
- // Bottom-left quadrant
- samples[2] = self.sampleRegion(0, self.grid.height / 2, self.grid.width / 2, self.grid.height);
- // Bottom-right quadrant
- samples[3] = self.sampleRegion(self.grid.width / 2, self.grid.height / 2, self.grid.width, self.grid.height);
-
- // Weighted combination
- const weighted = (samples[0] * PHI + samples[1] + samples[2] + samples[3] * PHI_INV) / (PHI + 2.0 + PHI_INV);
-
- // Apply temperature
- const temp_adjusted = weighted * self.temperature;
-
- // Map to character with English frequency bias
- const normalized = (temp_adjusted + 1.0) * 0.5; // [0, 1]
- const idx = @as(usize, @intFromFloat(normalized * @as(f32, @floatFromInt(CHAR_WEIGHTS.len - 1))));
- return CHAR_WEIGHTS[@min(idx, CHAR_WEIGHTS.len - 1)];
- }
-
- /// Sample average amplitude from grid region
- fn sampleRegion(self: *AdvancedTextGenerator, x1: usize, y1: usize, x2: usize, y2: usize) f32 {
- var sum: f32 = 0.0;
- var count: usize = 0;
-
- var y = y1;
- while (y < y2) : (y += 2) { // Sample every other cell for speed
- var x = x1;
- while (x < x2) : (x += 2) {
- sum += self.grid.get(x, y).amplitude;
- count += 1;
- }
- }
-
- return if (count > 0) sum / @as(f32, @floatFromInt(count)) else 0.0;
- }
-};
-
-/// Image exporter - save grid state as image data
-pub const ImageExporter = struct {
- grid: *const PhotonGrid,
-
- pub fn init(grid: *const PhotonGrid) ImageExporter {
- return ImageExporter{ .grid = grid };
- }
-
- /// Get RGBA pixel buffer (4 bytes per pixel)
- pub fn getRGBA(self: *const ImageExporter, allocator: std.mem.Allocator) ![]u8 {
- const pixels = try allocator.alloc(u8, self.grid.width * self.grid.height * 4);
-
- for (0..self.grid.height) |y| {
- for (0..self.grid.width) |x| {
- const p = self.grid.get(x, y);
- const rgb = p.toRGB();
- const idx = (y * self.grid.width + x) * 4;
-
- pixels[idx] = rgb[0]; // R
- pixels[idx + 1] = rgb[1]; // G
- pixels[idx + 2] = rgb[2]; // B
- pixels[idx + 3] = 255; // A (fully opaque)
- }
- }
-
- return pixels;
- }
-
- /// Get grayscale buffer (1 byte per pixel)
- pub fn getGrayscale(self: *const ImageExporter, allocator: std.mem.Allocator) ![]u8 {
- const pixels = try allocator.alloc(u8, self.grid.width * self.grid.height);
-
- for (0..self.grid.height) |y| {
- for (0..self.grid.width) |x| {
- const p = self.grid.get(x, y);
- pixels[y * self.grid.width + x] = p.toGrayscale();
- }
- }
-
- return pixels;
- }
-
- /// Export as PPM format (simple, no external libs)
- pub fn exportPPM(self: *const ImageExporter, allocator: std.mem.Allocator) ![]u8 {
- // PPM header: "P6\nWIDTH HEIGHT\n255\n" + RGB data
- const header_size = 64; // Estimated
- const data_size = self.grid.width * self.grid.height * 3;
- var buffer = try allocator.alloc(u8, header_size + data_size);
-
- // Write header
- const header = std.fmt.bufPrint(buffer[0..header_size], "P6\n{d} {d}\n255\n", .{ self.grid.width, self.grid.height }) catch return error.FormatError;
- const header_len = header.len;
-
- // Write RGB data
- var offset = header_len;
- for (0..self.grid.height) |y| {
- for (0..self.grid.width) |x| {
- const p = self.grid.get(x, y);
- const rgb = p.toRGB();
- buffer[offset] = rgb[0];
- buffer[offset + 1] = rgb[1];
- buffer[offset + 2] = rgb[2];
- offset += 3;
- }
- }
-
- // Resize to actual size
- return allocator.realloc(buffer, offset) catch buffer[0..offset];
- }
-};
-
-/// Audio synthesizer - generate waveform from grid state
-pub const AudioSynthesizer = struct {
- grid: *const PhotonGrid,
- sample_rate: u32,
- base_frequency: f32,
-
- pub fn init(grid: *const PhotonGrid) AudioSynthesizer {
- return AudioSynthesizer{
- .grid = grid,
- .sample_rate = 44100, // CD quality
- .base_frequency = 440.0, // A4 note
- };
- }
-
- /// Generate audio samples from grid state
- /// Returns f32 samples in range [-1, 1]
- pub fn generateSamples(self: *const AudioSynthesizer, allocator: std.mem.Allocator, duration_ms: u32) ![]f32 {
- const num_samples = (self.sample_rate * duration_ms) / 1000;
- const samples = try allocator.alloc(f32, num_samples);
-
- // Use grid columns as frequency components
- const dt = 1.0 / @as(f32, @floatFromInt(self.sample_rate));
-
- for (samples, 0..) |*sample, i| {
- const t = @as(f32, @floatFromInt(i)) * dt;
- var sum: f32 = 0.0;
-
- // Sum contributions from grid photons
- // Use first row as fundamental frequencies
- for (0..@min(32, self.grid.width)) |col| {
- const p = self.grid.get(col, 0);
-
- // Frequency based on column position and amplitude
- const freq = self.base_frequency * (1.0 + @as(f32, @floatFromInt(col)) * 0.1);
- const amp = @abs(p.amplitude) * 0.1; // Scale down
-
- sum += amp * @sin(TAU * freq * t + p.phase);
- }
-
- // Add harmonics from center row
- const center_y = self.grid.height / 2;
- for (0..@min(16, self.grid.width)) |col| {
- const p = self.grid.get(col, center_y);
- const harmonic = 2.0 + @as(f32, @floatFromInt(col)) * 0.5;
- const freq = self.base_frequency * harmonic;
- const amp = @abs(p.amplitude) * 0.05;
-
- sum += amp * @sin(TAU * freq * t + p.phase);
- }
-
- // Clamp to [-1, 1]
- sample.* = @max(-1.0, @min(1.0, sum));
- }
-
- return samples;
- }
-
- /// Generate raw 16-bit PCM audio data
- pub fn generatePCM16(self: *const AudioSynthesizer, allocator: std.mem.Allocator, duration_ms: u32) ![]i16 {
- const float_samples = try self.generateSamples(allocator, duration_ms);
- defer allocator.free(float_samples);
-
- const pcm = try allocator.alloc(i16, float_samples.len);
-
- for (float_samples, 0..) |sample, i| {
- // Convert float [-1, 1] to i16 [-32768, 32767]
- pcm[i] = @intFromFloat(sample * 32767.0);
- }
-
- return pcm;
- }
-
- /// Get frequency spectrum from current grid state
- pub fn getSpectrum(self: *const AudioSynthesizer, out: []f32) void {
- const bins = @min(out.len, self.grid.width);
-
- for (0..bins) |i| {
- // Average amplitude across column
- var sum: f32 = 0.0;
- for (0..self.grid.height) |y| {
- sum += @abs(self.grid.get(i, y).amplitude);
- }
- out[i] = sum / @as(f32, @floatFromInt(self.grid.height));
- }
- }
-};
-
-/// WAV file header structure
-pub const WavHeader = struct {
- // RIFF chunk
- riff: [4]u8 = .{ 'R', 'I', 'F', 'F' },
- file_size: u32,
- wave: [4]u8 = .{ 'W', 'A', 'V', 'E' },
- // fmt chunk
- fmt: [4]u8 = .{ 'f', 'm', 't', ' ' },
- fmt_size: u32 = 16,
- audio_format: u16 = 1, // PCM
- num_channels: u16 = 1, // Mono
- sample_rate: u32,
- byte_rate: u32,
- block_align: u16 = 2,
- bits_per_sample: u16 = 16,
- // data chunk
- data: [4]u8 = .{ 'd', 'a', 't', 'a' },
- data_size: u32,
-
- pub fn init(sample_rate: u32, num_samples: u32) WavHeader {
- const data_size = num_samples * 2; // 16-bit = 2 bytes per sample
- return WavHeader{
- .file_size = 36 + data_size,
- .sample_rate = sample_rate,
- .byte_rate = sample_rate * 2,
- .data_size = data_size,
- };
- }
-
- pub fn toBytes(self: *const WavHeader) [44]u8 {
- var bytes: [44]u8 = undefined;
- @memcpy(bytes[0..4], &self.riff);
- @memcpy(bytes[4..8], std.mem.asBytes(&self.file_size));
- @memcpy(bytes[8..12], &self.wave);
- @memcpy(bytes[12..16], &self.fmt);
- @memcpy(bytes[16..20], std.mem.asBytes(&self.fmt_size));
- @memcpy(bytes[20..22], std.mem.asBytes(&self.audio_format));
- @memcpy(bytes[22..24], std.mem.asBytes(&self.num_channels));
- @memcpy(bytes[24..28], std.mem.asBytes(&self.sample_rate));
- @memcpy(bytes[28..32], std.mem.asBytes(&self.byte_rate));
- @memcpy(bytes[32..34], std.mem.asBytes(&self.block_align));
- @memcpy(bytes[34..36], std.mem.asBytes(&self.bits_per_sample));
- @memcpy(bytes[36..40], &self.data);
- @memcpy(bytes[40..44], std.mem.asBytes(&self.data_size));
- return bytes;
- }
-};
-
-// =============================================================================
-// TESTS
-// =============================================================================
-
-test "photon wave function" {
- var p = Photon.init(0, 0);
- p.amplitude = 1.0;
- p.frequency = 1.0;
- p.phase = 0.0;
-
- // At t=0, sin(0) = 0
- const w0 = p.wave(0.0);
- try std.testing.expectApproxEqAbs(@as(f32, 0.0), w0, 0.01);
-
- // At t=0.25 (quarter period), sin(pi/2) = 1
- const w1 = p.wave(0.25);
- try std.testing.expectApproxEqAbs(@as(f32, 1.0), w1, 0.01);
-}
-
-test "photon grid initialization" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 16, 16);
- defer grid.deinit();
-
- try std.testing.expectEqual(@as(usize, 256), grid.photons.len);
- try std.testing.expectEqual(@as(usize, 16), grid.width);
- try std.testing.expectEqual(@as(usize, 16), grid.height);
-}
-
-test "wave injection and propagation" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 32, 32);
- defer grid.deinit();
-
- // Inject point source at center
- grid.injectWave(.{ .point_source = .{
- .x = 16,
- .y = 16,
- .amplitude = 1.0,
- } });
-
- // Check injection
- try std.testing.expectApproxEqAbs(@as(f32, 1.0), grid.get(16, 16).amplitude, 0.01);
-
- // Propagate
- for (0..100) |_| {
- grid.stepSIMD();
- }
-
- // Wave should have spread (neighbors should have non-zero amplitude)
- try std.testing.expect(grid.get(15, 16).amplitude != 0.0);
- try std.testing.expect(grid.get(17, 16).amplitude != 0.0);
-}
-
-test "cursor perturbation" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 32, 32);
- defer grid.deinit();
-
- // Set cursor at center with strong perturbation
- grid.setCursor(16.0, 16.0, 1.0);
-
- // Step to apply perturbation
- grid.step();
-
- // Check that photons near cursor were affected
- const center = grid.get(16, 16);
- try std.testing.expect(center.amplitude != 0.0);
-}
-
-test "emergent text generation" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 64, 64);
- defer grid.deinit();
-
- var gen = EmergentTextGenerator.init(&grid);
-
- var output: [32]u8 = undefined;
- const len = gen.generate("Hello", 10, &output);
-
- // Should generate some text
- try std.testing.expect(len > 0);
- try std.testing.expect(len <= 10);
-}
-
-test "golden spiral pattern" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 64, 64);
- defer grid.deinit();
-
- grid.injectWave(.{ .golden_spiral = .{
- .center_x = 32,
- .center_y = 32,
- .scale = 1.0,
- .amplitude = 1.0,
- } });
-
- // Check that spiral was injected (some photons should be non-zero)
- var non_zero: usize = 0;
- for (grid.photons) |p| {
- if (p.amplitude != 0.0) non_zero += 1;
- }
- try std.testing.expect(non_zero > 0);
-}
-
-test "SIMD step correctness" {
- const allocator = std.testing.allocator;
-
- // Create two identical grids
- var grid1 = try PhotonGrid.init(allocator, 32, 32);
- defer grid1.deinit();
-
- var grid2 = try PhotonGrid.init(allocator, 32, 32);
- defer grid2.deinit();
-
- // Same initial condition
- grid1.getMut(16, 16).amplitude = 1.0;
- grid2.getMut(16, 16).amplitude = 1.0;
-
- // Step with different methods
- for (0..10) |_| {
- grid1.step();
- grid2.stepSIMD();
- }
-
- // Results should be approximately equal
- for (grid1.photons, grid2.photons) |p1, p2| {
- try std.testing.expectApproxEqAbs(p1.amplitude, p2.amplitude, 0.01);
- }
-}
-
-test "advanced text generator" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 64, 64);
- defer grid.deinit();
-
- var gen = AdvancedTextGenerator.init(&grid);
-
- var output: [32]u8 = undefined;
- const len = gen.generate("WAVE", 16, &output);
-
- // Should generate text
- try std.testing.expect(len > 0);
- try std.testing.expect(len <= 16);
-
- // Output should be printable ASCII
- for (output[0..len]) |c| {
- try std.testing.expect(c >= 32 and c <= 126);
- }
-}
-
-test "image exporter RGBA" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 16, 16);
- defer grid.deinit();
-
- // Set some amplitudes
- grid.getMut(8, 8).amplitude = 1.0;
- grid.getMut(4, 4).amplitude = -1.0;
-
- const exporter = ImageExporter.init(&grid);
- const rgba = try exporter.getRGBA(allocator);
- defer allocator.free(rgba);
-
- // Should be width * height * 4 bytes
- try std.testing.expectEqual(@as(usize, 16 * 16 * 4), rgba.len);
-
- // Alpha channel should be 255 for all pixels
- for (0..256) |i| {
- try std.testing.expectEqual(@as(u8, 255), rgba[i * 4 + 3]);
- }
-}
-
-test "image exporter PPM" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 8, 8);
- defer grid.deinit();
-
- const exporter = ImageExporter.init(&grid);
- const ppm = try exporter.exportPPM(allocator);
- defer allocator.free(ppm);
-
- // Should start with "P6\n"
- try std.testing.expectEqualStrings("P6\n", ppm[0..3]);
-}
-
-test "audio synthesizer samples" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 32, 32);
- defer grid.deinit();
-
- // Set wave pattern
- grid.getMut(0, 0).amplitude = 1.0;
- grid.getMut(1, 0).amplitude = 0.5;
-
- const synth = AudioSynthesizer.init(&grid);
- const samples = try synth.generateSamples(allocator, 100); // 100ms
- defer allocator.free(samples);
-
- // Should have correct number of samples (44100 * 0.1 = 4410)
- try std.testing.expectEqual(@as(usize, 4410), samples.len);
-
- // All samples should be in range [-1, 1]
- for (samples) |s| {
- try std.testing.expect(s >= -1.0 and s <= 1.0);
- }
-}
-
-test "audio synthesizer PCM16" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 32, 32);
- defer grid.deinit();
-
- const synth = AudioSynthesizer.init(&grid);
- const pcm = try synth.generatePCM16(allocator, 50); // 50ms
- defer allocator.free(pcm);
-
- // Should have samples
- try std.testing.expect(pcm.len > 0);
-
- // All samples should be in valid i16 range
- for (pcm) |s| {
- try std.testing.expect(s >= -32768 and s <= 32767);
- }
-}
-
-test "WAV header" {
- const header = WavHeader.init(44100, 44100); // 1 second
- const bytes = header.toBytes();
-
- // Check RIFF header
- try std.testing.expectEqualStrings("RIFF", bytes[0..4]);
- try std.testing.expectEqualStrings("WAVE", bytes[8..12]);
- try std.testing.expectEqualStrings("fmt ", bytes[12..16]);
- try std.testing.expectEqualStrings("data", bytes[36..40]);
-}
-
-test "spectrum analysis" {
- const allocator = std.testing.allocator;
- var grid = try PhotonGrid.init(allocator, 64, 64);
- defer grid.deinit();
-
- // Create some wave activity
- grid.getMut(0, 32).amplitude = 1.0;
- grid.getMut(32, 32).amplitude = 0.5;
-
- const synth = AudioSynthesizer.init(&grid);
- var spectrum: [64]f32 = undefined;
- synth.getSpectrum(&spectrum);
-
- // First bin should have higher value
- try std.testing.expect(spectrum[0] > 0.0);
-}
diff --git a/src/vsa/photon_demo.zig b/src/vsa/photon_demo.zig
deleted file mode 100644
index 9614b10431..0000000000
--- a/src/vsa/photon_demo.zig
+++ /dev/null
@@ -1,500 +0,0 @@
-// =============================================================================
-// EMERGENT PHOTON AI DEMO v0.2 - Multi-Modal Interactive Visualization
-// Real-time emergent wave generation with Text, Image, Audio output
-// phi^2 + 1/phi^2 = 3 = TRINITY
-// =============================================================================
-
-const std = @import("std");
-const photon = @import("photon.zig");
-const rl = @cImport({
- @cInclude("raylib.h");
-});
-
-// =============================================================================
-// CONFIGURATION
-// =============================================================================
-
-const GRID_SIZE: usize = 128; // 128x128 photon grid
-var g_screen_width: c_int = 1512; // Updated at runtime
-var g_screen_height: c_int = 982; // Updated at runtime
-const PIXEL_SIZE: c_int = 6; // Each photon = 6x6 pixels
-
-// Font state (Montserrat)
-var g_font: rl.Font = undefined;
-var g_font_loaded: bool = false;
-
-// Colors (Trinity theme)
-const BG_COLOR = rl.Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
-const ACCENT_COLOR = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = 0xFF };
-const GOLDEN_COLOR = rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 0xFF };
-const TEXT_COLOR = rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
-const MUTED_COLOR = rl.Color{ .r = 0xAA, .g = 0xAA, .b = 0xAA, .a = 0xFF };
-
-// =============================================================================
-// DEMO STATE
-// =============================================================================
-
-const DemoMode = enum {
- point_source,
- line_wave,
- golden_spiral,
- text_emergence,
- free_draw,
-};
-
-// =============================================================================
-// MAIN
-// =============================================================================
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- // Initialize photon grid
- var grid = try photon.PhotonGrid.init(allocator, GRID_SIZE, GRID_SIZE);
- defer grid.deinit();
-
- // State
- var mode: DemoMode = .point_source;
- var paused = false;
- var show_stats = true;
- var generated_text: [256]u8 = undefined;
- var text_len: usize = 0;
-
- // Status message for feedback
- var status_msg: [64]u8 = undefined;
- var status_len: usize = 0;
- var status_timer: f32 = 0;
-
- // Audio state
- var audio_playing = false;
- var spectrum: [64]f32 = undefined;
- @memset(&spectrum, 0);
-
- // Get native monitor resolution for fullscreen
- const monitor = rl.GetCurrentMonitor();
- const monitor_width = rl.GetMonitorWidth(monitor);
- const monitor_height = rl.GetMonitorHeight(monitor);
-
- // Raylib init - borderless fullscreen for native quality
- rl.SetConfigFlags(rl.FLAG_BORDERLESS_WINDOWED_MODE | rl.FLAG_VSYNC_HINT | rl.FLAG_MSAA_4X_HINT);
- rl.InitWindow(monitor_width, monitor_height, "EMERGENT PHOTON AI v0.2 | Multi-Modal | TRINITY");
- defer rl.CloseWindow();
-
- // Store screen dimensions in globals
- g_screen_width = monitor_width;
- g_screen_height = monitor_height;
-
- // Init audio device
- rl.InitAudioDevice();
- defer rl.CloseAudioDevice();
-
- // Load San Francisco font at high resolution for crisp rendering
- const font_paths = [_][*:0]const u8{
- "assets/fonts/SFPro.ttf", // Apple San Francisco - BEST
- "assets/fonts/Montserrat.ttf", // Montserrat fallback
- "assets/fonts/Roboto-Regular.ttf", // Roboto fallback
- };
- for (font_paths) |path| {
- const font = rl.LoadFontEx(path, 96, null, 0);
- if (font.texture.id != 0) {
- g_font = font;
- g_font_loaded = true;
- rl.SetTextureFilter(font.texture, rl.TEXTURE_FILTER_TRILINEAR);
- break;
- }
- }
- defer if (g_font_loaded) rl.UnloadFont(g_font);
-
- rl.SetTargetFPS(60);
-
- // Main loop
- while (!rl.WindowShouldClose()) {
- const dt = rl.GetFrameTime();
-
- // Handle input
- handleInput(allocator, &grid, &mode, &paused, &show_stats, &generated_text, &text_len, &status_msg, &status_len, &status_timer, &audio_playing, &spectrum);
-
- // Physics step (if not paused)
- if (!paused) {
- grid.stepSIMD();
- }
-
- // Update status timer
- if (status_timer > 0) {
- status_timer -= dt;
- }
-
- // Cursor interaction
- if (rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT)) {
- const mx = @as(f32, @floatFromInt(rl.GetMouseX())) / @as(f32, @floatFromInt(PIXEL_SIZE));
- const my = @as(f32, @floatFromInt(rl.GetMouseY() - 60)) / @as(f32, @floatFromInt(PIXEL_SIZE));
-
- if (my > 0 and mx < @as(f32, @floatFromInt(GRID_SIZE)) and my < @as(f32, @floatFromInt(GRID_SIZE))) {
- grid.setCursor(mx, my, 0.8);
- }
- }
-
- // Update spectrum
- const synth = photon.AudioSynthesizer.init(&grid);
- synth.getSpectrum(&spectrum);
-
- // Draw
- rl.BeginDrawing();
- defer rl.EndDrawing();
-
- rl.ClearBackground(BG_COLOR);
-
- // Draw header
- drawHeader(mode, paused, audio_playing);
-
- // Draw photon grid
- drawGrid(&grid);
-
- // Draw stats panel
- if (show_stats) {
- drawStats(&grid, &spectrum);
- }
-
- // Draw generated text
- if (text_len > 0) {
- drawGeneratedText(&generated_text, text_len);
- }
-
- // Draw status message
- if (status_timer > 0 and status_len > 0) {
- const alpha: u8 = @intFromFloat(@min(255.0, status_timer * 255.0));
- const status_color = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = alpha };
- var status_buf: [65]u8 = undefined;
- @memcpy(status_buf[0..status_len], status_msg[0..status_len]);
- status_buf[status_len] = 0;
- drawText(@ptrCast(&status_buf), 800, 140, 16, status_color);
- }
-
- // Draw help
- drawHelp();
- }
-}
-
-fn handleInput(
- allocator: std.mem.Allocator,
- grid: *photon.PhotonGrid,
- mode: *DemoMode,
- paused: *bool,
- show_stats: *bool,
- generated_text: *[256]u8,
- text_len: *usize,
- status_msg: *[64]u8,
- status_len: *usize,
- status_timer: *f32,
- audio_playing: *bool,
- spectrum: *[64]f32,
-) void {
- _ = spectrum;
- _ = audio_playing;
-
- // Mode switching
- if (rl.IsKeyPressed(rl.KEY_ONE)) {
- mode.* = .point_source;
- resetGrid(grid);
- }
- if (rl.IsKeyPressed(rl.KEY_TWO)) {
- mode.* = .line_wave;
- resetGrid(grid);
- grid.injectWave(.{ .line_wave = .{
- .position = GRID_SIZE / 2,
- .horizontal = true,
- .amplitude = 1.0,
- } });
- }
- if (rl.IsKeyPressed(rl.KEY_THREE)) {
- mode.* = .golden_spiral;
- resetGrid(grid);
- grid.injectWave(.{ .golden_spiral = .{
- .center_x = GRID_SIZE / 2,
- .center_y = GRID_SIZE / 2,
- .scale = 2.0,
- .amplitude = 1.0,
- } });
- }
- if (rl.IsKeyPressed(rl.KEY_FOUR)) {
- mode.* = .text_emergence;
- resetGrid(grid);
- grid.injectWave(.{ .text_seed = .{
- .text = "TRINITY",
- .x = GRID_SIZE / 4,
- .y = GRID_SIZE / 2,
- } });
- }
- if (rl.IsKeyPressed(rl.KEY_FIVE)) {
- mode.* = .free_draw;
- resetGrid(grid);
- }
-
- // Controls
- if (rl.IsKeyPressed(rl.KEY_SPACE)) paused.* = !paused.*;
- if (rl.IsKeyPressed(rl.KEY_S)) show_stats.* = !show_stats.*;
- if (rl.IsKeyPressed(rl.KEY_R)) resetGrid(grid);
-
- // [G] Generate basic text
- if (rl.IsKeyPressed(rl.KEY_G)) {
- var gen = photon.EmergentTextGenerator.init(grid);
- text_len.* = gen.generate("WAVE", 32, generated_text);
- setStatus(status_msg, status_len, status_timer, "Text generated!");
- }
-
- // [T] Generate advanced text
- if (rl.IsKeyPressed(rl.KEY_T)) {
- var adv_gen = photon.AdvancedTextGenerator.init(grid);
- text_len.* = adv_gen.generate("PHOTON", 48, generated_text);
- setStatus(status_msg, status_len, status_timer, "Advanced text generated!");
- }
-
- // [I] Export image (PPM format)
- if (rl.IsKeyPressed(rl.KEY_I)) {
- const exporter = photon.ImageExporter.init(grid);
- if (exporter.exportPPM(allocator)) |ppm_data| {
- // Save to file
- const timestamp = @as(u64, @intCast(std.time.timestamp()));
- var filename: [64]u8 = undefined;
- const fname = std.fmt.bufPrintZ(&filename, "photon_{d}.ppm", .{timestamp}) catch "photon.ppm";
-
- if (std.fs.cwd().createFile(fname, .{})) |file| {
- file.writeAll(ppm_data) catch {};
- file.close();
- setStatus(status_msg, status_len, status_timer, "Image saved!");
- } else |_| {
- setStatus(status_msg, status_len, status_timer, "Image save failed!");
- }
- allocator.free(ppm_data);
- } else |_| {
- setStatus(status_msg, status_len, status_timer, "Export failed!");
- }
- }
-
- // [A] Generate and play audio (save WAV file)
- if (rl.IsKeyPressed(rl.KEY_A)) {
- const synth = photon.AudioSynthesizer.init(grid);
- if (synth.generatePCM16(allocator, 1000)) |pcm_data| { // 1 second
- defer allocator.free(pcm_data);
-
- // Create WAV file
- const timestamp = @as(u64, @intCast(std.time.timestamp()));
- var filename: [64]u8 = undefined;
- const fname = std.fmt.bufPrintZ(&filename, "photon_{d}.wav", .{timestamp}) catch "photon.wav";
-
- if (std.fs.cwd().createFile(fname, .{})) |file| {
- // Write WAV header
- const header = photon.WavHeader.init(44100, @intCast(pcm_data.len));
- const header_bytes = header.toBytes();
- file.writeAll(&header_bytes) catch {};
-
- // Write PCM data
- const pcm_bytes = std.mem.sliceAsBytes(pcm_data);
- file.writeAll(pcm_bytes) catch {};
- file.close();
-
- setStatus(status_msg, status_len, status_timer, "Audio saved as WAV!");
- } else |_| {
- setStatus(status_msg, status_len, status_timer, "Audio save failed!");
- }
- } else |_| {
- setStatus(status_msg, status_len, status_timer, "Audio gen failed!");
- }
- }
-
- // Inject point on click
- if (rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_RIGHT)) {
- const mx = @as(usize, @intCast(@divTrunc(@max(0, rl.GetMouseX()), PIXEL_SIZE)));
- const my = @as(usize, @intCast(@divTrunc(@max(0, rl.GetMouseY() - 60), PIXEL_SIZE)));
-
- if (mx < GRID_SIZE and my < GRID_SIZE) {
- grid.injectWave(.{ .point_source = .{
- .x = mx,
- .y = my,
- .amplitude = 1.0,
- } });
- }
- }
-}
-
-fn setStatus(msg: *[64]u8, len: *usize, timer: *f32, text: []const u8) void {
- const copy_len = @min(text.len, 64);
- @memcpy(msg[0..copy_len], text[0..copy_len]);
- len.* = copy_len;
- timer.* = 2.0; // Show for 2 seconds
-}
-
-fn resetGrid(grid: *photon.PhotonGrid) void {
- for (grid.photons) |*p| {
- p.amplitude = 0.0;
- p.interference = 0.0;
- }
- grid.time = 0.0;
-}
-
-/// Draw text with San Francisco font (high quality)
-fn drawText(text: [*:0]const u8, x: c_int, y: c_int, size: c_int, color: rl.Color) void {
- if (g_font_loaded) {
- const font_size: f32 = @floatFromInt(size);
- const spacing: f32 = font_size * 0.05; // SF Pro spacing
- rl.DrawTextEx(g_font, text, .{ .x = @floatFromInt(x), .y = @floatFromInt(y) }, font_size, spacing, color);
- } else {
- rl.DrawText(text, x, y, size, color); // Fallback to default font
- }
-}
-
-fn drawHeader(mode: DemoMode, paused: bool, audio_playing: bool) void {
- _ = audio_playing;
-
- // Title bar
- rl.DrawRectangle(0, 0, g_screen_width, 50, rl.Color{ .r = 0x05, .g = 0x05, .b = 0x05, .a = 0xFF });
-
- drawText("EMERGENT PHOTON AI v0.2", 16, 14, 24, ACCENT_COLOR);
-
- // Mode indicator
- const mode_str: [*:0]const u8 = switch (mode) {
- .point_source => "Point Source [1]",
- .line_wave => "Line Wave [2]",
- .golden_spiral => "Golden Spiral [3]",
- .text_emergence => "Text Emergence [4]",
- .free_draw => "Free Draw [5]",
- };
- drawText(mode_str, 320, 18, 18, GOLDEN_COLOR);
-
- // Paused indicator
- if (paused) {
- drawText("PAUSED", 550, 18, 18, rl.Color{ .r = 0xFF, .g = 0x5F, .b = 0x57, .a = 0xFF });
- }
-
- // Multi-modal badge
- drawText("MULTI-MODAL", 650, 18, 14, rl.Color{ .r = 0x8B, .g = 0x5C, .b = 0xF6, .a = 0xFF });
-
- // Trinity formula
- drawText("phi^2 + 1/phi^2 = 3", g_screen_width - 200, 18, 16, rl.Color{ .r = 0x88, .g = 0x88, .b = 0x88, .a = 0xFF });
-}
-
-fn drawGrid(grid: *photon.PhotonGrid) void {
- const y_offset: c_int = 60;
-
- for (0..grid.height) |y| {
- for (0..grid.width) |x| {
- const p = grid.get(x, y);
- const rgb = p.toRGB();
-
- const px: c_int = @intCast(x * PIXEL_SIZE);
- const py: c_int = @intCast(y * PIXEL_SIZE + @as(usize, @intCast(y_offset)));
-
- const color = rl.Color{
- .r = rgb[0],
- .g = rgb[1],
- .b = rgb[2],
- .a = 255,
- };
-
- rl.DrawRectangle(px, py, PIXEL_SIZE - 1, PIXEL_SIZE - 1, color);
- }
- }
-}
-
-fn drawStats(grid: *photon.PhotonGrid, spectrum: *const [64]f32) void {
- const x: c_int = 800;
- var y: c_int = 200;
- const line_h: c_int = 20;
-
- drawText("STATISTICS", x, y, 18, ACCENT_COLOR);
- y += line_h + 5;
-
- var buf: [64]u8 = undefined;
-
- // Time
- const time_str = std.fmt.bufPrintZ(&buf, "Time: {d:.2}s", .{grid.time}) catch "?";
- drawText(time_str, x, y, 14, TEXT_COLOR);
- y += line_h;
-
- // Energy
- const energy_str = std.fmt.bufPrintZ(&buf, "Energy: {d:.4}", .{grid.total_energy}) catch "?";
- drawText(energy_str, x, y, 14, TEXT_COLOR);
- y += line_h;
-
- // Amplitude range
- const amp_str = std.fmt.bufPrintZ(&buf, "Amp: [{d:.2}, {d:.2}]", .{ grid.min_amplitude, grid.max_amplitude }) catch "?";
- drawText(amp_str, x, y, 14, TEXT_COLOR);
- y += line_h;
-
- // Grid size
- const size_str = std.fmt.bufPrintZ(&buf, "Grid: {d}x{d}", .{ grid.width, grid.height }) catch "?";
- drawText(size_str, x, y, 14, TEXT_COLOR);
- y += line_h;
-
- // Photons
- const photon_str = std.fmt.bufPrintZ(&buf, "Photons: {d}", .{grid.photons.len}) catch "?";
- drawText(photon_str, x, y, 14, TEXT_COLOR);
- y += line_h + 10;
-
- // Spectrum visualization
- drawText("SPECTRUM", x, y, 14, ACCENT_COLOR);
- y += 18;
-
- const bar_width: c_int = 3;
- const max_height: c_int = 40;
-
- for (0..@min(64, spectrum.len)) |i| {
- const bar_x = x + @as(c_int, @intCast(i)) * (bar_width + 1);
- const bar_h: c_int = @intFromFloat(spectrum[i] * @as(f32, @floatFromInt(max_height)));
- const clamped_h = @max(1, @min(max_height, bar_h));
-
- // Color based on height
- const intensity: u8 = @intFromFloat(@min(255.0, spectrum[i] * 500.0));
- const bar_color = rl.Color{ .r = 0x00, .g = intensity, .b = 0x88, .a = 0xFF };
-
- rl.DrawRectangle(bar_x, y + max_height - clamped_h, bar_width, clamped_h, bar_color);
- }
-}
-
-fn drawGeneratedText(generated_text: *const [256]u8, text_len: usize) void {
- drawText("GENERATED TEXT:", 800, 80, 14, ACCENT_COLOR);
-
- var text_buf: [257]u8 = undefined;
- @memcpy(text_buf[0..text_len], generated_text[0..text_len]);
- text_buf[text_len] = 0;
- drawText(@ptrCast(&text_buf), 800, 100, 16, GOLDEN_COLOR);
-}
-
-fn drawHelp() void {
- const x: c_int = 800;
- var y: c_int = 430;
- const line_h: c_int = 16;
-
- drawText("CONTROLS", x, y, 16, ACCENT_COLOR);
- y += line_h + 5;
-
- drawText("[1-5] Mode", x, y, 12, MUTED_COLOR);
- y += line_h;
- drawText("[SPACE] Pause", x, y, 12, MUTED_COLOR);
- y += line_h;
- drawText("[R] Reset", x, y, 12, MUTED_COLOR);
- y += line_h;
- drawText("[S] Stats", x, y, 12, MUTED_COLOR);
- y += line_h + 5;
-
- drawText("MULTI-MODAL OUTPUT:", x, y, 14, rl.Color{ .r = 0x8B, .g = 0x5C, .b = 0xF6, .a = 0xFF });
- y += line_h + 2;
-
- drawText("[G] Text (basic)", x, y, 12, MUTED_COLOR);
- y += line_h;
- drawText("[T] Text (advanced)", x, y, 12, MUTED_COLOR);
- y += line_h;
- drawText("[I] Image (PPM)", x, y, 12, MUTED_COLOR);
- y += line_h;
- drawText("[A] Audio (WAV)", x, y, 12, MUTED_COLOR);
- y += line_h + 5;
-
- drawText("[LMB] Perturb", x, y, 12, MUTED_COLOR);
- y += line_h;
- drawText("[RMB] Point Source", x, y, 12, MUTED_COLOR);
-
- // Footer
- drawText("", x, g_screen_height - 30, 12, rl.Color{ .r = 0x44, .g = 0x44, .b = 0x44, .a = 0xFF });
-}
diff --git a/src/vsa/photon_immersive.zig b/src/vsa/photon_immersive.zig
deleted file mode 100644
index 5979ddf9f2..0000000000
--- a/src/vsa/photon_immersive.zig
+++ /dev/null
@@ -1,676 +0,0 @@
-// =============================================================================
-// EMERGENT PHOTON AI v0.3 - IMMERSIVE COSMIC CANVAS
-// No UI panels. No buttons. No text. Pure emergent wave intelligence.
-// The entire screen IS the AI. Information emerges from interference.
-// phi^2 + 1/phi^2 = 3 = TRINITY
-// =============================================================================
-
-const std = @import("std");
-const photon = @import("photon.zig");
-const math = std.math;
-const rl = @cImport({
- @cInclude("raylib.h");
-});
-
-// =============================================================================
-// COSMIC CONSTANTS
-// =============================================================================
-
-const PHI: f32 = 1.6180339887;
-const PHI_INV: f32 = 0.6180339887;
-const TAU: f32 = 6.28318530718;
-
-// Grid fills ENTIRE screen
-var g_width: c_int = 1512;
-var g_height: c_int = 982;
-var g_pixel_size: c_int = 4; // Smaller pixels = higher resolution
-
-// =============================================================================
-// COSMIC COLORS (Neon on void)
-// =============================================================================
-
-const VOID_BLACK = rl.Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
-const NEON_CYAN = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0xFF, .a = 0xFF };
-const NEON_MAGENTA = rl.Color{ .r = 0xFF, .g = 0x00, .b = 0xFF, .a = 0xFF };
-const NEON_GREEN = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = 0xFF };
-const NEON_GOLD = rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 0xFF };
-const NEON_PURPLE = rl.Color{ .r = 0x8B, .g = 0x5C, .b = 0xF6, .a = 0xFF };
-
-// =============================================================================
-// PARTICLE SYSTEM (Orbiting stats, trails)
-// =============================================================================
-
-const MAX_PARTICLES = 512;
-
-const Particle = struct {
- x: f32,
- y: f32,
- vx: f32,
- vy: f32,
- life: f32, // 0-1, decays over time
- hue: f32, // Color
- size: f32,
- orbit_center_x: f32,
- orbit_center_y: f32,
- orbit_radius: f32,
- orbit_speed: f32,
- orbit_angle: f32,
- is_orbiting: bool,
-
- pub fn update(self: *Particle, dt: f32) void {
- if (self.is_orbiting) {
- // Orbital motion
- self.orbit_angle += self.orbit_speed * dt;
- self.x = self.orbit_center_x + self.orbit_radius * @cos(self.orbit_angle);
- self.y = self.orbit_center_y + self.orbit_radius * @sin(self.orbit_angle);
- } else {
- // Free motion with decay
- self.x += self.vx * dt;
- self.y += self.vy * dt;
- self.vx *= 0.98;
- self.vy *= 0.98;
- }
- self.life -= dt * 0.3; // Slow decay
- }
-
- pub fn isAlive(self: *const Particle) bool {
- return self.life > 0;
- }
-};
-
-const ParticleSystem = struct {
- particles: [MAX_PARTICLES]Particle,
- count: usize,
-
- pub fn init() ParticleSystem {
- var sys = ParticleSystem{
- .particles = undefined,
- .count = 0,
- };
- for (&sys.particles) |*p| {
- p.life = 0;
- }
- return sys;
- }
-
- pub fn spawn(self: *ParticleSystem, x: f32, y: f32, hue: f32) void {
- if (self.count >= MAX_PARTICLES) {
- // Find dead particle to reuse
- for (&self.particles) |*p| {
- if (!p.isAlive()) {
- p.* = createParticle(x, y, hue);
- return;
- }
- }
- return;
- }
-
- self.particles[self.count] = createParticle(x, y, hue);
- self.count += 1;
- }
-
- pub fn spawnOrbiting(self: *ParticleSystem, cx: f32, cy: f32, radius: f32, speed: f32, hue: f32) void {
- if (self.count >= MAX_PARTICLES) return;
-
- var p = createParticle(cx + radius, cy, hue);
- p.is_orbiting = true;
- p.orbit_center_x = cx;
- p.orbit_center_y = cy;
- p.orbit_radius = radius;
- p.orbit_speed = speed;
- p.orbit_angle = 0;
- p.life = 10.0; // Long life for orbiting particles
-
- self.particles[self.count] = p;
- self.count += 1;
- }
-
- pub fn update(self: *ParticleSystem, dt: f32) void {
- for (&self.particles) |*p| {
- if (p.isAlive()) {
- p.update(dt);
- }
- }
- }
-
- pub fn draw(self: *const ParticleSystem) void {
- for (&self.particles) |*p| {
- if (p.isAlive()) {
- const alpha: u8 = @intFromFloat(@min(255.0, p.life * 255.0));
- const rgb = hsvToRgb(p.hue, 1.0, 1.0);
- const color = rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = alpha };
-
- const px: c_int = @intFromFloat(p.x);
- const py: c_int = @intFromFloat(p.y);
- const size: c_int = @intFromFloat(p.size * p.life);
-
- // Glow effect
- rl.DrawCircle(px, py, @floatFromInt(size + 2), rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = @divTrunc(alpha, 4) });
- rl.DrawCircle(px, py, @floatFromInt(size), color);
- }
- }
- }
-
- fn createParticle(x: f32, y: f32, hue: f32) Particle {
- const angle = @as(f32, @floatFromInt(std.crypto.random.int(u32) % 360)) * TAU / 360.0;
- const speed = 20.0 + @as(f32, @floatFromInt(std.crypto.random.int(u32) % 50));
-
- return Particle{
- .x = x,
- .y = y,
- .vx = @cos(angle) * speed,
- .vy = @sin(angle) * speed,
- .life = 1.0,
- .hue = hue,
- .size = 3.0 + @as(f32, @floatFromInt(std.crypto.random.int(u32) % 5)),
- .orbit_center_x = 0,
- .orbit_center_y = 0,
- .orbit_radius = 0,
- .orbit_speed = 0,
- .orbit_angle = 0,
- .is_orbiting = false,
- };
- }
-};
-
-// =============================================================================
-// TRAIL SYSTEM (Cursor trails, wave paths)
-// =============================================================================
-
-const MAX_TRAIL_POINTS = 256;
-
-const TrailPoint = struct {
- x: f32,
- y: f32,
- life: f32,
- hue: f32,
-};
-
-const Trail = struct {
- points: [MAX_TRAIL_POINTS]TrailPoint,
- head: usize,
- count: usize,
-
- pub fn init() Trail {
- return Trail{
- .points = undefined,
- .head = 0,
- .count = 0,
- };
- }
-
- pub fn add(self: *Trail, x: f32, y: f32, hue: f32) void {
- self.points[self.head] = TrailPoint{
- .x = x,
- .y = y,
- .life = 1.0,
- .hue = hue,
- };
- self.head = (self.head + 1) % MAX_TRAIL_POINTS;
- if (self.count < MAX_TRAIL_POINTS) self.count += 1;
- }
-
- pub fn update(self: *Trail, dt: f32) void {
- for (&self.points) |*p| {
- if (p.life > 0) {
- p.life -= dt * 2.0;
- }
- }
- }
-
- pub fn draw(self: *const Trail) void {
- for (&self.points) |*p| {
- if (p.life > 0) {
- const alpha: u8 = @intFromFloat(p.life * 200.0);
- const rgb = hsvToRgb(p.hue, 0.8, 1.0);
-
- const px: c_int = @intFromFloat(p.x);
- const py: c_int = @intFromFloat(p.y);
-
- // Glow
- rl.DrawCircle(px, py, 8, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = @divTrunc(alpha, 4) });
- rl.DrawCircle(px, py, 4, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = alpha });
- }
- }
- }
-};
-
-// =============================================================================
-// EMERGENT TEXT (Standing wave patterns)
-// =============================================================================
-
-const EmergentGlyph = struct {
- x: f32,
- y: f32,
- char: u8,
- amplitude: f32,
- phase: f32,
- life: f32,
-};
-
-const MAX_GLYPHS = 128;
-
-const EmergentText = struct {
- glyphs: [MAX_GLYPHS]EmergentGlyph,
- count: usize,
-
- pub fn init() EmergentText {
- return EmergentText{
- .glyphs = undefined,
- .count = 0,
- };
- }
-
- pub fn spawnText(self: *EmergentText, text: []const u8, cx: f32, cy: f32) void {
- const spacing: f32 = 30.0;
- const start_x = cx - @as(f32, @floatFromInt(text.len)) * spacing / 2.0;
-
- for (text, 0..) |c, i| {
- if (self.count >= MAX_GLYPHS) break;
-
- self.glyphs[self.count] = EmergentGlyph{
- .x = start_x + @as(f32, @floatFromInt(i)) * spacing,
- .y = cy,
- .char = c,
- .amplitude = 0.0,
- .phase = @as(f32, @floatFromInt(i)) * PHI,
- .life = 5.0,
- };
- self.count += 1;
- }
- }
-
- pub fn update(self: *EmergentText, dt: f32, time: f32) void {
- var i: usize = 0;
- while (i < self.count) {
- var g = &self.glyphs[i];
-
- // Fade in
- if (g.amplitude < 1.0) {
- g.amplitude += dt * 2.0;
- }
-
- // Update phase
- g.phase += dt * TAU * 0.5;
-
- // Wave motion
- g.y += @sin(time * 2.0 + g.phase) * 0.5;
-
- // Decay
- g.life -= dt * 0.2;
-
- if (g.life <= 0) {
- // Remove glyph
- self.glyphs[i] = self.glyphs[self.count - 1];
- self.count -= 1;
- } else {
- i += 1;
- }
- }
- }
-
- pub fn draw(self: *const EmergentText, time: f32) void {
- for (self.glyphs[0..self.count]) |g| {
- const alpha: u8 = @intFromFloat(@min(255.0, g.life * 100.0 * g.amplitude));
-
- // Oscillating color
- const hue = @mod(time * 50.0 + g.phase * 30.0, 360.0);
- const rgb = hsvToRgb(hue, 0.7, 1.0);
-
- const px: c_int = @intFromFloat(g.x);
- const py: c_int = @intFromFloat(g.y);
-
- // Glow
- const glow_size: c_int = @intFromFloat(20.0 * g.amplitude);
- rl.DrawCircle(px, py, @floatFromInt(glow_size), rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = @divTrunc(alpha, 6) });
-
- // Character as simple shape (wave node)
- const wave_offset = @sin(time * 3.0 + g.phase) * 5.0 * g.amplitude;
- const final_y: c_int = @intFromFloat(g.y + wave_offset);
-
- // Draw character representation as concentric rings
- const rings: usize = 3;
- for (0..rings) |r| {
- const radius = @as(f32, @floatFromInt(r + 1)) * 4.0 * g.amplitude;
- const ring_alpha: u8 = @intFromFloat(@as(f32, @floatFromInt(alpha)) * (1.0 - @as(f32, @floatFromInt(r)) / @as(f32, @floatFromInt(rings))));
- rl.DrawCircleLines(px, final_y, radius, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = ring_alpha });
- }
- }
- }
-};
-
-// =============================================================================
-// MAIN - IMMERSIVE EXPERIENCE
-// =============================================================================
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- // Raylib init FIRST - BORDERLESS WINDOWED for NATIVE resolution (no upscaling!)
- rl.SetConfigFlags(rl.FLAG_BORDERLESS_WINDOWED_MODE | rl.FLAG_VSYNC_HINT | rl.FLAG_MSAA_4X_HINT);
- rl.InitWindow(0, 0, "EMERGENT PHOTON AI v0.3 | IMMERSIVE COSMIC CANVAS");
- defer rl.CloseWindow();
-
- // Get native screen resolution AFTER window init
- g_width = rl.GetScreenWidth();
- g_height = rl.GetScreenHeight();
-
- // Calculate grid size to fill screen
- const grid_w: usize = @intCast(@divTrunc(g_width, g_pixel_size));
- const grid_h: usize = @intCast(@divTrunc(g_height, g_pixel_size));
-
- // Initialize photon grid to fill entire screen
- var grid = try photon.PhotonGrid.init(allocator, grid_w, grid_h);
- defer grid.deinit();
-
- // Particle system
- var particles = ParticleSystem.init();
-
- // Cursor trail
- var cursor_trail = Trail.init();
-
- // Emergent text
- var emergent_text = EmergentText.init();
-
- // State
- var time: f32 = 0;
- var cursor_hue: f32 = 120; // Start with green
-
- // Create orbiting stat particles
- const cx = @as(f32, @floatFromInt(g_width)) / 2.0;
- const cy = @as(f32, @floatFromInt(g_height)) / 2.0;
-
- particles.spawnOrbiting(cx, cy, 100.0, 1.0, 0); // Red orbit
- particles.spawnOrbiting(cx, cy, 150.0, -0.8, 120); // Green orbit
- particles.spawnOrbiting(cx, cy, 200.0, 0.6, 240); // Blue orbit
-
- rl.InitAudioDevice();
- defer rl.CloseAudioDevice();
-
- rl.SetTargetFPS(60);
- rl.HideCursor(); // Hide system cursor for immersion
-
- // Initial text
- emergent_text.spawnText("WELCOME TO THE VOID", cx, cy - 100);
-
- // Main loop - PURE IMMERSION
- while (!rl.WindowShouldClose()) {
- const dt = rl.GetFrameTime();
- time += dt;
-
- // Cursor position
- const mouse_x = rl.GetMouseX();
- const mouse_y = rl.GetMouseY();
- const mx = @as(f32, @floatFromInt(mouse_x));
- const my = @as(f32, @floatFromInt(mouse_y));
-
- // Grid coordinates
- const gx = @as(usize, @intCast(@divTrunc(mouse_x, g_pixel_size)));
- const gy = @as(usize, @intCast(@divTrunc(mouse_y, g_pixel_size)));
-
- // Evolving cursor hue
- cursor_hue = @mod(cursor_hue + dt * 30.0, 360.0);
-
- // === CURSOR INTERACTIONS ===
-
- // LMB = Wave source (positive perturbation)
- if (rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT)) {
- if (gx < grid.width and gy < grid.height) {
- grid.setCursor(@floatFromInt(gx), @floatFromInt(gy), 1.0);
- }
- // Spawn particles at cursor
- particles.spawn(mx, my, cursor_hue);
- // Add trail point
- cursor_trail.add(mx, my, cursor_hue);
- }
-
- // RMB = Wave sink (negative perturbation)
- if (rl.IsMouseButtonDown(rl.MOUSE_BUTTON_RIGHT)) {
- if (gx < grid.width and gy < grid.height) {
- grid.getMut(gx, gy).amplitude = -1.0;
- }
- particles.spawn(mx, my, @mod(cursor_hue + 180.0, 360.0));
- }
-
- // Mouse wheel = frequency modulation
- const wheel = rl.GetMouseWheelMove();
- if (wheel != 0 and gx < grid.width and gy < grid.height) {
- grid.getMut(gx, gy).frequency += wheel * 0.5;
- }
-
- // === KEYBOARD SHORTCUTS (minimal, for emergent triggers) ===
-
- // T = Spawn emergent text at cursor
- if (rl.IsKeyPressed(rl.KEY_T)) {
- emergent_text.spawnText("EMERGENCE", mx, my);
- }
-
- // G = Golden spiral injection
- if (rl.IsKeyPressed(rl.KEY_G)) {
- grid.injectWave(.{ .golden_spiral = .{
- .center_x = gx,
- .center_y = gy,
- .scale = 3.0,
- .amplitude = 1.0,
- } });
- emergent_text.spawnText("PHI", mx, my);
- }
-
- // W = Wave pulse
- if (rl.IsKeyPressed(rl.KEY_W)) {
- grid.injectWave(.{ .circle = .{
- .center_x = gx,
- .center_y = gy,
- .radius = 20,
- .amplitude = 1.0,
- } });
- }
-
- // R = Reset (cosmic rebirth)
- if (rl.IsKeyPressed(rl.KEY_R)) {
- for (grid.photons) |*p| {
- p.amplitude = 0;
- p.interference = 0;
- }
- emergent_text.spawnText("REBIRTH", cx, cy);
- }
-
- // I = Export image (PPM)
- if (rl.IsKeyPressed(rl.KEY_I)) {
- const exporter = photon.ImageExporter.init(&grid);
- if (exporter.exportPPM(allocator)) |ppm| {
- defer allocator.free(ppm);
- const timestamp = @as(u64, @intCast(std.time.milliTimestamp()));
- var path_buf: [128]u8 = undefined;
- const path = std.fmt.bufPrint(&path_buf, "photon_{d}.ppm", .{timestamp}) catch "photon.ppm";
- const file = std.fs.cwd().createFile(path, .{}) catch {
- emergent_text.spawnText("EXPORT FAILED", mx, my);
- continue;
- };
- defer file.close();
- file.writeAll(ppm) catch {};
- emergent_text.spawnText("IMAGE SAVED", mx, my);
- } else |_| {
- emergent_text.spawnText("EXPORT FAILED", mx, my);
- }
- }
-
- // A = Export audio (WAV)
- if (rl.IsKeyPressed(rl.KEY_A)) {
- const synth = photon.AudioSynthesizer.init(&grid);
- if (synth.generatePCM16(allocator, 1000)) |samples| {
- defer allocator.free(samples);
- const header = photon.WavHeader.init(44100, @intCast(samples.len));
- const timestamp = @as(u64, @intCast(std.time.milliTimestamp()));
- var path_buf: [128]u8 = undefined;
- const path = std.fmt.bufPrint(&path_buf, "photon_{d}.wav", .{timestamp}) catch "photon.wav";
- const file = std.fs.cwd().createFile(path, .{}) catch {
- emergent_text.spawnText("AUDIO FAILED", mx, my);
- continue;
- };
- defer file.close();
- file.writeAll(&header.toBytes()) catch {};
- file.writeAll(std.mem.sliceAsBytes(samples)) catch {};
- emergent_text.spawnText("AUDIO SAVED", mx, my);
- } else |_| {
- emergent_text.spawnText("AUDIO FAILED", mx, my);
- }
- }
-
- // === PHYSICS UPDATE ===
- grid.stepSIMD();
- particles.update(dt);
- cursor_trail.update(dt);
- emergent_text.update(dt, time);
-
- // Update orbiting particles to reflect stats
- // Energy β orbit radius pulsation
- const energy_factor = 1.0 + grid.total_energy * 0.0001;
- for (&particles.particles) |*p| {
- if (p.is_orbiting and p.isAlive()) {
- p.orbit_radius *= 0.99 + energy_factor * 0.01;
- }
- }
-
- // Note: last_mouse_x/y available for velocity calculations if needed
-
- // === RENDER ===
- rl.BeginDrawing();
- defer rl.EndDrawing();
-
- // Pure void background
- rl.ClearBackground(VOID_BLACK);
-
- // Draw photon grid (fills entire screen)
- drawImmersiveGrid(&grid, time);
-
- // Draw cursor trail
- cursor_trail.draw();
-
- // Draw particles
- particles.draw();
-
- // Draw emergent text
- emergent_text.draw(time);
-
- // Draw custom cursor (photon probe)
- drawPhotonCursor(mx, my, cursor_hue, time);
-
- // Subtle corner indicators (barely visible, emergent feel)
- drawCornerGlyphs(time);
- }
-}
-
-fn drawImmersiveGrid(grid: *photon.PhotonGrid, time: f32) void {
- for (0..grid.height) |y| {
- for (0..grid.width) |x| {
- const p = grid.get(x, y);
-
- // Skip very low amplitude (performance + visual)
- if (@abs(p.amplitude) < 0.01) continue;
-
- const px: c_int = @intCast(x * @as(usize, @intCast(g_pixel_size)));
- const py: c_int = @intCast(y * @as(usize, @intCast(g_pixel_size)));
-
- // Color based on amplitude + phase + time
- const hue = @mod(p.hue + time * 20.0 + p.phase * 10.0, 360.0);
- const saturation: f32 = 0.8;
- const brightness = @min(1.0, @abs(p.amplitude));
-
- const rgb = hsvToRgb(hue, saturation, brightness);
-
- // Alpha based on amplitude
- const alpha: u8 = @intFromFloat(@min(255.0, @abs(p.amplitude) * 300.0));
-
- const color = rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = alpha };
-
- // Draw pixel with slight glow for high amplitude
- if (@abs(p.amplitude) > 0.5) {
- const glow_alpha: u8 = @intFromFloat(@min(100.0, @abs(p.amplitude) * 100.0));
- rl.DrawRectangle(px - 1, py - 1, g_pixel_size + 2, g_pixel_size + 2, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = glow_alpha });
- }
-
- rl.DrawRectangle(px, py, g_pixel_size - 1, g_pixel_size - 1, color);
- }
- }
-}
-
-fn drawPhotonCursor(x: f32, y: f32, hue: f32, time: f32) void {
- const px: c_int = @intFromFloat(x);
- const py: c_int = @intFromFloat(y);
-
- const rgb = hsvToRgb(hue, 1.0, 1.0);
-
- // Pulsating rings
- const pulse = (@sin(time * 5.0) + 1.0) * 0.5;
-
- // Outer glow
- rl.DrawCircle(px, py, 20 + pulse * 10, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = 30 });
- rl.DrawCircle(px, py, 12 + pulse * 5, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = 60 });
-
- // Inner rings
- rl.DrawCircleLines(px, py, 8 + pulse * 3, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = 200 });
- rl.DrawCircleLines(px, py, 4 + pulse * 2, rl.Color{ .r = 255, .g = 255, .b = 255, .a = 255 });
-
- // Center dot
- rl.DrawCircle(px, py, 2, rl.Color{ .r = 255, .g = 255, .b = 255, .a = 255 });
-}
-
-fn drawCornerGlyphs(time: f32) void {
- const alpha: u8 = @intFromFloat(30.0 + @sin(time * 0.5) * 20.0);
- const color = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = alpha };
-
- // Top-left: phi symbol hint
- rl.DrawText("phi", 10, 10, 12, color);
-
- // Top-right: trinity
- rl.DrawText("3", g_width - 20, 10, 12, color);
-
- // Bottom-left
- rl.DrawText("v0.3", 10, g_height - 20, 10, color);
-
- // Bottom-right
- rl.DrawText("ESC", g_width - 30, g_height - 20, 10, color);
-}
-
-// =============================================================================
-// UTILITY
-// =============================================================================
-
-fn hsvToRgb(h: f32, s: f32, v: f32) [3]u8 {
- const c = v * s;
- const x = c * (1.0 - @abs(@mod(h / 60.0, 2.0) - 1.0));
- const m = v - c;
-
- var r: f32 = 0;
- var g: f32 = 0;
- var b: f32 = 0;
-
- if (h < 60) {
- r = c;
- g = x;
- } else if (h < 120) {
- r = x;
- g = c;
- } else if (h < 180) {
- g = c;
- b = x;
- } else if (h < 240) {
- g = x;
- b = c;
- } else if (h < 300) {
- r = x;
- b = c;
- } else {
- r = c;
- b = x;
- }
-
- return .{
- @intFromFloat((r + m) * 255.0),
- @intFromFloat((g + m) * 255.0),
- @intFromFloat((b + m) * 255.0),
- };
-}
diff --git a/src/vsa/photon_terminal.zig b/src/vsa/photon_terminal.zig
deleted file mode 100644
index 9ea07ae193..0000000000
--- a/src/vsa/photon_terminal.zig
+++ /dev/null
@@ -1,743 +0,0 @@
-// =============================================================================
-// PHOTON TERMINAL v1.0 - TERNARY EMERGENT TUI
-// Not a grid of cells β a living wave field.
-// Text emerges from standing waves. Input perturbs reality.
-// phi^2 + 1/phi^2 = 3 = TRINITY
-// =============================================================================
-
-const std = @import("std");
-const photon = @import("photon.zig");
-const math = std.math;
-const posix = std.posix;
-
-// =============================================================================
-// COSMIC CONSTANTS
-// =============================================================================
-
-const PHI: f32 = 1.6180339887;
-const PHI_INV: f32 = 0.6180339887;
-const TAU: f32 = 6.28318530718;
-
-// Terminal grid (photon resolution)
-const GRID_WIDTH: usize = 120;
-const GRID_HEIGHT: usize = 40;
-
-// ANSI color codes (256-color mode)
-const ANSI_RESET = "\x1b[0m";
-const ANSI_CLEAR = "\x1b[2J\x1b[H";
-const ANSI_HIDE_CURSOR = "\x1b[?25l";
-const ANSI_SHOW_CURSOR = "\x1b[?25h";
-const ANSI_ALT_SCREEN = "\x1b[?1049h";
-const ANSI_MAIN_SCREEN = "\x1b[?1049l";
-
-// =============================================================================
-// TERMINAL RAW MODE
-// =============================================================================
-
-const TerminalState = struct {
- original_termios: posix.termios,
- stdin_fd: posix.fd_t,
-
- pub fn init() !TerminalState {
- const stdin_fd = posix.STDIN_FILENO;
- const original = try posix.tcgetattr(stdin_fd);
-
- var raw = original;
- // Disable canonical mode, echo, signals
- raw.lflag.ICANON = false;
- raw.lflag.ECHO = false;
- raw.lflag.ISIG = false;
- raw.lflag.IEXTEN = false;
- // Disable input processing
- raw.iflag.IXON = false;
- raw.iflag.ICRNL = false;
- raw.iflag.BRKINT = false;
- raw.iflag.INPCK = false;
- raw.iflag.ISTRIP = false;
- // Disable output processing
- raw.oflag.OPOST = false;
- // Set read timeout (non-blocking with timeout)
- raw.cc[@intFromEnum(posix.V.MIN)] = 0;
- raw.cc[@intFromEnum(posix.V.TIME)] = 1; // 100ms timeout
-
- try posix.tcsetattr(stdin_fd, .FLUSH, raw);
-
- return .{
- .original_termios = original,
- .stdin_fd = stdin_fd,
- };
- }
-
- pub fn deinit(self: *TerminalState) void {
- // Silently ignore restore failures - terminal may already be closed
- _ = posix.tcsetattr(self.stdin_fd, .FLUSH, self.original_termios) catch {};
- }
-
- pub fn readKey(self: *TerminalState) ?u8 {
- var buf: [1]u8 = undefined;
- const n = posix.read(self.stdin_fd, &buf) catch return null;
- if (n == 0) return null;
- return buf[0];
- }
-
- pub fn readKeyNonBlocking(self: *TerminalState) ?u8 {
- // Check if data available
- var fds = [_]posix.pollfd{.{
- .fd = self.stdin_fd,
- .events = posix.POLL.IN,
- .revents = 0,
- }};
-
- const ready = posix.poll(&fds, 0) catch return null;
- if (ready == 0) return null;
-
- return self.readKey();
- }
-};
-
-// =============================================================================
-// ANSI RENDERING
-// =============================================================================
-
-const AnsiRenderer = struct {
- buffer: std.ArrayListUnmanaged(u8),
- allocator: std.mem.Allocator,
- width: usize,
- height: usize,
-
- pub fn init(allocator: std.mem.Allocator, width: usize, height: usize) AnsiRenderer {
- return .{
- .buffer = .{},
- .allocator = allocator,
- .width = width,
- .height = height,
- };
- }
-
- pub fn deinit(self: *AnsiRenderer) void {
- self.buffer.deinit(self.allocator);
- }
-
- pub fn clear(self: *AnsiRenderer) void {
- self.buffer.clearRetainingCapacity();
- }
-
- pub fn moveTo(self: *AnsiRenderer, x: usize, y: usize) !void {
- var buf: [32]u8 = undefined;
- const s = std.fmt.bufPrint(&buf, "\x1b[{d};{d}H", .{ y + 1, x + 1 }) catch return;
- try self.buffer.appendSlice(self.allocator, s);
- }
-
- pub fn setColor256(self: *AnsiRenderer, fg: u8, bg: u8) !void {
- var buf: [32]u8 = undefined;
- const s = std.fmt.bufPrint(&buf, "\x1b[38;5;{d};48;5;{d}m", .{ fg, bg }) catch return;
- try self.buffer.appendSlice(self.allocator, s);
- }
-
- pub fn setColorRGB(self: *AnsiRenderer, r: u8, g: u8, b: u8) !void {
- var buf: [32]u8 = undefined;
- const s = std.fmt.bufPrint(&buf, "\x1b[38;2;{d};{d};{d}m", .{ r, g, b }) catch return;
- try self.buffer.appendSlice(self.allocator, s);
- }
-
- pub fn setBgRGB(self: *AnsiRenderer, r: u8, g: u8, b: u8) !void {
- var buf: [32]u8 = undefined;
- const s = std.fmt.bufPrint(&buf, "\x1b[48;2;{d};{d};{d}m", .{ r, g, b }) catch return;
- try self.buffer.appendSlice(self.allocator, s);
- }
-
- pub fn writeChar(self: *AnsiRenderer, c: u8) !void {
- try self.buffer.append(self.allocator, c);
- }
-
- pub fn writeStr(self: *AnsiRenderer, s: []const u8) !void {
- try self.buffer.appendSlice(self.allocator, s);
- }
-
- pub fn reset(self: *AnsiRenderer) !void {
- try self.buffer.appendSlice(self.allocator, ANSI_RESET);
- }
-
- pub fn flush(self: *AnsiRenderer) !void {
- _ = posix.write(posix.STDOUT_FILENO, self.buffer.items) catch {};
- }
-};
-
-// =============================================================================
-// EMERGENT GLYPH MAPPING
-// =============================================================================
-
-const GlyphMapper = struct {
- // Map wave amplitude to ASCII characters
- // Higher amplitude = denser glyph
- const GLYPHS = " .'`^\",:;Il!i><~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$";
-
- pub fn amplitudeToGlyph(amplitude: f32) u8 {
- const normalized = @min(1.0, @max(0.0, @abs(amplitude)));
- const idx: usize = @intFromFloat(normalized * @as(f32, @floatFromInt(GLYPHS.len - 1)));
- return GLYPHS[idx];
- }
-
- pub fn amplitudeToColor(amplitude: f32, phase: f32, hue_offset: f32) [3]u8 {
- const h = @mod(hue_offset + phase * 60.0, 360.0);
- const s: f32 = 0.8;
- const v = @min(1.0, @abs(amplitude));
- return hsvToRgb(h, s, v);
- }
-};
-
-// =============================================================================
-// EMERGENT TEXT SYSTEM
-// =============================================================================
-
-const MAX_TEXT_WAVES = 16;
-const MAX_TEXT_LEN = 128;
-
-const TextWave = struct {
- text: [MAX_TEXT_LEN]u8,
- len: usize,
- x: usize,
- y: usize,
- phase: f32,
- amplitude: f32,
- life: f32,
- is_input: bool, // User input vs system output
-
- pub fn spawn(x: usize, y: usize, text: []const u8, is_input: bool) TextWave {
- var tw = TextWave{
- .text = undefined,
- .len = @min(text.len, MAX_TEXT_LEN),
- .x = x,
- .y = y,
- .phase = 0,
- .amplitude = 1.0,
- .life = 1.0,
- .is_input = is_input,
- };
- @memcpy(tw.text[0..tw.len], text[0..tw.len]);
- return tw;
- }
-
- pub fn update(self: *TextWave, dt: f32) void {
- self.phase += dt * 3.0;
- self.life -= dt * 0.1;
- }
-
- pub fn isAlive(self: *const TextWave) bool {
- return self.life > 0;
- }
-
- // Inject text as wave perturbation into grid
- pub fn injectIntoGrid(self: *const TextWave, grid: *photon.PhotonGrid) void {
- if (!self.isAlive()) return;
-
- for (0..self.len) |i| {
- const gx = self.x + i;
- if (gx >= grid.width) break;
-
- const c = self.text[i];
- const char_amp = @as(f32, @floatFromInt(c)) / 128.0;
-
- // Create standing wave pattern for each character
- const wave_y_start = if (self.y >= 2) self.y - 2 else 0;
- const wave_y_end = @min(self.y + 3, grid.height);
-
- for (wave_y_start..wave_y_end) |gy| {
- if (gx < grid.width and gy < grid.height) {
- const dy = @as(f32, @floatFromInt(gy)) - @as(f32, @floatFromInt(self.y));
- const wave = @sin(self.phase + @as(f32, @floatFromInt(i)) * 0.5) * @exp(-dy * dy * 0.2);
- grid.getMut(gx, gy).amplitude += char_amp * wave * self.amplitude * self.life;
- grid.getMut(gx, gy).hue = if (self.is_input) 180.0 else 120.0; // Cyan input, green output
- }
- }
- }
- }
-};
-
-const TextWaveSystem = struct {
- waves: [MAX_TEXT_WAVES]TextWave,
- count: usize,
-
- pub fn init() TextWaveSystem {
- var sys = TextWaveSystem{
- .waves = undefined,
- .count = 0,
- };
- for (&sys.waves) |*w| {
- w.life = 0;
- }
- return sys;
- }
-
- pub fn spawn(self: *TextWaveSystem, x: usize, y: usize, text: []const u8, is_input: bool) void {
- for (&self.waves) |*w| {
- if (!w.isAlive()) {
- w.* = TextWave.spawn(x, y, text, is_input);
- return;
- }
- }
- }
-
- pub fn update(self: *TextWaveSystem, dt: f32) void {
- for (&self.waves) |*w| {
- if (w.isAlive()) {
- w.update(dt);
- }
- }
- }
-
- pub fn injectAll(self: *TextWaveSystem, grid: *photon.PhotonGrid) void {
- for (&self.waves) |*w| {
- w.injectIntoGrid(grid);
- }
- }
-};
-
-// =============================================================================
-// INPUT BUFFER
-// =============================================================================
-
-const InputBuffer = struct {
- buffer: [256]u8,
- len: usize,
- cursor: usize,
- active: bool,
-
- pub fn init() InputBuffer {
- return .{
- .buffer = undefined,
- .len = 0,
- .cursor = 0,
- .active = true,
- };
- }
-
- pub fn addChar(self: *InputBuffer, c: u8) void {
- if (self.len < 255) {
- self.buffer[self.len] = c;
- self.len += 1;
- self.cursor = self.len;
- }
- }
-
- pub fn backspace(self: *InputBuffer) void {
- if (self.len > 0) {
- self.len -= 1;
- self.cursor = self.len;
- }
- }
-
- pub fn clear(self: *InputBuffer) void {
- self.len = 0;
- self.cursor = 0;
- }
-
- pub fn getText(self: *const InputBuffer) []const u8 {
- return self.buffer[0..self.len];
- }
-};
-
-// =============================================================================
-// PHOTON TERMINAL
-// =============================================================================
-
-pub const PhotonTerminal = struct {
- allocator: std.mem.Allocator,
- grid: photon.PhotonGrid,
- renderer: AnsiRenderer,
- terminal: TerminalState,
- text_waves: TextWaveSystem,
- input: InputBuffer,
- time: f32,
- cursor_x: usize,
- cursor_y: usize,
- running: bool,
- mode: TerminalMode,
- output_lines: std.ArrayListUnmanaged([]const u8),
- hue_offset: f32,
-
- const TerminalMode = enum {
- wave, // Pure wave exploration
- chat, // Chat mode (input β response)
- code, // Code generation mode
- tools, // Tool execution visualization
- };
-
- pub fn init(allocator: std.mem.Allocator) !*PhotonTerminal {
- const self = try allocator.create(PhotonTerminal);
-
- self.* = .{
- .allocator = allocator,
- .grid = try photon.PhotonGrid.init(allocator, GRID_WIDTH, GRID_HEIGHT),
- .renderer = AnsiRenderer.init(allocator, GRID_WIDTH, GRID_HEIGHT),
- .terminal = try TerminalState.init(),
- .text_waves = TextWaveSystem.init(),
- .input = InputBuffer.init(),
- .time = 0,
- .cursor_x = GRID_WIDTH / 2,
- .cursor_y = GRID_HEIGHT - 3,
- .running = true,
- .mode = .chat,
- .output_lines = .{},
- .hue_offset = 120.0, // Start with green
- };
-
- return self;
- }
-
- pub fn deinit(self: *PhotonTerminal) void {
- self.terminal.deinit();
- self.renderer.deinit();
- self.grid.deinit();
- for (self.output_lines.items) |line| {
- self.allocator.free(line);
- }
- self.output_lines.deinit(self.allocator);
- self.allocator.destroy(self);
- }
-
- fn writeStdout(data: []const u8) void {
- _ = posix.write(posix.STDOUT_FILENO, data) catch {};
- }
-
- pub fn run(self: *PhotonTerminal) !void {
- // Enter alternate screen and hide cursor
- writeStdout(ANSI_ALT_SCREEN);
- writeStdout(ANSI_HIDE_CURSOR);
- defer {
- writeStdout(ANSI_SHOW_CURSOR);
- writeStdout(ANSI_MAIN_SCREEN);
- }
-
- // Welcome message
- self.text_waves.spawn(5, 3, "PHOTON TERMINAL v1.0", false);
- self.text_waves.spawn(5, 5, "Type to perturb reality. ESC to exit.", false);
- self.text_waves.spawn(5, 7, "phi^2 + 1/phi^2 = 3 = TRINITY", false);
-
- // Initial wave pattern
- self.grid.injectWave(.{ .golden_spiral = .{
- .center_x = GRID_WIDTH / 2,
- .center_y = GRID_HEIGHT / 2,
- .scale = 2.0,
- .amplitude = 0.5,
- } });
-
- var timer = try std.time.Timer.start();
-
- while (self.running) {
- const dt = @as(f32, @floatFromInt(timer.lap())) / 1_000_000_000.0;
- self.time += dt;
-
- // Process input
- try self.processInput();
-
- // Update physics
- self.update(dt);
-
- // Render
- try self.render();
-
- // Frame rate limit (~30 FPS for terminal)
- std.Thread.sleep(33_000_000); // 33ms
- }
- }
-
- fn processInput(self: *PhotonTerminal) !void {
- while (self.terminal.readKeyNonBlocking()) |key| {
- switch (key) {
- 27 => { // ESC
- self.running = false;
- },
- 13 => { // Enter
- if (self.input.len > 0) {
- const text = self.input.getText();
- // Spawn input as wave
- self.text_waves.spawn(2, self.cursor_y - 2, text, true);
-
- // Generate response
- try self.generateResponse(text);
-
- self.input.clear();
- }
- },
- 127, 8 => { // Backspace
- self.input.backspace();
- // Negative perturbation
- if (self.cursor_x > 0) {
- self.cursor_x -= 1;
- self.grid.getMut(self.cursor_x, self.cursor_y).amplitude = -0.5;
- }
- },
- // Arrow keys (escape sequences)
- else => {
- if (key >= 32 and key < 127) {
- self.input.addChar(key);
- // Positive perturbation at cursor
- self.grid.getMut(@min(self.cursor_x, GRID_WIDTH - 1), self.cursor_y).amplitude = 1.0;
- self.grid.getMut(@min(self.cursor_x, GRID_WIDTH - 1), self.cursor_y).hue = 180.0; // Cyan for input
- self.cursor_x = @min(self.cursor_x + 1, GRID_WIDTH - 1);
-
- // Radiate waves from keystroke
- self.injectKeystrokeWave(key);
- }
- },
- }
- }
- }
-
- fn injectKeystrokeWave(self: *PhotonTerminal, key: u8) void {
- // Each key creates a unique wave pattern
- const freq = @as(f32, @floatFromInt(key)) / 128.0;
- const amp = 0.3 + freq * 0.2;
-
- self.grid.injectWave(.{ .circle = .{
- .center_x = self.cursor_x,
- .center_y = self.cursor_y,
- .radius = 5 + @as(usize, @intFromFloat(freq * 10)),
- .amplitude = amp,
- } });
- }
-
- fn generateResponse(self: *PhotonTerminal, input: []const u8) !void {
- // Simple emergent response generation
- // In real version, connect to fluent coder/GGUF inference
-
- var response_buf: [256]u8 = undefined;
- var response_len: usize = 0;
-
- // Check for commands
- if (std.mem.startsWith(u8, input, "/wave")) {
- const msg = "Injecting golden spiral wave...";
- @memcpy(response_buf[0..msg.len], msg);
- response_len = msg.len;
-
- self.grid.injectWave(.{ .golden_spiral = .{
- .center_x = GRID_WIDTH / 2,
- .center_y = GRID_HEIGHT / 2,
- .scale = 3.0,
- .amplitude = 1.0,
- } });
- } else if (std.mem.startsWith(u8, input, "/reset")) {
- const msg = "Reality reset. Waves calming...";
- @memcpy(response_buf[0..msg.len], msg);
- response_len = msg.len;
-
- for (self.grid.photons) |*p| {
- p.amplitude = 0;
- p.interference = 0;
- }
- } else if (std.mem.startsWith(u8, input, "/mode")) {
- const modes = [_][]const u8{ "wave", "chat", "code", "tools" };
- const mode_idx = @as(usize, @intFromEnum(self.mode));
- const next_mode = (mode_idx + 1) % modes.len;
- self.mode = @enumFromInt(next_mode);
-
- var msg_buf: [64]u8 = undefined;
- const msg = std.fmt.bufPrint(&msg_buf, "Mode: {s}", .{modes[next_mode]}) catch "Mode changed";
- @memcpy(response_buf[0..msg.len], msg);
- response_len = msg.len;
- } else if (std.mem.startsWith(u8, input, "/help")) {
- const msg = "/wave /reset /mode /help | ESC=exit";
- @memcpy(response_buf[0..msg.len], msg);
- response_len = msg.len;
- } else {
- // Echo with emergent transformation
- const prefix = ">> ";
- @memcpy(response_buf[0..prefix.len], prefix);
- const copy_len = @min(input.len, 256 - prefix.len);
- @memcpy(response_buf[prefix.len..][0..copy_len], input[0..copy_len]);
- response_len = prefix.len + copy_len;
- }
-
- // Spawn response as wave
- self.text_waves.spawn(2, self.cursor_y - 4, response_buf[0..response_len], false);
-
- // Create expansion wave for response
- self.grid.injectWave(.{ .line_wave = .{
- .position = if (self.cursor_y >= 4) self.cursor_y - 4 else 0,
- .horizontal = true,
- .amplitude = 0.8,
- } });
- }
-
- fn update(self: *PhotonTerminal, dt: f32) void {
- // Update text waves
- self.text_waves.update(dt);
-
- // Inject text waves into grid
- self.text_waves.injectAll(&self.grid);
-
- // Propagate waves
- self.grid.stepSIMD();
-
- // Evolving hue
- self.hue_offset = @mod(self.hue_offset + dt * 10.0, 360.0);
- }
-
- fn render(self: *PhotonTerminal) !void {
- self.renderer.clear();
-
- // Move to top-left
- try self.renderer.moveTo(0, 0);
-
- // Render grid as characters
- for (0..GRID_HEIGHT) |y| {
- for (0..GRID_WIDTH) |x| {
- const p = self.grid.get(x, y);
-
- // Get glyph based on amplitude
- const glyph = GlyphMapper.amplitudeToGlyph(p.amplitude);
-
- // Get color based on amplitude and phase
- const rgb = GlyphMapper.amplitudeToColor(p.amplitude, p.phase, self.hue_offset + p.hue);
-
- // Only color if there's significant amplitude
- if (@abs(p.amplitude) > 0.05) {
- try self.renderer.setColorRGB(rgb[0], rgb[1], rgb[2]);
- try self.renderer.setBgRGB(0, 0, 0);
- } else {
- try self.renderer.setColorRGB(30, 30, 30);
- try self.renderer.setBgRGB(0, 0, 0);
- }
-
- try self.renderer.writeChar(glyph);
- }
- try self.renderer.writeChar('\n');
- }
-
- // Draw input line
- try self.renderer.reset();
- try self.renderer.moveTo(0, GRID_HEIGHT);
- try self.renderer.setColorRGB(0, 255, 136); // Neon green
- try self.renderer.writeStr("> ");
- try self.renderer.setColorRGB(255, 255, 255);
- try self.renderer.writeStr(self.input.getText());
-
- // Draw cursor
- try self.renderer.setColorRGB(0, 255, 255); // Cyan cursor
- try self.renderer.writeChar('_');
-
- // Draw mode indicator
- try self.renderer.moveTo(GRID_WIDTH - 20, GRID_HEIGHT);
- try self.renderer.setColorRGB(100, 100, 100);
- const mode_str = switch (self.mode) {
- .wave => "[WAVE]",
- .chat => "[CHAT]",
- .code => "[CODE]",
- .tools => "[TOOLS]",
- };
- try self.renderer.writeStr(mode_str);
-
- try self.renderer.reset();
- try self.renderer.flush();
- }
-};
-
-// =============================================================================
-// UTILITY
-// =============================================================================
-
-fn hsvToRgb(h: f32, s: f32, v: f32) [3]u8 {
- const c = v * s;
- const x = c * (1.0 - @abs(@mod(h / 60.0, 2.0) - 1.0));
- const m = v - c;
-
- var r: f32 = 0;
- var g: f32 = 0;
- var b: f32 = 0;
-
- if (h < 60) {
- r = c;
- g = x;
- } else if (h < 120) {
- r = x;
- g = c;
- } else if (h < 180) {
- g = c;
- b = x;
- } else if (h < 240) {
- g = x;
- b = c;
- } else if (h < 300) {
- r = x;
- b = c;
- } else {
- r = c;
- b = x;
- }
-
- return .{
- @intFromFloat((r + m) * 255.0),
- @intFromFloat((g + m) * 255.0),
- @intFromFloat((b + m) * 255.0),
- };
-}
-
-// =============================================================================
-// MAIN
-// =============================================================================
-
-pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- defer _ = gpa.deinit();
- const allocator = gpa.allocator();
-
- var terminal = try PhotonTerminal.init(allocator);
- defer terminal.deinit();
-
- try terminal.run();
-}
-
-// =============================================================================
-// TESTS
-// =============================================================================
-
-test "glyph mapping" {
- const g1 = GlyphMapper.amplitudeToGlyph(0);
- try std.testing.expect(g1 == ' ');
-
- const g2 = GlyphMapper.amplitudeToGlyph(1.0);
- try std.testing.expect(g2 == '$');
-
- const g3 = GlyphMapper.amplitudeToGlyph(0.5);
- try std.testing.expect(g3 != ' ' and g3 != '$');
-}
-
-test "text wave spawn" {
- var sys = TextWaveSystem.init();
- sys.spawn(10, 10, "Hello", true);
-
- var alive_count: usize = 0;
- for (&sys.waves) |*w| {
- if (w.isAlive()) alive_count += 1;
- }
- try std.testing.expect(alive_count == 1);
-}
-
-test "input buffer" {
- var buf = InputBuffer.init();
- buf.addChar('H');
- buf.addChar('i');
-
- try std.testing.expectEqualStrings("Hi", buf.getText());
-
- buf.backspace();
- try std.testing.expectEqualStrings("H", buf.getText());
-
- buf.clear();
- try std.testing.expectEqualStrings("", buf.getText());
-}
-
-test "hsv to rgb" {
- // Red
- const red = hsvToRgb(0, 1, 1);
- try std.testing.expect(red[0] == 255);
-
- // Green
- const green = hsvToRgb(120, 1, 1);
- try std.testing.expect(green[1] == 255);
-
- // Blue
- const blue = hsvToRgb(240, 1, 1);
- try std.testing.expect(blue[2] == 255);
-}
diff --git a/src/vsa/photon_trinity_canvas.zig b/src/vsa/photon_trinity_canvas.zig
deleted file mode 100644
index 424741ed4d..0000000000
--- a/src/vsa/photon_trinity_canvas.zig
+++ /dev/null
@@ -1,10318 +0,0 @@
-// =============================================================================
-// TRINITY CANVAS v2.1 - MIRROR OF THREE WORLDS
-// No side panels β everything inside canvas as wave patterns
-// Shift+1 Chat | Shift+2 Code | Shift+3 Tools | Shift+4 Settings | Shift+5 Vision | Shift+6 Voice
-// ESC = return to idle (27 petals logo)
-// phi^2 + 1/phi^2 = 3 = TRINITY
-// =============================================================================
-
-const std = @import("std");
-const builtin = @import("builtin");
-const is_emscripten = builtin.os.tag == .emscripten;
-const photon = @import("photon.zig");
-const wave_scroll = @import("wave_scroll.zig"); // Emergent Wave ScrollView v1.0
-const theme = @import("trinity_canvas/theme.zig"); // SINGLE SOURCE OF TRUTH
-const world_docs = @import("trinity_canvas/world_docs.zig");
-const igla_chat = @import("igla_chat");
-const fluent_chat = @import("igla_fluent_chat");
-const igla_hybrid_chat = @import("igla_hybrid_chat");
-const golden_chain = @import("golden_chain");
-const tvc = @import("tvc_corpus");
-const auto_shard = @import("auto_shard");
-const world_dots = @import("world_dots.zig");
-const math = std.math;
-const rl = @cImport({
- @cInclude("raylib.h");
- @cInclude("raygui.h");
-});
-// v8.4: raygui shortcut
-const rg = rl;
-
-// Emscripten API for browser yield (emscripten_sleep)
-const emc = if (is_emscripten) @cImport(@cInclude("emscripten/emscripten.h")) else struct {};
-
-// Global chat engines
-var g_chat_engine: igla_chat.IglaLocalChat = igla_chat.IglaLocalChat.init();
-var g_fluent_engine: fluent_chat.FluentChatEngine = undefined;
-var g_fluent_engine_inited: bool = false;
-
-// v2.4: Hybrid chat engine (4-level cache: Tools β Symbolic β TVC β LLM)
-var g_hybrid_engine: ?igla_hybrid_chat.IglaHybridChat = null;
-var g_hybrid_corpus: ?*tvc.TVCCorpus = null;
-var g_hybrid_inited: bool = false;
-// GPA for hybrid engine allocations (page_allocator on WASM)
-var g_hybrid_gpa: if (is_emscripten) u8 else std.heap.GeneralPurposeAllocator(.{}) = if (is_emscripten) 0 else std.heap.GeneralPurposeAllocator(.{}){};
-
-// v3.0: Golden Chain Agent (8-node unified pipeline)
-var g_chain_agent: ?golden_chain.GoldenChainAgent = null;
-
-// =============================================================================
-// COSMIC CONSTANTS (from theme.zig)
-// =============================================================================
-
-const PHI: f32 = theme.PHI;
-const PHI_INV: f32 = theme.PHI_INV;
-const TAU: f32 = theme.TAU;
-
-// Grid fills ENTIRE screen
-var g_width: c_int = 1512;
-var g_height: c_int = 982;
-var g_pixel_size: c_int = 4;
-// Adaptive font scale: proportional to screen width (reference: 1280px)
-var g_font_scale: f32 = 1.0;
-// HiDPI scale factor (2.0 on Retina, 1.0 on standard displays)
-var g_dpi_scale: f32 = 1.0;
-// Chat font (Montserrat with Cyrillic) β set in main()
-var g_font_chat: rl.Font = undefined;
-// v8.6: Emoji font for tool pills and UI elements
-var g_font_emoji: rl.Font = undefined;
-
-// ββ Persistent chat state (survives panel close/reopen) ββ
-const MAX_CHAT_MSGS = 128; // v3.0: increased for Golden Chain (8+ msgs per query)
-const ChatMsgType = enum {
- user,
- ai,
- log,
- // β 8 chain nodes (Chakra colors)
- chain_goal_parse, // Red β
- chain_decompose, // Orange β inandwithon
- chain_schedule, // Yellow β and
- chain_execute, // Green β on
- chain_monitor, // Blue β and
- chain_adapt, // Indigo β on
- chain_synthesize, // Violet β with
- chain_deliver, // Gold β andwithin
- // Additional feedback types
- tool_result, // Tool execution
- routing_info, // Routing decision
- reflection, // Self-learning event
- agent_error, // Error
- // v1.1: Truth & Provenance
- provenance_step, // Hash chain record (steel blue)
- truth_verification, // Chain integrity verdict (bright teal)
- // v1.2: Quark-Gluon
- quark_step, // Quark sub-step record (light steel blue)
- gluon_entangle, // Gluon entanglement notification (magenta)
- // v1.4: DAG + Rewards
- dag_visualization, // DAG edge/stats summary (cyan)
- reward_summary, // $TRI reward summary (gold)
- // v1.5: Collapsible + Shareable + Staking
- collapse_toggle, // Node collapse/expand event (slate)
- share_link_generated, // Shareable link created (electric blue)
- staking_event, // Staking lock/unlock/yield event (emerald)
- // v2.0: Immortal Self-Verifying Agent
- self_repair_event, // Self-repair action (warm orange)
- immortal_persist, // Persistence checkpoint (deep teal)
- evolution_step, // Evolution generation step (aurora green)
- chain_health_check, // Chain health assessment (sky blue)
- // v2.1: Public Launch + Faucet + Canvas
- faucet_claim, // Faucet $TRI claim event (gold)
- public_launch, // Public session launch event (bright cyan)
- canvas_sync, // Canvas browser sync event (violet)
- faucet_distribution, // Faucet distribution summary (amber)
- // v2.2: Agent OS + Decentralized Network
- decentral_sync, // Multi-node sync event (electric purple)
- node_consensus, // Network consensus vote (lime green)
- network_health, // Network health report (ocean blue)
- agent_os_init, // Agent OS lifecycle event (bright coral)
- // v2.3: Mainnet Genesis + DAO + Swarm
- mainnet_genesis, // Mainnet genesis event (gold)
- dao_vote, // DAO governance vote (royal blue)
- swarm_sync, // Swarm node sync (neon green)
- token_mint, // $TRI token mint (amber)
- // v2.4: Mainnet v1.0 Launch
- mainnet_launch, // Mainnet v1.0 launch (crimson)
- community_onboard, // Community onboarding (lime)
- node_discovery, // Node discovery (cyan)
- governance_exec, // Governance execution (magenta)
- // v2.5: Immortal Agent Swarm v1.0
- swarm_orchestrate, // Swarm orchestration (electric purple)
- swarm_failover, // Swarm failover (red-orange)
- swarm_telemetry, // Swarm telemetry (teal)
- swarm_replication, // Swarm replication (sky blue)
- // v2.6: Swarm Scaling + Live Rewards + DAO Governance
- swarm_scale, // Swarm scale (gold)
- reward_distribute, // Reward distribution (amber)
- dao_governance_live, // DAO governance live (royal blue)
- node_scaling, // Node scaling (spring green)
- // v2.7: Community Nodes v1.0 + Gossip Protocol + DHT 10k+
- community_node, // Community node (lime green)
- gossip_broadcast, // Gossip broadcast (coral)
- dht_lookup, // DHT lookup (dodger blue)
- community_sync, // Community sync (medium orchid)
- // v2.8: DAO Full Governance v1.0
- dao_delegate, // DAO delegation (gold)
- timelock_vote, // Time-locked voting (crimson)
- proposal_exec, // Proposal execution (sea green)
- yield_farming, // Yield farming (dark orange)
- // v2.9: Cross-Chain Bridge v1.0
- cross_chain_bridge, // Cross-chain bridge (deep sky blue)
- atomic_swap, // Atomic swap (orange red)
- state_replicate, // State replication (medium sea green)
- bridge_sync, // Bridge sync (royal blue)
- // v2.10: Trinity DAO Full Governance v1.0 + $TRI Staking Rewards
- dao_full_governance, // DAO full governance (gold)
- tri_staking, // $TRI staking (lime green)
- reward_distribute_v2, // Reward distribution v2 (hot pink)
- staking_validate, // Staking validation (steel blue)
- // v2.11: Swarm 100k + Community 50k (Sharded Gossip + Hierarchical DHT)
- swarm_100k, // Swarm 100k (orange)
- gossip_shard, // Gossip shard (dark turquoise)
- dht_sync, // DHT hierarchical (medium purple)
- community_50k, // Community 50k (spring green)
- // v2.12: Zero-Knowledge Bridge v1.0 (ZK-Proof Verification + Privacy Transfers)
- zk_bridge, // ZK bridge (crimson)
- zk_proof, // ZK proof (electric blue)
- privacy_transfer, // Privacy transfer (indigo)
- cross_chain_sync_v2, // Cross-chain sync (emerald)
- // v2.13: Layer-2 Rollup v1.0 (u8 Upgrade)
- l2_rollup, // L2 rollup (coral)
- optimistic_verify, // Optimistic verify (cyan)
- state_channel, // State channel (orchid)
- batch_compress, // Batch compress (turquoise)
- // v2.14: Dynamic Shard Rebalancing v1.0
- dynamic_shard, // Dynamic shard (gold)
- shard_split, // Shard split (lime)
- shard_merge, // Shard merge (salmon)
- dht_adapt, // DHT adapt (steel blue)
- // v2.15: Swarm 1M + Community 500k
- swarm_million, // Swarm million (orange red)
- community_node_v2, // Community node v2 (medium purple)
- hierarchical_gossip, // Hierarchical gossip (dark cyan)
- geographic_shard, // Geographic shard (indian red)
- // v2.16: ZK-Rollup v2.0
- zk_snark_proof, // ZK-SNARK proof (lime green)
- recursive_proof, // Recursive proof (deep pink)
- l2_scaling, // L2 scaling (dodger blue)
- rollup_batch, // Rollup batch (dark orange)
- // v2.17: Cross-Shard Transactions v1.0
- cross_shard_tx, // Cross-shard transaction (spring green)
- atomic_2pc, // Atomic 2PC (hot pink)
- shard_fee, // Shard fee (steel blue)
- tx_coordinator, // Transaction coordinator (golden rod)
- // v2.18: Network Partition Recovery v1.0
- partition_detect, // Partition detection (coral #FF7F50)
- split_brain, // Split-brain detection (medium orchid #BA55D3)
- auto_heal, // Auto-healing (medium sea green #3CB371)
- partition_tolerance, // Partition tolerance (slate blue #6A5ACD)
- // v2.19: Swarm 10M + Community 5M
- swarm_10m, // Swarm 10M (lime green #32CD32)
- community_5m, // Community 5M (deep pink #FF1493)
- earning_boost, // Earning boost (dodger blue #1E90FF)
- massive_gossip, // Massive gossip (dark orange #FF8C00)
- // v2.20: ZK-Rollup v2.0
- zk_rollup_v2, // ZK-Rollup v2 (medium spring green #00FA9A)
- snark_generate, // SNARK generation (hot pink #FF69B4)
- recursive_compose, // Recursive composition (royal blue #4169E1)
- l2_fee_collect, // L2 fee collection (gold #FFD700)
- // v2.21: Cross-Shard Transactions v1.0
- cross_shard_tx_v2, // Cross-shard tx v2 (cyan #00FFFF)
- atomic_2pc_v2, // Atomic 2PC v2 (magenta #FF00FF)
- shard_fee_v2, // Shard fee v2 (orange red #FF4500)
- inter_shard_sync_v2, // Inter-shard sync v2 (spring green #00FF7F)
- // v2.22: Formal Verification v1.0
- formal_verify_v2, // Formal verify v2 (deep sky blue #00BFFF)
- property_test_v2, // Property test v2 (deep pink #FF1493)
- invariant_check_v2, // Invariant check v2 (lime green #32CD32)
- proof_generate_v2, // Proof generate v2 (orange #FFA500)
- // v2.23: Swarm 100M + Community 50M
- swarm_100m_v2,
- community_50m_v2,
- earning_moonshot_v2,
- gossip_v3_v2,
- // v2.24: Trinity Global Dominance v1.0
- global_dominance_v2,
- world_adoption_v2,
- tri_to_one_v2,
- ecosystem_complete_v2,
-
- // v2.25: Trinity Eternal v1.0
- ouroboros_evolve_v2,
- infinite_scale_v2,
- universal_reserve_v2,
- eternal_uptime_v2,
-
- // v2.26: $TRI to $10
- tri_to_ten_v2,
- mass_adoption_v2,
- exchange_listing_v2,
- universal_wallet_v2,
-
- // v2.27: Trinity Beyond v1.0
- tri_to_hundred_v2,
- universal_adoption_v2,
- exchange_v2_v2,
- global_wallet_v2,
- // v2.28: Swarm 10M + u8 FULL
- swarm_10m_v2,
- community_5m_v2,
- earning_ultimate_v2,
- node_discovery_10m_v2,
- // v2.29: u16 Upgrade canvas types
- swarm_1b_v2,
- community_500m_v2,
- earning_god_mode_v2,
- node_discovery_1b_v2,
- // v2.30: Trinity Neural Network v1.0
- ternary_nn_v2,
- recursive_self_train_v2,
- contribution_reward_v2,
- neural_consensus_v2,
- // v2.31: $TRI to $1000 + Eternal Dominance
- tri_to_1000_v2,
- universal_reserve_v2_v2,
- global_dominance_v2_v2,
- eternal_governance_v2_v2,
- // v2.32: Trinity Beyond v1.0
- trinity_beyond_v2,
- infinite_scale_v2_v2,
- multiverse_dominance_v2,
- eternal_evolution_v2,
- // v3.0: Trinity Absolute v1.0
- trinity_absolute_v3,
- infinite_tri_v3,
- eternal_victory_v3,
- multiverse_complete_v3,
-};
-var g_chat_messages: [MAX_CHAT_MSGS][512]u8 = undefined; // v3.0: 512 bytes per msg
-var g_chat_msg_lens: [MAX_CHAT_MSGS]usize = .{0} ** MAX_CHAT_MSGS;
-var g_chat_msg_types: [MAX_CHAT_MSGS]ChatMsgType = .{.ai} ** MAX_CHAT_MSGS;
-var g_chat_msg_count: usize = 0;
-var g_chat_input: [256]u8 = undefined;
-var g_chat_input_len: usize = 0;
-var g_backspace_timer: f32 = 0;
-var g_chat_scroll_y: f32 = 0;
-var g_chat_scroll_target: f32 = 0;
-
-// ββ v1.9: Emergent Wave Mode (replaces panel system) ββ
-const WaveMode = enum {
- idle, // 27 petals logo β main menu
- chat, // Fullscreen chat wave field
- code, // Fullscreen code editor wave field
- tools, // Fullscreen tools wave field
- settings, // Fullscreen settings wave field
- vision, // Fullscreen vision wave field
- voice, // Fullscreen voice wave field
- finder, // Fullscreen finder wave field
- docs, // Fullscreen docs wave field
- mirror, // v2.1: Mirror of Three Worlds dashboard
- depin, // v2.4: DePIN Node control panel
- ralph, // v2.9: Ralph Autonomous Monitor panel
-
- pub fn getLabel(self: WaveMode) [*:0]const u8 {
- return switch (self) {
- .idle => "TRINITY",
- .chat => "CHAT",
- .code => "CODE",
- .tools => "TOOLS",
- .settings => "SETTINGS",
- .vision => "VISION",
- .voice => "VOICE",
- .finder => "FINDER",
- .docs => "DOCS",
- .mirror => "MIRROR",
- .depin => "DEPIN",
- .ralph => "RALPH",
- };
- }
-
- pub fn getHue(self: WaveMode) f32 {
- return switch (self) {
- .idle => 45.0, // Gold
- .chat => 150.0, // Green
- .code => 210.0, // Blue
- .tools => 30.0, // Orange
- .settings => 270.0, // Purple
- .vision => 180.0, // Cyan
- .voice => 330.0, // Pink
- .finder => 60.0, // Yellow
- .docs => 120.0, // Green-light
- .mirror => 45.0, // Gold (Trinity)
- .depin => 90.0, // Green-yellow (earning)
- .ralph => 200.0, // Cyan-blue (autonomous)
- };
- }
-};
-var g_wave_mode: WaveMode = .idle;
-var g_wave_transition: f32 = 0; // 0..1 animation progress
-var g_wave_mode_prev: WaveMode = .idle;
-
-// v2.4: DePIN Node state
-var g_depin_running: bool = false;
-var g_depin_docker_ok: bool = false;
-var g_depin_earned_tri: f64 = 0.0;
-var g_depin_pending_tri: f64 = 0.0;
-var g_depin_operations: u64 = 0;
-var g_depin_uptime_hours: f32 = 0.0;
-var g_depin_shards: u64 = 0;
-var g_depin_peers: u32 = 0;
-var g_depin_poll_timer: f32 = 0.0;
-var g_depin_auto_started: bool = false;
-// Docker commands use /bin/sh -c to inherit user PATH
-
-// v2.0: Finder mode β real directory listing cache
-const FINDER_MAX_ENTRIES: usize = 32;
-var g_finder_names: [FINDER_MAX_ENTRIES][64:0]u8 = undefined;
-var g_finder_is_dir: [FINDER_MAX_ENTRIES]bool = [_]bool{false} ** FINDER_MAX_ENTRIES;
-var g_finder_count: usize = 0;
-var g_finder_last_scan: i64 = 0; // timestamp of last scan
-var g_finder_scanned: bool = false;
-
-// v2.1: Mirror live log buffer
-const LIVE_LOG_MAX: usize = 16;
-var g_live_log_text: [LIVE_LOG_MAX][96:0]u8 = undefined;
-var g_live_log_lens: [LIVE_LOG_MAX]usize = [_]usize{0} ** LIVE_LOG_MAX;
-var g_live_log_hues: [LIVE_LOG_MAX]f32 = [_]f32{0} ** LIVE_LOG_MAX;
-var g_live_log_count: usize = 0;
-var g_last_reflection_name: [32:0]u8 = undefined;
-var g_last_reflection_len: usize = 0;
-
-// v2.9: Circuit breaker tri-state (RALPH-CANVAS-004)
-const CircuitBreakerState = enum {
- closed, // Normal operation (green)
- degraded, // Warning state (yellow)
- cb_open, // Circuit open, halted (red)
-
- pub fn getColor(self: CircuitBreakerState, a: u8) rl.Color {
- return switch (self) {
- .closed => rl.Color{ .r = 0x00, .g = 0xCC, .b = 0x66, .a = a },
- .degraded => rl.Color{ .r = 0xFF, .g = 0xCC, .b = 0x00, .a = a },
- .cb_open => rl.Color{ .r = 0xFF, .g = 0x33, .b = 0x33, .a = a },
- };
- }
-
- pub fn getLabel(self: CircuitBreakerState) [*:0]const u8 {
- return switch (self) {
- .closed => "CLOSED",
- .degraded => "DEGRADED",
- .cb_open => "OPEN",
- };
- }
-};
-
-// v3.0: Multi-agent Ralph Monitor (RALPH-CANVAS-005)
-const MAX_RALPH_AGENTS = 4;
-
-// v8.6: Aceternity Glassmorphism Neon Palette (global)
-const GLASS_NEON_PURPLE = rl.Color{ .r = 0x88, .g = 0x44, .b = 0xFF, .a = 255 };
-const GLASS_NEON_CYAN = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0xFF, .a = 255 };
-const GLASS_NEON_MAGENTA = rl.Color{ .r = 0xFF, .g = 0x14, .b = 0x93, .a = 255 };
-const GLASS_NEON_LIME = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x66, .a = 255 };
-const GLASS_BG_DARK = rl.Color{ .r = 20, .g = 20, .b = 35, .a = 180 };
-const GLASS_BG_LIGHT = rl.Color{ .r = 40, .g = 40, .b = 60, .a = 160 };
-
-pub const RalphAgent = struct {
- // Identity
- name: [32:0]u8 = [_:0]u8{0} ** 32,
- name_len: usize = 0,
- branch: [64:0]u8 = [_:0]u8{0} ** 64,
- branch_len: usize = 0,
- // Metrics (from status_report.json + circuit_breaker_state)
- loop: usize = 0,
- total_calls: usize = 0,
- is_healthy: bool = true,
- goal: [128:0]u8 = [_:0]u8{0} ** 128,
- goal_len: usize = 0,
- last_action: [64:0]u8 = [_:0]u8{0} ** 64,
- last_action_len: usize = 0,
- log_ptr: usize = 0,
- // Per-agent state
- cb_state: CircuitBreakerState = .closed,
- running: bool = false,
- reachable: bool = false,
- // Ralph loop logs (ralph.log β left pane)
- logs: [30][128:0]u8 = undefined,
- log_count: usize = 0,
- // Live Claude Code output (from latest claude_output_*.log β right-top pane)
- live_result: [4096:0]u8 = [_:0]u8{0} ** 4096,
- live_result_len: usize = 0,
- live_num_turns: usize = 0,
- live_duration_ms: usize = 0,
- live_cost_usd: [16:0]u8 = [_:0]u8{0} ** 16, // formatted as string
- live_cost_len: usize = 0,
- live_is_error: bool = false,
- live_session_id: [40:0]u8 = [_:0]u8{0} ** 40,
- live_session_len: usize = 0,
- // Status monitor data (status.json β right-bottom pane)
- loop_count_status: usize = 0, // from status.json loop_count
- calls_this_hour: usize = 0, // calls_made_this_hour
- max_calls_hour: usize = 100, // max_calls_per_hour
- status_text: [32:0]u8 = [_:0]u8{0} ** 32, // "running", "idle", etc
- status_text_len: usize = 0,
- next_reset: [16:0]u8 = [_:0]u8{0} ** 16,
- next_reset_len: usize = 0,
- // Progress tracking from status_report.json
- progress_status: [32:0]u8 = [_:0]u8{0} ** 32, // "completed", "in_progress", etc
- progress_status_len: usize = 0,
- recent_commits_count: usize = 0,
- // Data freshness tracking (file modification times as epoch seconds)
- log_mtime: i64 = 0, // ralph.log last modified
- status_mtime: i64 = 0, // status.json last modified
- live_mtime: i64 = 0, // latest claude_output_*.log modified
- data_age_seconds: i64 = 0, // age of newest data source
- rate_limited: bool = false, // detected from live_result
- is_executing: bool = false, // detected from status.json last_action
- // Todo list from TodoWrite (parsed from claude_output log tail)
- todo_items: [10][96:0]u8 = [_][96:0]u8{[_:0]u8{0} ** 96} ** 10,
- todo_statuses: [10]u8 = [_]u8{0} ** 10, // 0=none, 1=pending, 2=in_progress, 3=completed
- todo_count: usize = 0,
- // Per-agent poll timer (staggered)
- update_timer: f32 = 0,
- // Unified chat dialog messages (chronologically sorted)
- chat_msgs: [50]ChatMsg = [_]ChatMsg{ChatMsg{}} ** 50,
- chat_count: usize = 0,
- chat_built_log_mt: i64 = 0,
- chat_built_live_mt: i64 = 0,
-};
-
-// ββ Unified Chat Message for merged agent dialog ββ
-const ChatSender = enum { loop, claude };
-const ChatMsgKind = enum { log_line, claude_result, task_list, meta_info };
-
-const ChatMsg = struct {
- sender: ChatSender = .loop,
- kind: ChatMsgKind = .log_line,
- timestamp: i64 = 0,
- text: [256:0]u8 = [_:0]u8{0} ** 256,
- text_len: usize = 0,
- result_offset: usize = 0,
- result_len: usize = 0,
- todo_count: usize = 0,
- tag_r: u8 = 0xBB,
- tag_g: u8 = 0xBB,
- tag_b: u8 = 0xBB,
- show_full: bool = false,
-};
-
-var g_ralph_agents: [MAX_RALPH_AGENTS]RalphAgent = [_]RalphAgent{RalphAgent{}} ** MAX_RALPH_AGENTS;
-
-var g_ralph_agent_count: usize = 0;
-var g_ralph_active_tab: usize = 0;
-var g_ralph_prev_tab: usize = 0;
-var g_ralph_initialized: bool = false;
-// Unified chat scroll state
-var g_ralph_chat_scroll_y: f32 = 0;
-var g_ralph_chat_scroll_target: f32 = 0;
-var g_ralph_prev_chat_count: usize = 0;
-var g_ralph_prev_result_len: usize = 0;
-
-// ββ v8.1: Collapsible section state ββ
-const MAX_SECTIONS_PER_MSG = 16;
-var g_ralph_section_collapsed: [MAX_RALPH_AGENTS][50][MAX_SECTIONS_PER_MSG]bool =
- [_][50][MAX_SECTIONS_PER_MSG]bool{
- [_][MAX_SECTIONS_PER_MSG]bool{[_]bool{false} ** MAX_SECTIONS_PER_MSG} ** 50,
- } ** MAX_RALPH_AGENTS;
-var g_ralph_section_anim: [MAX_RALPH_AGENTS][50][MAX_SECTIONS_PER_MSG]f32 =
- [_][50][MAX_SECTIONS_PER_MSG]f32{
- [_][MAX_SECTIONS_PER_MSG]f32{[_]f32{1.0} ** MAX_SECTIONS_PER_MSG} ** 50,
- } ** MAX_RALPH_AGENTS;
-var g_ralph_msg_prev_rlen: [MAX_RALPH_AGENTS][50]usize =
- [_][50]usize{[_]usize{0} ** 50} ** MAX_RALPH_AGENTS;
-
-fn setAgentIdentity(agent: *RalphAgent, name: []const u8, branch: []const u8) void {
- const nl = @min(name.len, 31);
- @memcpy(agent.name[0..nl], name[0..nl]);
- agent.name_len = nl;
- const bl = @min(branch.len, 63);
- @memcpy(agent.branch[0..bl], branch[0..bl]);
- agent.branch_len = bl;
-}
-
-// Dynamic worktree paths (discovered at runtime from .git/worktrees/)
-var g_ralph_worktree_paths: [MAX_RALPH_AGENTS][256]u8 = undefined;
-var g_ralph_worktree_path_lens: [MAX_RALPH_AGENTS]usize = [_]usize{0} ** MAX_RALPH_AGENTS;
-
-fn getWorktreePath(ai: usize) []const u8 {
- if (ai >= g_ralph_agent_count) return "";
- return g_ralph_worktree_paths[ai][0..g_ralph_worktree_path_lens[ai]];
-}
-
-// βββ Ralph Process Control (tmux commands) βββ
-const RalphCmd = enum { none, start, stop, restart };
-var g_ralph_pending_cmd: RalphCmd = .none;
-var g_ralph_tmux_session: [64]u8 = [_]u8{0} ** 64;
-var g_ralph_tmux_session_len: usize = 0;
-
-// v8.1.1: Hybrid mode β track external ralph_loop.sh process
-var g_ralph_loop_pid: i32 = 0;
-var g_ralph_tmux_loop_running: bool = false;
-var g_ralph_last_pid_check: f64 = 0;
-
-/// Discover the ralph tmux session name (ralph-XXXXXXXXXX) β picks newest (last sorted)
-fn ralphDiscoverTmuxSession() void {
- const allocator = std.heap.page_allocator;
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", "tmux list-sessions -F '#{session_name}' 2>/dev/null | grep '^ralph-' | sort -r | head -1" },
- }) catch return;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
- const out = std.mem.trimRight(u8, result.stdout, "\n\r \t");
- if (out.len > 0 and out.len < 64) {
- @memcpy(g_ralph_tmux_session[0..out.len], out);
- g_ralph_tmux_session_len = out.len;
- std.debug.print("[RALPH] discovered tmux session: {s}\n", .{g_ralph_tmux_session[0..out.len]});
- } else {
- std.debug.print("[RALPH] no tmux session found\n", .{});
- }
-}
-
-/// Find PID of external ralph_loop.sh process (v8.1.1 hybrid mode)
-fn ralphFindLoopPid() i32 {
- const allocator = std.heap.page_allocator;
- // pgrep returns multiple PIDs, take the first one (newest)
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", "pgrep -f 'ralph_loop.sh' 2>/dev/null | head -1" },
- }) catch return 0;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
- const out = std.mem.trimRight(u8, result.stdout, "\n\r \t");
- if (out.len > 0) {
- const pid = std.fmt.parseInt(i32, out, 10) catch 0;
- if (pid > 0) {
- std.debug.print("[RALPH] found external loop PID: {}\n", .{pid});
- return pid;
- }
- }
- return 0;
-}
-
-/// Check if ralph is running INSIDE tmux pane (v8.1.1 hybrid mode)
-fn ralphCheckTmuxLoop() bool {
- if (g_ralph_tmux_session_len == 0) return false;
- const sess = g_ralph_tmux_session[0..g_ralph_tmux_session_len];
- const allocator = std.heap.page_allocator;
-
- // Get pane PID for pane 1.1
- var buf: [128]u8 = undefined;
- const cmd = std.fmt.bufPrint(&buf, "tmux list-panes -t '{s}:1.1' -F '{{pane_pid}}' 2>/dev/null", .{sess}) catch return false;
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", cmd },
- }) catch return false;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
- const pane_pid_str = std.mem.trimRight(u8, result.stdout, "\n\r \t");
- if (pane_pid_str.len == 0) return false;
-
- const pane_pid = std.fmt.parseInt(i32, pane_pid_str, 10) catch return false;
- if (pane_pid <= 0) return false;
-
- // Check if that process has 'ralph' in its command line
- var buf2: [256]u8 = undefined;
- const cmd2 = std.fmt.bufPrint(&buf2, "ps -p {} -o command= 2>/dev/null | grep -q ralph", .{pane_pid}) catch return false;
- const result2 = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", cmd2 },
- }) catch return false;
- defer allocator.free(result2.stdout);
- defer allocator.free(result2.stderr);
-
- const running = (switch (result2.term) {
- .Exited => |code| code,
- else => @as(u32, 1),
- }) == 0;
- if (running) {
- std.debug.print("[RALPH] tmux pane has ralph running (PID {})\n", .{pane_pid});
- }
- return running;
-}
-
-/// Update ralph loop detection state (call periodically)
-fn ralphUpdateLoopState() void {
- const now = rl.GetTime();
- // Check every 2 seconds
- if (now - g_ralph_last_pid_check < 2.0) return;
- g_ralph_last_pid_check = now;
-
- g_ralph_loop_pid = ralphFindLoopPid();
- g_ralph_tmux_loop_running = ralphCheckTmuxLoop();
-}
-
-/// Quick check if any ralph_loop.sh process is actually running (v8.1.1 fix)
-/// Used to override status.json when processes are killed but file not updated
-fn ralphProcessRunning() bool {
- const allocator = std.heap.page_allocator;
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", "pgrep -f 'ralph_loop.sh' 2>/dev/null | head -1" },
- }) catch return false;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
- const out = std.mem.trimRight(u8, result.stdout, "\n\r \t");
- return out.len > 0;
-}
-
-/// Execute pending ralph command (v8.1.1: hybrid mode β PID signals OR tmux)
-fn ralphExecPendingCmd() void {
- const cmd = g_ralph_pending_cmd;
- if (cmd == .none) return;
- std.debug.print("[RALPH] executing cmd: {s}\n", .{if (cmd == .start) "START" else if (cmd == .stop) "STOP" else if (cmd == .restart) "RESTART" else "NONE"});
- g_ralph_pending_cmd = .none;
-
- // Update detection state
- ralphUpdateLoopState();
-
- const allocator = std.heap.page_allocator;
-
- // Hybrid mode: external process takes priority
- if (g_ralph_loop_pid > 0) {
- std.debug.print("[RALPH] STOP: killing external process (PID {})\n", .{g_ralph_loop_pid});
- switch (cmd) {
- .stop => {
- // v8.1.1 fix: Kill monitor, loop processes, AND all their children
- // First kill children, then parents (to avoid orphans)
- const sh_cmd = "pgrep -f 'ralph_loop.sh' 2>/dev/null | xargs -r pkill -9 -P 2>/dev/null; pkill -9 -f 'ralph_monitor.sh' 2>/dev/null; pkill -9 -f 'ralph_loop.sh' 2>/dev/null";
- _ = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", sh_cmd },
- }) catch {};
- },
- .start => {
- // Already running, just log
- std.debug.print("[RALPH] START: already running (PID {})\n", .{g_ralph_loop_pid});
- },
- .restart => {
- // v8.1.1 fix: Kill children first, then parents (same as STOP)
- const cmd1 = "pgrep -f 'ralph_loop.sh' 2>/dev/null | xargs -r pkill -9 -P 2>/dev/null; pkill -9 -f 'ralph_monitor.sh' 2>/dev/null; pkill -9 -f 'ralph_loop.sh' 2>/dev/null; sleep 1";
- _ = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", cmd1 },
- }) catch {};
- std.debug.print("[RALPH] RESTART: killed processes, will restart\n", .{});
- },
- .none => {},
- }
- return;
- }
-
- // Fallback: tmux mode (if tmux loop is running or session exists)
- if (g_ralph_tmux_loop_running or g_ralph_tmux_session_len > 0) {
- std.debug.print("[RALPH] using tmux mode\n", .{});
- if (g_ralph_tmux_session_len == 0) ralphDiscoverTmuxSession();
- if (g_ralph_tmux_session_len == 0) return; // no tmux session
-
- const sess = g_ralph_tmux_session[0..g_ralph_tmux_session_len];
-
- switch (cmd) {
- .stop => {
- var buf: [128]u8 = undefined;
- const sh_cmd = std.fmt.bufPrint(&buf, "tmux send-keys -t '{s}:1.1' C-c 2>/dev/null", .{sess}) catch return;
- _ = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", buf[0..sh_cmd.len] },
- }) catch {};
- },
- .start => {
- var buf: [128]u8 = undefined;
- const sh_cmd = std.fmt.bufPrint(&buf, "tmux send-keys -t '{s}:1.1' 'ralph' Enter 2>/dev/null", .{sess}) catch return;
- _ = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", buf[0..sh_cmd.len] },
- }) catch {};
- },
- .restart => {
- var buf1: [128]u8 = undefined;
- const cmd1 = std.fmt.bufPrint(&buf1, "tmux send-keys -t '{s}:1.1' C-c 2>/dev/null; sleep 1; tmux send-keys -t '{s}:1.1' 'ralph' Enter 2>/dev/null", .{ sess, sess }) catch return;
- _ = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", buf1[0..cmd1.len] },
- }) catch {};
- },
- .none => {},
- }
- return;
- }
-
- std.debug.print("[RALPH] no ralph loop found to control\n", .{});
-}
-
-/// Read a git HEAD file and extract the branch name (strip "ref: refs/heads/")
-fn readGitBranch(head_path: [:0]const u8, out: []u8) usize {
- const file = std.fs.openFileAbsolute(head_path, .{}) catch return 0;
- defer file.close();
- var buf: [256]u8 = undefined;
- const n = file.readAll(&buf) catch return 0;
- if (n == 0) return 0;
- // Strip trailing newline/whitespace
- var end: usize = n;
- while (end > 0 and (buf[end - 1] == '\n' or buf[end - 1] == '\r' or buf[end - 1] == ' ')) end -= 1;
- const line = buf[0..end];
- const prefix = "ref: refs/heads/";
- const branch = if (std.mem.startsWith(u8, line, prefix)) line[prefix.len..] else line;
- const len = @min(branch.len, out.len);
- @memcpy(out[0..len], branch[0..len]);
- return len;
-}
-
-fn initRalphAgents() void {
- if (g_ralph_initialized) return;
- g_ralph_initialized = true;
-
- // Zero all paths
- for (&g_ralph_worktree_paths) |*p| @memset(p, 0);
-
- // Agent 0 = main repo (cwd)
- const main_path = "/Users/playra/trinity";
- const main_len = main_path.len;
- @memcpy(g_ralph_worktree_paths[0][0..main_len], main_path);
- g_ralph_worktree_path_lens[0] = main_len;
-
- // Read main repo branch from .git/HEAD
- var branch_buf: [64]u8 = undefined;
- @memset(&branch_buf, 0);
- const branch_len = readGitBranch("/Users/playra/trinity/.git/HEAD", &branch_buf);
- const main_branch = if (branch_len > 0) branch_buf[0..branch_len] else "main";
- setAgentIdentity(&g_ralph_agents[0], "trinity", main_branch);
- g_ralph_agents[0].update_timer = 0.0;
- g_ralph_agent_count = 1;
-
- // Discover additional worktrees from .git/worktrees/
- const wt_dir = std.fs.openDirAbsolute("/Users/playra/trinity/.git/worktrees", .{ .iterate = true }) catch {
- return; // No worktrees dir β single repo mode
- };
- // Need mutable for iteration
- var wt_dir_m = wt_dir;
- defer wt_dir_m.close();
- var iter = wt_dir_m.iterate();
- while (iter.next() catch null) |entry| {
- if (g_ralph_agent_count >= MAX_RALPH_AGENTS) break;
- if (entry.kind != .directory) continue;
-
- const ai = g_ralph_agent_count;
- var gitdir_path_buf: [256]u8 = undefined;
- @memset(&gitdir_path_buf, 0);
- const gitdir_path = std.fmt.bufPrint(&gitdir_path_buf, "/Users/playra/trinity/.git/worktrees/{s}/gitdir", .{entry.name}) catch continue;
-
- // Read gitdir to get worktree path (contains "/.git\n")
- const gf = std.fs.openFileAbsolute(gitdir_path_buf[0..gitdir_path.len :0], .{}) catch continue;
- defer gf.close();
- var gd_buf: [256]u8 = undefined;
- const gd_n = gf.readAll(&gd_buf) catch continue;
- if (gd_n < 5) continue;
-
- // Strip trailing whitespace and "/.git" suffix
- var gd_end: usize = gd_n;
- while (gd_end > 0 and (gd_buf[gd_end - 1] == '\n' or gd_buf[gd_end - 1] == '\r' or gd_buf[gd_end - 1] == ' ')) gd_end -= 1;
- const gd_line = gd_buf[0..gd_end];
- const wt_path = if (std.mem.endsWith(u8, gd_line, "/.git")) gd_line[0 .. gd_line.len - 5] else gd_line;
- if (wt_path.len == 0 or wt_path.len >= 256) continue;
-
- @memcpy(g_ralph_worktree_paths[ai][0..wt_path.len], wt_path);
- g_ralph_worktree_path_lens[ai] = wt_path.len;
-
- // Read branch from .git/worktrees//HEAD
- var head_path_buf: [256]u8 = undefined;
- @memset(&head_path_buf, 0);
- const head_path = std.fmt.bufPrint(&head_path_buf, "/Users/playra/trinity/.git/worktrees/{s}/HEAD", .{entry.name}) catch continue;
-
- @memset(&branch_buf, 0);
- const wt_branch_len = readGitBranch(head_path_buf[0..head_path.len :0], &branch_buf);
- const wt_branch = if (wt_branch_len > 0) branch_buf[0..wt_branch_len] else entry.name;
-
- setAgentIdentity(&g_ralph_agents[ai], entry.name, wt_branch);
- g_ralph_agents[ai].update_timer = @as(f32, @floatFromInt(ai)) * 0.5; // Stagger polls
- g_ralph_agent_count += 1;
- }
-
- // Discover ralph tmux session for process control
- ralphDiscoverTmuxSession();
-}
-
-/// Desktop-only: Read .ralph/ files directly from worktree filesystem
-fn pollRalphAgentDesktop(ai: usize) void {
- if (ai >= g_ralph_agent_count) return;
- const agent = &g_ralph_agents[ai];
- const base_path = getWorktreePath(ai);
-
- std.debug.print("[POLL ai={d}] base_path={s}\n", .{ ai, base_path });
-
- var path_buf: [256]u8 = undefined;
- @memset(&path_buf, 0);
-
- // Read status_report.json
- {
- const sr_path = std.fmt.bufPrint(&path_buf, "{s}/.ralph/status_report.json", .{base_path}) catch return;
- const file = std.fs.openFileAbsolute(path_buf[0..sr_path.len :0], .{}) catch {
- std.debug.print("[POLL ai={d}] status_report.json NOT FOUND - unreachable\n", .{ai});
- agent.reachable = false;
- return;
- };
- defer file.close();
- agent.reachable = true;
-
- var read_buf: [4096]u8 = undefined;
- const bytes_read = file.readAll(&read_buf) catch 0;
- if (bytes_read < 10) return;
- const json = read_buf[0..bytes_read];
-
- // Parse circuit_breaker.state
- if (std.mem.indexOf(u8, json, "\"state\":")) |idx| {
- const after = json[@min(idx + 9, json.len)..];
- if (std.mem.indexOf(u8, after, "\"")) |q1| {
- const val_start = q1 + 1;
- if (std.mem.indexOfScalar(u8, after[val_start..], '"')) |q2| {
- const val = after[val_start .. val_start + q2];
- if (std.mem.eql(u8, val, "CLOSED")) {
- agent.cb_state = .closed;
- agent.is_healthy = true;
- } else if (std.mem.eql(u8, val, "OPEN")) {
- agent.cb_state = .cb_open;
- agent.is_healthy = false;
- } else {
- agent.cb_state = .degraded;
- agent.is_healthy = false;
- }
- }
- }
- }
-
- // Parse circuit_breaker.loop
- if (std.mem.indexOf(u8, json, "\"loop\":")) |idx| {
- var start = idx + 7;
- while (start < json.len and (json[start] == ' ' or json[start] == '\t' or json[start] == '\n' or json[start] == '\r')) start += 1;
- var end = start;
- while (end < json.len and json[end] >= '0' and json[end] <= '9') end += 1;
- if (end > start) {
- agent.loop = std.fmt.parseInt(usize, json[start..end], 10) catch agent.loop;
- }
- }
-
- // Parse session.call_count as total_calls
- if (std.mem.indexOf(u8, json, "\"call_count\":")) |idx| {
- var start = idx + 13;
- while (start < json.len and (json[start] == ' ' or json[start] == '\t' or json[start] == '\n' or json[start] == '\r')) start += 1;
- var end = start;
- while (end < json.len and json[end] >= '0' and json[end] <= '9') end += 1;
- if (end > start) {
- agent.total_calls = std.fmt.parseInt(usize, json[start..end], 10) catch agent.total_calls;
- }
- }
-
- // Parse active_task as goal
- if (std.mem.indexOf(u8, json, "\"active_task\":")) |idx| {
- const after = json[@min(idx + 14, json.len)..];
- if (std.mem.indexOf(u8, after, "\"")) |q1| {
- const val_start = q1 + 1;
- if (std.mem.indexOfScalar(u8, after[val_start..], '"')) |q2| {
- const val = after[val_start .. val_start + q2];
- const len = @min(val.len, 127);
- @memcpy(agent.goal[0..len], val[0..len]);
- agent.goal[len] = 0;
- agent.goal_len = len;
- }
- }
- }
-
- // Parse progress.status
- if (std.mem.indexOf(u8, json, "\"status\":")) |idx| {
- const after = json[@min(idx + 9, json.len)..];
- if (std.mem.indexOf(u8, after, "\"")) |q1| {
- const val_start = q1 + 1;
- if (std.mem.indexOfScalar(u8, after[val_start..], '"')) |q2| {
- const val = after[val_start .. val_start + q2];
- const len = @min(val.len, 31);
- @memcpy(agent.progress_status[0..len], val[0..len]);
- agent.progress_status[len] = 0;
- agent.progress_status_len = len;
- }
- }
- }
-
- // Count recent_commits
- {
- var count: usize = 0;
- if (std.mem.indexOf(u8, json, "\"recent_commits\":")) |idx| {
- const after = json[@min(idx + 17, json.len)..];
- for (after) |ch| {
- if (ch == '"') count += 1;
- if (ch == ']') break;
- }
- agent.recent_commits_count = count / 2;
- }
- }
-
- agent.running = (agent.loop > 0);
- std.debug.print("[POLL ai={d}] status_report: cb={s} loop={d} calls={d} goal_len={d}\n", .{
- ai,
- if (agent.cb_state == .closed) "CLOSED" else if (agent.cb_state == .cb_open) "OPEN" else "DEGRADED",
- agent.loop,
- agent.total_calls,
- agent.goal_len,
- });
- }
-
- // Read .ralph/internal/.circuit_breaker_state for current_loop (more accurate)
- {
- @memset(&path_buf, 0);
- const cb_path = std.fmt.bufPrint(&path_buf, "{s}/.ralph/internal/.circuit_breaker_state", .{base_path}) catch "";
- if (cb_path.len > 0) {
- if (std.fs.openFileAbsolute(path_buf[0..cb_path.len :0], .{})) |f| {
- defer f.close();
- var cb_buf: [1024]u8 = undefined;
- const bytes = f.readAll(&cb_buf) catch 0;
- if (bytes > 10) {
- const cb_json = cb_buf[0..bytes];
- if (std.mem.indexOf(u8, cb_json, "\"current_loop\":")) |idx| {
- var start = idx + 15;
- while (start < cb_json.len and (cb_json[start] == ' ' or cb_json[start] == '\t' or cb_json[start] == '\n' or cb_json[start] == '\r')) start += 1;
- var end = start;
- while (end < cb_json.len and cb_json[end] >= '0' and cb_json[end] <= '9') end += 1;
- if (end > start) {
- agent.loop = std.fmt.parseInt(usize, cb_json[start..end], 10) catch agent.loop;
- agent.running = true;
- }
- }
- }
- } else |_| {}
- }
- }
-
- // Read last N lines of .ralph/logs/ralph.log (Left pane: Ralph Loop output)
- {
- @memset(&path_buf, 0);
- const log_path = std.fmt.bufPrint(&path_buf, "{s}/.ralph/logs/ralph.log", .{base_path}) catch return;
- const file = std.fs.openFileAbsolute(path_buf[0..log_path.len :0], .{}) catch return;
- defer file.close();
-
- // Track file modification time
- if (file.stat()) |st| {
- agent.log_mtime = @intCast(@divFloor(st.mtime, std.time.ns_per_s));
- std.debug.print("[POLL ai={d}] ralph.log mtime={d}\n", .{ ai, agent.log_mtime });
- } else |_| {}
-
- const file_size = file.getEndPos() catch 0;
- if (file_size > 8192) {
- file.seekTo(file_size - 8192) catch {};
- }
-
- var log_buf: [8192]u8 = undefined;
- const bytes = file.readAll(&log_buf) catch 0;
- if (bytes == 0) return;
- const content = log_buf[0..bytes];
-
- // Find line boundaries, keep last 30
- var line_starts: [31]usize = undefined;
- var line_count: usize = 0;
- line_starts[0] = 0;
- line_count = 1;
- for (content, 0..) |c, ci| {
- if (c == '\n' and ci + 1 < content.len) {
- if (line_count < 31) {
- line_starts[line_count] = ci + 1;
- line_count += 1;
- } else {
- for (0..30) |si| {
- line_starts[si] = line_starts[si + 1];
- }
- line_starts[30] = ci + 1;
- }
- }
- }
-
- const first_line = if (line_count > 30) line_count - 30 else 0;
- var li: usize = 0;
- var si: usize = first_line;
- while (si < line_count and li < 30) {
- const start = line_starts[si];
- const end_pos = if (si + 1 < line_count) line_starts[si + 1] -| 1 else content.len;
- const end = if (end_pos > start and content[end_pos - 1] == '\r') end_pos - 1 else end_pos;
- if (end > start) {
- const line_data = content[start..end];
- const len = @min(line_data.len, 127);
- @memset(&agent.logs[li], 0);
- @memcpy(agent.logs[li][0..len], line_data[0..len]);
- } else {
- agent.logs[li][0] = 0;
- }
- si += 1;
- li += 1;
- }
- agent.log_count = li;
- }
-
- // Read latest .ralph/logs/claude_output_*.log (Right-Top: Claude Code result)
- // Find latest non-stream log by scanning directory for newest timestamp in filename
- {
- @memset(&path_buf, 0);
- const logs_dir_path = std.fmt.bufPrint(&path_buf, "{s}/.ralph/logs", .{base_path}) catch return;
- if (std.fs.openDirAbsolute(logs_dir_path[0..logs_dir_path.len], .{})) |dir_handle| {
- var dir = dir_handle;
- defer dir.close();
- // Find newest and second-newest claude_output_*.log (not _stream.log)
- var newest_name: [64]u8 = undefined;
- var newest_len: usize = 0;
- var second_name: [64]u8 = undefined;
- var second_len: usize = 0;
- var iter = dir.iterate();
- while (iter.next() catch null) |entry| {
- if (entry.kind != .file) continue;
- const name = entry.name;
- if (!std.mem.startsWith(u8, name, "claude_output_")) continue;
- if (std.mem.endsWith(u8, name, "_stream.log")) continue;
- if (!std.mem.endsWith(u8, name, ".log")) continue;
- // Lexicographic compare: later timestamp = larger string
- if (name.len <= 63 and (newest_len == 0 or std.mem.order(u8, name[0..name.len], newest_name[0..newest_len]) == .gt)) {
- // Demote current newest to second
- if (newest_len > 0) {
- @memcpy(second_name[0..newest_len], newest_name[0..newest_len]);
- second_len = newest_len;
- }
- @memcpy(newest_name[0..name.len], name[0..name.len]);
- newest_len = name.len;
- } else if (name.len <= 63 and (second_len == 0 or std.mem.order(u8, name[0..name.len], second_name[0..second_len]) == .gt)) {
- @memcpy(second_name[0..name.len], name[0..name.len]);
- second_len = name.len;
- }
- }
- // Try newest file, fall back to second-newest if newest is empty
- const candidates = [_]struct { name: []const u8 }{
- .{ .name = if (newest_len > 0) newest_name[0..newest_len] else "" },
- .{ .name = if (second_len > 0) second_name[0..second_len] else "" },
- };
- var parsed_output = false;
- for (&candidates) |cand| {
- if (cand.name.len == 0 or parsed_output) continue;
- var full_path: [320]u8 = undefined;
- @memset(&full_path, 0);
- const fp = std.fmt.bufPrint(&full_path, "{s}/.ralph/logs/{s}", .{ base_path, cand.name }) catch "";
- if (fp.len == 0) continue;
- const f = std.fs.openFileAbsolute(full_path[0..fp.len :0], .{}) catch continue;
- defer f.close();
- // Track mtime (from newest candidate only)
- if (!parsed_output) {
- if (f.stat()) |st| {
- agent.live_mtime = @intCast(@divFloor(st.mtime, std.time.ns_per_s));
- } else |_| {}
- }
- // Read last 4KB (the JSON result is at end of file)
- const fsize = f.getEndPos() catch 0;
- if (fsize > 4096) f.seekTo(fsize - 4096) catch {};
- var out_buf: [4096]u8 = undefined;
- const bytes = f.readAll(&out_buf) catch 0;
- if (bytes <= 10) continue; // Empty β try next candidate
- parsed_output = true;
- const json = out_buf[0..bytes];
-
- // Parse "result":"..." β extract first 500 chars
- if (std.mem.indexOf(u8, json, "\"result\":\"")) |idx| {
- const vs = idx + 10;
- // Find closing quote (handle escaped quotes)
- var end_q: usize = vs;
- while (end_q < json.len) {
- if (json[end_q] == '\\' and end_q + 1 < json.len) {
- end_q += 2;
- continue;
- }
- if (json[end_q] == '"') break;
- end_q += 1;
- }
- const val = json[vs..end_q];
- const rlen = @min(val.len, 4095);
- @memset(&agent.live_result, 0);
- // Copy with ASCII sanitization (replace non-ASCII with -)
- for (0..rlen) |ci| {
- agent.live_result[ci] = if (val[ci] >= 0x80) '-' else val[ci];
- }
- agent.live_result_len = rlen;
- }
-
- // Parse "is_error":true/false
- agent.live_is_error = std.mem.indexOf(u8, json, "\"is_error\":true") != null;
-
- // Parse "num_turns":N
- if (std.mem.indexOf(u8, json, "\"num_turns\":")) |idx| {
- var start = idx + 12;
- while (start < json.len and json[start] == ' ') start += 1;
- var end_n: usize = start;
- while (end_n < json.len and json[end_n] >= '0' and json[end_n] <= '9') end_n += 1;
- if (end_n > start) agent.live_num_turns = std.fmt.parseInt(usize, json[start..end_n], 10) catch 0;
- }
-
- // Parse "duration_ms":N
- if (std.mem.indexOf(u8, json, "\"duration_ms\":")) |idx| {
- var start = idx + 14;
- while (start < json.len and json[start] == ' ') start += 1;
- var end_n: usize = start;
- while (end_n < json.len and json[end_n] >= '0' and json[end_n] <= '9') end_n += 1;
- if (end_n > start) agent.live_duration_ms = std.fmt.parseInt(usize, json[start..end_n], 10) catch 0;
- }
-
- // Parse "total_cost_usd":N.NN
- if (std.mem.indexOf(u8, json, "\"total_cost_usd\":")) |idx| {
- var start = idx + 17;
- while (start < json.len and json[start] == ' ') start += 1;
- var end_n: usize = start;
- while (end_n < json.len and (json[end_n] >= '0' and json[end_n] <= '9' or json[end_n] == '.')) end_n += 1;
- if (end_n > start) {
- const val = json[start..end_n];
- const clen = @min(val.len, 15);
- @memset(&agent.live_cost_usd, 0);
- @memcpy(agent.live_cost_usd[0..clen], val[0..clen]);
- agent.live_cost_len = clen;
- }
- }
-
- // Parse TodoWrite from log tail (last 16KB for last "todos":[)
- {
- agent.todo_count = 0;
- for (&agent.todo_items) |*item| @memset(item, 0);
- @memset(&agent.todo_statuses, 0);
- f.seekTo(if (fsize > 16384) fsize - 16384 else 0) catch {};
- var todo_buf: [16384]u8 = undefined;
- const tbytes = f.readAll(&todo_buf) catch 0;
- if (tbytes > 20) {
- const tdata = todo_buf[0..tbytes];
- // Find LAST occurrence of "todos":[{
- var last_todos_pos: ?usize = null;
- var search_pos: usize = 0;
- while (search_pos < tdata.len) {
- if (std.mem.indexOf(u8, tdata[search_pos..], "\"todos\":[{")) |found| {
- last_todos_pos = search_pos + found;
- search_pos = search_pos + found + 10;
- } else break;
- }
- if (last_todos_pos) |tp| {
- var tpos = tp + 9; // skip "todos":[
- while (tpos < tdata.len and agent.todo_count < 10) {
- // Find "content":"
- if (std.mem.indexOf(u8, tdata[tpos..], "\"content\":\"")) |ci| {
- const cs = tpos + ci + 11;
- if (cs < tdata.len) {
- if (std.mem.indexOfScalar(u8, tdata[cs..@min(cs + 96, tdata.len)], '"')) |ce| {
- const clen = @min(ce, 95);
- @memcpy(agent.todo_items[agent.todo_count][0..clen], tdata[cs .. cs + clen]);
- }
- }
- // Find "status":"
- const sbase = tpos + ci;
- if (std.mem.indexOf(u8, tdata[sbase..@min(sbase + 200, tdata.len)], "\"status\":\"")) |si| {
- const ss = sbase + si + 10;
- if (ss < tdata.len) {
- if (std.mem.indexOfScalar(u8, tdata[ss..@min(ss + 20, tdata.len)], '"')) |se| {
- const status = tdata[ss .. ss + se];
- if (std.mem.eql(u8, status, "completed")) {
- agent.todo_statuses[agent.todo_count] = 3;
- } else if (std.mem.eql(u8, status, "in_progress")) {
- agent.todo_statuses[agent.todo_count] = 2;
- } else {
- agent.todo_statuses[agent.todo_count] = 1;
- }
- }
- }
- }
- agent.todo_count += 1;
- tpos = tpos + ci + 20;
- } else break;
- }
- }
- }
- }
- }
- std.debug.print("[POLL ai={d}] claude_output: parsed={} newest_len={d} second_len={d} result_len={d} is_error={}\n", .{
- ai, parsed_output, newest_len, second_len, agent.live_result_len, agent.live_is_error,
- });
- // Always read live.log β if it's NEWER than claude_output, use streaming content
- {
- var live_path: [320]u8 = undefined;
- @memset(&live_path, 0);
- const lp = std.fmt.bufPrint(&live_path, "{s}/.ralph/logs/live.log", .{base_path}) catch "";
- if (lp.len > 0) {
- if (std.fs.openFileAbsolute(live_path[0..lp.len :0], .{})) |lf| {
- defer lf.close();
- var live_log_mtime: i64 = 0;
- if (lf.stat()) |st| {
- live_log_mtime = @intCast(@divFloor(st.mtime, std.time.ns_per_s));
- } else |_| {}
- // Read last 8KB of live.log (streaming text, not JSON)
- const fsize = lf.getEndPos() catch 0;
- if (fsize > 8192) lf.seekTo(fsize - 8192) catch {};
- var lb: [8192]u8 = undefined;
- const lb_n = lf.readAll(&lb) catch 0;
- // Always use live.log if it has any content β eliminates stale data during loop transitions
- if (lb_n > 10) {
- const raw = lb[0..lb_n];
- var start: usize = 0;
- if (fsize > 8192) {
- if (std.mem.indexOfScalar(u8, raw, '\n')) |nl| {
- start = nl + 1;
- }
- }
- if (start < raw.len) {
- const text = raw[start..];
- var wi: usize = 0;
- var ri: usize = 0;
- @memset(&agent.live_result, 0);
- while (ri < text.len and wi < 4090) {
- if (text[ri] == '\n') {
- agent.live_result[wi] = '\\';
- agent.live_result[wi + 1] = 'n';
- wi += 2;
- } else if (text[ri] >= 0x80) {
- agent.live_result[wi] = '-';
- wi += 1;
- } else {
- agent.live_result[wi] = text[ri];
- wi += 1;
- }
- ri += 1;
- }
- agent.live_result_len = wi;
- agent.live_mtime = live_log_mtime;
- agent.live_is_error = false;
- // Clear stale metrics from old completed result
- agent.live_num_turns = 0;
- agent.live_duration_ms = 0;
- agent.live_cost_len = 0;
- std.debug.print("[POLL ai={d}] live.log STREAMING: {d} bytes, mtime={d}\n", .{ ai, lb_n, live_log_mtime });
- }
- }
- } else |_| {}
- }
- }
- } else |_| {}
- }
-
- // Read .ralph/logs/status.json (Right-Bottom pane: Status Monitor data)
- {
- @memset(&path_buf, 0);
- const st_path = std.fmt.bufPrint(&path_buf, "{s}/.ralph/logs/status.json", .{base_path}) catch return;
- if (std.fs.openFileAbsolute(path_buf[0..st_path.len :0], .{})) |file| {
- defer file.close();
- // Track mtime
- if (file.stat()) |st| {
- agent.status_mtime = @intCast(@divFloor(st.mtime, std.time.ns_per_s));
- } else |_| {}
- var st_buf: [2048]u8 = undefined;
- const bytes = file.readAll(&st_buf) catch 0;
- if (bytes > 10) {
- const json = st_buf[0..bytes];
-
- // Parse loop_count
- if (std.mem.indexOf(u8, json, "\"loop_count\":")) |idx| {
- var start = idx + 13;
- while (start < json.len and (json[start] == ' ' or json[start] == '\t')) start += 1;
- var end = start;
- while (end < json.len and json[end] >= '0' and json[end] <= '9') end += 1;
- if (end > start) agent.loop_count_status = std.fmt.parseInt(usize, json[start..end], 10) catch 0;
- }
-
- // Parse calls_made_this_hour
- if (std.mem.indexOf(u8, json, "\"calls_made_this_hour\":")) |idx| {
- var start = idx + 22;
- while (start < json.len and (json[start] == ' ' or json[start] == '\t')) start += 1;
- var end = start;
- while (end < json.len and json[end] >= '0' and json[end] <= '9') end += 1;
- if (end > start) agent.calls_this_hour = std.fmt.parseInt(usize, json[start..end], 10) catch 0;
- }
-
- // Parse max_calls_per_hour
- if (std.mem.indexOf(u8, json, "\"max_calls_per_hour\":")) |idx| {
- var start = idx + 20;
- while (start < json.len and (json[start] == ' ' or json[start] == '\t')) start += 1;
- var end = start;
- while (end < json.len and json[end] >= '0' and json[end] <= '9') end += 1;
- if (end > start) agent.max_calls_hour = std.fmt.parseInt(usize, json[start..end], 10) catch 100;
- }
-
- // Parse status string
- if (std.mem.indexOf(u8, json, "\"status\":")) |idx| {
- const after = json[@min(idx + 9, json.len)..];
- if (std.mem.indexOf(u8, after, "\"")) |q1| {
- const vs = q1 + 1;
- if (std.mem.indexOfScalar(u8, after[vs..], '"')) |q2| {
- const val = after[vs .. vs + q2];
- const len = @min(val.len, 31);
- @memset(&agent.status_text, 0);
- @memcpy(agent.status_text[0..len], val[0..len]);
- agent.status_text_len = len;
- }
- }
- }
-
- // Parse last_action
- if (std.mem.indexOf(u8, json, "\"last_action\":")) |idx| {
- const after = json[@min(idx + 14, json.len)..];
- if (std.mem.indexOf(u8, after, "\"")) |q1| {
- const vs = q1 + 1;
- if (std.mem.indexOfScalar(u8, after[vs..], '"')) |q2| {
- const val = after[vs .. vs + q2];
- const len = @min(val.len, 63);
- @memset(&agent.last_action, 0);
- @memcpy(agent.last_action[0..len], val[0..len]);
- agent.last_action_len = len;
- // Detect active execution
- agent.is_executing = std.mem.eql(u8, val, "executing");
- }
- }
- }
-
- // Parse next_reset
- if (std.mem.indexOf(u8, json, "\"next_reset\":")) |idx| {
- const after = json[@min(idx + 13, json.len)..];
- if (std.mem.indexOf(u8, after, "\"")) |q1| {
- const vs = q1 + 1;
- if (std.mem.indexOfScalar(u8, after[vs..], '"')) |q2| {
- const val = after[vs .. vs + q2];
- const len = @min(val.len, 15);
- @memset(&agent.next_reset, 0);
- @memcpy(agent.next_reset[0..len], val[0..len]);
- agent.next_reset_len = len;
- }
- }
- }
- }
- } else |_| {}
- }
-
- // Prefer status.json loop_count over stale circuit_breaker_state loop
- if (agent.loop_count_status > 0) {
- agent.loop = agent.loop_count_status;
- }
-
- // Compute data freshness: age of newest data source
- {
- const now_secs: i64 = @intCast(@divFloor(std.time.nanoTimestamp(), std.time.ns_per_s));
- const newest_mtime = @max(agent.log_mtime, @max(agent.status_mtime, agent.live_mtime));
- agent.data_age_seconds = if (newest_mtime > 0) now_secs - newest_mtime else 0;
- if (agent.data_age_seconds < 0) agent.data_age_seconds = 0;
- std.debug.print("[POLL ai={d}] freshness: log_mt={d} status_mt={d} live_mt={d} age={d}s rate_lim={}\n", .{
- ai, agent.log_mtime, agent.status_mtime, agent.live_mtime, agent.data_age_seconds, agent.rate_limited,
- });
- }
-
- // Detect rate limiting from live_result
- {
- if (agent.live_result_len > 0) {
- const result = agent.live_result[0..agent.live_result_len];
- agent.rate_limited = (std.mem.indexOf(u8, result, "hit your limit") != null) or
- (std.mem.indexOf(u8, result, "rate limit") != null);
- } else {
- agent.rate_limited = false;
- }
- }
-
- // v8.1.1: Update ralph loop detection state before executing commands (all tabs)
- ralphUpdateLoopState();
-
- // Execute any pending ralph control command (START/STOP/RESTART) (all tabs)
- ralphExecPendingCmd();
-}
-
-// ββ v8.0: Unified Chat Helpers ββ
-
-/// Parse [YYYY-MM-DD HH:MM:SS] from log line into comparable i64 for sorting.
-fn parseLogTimestamp(line: []const u8) i64 {
- // Format: [2026-02-18 21:36:35] ...
- if (line.len < 21 or line[0] != '[') return 0;
- const year = std.fmt.parseInt(i64, line[1..5], 10) catch return 0;
- const month = std.fmt.parseInt(i64, line[6..8], 10) catch return 0;
- const day = std.fmt.parseInt(i64, line[9..11], 10) catch return 0;
- const hour = std.fmt.parseInt(i64, line[12..14], 10) catch return 0;
- const min = std.fmt.parseInt(i64, line[15..17], 10) catch return 0;
- const sec = std.fmt.parseInt(i64, line[18..20], 10) catch return 0;
- return (year - 2020) * 31536000 + month * 2678400 + day * 86400 + hour * 3600 + min * 60 + sec;
-}
-
-/// Get tag color RGB for a log line (without alpha).
-fn getLogTagColor(line: []const u8) struct { r: u8, g: u8, b: u8 } {
- if (line.len < 3) return .{ .r = 0xBB, .g = 0xBB, .b = 0xBB };
- if (containsBytes(line, "[LOOP]") or containsBytes(line, "=== "))
- return .{ .r = 0xFF, .g = 0xAA, .b = 0x00 };
- if (containsBytes(line, "[SUCCESS]"))
- return .{ .r = 0x00, .g = 0xFF, .b = 0x41 };
- if (containsBytes(line, "[INFO]"))
- return .{ .r = 0x88, .g = 0xCC, .b = 0xFF };
- if (containsBytes(line, "[WARN]"))
- return .{ .r = 0xFF, .g = 0xFF, .b = 0x00 };
- if (containsBytes(line, "[ERROR]") or containsBytes(line, "[FAIL]"))
- return .{ .r = 0xFF, .g = 0x33, .b = 0x66 };
- if (containsBytes(line, "Executing Claude"))
- return .{ .r = 0xFF, .g = 0x14, .b = 0x93 };
- if (containsBytes(line, "Completed Loop"))
- return .{ .r = 0x50, .g = 0xFA, .b = 0x7B };
- return .{ .r = 0xBB, .g = 0xBB, .b = 0xBB };
-}
-
-/// Build unified chat message array from logs + claude output, sorted chronologically.
-fn buildUnifiedChat(ai: usize) void {
- const agent = &g_ralph_agents[ai];
-
- // Skip rebuild if nothing changed
- if (agent.log_mtime == agent.chat_built_log_mt and
- agent.live_mtime == agent.chat_built_live_mt) return;
-
- agent.chat_count = 0;
-
- // 1. Add log lines
- for (0..agent.log_count) |i| {
- if (agent.chat_count >= 50) break;
- const log_slice = std.mem.sliceTo(&agent.logs[i], 0);
- if (log_slice.len == 0) continue;
-
- var msg = &agent.chat_msgs[agent.chat_count];
- msg.* = ChatMsg{};
- msg.sender = .loop;
- msg.kind = .log_line;
- msg.timestamp = parseLogTimestamp(log_slice);
- const len = @min(log_slice.len, 255);
- @memcpy(msg.text[0..len], log_slice[0..len]);
- msg.text_len = len;
- const tc = getLogTagColor(log_slice);
- msg.tag_r = tc.r;
- msg.tag_g = tc.g;
- msg.tag_b = tc.b;
- agent.chat_count += 1;
- }
-
- // 2. Add claude metadata
- if (agent.live_result_len > 0 and agent.live_num_turns > 0 and agent.chat_count < 50) {
- var msg = &agent.chat_msgs[agent.chat_count];
- msg.* = ChatMsg{};
- msg.sender = .claude;
- msg.kind = .meta_info;
- msg.timestamp = agent.live_mtime;
- _ = std.fmt.bufPrint(&msg.text, "Turns: {d} | Duration: {d}m{d}s | Cost: ${s}", .{
- agent.live_num_turns,
- agent.live_duration_ms / 60000,
- (agent.live_duration_ms / 1000) % 60,
- std.mem.sliceTo(&agent.live_cost_usd, 0),
- }) catch {};
- msg.text_len = std.mem.sliceTo(&msg.text, 0).len;
- agent.chat_count += 1;
- }
-
- // 3. Add task list
- if (agent.todo_count > 0 and agent.chat_count < 50) {
- var msg = &agent.chat_msgs[agent.chat_count];
- msg.* = ChatMsg{};
- msg.sender = .claude;
- msg.kind = .task_list;
- msg.timestamp = agent.live_mtime;
- msg.todo_count = agent.todo_count;
- agent.chat_count += 1;
- }
-
- // 4. Add claude result body
- if (agent.live_result_len > 0 and agent.chat_count < 50) {
- var msg = &agent.chat_msgs[agent.chat_count];
- msg.* = ChatMsg{};
- msg.sender = .claude;
- msg.kind = .claude_result;
- msg.timestamp = agent.live_mtime + 1;
- msg.result_offset = 0;
- msg.result_len = agent.live_result_len;
- agent.chat_count += 1;
- }
-
- // 5. Insertion sort by timestamp (N<=50)
- var si: usize = 1;
- while (si < agent.chat_count) : (si += 1) {
- const key = agent.chat_msgs[si];
- var j: usize = si;
- while (j > 0 and agent.chat_msgs[j - 1].timestamp > key.timestamp) {
- agent.chat_msgs[j] = agent.chat_msgs[j - 1];
- j -= 1;
- }
- agent.chat_msgs[j] = key;
- }
-
- agent.chat_built_log_mt = agent.log_mtime;
- agent.chat_built_live_mt = agent.live_mtime;
-}
-
-// v2.1: Add entry to live log buffer (ring buffer)
-fn addLiveLog(text: []const u8, source_hue: f32) void {
- if (g_live_log_count >= LIVE_LOG_MAX) {
- // Shift entries up (drop oldest)
- for (0..LIVE_LOG_MAX - 1) |i| {
- @memcpy(&g_live_log_text[i], &g_live_log_text[i + 1]);
- g_live_log_lens[i] = g_live_log_lens[i + 1];
- g_live_log_hues[i] = g_live_log_hues[i + 1];
- }
- g_live_log_count = LIVE_LOG_MAX - 1;
- }
- const idx = g_live_log_count;
- const copy_len = @min(text.len, 95);
- @memcpy(g_live_log_text[idx][0..copy_len], text[0..copy_len]);
- g_live_log_text[idx][copy_len] = 0;
- g_live_log_lens[idx] = copy_len;
- g_live_log_hues[idx] = source_hue;
- g_live_log_count += 1;
-}
-
-// v2.0: Scan current working directory for finder mode
-fn scanDirectory() void {
- g_finder_count = 0;
- if (is_emscripten) {
- // WASM: static demo file list (no filesystem access)
- const demo_names = [_][]const u8{
- "src/", "assets/", "build.zig", "README.md", "specs/",
- "photon.zig", "trinity_canvas/", "wave_scroll.zig",
- };
- const demo_is_dir = [_]bool{ true, true, false, false, true, false, true, false };
- for (demo_names, 0..) |name, i| {
- if (i >= FINDER_MAX_ENTRIES) break;
- const name_len = @min(name.len, 63);
- @memcpy(g_finder_names[i][0..name_len], name[0..name_len]);
- g_finder_names[i][name_len] = 0;
- g_finder_is_dir[i] = demo_is_dir[i];
- g_finder_count += 1;
- }
- g_finder_scanned = true;
- return;
- }
- var dir = std.fs.cwd().openDir(".", .{ .iterate = true }) catch return;
- defer dir.close();
- var iter = dir.iterate();
- while (g_finder_count < FINDER_MAX_ENTRIES) {
- const entry = iter.next() catch break;
- if (entry == null) break;
- const e = entry.?;
- const name_len = @min(e.name.len, 63);
- @memcpy(g_finder_names[g_finder_count][0..name_len], e.name[0..name_len]);
- g_finder_names[g_finder_count][name_len] = 0;
- g_finder_is_dir[g_finder_count] = (e.kind == .directory);
- g_finder_count += 1;
- }
- g_finder_scanned = true;
- g_finder_last_scan = std.time.timestamp();
-}
-
-fn addGlobalChatMessage(msg: []const u8, msg_type: ChatMsgType) void {
- if (g_chat_msg_count >= MAX_CHAT_MSGS) {
- // Shift messages up (drop oldest)
- for (0..MAX_CHAT_MSGS - 1) |i| {
- @memcpy(&g_chat_messages[i], &g_chat_messages[i + 1]);
- g_chat_msg_lens[i] = g_chat_msg_lens[i + 1];
- g_chat_msg_types[i] = g_chat_msg_types[i + 1];
- }
- g_chat_msg_count = MAX_CHAT_MSGS - 1;
- }
- const idx = g_chat_msg_count;
- const copy_len = @min(msg.len, 511);
- @memcpy(g_chat_messages[idx][0..copy_len], msg[0..copy_len]);
- g_chat_msg_lens[idx] = copy_len;
- g_chat_msg_types[idx] = msg_type;
- g_chat_msg_count += 1;
-}
-
-fn addChatLogMessage(comptime fmt: []const u8, args: anytype) void {
- var buf: [256]u8 = undefined;
- const text = std.fmt.bufPrint(&buf, fmt, args) catch "...";
- addGlobalChatMessage(text, .log);
-}
-
-// =============================================================================
-// β Chakra Colors + Chain Indicator Renderer
-// =============================================================================
-
-fn getChainMsgColor(msg_type: ChatMsgType, alpha: u8) rl.Color {
- return switch (msg_type) {
- .chain_goal_parse => .{ .r = 0xFF, .g = 0x30, .b = 0x30, .a = alpha }, // Red
- .chain_decompose => .{ .r = 0xFF, .g = 0x7F, .b = 0x00, .a = alpha }, // Orange
- .chain_schedule => .{ .r = 0xFF, .g = 0xDD, .b = 0x00, .a = alpha }, // Yellow
- .chain_execute => .{ .r = 0x00, .g = 0xEE, .b = 0x44, .a = alpha }, // Green
- .chain_monitor => .{ .r = 0x44, .g = 0x88, .b = 0xFF, .a = alpha }, // Blue
- .chain_adapt => .{ .r = 0x6B, .g = 0x20, .b = 0xA2, .a = alpha }, // Indigo
- .chain_synthesize => .{ .r = 0xAB, .g = 0x30, .b = 0xFF, .a = alpha }, // Violet
- .chain_deliver => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .tool_result => .{ .r = 0x00, .g = 0x88, .b = 0xFF, .a = alpha }, // Tool blue
- .routing_info => .{ .r = 0x00, .g = 0xCC, .b = 0xFF, .a = alpha }, // Cyan
- .reflection => .{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = alpha }, // Learn green
- .agent_error => .{ .r = 0xFF, .g = 0x44, .b = 0x44, .a = alpha }, // Error red
- .provenance_step => .{ .r = 0x88, .g = 0x88, .b = 0xAA, .a = alpha }, // Steel blue
- .truth_verification => .{ .r = 0x00, .g = 0xFF, .b = 0xAA, .a = alpha }, // Bright teal
- .quark_step => .{ .r = 0x99, .g = 0x99, .b = 0xBB, .a = alpha }, // Light steel blue
- .gluon_entangle => .{ .r = 0xCC, .g = 0x44, .b = 0xFF, .a = alpha }, // Magenta
- .dag_visualization => .{ .r = 0x00, .g = 0xDD, .b = 0xCC, .a = alpha }, // Cyan
- .reward_summary => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .collapse_toggle => .{ .r = 0x70, .g = 0x80, .b = 0x90, .a = alpha }, // Slate
- .share_link_generated => .{ .r = 0x00, .g = 0x7B, .b = 0xFF, .a = alpha }, // Electric blue
- .staking_event => .{ .r = 0x50, .g = 0xC8, .b = 0x78, .a = alpha }, // Emerald
- .self_repair_event => .{ .r = 0xFF, .g = 0x99, .b = 0x33, .a = alpha }, // Warm orange
- .immortal_persist => .{ .r = 0x00, .g = 0x99, .b = 0x88, .a = alpha }, // Deep teal
- .evolution_step => .{ .r = 0x33, .g = 0xFF, .b = 0x77, .a = alpha }, // Aurora green
- .chain_health_check => .{ .r = 0x55, .g = 0xBB, .b = 0xFF, .a = alpha }, // Sky blue
- .faucet_claim => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .public_launch => .{ .r = 0x00, .g = 0xEE, .b = 0xFF, .a = alpha }, // Bright cyan
- .canvas_sync => .{ .r = 0x88, .g = 0x44, .b = 0xFF, .a = alpha }, // Violet
- .faucet_distribution => .{ .r = 0xFF, .g = 0xBB, .b = 0x33, .a = alpha }, // Amber
- .decentral_sync => .{ .r = 0x99, .g = 0x33, .b = 0xFF, .a = alpha }, // Electric purple
- .node_consensus => .{ .r = 0x77, .g = 0xFF, .b = 0x33, .a = alpha }, // Lime green
- .network_health => .{ .r = 0x00, .g = 0x77, .b = 0xCC, .a = alpha }, // Ocean blue
- .agent_os_init => .{ .r = 0xFF, .g = 0x66, .b = 0x55, .a = alpha }, // Bright coral
- .mainnet_genesis => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .dao_vote => .{ .r = 0x41, .g = 0x69, .b = 0xE1, .a = alpha }, // Royal blue
- .swarm_sync => .{ .r = 0x39, .g = 0xFF, .b = 0x14, .a = alpha }, // Neon green
- .token_mint => .{ .r = 0xFF, .g = 0xBF, .b = 0x00, .a = alpha }, // Amber
- .mainnet_launch => .{ .r = 0xDC, .g = 0x14, .b = 0x3C, .a = alpha }, // Crimson
- .community_onboard => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime
- .node_discovery => .{ .r = 0x00, .g = 0xCE, .b = 0xD1, .a = alpha }, // Cyan
- .governance_exec => .{ .r = 0xFF, .g = 0x00, .b = 0xFF, .a = alpha }, // Magenta
- .swarm_orchestrate => .{ .r = 0x99, .g = 0x33, .b = 0xFF, .a = alpha }, // Electric purple
- .swarm_failover => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = alpha }, // Red-orange
- .swarm_telemetry => .{ .r = 0x00, .g = 0x80, .b = 0x80, .a = alpha }, // Teal
- .swarm_replication => .{ .r = 0x87, .g = 0xCE, .b = 0xEB, .a = alpha }, // Sky blue
- .swarm_scale => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .reward_distribute => .{ .r = 0xFF, .g = 0xBF, .b = 0x00, .a = alpha }, // Amber
- .dao_governance_live => .{ .r = 0x41, .g = 0x69, .b = 0xE1, .a = alpha }, // Royal blue
- .node_scaling => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = alpha }, // Spring green
- // v2.7: Community Nodes v1.0 + Gossip Protocol + DHT 10k+
- .community_node => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime green
- .gossip_broadcast => .{ .r = 0xFF, .g = 0x7F, .b = 0x50, .a = alpha }, // Coral
- .dht_lookup => .{ .r = 0x1E, .g = 0x90, .b = 0xFF, .a = alpha }, // Dodger blue
- .community_sync => .{ .r = 0xBA, .g = 0x55, .b = 0xD3, .a = alpha }, // Medium orchid
- // v2.8: DAO Full Governance v1.0
- .dao_delegate => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .timelock_vote => .{ .r = 0xDC, .g = 0x14, .b = 0x3C, .a = alpha }, // Crimson
- .proposal_exec => .{ .r = 0x2E, .g = 0x8B, .b = 0x57, .a = alpha }, // Sea green
- .yield_farming => .{ .r = 0xFF, .g = 0x8C, .b = 0x00, .a = alpha }, // Dark orange
- // v2.9: Cross-Chain Bridge v1.0
- .cross_chain_bridge => .{ .r = 0x00, .g = 0xBF, .b = 0xFF, .a = alpha }, // Deep sky blue
- .atomic_swap => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = alpha }, // Orange red
- .state_replicate => .{ .r = 0x3C, .g = 0xB3, .b = 0x71, .a = alpha }, // Medium sea green
- .bridge_sync => .{ .r = 0x41, .g = 0x69, .b = 0xE1, .a = alpha }, // Royal blue
- // v2.10: Trinity DAO Full Governance v1.0 + $TRI Staking Rewards
- .dao_full_governance => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .tri_staking => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime green
- .reward_distribute_v2 => .{ .r = 0xFF, .g = 0x69, .b = 0xB4, .a = alpha }, // Hot pink
- .staking_validate => .{ .r = 0x46, .g = 0x82, .b = 0xB4, .a = alpha }, // Steel blue
- // v2.11: Swarm 100k + Community 50k (Sharded Gossip + Hierarchical DHT)
- .swarm_100k => .{ .r = 0xFF, .g = 0xA5, .b = 0x00, .a = alpha }, // Orange
- .gossip_shard => .{ .r = 0x00, .g = 0xCE, .b = 0xD1, .a = alpha }, // Dark turquoise
- .dht_sync => .{ .r = 0x93, .g = 0x70, .b = 0xDB, .a = alpha }, // Medium purple
- .community_50k => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = alpha }, // Spring green
- // v2.12: Zero-Knowledge Bridge v1.0 (ZK-Proof Verification + Privacy Transfers)
- .zk_bridge => .{ .r = 0xDC, .g = 0x14, .b = 0x3C, .a = alpha }, // Crimson
- .zk_proof => .{ .r = 0x7D, .g = 0xF9, .b = 0xFF, .a = alpha }, // Electric blue
- .privacy_transfer => .{ .r = 0x4B, .g = 0x00, .b = 0x82, .a = alpha }, // Indigo
- .cross_chain_sync_v2 => .{ .r = 0x50, .g = 0xC8, .b = 0x78, .a = alpha }, // Emerald
- // v2.13: Layer-2 Rollup v1.0 (u8 Upgrade)
- .l2_rollup => .{ .r = 0xFF, .g = 0x7F, .b = 0x50, .a = alpha }, // Coral
- .optimistic_verify => .{ .r = 0x00, .g = 0xFF, .b = 0xFF, .a = alpha }, // Cyan
- .state_channel => .{ .r = 0xDA, .g = 0x70, .b = 0xD6, .a = alpha }, // Orchid
- .batch_compress => .{ .r = 0x40, .g = 0xE0, .b = 0xD0, .a = alpha }, // Turquoise
- // v2.14: Dynamic Shard Rebalancing v1.0
- .dynamic_shard => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .shard_split => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime
- .shard_merge => .{ .r = 0xFA, .g = 0x80, .b = 0x72, .a = alpha }, // Salmon
- .dht_adapt => .{ .r = 0x46, .g = 0x82, .b = 0xB4, .a = alpha }, // Steel Blue
- // v2.15: Swarm 1M + Community 500k
- .swarm_million => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = alpha }, // Orange Red
- .community_node_v2 => .{ .r = 0x93, .g = 0x70, .b = 0xDB, .a = alpha }, // Medium Purple
- .hierarchical_gossip => .{ .r = 0x00, .g = 0x8B, .b = 0x8B, .a = alpha }, // Dark Cyan
- .geographic_shard => .{ .r = 0xCD, .g = 0x5C, .b = 0x5C, .a = alpha }, // Indian Red
- // v2.16: ZK-Rollup v2.0
- .zk_snark_proof => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime Green
- .recursive_proof => .{ .r = 0xFF, .g = 0x14, .b = 0x93, .a = alpha }, // Deep Pink
- .l2_scaling => .{ .r = 0x1E, .g = 0x90, .b = 0xFF, .a = alpha }, // Dodger Blue
- .rollup_batch => .{ .r = 0xFF, .g = 0x8C, .b = 0x00, .a = alpha }, // Dark Orange
- // v2.17: Cross-Shard Transactions v1.0
- .cross_shard_tx => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = alpha }, // Spring Green
- .atomic_2pc => .{ .r = 0xFF, .g = 0x69, .b = 0xB4, .a = alpha }, // Hot Pink
- .shard_fee => .{ .r = 0x46, .g = 0x82, .b = 0xB4, .a = alpha }, // Steel Blue
- .tx_coordinator => .{ .r = 0xDA, .g = 0xA5, .b = 0x20, .a = alpha }, // Golden Rod
- .partition_detect => .{ .r = 0xFF, .g = 0x7F, .b = 0x50, .a = alpha }, // Coral
- .split_brain => .{ .r = 0xBA, .g = 0x55, .b = 0xD3, .a = alpha }, // Medium Orchid
- .auto_heal => .{ .r = 0x3C, .g = 0xB3, .b = 0x71, .a = alpha }, // Medium Sea Green
- .partition_tolerance => .{ .r = 0x6A, .g = 0x5A, .b = 0xCD, .a = alpha }, // Slate Blue
- // v2.19: Swarm 10M + Community 5M colors
- .swarm_10m => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime Green
- .community_5m => .{ .r = 0xFF, .g = 0x14, .b = 0x93, .a = alpha }, // Deep Pink
- .earning_boost => .{ .r = 0x1E, .g = 0x90, .b = 0xFF, .a = alpha }, // Dodger Blue
- .massive_gossip => .{ .r = 0xFF, .g = 0x8C, .b = 0x00, .a = alpha }, // Dark Orange
- // v2.20: ZK-Rollup v2.0 colors
- .zk_rollup_v2 => .{ .r = 0x00, .g = 0xFA, .b = 0x9A, .a = alpha }, // Medium Spring Green
- .snark_generate => .{ .r = 0xFF, .g = 0x69, .b = 0xB4, .a = alpha }, // Hot Pink
- .recursive_compose => .{ .r = 0x41, .g = 0x69, .b = 0xE1, .a = alpha }, // Royal Blue
- .l2_fee_collect => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- // v2.21: Cross-Shard Transactions v1.0
- .cross_shard_tx_v2 => .{ .r = 0x00, .g = 0xFF, .b = 0xFF, .a = alpha }, // Cyan
- .atomic_2pc_v2 => .{ .r = 0xFF, .g = 0x00, .b = 0xFF, .a = alpha }, // Magenta
- .shard_fee_v2 => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = alpha }, // Orange Red
- .inter_shard_sync_v2 => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = alpha }, // Spring Green
- // v2.22: Formal Verification v1.0
- .formal_verify_v2 => .{ .r = 0x00, .g = 0xBF, .b = 0xFF, .a = alpha }, // Deep Sky Blue
- .property_test_v2 => .{ .r = 0xFF, .g = 0x14, .b = 0x93, .a = alpha }, // Deep Pink
- .invariant_check_v2 => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime Green
- .proof_generate_v2 => .{ .r = 0xFF, .g = 0xA5, .b = 0x00, .a = alpha }, // Orange
- // v2.23: Swarm 100M + Community 50M
- .swarm_100m_v2 => .{ .r = 0x00, .g = 0xBF, .b = 0xFF, .a = alpha }, // Deep Sky Blue
- .community_50m_v2 => .{ .r = 0xFF, .g = 0x14, .b = 0x93, .a = alpha }, // Deep Pink
- .earning_moonshot_v2 => .{ .r = 0x32, .g = 0xCD, .b = 0x32, .a = alpha }, // Lime Green
- .gossip_v3_v2 => .{ .r = 0xFF, .g = 0xA5, .b = 0x00, .a = alpha }, // Orange
- // v2.24: Trinity Global Dominance v1.0 colors
- .global_dominance_v2 => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha }, // Gold
- .world_adoption_v2 => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = alpha }, // Spring Green
- .tri_to_one_v2 => .{ .r = 0x94, .g = 0x00, .b = 0xD3, .a = alpha }, // Dark Violet
- .ecosystem_complete_v2 => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = alpha }, // Orange Red
- // v2.25: Trinity Eternal v1.0
- .ouroboros_evolve_v2 => .{ .r = 0, .g = 255, .b = 127, .a = 255 }, // spring green
- .infinite_scale_v2 => .{ .r = 138, .g = 43, .b = 226, .a = 255 }, // blue violet
- .universal_reserve_v2 => .{ .r = 255, .g = 215, .b = 0, .a = 255 }, // gold
- .eternal_uptime_v2 => .{ .r = 0, .g = 191, .b = 255, .a = 255 }, // deep sky blue
- // v2.26
- .tri_to_ten_v2 => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = 255 },
- .mass_adoption_v2 => .{ .r = 0x00, .g = 0xBF, .b = 0xFF, .a = 255 },
- .exchange_listing_v2 => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 255 },
- .universal_wallet_v2 => .{ .r = 0x7B, .g = 0x68, .b = 0xEE, .a = 255 },
- // v2.27
- .tri_to_hundred_v2 => .{ .r = 0xDC, .g = 0x14, .b = 0x3C, .a = 255 },
- .universal_adoption_v2 => .{ .r = 0x00, .g = 0xFA, .b = 0x9A, .a = 255 },
- .exchange_v2_v2 => .{ .r = 0xFF, .g = 0x69, .b = 0xB4, .a = 255 },
- .global_wallet_v2 => .{ .r = 0x48, .g = 0xD1, .b = 0xCC, .a = 255 },
- // v2.28
- .swarm_10m_v2 => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = 255 },
- .community_5m_v2 => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 255 },
- .earning_ultimate_v2 => .{ .r = 0x7F, .g = 0xFF, .b = 0x00, .a = 255 },
- .node_discovery_10m_v2 => .{ .r = 0xFF, .g = 0x00, .b = 0xFF, .a = 255 },
- // v2.29: u16 Upgrade colors
- .swarm_1b_v2 => .{ .r = 0x00, .g = 0xBF, .b = 0xFF, .a = 255 }, // deep sky blue
- .community_500m_v2 => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = 255 }, // orange red
- .earning_god_mode_v2 => .{ .r = 0xAD, .g = 0xFF, .b = 0x2F, .a = 255 }, // green yellow
- .node_discovery_1b_v2 => .{ .r = 0xDA, .g = 0x70, .b = 0xD6, .a = 255 }, // orchid
- // v2.30: Trinity Neural Network v1.0
- .ternary_nn_v2 => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = 255 }, // spring green
- .recursive_self_train_v2 => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 255 }, // gold
- .contribution_reward_v2 => .{ .r = 0x7F, .g = 0xFF, .b = 0x00, .a = 255 }, // chartreuse
- .neural_consensus_v2 => .{ .r = 0xFF, .g = 0x00, .b = 0xFF, .a = 255 }, // magenta
- // v2.31: $TRI to $1000 + Eternal Dominance
- .tri_to_1000_v2 => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 255 }, // gold
- .universal_reserve_v2_v2 => .{ .r = 0x00, .g = 0xBF, .b = 0xFF, .a = 255 }, // deep sky blue
- .global_dominance_v2_v2 => .{ .r = 0xFF, .g = 0x45, .b = 0x00, .a = 255 }, // orange red
- .eternal_governance_v2_v2 => .{ .r = 0x9A, .g = 0xCD, .b = 0x32, .a = 255 }, // yellow green
- // v2.32: Trinity Beyond v1.0
- .trinity_beyond_v2 => .{ .r = 0xE0, .g = 0x00, .b = 0xFF, .a = 255 }, // electric purple
- .infinite_scale_v2_v2 => .{ .r = 0x00, .g = 0xFF, .b = 0xCC, .a = 255 }, // aqua green
- .multiverse_dominance_v2 => .{ .r = 0xFF, .g = 0x00, .b = 0x80, .a = 255 }, // hot pink
- .eternal_evolution_v2 => .{ .r = 0x00, .g = 0xFF, .b = 0x00, .a = 255 }, // lime green
- // v3.0: Trinity Absolute v1.0
- .trinity_absolute_v3 => .{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 255 }, // pure white (absolute)
- .infinite_tri_v3 => .{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 255 }, // gold (infinite $TRI)
- .eternal_victory_v3 => .{ .r = 0x00, .g = 0xFF, .b = 0x7F, .a = 255 }, // spring green (victory)
- .multiverse_complete_v3 => .{ .r = 0xDA, .g = 0x70, .b = 0xD6, .a = 255 }, // orchid (complete)
- .user => .{ .r = 0x70, .g = 0x70, .b = 0x90, .a = alpha },
- .ai => .{ .r = 0x30, .g = 0x80, .b = 0x50, .a = alpha },
- .log => .{ .r = 0x60, .g = 0x60, .b = 0x60, .a = alpha },
- };
-}
-
-fn getChainMsgLabel(msg_type: ChatMsgType) [*:0]const u8 {
- return switch (msg_type) {
- .chain_goal_parse => "GOAL_PARSE",
- .chain_decompose => "DECOMPOSE",
- .chain_schedule => "SCHEDULE",
- .chain_execute => "EXECUTE",
- .chain_monitor => "MONITOR",
- .chain_adapt => "ADAPT",
- .chain_synthesize => "SYNTHESIZE",
- .chain_deliver => "DELIVER",
- .tool_result => "TOOL",
- .routing_info => "->",
- .reflection => "LEARNED",
- .agent_error => "ERROR",
- .provenance_step => "HASH",
- .truth_verification => "TRUTH",
- .quark_step => "QUARK",
- .gluon_entangle => "GLUON",
- .dag_visualization => "DAG",
- .reward_summary => "$TRI",
- .collapse_toggle => "VIEW",
- .share_link_generated => "SHARE",
- .staking_event => "STAKE",
- .self_repair_event => "REPAIR",
- .immortal_persist => "PERSIST",
- .evolution_step => "EVOLVE",
- .chain_health_check => "HEALTH",
- .faucet_claim => "FAUCET",
- .public_launch => "PUBLIC",
- .canvas_sync => "CANVAS",
- .faucet_distribution => "FAUCET_D",
- .decentral_sync => "DSYNC",
- .node_consensus => "CONSENSUS",
- .network_health => "NET_HEALTH",
- .agent_os_init => "AGENT_OS",
- .mainnet_genesis => "GENESIS",
- .dao_vote => "DAO",
- .swarm_sync => "SWARM",
- .token_mint => "MINT",
- .mainnet_launch => "LAUNCH",
- .community_onboard => "COMMUNITY",
- .node_discovery => "DISCOVER",
- .governance_exec => "GOV_EXEC",
- .swarm_orchestrate => "SWARM_ORCH",
- .swarm_failover => "SWARM_FAIL",
- .swarm_telemetry => "SWARM_TELE",
- .swarm_replication => "SWARM_REPL",
- .swarm_scale => "SWARM_SCALE",
- .reward_distribute => "REWARD_DIST",
- .dao_governance_live => "DAO_GOV_LV",
- .node_scaling => "NODE_SCALE",
- // v2.7: Community Nodes v1.0 + Gossip Protocol + DHT 10k+
- .community_node => "COMM_NODE",
- .gossip_broadcast => "GOSSIP_BC",
- .dht_lookup => "DHT_LOOKUP",
- .community_sync => "COMM_SYNC",
- // v2.8: DAO Full Governance v1.0
- .dao_delegate => "DAO_DELEG",
- .timelock_vote => "TIMELVOTE",
- .proposal_exec => "PROP_EXEC",
- .yield_farming => "YIELD_FRM",
- // v2.9: Cross-Chain Bridge v1.0
- .cross_chain_bridge => "XCH_BRDG",
- .atomic_swap => "ATOM_SWAP",
- .state_replicate => "ST_REPLIC",
- .bridge_sync => "BRDG_SYNC",
- // v2.10: Trinity DAO Full Governance v1.0 + $TRI Staking Rewards
- .dao_full_governance => "DAO_FGOV",
- .tri_staking => "TRI_STAK",
- .reward_distribute_v2 => "RWD_DIST2",
- .staking_validate => "STK_VLDR",
- // v2.11: Swarm 100k + Community 50k (Sharded Gossip + Hierarchical DHT)
- .swarm_100k => "SWM_100K",
- .gossip_shard => "GSP_SHRD",
- .dht_sync => "DHT_SYNC",
- .community_50k => "COM_50K",
- // v2.12: Zero-Knowledge Bridge v1.0 (ZK-Proof Verification + Privacy Transfers)
- .zk_bridge => "ZK_BRDG",
- .zk_proof => "ZK_PROOF",
- .privacy_transfer => "PRV_XFER",
- .cross_chain_sync_v2 => "XCH_SYNC",
- // v2.13: Layer-2 Rollup v1.0
- .l2_rollup => "L2_ROLL",
- .optimistic_verify => "OPT_VRFY",
- .state_channel => "ST_CHAN",
- .batch_compress => "BCH_COMP",
- // v2.15: Swarm 1M + Community 500k
- .swarm_million => "SWM_1M",
- .community_node_v2 => "COM_ND2",
- .hierarchical_gossip => "HIR_GSP",
- .geographic_shard => "GEO_SHD",
- // v2.16: ZK-Rollup v2.0
- .zk_snark_proof => "ZK_PRF",
- .recursive_proof => "REC_PRF",
- .l2_scaling => "L2_SCL",
- .rollup_batch => "RLP_BAT",
- .cross_shard_tx => "XSH_TX",
- .atomic_2pc => "ATM_2PC",
- .shard_fee => "SHD_FEE",
- .tx_coordinator => "TX_CRD",
- .partition_detect => "PRT_DET",
- .split_brain => "SPL_BRN",
- .auto_heal => "AUT_HEL",
- .partition_tolerance => "PRT_TOL",
- // v2.19
- .swarm_10m => "SWM_10M",
- .community_5m => "COM_5M",
- .earning_boost => "ERN_BST",
- .massive_gossip => "MAS_GSP",
- // v2.20
- .zk_rollup_v2 => "ZKR_V2",
- .snark_generate => "SNK_GEN",
- .recursive_compose => "REC_CMP",
- .l2_fee_collect => "L2_FEE",
- // v2.21
- .cross_shard_tx_v2 => "XSH_V2",
- .atomic_2pc_v2 => "2PC_V2",
- .shard_fee_v2 => "SHF_V2",
- .inter_shard_sync_v2 => "ISS_V2",
- // v2.22: Formal Verification v1.0
- .formal_verify_v2 => "FRM_VRF",
- .property_test_v2 => "PRP_TST",
- .invariant_check_v2 => "INV_CHK",
- .proof_generate_v2 => "PRF_GEN",
- // v2.23: Swarm 100M + Community 50M
- .swarm_100m_v2 => "SWM_100M",
- .community_50m_v2 => "COM_50M",
- .earning_moonshot_v2 => "ERN_MSH",
- .gossip_v3_v2 => "GSP_V3",
- // v2.24: Trinity Global Dominance v1.0
- .global_dominance_v2 => "GLB_DOM",
- .world_adoption_v2 => "WLD_ADP",
- .tri_to_one_v2 => "TRI_$1",
- .ecosystem_complete_v2 => "ECO_CMP",
- // v2.25: Trinity Eternal v1.0
- .ouroboros_evolve_v2 => "ORB_EVO",
- .infinite_scale_v2 => "INF_SCL",
- .universal_reserve_v2 => "UNI_RSV",
- .eternal_uptime_v2 => "ETR_UPT",
- // v2.26
- .tri_to_ten_v2 => "$TRIβ$10",
- .mass_adoption_v2 => "MASS_ADP",
- .exchange_listing_v2 => "EXC_LIST",
- .universal_wallet_v2 => "UNI_WALLET",
- // v2.27
- .tri_to_hundred_v2 => "$TRIβ$100",
- .universal_adoption_v2 => "UNI_ADOPT",
- .exchange_v2_v2 => "EXC_V2",
- .global_wallet_v2 => "GLB_WALLET",
- // v2.28
- .swarm_10m_v2 => "SWM_10M",
- .community_5m_v2 => "COM_5M",
- .earning_ultimate_v2 => "ERN_ULT",
- .node_discovery_10m_v2 => "NOD_10M",
- .swarm_1b_v2 => "SWM_1B",
- .community_500m_v2 => "COM_500M",
- .earning_god_mode_v2 => "ERN_GOD",
- .node_discovery_1b_v2 => "NOD_1B",
- // v2.30: Trinity Neural Network v1.0
- .ternary_nn_v2 => "TRN_NN",
- .recursive_self_train_v2 => "REC_ST",
- .contribution_reward_v2 => "CTR_RW",
- .neural_consensus_v2 => "NRL_CON",
- .tri_to_1000_v2 => "TRI_1K",
- .universal_reserve_v2_v2 => "UNI_RSV",
- .global_dominance_v2_v2 => "GLB_DOM",
- .eternal_governance_v2_v2 => "ETR_GOV",
- // v2.32: Trinity Beyond v1.0
- .trinity_beyond_v2 => "TRN_BYD",
- .infinite_scale_v2_v2 => "INF_SCL",
- .multiverse_dominance_v2 => "MLT_DOM",
- .eternal_evolution_v2 => "ETR_EVO",
- // v3.0: Trinity Absolute v1.0
- .trinity_absolute_v3 => "TRN_ABS",
- .infinite_tri_v3 => "INF_TRI",
- .eternal_victory_v3 => "ETR_VIC",
- .multiverse_complete_v3 => "MLT_CMP",
- .user => "YOU",
- .ai => "AI",
- .log => "LOG",
- else => "CHAIN",
- };
-}
-
-fn isChainType(msg_type: ChatMsgType) bool {
- return switch (msg_type) {
- .chain_goal_parse, .chain_decompose, .chain_schedule, .chain_execute, .chain_monitor, .chain_adapt, .chain_synthesize, .chain_deliver, .tool_result, .routing_info, .reflection, .agent_error, .provenance_step, .truth_verification, .quark_step, .gluon_entangle, .dag_visualization, .reward_summary, .collapse_toggle, .share_link_generated, .staking_event, .self_repair_event, .immortal_persist, .evolution_step, .chain_health_check, .faucet_claim, .public_launch, .canvas_sync, .faucet_distribution, .decentral_sync, .node_consensus, .network_health, .agent_os_init, .mainnet_genesis, .dao_vote, .swarm_sync, .token_mint, .mainnet_launch, .community_onboard, .node_discovery, .governance_exec, .swarm_orchestrate, .swarm_failover, .swarm_telemetry, .swarm_replication, .swarm_scale, .reward_distribute, .dao_governance_live, .node_scaling, .community_node, .gossip_broadcast, .dht_lookup, .community_sync, .dao_delegate, .timelock_vote, .proposal_exec, .yield_farming, .cross_chain_bridge, .atomic_swap, .state_replicate, .bridge_sync, .dao_full_governance, .tri_staking, .reward_distribute_v2, .staking_validate, .swarm_100k, .gossip_shard, .dht_sync, .community_50k, .zk_bridge, .zk_proof, .privacy_transfer, .cross_chain_sync_v2, .l2_rollup, .optimistic_verify, .state_channel, .batch_compress, .dynamic_shard, .shard_split, .shard_merge, .dht_adapt, .swarm_million, .community_node_v2, .hierarchical_gossip, .geographic_shard, .zk_snark_proof, .recursive_proof, .l2_scaling, .rollup_batch, .cross_shard_tx, .atomic_2pc, .shard_fee, .tx_coordinator, .partition_detect, .split_brain, .auto_heal, .partition_tolerance, .swarm_10m, .community_5m, .earning_boost, .massive_gossip, .zk_rollup_v2, .snark_generate, .recursive_compose, .l2_fee_collect, .cross_shard_tx_v2, .atomic_2pc_v2, .shard_fee_v2, .inter_shard_sync_v2, .formal_verify_v2, .property_test_v2, .invariant_check_v2, .proof_generate_v2, .swarm_100m_v2, .community_50m_v2, .earning_moonshot_v2, .gossip_v3_v2, .global_dominance_v2, .world_adoption_v2, .tri_to_one_v2, .ecosystem_complete_v2, .ouroboros_evolve_v2, .infinite_scale_v2, .universal_reserve_v2, .eternal_uptime_v2, .tri_to_ten_v2, .mass_adoption_v2, .exchange_listing_v2, .universal_wallet_v2, .tri_to_hundred_v2, .universal_adoption_v2, .exchange_v2_v2, .global_wallet_v2, .swarm_10m_v2, .community_5m_v2, .earning_ultimate_v2, .node_discovery_10m_v2, .swarm_1b_v2, .community_500m_v2, .earning_god_mode_v2, .node_discovery_1b_v2, .ternary_nn_v2, .recursive_self_train_v2, .contribution_reward_v2, .neural_consensus_v2, .tri_to_1000_v2, .universal_reserve_v2_v2, .global_dominance_v2_v2, .eternal_governance_v2_v2, .trinity_beyond_v2, .infinite_scale_v2_v2, .multiverse_dominance_v2, .eternal_evolution_v2, .trinity_absolute_v3, .infinite_tri_v3, .eternal_victory_v3, .multiverse_complete_v3 => true,
- else => false,
- };
-}
-
-/// Convert GoldenChain message to canvas ChatMsgType
-fn chainMsgToCanvasType(chain_msg: *const golden_chain.ChainMessage) ChatMsgType {
- return switch (chain_msg.msg_type) {
- .User => .user,
- .ChainStep => if (chain_msg.node) |node| switch (node) {
- .GoalParse => .chain_goal_parse,
- .Decompose => .chain_decompose,
- .Schedule => .chain_schedule,
- .Execute => .chain_execute,
- .Monitor => .chain_monitor,
- .Adapt => .chain_adapt,
- .Synthesize => .chain_synthesize,
- .Deliver => .chain_deliver,
- } else .ai,
- .ToolResult => .tool_result,
- .RoutingInfo => .routing_info,
- .Reflection => .reflection,
- .AgentState => .log,
- .Error => .agent_error,
- .ProvenanceStep => .provenance_step,
- .TruthVerification => .truth_verification,
- .QuarkStep => .quark_step,
- .GluonEntangle => .gluon_entangle,
- .DAGVisualization => .dag_visualization,
- .RewardSummary => .reward_summary,
- .CollapseToggle => .collapse_toggle,
- .ShareLinkGenerated => .share_link_generated,
- .StakingEvent => .staking_event,
- .SelfRepairEvent => .self_repair_event,
- .ImmortalPersist => .immortal_persist,
- .EvolutionStep => .evolution_step,
- .ChainHealthCheck => .chain_health_check,
- .FaucetClaim => .faucet_claim,
- .PublicLaunch => .public_launch,
- .CanvasSync => .canvas_sync,
- .FaucetDistribution => .faucet_distribution,
- .DecentralSync => .decentral_sync,
- .NodeConsensus => .node_consensus,
- .NetworkHealth => .network_health,
- .AgentOSInit => .agent_os_init,
- .MainnetGenesis => .mainnet_genesis,
- .DAOVote => .dao_vote,
- .SwarmSync => .swarm_sync,
- .TokenMint => .token_mint,
- .MainnetLaunch => .mainnet_launch,
- .CommunityOnboard => .community_onboard,
- .NodeDiscovery => .node_discovery,
- .GovernanceExec => .governance_exec,
- .SwarmOrchestrate => .swarm_orchestrate,
- .SwarmFailover => .swarm_failover,
- .SwarmTelemetry => .swarm_telemetry,
- .SwarmReplication => .swarm_replication,
- .SwarmScale => .swarm_scale,
- .RewardDistribute => .reward_distribute,
- .DAOGovernanceLive => .dao_governance_live,
- .NodeScaling => .node_scaling,
- // v2.7: Community Nodes v1.0 + Gossip Protocol + DHT 10k+
- .CommunityNode => .community_node,
- .GossipBroadcast => .gossip_broadcast,
- .DHTLookup => .dht_lookup,
- .CommunitySyncEvent => .community_sync,
- // v2.8: DAO Full Governance v1.0
- .DAODelegation => .dao_delegate,
- .TimelockVote => .timelock_vote,
- .ProposalExecution => .proposal_exec,
- .YieldFarmingEvent => .yield_farming,
- // v2.9: Cross-Chain Bridge v1.0
- .CrossChainBridge => .cross_chain_bridge,
- .AtomicSwap => .atomic_swap,
- .StateReplication => .state_replicate,
- .BridgeSyncEvent => .bridge_sync,
- // v2.10: Trinity DAO Full Governance v1.0 + $TRI Staking Rewards
- .DAOFullGovernance => .dao_full_governance,
- .TRIStaking => .tri_staking,
- .RewardDistribution => .reward_distribute_v2,
- .StakingValidation => .staking_validate,
- // v2.11: Swarm 100k + Community 50k (Sharded Gossip + Hierarchical DHT)
- .Swarm100kScale => .swarm_100k,
- .GossipShardEvent => .gossip_shard,
- .DHTHierarchicalSync => .dht_sync,
- .Community50kOnboard => .community_50k,
- // v2.12: Zero-Knowledge Bridge v1.0 (ZK-Proof Verification + Privacy Transfers)
- .ZKBridgeVerification => .zk_bridge,
- .ZKProofGenerated => .zk_proof,
- .PrivacyTransfer => .privacy_transfer,
- .CrossChainSyncEvent => .cross_chain_sync_v2,
- // v2.13: Layer-2 Rollup v1.0
- .L2RollupSubmission => .l2_rollup,
- .OptimisticVerification => .optimistic_verify,
- .StateChannelUpdate => .state_channel,
- .BatchCompressionEvent => .batch_compress,
- // v2.14: Dynamic Shard Rebalancing v1.0
- .DynamicShardEvent => .dynamic_shard,
- .ShardLoadUpdate => .shard_split,
- .AdaptiveDHTEvent => .dht_adapt,
- .GossipReshardEvent => .shard_merge,
- // v2.15: Swarm 1M + Community 500k
- .SwarmMillionEvent => .swarm_million,
- .CommunityNodeUpdate => .community_node_v2,
- .HierarchicalGossipEvent => .hierarchical_gossip,
- .GeographicShardEvent => .geographic_shard,
- // v2.16: ZK-Rollup v2.0
- .ZkSnarkProofEvent => .zk_snark_proof,
- .RecursiveProofUpdate => .recursive_proof,
- .L2ScalingEvent => .l2_scaling,
- .RollupBatchEvent => .rollup_batch,
- // v2.17: Cross-Shard Transactions v1.0
- .CrossShardTxEvent => .cross_shard_tx,
- .Atomic2pcUpdate => .atomic_2pc,
- .ShardFeeEvent => .shard_fee,
- .TxCoordinatorEvent => .tx_coordinator,
- .PartitionDetectEvent => .partition_detect,
- .SplitBrainUpdate => .split_brain,
- .AutoHealEvent => .auto_heal,
- .PartitionToleranceEvent => .partition_tolerance,
- // v2.19: Swarm 10M + Community 5M
- .Swarm10MEvent => .swarm_10m,
- .Community5MUpdate => .community_5m,
- .EarningBoostEvent => .earning_boost,
- .MassiveGossipEvent => .massive_gossip,
- // v2.20: ZK-Rollup v2.0
- .ZkRollupV2Event => .zk_rollup_v2,
- .SnarkGenerateUpdate => .snark_generate,
- .RecursiveComposeEvent => .recursive_compose,
- .L2FeeCollectEvent => .l2_fee_collect,
- // v2.21: Cross-Shard Transactions v1.0
- .CrossShardTxEventV2 => .cross_shard_tx_v2,
- .Atomic2PCUpdate => .atomic_2pc_v2,
- .ShardFeeEventV2 => .shard_fee_v2,
- .InterShardSyncEvent => .inter_shard_sync_v2,
- // v2.22: Formal Verification v1.0
- .FormalVerifyEvent => .formal_verify_v2,
- .PropertyTestUpdate => .property_test_v2,
- .InvariantCheckEvent => .invariant_check_v2,
- .ProofGenerateEvent => .proof_generate_v2,
- // v2.23: Swarm 100M + Community 50M
- .Swarm100MEvent => .swarm_100m_v2,
- .Community50MUpdate => .community_50m_v2,
- .EarningMoonshotEvent => .earning_moonshot_v2,
- .GossipV3Event => .gossip_v3_v2,
- // v2.24: Trinity Global Dominance v1.0
- .GlobalDominanceEvent => .global_dominance_v2,
- .WorldAdoptionUpdate => .world_adoption_v2,
- .TriToOneEvent => .tri_to_one_v2,
- .EcosystemCompleteEvent => .ecosystem_complete_v2,
- // v2.25: Trinity Eternal v1.0
- .OuroborosEvolveEvent => .ouroboros_evolve_v2,
- .InfiniteScaleUpdate => .infinite_scale_v2,
- .UniversalReserveEvent => .universal_reserve_v2,
- .EternalUptimeEvent => .eternal_uptime_v2,
- // v2.26
- .TriToTenEvent => .tri_to_ten_v2,
- .MassAdoptionUpdate => .mass_adoption_v2,
- .ExchangeListingEvent => .exchange_listing_v2,
- .UniversalWalletEvent => .universal_wallet_v2,
- // v2.27
- .TriToHundredEvent => .tri_to_hundred_v2,
- .UniversalAdoptionUpdate => .universal_adoption_v2,
- .ExchangeV2Event => .exchange_v2_v2,
- .GlobalWalletEvent => .global_wallet_v2,
- // v2.28
- .Swarm10MEventV2 => .swarm_10m_v2,
- .Community5MUpdateV2 => .community_5m_v2,
- .EarningUltimateEvent => .earning_ultimate_v2,
- .NodeDiscovery10MEvent => .node_discovery_10m_v2,
- .Swarm1BEvent => .swarm_1b_v2,
- .Community500MUpdate => .community_500m_v2,
- .EarningGodModeEvent => .earning_god_mode_v2,
- .NodeDiscovery1BEvent => .node_discovery_1b_v2,
- // v2.30: Trinity Neural Network v1.0
- .TernaryNNEvent => .ternary_nn_v2,
- .RecursiveSelfTrainUpdate => .recursive_self_train_v2,
- .ContributionRewardEvent => .contribution_reward_v2,
- .NeuralConsensusEvent => .neural_consensus_v2,
- .TRITo1000Event => .tri_to_1000_v2,
- .UniversalReserveV2Update => .universal_reserve_v2_v2,
- .GlobalDominanceV2Event => .global_dominance_v2_v2,
- .EternalGovernanceV2Event => .eternal_governance_v2_v2,
- // v2.32: Trinity Beyond v1.0
- .TrinityBeyondEvent => .trinity_beyond_v2,
- .InfiniteScaleUpdateV2 => .infinite_scale_v2_v2,
- .MultiVerseDominanceEvent => .multiverse_dominance_v2,
- .EternalEvolutionEvent => .eternal_evolution_v2,
- // v3.0: Trinity Absolute v1.0
- .TrinityAbsoluteEvent => .trinity_absolute_v3,
- .InfiniteTRIUpdate => .infinite_tri_v3,
- .EternalVictoryEvent => .eternal_victory_v3,
- .MultiVerseCompleteEvent => .multiverse_complete_v3,
- };
-}
-
-/// Draw a pulsing Chakra-colored circle indicator (sound wave dot)
-fn drawChainIndicator(x: f32, y: f32, msg_type: ChatMsgType, time: f32, fs: f32) void {
- const color = getChainMsgColor(msg_type, 200);
- const radius = 5.0 * fs;
- const pulse: f32 = @sin(time * 4.0) * 0.3 + 0.7;
-
- // Outer glow
- const glow_alpha: u8 = @intFromFloat(@max(0, @min(255, 50.0 * pulse)));
- rl.DrawCircle(@intFromFloat(x), @intFromFloat(y), radius * 1.5, rl.Color{ .r = color.r, .g = color.g, .b = color.b, .a = glow_alpha });
-
- // Inner solid circle
- rl.DrawCircle(@intFromFloat(x), @intFromFloat(y), radius, color);
-
- // Center bright dot
- const center_alpha: u8 = @intFromFloat(@max(0, @min(255, 150.0 * pulse)));
- rl.DrawCircle(@intFromFloat(x), @intFromFloat(y), radius * 0.35, rl.Color{ .r = 255, .g = 255, .b = 255, .a = center_alpha });
-}
-
-// =============================================================================
-// HYPER TERMINAL STYLE COLORS (from theme.zig - SINGLE SOURCE OF TRUTH)
-// @bitCast converts theme.Color to rl.Color (same extern struct layout)
-// =============================================================================
-
-fn toRl(c: theme.Color) rl.Color {
- return @bitCast(c);
-}
-
-// === SWITCHABLE surface colors (var β re-read from theme on toggle) ===
-// Initialized with comptime dark defaults; reloadThemeAliases() updates at runtime.
-var BG_BLACK: rl.Color = @bitCast(theme.colors.bg);
-var TEXT_WHITE: rl.Color = @bitCast(theme.colors.text);
-var MUTED_GRAY: rl.Color = @bitCast(theme.colors.text_muted);
-var BORDER_SUBTLE: rl.Color = @bitCast(theme.colors.border);
-var VOID_BLACK: rl.Color = @bitCast(theme.colors.bg);
-var NOVA_WHITE: rl.Color = @bitCast(theme.colors.text);
-var GLASS_BG: rl.Color = @bitCast(theme.colors.bg_panel);
-var GLASS_BORDER: rl.Color = @bitCast(theme.colors.border);
-var BG_SURFACE: rl.Color = @bitCast(theme.colors.bg_surface);
-var BG_INPUT: rl.Color = @bitCast(theme.colors.bg_input);
-var BG_BAR: rl.Color = @bitCast(theme.colors.bg_bar);
-var BG_HOVER: rl.Color = @bitCast(theme.colors.bg_hover);
-var SEPARATOR: rl.Color = @bitCast(theme.colors.separator);
-var BORDER_LIGHT: rl.Color = @bitCast(theme.colors.border_light);
-var TEXT_DIM: rl.Color = @bitCast(theme.colors.text_dim);
-var TEXT_HINT: rl.Color = @bitCast(theme.colors.text_hint);
-var CONTENT_TEXT: rl.Color = @bitCast(theme.colors.content_text);
-
-// Chat panel colors (theme-switchable)
-var CHAT_TEXT: rl.Color = @bitCast(theme.colors.chat_text);
-var CHAT_LABEL_USER: rl.Color = @bitCast(theme.colors.chat_label_user);
-var CHAT_LABEL_AI: rl.Color = @bitCast(theme.colors.chat_label_ai);
-var CHAT_BUBBLE_USER: rl.Color = @bitCast(theme.colors.chat_bubble_user);
-var CHAT_BUBBLE_AI: rl.Color = @bitCast(theme.colors.chat_bubble_ai);
-var CHAT_BUBBLE_BORDER: rl.Color = @bitCast(theme.colors.chat_bubble_border);
-var CHAT_INPUT_BG: rl.Color = @bitCast(theme.colors.chat_input_bg);
-var CHAT_INPUT_BORDER: rl.Color = @bitCast(theme.colors.chat_input_border);
-var CHAT_INPUT_TEXT: rl.Color = @bitCast(theme.colors.chat_input_text);
-var SACRED_HEADER_BG: rl.Color = @bitCast(theme.colors.sacred_header_bg);
-var SACRED_HEADER_TEXT: rl.Color = @bitCast(theme.colors.sacred_header_text);
-
-// === ACCENT colors (const β same in dark and light) ===
-const HYPER_MAGENTA: rl.Color = @bitCast(theme.accents.magenta);
-const HYPER_CYAN: rl.Color = @bitCast(theme.accents.cyan);
-const HYPER_GREEN: rl.Color = @bitCast(theme.accents.green);
-const HYPER_YELLOW: rl.Color = @bitCast(theme.accents.yellow);
-const HYPER_RED: rl.Color = @bitCast(theme.accents.red);
-const ACCENT_GREEN: rl.Color = @bitCast(theme.accents.green);
-const NEON_CYAN: rl.Color = @bitCast(theme.accents.cyan);
-const NEON_MAGENTA: rl.Color = @bitCast(theme.accents.magenta);
-const NEON_GREEN: rl.Color = @bitCast(theme.accents.green);
-const NEON_GOLD: rl.Color = @bitCast(theme.accents.yellow);
-const NEON_PURPLE: rl.Color = @bitCast(theme.accents.magenta);
-const SINK_RED: rl.Color = @bitCast(theme.accents.red);
-const GLASS_GLOW: rl.Color = @bitCast(theme.accents.glow_magenta);
-const RECORDING_RED: rl.Color = @bitCast(theme.accents.recording_red);
-const GOLD: rl.Color = @bitCast(theme.accents.gold);
-const BLUE: rl.Color = @bitCast(theme.accents.blue);
-const ORANGE: rl.Color = @bitCast(theme.accents.orange);
-const PURPLE: rl.Color = @bitCast(theme.accents.purple);
-const LOGO_GREEN: rl.Color = @bitCast(theme.accents.logo_green);
-
-// Panel traffic light buttons (const β always same)
-const BTN_CLOSE: rl.Color = @bitCast(theme.panel.btn_close);
-const BTN_MINIMIZE: rl.Color = @bitCast(theme.panel.btn_minimize);
-const BTN_MAXIMIZE: rl.Color = @bitCast(theme.panel.btn_maximize);
-
-// File type colors (const β accent-based)
-const FILE_FOLDER: rl.Color = @bitCast(theme.accents.file_folder);
-const FILE_ZIG: rl.Color = @bitCast(theme.accents.file_zig);
-const FILE_CODE: rl.Color = @bitCast(theme.accents.file_code);
-const FILE_IMAGE: rl.Color = @bitCast(theme.accents.file_image);
-const FILE_AUDIO: rl.Color = @bitCast(theme.accents.file_audio);
-const FILE_DOCUMENT: rl.Color = @bitCast(theme.accents.file_document);
-const FILE_DATA: rl.Color = @bitCast(theme.accents.file_data);
-const FILE_UNKNOWN: rl.Color = @bitCast(theme.accents.file_unknown);
-
-// Helper: apply runtime alpha to a color
-fn withAlpha(c: rl.Color, alpha: u8) rl.Color {
- return rl.Color{ .r = c.r, .g = c.g, .b = c.b, .a = alpha };
-}
-
-fn containsBytes(haystack: []const u8, needle: []const u8) bool {
- return std.mem.indexOf(u8, haystack, needle) != null;
-}
-
-// Accent text color β vivid on dark theme, dark monochrome on light theme
-// Use for any text that would be accent-colored; keeps icons/borders/decorative elements vivid.
-fn accentText(accent: rl.Color, alpha: u8) rl.Color {
- // Dark theme: vivid accent color. Light theme: pure black for max contrast
- return if (theme.isDark()) withAlpha(accent, alpha) else rl.Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = alpha };
-}
-
-// Reload all var aliases from theme after toggle()
-fn reloadThemeAliases() void {
- BG_BLACK = @bitCast(theme.bg);
- TEXT_WHITE = @bitCast(theme.text);
- MUTED_GRAY = @bitCast(theme.text_muted);
- BORDER_SUBTLE = @bitCast(theme.border);
- VOID_BLACK = @bitCast(theme.bg);
- NOVA_WHITE = @bitCast(theme.text);
- GLASS_BG = @bitCast(theme.bg_panel);
- GLASS_BORDER = @bitCast(theme.border);
- BG_SURFACE = @bitCast(theme.bg_surface);
- BG_INPUT = @bitCast(theme.bg_input);
- BG_BAR = @bitCast(theme.bg_bar);
- BG_HOVER = @bitCast(theme.bg_hover);
- SEPARATOR = @bitCast(theme.separator);
- BORDER_LIGHT = @bitCast(theme.border_light);
- TEXT_DIM = @bitCast(theme.text_dim);
- TEXT_HINT = @bitCast(theme.text_hint);
- CONTENT_TEXT = @bitCast(theme.content_text);
- CHAT_TEXT = @bitCast(theme.chat_text);
- CHAT_LABEL_USER = @bitCast(theme.chat_label_user);
- CHAT_LABEL_AI = @bitCast(theme.chat_label_ai);
- CHAT_BUBBLE_USER = @bitCast(theme.chat_bubble_user);
- CHAT_BUBBLE_AI = @bitCast(theme.chat_bubble_ai);
- CHAT_BUBBLE_BORDER = @bitCast(theme.chat_bubble_border);
- CHAT_INPUT_BG = @bitCast(theme.chat_input_bg);
- CHAT_INPUT_BORDER = @bitCast(theme.chat_input_border);
- CHAT_INPUT_TEXT = @bitCast(theme.chat_input_text);
- SACRED_HEADER_BG = @bitCast(theme.sacred_header_bg);
- SACRED_HEADER_TEXT = @bitCast(theme.sacred_header_text);
-}
-
-// =============================================================================
-// TRINITY LOGO ANIMATION β 27 BLOCKS ASSEMBLY
-// Logo assembles from 27 triangular blocks flying from all sides
-// =============================================================================
-
-const LogoBlock = struct {
- // Polygon vertices (up to 5 points per shape)
- v: [5]rl.Vector2,
- count: u8,
- // Animation state
- offset: rl.Vector2, // Current animated offset from target
- rotation: f32, // Current rotation
- scale: f32, // Current scale
- delay: f32, // Animation start delay
- center: rl.Vector2, // Center of the block for positioning
- // Assembly animation velocity (spring physics)
- anim_vx: f32,
- anim_vy: f32,
- anim_vr: f32,
- // Cursor physics
- push_x: f32, // Current push displacement from cursor
- push_y: f32,
- push_rot: f32, // Rotation from cursor push
- vel_x: f32, // Velocity for spring-back
- vel_y: f32,
- vel_rot: f32,
-};
-
-const sacred_worlds = @import("trinity_canvas/sacred_worlds.zig");
-
-const LogoAnimation = struct {
- blocks: [27]LogoBlock,
- time: f32,
- duration: f32,
- is_complete: bool,
- logo_scale: f32, // Scale the logo to fit screen
- logo_offset: rl.Vector2, // Center the logo on screen
- hovered_block: i32, // Index of block under cursor (-1 = none)
- clicked_block: i32, // Block clicked this frame (-1 = none)
-
- // SVG viewBox: 596 x 526, center at ~298, 263
- const SVG_WIDTH: f32 = 596.0;
- const SVG_HEIGHT: f32 = 526.0;
- const SVG_CENTER_X: f32 = 298.0;
- const SVG_CENTER_Y: f32 = 263.0;
-
- pub fn init(screen_w: f32, screen_h: f32) LogoAnimation {
- var self = LogoAnimation{
- .blocks = undefined,
- .time = 0,
- .duration = 2.5, // Fast assembly animation
- .is_complete = false,
- .logo_scale = @min(screen_w / SVG_WIDTH, screen_h / SVG_HEIGHT) * 0.35,
- .logo_offset = .{ .x = screen_w / 2, .y = screen_h / 2 },
- .hovered_block = -1,
- .clicked_block = -1,
- };
-
- // 27 blocks parsed from assets/999.svg
- const raw_blocks = [27][5][2]f32{
- // Block 0
- .{ .{ 296.767, 435.228 }, .{ 236.563, 329.491 }, .{ 211.501, 373.56 }, .{ 296.767, 523.496 }, .{ 0, 0 } },
- // Block 1
- .{ .{ 235.71, 328.065 }, .{ 177.201, 224.57 }, .{ 126.893, 224.57 }, .{ 210.755, 372.182 }, .{ 0, 0 } },
- // Block 2
- .{ .{ 116.304, 118.557 }, .{ 175.824, 223.238 }, .{ 126.022, 223.26 }, .{ 42.177, 74.909 }, .{ 0, 0 } },
- // Block 3
- .{ .{ 43.019, 73.555 }, .{ 117.106, 116.68 }, .{ 235.544, 116.68 }, .{ 211.46, 73.525 }, .{ 0, 0 } },
- // Block 4
- .{ .{ 213.1, 73.52 }, .{ 237.875, 116.409 }, .{ 356.58, 116.741 }, .{ 381.646, 73.509 }, .{ 0, 0 } },
- // Block 5
- .{ .{ 477.724, 116.854 }, .{ 358.701, 116.802 }, .{ 383.404, 73.803 }, .{ 550.969, 73.877 }, .{ 0, 0 } },
- // Block 6
- .{ .{ 477.056, 118.915 }, .{ 418.023, 223.109 }, .{ 468.886, 223.131 }, .{ 553.143, 74.338 }, .{ 0, 0 } },
- // Block 7
- .{ .{ 358.646, 327.197 }, .{ 384.221, 372.152 }, .{ 468.192, 224.521 }, .{ 416.976, 224.579 }, .{ 0, 0 } },
- // Block 8
- .{ .{ 298.138, 434.656 }, .{ 357.793, 328.533 }, .{ 383.376, 373.808 }, .{ 298.138, 523.876 }, .{ 0, 0 } },
- // Block 9
- .{ .{ 297.148, 352.965 }, .{ 260.326, 288.171 }, .{ 237.943, 327.796 }, .{ 297.148, 432.004 }, .{ 0, 0 } },
- // Block 10
- .{ .{ 259.613, 286.78 }, .{ 224.371, 224.818 }, .{ 179.6, 224.818 }, .{ 237.048, 326.301 }, .{ 0, 0 } },
- // Block 11
- .{ .{ 223.536, 223.354 }, .{ 187.285, 159.675 }, .{ 120.085, 120.508 }, .{ 178.781, 223.779 }, .{ 0, 0 } },
- // Block 12
- .{ .{ 121.863, 119.193 }, .{ 187.937, 158.358 }, .{ 260.042, 158.355 }, .{ 237.348, 118.746 }, .{ 0, 0 } },
- // Block 13
- .{ .{ 261.857, 158.313 }, .{ 333.559, 158.29 }, .{ 356.01, 118.829 }, .{ 239.269, 118.829 }, .{ 0, 0 } },
- // Block 14
- .{ .{ 335.294, 158.3 }, .{ 407.736, 158.226 }, .{ 474.496, 118.923 }, .{ 357.761, 118.923 }, .{ 0, 0 } },
- // Block 15
- .{ .{ 408.358, 159.547 }, .{ 372.034, 223.421 }, .{ 416.476, 223.315 }, .{ 475.012, 120.916 }, .{ 0, 0 } },
- // Block 16
- .{ .{ 336.052, 286.778 }, .{ 358.165, 325.872 }, .{ 415.649, 224.808 }, .{ 371.244, 224.759 }, .{ 0, 0 } },
- // Block 17
- .{ .{ 298.893, 352.826 }, .{ 335.156, 288.19 }, .{ 357.382, 327.328 }, .{ 298.893, 430.179 }, .{ 0, 0 } },
- // Block 18
- .{ .{ 296.258, 272.716 }, .{ 282.337, 248.309 }, .{ 260.496, 286.972 }, .{ 296.258, 349.653 }, .{ 0, 0 } },
- // Block 19
- .{ .{ 259.547, 285.675 }, .{ 281.633, 246.705 }, .{ 269.336, 225.016 }, .{ 225.274, 224.996 }, .{ 0, 0 } },
- // Block 20
- .{ .{ 254.956, 199.798 }, .{ 268.406, 223.578 }, .{ 224.465, 223.598 }, .{ 189.037, 161.206 }, .{ 0, 0 } },
- // Block 21
- .{ .{ 255.476, 198.549 }, .{ 282.068, 198.538 }, .{ 260.192, 160.039 }, .{ 189.751, 160.07 }, .{ 0, 0 } },
- // Block 22
- .{ .{ 261.646, 160.062 }, .{ 283.582, 198.505 }, .{ 309.702, 198.505 }, .{ 331.733, 160.062 }, .{ 0, 0 } },
- // Block 23
- .{ .{ 338.542, 198.607 }, .{ 311.435, 198.595 }, .{ 333.423, 160.068 }, .{ 404.244, 160.099 }, .{ 0, 0 } },
- // Block 24
- .{ .{ 338.85, 199.978 }, .{ 325.556, 223.591 }, .{ 369.518, 223.61 }, .{ 404.907, 161.243 }, .{ 0, 0 } },
- // Block 25
- .{ .{ 334.38, 285.625 }, .{ 312.392, 246.733 }, .{ 324.681, 224.989 }, .{ 368.779, 224.969 }, .{ 0, 0 } },
- // Block 26
- .{ .{ 298.025, 272.637 }, .{ 311.561, 248.279 }, .{ 333.297, 287.01 }, .{ 298.025, 349.402 }, .{ 0, 0 } },
- };
- const counts = [27]u8{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
-
- for (0..27) |i| {
- var center_x: f32 = 0;
- var center_y: f32 = 0;
- const cnt = counts[i];
-
- // Convert raw vertices to rl.Vector2 and center relative to SVG center
- for (0..cnt) |j| {
- const x = raw_blocks[i][j][0] - SVG_CENTER_X;
- const y = raw_blocks[i][j][1] - SVG_CENTER_Y;
- self.blocks[i].v[j] = .{ .x = x, .y = y };
- center_x += x;
- center_y += y;
- }
- center_x /= @floatFromInt(cnt);
- center_y /= @floatFromInt(cnt);
- self.blocks[i].count = cnt;
- self.blocks[i].center = .{ .x = center_x, .y = center_y };
-
- // Each block flies straight from its own direction β no chaos
- // Direction = from center through block's position, extended far out
- const dir_len = @sqrt(center_x * center_x + center_y * center_y);
- const norm_x = if (dir_len > 0.1) center_x / dir_len else @cos(@as(f32, @floatFromInt(i)) * TAU / 27.0);
- const norm_y = if (dir_len > 0.1) center_y / dir_len else @sin(@as(f32, @floatFromInt(i)) * TAU / 27.0);
- const distance: f32 = 800.0; // Shorter travel distance β faster entrance
- self.blocks[i].offset = .{
- .x = norm_x * distance,
- .y = norm_y * distance,
- };
- self.blocks[i].rotation = 0; // No rotation β flat, clean
- self.blocks[i].scale = 1.0; // Full size from start
- self.blocks[i].delay = 0; // All start simultaneously
- self.blocks[i].anim_vx = 0;
- self.blocks[i].anim_vy = 0;
- self.blocks[i].anim_vr = 0;
- self.blocks[i].push_x = 0;
- self.blocks[i].push_y = 0;
- self.blocks[i].push_rot = 0;
- self.blocks[i].vel_x = 0;
- self.blocks[i].vel_y = 0;
- self.blocks[i].vel_rot = 0;
- }
-
- return self;
- }
-
- pub fn update(self: *LogoAnimation, dt: f32) void {
- if (self.is_complete) return;
-
- self.time += dt;
-
- var all_done = true;
- for (&self.blocks) |*block| {
- const t = @max(0, self.time - block.delay);
- const progress = @min(1.0, t / self.duration);
-
- // Two phases:
- // Phase 1 (0β0.7): straight linear flight toward center
- // Phase 2 (0.7β1.0): spring compression + bounce
- const arrival = 0.7; // when blocks "arrive" and spring kicks in
-
- if (progress < arrival) {
- // Straight flight β exponential ease-in toward center
- const speed = 4.5 * dt;
- block.offset.x -= block.offset.x * speed;
- block.offset.y -= block.offset.y * speed;
-
- // Carry momentum into spring phase
- block.anim_vx = -block.offset.x * 0.4;
- block.anim_vy = -block.offset.y * 0.4;
- block.anim_vr = 0;
- } else {
- // Spring phase β snappy elastic settle
- const spring_k: f32 = 28.0;
- const damp: f32 = 0.86;
-
- // Spring force pulls offset to zero
- block.anim_vx += (-block.offset.x * spring_k) * dt;
- block.anim_vy += (-block.offset.y * spring_k) * dt;
- block.anim_vx *= damp;
- block.anim_vy *= damp;
- block.offset.x += block.anim_vx * dt * 60.0;
- block.offset.y += block.anim_vy * dt * 60.0;
-
- // Spring on rotation
- block.anim_vr += (-block.rotation * spring_k) * dt;
- block.anim_vr *= damp;
- block.rotation += block.anim_vr * dt * 60.0;
-
- // Scale settles to 1.0
- block.scale += (1.0 - block.scale) * 0.1;
- }
-
- // Check if settled
- const dist = @sqrt(block.offset.x * block.offset.x + block.offset.y * block.offset.y);
- const vel = @sqrt(block.anim_vx * block.anim_vx + block.anim_vy * block.anim_vy);
- if (dist > 0.3 or vel > 0.3 or @abs(block.rotation) > 0.003) {
- all_done = false;
- }
- }
-
- // Brief pause after assembly before transitioning
- if (all_done and self.time > self.duration + 0.5) {
- self.is_complete = true;
- }
- }
-
- /// Point-in-polygon test (ray casting)
- fn pointInPoly(verts: [5]rl.Vector2, cnt: u8, px: f32, py: f32) bool {
- var inside = false;
- var j: usize = cnt - 1;
- var i: usize = 0;
- while (i < cnt) : (i += 1) {
- const yi = verts[i].y;
- const yj = verts[j].y;
- const xi = verts[i].x;
- const xj = verts[j].x;
- if (((yi > py) != (yj > py)) and
- (px < (xj - xi) * (py - yi) / (yj - yi) + xi))
- {
- inside = !inside;
- }
- j = i;
- }
- return inside;
- }
-
- /// Highlight block under cursor + detect clicks
- pub fn applyMouse(self: *LogoAnimation, mouse_x: f32, mouse_y: f32, _: f32, mouse_pressed: bool) void {
- const scale = self.logo_scale;
- const ox = self.logo_offset.x;
- const oy = self.logo_offset.y;
-
- self.hovered_block = -1;
- self.clicked_block = -1;
-
- for (self.blocks, 0..) |block, i| {
- var verts: [5]rl.Vector2 = undefined;
- const cnt = block.count;
-
- const cos_r = @cos(block.rotation);
- const sin_r = @sin(block.rotation);
-
- for (0..cnt) |j| {
- var bx = block.v[j].x * block.scale;
- var by = block.v[j].y * block.scale;
-
- // Apply rotation around block center (must match draw())
- const ddx = bx - block.center.x * block.scale;
- const ddy = by - block.center.y * block.scale;
- bx = block.center.x * block.scale + ddx * cos_r - ddy * sin_r;
- by = block.center.y * block.scale + ddx * sin_r + ddy * cos_r;
-
- bx += block.offset.x;
- by += block.offset.y;
-
- verts[j] = .{
- .x = ox + bx * scale,
- .y = oy + by * scale,
- };
- }
-
- if (pointInPoly(verts, cnt, mouse_x, mouse_y)) {
- self.hovered_block = @intCast(i);
- if (mouse_pressed) {
- self.clicked_block = @intCast(i);
- }
- }
- }
- }
-
- pub fn draw(self: *const LogoAnimation) void {
- const scale = self.logo_scale;
- const ox = self.logo_offset.x;
- const oy = self.logo_offset.y;
-
- // Hover color: highlight petal on hover (switches with theme)
- const highlight_color: rl.Color = @bitCast(theme.logo_highlight);
-
- // Petals β spider web look (switches with theme: black on dark, white on light)
- const petal_color: rl.Color = @bitCast(theme.logo_petal);
-
- // Outline β spider web threads (switches with theme)
- const outline_color: rl.Color = @bitCast(theme.logo_outline);
-
- for (self.blocks, 0..) |block, idx| {
- // v3.0: Block 2 pulses cyan when ANY Ralph agent is active (healthy + loop > 0)
- const is_ralph_active = blk: {
- var rai: usize = 0;
- while (rai < g_ralph_agent_count) : (rai += 1) {
- if (g_ralph_agents[rai].loop > 0 and g_ralph_agents[rai].is_healthy) break :blk true;
- }
- break :blk false;
- };
- const ralph_petal_glow = if (idx == 2 and is_ralph_active)
- rl.Color{ .r = 0, .g = 0xCC, .b = 0xFF, .a = @intFromFloat(@max(40, @min(120, @sin(frame_time * 3.0) * 40 + 80))) }
- else
- petal_color;
- const fill_color = if (self.hovered_block >= 0 and idx == @as(usize, @intCast(self.hovered_block))) highlight_color else ralph_petal_glow;
- var verts: [5]rl.Vector2 = undefined;
- const cnt = block.count;
-
- const cos_r = @cos(block.rotation);
- const sin_r = @sin(block.rotation);
-
- for (0..cnt) |j| {
- var bx = block.v[j].x * block.scale;
- var by = block.v[j].y * block.scale;
-
- const ddx = bx - block.center.x * block.scale;
- const ddy = by - block.center.y * block.scale;
- bx = block.center.x * block.scale + ddx * cos_r - ddy * sin_r;
- by = block.center.y * block.scale + ddx * sin_r + ddy * cos_r;
-
- bx += block.offset.x;
- by += block.offset.y;
-
- verts[j] = .{
- .x = ox + bx * scale,
- .y = oy + by * scale,
- };
- }
-
- // Fill
- if (cnt >= 3) {
- var k: usize = 1;
- while (k < cnt - 1) : (k += 1) {
- rl.DrawTriangle(verts[0], verts[k], verts[k + 1], fill_color);
- rl.DrawTriangle(verts[0], verts[k + 1], verts[k], fill_color);
- }
- }
-
- // Outline β integer-width line to avoid sub-pixel artifacts
- var m: usize = 0;
- while (m < cnt) : (m += 1) {
- const next = (m + 1) % cnt;
- rl.DrawLineEx(verts[m], verts[next], 1.0, outline_color);
- }
- }
- }
-};
-
-// =============================================================================
-// =============================================================================
-// SACRED FORMULA PARTICLES - Fibonacci spiral orbiting formulas
-// =============================================================================
-
-const FormulaParticle = struct {
- text: [48:0]u8,
- text_len: u8,
- desc: [80:0]u8,
- desc_len: u8,
- // Fibonacci spiral parameters
- base_angle: f32, // base position on spiral
- orbit_radius: f32, // distance from center
- orbit_speed: f32, // angular velocity (rad/s)
- angle_offset: f32, // current offset from mouse push
- expanded: bool,
- expand_anim: f32,
-
- fn init(text: []const u8, desc: []const u8, base_angle_val: f32, radius: f32, speed: f32) FormulaParticle {
- var p: FormulaParticle = undefined;
- const tlen = @min(text.len, 47);
- @memcpy(p.text[0..tlen], text[0..tlen]);
- p.text[tlen] = 0;
- p.text_len = @intCast(tlen);
- const dlen = @min(desc.len, 79);
- @memcpy(p.desc[0..dlen], desc[0..dlen]);
- p.desc[dlen] = 0;
- p.desc_len = @intCast(dlen);
- p.base_angle = base_angle_val;
- p.orbit_radius = radius;
- p.orbit_speed = speed;
- p.angle_offset = 0;
- p.expanded = false;
- p.expand_anim = 0;
- return p;
- }
-
- fn getPos(self: *const FormulaParticle, time_val: f32, cx: f32, cy: f32) struct { x: f32, y: f32 } {
- const angle = self.base_angle + time_val * self.orbit_speed + self.angle_offset;
- return .{
- .x = cx + @cos(angle) * self.orbit_radius,
- .y = cy + @sin(angle) * self.orbit_radius,
- };
- }
-
- fn update(self: *FormulaParticle, dt: f32, time_val: f32, mouse_x: f32, mouse_y: f32, mouse_pressed: bool, cx: f32, cy: f32) void {
- const pos = self.getPos(time_val, cx, cy);
-
- // Check if mouse is near this formula
- const ddx = pos.x - mouse_x;
- const ddy = pos.y - mouse_y;
- const dist = @sqrt(ddx * ddx + ddy * ddy + 1.0);
- const hover_radius: f32 = 60.0;
-
- if (dist < hover_radius) {
- // STOP: counter the orbital rotation so formula stays in place
- self.angle_offset -= self.orbit_speed * dt;
- }
-
- // Slowly return angle_offset to 0 when not hovered
- if (dist >= hover_radius) {
- self.angle_offset *= (1.0 - 0.8 * dt);
- }
-
- // Click to expand
- if (mouse_pressed) {
- const tw = @as(f32, @floatFromInt(self.text_len)) * 8.0;
- const half_tw = tw / 2;
- if (mouse_x >= pos.x - half_tw - 5 and mouse_x <= pos.x + half_tw + 5 and
- mouse_y >= pos.y - 10 and mouse_y <= pos.y + 18)
- {
- self.expanded = !self.expanded;
- }
- }
-
- // Expand animation
- if (self.expanded and self.expand_anim < 1.0) {
- self.expand_anim = @min(1.0, self.expand_anim + dt * 4.0);
- } else if (!self.expanded and self.expand_anim > 0.0) {
- self.expand_anim = @max(0.0, self.expand_anim - dt * 4.0);
- }
- }
-
- fn draw(self: *const FormulaParticle, time_val: f32, cx: f32, cy: f32, font: rl.Font) void {
- const pos = self.getPos(time_val, cx, cy);
- const text_color = withAlpha(@as(rl.Color, @bitCast(theme.formula_text)), 160);
- const tw = @as(f32, @floatFromInt(self.text_len)) * 8.0;
-
- // Draw formula text (centered)
- rl.DrawTextEx(font, &self.text, .{ .x = pos.x - tw / 2, .y = pos.y - 7 }, 14, 0.5, text_color);
-
- // Expanded description (no background rect β clean text only)
- if (self.expand_anim > 0.3) {
- const desc_alpha: u8 = @intFromFloat(@min(self.expand_anim, 1.0) * 200.0);
- // On light theme: dark text (accent green invisible on white)
- const desc_accent = @as(rl.Color, @bitCast(theme.accents.logo_green));
- const desc_color = if (theme.isDark()) withAlpha(desc_accent, desc_alpha) else withAlpha(@as(rl.Color, @bitCast(theme.text)), desc_alpha);
- const dw = @as(f32, @floatFromInt(self.desc_len)) * 7.0;
- rl.DrawTextEx(font, &self.desc, .{ .x = pos.x - dw / 2, .y = pos.y + 12 }, 12, 0.5, desc_color);
- }
- }
-};
-
-const MAX_FORMULA_PARTICLES = 42;
-
-// ADVANCED WINDOW SYSTEM - GLASSMORPHISM PANELS
-// Floating notinwith windows with phi-based animations
-// =============================================================================
-
-const MAX_PANELS = 12;
-const PANEL_RADIUS: f32 = 16.0;
-
-const PanelState = enum {
- closed,
- opening,
- open,
- closing,
- minimizing,
- maximizing,
-};
-
-const PanelType = enum {
- chat, // Chat with AI - input/output
- code, // Code editor - syntax highlight
- tools, // Tool execution - list + run
- settings, // App settings - toggles
- vision, // Image analysis - load + describe
- voice, // Voice - STT/TTS waves
- finder, // Emergent Finder - wave-based file system
- system, // System monitor - CPU, Memory, Temperature
- sacred_world, // Sacred Mathematics world panel (27 worlds)
-};
-
-// =============================================================================
-// EMERGENT FINDER - Wave-Based File System Visualization
-// Folders = concentric rings, Files = orbiting photons
-// =============================================================================
-
-const FileType = enum {
- folder,
- code_zig,
- code_other,
- image,
- audio,
- document,
- data,
- unknown,
-
- pub fn fromName(name: []const u8) FileType {
- if (name.len < 2) return .unknown;
- // Check extension
- var i: usize = name.len - 1;
- while (i > 0) : (i -= 1) {
- if (name[i] == '.') break;
- }
- if (i == 0) return .folder; // No extension = likely folder
- const ext = name[i..];
- if (std.mem.eql(u8, ext, ".zig")) return .code_zig;
- if (std.mem.eql(u8, ext, ".rs") or std.mem.eql(u8, ext, ".c") or std.mem.eql(u8, ext, ".cpp") or std.mem.eql(u8, ext, ".h") or std.mem.eql(u8, ext, ".py") or std.mem.eql(u8, ext, ".js") or std.mem.eql(u8, ext, ".ts")) return .code_other;
- if (std.mem.eql(u8, ext, ".png") or std.mem.eql(u8, ext, ".jpg") or std.mem.eql(u8, ext, ".gif") or std.mem.eql(u8, ext, ".svg") or std.mem.eql(u8, ext, ".ico")) return .image;
- if (std.mem.eql(u8, ext, ".mp3") or std.mem.eql(u8, ext, ".wav") or std.mem.eql(u8, ext, ".ogg") or std.mem.eql(u8, ext, ".flac")) return .audio;
- if (std.mem.eql(u8, ext, ".md") or std.mem.eql(u8, ext, ".txt") or std.mem.eql(u8, ext, ".pdf") or std.mem.eql(u8, ext, ".doc")) return .document;
- if (std.mem.eql(u8, ext, ".json") or std.mem.eql(u8, ext, ".toml") or std.mem.eql(u8, ext, ".yaml") or std.mem.eql(u8, ext, ".xml")) return .data;
- return .unknown;
- }
-
- pub fn getColor(self: FileType) rl.Color {
- return switch (self) {
- .folder => FILE_FOLDER,
- .code_zig => FILE_ZIG,
- .code_other => FILE_CODE,
- .image => FILE_IMAGE,
- .audio => FILE_AUDIO,
- .document => FILE_DOCUMENT,
- .data => FILE_DATA,
- .unknown => FILE_UNKNOWN,
- };
- }
-
- pub fn getIcon(self: FileType) u8 {
- return switch (self) {
- .folder => 'D',
- .code_zig => 'Z',
- .code_other => 'C',
- .image => 'I',
- .audio => 'A',
- .document => 'T',
- .data => 'J',
- .unknown => '?',
- };
- }
-};
-
-const FinderEntry = struct {
- name: [128]u8,
- name_len: usize,
- is_dir: bool,
- file_type: FileType,
- orbit_angle: f32, // For wave animation
- orbit_radius: f32, // Distance from center
-
- pub fn init() FinderEntry {
- return .{
- .name = undefined,
- .name_len = 0,
- .is_dir = false,
- .file_type = .unknown,
- .orbit_angle = 0,
- .orbit_radius = 0,
- };
- }
-};
-
-// =============================================================================
-// NETWORK ADMIN β Node connection tracking for distributed inference
-// =============================================================================
-
-const NodeStatus = enum {
- offline,
- connecting,
- online,
- degraded,
- error_state,
-
- pub fn label(self: NodeStatus) []const u8 {
- return switch (self) {
- .offline => "OFFLINE",
- .connecting => "CONNECTING",
- .online => "ONLINE",
- .degraded => "DEGRADED",
- .error_state => "ERROR",
- };
- }
-};
-
-const NetworkNode = struct {
- name: [32]u8,
- name_len: u8,
- address: [48]u8,
- address_len: u8,
- location: [32]u8,
- location_len: u8,
- geo_lat: f32, // latitude (-90..90)
- geo_lon: f32, // longitude (-180..180)
- status: NodeStatus,
- layers_start: u8,
- layers_end: u8,
- ram_mb: u16,
- latency_ms: u16,
- tokens_processed: u32,
- role: [16]u8,
- role_len: u8,
- session_time_ms: u32,
- is_local: bool,
-
- pub fn init() NetworkNode {
- return .{
- .name = undefined,
- .name_len = 0,
- .address = undefined,
- .address_len = 0,
- .location = undefined,
- .location_len = 0,
- .geo_lat = 0,
- .geo_lon = 0,
- .status = .offline,
- .layers_start = 0,
- .layers_end = 0,
- .ram_mb = 0,
- .latency_ms = 0,
- .tokens_processed = 0,
- .role = undefined,
- .role_len = 0,
- .session_time_ms = 0,
- .is_local = true,
- };
- }
-};
-
-fn mkNode(name: []const u8, addr: []const u8, role: []const u8, loc: []const u8, glat: f32, glon: f32, status: NodeStatus, l_start: u8, l_end: u8, ram: u16, latency: u16, tokens: u32, session: u32, local: bool) NetworkNode {
- var n = NetworkNode.init();
- const nl = @min(name.len, 31);
- @memcpy(n.name[0..nl], name[0..nl]);
- n.name_len = @intCast(nl);
- const al = @min(addr.len, 47);
- @memcpy(n.address[0..al], addr[0..al]);
- n.address_len = @intCast(al);
- const rl2 = @min(role.len, 15);
- @memcpy(n.role[0..rl2], role[0..rl2]);
- n.role_len = @intCast(rl2);
- const ll = @min(loc.len, 31);
- @memcpy(n.location[0..ll], loc[0..ll]);
- n.location_len = @intCast(ll);
- n.geo_lat = glat;
- n.geo_lon = glon;
- n.status = status;
- n.layers_start = l_start;
- n.layers_end = l_end;
- n.ram_mb = ram;
- n.latency_ms = latency;
- n.tokens_processed = tokens;
- n.session_time_ms = session;
- n.is_local = local;
- return n;
-}
-
-// Mercator projection: geo coords -> pixel position within map rect
-fn geoToMap(lat: f32, lon: f32, map_x: f32, map_y: f32, map_w: f32, map_h: f32) struct { x: f32, y: f32 } {
- // lon: -180..180 -> 0..map_w
- const mx = map_x + ((lon + 180.0) / 360.0) * map_w;
- // lat: 90..-90 -> 0..map_h (simple equirectangular)
- const my = map_y + ((90.0 - lat) / 180.0) * map_h;
- return .{ .x = mx, .y = my };
-}
-
-// ββ Runtime network state (detected at startup, updated dynamically) ββ
-const MAX_NETWORK_NODES = 8;
-var g_network_nodes: [MAX_NETWORK_NODES]NetworkNode = [_]NetworkNode{NetworkNode.init()} ** MAX_NETWORK_NODES;
-var g_network_node_count: usize = 0;
-var g_network_total_layers: u8 = 0;
-var g_network_model_name: [64]u8 = [_]u8{0} ** 64;
-var g_network_model_name_len: usize = 0;
-var g_network_initialized: bool = false;
-var g_network_uptime_ms: u64 = 0;
-var g_network_probe_thread: if (is_emscripten) ?u8 else ?std.Thread = null;
-var g_network_probe_done: bool = false;
-var g_net_scroll_y: f32 = 0;
-var g_net_scroll_target: f32 = 0;
-
-// ββ Timezone β Geo mapping (offline, instant, ~country-level accuracy) ββ
-const TzGeo = struct { tz: []const u8, lat: f32, lon: f32, city: []const u8 };
-const TZ_MAP = [_]TzGeo{
- .{ .tz = "Asia/Bangkok", .lat = 13.75, .lon = 100.52, .city = "Bangkok, TH" },
- .{ .tz = "Asia/Ho_Chi_Minh", .lat = 10.82, .lon = 106.63, .city = "Ho Chi Minh, VN" },
- .{ .tz = "Asia/Singapore", .lat = 1.35, .lon = 103.82, .city = "Singapore, SG" },
- .{ .tz = "Asia/Tokyo", .lat = 35.68, .lon = 139.69, .city = "Tokyo, JP" },
- .{ .tz = "Asia/Shanghai", .lat = 31.23, .lon = 121.47, .city = "Shanghai, CN" },
- .{ .tz = "Asia/Kolkata", .lat = 28.61, .lon = 77.23, .city = "Delhi, IN" },
- .{ .tz = "Asia/Dubai", .lat = 25.20, .lon = 55.27, .city = "Dubai, AE" },
- .{ .tz = "Asia/Seoul", .lat = 37.57, .lon = 126.98, .city = "Seoul, KR" },
- .{ .tz = "Asia/Taipei", .lat = 25.03, .lon = 121.57, .city = "Taipei, TW" },
- .{ .tz = "Asia/Jakarta", .lat = -6.21, .lon = 106.85, .city = "Jakarta, ID" },
- .{ .tz = "Asia/Manila", .lat = 14.60, .lon = 120.98, .city = "Manila, PH" },
- .{ .tz = "Europe/Moscow", .lat = 55.76, .lon = 37.62, .city = "Moscow, RU" },
- .{ .tz = "Europe/London", .lat = 51.51, .lon = -0.13, .city = "London, UK" },
- .{ .tz = "Europe/Berlin", .lat = 52.52, .lon = 13.41, .city = "Berlin, DE" },
- .{ .tz = "Europe/Paris", .lat = 48.86, .lon = 2.35, .city = "Paris, FR" },
- .{ .tz = "Europe/Istanbul", .lat = 41.01, .lon = 28.98, .city = "Istanbul, TR" },
- .{ .tz = "Europe/Kyiv", .lat = 50.45, .lon = 30.52, .city = "Kyiv, UA" },
- .{ .tz = "Europe/Warsaw", .lat = 52.23, .lon = 21.01, .city = "Warsaw, PL" },
- .{ .tz = "Europe/Amsterdam", .lat = 52.37, .lon = 4.90, .city = "Amsterdam, NL" },
- .{ .tz = "Europe/Lisbon", .lat = 38.72, .lon = -9.14, .city = "Lisbon, PT" },
- .{ .tz = "America/New_York", .lat = 40.71, .lon = -74.01, .city = "New York, US" },
- .{ .tz = "America/Chicago", .lat = 41.88, .lon = -87.63, .city = "Chicago, US" },
- .{ .tz = "America/Denver", .lat = 39.74, .lon = -104.99, .city = "Denver, US" },
- .{ .tz = "America/Los_Angeles", .lat = 34.05, .lon = -118.24, .city = "Los Angeles, US" },
- .{ .tz = "America/Sao_Paulo", .lat = -23.55, .lon = -46.63, .city = "Sao Paulo, BR" },
- .{ .tz = "America/Toronto", .lat = 43.65, .lon = -79.38, .city = "Toronto, CA" },
- .{ .tz = "America/Mexico_City", .lat = 19.43, .lon = -99.13, .city = "Mexico City, MX" },
- .{ .tz = "America/Argentina/Buenos_Aires", .lat = -34.60, .lon = -58.38, .city = "Buenos Aires, AR" },
- .{ .tz = "Australia/Sydney", .lat = -33.87, .lon = 151.21, .city = "Sydney, AU" },
- .{ .tz = "Pacific/Auckland", .lat = -36.85, .lon = 174.76, .city = "Auckland, NZ" },
- .{ .tz = "Africa/Cairo", .lat = 30.04, .lon = 31.24, .city = "Cairo, EG" },
- .{ .tz = "Africa/Lagos", .lat = 6.52, .lon = 3.38, .city = "Lagos, NG" },
- .{ .tz = "Africa/Johannesburg", .lat = -26.20, .lon = 28.04, .city = "Johannesburg, ZA" },
-};
-
-/// Detect local geo coordinates from system timezone (offline, instant).
-/// Reads /etc/localtime symlink on macOS/Linux β extracts TZ name β looks up in TZ_MAP.
-/// Returns null if timezone cannot be determined.
-fn detectTimezoneGeo() ?TzGeo {
- if (is_emscripten) return null;
- // macOS: /etc/localtime -> /var/db/timezone/zoneinfo/Asia/Bangkok
- // Linux: /etc/localtime -> /usr/share/zoneinfo/Asia/Bangkok
- var link_buf: [256]u8 = undefined;
- const link = std.fs.cwd().readLink("/etc/localtime", &link_buf) catch return null;
-
- // Extract timezone part after "zoneinfo/"
- const marker = "zoneinfo/";
- const idx = std.mem.indexOf(u8, link, marker) orelse return null;
- const tz_name = link[idx + marker.len ..];
- if (tz_name.len == 0) return null;
-
- // Look up in table
- for (TZ_MAP) |entry| {
- if (std.mem.eql(u8, entry.tz, tz_name)) return entry;
- }
- return null;
-}
-
-/// Geo result from IP API
-const IpGeoResult = struct {
- lat: f32,
- lon: f32,
- city: [48]u8,
- city_len: usize,
-};
-
-/// Fetch geo coordinates via ip-api.com (online, city-level accuracy).
-/// Uses curl subprocess with 3-second timeout. Pass null for local public IP.
-/// Works from background thread β uses page_allocator.
-fn fetchIpGeo(ip: ?[]const u8) ?IpGeoResult {
- if (is_emscripten) return null; // No subprocess in WASM
- const allocator = std.heap.page_allocator;
-
- // Build URL: ip-api.com/json or ip-api.com/json/{ip}?fields=lat,lon,city,country
- var url_buf: [128]u8 = undefined;
- const url = if (ip) |addr|
- std.fmt.bufPrint(&url_buf, "http://ip-api.com/json/{s}?fields=lat,lon,city,country", .{addr}) catch return null
- else
- std.fmt.bufPrint(&url_buf, "http://ip-api.com/json/?fields=lat,lon,city,country", .{}) catch return null;
-
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "curl", "-s", "-m", "3", url },
- }) catch return null;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
-
- if (result.stdout.len == 0) return null;
-
- // Parse JSON: {"lat":7.8804,"lon":98.3923,"city":"Phuket","country":"Thailand"}
- return parseIpApiJson(result.stdout);
-}
-
-/// Simple JSON field extractor β avoids needing full JSON parser.
-/// Extracts "lat", "lon", "city", "country" from ip-api.com response.
-fn parseIpApiJson(json: []const u8) ?IpGeoResult {
- const lat = parseJsonFloat(json, "\"lat\":") orelse return null;
- const lon = parseJsonFloat(json, "\"lon\":") orelse return null;
-
- var res = IpGeoResult{ .lat = lat, .lon = lon, .city = [_]u8{0} ** 48, .city_len = 0 };
-
- // Extract city
- if (extractJsonString(json, "\"city\":\"")) |city| {
- // Extract country
- if (extractJsonString(json, "\"country\":\"")) |country| {
- const cl = @min(city.len, 40);
- @memcpy(res.city[0..cl], city[0..cl]);
- res.city_len = cl;
- // Append ", XX"
- if (cl + 2 + country.len <= 48) {
- res.city[cl] = ',';
- res.city[cl + 1] = ' ';
- const co = @min(country.len, 48 - cl - 2);
- @memcpy(res.city[cl + 2 .. cl + 2 + co], country[0..co]);
- res.city_len = cl + 2 + co;
- }
- } else {
- const cl = @min(city.len, 48);
- @memcpy(res.city[0..cl], city[0..cl]);
- res.city_len = cl;
- }
- }
-
- return res;
-}
-
-fn parseJsonFloat(json: []const u8, key: []const u8) ?f32 {
- const idx = std.mem.indexOf(u8, json, key) orelse return null;
- const start = idx + key.len;
- // Find end: comma, }, or whitespace
- var end = start;
- while (end < json.len) : (end += 1) {
- const c = json[end];
- if (c == ',' or c == '}' or c == ' ' or c == '\n') break;
- }
- if (end == start) return null;
- return std.fmt.parseFloat(f32, json[start..end]) catch return null;
-}
-
-fn extractJsonString(json: []const u8, key: []const u8) ?[]const u8 {
- const idx = std.mem.indexOf(u8, json, key) orelse return null;
- const start = idx + key.len;
- // Find closing quote
- const end_off = std.mem.indexOfPos(u8, json, start, "\"") orelse return null;
- return json[start..end_off];
-}
-
-// ββ v2.4: DePIN Node Management ββββββββββββββββββββββββββββββββββββββββββ
-
-/// Check if Docker is installed using /bin/sh -c to inherit user PATH.
-fn depinCheckDocker() bool {
- if (is_emscripten) return false;
- const allocator = std.heap.page_allocator;
- // Use /bin/sh -c so the user's PATH is inherited (Docker Desktop, Homebrew, etc.)
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", "docker --version" },
- }) catch return false;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
- return result.stdout.len > 0;
-}
-
-/// Check if trinity-node container is running.
-fn depinCheckRunning() bool {
- if (is_emscripten) return false;
- const allocator = std.heap.page_allocator;
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", "docker ps -q --filter name=trinity-node" },
- }) catch return false;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
- for (result.stdout) |c| {
- if (c != ' ' and c != '\n' and c != '\r') return true;
- }
- return false;
-}
-
-/// Start the trinity-node Docker container.
-fn depinStartNode() void {
- if (is_emscripten) return;
- if (!g_depin_docker_ok) return;
- const allocator = std.heap.page_allocator;
-
- // Resolve $HOME for volume mount (tilde doesn't expand in argv)
- const home = std.posix.getenv("HOME") orelse "/tmp";
- const run_cmd = std.fmt.allocPrint(allocator, "docker rm -f trinity-node 2>/dev/null; " ++
- "docker pull ghcr.io/ghashtag/trinity-node:latest && " ++
- "docker run -d --name trinity-node " ++
- "-p 8080:8080 -p 9090:9090 -p 9333:9333/udp -p 9334:9334 " ++
- "-v {s}/.trinity:/data " ++
- "ghcr.io/ghashtag/trinity-node:latest", .{home}) catch return;
- defer allocator.free(run_cmd);
-
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", run_cmd },
- }) catch return;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
- g_depin_running = result.stdout.len > 0;
-}
-
-/// Stop and remove the trinity-node Docker container.
-fn depinStopNode() void {
- if (is_emscripten) return;
- const allocator = std.heap.page_allocator;
- if (std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "/bin/sh", "-c", "docker stop trinity-node && docker rm trinity-node" },
- })) |ok| {
- allocator.free(ok.stdout);
- allocator.free(ok.stderr);
- } else |_| {}
- g_depin_running = false;
- g_depin_earned_tri = 0;
- g_depin_pending_tri = 0;
- g_depin_operations = 0;
- g_depin_uptime_hours = 0;
- g_depin_shards = 0;
- g_depin_peers = 0;
-}
-
-/// Poll node stats from HTTP API via curl.
-fn depinPollStats() void {
- if (is_emscripten) return;
- const allocator = std.heap.page_allocator;
-
- // GET /v1/node/stats β {"operations":N,"earned_tri":F,"pending_tri":F}
- const stats = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "curl", "-s", "-m", "3", "http://localhost:8080/v1/node/stats" },
- }) catch return;
- defer allocator.free(stats.stdout);
- defer allocator.free(stats.stderr);
-
- if (stats.stdout.len > 0) {
- if (parseJsonFloat(stats.stdout, "\"earned_tri\":")) |v| g_depin_earned_tri = @floatCast(v);
- if (parseJsonFloat(stats.stdout, "\"pending_tri\":")) |v| g_depin_pending_tri = @floatCast(v);
- if (parseJsonFloat(stats.stdout, "\"operations\":")) |v| g_depin_operations = @intFromFloat(@max(0, @as(f64, @floatCast(v))));
- }
-
- // GET /node/status β {"status":"earning","uptime_hours":F,"peers":N}
- const status = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "curl", "-s", "-m", "3", "http://localhost:8080/node/status" },
- }) catch return;
- defer allocator.free(status.stdout);
- defer allocator.free(status.stderr);
-
- if (status.stdout.len > 0) {
- if (parseJsonFloat(status.stdout, "\"uptime_hours\":")) |v| g_depin_uptime_hours = v;
- if (parseJsonFloat(status.stdout, "\"peers\":")) |v| g_depin_peers = @intFromFloat(@max(0, @as(f64, @floatCast(v))));
- }
-
- // GET /storage/stats β {"shards_hosted":N,...}
- const storage = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "curl", "-s", "-m", "3", "http://localhost:8080/storage/stats" },
- }) catch return;
- defer allocator.free(storage.stdout);
- defer allocator.free(storage.stderr);
-
- if (storage.stdout.len > 0) {
- if (parseJsonFloat(storage.stdout, "\"shards_hosted\":")) |v| g_depin_shards = @intFromFloat(@max(0, @as(f64, @floatCast(v))));
- }
-}
-
-/// Claim pending $TRI rewards.
-fn depinClaimRewards() void {
- if (is_emscripten) return;
- const allocator = std.heap.page_allocator;
- const result = std.process.Child.run(.{
- .allocator = allocator,
- .argv = &[_][]const u8{ "curl", "-s", "-m", "3", "-X", "POST", "http://localhost:8080/v1/node/claim" },
- }) catch return;
- defer allocator.free(result.stdout);
- defer allocator.free(result.stderr);
-
- if (result.stdout.len > 0) {
- if (parseJsonFloat(result.stdout, "\"claimed_tri\":")) |v| {
- g_depin_earned_tri += @floatCast(v);
- g_depin_pending_tri = 0;
- }
- }
-}
-
-/// Known worker endpoints to probe via TCP
-const ProbeTarget = struct {
- host: []const u8,
- port: u16,
- name: []const u8,
- role: []const u8,
- location: []const u8,
- geo_lat: f32,
- geo_lon: f32,
- is_local: bool,
-};
-const PROBE_TARGETS = [_]ProbeTarget{
- .{ .host = "199.68.196.38", .port = 9335, .name = "VPS Worker", .role = "worker", .location = "Buffalo, US", .geo_lat = 42.89, .geo_lon = -78.88, .is_local = false },
- .{ .host = "127.0.0.1", .port = 9337, .name = "Local Relay", .role = "relay", .location = "local", .geo_lat = 0, .geo_lon = 0, .is_local = true },
- .{ .host = "127.0.0.1", .port = 9335, .name = "Local Worker", .role = "worker", .location = "local", .geo_lat = 0, .geo_lon = 0, .is_local = true },
-};
-
-/// Background TCP probe: try connecting to known endpoints + IP geo refinement
-fn probeNetworkNodes() void {
- if (is_emscripten) {
- g_network_probe_done = true;
- return; // No sockets in WASM
- }
- // Step 2: Refine local node (index 0) via IP API (city-level accuracy)
- if (fetchIpGeo(null)) |geo| {
- g_network_nodes[0].geo_lat = geo.lat;
- g_network_nodes[0].geo_lon = geo.lon;
- if (geo.city_len > 0) {
- const cl = @min(geo.city_len, 31);
- @memcpy(g_network_nodes[0].location[0..cl], geo.city[0..cl]);
- g_network_nodes[0].location_len = @intCast(cl);
- }
- }
-
- // Step 3: Probe remote/local endpoints via TCP
- for (PROBE_TARGETS) |target| {
- // Try TCP connect with short timeout
- const addr = std.net.Address.parseIp4(target.host, target.port) catch continue;
- const sock = std.posix.socket(std.posix.AF.INET, std.posix.SOCK.STREAM, 0) catch continue;
- defer std.posix.close(sock);
-
- // Set send timeout to 2 seconds as connect timeout proxy
- const timeout = std.posix.timeval{ .sec = 2, .usec = 0 };
- std.posix.setsockopt(sock, std.posix.SOL.SOCKET, std.posix.SO.SNDTIMEO, std.mem.asBytes(&timeout)) catch {};
- std.posix.setsockopt(sock, std.posix.SOL.SOCKET, std.posix.SO.RCVTIMEO, std.mem.asBytes(&timeout)) catch {};
-
- // Attempt connect
- std.posix.connect(sock, &addr.any, addr.getOsSockLen()) catch continue;
-
- // Connection succeeded β node is alive
- if (g_network_node_count >= MAX_NETWORK_NODES) break;
- var node = NetworkNode.init();
- const nl2 = @min(target.name.len, 31);
- @memcpy(node.name[0..nl2], target.name[0..nl2]);
- node.name_len = @intCast(nl2);
-
- var addr_str: [48]u8 = [_]u8{0} ** 48;
- const al2 = std.fmt.bufPrint(&addr_str, "{s}:{d}", .{ target.host, target.port }) catch continue;
- @memcpy(node.address[0..al2.len], al2);
- node.address_len = @intCast(al2.len);
-
- const rl3 = @min(target.role.len, 15);
- @memcpy(node.role[0..rl3], target.role[0..rl3]);
- node.role_len = @intCast(rl3);
-
- // For remote nodes: use IP API for accurate geo; for local: copy from local node
- if (!target.is_local) {
- if (fetchIpGeo(target.host)) |geo| {
- node.geo_lat = geo.lat;
- node.geo_lon = geo.lon;
- if (geo.city_len > 0) {
- const cl = @min(geo.city_len, 31);
- @memcpy(node.location[0..cl], geo.city[0..cl]);
- node.location_len = @intCast(cl);
- } else {
- const ll2 = @min(target.location.len, 31);
- @memcpy(node.location[0..ll2], target.location[0..ll2]);
- node.location_len = @intCast(ll2);
- }
- } else {
- // Fallback to static coords from probe target
- node.geo_lat = target.geo_lat;
- node.geo_lon = target.geo_lon;
- const ll2 = @min(target.location.len, 31);
- @memcpy(node.location[0..ll2], target.location[0..ll2]);
- node.location_len = @intCast(ll2);
- }
- } else {
- // Local node: copy geo from local coordinator (already refined)
- node.geo_lat = g_network_nodes[0].geo_lat;
- node.geo_lon = g_network_nodes[0].geo_lon;
- const ll3 = g_network_nodes[0].location_len;
- @memcpy(node.location[0..ll3], g_network_nodes[0].location[0..ll3]);
- node.location_len = ll3;
- }
-
- node.status = .online;
- node.is_local = target.is_local;
- node.latency_ms = if (target.is_local) 1 else 95;
-
- g_network_nodes[g_network_node_count] = node;
- g_network_node_count += 1;
- }
- g_network_probe_done = true;
-}
-
-/// Detect local machine and spawn background probe for remote nodes.
-/// Called once when the Network panel is first opened.
-fn initNetworkState() void {
- if (g_network_initialized) return;
- g_network_initialized = true;
-
- // Query real system RAM via auto_shard (sysctl on macOS, /proc/meminfo on Linux)
- const sys_mem = auto_shard.getSystemMemory() catch auto_shard.SystemMemory{
- .total_bytes = 0,
- .available_bytes = 0,
- };
- const ram_mb: u16 = @intCast(@min(sys_mem.total_bytes / (1024 * 1024), 65535));
-
- // Get hostname
- var hostname_buf: [64]u8 = [_]u8{0} ** 64;
- var hostname_len: usize = 0;
- if (is_emscripten) {
- const wasm_name = "Browser";
- @memcpy(hostname_buf[0..wasm_name.len], wasm_name);
- hostname_len = wasm_name.len;
- } else if (std.c.gethostname(&hostname_buf, hostname_buf.len) == 0) {
- for (hostname_buf, 0..) |c, i| {
- if (c == 0) {
- hostname_len = i;
- break;
- }
- }
- if (hostname_len == 0) hostname_len = hostname_buf.len;
- } else {
- const fallback = "localhost";
- @memcpy(hostname_buf[0..fallback.len], fallback);
- hostname_len = fallback.len;
- }
-
- // Create local node entry with real detected values
- var local_node = NetworkNode.init();
- const nl = @min(hostname_len, 31);
- @memcpy(local_node.name[0..nl], hostname_buf[0..nl]);
- local_node.name_len = @intCast(nl);
- const addr = "127.0.0.1:9336";
- @memcpy(local_node.address[0..addr.len], addr);
- local_node.address_len = @intCast(addr.len);
- const role = "coordinator";
- @memcpy(local_node.role[0..role.len], role);
- local_node.role_len = @intCast(role.len);
-
- // Step 1: Detect geo from timezone (instant, offline, ~country-level)
- if (detectTimezoneGeo()) |tz_geo| {
- local_node.geo_lat = tz_geo.lat;
- local_node.geo_lon = tz_geo.lon;
- const cl = @min(tz_geo.city.len, 31);
- @memcpy(local_node.location[0..cl], tz_geo.city[0..cl]);
- local_node.location_len = @intCast(cl);
- } else {
- const loc = "Unknown";
- @memcpy(local_node.location[0..loc.len], loc);
- local_node.location_len = @intCast(loc.len);
- }
-
- local_node.status = .online;
- local_node.ram_mb = ram_mb;
- local_node.latency_ms = 0;
- local_node.is_local = true;
- local_node.layers_start = 0;
- local_node.layers_end = 0;
-
- g_network_nodes[0] = local_node;
- g_network_node_count = 1;
-
- const no_model = if (is_emscripten) "WASM Browser Node" else "Scanning network...";
- @memcpy(g_network_model_name[0..no_model.len], no_model);
- g_network_model_name_len = no_model.len;
-
- if (is_emscripten) {
- // No background threads in WASM β mark probe as done immediately
- g_network_probe_done = true;
- } else {
- // Spawn background thread to probe known endpoints + refine geo via IP API
- g_network_probe_thread = std.Thread.spawn(.{}, probeNetworkNodes, .{}) catch null;
- }
-
- // v2.4: DePIN Docker detection on startup
- g_depin_docker_ok = depinCheckDocker();
- g_depin_running = if (g_depin_docker_ok) depinCheckRunning() else false;
-}
-
-const GlassPanel = struct {
- // Position & size
- x: f32,
- y: f32,
- width: f32,
- height: f32,
-
- // Target position (for animations)
- target_x: f32,
- target_y: f32,
- target_w: f32,
- target_h: f32,
-
- // Animation
- state: PanelState,
- anim_t: f32, // 0..1
- opacity: f32,
- scale: f32,
-
- // Content
- panel_type: PanelType,
- title: [64]u8,
- title_len: usize,
-
- // Interaction
- dragging: bool,
- drag_offset_x: f32,
- drag_offset_y: f32,
-
- // Velocity for swipe inertia
- vel_x: f32,
- vel_y: f32,
-
- // Resize
- resizing: bool,
- resize_edge: u8, // 0=none, 1=right, 2=bottom, 4=left, 8=top, combos for corners
-
- // Content data
- content_text: [512]u8,
- content_len: usize,
- scroll_y: f32,
- scroll_target: f32, // Smooth scroll target (lerp toward this)
-
- // For tools panel
- tool_selected: usize,
-
- // For voice panel
- voice_amplitude: f32,
- voice_recording: bool,
- voice_wave_phase: f32,
-
- // For chat panel - multi-modal content
- chat_messages: [32][256]u8,
- chat_msg_lens: [32]usize,
- chat_msg_is_user: [32]bool,
- chat_msg_count: usize,
- chat_input: [256]u8,
- chat_input_len: usize,
- chat_ripple: f32, // Response ripple animation
-
- // For code panel - syntax waves
- code_wave_phase: f32,
- code_cursor_line: usize,
-
- // For vision panel
- vision_analyzing: bool,
- vision_progress: f32,
- vision_result: [256]u8,
- vision_result_len: usize,
-
- // Focus state for full-screen transitions
- is_focused: bool,
- focus_ripple: f32,
- pre_focus_x: f32,
- pre_focus_y: f32,
- pre_focus_w: f32,
- pre_focus_h: f32,
-
- // JARVIS spherical morph animation
- jarvis_morph: f32, // 0 = sphere, 1 = rectangle
- jarvis_glow_pulse: f32,
- jarvis_ring_rotation: f32,
-
- // For finder panel
- finder_path: [512]u8,
- finder_path_len: usize,
- finder_entries: [64]FinderEntry,
- finder_entry_count: usize,
- finder_selected: usize,
- finder_animation: f32,
- finder_ripple: f32, // 0-1 ripple animation on folder open
-
- // For system monitor panel
- sys_cpu_usage: f32, // 0-100%
- sys_mem_used: f32, // GB
- sys_mem_total: f32, // GB
- sys_cpu_temp: f32, // Celsius
- sys_update_timer: f32, // Timer for updates
-
- // For sacred world panel (27 worlds of 999 kingdom)
- world_id: u8, // Block index 0-26
- world_anim_phase: f32, // phi-spiral animation
-
- // Emergent Wave ScrollView v1.0
- // When enabled, replaces legacy lerp scroll with phi-damped wave physics
- wave_scroll_enabled: bool,
- wave_sv: wave_scroll.WaveScrollView,
-
- pub fn init(px: f32, py: f32, pw: f32, ph: f32, ptype: PanelType, title_str: []const u8) GlassPanel {
- var panel = GlassPanel{
- .x = px,
- .y = py,
- .width = pw,
- .height = ph,
- .target_x = px,
- .target_y = py,
- .target_w = pw,
- .target_h = ph,
- .state = .closed,
- .anim_t = 0,
- .opacity = 0,
- .scale = 0.8,
- .panel_type = ptype,
- .title = undefined,
- .title_len = @min(title_str.len, 63),
- .dragging = false,
- .drag_offset_x = 0,
- .drag_offset_y = 0,
- .vel_x = 0,
- .vel_y = 0,
- .resizing = false,
- .resize_edge = 0,
- .content_text = undefined,
- .content_len = 0,
- .scroll_y = 0,
- .scroll_target = 0,
- .tool_selected = 0,
- .voice_amplitude = 0,
- .voice_recording = false,
- .voice_wave_phase = 0,
- .chat_messages = undefined,
- .chat_msg_lens = .{0} ** 32,
- .chat_msg_is_user = .{false} ** 32,
- .chat_msg_count = 0,
- .chat_input = undefined,
- .chat_input_len = 0,
- .chat_ripple = 0,
- .code_wave_phase = 0,
- .code_cursor_line = 0,
- .vision_analyzing = false,
- .vision_progress = 0,
- .vision_result = undefined,
- .vision_result_len = 0,
- .is_focused = false,
- .focus_ripple = 0,
- .pre_focus_x = px,
- .pre_focus_y = py,
- .pre_focus_w = pw,
- .pre_focus_h = ph,
- .jarvis_morph = 1.0, // Start as rectangle
- .jarvis_glow_pulse = 0,
- .jarvis_ring_rotation = 0,
- .finder_path = undefined,
- .finder_path_len = 0,
- .finder_entries = undefined,
- .finder_entry_count = 0,
- .finder_selected = 0,
- .finder_animation = 0,
- .finder_ripple = 0,
- .sys_cpu_usage = 0,
- .sys_mem_used = 0,
- .sys_mem_total = 16.0, // Default 16GB
- .sys_cpu_temp = 45.0, // Default temp
- .sys_update_timer = 0,
- .world_id = 0,
- .world_anim_phase = 0,
- .wave_scroll_enabled = false,
- .wave_sv = wave_scroll.WaveScrollView.init(px, py + 32.0, pw, ph - 32.0),
- };
- @memcpy(panel.title[0..panel.title_len], title_str[0..panel.title_len]);
- panel.title[panel.title_len] = 0;
-
- // Initialize finder entries
- for (&panel.finder_entries) |*entry| {
- entry.* = FinderEntry.init();
- }
-
- // Default content based on type
- const default_content = switch (ptype) {
- .chat => "Type a message...",
- .code => "// Your code here\nfn main() void {\n \n}",
- .tools => "inference\nembedding\nsearch\ngenerate",
- .settings => "Dark Mode: ON\nSound: OFF\nAnimations: ON",
- .vision => "Drop image or click to load...",
- .voice => "Press to speak...",
- .finder => "Loading directory...",
- .system => "System monitor",
- .sacred_world => "Sacred Mathematics",
- };
-
- // Initialize finder with current directory for finder panels
- if (ptype == .finder) {
- panel.loadDirectory(".");
- }
- const content_copy_len = @min(default_content.len, 511);
- @memcpy(panel.content_text[0..content_copy_len], default_content[0..content_copy_len]);
- panel.content_len = content_copy_len;
-
- return panel;
- }
-
- // Phi-based easing (smooth cosmic feel)
- fn easePhiInOut(t: f32) f32 {
- if (t < 0.5) {
- return 2.0 * t * t * PHI_INV;
- } else {
- const f = -2.0 * t + 2.0;
- return 1.0 - (f * f * PHI_INV) / 2.0;
- }
- }
-
- pub fn open(self: *GlassPanel) void {
- if (self.state == .closed or self.state == .closing) {
- self.state = .opening;
- self.anim_t = 0;
- }
- }
-
- pub fn close(self: *GlassPanel) void {
- if (self.state == .open or self.state == .opening) {
- self.state = .closing;
- self.anim_t = 0;
- }
- }
-
- pub fn minimize(self: *GlassPanel) void {
- if (self.state == .open) {
- self.state = .minimizing;
- self.anim_t = 0;
- self.target_y = @as(f32, @floatFromInt(g_height)) + 100;
- }
- }
-
- // Focus panel to full screen with cosmic transition
- pub fn focus(self: *GlassPanel) void {
- if (!self.is_focused and self.state == .open) {
- // Save current position for restoration
- self.pre_focus_x = self.x;
- self.pre_focus_y = self.y;
- self.pre_focus_w = self.width;
- self.pre_focus_h = self.height;
- // Set target to full screen with margin
- self.target_x = 20;
- self.target_y = 40;
- self.target_w = @as(f32, @floatFromInt(g_width)) - 40;
- self.target_h = @as(f32, @floatFromInt(g_height)) - 100;
- self.is_focused = true;
- self.focus_ripple = 1.0;
- }
- }
-
- // Unfocus panel - restore to previous position
- pub fn unfocus(self: *GlassPanel) void {
- if (self.is_focused) {
- self.target_x = self.pre_focus_x;
- self.target_y = self.pre_focus_y;
- self.target_w = self.pre_focus_w;
- self.target_h = self.pre_focus_h;
- self.is_focused = false;
- self.focus_ripple = 1.0;
- self.jarvis_morph = 1.0; // Rectangle
- }
- }
-
- // JARVIS-style focus with spherical morph animation
- pub fn jarvisFocus(self: *GlassPanel) void {
- // Save current position for restoration
- if (!self.is_focused) {
- self.pre_focus_x = self.x;
- self.pre_focus_y = self.y;
- self.pre_focus_w = self.width;
- self.pre_focus_h = self.height;
- }
- // Set target to full screen with margin
- self.target_x = 20;
- self.target_y = 40;
- self.target_w = @as(f32, @floatFromInt(g_width)) - 40;
- self.target_h = @as(f32, @floatFromInt(g_height)) - 100;
- self.is_focused = true;
- self.focus_ripple = 1.0;
- // Start from sphere (0) and morph to rectangle (1)
- self.jarvis_morph = 0;
- self.jarvis_glow_pulse = 1.0;
- }
-
- // Add chat message with response ripple
- pub fn addChatMessage(self: *GlassPanel, msg: []const u8, is_user: bool) void {
- if (self.chat_msg_count >= 32) {
- // Shift messages up (drop oldest)
- for (0..31) |i| {
- @memcpy(&self.chat_messages[i], &self.chat_messages[i + 1]);
- self.chat_msg_lens[i] = self.chat_msg_lens[i + 1];
- self.chat_msg_is_user[i] = self.chat_msg_is_user[i + 1];
- }
- self.chat_msg_count = 31;
- }
- const idx = self.chat_msg_count;
- const copy_len = @min(msg.len, 255);
- @memcpy(self.chat_messages[idx][0..copy_len], msg[0..copy_len]);
- self.chat_msg_lens[idx] = copy_len;
- self.chat_msg_is_user[idx] = is_user;
- self.chat_msg_count += 1;
- // Trigger response ripple for AI responses
- if (!is_user) {
- self.chat_ripple = 1.0;
- }
- }
-
- pub fn update(self: *GlassPanel, dt: f32) void {
- const anim_speed: f32 = 3.0; // Animation duration ~0.33s
-
- switch (self.state) {
- .opening => {
- self.anim_t += dt * anim_speed;
- if (self.anim_t >= 1.0) {
- self.anim_t = 1.0;
- self.state = .open;
- }
- const e = easePhiInOut(self.anim_t);
- self.opacity = e;
- self.scale = 0.8 + e * 0.2;
- },
- .closing => {
- self.anim_t += dt * anim_speed;
- if (self.anim_t >= 1.0) {
- self.anim_t = 1.0;
- self.state = .closed;
- }
- const e = easePhiInOut(self.anim_t);
- self.opacity = 1.0 - e;
- self.scale = 1.0 - e * 0.2;
- },
- .minimizing => {
- self.anim_t += dt * anim_speed;
- if (self.anim_t >= 1.0) {
- self.state = .closed;
- }
- const e = easePhiInOut(self.anim_t);
- self.y = self.y + (self.target_y - self.y) * e * 0.3;
- self.opacity = 1.0 - e;
- self.scale = 1.0 - e * 0.5;
- },
- .open => {
- self.opacity = 1.0;
- self.scale = 1.0;
-
- // === JARVIS FOCUS TRANSITION ANIMATION ===
- const focus_speed: f32 = 4.0; // Phi-smooth transition
- if (self.is_focused or self.focus_ripple > 0) {
- // Animate position and size towards target
- const lerp_factor = dt * focus_speed;
- self.x += (self.target_x - self.x) * lerp_factor;
- self.y += (self.target_y - self.y) * lerp_factor;
- self.width += (self.target_w - self.width) * lerp_factor;
- self.height += (self.target_h - self.height) * lerp_factor;
- // Decay focus ripple
- if (self.focus_ripple > 0) {
- self.focus_ripple -= dt * 1.5;
- if (self.focus_ripple < 0) self.focus_ripple = 0;
- }
- }
-
- // JARVIS spherical morph (0 = sphere β 1 = rectangle)
- if (self.jarvis_morph < 1.0) {
- self.jarvis_morph += dt * 2.5;
- if (self.jarvis_morph > 1.0) self.jarvis_morph = 1.0;
- }
-
- // JARVIS glow pulse decay
- if (self.jarvis_glow_pulse > 0) {
- self.jarvis_glow_pulse -= dt * 1.2;
- if (self.jarvis_glow_pulse < 0) self.jarvis_glow_pulse = 0;
- }
-
- // JARVIS ring rotation (continuous)
- if (self.is_focused) {
- self.jarvis_ring_rotation += dt * 2.0;
- }
-
- // === MULTI-MODAL CONTENT ANIMATIONS ===
-
- // Chat ripple animation
- if (self.chat_ripple > 0) {
- self.chat_ripple -= dt * 2.0;
- if (self.chat_ripple < 0) self.chat_ripple = 0;
- }
-
- // Code wave phase (continuous syntax animation)
- if (self.panel_type == .code) {
- self.code_wave_phase += dt * 2.0;
- }
-
- // Vision analyzing progress
- if (self.vision_analyzing) {
- self.vision_progress += dt * 0.5;
- if (self.vision_progress >= 1.0) {
- self.vision_analyzing = false;
- self.vision_progress = 1.0;
- // Set result
- const result = "Cosmic image analyzed: wave patterns detected!";
- @memcpy(self.vision_result[0..result.len], result);
- self.vision_result_len = result.len;
- }
- }
-
- // Voice wave phase and amplitude
- if (self.panel_type == .voice) {
- self.voice_wave_phase += dt * 8.0;
- if (self.voice_recording) {
- // Simulate audio amplitude
- self.voice_amplitude = 0.5 + @sin(self.voice_wave_phase) * 0.3;
- } else {
- self.voice_amplitude *= 0.9; // Decay
- }
- }
-
- // Animate finder entries appearing
- if (self.panel_type == .finder and self.finder_animation < 1.0) {
- self.finder_animation += dt * 2.0;
- if (self.finder_animation > 1.0) self.finder_animation = 1.0;
- }
-
- // Animate finder ripple effect
- if (self.panel_type == .finder and self.finder_ripple > 0) {
- self.finder_ripple -= dt * 1.5;
- if (self.finder_ripple < 0) self.finder_ripple = 0;
- }
-
- // Apply velocity (swipe inertia) - only when not focused
- if (!self.dragging and !self.is_focused) {
- self.x += self.vel_x * dt;
- self.y += self.vel_y * dt;
- // Friction
- self.vel_x *= 0.92;
- self.vel_y *= 0.92;
-
- // Bounce off edges
- const fw = @as(f32, @floatFromInt(g_width));
- const fh = @as(f32, @floatFromInt(g_height));
- if (self.x < 0) {
- self.x = 0;
- self.vel_x = -self.vel_x * 0.5;
- }
- if (self.x + self.width > fw) {
- self.x = fw - self.width;
- self.vel_x = -self.vel_x * 0.5;
- }
- if (self.y < 0) {
- self.y = 0;
- self.vel_y = -self.vel_y * 0.5;
- }
- if (self.y + self.height > fh - 60) {
- self.y = fh - 60 - self.height;
- self.vel_y = -self.vel_y * 0.5;
- }
- }
- },
- .closed => {},
- .maximizing => {},
- }
- }
-
- pub fn draw(self: *const GlassPanel, time: f32, font: rl.Font) void {
- if (self.state == .closed) return;
-
- const cx = self.x + self.width / 2;
- const cy = self.y + self.height / 2;
-
- // Scale from center
- const sw = self.width * self.scale;
- const sh = self.height * self.scale;
- const sx = cx - sw / 2;
- const sy = cy - sh / 2;
-
- // Skip drawing if panel is not focused (teleportation effect - only show focused)
- if (!self.is_focused and self.state == .open) {
- return; // Hide unfocused panels completely
- }
-
- // Smoother rounded corners (Hyper style)
- const roundness = 0.06; // Slightly larger for smoother look
-
- // === FOCUS TRANSITION RIPPLE === REMOVED (Teleportation effect - instant switch)
- // if (self.focus_ripple > 0) {
- // const ripple_progress = 1.0 - self.focus_ripple;
- // const max_radius = @max(sw, sh);
- // for (0..5) |ring| {
- // const ring_f = @as(f32, @floatFromInt(ring));
- // const ring_delay = ring_f * 0.1;
- // const ring_progress = @max(0, @min(1.0, (ripple_progress - ring_delay) / 0.7));
- // if (ring_progress > 0) {
- // const ripple_radius = ring_progress * max_radius;
- // const ripple_alpha: u8 = @intFromFloat(@max(0, self.opacity * 150 * (1.0 - ring_progress) * self.focus_ripple));
- // const ripple_color = if (self.is_focused) rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = ripple_alpha } else rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = ripple_alpha };
- // rl.DrawCircleLines(@intFromFloat(cx), @intFromFloat(cy), ripple_radius, ripple_color);
- // }
- // }
- // }
-
- // === FOCUSED GLOW EFFECT === REMOVED (Hyper style - clean borders)
- // if (self.is_focused) {
- // const glow_pulse = @sin(time * 3) * 0.2 + 0.8;
- // const glow_alpha: u8 = @intFromFloat(self.opacity * 25 * glow_pulse);
- // rl.DrawRectangleRounded(
- // .{ .x = sx - 3, .y = sy - 3, .width = sw + 6, .height = sh + 6 },
- // roundness, 16,
- // rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = glow_alpha },
- // );
- // }
-
- // === PROFESSIONAL GLASSMORPHISM ===
-
- // Shadow (soft, offset down-right β darker on light theme for visibility)
- const shadow_offset: f32 = 4.0;
- const shadow_strength: f32 = if (theme.isDark()) 40 else 80;
- const shadow_alpha: u8 = @intFromFloat(self.opacity * shadow_strength);
- const shadow_color = rl.Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = shadow_alpha };
- rl.DrawRectangleRounded(
- .{ .x = sx + shadow_offset, .y = sy + shadow_offset, .width = sw, .height = sh },
- roundness,
- 32, // More segments for smoother corners
- shadow_color,
- );
-
- // Main glass background (Hyper style)
- // Dark theme: semi-transparent glass effect (230 alpha)
- // Light theme: fully opaque (255 alpha) β no dark bleed-through
- const bg_base_alpha: f32 = if (self.panel_type == .sacred_world) 255 else if (theme.isDark()) 230 else 255;
- const bg_alpha: u8 = @intFromFloat(self.opacity * bg_base_alpha);
- const bg_color = if (self.panel_type == .sacred_world) @as(rl.Color, @bitCast(theme.sacred_world_bg)) else BG_SURFACE;
- rl.DrawRectangleRounded(
- .{ .x = sx, .y = sy, .width = sw, .height = sh },
- roundness,
- 32,
- withAlpha(bg_color, bg_alpha),
- );
-
- // Gradient overlay REMOVED (clean Hyper style - no gradient)
- // const grad_alpha: u8 = @intFromFloat(self.opacity * 15);
- // rl.DrawRectangleRounded(
- // .{ .x = sx, .y = sy, .width = sw, .height = sh / 3 },
- // roundness, 32,
- // withAlpha(TEXT_WHITE, grad_alpha),
- // );
-
- // Border β visible on both themes (stronger on light)
- const border_strength: f32 = if (theme.isDark()) 40 else 180;
- const border_alpha: u8 = @intFromFloat(self.opacity * border_strength);
- rl.DrawRectangleRoundedLinesEx(
- .{ .x = sx, .y = sy, .width = sw, .height = sh },
- roundness,
- 32,
- 1.0,
- withAlpha(@as(rl.Color, @bitCast(theme.border)), border_alpha),
- );
-
- // Wave scroll: animated cyan border pulse (Emergent Wave ScrollView v1.0)
- if (self.wave_scroll_enabled) {
- const wave_border_pulse = @sin(self.wave_sv.wave_time * 2.0) * 0.3 + 0.4;
- const wb_alpha: u8 = @intFromFloat(@max(0, @min(255.0, wave_border_pulse * 50.0 * self.opacity)));
- rl.DrawRectangleRoundedLinesEx(
- .{ .x = sx - 1, .y = sy - 1, .width = sw + 2, .height = sh + 2 },
- roundness,
- 32,
- 1.0,
- rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = wb_alpha },
- );
- }
-
- // === TITLE BAR (Hyper style - no traffic lights) ===
- // Traffic light buttons REMOVED - use Shift+1-8 for panel switching
- // const btn_y = sy + 14;
- // const btn_spacing: f32 = 20;
- // rl.DrawCircle(@intFromFloat(sx + 16), @intFromFloat(btn_y), 6, withAlpha(BTN_CLOSE, alpha));
- // rl.DrawCircle(@intFromFloat(sx + 16 + btn_spacing), @intFromFloat(btn_y), 6, withAlpha(BTN_MINIMIZE, alpha));
- // rl.DrawCircle(@intFromFloat(sx + 16 + btn_spacing * 2), @intFromFloat(btn_y), 6, withAlpha(BTN_MAXIMIZE, alpha));
-
- // Title (centered)
- const title_alpha: u8 = @intFromFloat(self.opacity * 200);
- const title_width: f32 = @floatFromInt(rl.MeasureText(&self.title, 14));
- const title_x = sx + (sw - title_width) / 2;
- rl.DrawTextEx(font, &self.title, .{ .x = title_x, .y = sy + 6 }, 16, 0.5, withAlpha(@as(rl.Color, @bitCast(theme.panel_title)), title_alpha));
-
- // Title bar separator
- const sep_alpha: u8 = @intFromFloat(self.opacity * 30);
- rl.DrawLine(@intFromFloat(sx), @intFromFloat(sy + 32), @intFromFloat(sx + sw), @intFromFloat(sy + 32), withAlpha(@as(rl.Color, @bitCast(theme.panel_title_sep)), sep_alpha));
-
- // === CONTENT AREA (Multi-Modal) ===
- const content_y = sy + 40;
- const content_h = sh - 50;
- const content_alpha: u8 = @intFromFloat(self.opacity * theme.panel_content_alpha);
- const text_color = withAlpha(CONTENT_TEXT, content_alpha);
-
- switch (self.panel_type) {
- .chat => {
- // === MULTI-MODAL CHAT PANEL ===
- // Response ripple animation (cosmic wave on new AI message)
- if (self.chat_ripple > 0) {
- const ripple_center_y = content_y + content_h / 2;
- const ripple_progress = 1.0 - self.chat_ripple;
- for (0..3) |ring| {
- const ring_f = @as(f32, @floatFromInt(ring));
- const ring_radius = ripple_progress * sw * 0.5 + ring_f * 20;
- const ring_alpha: u8 = @intFromFloat(@max(0, self.opacity * 120 * self.chat_ripple));
- rl.DrawCircleLines(@intFromFloat(sx + sw / 2), @intFromFloat(ripple_center_y), ring_radius, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = ring_alpha });
- }
- }
-
- // Messages area with scroll support
- const msg_area_h = content_h - 50;
- const msg_y_start = content_y + 5 - self.scroll_y;
- const line_spacing: f32 = 28;
-
- for (0..self.chat_msg_count) |i| {
- const msg_y = msg_y_start + @as(f32, @floatFromInt(i)) * line_spacing;
- // Skip messages outside visible area
- if (msg_y < content_y - line_spacing) continue;
- if (msg_y > content_y + msg_area_h) break;
-
- const is_user = self.chat_msg_is_user[i];
- const label_color = if (is_user) withAlpha(TEXT_WHITE, content_alpha) else withAlpha(HYPER_GREEN, content_alpha);
- const label = if (is_user) "YOU:" else "AI:";
-
- rl.DrawTextEx(font, label.ptr, .{ .x = sx + 12, .y = msg_y }, 11, 0.5, label_color);
-
- // Message text
- var msg_buf: [260:0]u8 = undefined;
- const msg_len = self.chat_msg_lens[i];
- const show_len = @min(msg_len, @as(usize, @intFromFloat((sw - 60) / 6)));
- @memcpy(msg_buf[0..show_len], self.chat_messages[i][0..show_len]);
- msg_buf[show_len] = 0;
- rl.DrawTextEx(font, &msg_buf, .{ .x = sx + 45, .y = msg_y }, 11, 0.5, text_color);
- }
-
- // Welcome message if empty
- if (self.chat_msg_count == 0) {
- rl.DrawTextEx(font, "AI:", .{ .x = sx + 12, .y = content_y + 10 }, 12, 0.5, withAlpha(HYPER_GREEN, content_alpha));
- rl.DrawTextEx(font, "Hello! Type a message to chat.", .{ .x = sx + 12, .y = content_y + 28 }, 12, 0.5, text_color);
- }
-
- // Input area (bottom)
- const input_y = sy + sh - 40;
- rl.DrawRectangle(@intFromFloat(sx + 8), @intFromFloat(input_y), @intFromFloat(sw - 16), 30, withAlpha(BG_INPUT, content_alpha));
- rl.DrawRectangleLines(@intFromFloat(sx + 8), @intFromFloat(input_y), @intFromFloat(sw - 16), 30, withAlpha(BORDER_LIGHT, content_alpha));
-
- // Show current input or placeholder
- if (self.chat_input_len > 0) {
- var input_buf: [260:0]u8 = undefined;
- const show_len = @min(self.chat_input_len, 50);
- @memcpy(input_buf[0..show_len], self.chat_input[0..show_len]);
- // Cursor blink
- if (@mod(@as(u32, @intFromFloat(time * 3)), 2) == 0) {
- input_buf[show_len] = '_';
- input_buf[show_len + 1] = 0;
- } else {
- input_buf[show_len] = 0;
- }
- rl.DrawTextEx(font, &input_buf, .{ .x = sx + 16, .y = input_y + 8 }, 12, 0.5, NOVA_WHITE);
- } else {
- rl.DrawTextEx(font, "Type message... (click to focus)", .{ .x = sx + 16, .y = input_y + 8 }, 11, 0.5, withAlpha(MUTED_GRAY, content_alpha));
- }
- },
- .code => {
- // === MULTI-MODAL CODE EDITOR WITH SYNTAX WAVES ===
- const line_h: f32 = 18;
- const code_lines = [_][]const u8{
- "// TRINITY COSMIC ENGINE",
- "const PHI: f32 = 1.618033988;",
- "",
- "fn main() !void {",
- " const grid = try init();",
- " defer grid.deinit();",
- "",
- " // Cosmic infinity loop",
- " while (running) {",
- " update();",
- " render();",
- " }",
- "}",
- };
-
- for (code_lines, 0..) |line, i| {
- const fi = @as(f32, @floatFromInt(i));
- // Wave offset for each line
- const wave_offset = @sin(self.code_wave_phase + fi * 0.3) * 2;
- const line_y = content_y + 10 + fi * line_h;
- if (line_y > sy + sh - 20) break;
-
- // Line number with wave glow
- const ln_glow = @abs(@sin(self.code_wave_phase * 0.5 + fi * 0.5));
- const ln_alpha: u8 = @intFromFloat(50 + ln_glow * 30);
- var ln_buf: [8:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&ln_buf, "{d:>3}", .{i + 1}) catch {};
- rl.DrawTextEx(font, &ln_buf, .{ .x = sx + 8, .y = line_y }, 10, 0.5, withAlpha(@as(rl.Color, @bitCast(theme.line_number)), ln_alpha + content_alpha / 2));
-
- if (line.len == 0) continue;
-
- // Syntax-based coloring with wave brightness modulation
- const wave_brightness: f32 = 0.8 + @sin(self.code_wave_phase + fi * 0.2) * 0.2;
-
- var code_color: rl.Color = undefined;
- if (line[0] == '/' and line.len > 1 and line[1] == '/') {
- // Comment - green with wave
- code_color = rl.Color{ .r = @intFromFloat(0x50 * wave_brightness), .g = @intFromFloat(0xA0 * wave_brightness), .b = @intFromFloat(0x50 * wave_brightness), .a = content_alpha };
- } else if (std.mem.startsWith(u8, line, "const") or std.mem.startsWith(u8, line, "fn ") or std.mem.startsWith(u8, line, " const") or std.mem.startsWith(u8, line, " defer") or std.mem.startsWith(u8, line, " while")) {
- // Keyword - green wave
- code_color = rl.Color{ .r = @intFromFloat(0x00 * wave_brightness), .g = @intFromFloat(0xFF * wave_brightness), .b = @intFromFloat(0x88 * wave_brightness), .a = content_alpha };
- } else if (std.mem.indexOf(u8, line, "PHI") != null or std.mem.indexOf(u8, line, "1.618") != null) {
- // PHI constant - golden wave
- code_color = rl.Color{ .r = @intFromFloat(0xFF * wave_brightness), .g = @intFromFloat(0xD7 * wave_brightness), .b = @intFromFloat(0x00 * wave_brightness), .a = content_alpha };
- } else {
- code_color = rl.Color{ .r = @intFromFloat(0xC0 * wave_brightness), .g = @intFromFloat(0xC8 * wave_brightness), .b = @intFromFloat(0xD0 * wave_brightness), .a = content_alpha };
- }
-
- // Draw code with wave offset
- rl.DrawText(line.ptr, @intFromFloat(sx + 40 + wave_offset), @intFromFloat(line_y), 11, code_color);
-
- // Trailing wave particles for active lines
- if (i == self.code_cursor_line) {
- const particle_x = sx + 40 + @as(f32, @floatFromInt(line.len)) * 7 + 10;
- const particle_glow = @abs(@sin(self.code_wave_phase * 3));
- rl.DrawCircle(@intFromFloat(particle_x), @intFromFloat(line_y + 6), 3 + particle_glow * 2, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = @intFromFloat(self.opacity * 150) });
- }
- }
-
- // Bottom status with wave
- const status_y = sy + sh - 25;
- const status_wave = @sin(time * 2) * 0.3 + 0.7;
- rl.DrawText("Zig | UTF-8 | phi^2 + 1/phi^2 = 3", @intFromFloat(sx + 12), @intFromFloat(status_y), 10, rl.Color{ .r = @intFromFloat(0x60 * status_wave), .g = @intFromFloat(0x70 * status_wave), .b = @intFromFloat(0x80 * status_wave), .a = content_alpha });
- },
- .tools => {
- // Tools list
- const tools_list = [_][]const u8{ "inference", "embedding", "search", "generate", "vision", "voice" };
- for (tools_list, 0..) |tool, i| {
- const tool_y = content_y + 10 + @as(f32, @floatFromInt(i)) * 28;
- const is_selected = i == self.tool_selected;
- // Background
- if (is_selected) {
- rl.DrawRectangle(@intFromFloat(sx + 8), @intFromFloat(tool_y - 2), @intFromFloat(sw - 16), 24, withAlpha(@as(rl.Color, @bitCast(theme.tool_selected_bg)), content_alpha));
- }
- // Icon placeholder
- rl.DrawCircle(@intFromFloat(sx + 22), @intFromFloat(tool_y + 10), 6, withAlpha(HYPER_GREEN, content_alpha));
- // Text
- rl.DrawText(tool.ptr, @intFromFloat(sx + 36), @intFromFloat(tool_y + 4), 12, if (is_selected) withAlpha(TEXT_WHITE, content_alpha) else text_color);
- }
- },
- .settings => {
- // Settings toggles
- const settings = [_]struct { name: []const u8, on: bool }{
- .{ .name = "Dark Mode", .on = true },
- .{ .name = "Animations", .on = true },
- .{ .name = "Sound", .on = false },
- .{ .name = "Auto-save", .on = true },
- .{ .name = "Notifications", .on = false },
- };
- for (settings, 0..) |setting, i| {
- const set_y = content_y + 10 + @as(f32, @floatFromInt(i)) * 32;
- // Label
- rl.DrawText(setting.name.ptr, @intFromFloat(sx + 16), @intFromFloat(set_y + 4), 12, text_color);
- // Toggle
- const toggle_x = sx + sw - 50;
- const toggle_color = if (setting.on) withAlpha(@as(rl.Color, @bitCast(theme.settings_toggle_on)), content_alpha) else withAlpha(@as(rl.Color, @bitCast(theme.settings_toggle_off)), content_alpha);
- rl.DrawRectangleRounded(.{ .x = toggle_x, .y = set_y, .width = 36, .height = 20 }, 0.5, 8, toggle_color);
- const knob_x = if (setting.on) toggle_x + 20 else toggle_x + 4;
- rl.DrawCircle(@intFromFloat(knob_x + 6), @intFromFloat(set_y + 10), 8, withAlpha(TEXT_WHITE, content_alpha));
- }
- },
- .vision => {
- // === MULTI-MODAL VISION ANALYZER ===
- const img_size: f32 = @min(sw - 40, content_h - 80);
- const img_x = sx + (sw - img_size) / 2;
- const img_y = content_y + 10;
- const img_h = img_size * 0.6;
-
- // Image placeholder with scanning effect
- rl.DrawRectangleRounded(.{ .x = img_x, .y = img_y, .width = img_size, .height = img_h }, 0.02, 8, withAlpha(BG_INPUT, content_alpha));
-
- // Analyzing animation - scanning line + wave burst
- if (self.vision_analyzing) {
- // Scanning line
- const scan_y = img_y + (self.vision_progress * img_h);
- rl.DrawLine(@intFromFloat(img_x + 5), @intFromFloat(scan_y), @intFromFloat(img_x + img_size - 5), @intFromFloat(scan_y), rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = @intFromFloat(self.opacity * 200) });
- // Glow
- rl.DrawRectangle(@intFromFloat(img_x), @intFromFloat(scan_y - 2), @intFromFloat(img_size), 4, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = @intFromFloat(self.opacity * 50) });
-
- // Wave burst from scan position
- const burst_rings: usize = 3;
- for (0..burst_rings) |ring| {
- const ring_f = @as(f32, @floatFromInt(ring));
- const ring_radius = 10 + ring_f * 15 + @sin(time * 5) * 5;
- const ring_alpha: u8 = @intFromFloat(@max(0, self.opacity * 60 * (1.0 - ring_f / 3.0)));
- rl.DrawCircleLines(@intFromFloat(img_x + img_size / 2), @intFromFloat(scan_y), ring_radius, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = ring_alpha });
- }
-
- // Progress bar
- const progress_w = (sw - 40) * self.vision_progress;
- rl.DrawRectangle(@intFromFloat(sx + 20), @intFromFloat(img_y + img_h + 10), @intFromFloat(progress_w), 4, NEON_MAGENTA);
- rl.DrawRectangleLines(@intFromFloat(sx + 20), @intFromFloat(img_y + img_h + 10), @intFromFloat(sw - 40), 4, rl.Color{ .r = 0x40, .g = 0x40, .b = 0x50, .a = content_alpha });
-
- rl.DrawText("Analyzing cosmic patterns...", @intFromFloat(sx + 20), @intFromFloat(img_y + img_h + 20), 11, NEON_CYAN);
- } else if (self.vision_result_len > 0) {
- // Show result with wave glow
- const result_wave = @sin(time * 2) * 0.2 + 0.8;
- var result_buf: [260:0]u8 = undefined;
- @memcpy(result_buf[0..self.vision_result_len], self.vision_result[0..self.vision_result_len]);
- result_buf[self.vision_result_len] = 0;
- rl.DrawText(&result_buf, @intFromFloat(sx + 20), @intFromFloat(img_y + img_h + 15), 11, rl.Color{ .r = @intFromFloat(0x80 * result_wave), .g = @intFromFloat(0xFF * result_wave), .b = @intFromFloat(0x80 * result_wave), .a = content_alpha });
-
- // Success burst rings
- for (0..3) |ring| {
- const ring_f = @as(f32, @floatFromInt(ring));
- const ring_radius = 30 + ring_f * 25 + @sin(time * 2 + ring_f) * 10;
- rl.DrawCircleLines(@intFromFloat(img_x + img_size / 2), @intFromFloat(img_y + img_h / 2), ring_radius, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = @intFromFloat(self.opacity * 30) });
- }
- } else {
- // Drop zone
- rl.DrawRectangleRoundedLinesEx(.{ .x = img_x, .y = img_y, .width = img_size, .height = img_h }, 0.02, 8, 2.0, rl.Color{ .r = 0x40, .g = 0x40, .b = 0x40, .a = @intFromFloat(self.opacity * 100) });
- rl.DrawText("+", @intFromFloat(img_x + img_size / 2 - 15), @intFromFloat(img_y + img_h / 2 - 20), 40, rl.Color{ .r = 0x60, .g = 0x60, .b = 0x60, .a = content_alpha });
- rl.DrawText("Click to analyze image", @intFromFloat(sx + 20), @intFromFloat(img_y + img_h + 15), 11, withAlpha(MUTED_GRAY, content_alpha));
- }
- },
- .voice => {
- // === MULTI-MODAL VOICE PANEL WITH STT RIPPLE ===
- const wave_center_y = content_y + content_h / 2 - 20;
- const wave_width = sw - 60;
-
- // Recording button (center top)
- const mic_btn_x = sx + sw / 2;
- const mic_btn_y = content_y + 30;
- const mic_btn_radius: f32 = if (self.voice_recording) 25 else 20;
- const mic_btn_pulse = @sin(self.voice_wave_phase) * 3;
-
- // Recording glow rings
- if (self.voice_recording) {
- for (0..4) |ring| {
- const ring_f = @as(f32, @floatFromInt(ring));
- const ring_radius = mic_btn_radius + 10 + ring_f * 15 + @sin(self.voice_wave_phase + ring_f) * 5;
- const ring_alpha: u8 = @intFromFloat(@max(0, self.opacity * 80 * (1.0 - ring_f / 4.0)));
- rl.DrawCircleLines(@intFromFloat(mic_btn_x), @intFromFloat(mic_btn_y), ring_radius, rl.Color{ .r = 0xFF, .g = 0x40, .b = 0x40, .a = ring_alpha });
- }
- }
-
- // Button
- const mic_btn_color = if (self.voice_recording) rl.Color{ .r = 0xFF, .g = 0x40, .b = 0x40, .a = content_alpha } else withAlpha(HYPER_GREEN, content_alpha);
- rl.DrawCircle(@intFromFloat(mic_btn_x), @intFromFloat(mic_btn_y), mic_btn_radius + mic_btn_pulse, mic_btn_color);
-
- // Mic icon
- if (self.voice_recording) {
- rl.DrawRectangle(@intFromFloat(mic_btn_x - 4), @intFromFloat(mic_btn_y - 8), 8, 12, withAlpha(TEXT_WHITE, content_alpha));
- } else {
- rl.DrawCircle(@intFromFloat(mic_btn_x), @intFromFloat(mic_btn_y), 8, withAlpha(TEXT_WHITE, content_alpha));
- }
-
- // === WAVEFORM VISUALIZATION ===
- const num_bars: usize = 48;
- const bar_w = wave_width / @as(f32, @floatFromInt(num_bars));
-
- for (0..num_bars) |i| {
- const fi = @as(f32, @floatFromInt(i));
- // Multiple wave frequencies for complex waveform
- const wave1 = @sin(fi * 0.3 + self.voice_wave_phase);
- const wave2 = @sin(fi * 0.7 + self.voice_wave_phase * 1.5) * 0.5;
- const wave3 = @sin(fi * 0.1 + self.voice_wave_phase * 0.3) * 0.3;
- const combined = (wave1 + wave2 + wave3) / 1.8;
-
- const bar_h = 15.0 + combined * 40.0 * (0.3 + self.voice_amplitude * 0.7);
- const bar_x = sx + 30 + fi * bar_w;
- const bar_y = wave_center_y - bar_h / 2;
-
- // Color gradient based on position and amplitude
- const hue = 200.0 + fi * 2.0 + self.voice_amplitude * 60;
- const saturation = 0.6 + self.voice_amplitude * 0.3;
- const rgb = hsvToRgb(hue, saturation, 0.9);
-
- // Draw bar with glow
- if (self.voice_amplitude > 0.3) {
- rl.DrawRectangle(@intFromFloat(bar_x - 1), @intFromFloat(bar_y - 2), @intFromFloat(bar_w), @intFromFloat(bar_h + 4), rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = content_alpha / 4 });
- }
- rl.DrawRectangle(@intFromFloat(bar_x), @intFromFloat(bar_y), @intFromFloat(bar_w - 2), @intFromFloat(bar_h), rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = content_alpha });
- }
-
- // STT Ripple effect when amplitude high
- if (self.voice_amplitude > 0.4) {
- const ripple_radius = 30 + self.voice_amplitude * 50;
- for (0..2) |ring| {
- const ring_f = @as(f32, @floatFromInt(ring));
- rl.DrawCircleLines(@intFromFloat(sx + sw / 2), @intFromFloat(wave_center_y), ripple_radius + ring_f * 20, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = @intFromFloat(self.opacity * 40) });
- }
- }
-
- // Status text
- const status_y = sy + sh - 35;
- if (self.voice_recording) {
- const blink = @mod(@as(u32, @intFromFloat(time * 2)), 2);
- const rec_color = if (blink == 0) rl.Color{ .r = 0xFF, .g = 0x40, .b = 0x40, .a = content_alpha } else rl.Color{ .r = 0x80, .g = 0x20, .b = 0x20, .a = content_alpha };
- rl.DrawCircle(@intFromFloat(sx + 25), @intFromFloat(status_y + 5), 5, rec_color);
- rl.DrawText("Recording... (click to stop)", @intFromFloat(sx + 38), @intFromFloat(status_y), 11, rl.Color{ .r = 0xFF, .g = 0x80, .b = 0x80, .a = content_alpha });
- } else {
- rl.DrawText("Click mic to start recording", @intFromFloat(sx + 20), @intFromFloat(status_y), 11, withAlpha(MUTED_GRAY, content_alpha));
- }
- },
- .finder => {
- // EMERGENT FINDER - Wave-based file system visualization
- const center_x = sx + sw / 2;
- const center_y = content_y + content_h / 2;
-
- // === CENTRAL WAVE SOURCE (Current Directory) ===
- // Pulsating center representing the root
- const pulse = @sin(time * 3.0) * 0.3 + 0.7;
- const core_radius: f32 = 20 * pulse;
-
- // Glow rings emanating from center
- for (0..5) |ring| {
- const ring_f = @as(f32, @floatFromInt(ring));
- const ring_radius = 30 + ring_f * 20 + @sin(time * 2.0 - ring_f * 0.5) * 5;
- const ring_alpha: u8 = @intFromFloat(@max(0, @min(255, self.opacity * (80 - ring_f * 15))));
- rl.DrawCircleLines(@intFromFloat(center_x), @intFromFloat(center_y), ring_radius, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = ring_alpha });
- }
-
- // Central core
- rl.DrawCircle(@intFromFloat(center_x), @intFromFloat(center_y), core_radius, rl.Color{ .r = 0x00, .g = 0xCC, .b = 0x66, .a = @intFromFloat(self.opacity * 200) });
- rl.DrawCircle(@intFromFloat(center_x), @intFromFloat(center_y), core_radius * 0.6, rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = @intFromFloat(self.opacity * 150) });
-
- // === COSMIC RIPPLE EFFECT (on folder navigation) ===
- if (self.finder_ripple > 0) {
- const ripple_progress = 1.0 - self.finder_ripple;
- const max_ripple_radius = @min(content_h, sw) * 0.8;
- for (0..4) |ring| {
- const ring_f = @as(f32, @floatFromInt(ring));
- const ring_delay = ring_f * 0.15;
- const ring_progress = @max(0, @min(1.0, (ripple_progress - ring_delay) / 0.6));
- if (ring_progress > 0) {
- const ripple_radius = ring_progress * max_ripple_radius;
- const ripple_alpha: u8 = @intFromFloat(@max(0, self.opacity * 180 * (1.0 - ring_progress)));
- rl.DrawCircleLines(@intFromFloat(center_x), @intFromFloat(center_y), ripple_radius, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = ripple_alpha });
- rl.DrawCircleLines(@intFromFloat(center_x), @intFromFloat(center_y), ripple_radius + 2, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = ripple_alpha / 2 });
- }
- }
- }
-
- // === ORBITING PHOTONS (Files and Folders) ===
- for (0..self.finder_entry_count) |i| {
- const entry = &self.finder_entries[i];
- const anim_progress = @min(1.0, self.finder_animation + @as(f32, @floatFromInt(i)) * 0.05);
-
- // Calculate orbit position with animation
- const angle = entry.orbit_angle + time * 0.3;
- const radius = entry.orbit_radius * anim_progress;
-
- const ex = center_x + @cos(angle) * radius;
- const ey = center_y + @sin(angle) * radius;
-
- // Get color based on file type
- const base_color = entry.file_type.getColor();
- const entry_alpha: u8 = @intFromFloat(self.opacity * 255 * anim_progress);
-
- // Draw orbit trail (faint arc)
- if (radius > 10) {
- rl.DrawCircleLines(@intFromFloat(center_x), @intFromFloat(center_y), radius, rl.Color{ .r = base_color.r, .g = base_color.g, .b = base_color.b, .a = @intFromFloat(self.opacity * 20) });
- }
-
- // Draw photon (size based on type)
- const photon_size: f32 = if (entry.is_dir) 12 else 8;
- const pulsate = @sin(time * 4.0 + entry.orbit_angle) * 2;
-
- // Glow
- rl.DrawCircle(@intFromFloat(ex), @intFromFloat(ey), photon_size + 4 + pulsate, rl.Color{ .r = base_color.r, .g = base_color.g, .b = base_color.b, .a = entry_alpha / 3 });
- // Core
- rl.DrawCircle(@intFromFloat(ex), @intFromFloat(ey), photon_size + pulsate, rl.Color{ .r = base_color.r, .g = base_color.g, .b = base_color.b, .a = entry_alpha });
- // Highlight
- if (i == self.finder_selected) {
- rl.DrawCircleLines(@intFromFloat(ex), @intFromFloat(ey), photon_size + 6 + pulsate, rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = entry_alpha });
- }
-
- // Draw name on hover (if selected)
- if (i == self.finder_selected and entry.name_len > 0) {
- var name_buf: [130:0]u8 = undefined;
- @memcpy(name_buf[0..entry.name_len], entry.name[0..entry.name_len]);
- name_buf[entry.name_len] = 0;
- const name_x = ex + photon_size + 8;
- const name_y = ey - 6;
- // Background
- const name_width: f32 = @as(f32, @floatFromInt(entry.name_len)) * 7 + 4;
- rl.DrawRectangle(@intFromFloat(name_x - 2), @intFromFloat(name_y - 2), @intFromFloat(@min(name_width, sw - 20)), 16, rl.Color{ .r = 0x10, .g = 0x10, .b = 0x10, .a = @intFromFloat(self.opacity * 200) });
- rl.DrawText(&name_buf, @intFromFloat(name_x), @intFromFloat(name_y), 11, rl.Color{ .r = 0xE0, .g = 0xE0, .b = 0xE0, .a = entry_alpha });
- }
- }
-
- // === PATH DISPLAY ===
- if (self.finder_path_len > 0) {
- var path_buf: [64:0]u8 = undefined;
- const show_len = @min(self.finder_path_len, 60);
- @memcpy(path_buf[0..show_len], self.finder_path[0..show_len]);
- if (self.finder_path_len > 60) {
- path_buf[57] = '.';
- path_buf[58] = '.';
- path_buf[59] = '.';
- path_buf[60] = 0;
- } else {
- path_buf[show_len] = 0;
- }
- rl.DrawText(&path_buf, @intFromFloat(sx + 12), @intFromFloat(content_y + 5), 10, withAlpha(MUTED_GRAY, content_alpha));
- }
-
- // === LEGEND ===
- const legend_y = sy + sh - 25;
- rl.DrawCircle(@intFromFloat(sx + 15), @intFromFloat(legend_y), 4, withAlpha(HYPER_GREEN, content_alpha));
- rl.DrawText("DIR", @intFromFloat(sx + 22), @intFromFloat(legend_y - 4), 8, withAlpha(MUTED_GRAY, content_alpha));
- rl.DrawCircle(@intFromFloat(sx + 55), @intFromFloat(legend_y), 4, rl.Color{ .r = 0xF7, .g = 0xA4, .b = 0x1D, .a = content_alpha });
- rl.DrawText(".zig", @intFromFloat(sx + 62), @intFromFloat(legend_y - 4), 8, withAlpha(MUTED_GRAY, content_alpha));
- rl.DrawCircle(@intFromFloat(sx + 95), @intFromFloat(legend_y), 4, rl.Color{ .r = 0x80, .g = 0xFF, .b = 0xA0, .a = content_alpha });
- rl.DrawText("code", @intFromFloat(sx + 102), @intFromFloat(legend_y - 4), 8, withAlpha(MUTED_GRAY, content_alpha));
-
- // Count display
- var count_buf: [32:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&count_buf, "{d} items", .{self.finder_entry_count}) catch {};
- rl.DrawText(&count_buf, @intFromFloat(sx + sw - 70), @intFromFloat(legend_y - 4), 10, withAlpha(MUTED_GRAY, content_alpha));
- },
- .system => {
- // === SYSTEM MONITORING PANEL (Hyper Terminal Style) ===
- const row_h: f32 = 60;
- const bar_h: f32 = 8;
- const margin: f32 = 20;
-
- // Simulated system stats (computed from time for smooth animation)
- const cpu_usage = 25.0 + @sin(time * 0.5) * 15 + @sin(time * 1.3) * 8;
- const mem_used = 8.2 + @sin(time * 0.3) * 0.5;
- const mem_total: f32 = 16.0;
- const cpu_temp = 45.0 + @sin(time * 0.7) * 8;
-
- // === CPU Usage ===
- const cpu_y = content_y + 10;
- rl.DrawTextEx(font, "CPU", .{ .x = sx + margin, .y = cpu_y }, 14, 0.5, HYPER_CYAN);
- var cpu_buf: [32:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&cpu_buf, "{d:.1}%", .{cpu_usage}) catch {};
- rl.DrawTextEx(font, &cpu_buf, .{ .x = sx + sw - margin - 50, .y = cpu_y }, 14, 0.5, TEXT_WHITE);
-
- // CPU bar background (Hyper style)
- const cpu_bar_y = cpu_y + 22;
- const bar_w = sw - margin * 2;
- rl.DrawRectangle(@intFromFloat(sx + margin), @intFromFloat(cpu_bar_y), @intFromFloat(bar_w), @intFromFloat(bar_h), withAlpha(BG_BAR, content_alpha));
- // CPU bar fill
- const cpu_fill = bar_w * (cpu_usage / 100.0);
- const cpu_color = if (cpu_usage > 80) HYPER_RED else if (cpu_usage > 50) HYPER_YELLOW else HYPER_GREEN;
- rl.DrawRectangle(@intFromFloat(sx + margin), @intFromFloat(cpu_bar_y), @intFromFloat(cpu_fill), @intFromFloat(bar_h), cpu_color);
-
- // === Memory Usage ===
- const mem_y = content_y + row_h + 10;
- rl.DrawTextEx(font, "MEMORY", .{ .x = sx + margin, .y = mem_y }, 14, 0.5, HYPER_MAGENTA);
- var mem_buf: [32:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&mem_buf, "{d:.1} / {d:.0} GB", .{ mem_used, mem_total }) catch {};
- rl.DrawTextEx(font, &mem_buf, .{ .x = sx + sw - margin - 100, .y = mem_y }, 14, 0.5, TEXT_WHITE);
-
- // Memory bar (Hyper style)
- const mem_bar_y = mem_y + 22;
- rl.DrawRectangle(@intFromFloat(sx + margin), @intFromFloat(mem_bar_y), @intFromFloat(bar_w), @intFromFloat(bar_h), withAlpha(BG_BAR, content_alpha));
- const mem_pct = mem_used / mem_total;
- const mem_fill = bar_w * mem_pct;
- const mem_color = if (mem_pct > 0.8) HYPER_RED else if (mem_pct > 0.5) HYPER_YELLOW else HYPER_MAGENTA;
- rl.DrawRectangle(@intFromFloat(sx + margin), @intFromFloat(mem_bar_y), @intFromFloat(mem_fill), @intFromFloat(bar_h), mem_color);
-
- // === Temperature ===
- const temp_y = content_y + row_h * 2 + 10;
- rl.DrawTextEx(font, "TEMP", .{ .x = sx + margin, .y = temp_y }, 14, 0.5, HYPER_YELLOW);
- var temp_buf: [32:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&temp_buf, "{d:.0}C", .{cpu_temp}) catch {};
- rl.DrawTextEx(font, &temp_buf, .{ .x = sx + sw - margin - 40, .y = temp_y }, 14, 0.5, TEXT_WHITE);
-
- // Temperature bar (Hyper style)
- const temp_bar_y = temp_y + 22;
- rl.DrawRectangle(@intFromFloat(sx + margin), @intFromFloat(temp_bar_y), @intFromFloat(bar_w), @intFromFloat(bar_h), withAlpha(BG_BAR, content_alpha));
- const temp_pct = @min(1.0, (cpu_temp - 30) / 70.0); // 30-100C range
- const temp_fill = bar_w * temp_pct;
- const temp_color = if (cpu_temp > 80) HYPER_RED else if (cpu_temp > 60) HYPER_YELLOW else HYPER_CYAN;
- rl.DrawRectangle(@intFromFloat(sx + margin), @intFromFloat(temp_bar_y), @intFromFloat(temp_fill), @intFromFloat(bar_h), temp_color);
-
- // === System Info ===
- const info_y = content_y + row_h * 3 + 20;
- rl.DrawTextEx(font, "SYSTEM", .{ .x = sx + margin, .y = info_y }, 12, 0.5, MUTED_GRAY);
- rl.DrawTextEx(font, "macOS | Apple M1 Pro", .{ .x = sx + margin, .y = info_y + 18 }, 11, 0.5, withAlpha(SEPARATOR, content_alpha));
- rl.DrawTextEx(font, "TRINITY OS v1.8", .{ .x = sx + margin, .y = info_y + 36 }, 11, 0.5, rl.Color{ .r = 0x60, .g = 0x60, .b = 0x60, .a = content_alpha });
-
- // Pulse effect for active monitoring
- const pulse_alpha: u8 = @intFromFloat(50 + @sin(time * 3) * 20);
- rl.DrawCircle(@intFromFloat(sx + sw - 30), @intFromFloat(content_y + 20), 4, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = pulse_alpha });
- },
-
- .sacred_world => {
- // === SACRED WORLD PANEL β Route by world_id ===
- const world = sacred_worlds.getWorldByBlock(self.world_id);
- const realm = sacred_worlds.blockToRealm(self.world_id);
- const realm_r = sacred_worlds.realmColorR(realm);
- const realm_g = sacred_worlds.realmColorG(realm);
- const realm_b = sacred_worlds.realmColorB(realm);
- const rc = rl.Color{ .r = realm_r, .g = realm_g, .b = realm_b, .a = content_alpha };
- const margin: f32 = 20 * g_font_scale;
- const fs = g_font_scale;
-
- // ββ Common header for all sacred_world panels ββ
- const header_h: f32 = 36 * fs;
- // Header: fully opaque (never transparent)
- rl.DrawRectangle(@intFromFloat(sx), @intFromFloat(content_y), @intFromFloat(sw), @intFromFloat(header_h), SACRED_HEADER_BG);
- rl.DrawCircle(@intFromFloat(sx + 12 * fs), @intFromFloat(content_y + header_h / 2), 4 * fs, rc);
- rl.DrawLine(@intFromFloat(sx), @intFromFloat(content_y + header_h), @intFromFloat(sx + sw), @intFromFloat(content_y + header_h), rc);
-
- const ri = @intFromEnum(realm);
- const rn_len = sacred_worlds.REALM_NAME_LENS[ri];
- var realm_buf: [16:0]u8 = undefined;
- @memcpy(realm_buf[0..rn_len], sacred_worlds.REALM_NAMES[ri][0..rn_len]);
- realm_buf[rn_len] = 0;
- rl.DrawTextEx(font, &realm_buf, .{ .x = sx + margin + 4, .y = content_y + 10 * fs }, 14 * fs, 0.5, SACRED_HEADER_TEXT);
-
- const rs_len = sacred_worlds.REALM_SYMBOL_LENS[ri];
- var sym_buf: [8:0]u8 = undefined;
- @memcpy(sym_buf[0..rs_len], sacred_worlds.REALM_SYMBOLS[ri][0..rs_len]);
- sym_buf[rs_len] = 0;
- rl.DrawTextEx(font, &sym_buf, .{ .x = sx + sw - margin - 30 * fs, .y = content_y + 10 * fs }, 14 * fs, 0.5, SACRED_HEADER_TEXT);
-
- // Content area below header
- const body_y = content_y + header_h + 4 * fs;
- const body_h = content_h - header_h - 4 * fs;
-
- // ββ ROUTE BY WORLD_ID ββ
- if (self.world_id == 0) {
- // ββββββββββββββββββββββββββββββββββββββββββββ
- // CHAT PANEL (world_id 0) β Trinity Chat
- // Uses GLOBAL chat state (persistent across panel reopen)
- // ββββββββββββββββββββββββββββββββββββββββββββ
-
- // Smooth scroll (global)
- const chat_dt = rl.GetFrameTime();
- g_chat_scroll_y += (g_chat_scroll_target - g_chat_scroll_y) * @min(1.0, 8.0 * chat_dt);
-
- const chat_top = body_y + 8 * fs;
- const input_h: f32 = 48 * fs;
- const chat_bottom = content_y + content_h - input_h - 8 * fs;
- const msg_area_h = chat_bottom - chat_top;
- const line_h: f32 = 22 * fs;
- const chat_font = g_font_chat;
- const msg_font_size: f32 = 17 * fs;
- const bubble_pad: f32 = 14 * fs;
- const chat_margin: f32 = 70 * fs; // Extra padding for chat messages and input
- const max_text_w = sw - chat_margin * 2 - bubble_pad * 2;
- // Chat colors: from theme (dark=white-on-dark, light=dark-on-light)
- const chat_text_color = withAlpha(CHAT_TEXT, content_alpha);
- _ = CHAT_BUBBLE_USER; // reserved for future use
-
- // Scissor clip for messages
- rl.BeginScissorMode(@intFromFloat(sx), @intFromFloat(chat_top), @intFromFloat(sw), @intFromFloat(@max(1, msg_area_h)));
-
- // Clamp scroll before rendering
- g_chat_scroll_target = @max(0, g_chat_scroll_target);
-
- if (g_chat_msg_count == 0) {
- // Welcome message
- const welcome_y = chat_top + msg_area_h * 0.3;
- rl.DrawTextEx(chat_font, "Trinity AI", .{ .x = sx + chat_margin, .y = welcome_y }, 18 * fs, 0.5, withAlpha(HYPER_GREEN, content_alpha));
- rl.DrawTextEx(chat_font, "Type a message below to start chatting.", .{ .x = sx + chat_margin, .y = welcome_y + 24 * fs }, 14 * fs, 0.5, withAlpha(MUTED_GRAY, content_alpha));
- g_chat_scroll_target = 0;
- g_chat_scroll_y = 0;
- } else {
- // Render messages with simple line-based rendering (no word-wrap byte corruption)
- var render_y: f32 = chat_top + 6 * fs - g_chat_scroll_y;
- var mi: usize = 0;
- while (mi < g_chat_msg_count) : (mi += 1) {
- const msg_type = g_chat_msg_types[mi];
- const msg_len = g_chat_msg_lens[mi];
- const msg_data = g_chat_messages[mi][0..msg_len];
-
- // Log messages: small dimmed text, no label
- if (msg_type == .log) {
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- var log_z: [256:0]u8 = undefined;
- @memcpy(log_z[0..msg_len], msg_data);
- log_z[msg_len] = 0;
- const log_font_size: f32 = 13 * fs;
- const log_color = rl.Color{ .r = 120, .g = 120, .b = 140, .a = 180 };
- rl.DrawTextEx(chat_font, &log_z, .{ .x = sx + chat_margin, .y = render_y }, log_font_size, 0.3, log_color);
- }
- render_y += 18 * fs;
- continue;
- }
-
- const is_user = msg_type == .user;
-
- // Label β user on right, Trinity on left
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- const label_color = if (is_user) withAlpha(CHAT_LABEL_USER, content_alpha) else withAlpha(CHAT_LABEL_AI, content_alpha);
- if (is_user) {
- const you_w = rl.MeasureTextEx(chat_font, "You", 16 * fs, 0.5).x;
- rl.DrawTextEx(chat_font, "You", .{ .x = sx + sw - chat_margin - you_w, .y = render_y }, 16 * fs, 0.5, label_color);
- } else {
- rl.DrawTextEx(chat_font, "Trinity", .{ .x = sx + chat_margin, .y = render_y }, 16 * fs, 0.5, label_color);
- }
- }
- render_y += 18 * fs;
-
- // Measure actual text width for bubble sizing
- var full_z: [256:0]u8 = undefined;
- @memcpy(full_z[0..msg_len], msg_data);
- full_z[msg_len] = 0;
- const text_size = rl.MeasureTextEx(chat_font, &full_z, msg_font_size, 0.5);
-
- // Bubble alignment: user=right, Trinity=left
- const needs_wrap = text_size.x > max_text_w;
-
- if (!needs_wrap) {
- if (is_user) {
- // User: plain text, right-aligned (no bubble)
- const text_x = sx + sw - chat_margin - text_size.x;
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- // Fake bold
- rl.DrawTextEx(chat_font, &full_z, .{ .x = text_x, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- rl.DrawTextEx(chat_font, &full_z, .{ .x = text_x + 0.6, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- }
- render_y += line_h + 8 * fs;
- } else {
- // Trinity: clean text, no bubble, left-aligned
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- rl.DrawTextEx(chat_font, &full_z, .{ .x = sx + chat_margin, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- rl.DrawTextEx(chat_font, &full_z, .{ .x = sx + chat_margin + 0.6, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- }
- render_y += line_h + 8 * fs;
- }
- } else {
- // Multi-line: UTF-8-safe word wrap
- // First pass: count lines
- var n_lines: f32 = 0;
- {
- var pos: usize = 0;
- while (pos < msg_data.len) {
- // Find how many bytes fit in max_text_w
- var end = pos;
- var last_space: usize = pos;
- while (end < msg_data.len) {
- // Advance one UTF-8 char
- var next = end + 1;
- while (next < msg_data.len and (msg_data[next] & 0xC0) == 0x80) next += 1;
- // Measure width up to 'next'
- var tmp: [256:0]u8 = undefined;
- const seg_len = @min(next - pos, 255);
- @memcpy(tmp[0..seg_len], msg_data[pos .. pos + seg_len]);
- tmp[seg_len] = 0;
- const w = rl.MeasureTextEx(chat_font, &tmp, msg_font_size, 0.5).x;
- if (w > max_text_w and end > pos) break;
- if (msg_data[end] == ' ') last_space = end;
- end = next;
- }
- // Wrap at last space if possible
- if (end < msg_data.len and last_space > pos) end = last_space + 1 else if (end == pos) end = pos + 1;
- n_lines += 1;
- pos = end;
- // Skip leading space on next line
- while (pos < msg_data.len and msg_data[pos] == ' ') pos += 1;
- }
- if (n_lines == 0) n_lines = 1;
- }
-
- const bubble_h = n_lines * line_h;
- const bubble_x = sx + chat_margin;
-
- // Second pass: render lines (no bubble for either side)
- var text_y = render_y;
- var pos2: usize = 0;
- var line_buf_chat: [256:0]u8 = undefined;
- while (pos2 < msg_data.len) {
- var end2 = pos2;
- var last_sp2: usize = pos2;
- while (end2 < msg_data.len) {
- var next2 = end2 + 1;
- while (next2 < msg_data.len and (msg_data[next2] & 0xC0) == 0x80) next2 += 1;
- var tmp2: [256:0]u8 = undefined;
- const seg_len2 = @min(next2 - pos2, 255);
- @memcpy(tmp2[0..seg_len2], msg_data[pos2 .. pos2 + seg_len2]);
- tmp2[seg_len2] = 0;
- const w2 = rl.MeasureTextEx(chat_font, &tmp2, msg_font_size, 0.5).x;
- if (w2 > max_text_w and end2 > pos2) break;
- if (msg_data[end2] == ' ') last_sp2 = end2;
- end2 = next2;
- }
- if (end2 < msg_data.len and last_sp2 > pos2) end2 = last_sp2 + 1 else if (end2 == pos2) end2 = pos2 + 1;
-
- if (text_y >= chat_top - line_h and text_y <= chat_bottom + line_h) {
- const ln_len = @min(end2 - pos2, 255);
- @memcpy(line_buf_chat[0..ln_len], msg_data[pos2 .. pos2 + ln_len]);
- // Trim trailing space
- var tlen = ln_len;
- while (tlen > 0 and line_buf_chat[tlen - 1] == ' ') tlen -= 1;
- line_buf_chat[tlen] = 0;
- // Fake bold: double draw
- rl.DrawTextEx(chat_font, &line_buf_chat, .{ .x = bubble_x + bubble_pad, .y = text_y }, msg_font_size, 0.5, chat_text_color);
- rl.DrawTextEx(chat_font, &line_buf_chat, .{ .x = bubble_x + bubble_pad + 0.6, .y = text_y }, msg_font_size, 0.5, chat_text_color);
- }
-
- text_y += line_h;
- pos2 = end2;
- while (pos2 < msg_data.len and msg_data[pos2] == ' ') pos2 += 1;
- }
-
- render_y += bubble_h + 8 * fs;
- }
- }
-
- // Calculate total content height for scroll clamping
- const total_content_h = render_y + g_chat_scroll_y - (chat_top + 6 * fs);
- const max_scroll = @max(0, total_content_h - msg_area_h + 20 * fs);
- g_chat_scroll_target = @min(g_chat_scroll_target, max_scroll);
- g_chat_scroll_y = @min(g_chat_scroll_y, max_scroll + 10 * fs);
- }
-
- rl.EndScissorMode();
-
- // Mouse wheel scroll in chat
- {
- const cmx = @as(f32, @floatFromInt(rl.GetMouseX()));
- const cmy = @as(f32, @floatFromInt(rl.GetMouseY()));
- if (cmx >= sx and cmx <= sx + sw and cmy >= chat_top and cmy <= chat_bottom) {
- g_chat_scroll_target -= rl.GetMouseWheelMove() * 40.0 * fs;
- g_chat_scroll_target = @max(0, g_chat_scroll_target);
- }
- }
-
- // Input area (bottom) β terminal style with separator lines
- const input_y = chat_bottom + 4 * fs;
- const sep_color = rl.Color{ .r = 100, .g = 100, .b = 110, .a = 120 };
-
- // Background fill
- rl.DrawRectangle(
- @intFromFloat(sx + chat_margin),
- @intFromFloat(input_y),
- @intFromFloat(sw - chat_margin * 2),
- @intFromFloat(input_h),
- CHAT_INPUT_BG,
- );
- // Top separator line
- rl.DrawLineEx(
- .{ .x = sx + chat_margin, .y = input_y },
- .{ .x = sx + sw - chat_margin, .y = input_y },
- 1.0,
- sep_color,
- );
- // Bottom separator line
- rl.DrawLineEx(
- .{ .x = sx + chat_margin, .y = input_y + input_h },
- .{ .x = sx + sw - chat_margin, .y = input_y + input_h },
- 1.0,
- sep_color,
- );
-
- // ">" prompt
- const prompt_color = rl.Color{ .r = 150, .g = 150, .b = 160, .a = 220 };
- const prompt_y = input_y + 14 * fs;
- const prompt_sz: f32 = 17 * fs;
- rl.DrawTextEx(chat_font, ">", .{ .x = sx + chat_margin + 6 * fs, .y = prompt_y }, prompt_sz, 0.5, prompt_color);
-
- // "β΅ send" hint (right side)
- const send_sz: f32 = 13 * fs;
- const send_color = rl.Color{ .r = 140, .g = 140, .b = 150, .a = 180 };
- const send_w = rl.MeasureTextEx(chat_font, "enter to send", send_sz, 0.5).x;
- rl.DrawTextEx(chat_font, "enter to send", .{ .x = sx + sw - chat_margin - send_w - 10 * fs, .y = input_y + 16 * fs }, send_sz, 0.5, send_color);
-
- if (g_chat_input_len > 0) {
- var input_disp: [260:0]u8 = undefined;
- const show_input = @min(g_chat_input_len, 255);
- @memcpy(input_disp[0..show_input], g_chat_input[0..show_input]);
- input_disp[show_input] = 0;
- const ix = sx + chat_margin + 22 * fs;
- const iy = input_y + 14 * fs;
- const isz: f32 = 17 * fs;
- rl.DrawTextEx(chat_font, &input_disp, .{ .x = ix, .y = iy }, isz, 0.5, CHAT_INPUT_TEXT);
- rl.DrawTextEx(chat_font, &input_disp, .{ .x = ix + 0.5, .y = iy }, isz, 0.5, CHAT_INPUT_TEXT);
- // Blinking rectangle cursor after text
- if (@mod(@as(u32, @intFromFloat(time * 3)), 2) == 0) {
- const text_w = rl.MeasureTextEx(chat_font, &input_disp, isz, 0.5).x;
- const cur_x: i32 = @intFromFloat(ix + text_w + 2 * fs);
- const cur_y: i32 = @intFromFloat(iy);
- const cur_w: i32 = @intFromFloat(2 * fs);
- const cur_h: i32 = @intFromFloat(isz);
- rl.DrawRectangle(cur_x, cur_y, cur_w, cur_h, CHAT_INPUT_TEXT);
- }
- } else {
- // Empty input: blinking rect cursor after ">"
- const ph_x = sx + chat_margin + 22 * fs;
- const ph_y = input_y + 14 * fs;
- const ph_sz: f32 = 17 * fs;
- if (@mod(@as(u32, @intFromFloat(time * 2)), 2) == 0) {
- rl.DrawRectangle(@intFromFloat(ph_x), @intFromFloat(ph_y), @intFromFloat(2 * fs), @intFromFloat(ph_sz), CHAT_INPUT_TEXT);
- }
- }
-
- // Status bar below input β real system info
- {
- const status_y = input_y + input_h + 3 * fs;
- const status_sz: f32 = 11 * fs;
- const status_color = rl.Color{ .r = 100, .g = 100, .b = 115, .a = 160 };
- const fps_val = rl.GetFPS();
-
- // Left: FPS + engine stats
- var status_buf: [256:0]u8 = undefined;
- if (g_fluent_engine_inited) {
- const st = g_fluent_engine.getStats();
- const sl = std.fmt.bufPrint(status_buf[0..255], "{d}fps | fluent {d:.0}% | {s} | {s} | s:{d:.1}", .{
- fps_val,
- st.fluent_rate * 100,
- st.current_language.getName(),
- st.current_topic.getName(),
- st.sentiment,
- }) catch "...";
- status_buf[sl.len] = 0;
- } else {
- const sl = std.fmt.bufPrint(status_buf[0..255], "{d}fps | trinity v2.0 | ready", .{fps_val}) catch "...";
- status_buf[sl.len] = 0;
- }
- rl.DrawTextEx(chat_font, &status_buf, .{ .x = sx + chat_margin + 4 * fs, .y = status_y }, status_sz, 0.3, status_color);
-
- // Right: message count
- var count_buf: [64:0]u8 = undefined;
- const ct = std.fmt.bufPrint(count_buf[0..63], "{d} msgs", .{g_chat_msg_count}) catch "0";
- count_buf[ct.len] = 0;
- const count_w = rl.MeasureTextEx(chat_font, &count_buf, status_sz, 0.3).x;
- rl.DrawTextEx(chat_font, &count_buf, .{ .x = sx + sw - chat_margin - count_w - 4 * fs, .y = status_y }, status_sz, 0.3, status_color);
- }
- } else if (self.world_id == 18) {
- // ββββββββββββββββββββββββββββββββββββββββββββ
- // DOCS PANEL (world_id 18) β All 27 docs consolidated
- // ββββββββββββββββββββββββββββββββββββββββββββ
-
- rl.DrawTextEx(font, "ALL DOCUMENTATION", .{ .x = sx + margin, .y = body_y + 4 * fs }, 18 * fs, 0.5, accentText(rc, content_alpha));
-
- const doc_top = body_y + 30 * fs;
- const doc_h = body_h - 34 * fs;
- const doc_x = sx + margin;
- const doc_w = sw - margin * 2;
- const line_h: f32 = 18 * fs;
- const font_size_doc: f32 = 13 * fs;
- const char_w: f32 = 7.0 * fs;
- const chars_per_line: usize = @max(20, @as(usize, @intFromFloat(doc_w / char_w)));
-
- rl.BeginScissorMode(@intFromFloat(sx), @intFromFloat(doc_top), @intFromFloat(sw), @intFromFloat(@max(1, doc_h)));
-
- var render_y: f32 = doc_top - self.scroll_y;
- var line_buf: [256:0]u8 = undefined;
-
- // Render ALL 27 docs sequentially
- var doc_idx: usize = 0;
- while (doc_idx < 27) : (doc_idx += 1) {
- const doc = world_docs.WORLD_DOCS[doc_idx];
- const dworld = sacred_worlds.getWorldByBlock(doc_idx);
-
- // Section header: "N. WORLD_NAME β subtitle"
- var section_hdr: [80:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(§ion_hdr, "{d}. {s}", .{ doc_idx + 1, dworld.name[0..dworld.name_len] }) catch {};
-
- if (render_y >= doc_top - line_h and render_y <= doc_top + doc_h) {
- const drealm = sacred_worlds.blockToRealm(doc_idx);
- const sec_color = rl.Color{
- .r = sacred_worlds.realmColorR(drealm),
- .g = sacred_worlds.realmColorG(drealm),
- .b = sacred_worlds.realmColorB(drealm),
- .a = content_alpha,
- };
- rl.DrawTextEx(font, §ion_hdr, .{ .x = doc_x, .y = render_y }, font_size_doc + 4, 0.5, accentText(sec_color, content_alpha));
- }
- render_y += line_h * 1.5;
-
- // Subtitle
- var sub_buf: [64:0]u8 = undefined;
- const slen = @min(doc.subtitle.len, 63);
- @memcpy(sub_buf[0..slen], doc.subtitle[0..slen]);
- sub_buf[slen] = 0;
- if (render_y >= doc_top - line_h and render_y <= doc_top + doc_h) {
- rl.DrawTextEx(font, &sub_buf, .{ .x = doc_x, .y = render_y }, font_size_doc - 1, 0.5, withAlpha(MUTED_GRAY, content_alpha));
- }
- render_y += line_h;
-
- // Doc content (markdown rendered)
- var iter = world_docs.LineIterator.init(doc.raw);
- var in_fm = false;
- while (iter.next()) |raw_line| {
- const trimmed = blk: {
- var ti: usize = 0;
- while (ti < raw_line.len and (raw_line[ti] == ' ' or raw_line[ti] == '\t')) : (ti += 1) {}
- break :blk raw_line[ti..];
- };
- if (trimmed.len >= 3 and trimmed[0] == '-' and trimmed[1] == '-' and trimmed[2] == '-') {
- in_fm = !in_fm;
- continue;
- }
- if (in_fm) continue;
- if (world_docs.isNoiseLine(raw_line)) continue;
-
- const heading_stripped = world_docs.stripHeading(raw_line);
- const is_heading = (heading_stripped.ptr != raw_line.ptr or heading_stripped.len != raw_line.len);
-
- var stripped_buf: [512]u8 = undefined;
- const stripped_len = world_docs.stripInline(heading_stripped, &stripped_buf);
- const display_line = stripped_buf[0..stripped_len];
-
- var line_start: usize = 0;
- while (line_start < display_line.len or line_start == 0) {
- const remaining = if (line_start < display_line.len) display_line[line_start..] else "";
- const chunk_len = if (remaining.len <= chars_per_line) remaining.len else blk2: {
- var best: usize = chars_per_line;
- var scan: usize = chars_per_line;
- while (scan > 0) {
- scan -= 1;
- if (remaining[scan] == ' ') {
- best = scan;
- break;
- }
- }
- break :blk2 best;
- };
-
- if (render_y >= doc_top - line_h and render_y <= doc_top + doc_h) {
- const copy_len = @min(chunk_len, 255);
- @memcpy(line_buf[0..copy_len], remaining[0..copy_len]);
- line_buf[copy_len] = 0;
-
- const doc_text_color = if (is_heading and line_start == 0)
- accentText(rc, content_alpha)
- else
- withAlpha(CONTENT_TEXT, content_alpha);
- const fsize: f32 = if (is_heading and line_start == 0) font_size_doc + 3 else font_size_doc;
- rl.DrawTextEx(font, &line_buf, .{ .x = doc_x, .y = render_y }, fsize, 0.5, doc_text_color);
- }
-
- render_y += line_h;
- if (chunk_len == 0) break;
- line_start += chunk_len;
- if (line_start < display_line.len and display_line[line_start] == ' ') line_start += 1;
- if (remaining.len <= chars_per_line) break;
- }
- }
- // Gap between docs
- render_y += line_h * 2;
- }
-
- rl.EndScissorMode();
-
- // Scroll indicator
- const total_text_h = render_y + self.scroll_y - doc_top;
- if (total_text_h > doc_h) {
- const scroll_track_x = sx + sw - 6;
- const max_scroll_val = total_text_h - doc_h;
- const scroll_pct = if (max_scroll_val > 0) self.scroll_y / max_scroll_val else 0;
- const thumb_h = @max(20.0, doc_h * (doc_h / total_text_h));
- const thumb_y = doc_top + scroll_pct * (doc_h - thumb_h);
- rl.DrawRectangleRounded(
- .{ .x = scroll_track_x, .y = thumb_y, .width = 4, .height = thumb_h },
- 1.0,
- 4,
- withAlpha(rc, 60),
- );
- }
- } else if (self.world_id == 16) {
- // ββββββββββββββββββββββββββββββββββββββββββββ
- // NETWORK ADMIN PANEL (world_id 16 = monitor)
- // Runtime-detected node data (no static/fake data)
- // Ctrl+8 to open
- // ββββββββββββββββββββββββββββββββββββββββββββ
-
- // Initialize network state on first render (detects local machine)
- initNetworkState();
- // Update uptime counter
- g_network_uptime_ms +|= @intFromFloat(rl.GetFrameTime() * 1000);
-
- const pad = margin * 1.5;
-
- // Update status when probe finishes
- if (g_network_probe_done and std.mem.eql(u8, g_network_model_name[0..g_network_model_name_len], "Scanning network...")) {
- if (g_network_node_count > 1) {
- const done_msg = "Network detected";
- @memcpy(g_network_model_name[0..done_msg.len], done_msg);
- g_network_model_name_len = done_msg.len;
- } else {
- const done_msg = "No peers found";
- @memcpy(g_network_model_name[0..done_msg.len], done_msg);
- g_network_model_name_len = done_msg.len;
- }
- }
-
- // ββ Scrollable content area ββ
- const net_top = body_y + 4 * fs;
- const net_area_h = content_h - (net_top - content_y) - 4 * fs;
-
- // Smooth scroll (uses global vars, draw receives const self)
- const net_dt = rl.GetFrameTime();
- g_net_scroll_y += (g_net_scroll_target - g_net_scroll_y) * @min(1.0, 8.0 * net_dt);
-
- // Scissor clip β all content clipped to panel body
- rl.BeginScissorMode(@intFromFloat(sx), @intFromFloat(net_top), @intFromFloat(sw), @intFromFloat(@max(1, net_area_h)));
-
- var render_y: f32 = net_top + 8 * fs - g_net_scroll_y;
-
- // ββ HEADER ββ
- rl.DrawTextEx(font, "NETWORK", .{ .x = sx + pad, .y = render_y }, 22 * fs, 0.5, accentText(rc, content_alpha));
- var summary_buf: [64:0]u8 = undefined;
- var online_count: usize = 0;
- for (0..g_network_node_count) |ni| {
- if (g_network_nodes[ni].status == .online) online_count += 1;
- }
- _ = std.fmt.bufPrintZ(&summary_buf, "{d} nodes | {d} online", .{ g_network_node_count, online_count }) catch {};
- rl.DrawTextEx(font, &summary_buf, .{ .x = sx + sw - pad - 160 * fs, .y = render_y + 4 * fs }, 11 * fs, 0.5, withAlpha(HYPER_GREEN, content_alpha));
- if (!g_network_probe_done) {
- const spin_pulse: u8 = @intFromFloat(120 + @sin(time * 6) * 120);
- rl.DrawCircle(@intFromFloat(sx + sw - pad - 170 * fs), @intFromFloat(render_y + 12 * fs), 3 * fs, rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = spin_pulse });
- } else {
- const pulse_a: u8 = @intFromFloat(120 + @sin(time * 4) * 80);
- rl.DrawCircle(@intFromFloat(sx + sw - pad - 170 * fs), @intFromFloat(render_y + 12 * fs), 3 * fs, rl.Color{ .r = 0x50, .g = 0xFA, .b = 0x7B, .a = pulse_a });
- }
- render_y += 32 * fs;
-
- // ββ 3D GLOBE ββ
- const globe_size = @min(sw - pad * 2, 420 * fs); // cap size for quality
- const globe_r = globe_size / 2.0;
- const globe_cx = sx + sw / 2.0;
- const globe_cy = render_y + globe_r;
-
- // Colors (Aceternity GitHub Globe exact palette)
- const GLOBE_BASE = rl.Color{ .r = 0x06, .g = 0x20, .b = 0x56, .a = 0xFF };
- const GLOBE_EMISSIVE = rl.Color{ .r = 0x08, .g = 0x28, .b = 0x68, .a = 0xFF };
- const GLOBE_DOT_LAND = rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xB3 }; // rgba(255,255,255,0.7)
- const ATMO_WHITE = rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF }; // atmosphereColor: #FFFFFF
- const ATMO_BLUE = rl.Color{ .r = 0x38, .g = 0xBD, .b = 0xF8, .a = 0xFF }; // ambientLight: #38bdf8
-
- const rot_angle = time * 0.12; // autoRotateSpeed: 0.5
-
- // Outer atmosphere glow β wide soft halo (atmosphereAltitude: 0.1)
- {
- var ai: u32 = 0;
- while (ai < 20) : (ai += 1) {
- const af = @as(f32, @floatFromInt(ai));
- const ar = globe_r + (af + 1.0) * 1.5 * fs;
- const falloff = (1.0 - af / 20.0);
- const aa: u8 = @intFromFloat(@max(0.0, falloff * falloff * 25.0 * @as(f32, @floatFromInt(content_alpha)) / 255.0));
- rl.DrawCircleLinesV(.{ .x = globe_cx, .y = globe_cy }, ar, withAlpha(ATMO_WHITE, aa));
- }
- // Inner blue tint atmosphere
- var bi: u32 = 0;
- while (bi < 6) : (bi += 1) {
- const bf = @as(f32, @floatFromInt(bi));
- const br = globe_r + (bf + 0.5) * 2.0 * fs;
- const ba: u8 = @intFromFloat(@max(0.0, (1.0 - bf / 6.0) * 18.0 * @as(f32, @floatFromInt(content_alpha)) / 255.0));
- rl.DrawCircleLinesV(.{ .x = globe_cx, .y = globe_cy }, br, withAlpha(ATMO_BLUE, ba));
- }
- }
-
- // Globe sphere: gradient fill (emissive: #062056 center, lighter edges)
- rl.DrawCircle(@intFromFloat(globe_cx), @intFromFloat(globe_cy), globe_r, withAlpha(GLOBE_BASE, content_alpha));
- // Emissive inner glow (lighter center)
- rl.DrawCircle(@intFromFloat(globe_cx - globe_r * 0.15), @intFromFloat(globe_cy - globe_r * 0.15), globe_r * 0.6, withAlpha(GLOBE_EMISSIVE, content_alpha / 5));
-
- // Latitude/longitude grid lines on sphere (shininess wireframe effect)
- {
- const GRID_COLOR = rl.Color{ .r = 0x20, .g = 0x50, .b = 0x80, .a = 0x18 };
- // Latitude circles (every 30 deg)
- var lat_i: i32 = -60;
- while (lat_i <= 60) : (lat_i += 30) {
- const lat_r = @as(f32, @floatFromInt(lat_i)) * math.pi / 180.0;
- const circle_r = globe_r * @cos(lat_r);
- const circle_y_off = globe_cy - globe_r * @sin(lat_r);
- // Draw ellipse as line segments
- var gi: u32 = 0;
- while (gi < 48) : (gi += 1) {
- const ga0 = @as(f32, @floatFromInt(gi)) / 48.0 * math.pi * 2.0 + rot_angle;
- const ga1 = @as(f32, @floatFromInt(gi + 1)) / 48.0 * math.pi * 2.0 + rot_angle;
- const gz0 = @sin(ga0);
- const gz1 = @sin(ga1);
- if (gz0 < -0.05 and gz1 < -0.05) continue;
- const gx0 = globe_cx + @cos(ga0) * circle_r;
- const gx1 = globe_cx + @cos(ga1) * circle_r;
- const d0: u8 = @intFromFloat(@max(0.0, (gz0 + 0.05) / 1.05 * 0.4) * @as(f32, @floatFromInt(content_alpha)));
- rl.DrawLineEx(.{ .x = gx0, .y = circle_y_off }, .{ .x = gx1, .y = circle_y_off }, 0.8, withAlpha(GRID_COLOR, d0));
- }
- }
- // Longitude meridians (every 30 deg)
- var lon_i: i32 = 0;
- while (lon_i < 180) : (lon_i += 30) {
- const lon_r = @as(f32, @floatFromInt(lon_i)) * math.pi / 180.0 + rot_angle;
- var gi: u32 = 0;
- while (gi < 48) : (gi += 1) {
- const la0 = (@as(f32, @floatFromInt(gi)) / 48.0 - 0.5) * math.pi;
- const la1 = (@as(f32, @floatFromInt(gi + 1)) / 48.0 - 0.5) * math.pi;
- const z0 = @cos(la0) * @sin(lon_r);
- const z1 = @cos(la1) * @sin(lon_r);
- if (z0 < -0.05 and z1 < -0.05) continue;
- const mx0 = globe_cx + @cos(la0) * @cos(lon_r) * globe_r;
- const my0 = globe_cy - @sin(la0) * globe_r;
- const mx1 = globe_cx + @cos(la1) * @cos(lon_r) * globe_r;
- const my1 = globe_cy - @sin(la1) * globe_r;
- const d0: u8 = @intFromFloat(@max(0.0, (z0 + 0.05) / 1.05 * 0.4) * @as(f32, @floatFromInt(content_alpha)));
- rl.DrawLineEx(.{ .x = mx0, .y = my0 }, .{ .x = mx1, .y = my1 }, 0.8, withAlpha(GRID_COLOR, d0));
- }
- }
- }
-
- // Land dots on sphere (pointSize: 4, polygonColor: rgba(255,255,255,0.7))
- const dot_base_r: f32 = @max(1.5, globe_r / 80.0);
- {
- var row: u32 = 0;
- while (row < world_dots.ROWS) : (row += 2) {
- const lat_rad = (90.0 - @as(f32, @floatFromInt(row)) * 2.0) * math.pi / 180.0;
- const cos_lat = @cos(lat_rad);
- const sin_lat = @sin(lat_rad);
- var col: u32 = 0;
- while (col < world_dots.COLS) : (col += 2) {
- const lon_rad = (-180.0 + @as(f32, @floatFromInt(col)) * 2.0) * math.pi / 180.0 + rot_angle;
- const gx3 = cos_lat * @cos(lon_rad);
- const gy3 = sin_lat;
- const gz3 = cos_lat * @sin(lon_rad);
- if (gz3 < -0.05) continue;
-
- const scr_x = globe_cx + gx3 * globe_r;
- const scr_y = globe_cy - gy3 * globe_r;
- const depth = @max(0.0, gz3 + 0.05) / 1.05;
-
- if (world_dots.isLand(row, col)) {
- const da: u8 = @intFromFloat(depth * @as(f32, @floatFromInt(content_alpha)) * 0.75);
- const dr = dot_base_r * (0.7 + depth * 0.6);
- rl.DrawCircle(@intFromFloat(scr_x), @intFromFloat(scr_y), dr, withAlpha(GLOBE_DOT_LAND, da));
- }
- }
- }
- }
-
- // Rim light (shininess: 0.9)
- rl.DrawCircleLinesV(.{ .x = globe_cx, .y = globe_cy }, globe_r, withAlpha(ATMO_WHITE, content_alpha / 8));
- rl.DrawCircleLinesV(.{ .x = globe_cx, .y = globe_cy }, globe_r - 0.5, withAlpha(ATMO_BLUE, content_alpha / 6));
-
- // ββ Arc connections (arcTime: 1000, arcLength: 0.9) ββ
- if (g_network_node_count > 1) {
- const local_nd = g_network_nodes[0];
- var ci: usize = 1;
- while (ci < g_network_node_count) : (ci += 1) {
- const remote_nd = g_network_nodes[ci];
- if (remote_nd.is_local) continue;
-
- const lat1 = local_nd.geo_lat * math.pi / 180.0;
- const lon1 = local_nd.geo_lon * math.pi / 180.0 + rot_angle;
- const lat2 = remote_nd.geo_lat * math.pi / 180.0;
- const lon2 = remote_nd.geo_lon * math.pi / 180.0 + rot_angle;
-
- // Arc colors cycle: #06b6d4, #3b82f6, #6366f1
- const arc_colors = [_][3]u8{ .{ 0x06, 0xB6, 0xD4 }, .{ 0x3B, 0x82, 0xF6 }, .{ 0x63, 0x66, 0xF1 } };
- const ac = arc_colors[ci % 3];
-
- const ARC_SEGS: u32 = 32;
- const arc_phase = @mod(time * 1.0 + @as(f32, @floatFromInt(ci)) * 1.5, 1.0); // arcTime: 1000ms
- var seg: u32 = 0;
- while (seg < ARC_SEGS) : (seg += 1) {
- const t0 = @as(f32, @floatFromInt(seg)) / @as(f32, @floatFromInt(ARC_SEGS));
- const t1 = @as(f32, @floatFromInt(seg + 1)) / @as(f32, @floatFromInt(ARC_SEGS));
-
- const alt0 = 1.0 + 0.12 * @sin(t0 * math.pi);
- const alt1 = 1.0 + 0.12 * @sin(t1 * math.pi);
- const la0 = lat1 + (lat2 - lat1) * t0;
- const lo0 = lon1 + (lon2 - lon1) * t0;
- const la1_v = lat1 + (lat2 - lat1) * t1;
- const lo1_v = lon1 + (lon2 - lon1) * t1;
-
- const px0 = globe_cx + @cos(la0) * @cos(lo0) * globe_r * alt0;
- const py0 = globe_cy - @sin(la0) * globe_r * alt0;
- const pz0 = @cos(la0) * @sin(lo0);
- const px1 = globe_cx + @cos(la1_v) * @cos(lo1_v) * globe_r * alt1;
- const py1 = globe_cy - @sin(la1_v) * globe_r * alt1;
- const pz1 = @cos(la1_v) * @sin(lo1_v);
- if (pz0 < -0.15 and pz1 < -0.15) continue;
-
- // arcLength: 0.9 β traveling bright band
- const seg_mid = (t0 + t1) / 2.0;
- const pulse_d = @abs(seg_mid - arc_phase);
- const pulse_b = @max(0.0, 1.0 - pulse_d * 4.0); // wide band
-
- const ca: u8 = @intFromFloat(@min(255.0, 30.0 + pulse_b * 220.0));
- const thick = 1.5 * fs + pulse_b * 2.0 * fs;
- rl.DrawLineEx(.{ .x = px0, .y = py0 }, .{ .x = px1, .y = py1 }, thick, rl.Color{ .r = ac[0], .g = ac[1], .b = ac[2], .a = ca });
- }
- }
- }
-
- // ββ Node markers (rings: 1, maxRings: 3) ββ
- for (0..g_network_node_count) |ni| {
- const node = g_network_nodes[ni];
- const nlat = node.geo_lat * math.pi / 180.0;
- const nlon = node.geo_lon * math.pi / 180.0 + rot_angle;
- const nz = @cos(nlat) * @sin(nlon);
- if (nz < -0.05) continue;
- const nx_g = globe_cx + @cos(nlat) * @cos(nlon) * globe_r;
- const ny_g = globe_cy - @sin(nlat) * globe_r;
- const depth = @max(0.0, nz + 0.05) / 1.05;
- const nc: rl.Color = switch (node.status) {
- .online => @bitCast(theme.accents.node_online),
- .connecting => @bitCast(theme.accents.node_connecting),
- .degraded => @bitCast(theme.accents.node_degraded),
- .error_state => @bitCast(theme.accents.node_error),
- .offline => @bitCast(theme.accents.node_offline),
- };
- // Expanding rings
- var ring: u32 = 0;
- while (ring < 3) : (ring += 1) {
- const phase = @mod(time * 1.0 + @as(f32, @floatFromInt(ring)) * 0.33 + @as(f32, @floatFromInt(ni)) * 0.7, 1.0);
- const rr = 3.0 * fs + phase * 16.0 * fs;
- const ra: u8 = @intFromFloat(@max(0.0, (1.0 - phase) * 50.0 * depth));
- rl.DrawCircleLinesV(.{ .x = nx_g, .y = ny_g }, rr, withAlpha(nc, ra));
- }
- const dot_a: u8 = @intFromFloat(depth * @as(f32, @floatFromInt(content_alpha)));
- rl.DrawCircle(@intFromFloat(nx_g), @intFromFloat(ny_g), 5.0 * fs, withAlpha(nc, dot_a));
- rl.DrawCircle(@intFromFloat(nx_g), @intFromFloat(ny_g), 8.0 * fs, withAlpha(nc, dot_a / 4));
- // Label
- if (depth > 0.4) {
- var loc_buf: [36:0]u8 = undefined;
- @memcpy(loc_buf[0..node.location_len], node.location[0..node.location_len]);
- loc_buf[node.location_len] = 0;
- rl.DrawTextEx(font, &loc_buf, .{ .x = nx_g + 12 * fs, .y = ny_g - 6 * fs }, 10 * fs, 0.5, withAlpha(TEXT_WHITE, dot_a));
- }
- }
-
- render_y += globe_size + 20 * fs;
-
- // ββ CONNECTED NODES ββ
- rl.DrawLine(@intFromFloat(sx + pad), @intFromFloat(render_y), @intFromFloat(sx + sw - pad), @intFromFloat(render_y), withAlpha(BORDER_SUBTLE, content_alpha / 3));
- render_y += 12 * fs;
- rl.DrawTextEx(font, "CONNECTED NODES", .{ .x = sx + pad, .y = render_y }, 12 * fs, 0.5, withAlpha(MUTED_GRAY, content_alpha));
- render_y += 20 * fs;
-
- for (0..g_network_node_count) |ni| {
- const node = g_network_nodes[ni];
- const node_color: rl.Color = switch (node.status) {
- .online => @bitCast(theme.accents.node_online),
- .connecting => @bitCast(theme.accents.node_connecting),
- .degraded => @bitCast(theme.accents.node_degraded),
- .error_state => @bitCast(theme.accents.node_error),
- .offline => @bitCast(theme.accents.node_offline),
- };
-
- // Card background
- rl.DrawRectangleRounded(.{ .x = sx + pad, .y = render_y, .width = sw - pad * 2, .height = 56 * fs }, 0.08, 4, withAlpha(BG_INPUT, content_alpha));
- rl.DrawRectangleRoundedLinesEx(.{ .x = sx + pad, .y = render_y, .width = sw - pad * 2, .height = 56 * fs }, 0.08, 4, 1.0, withAlpha(node_color, content_alpha / 3));
-
- // Status dot
- rl.DrawCircle(@intFromFloat(sx + pad + 14 * fs), @intFromFloat(render_y + 16 * fs), 4 * fs, withAlpha(node_color, content_alpha));
-
- // Name + role
- var name_buf: [36:0]u8 = undefined;
- @memcpy(name_buf[0..node.name_len], node.name[0..node.name_len]);
- name_buf[node.name_len] = 0;
- rl.DrawTextEx(font, &name_buf, .{ .x = sx + pad + 28 * fs, .y = render_y + 6 * fs }, 12 * fs, 0.5, withAlpha(TEXT_WHITE, content_alpha));
-
- var role_buf: [20:0]u8 = undefined;
- @memcpy(role_buf[0..node.role_len], node.role[0..node.role_len]);
- role_buf[node.role_len] = 0;
- rl.DrawTextEx(font, &role_buf, .{ .x = sx + pad + 28 * fs, .y = render_y + 24 * fs }, 10 * fs, 0.5, withAlpha(HYPER_CYAN, content_alpha));
-
- // Location
- var loc_buf2: [36:0]u8 = undefined;
- @memcpy(loc_buf2[0..node.location_len], node.location[0..node.location_len]);
- loc_buf2[node.location_len] = 0;
- rl.DrawTextEx(font, &loc_buf2, .{ .x = sx + pad + 28 * fs, .y = render_y + 40 * fs }, 9 * fs, 0.5, withAlpha(TEXT_DIM, content_alpha));
-
- // Right side: RAM + address
- var ram_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&ram_buf, "{d}MB", .{node.ram_mb}) catch {};
- rl.DrawTextEx(font, &ram_buf, .{ .x = sx + sw - pad - 70 * fs, .y = render_y + 6 * fs }, 11 * fs, 0.5, withAlpha(TEXT_WHITE, content_alpha));
-
- var addr_buf: [52:0]u8 = undefined;
- @memcpy(addr_buf[0..node.address_len], node.address[0..node.address_len]);
- addr_buf[node.address_len] = 0;
- rl.DrawTextEx(font, &addr_buf, .{ .x = sx + sw - pad - 140 * fs, .y = render_y + 24 * fs }, 9 * fs, 0.5, withAlpha(TEXT_DIM, content_alpha));
-
- const lr_text: [*:0]const u8 = if (node.is_local) "LOCAL" else "REMOTE";
- const lr_c = if (node.is_local) withAlpha(@as(rl.Color, @bitCast(theme.accents.node_local)), content_alpha) else withAlpha(@as(rl.Color, @bitCast(theme.accents.node_remote)), content_alpha);
- rl.DrawTextEx(font, lr_text, .{ .x = sx + sw - pad - 50 * fs, .y = render_y + 40 * fs }, 9 * fs, 0.5, lr_c);
-
- render_y += 62 * fs;
- }
-
- // ββ JOIN NETWORK ββ
- render_y += 8 * fs;
- rl.DrawLine(@intFromFloat(sx + pad), @intFromFloat(render_y), @intFromFloat(sx + sw - pad), @intFromFloat(render_y), withAlpha(BORDER_SUBTLE, content_alpha / 3));
- render_y += 12 * fs;
- rl.DrawTextEx(font, "JOIN NETWORK", .{ .x = sx + pad, .y = render_y }, 14 * fs, 0.5, accentText(rc, content_alpha));
- render_y += 22 * fs;
- rl.DrawTextEx(font, "1. zig build tri", .{ .x = sx + pad, .y = render_y }, 10 * fs, 0.5, withAlpha(TEXT_WHITE, content_alpha));
- render_y += 16 * fs;
- rl.DrawTextEx(font, "2. ./zig-out/bin/tri node --worker", .{ .x = sx + pad, .y = render_y }, 10 * fs, 0.5, withAlpha(TEXT_WHITE, content_alpha));
- render_y += 16 * fs;
- rl.DrawTextEx(font, "3. Auto-discover via UDP 9333", .{ .x = sx + pad, .y = render_y }, 10 * fs, 0.5, withAlpha(TEXT_WHITE, content_alpha));
- render_y += 24 * fs;
- const uptime_s = g_network_uptime_ms / 1000;
- var uptime_buf: [32:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&uptime_buf, "uptime: {d}s", .{uptime_s}) catch {};
- rl.DrawTextEx(font, &uptime_buf, .{ .x = sx + pad, .y = render_y }, 10 * fs, 0.5, withAlpha(TEXT_DIM, content_alpha));
- render_y += 20 * fs;
-
- // Scroll bounds clamping
- const total_content_ht = render_y + g_net_scroll_y - (net_top + 8 * fs);
- const max_scroll_net = @max(0, total_content_ht - net_area_h + 20 * fs);
- g_net_scroll_target = @min(g_net_scroll_target, max_scroll_net);
- g_net_scroll_target = @max(0, g_net_scroll_target);
- g_net_scroll_y = @min(g_net_scroll_y, max_scroll_net + 10 * fs);
-
- rl.EndScissorMode();
-
- // Mouse wheel scroll
- {
- const cmx = @as(f32, @floatFromInt(rl.GetMouseX()));
- const cmy = @as(f32, @floatFromInt(rl.GetMouseY()));
- if (cmx >= sx and cmx <= sx + sw and cmy >= net_top and cmy <= net_top + net_area_h) {
- g_net_scroll_target -= rl.GetMouseWheelMove() * 40.0 * fs;
- g_net_scroll_target = @max(0, g_net_scroll_target);
- }
- }
-
- // Scrollbar indicator
- if (total_content_ht > net_area_h) {
- const scroll_track_x = sx + sw - 6;
- const scroll_pct = if (max_scroll_net > 0) g_net_scroll_y / max_scroll_net else 0;
- const thumb_h = @max(20.0, net_area_h * (net_area_h / total_content_ht));
- const thumb_y = net_top + scroll_pct * (net_area_h - thumb_h);
- rl.DrawRectangleRounded(.{ .x = scroll_track_x, .y = thumb_y, .width = 4, .height = thumb_h }, 1.0, 4, withAlpha(rc, 60));
- }
- } else {
- // ββββββββββββββββββββββββββββββββββββββββββββ
- // PLACEHOLDER PANEL β Coming Soon
- // ββββββββββββββββββββββββββββββββββββββββββββ
-
- const center_x = sx + sw / 2;
- const center_y_pos = body_y + body_h * 0.35;
-
- // World name (large, centered)
- var title_buf: [28:0]u8 = undefined;
- @memcpy(title_buf[0..world.name_len], world.name[0..world.name_len]);
- title_buf[world.name_len] = 0;
- const title_w = @as(f32, @floatFromInt(rl.MeasureText(&title_buf, @intFromFloat(24 * fs))));
- rl.DrawTextEx(font, &title_buf, .{ .x = center_x - title_w / 2, .y = center_y_pos }, 24 * fs, 1, accentText(rc, content_alpha));
-
- // Subtitle (description)
- const doc = world_docs.WORLD_DOCS[self.world_id];
- var subtitle_buf: [64:0]u8 = undefined;
- const sub_len = @min(doc.subtitle.len, 63);
- @memcpy(subtitle_buf[0..sub_len], doc.subtitle[0..sub_len]);
- subtitle_buf[sub_len] = 0;
- const sub_w = @as(f32, @floatFromInt(rl.MeasureText(&subtitle_buf, @intFromFloat(13 * fs))));
- rl.DrawTextEx(font, &subtitle_buf, .{ .x = center_x - sub_w / 2, .y = center_y_pos + 34 * fs }, 13 * fs, 0.5, withAlpha(MUTED_GRAY, content_alpha));
-
- // "Coming Soon" badge
- const badge_y = center_y_pos + 64 * fs;
- const badge_text = "Coming Soon";
- const badge_w = @as(f32, @floatFromInt(rl.MeasureText(badge_text, @intFromFloat(12 * fs))));
- rl.DrawRectangleRounded(
- .{ .x = center_x - badge_w / 2 - 12 * fs, .y = badge_y - 4 * fs, .width = badge_w + 24 * fs, .height = 24 * fs },
- 0.5,
- 4,
- withAlpha(BORDER_SUBTLE, content_alpha / 2),
- );
- rl.DrawTextEx(font, badge_text, .{ .x = center_x - badge_w / 2, .y = badge_y }, 12 * fs, 0.5, withAlpha(TEXT_DIM, content_alpha));
-
- // Domain name
- const di = @intFromEnum(world.domain);
- const dn_len = sacred_worlds.DOMAIN_NAME_LENS[di];
- var domain_buf: [20:0]u8 = undefined;
- @memcpy(domain_buf[0..dn_len], sacred_worlds.DOMAIN_NAMES[di][0..dn_len]);
- domain_buf[dn_len] = 0;
- const dom_w = @as(f32, @floatFromInt(rl.MeasureText(&domain_buf, @intFromFloat(11 * fs))));
- rl.DrawTextEx(font, &domain_buf, .{ .x = center_x - dom_w / 2, .y = center_y_pos + 100 * fs }, 11 * fs, 0.5, withAlpha(TEXT_DIM, content_alpha));
-
- // Formula decoration (bottom)
- var formula_buf: [52:0]u8 = undefined;
- @memcpy(formula_buf[0..world.formula_len], world.formula[0..world.formula_len]);
- formula_buf[world.formula_len] = 0;
- const formula_w = @as(f32, @floatFromInt(rl.MeasureText(&formula_buf, @intFromFloat(11 * fs))));
- rl.DrawTextEx(font, &formula_buf, .{ .x = center_x - formula_w / 2, .y = center_y_pos + 130 * fs }, 11 * fs, 0.5, withAlpha(TEXT_HINT, content_alpha));
-
- // Block badge
- var idx_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrintZ(&idx_buf, "Block {d}/27", .{@as(u32, self.world_id) + 1}) catch {};
- const bidx_w = @as(f32, @floatFromInt(rl.MeasureText(&idx_buf, @intFromFloat(10 * fs))));
- rl.DrawTextEx(font, &idx_buf, .{ .x = center_x - bidx_w / 2, .y = center_y_pos + 152 * fs }, 10 * fs, 0.5, withAlpha(TEXT_DIM, content_alpha));
-
- // Animated realm-color spiral (decorative)
- const spiral_cx = center_x;
- const spiral_cy = center_y_pos - 60 * fs;
- var sp: u32 = 0;
- while (sp < 20) : (sp += 1) {
- const n = @as(f32, @floatFromInt(sp));
- const angle = n * PHI * std.math.pi + time * 0.3;
- const radius_sp = (5.0 + n * 1.5) * fs;
- const px = spiral_cx + @cos(angle) * radius_sp;
- const py = spiral_cy + @sin(angle) * radius_sp;
- const dot_alpha: u8 = @intFromFloat(@max(20, @as(f32, @floatFromInt(content_alpha)) * (1.0 - n / 20.0)));
- rl.DrawCircle(@intFromFloat(px), @intFromFloat(py), 2.0 * fs, rl.Color{ .r = realm_r, .g = realm_g, .b = realm_b, .a = dot_alpha });
- }
- }
- },
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // EMERGENT WAVE SCROLLVIEW v1.0 β Visual Effects on Panel Card
- // phi^2 + 1/phi^2 = 3 = TRINITY
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- if (self.wave_scroll_enabled) {
- const wsv = &self.wave_sv;
- const wave_content_y = sy + 34; // Below title bar
- const wave_content_h = sh - 44; // Content area height
-
- // Velocity-dependent visual intensity: idle=subtle, fast=bright
- const vel_intensity = @min(1.0, @abs(wsv.state.scroll_velocity) / 1000.0);
- const idle_base: f32 = 0.15;
- const visual_intensity = idle_base + (1.0 - idle_base) * vel_intensity;
-
- // 1. INTERFERENCE GLOW LINES β horizontal wave bands across panel
- if (wsv.interference_rows > 0) {
- const row_scale = wave_content_h / @as(f32, @floatFromInt(wsv.interference_rows));
- for (0..wsv.interference_rows) |row| {
- const intensity = wsv.interference[row];
- if (intensity > 0.03) {
- const iy = wave_content_y + @as(f32, @floatFromInt(row)) * row_scale;
- if (iy < sy or iy > sy + sh) continue;
- const glow_a = @min(@as(f32, 80.0), intensity * 100.0 * visual_intensity) * self.opacity;
- const glow_alpha: u8 = @intFromFloat(@max(0, glow_a));
- if (glow_alpha > 2) {
- rl.DrawLineEx(
- .{ .x = sx + 4, .y = iy },
- .{ .x = sx + sw - 4, .y = iy },
- 1.0,
- rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = glow_alpha },
- );
- }
- }
- }
- }
-
- // 2. WAVE VELOCITY INDICATOR β edge glow when scrolling fast
- const vel = @abs(wsv.state.scroll_velocity);
- if (vel > 50.0) {
- const vel_norm = @min(1.0, vel / 2000.0);
- const edge_alpha: u8 = @intFromFloat(@max(0, vel_norm * 140.0 * self.opacity));
- if (wsv.state.scroll_velocity > 0) {
- for (0..3) |gi| {
- const gf = @as(f32, @floatFromInt(gi));
- const ga: u8 = edge_alpha / (@as(u8, @intCast(gi)) + 1);
- rl.DrawLineEx(
- .{ .x = sx + 8, .y = sy + sh - 2 - gf * 2 },
- .{ .x = sx + sw - 8, .y = sy + sh - 2 - gf * 2 },
- 2.0,
- rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = ga },
- );
- }
- } else {
- for (0..3) |gi| {
- const gf = @as(f32, @floatFromInt(gi));
- const ga: u8 = edge_alpha / (@as(u8, @intCast(gi)) + 1);
- rl.DrawLineEx(
- .{ .x = sx + 8, .y = sy + 34 + gf * 2 },
- .{ .x = sx + sw - 8, .y = sy + 34 + gf * 2 },
- 2.0,
- rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = ga },
- );
- }
- }
- }
-
- // 3. BOUNCE GLOW β magenta flash on overscroll
- if (wsv.state.bounce_amplitude > 0.01) {
- const bounce_a: u8 = @intFromFloat(@min(255.0, wsv.state.bounce_amplitude * 400.0 * self.opacity));
- const bounce_pulse = @sin(wsv.state.bounce_phase) * 0.5 + 0.5;
- const bp_alpha: u8 = @intFromFloat(@as(f32, @floatFromInt(bounce_a)) * bounce_pulse);
- rl.DrawRectangleRoundedLinesEx(
- .{ .x = sx + 1, .y = sy + 1, .width = sw - 2, .height = sh - 2 },
- roundness,
- 32,
- 2.0,
- rl.Color{ .r = 0xF8, .g = 0x1C, .b = 0xE5, .a = bp_alpha },
- );
- }
-
- // 4. WAVE SCROLL POSITION INDICATOR
- const max_scroll_w = @max(1.0, wsv.state.total_content_height - wsv.state.viewport_height);
- const scroll_pct = @min(1.0, @max(0.0, wsv.state.scroll_phase / max_scroll_w));
- const indicator_h: f32 = @max(20.0, wave_content_h * (wsv.state.viewport_height / @max(1.0, wsv.state.total_content_height)));
- const indicator_y = wave_content_y + scroll_pct * (wave_content_h - indicator_h);
- const wave_pulse = @sin(wsv.wave_time * 3.0) * 0.3 + 0.7;
- const ind_alpha: u8 = @intFromFloat(@max(0, @min(255.0, wave_pulse * (40.0 + 60.0 * visual_intensity) * self.opacity)));
- rl.DrawRectangleRounded(
- .{ .x = sx + sw - 6, .y = indicator_y, .width = 3, .height = indicator_h },
- 0.5,
- 8,
- rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = ind_alpha },
- );
-
- // 5. EDGE FADE β gradient masking at top/bottom content edges
- const fade_bg = if (self.panel_type == .sacred_world) @as(rl.Color, @bitCast(theme.sacred_world_bg)) else BG_SURFACE;
- for (0..6) |fi| {
- const fade_f = @as(f32, @floatFromInt(6 - fi));
- const fade_a: u8 = @intFromFloat(@max(0, @min(255.0, self.opacity * fade_f * 40.0)));
- // Top edge fade
- rl.DrawLineEx(
- .{ .x = sx + 2, .y = sy + 34 + @as(f32, @floatFromInt(fi)) },
- .{ .x = sx + sw - 2, .y = sy + 34 + @as(f32, @floatFromInt(fi)) },
- 1.0,
- withAlpha(fade_bg, fade_a),
- );
- // Bottom edge fade
- rl.DrawLineEx(
- .{ .x = sx + 2, .y = sy + sh - @as(f32, @floatFromInt(fi)) },
- .{ .x = sx + sw - 2, .y = sy + sh - @as(f32, @floatFromInt(fi)) },
- 1.0,
- withAlpha(fade_bg, fade_a),
- );
- }
- }
-
- // Resize handle (bottom-right corner)
- const handle_size: f32 = 12;
- const handle_x = sx + sw - handle_size;
- const handle_y = sy + sh - handle_size;
- for (0..3) |i| {
- const fi = @as(f32, @floatFromInt(i));
- rl.DrawLine(@intFromFloat(handle_x + fi * 4), @intFromFloat(handle_y + handle_size), @intFromFloat(handle_x + handle_size), @intFromFloat(handle_y + fi * 4), rl.Color{ .r = 0x60, .g = 0x60, .b = 0x60, .a = @intFromFloat(self.opacity * 100) });
- }
- }
-
- pub fn isPointInside(self: *const GlassPanel, px: f32, py: f32) bool {
- return px >= self.x and px <= self.x + self.width and
- py >= self.y and py <= self.y + self.height;
- }
-
- pub fn isPointInTitleBar(self: *const GlassPanel, px: f32, py: f32) bool {
- return px >= self.x and px <= self.x + self.width and
- py >= self.y and py <= self.y + 36;
- }
-
- pub fn isPointOnClose(self: *const GlassPanel, px: f32, py: f32) bool {
- // Traffic light close button (left side, red)
- const close_x = self.x + 16;
- const close_y = self.y + 14;
- const dx = px - close_x;
- const dy = py - close_y;
- return dx * dx + dy * dy < 64; // radius 8
-
- }
-
- pub fn isPointOnResize(self: *const GlassPanel, px: f32, py: f32) bool {
- // Bottom-right corner resize handle
- const handle_size: f32 = 16;
- return px >= self.x + self.width - handle_size and
- px <= self.x + self.width and
- py >= self.y + self.height - handle_size and
- py <= self.y + self.height;
- }
-
- // Load directory for finder panel
- pub fn loadDirectory(self: *GlassPanel, path: []const u8) void {
- // Store path
- const path_copy_len = @min(path.len, 511);
- @memcpy(self.finder_path[0..path_copy_len], path[0..path_copy_len]);
- self.finder_path_len = path_copy_len;
- self.finder_entry_count = 0;
- self.finder_animation = 0;
-
- if (is_emscripten) {
- // WASM: show demo entries (no real filesystem)
- const demo = [_]struct { name: []const u8, is_dir: bool }{
- .{ .name = "src/", .is_dir = true },
- .{ .name = "build.zig", .is_dir = false },
- .{ .name = "assets/", .is_dir = true },
- .{ .name = "README.md", .is_dir = false },
- };
- for (demo, 0..) |d, i| {
- if (i >= 64) break;
- const nl = @min(d.name.len, 127);
- @memcpy(self.finder_entries[i].name[0..nl], d.name[0..nl]);
- self.finder_entries[i].name_len = nl;
- self.finder_entries[i].is_dir = d.is_dir;
- self.finder_entries[i].file_type = if (d.is_dir) .folder else FileType.fromName(d.name);
- const fi = @as(f32, @floatFromInt(i));
- self.finder_entries[i].orbit_angle = fi * 0.618033988 * TAU;
- self.finder_entries[i].orbit_radius = 60 + fi * 8;
- self.finder_entry_count += 1;
- }
- return;
- }
-
- // Open directory using std.fs
- const dir = std.fs.cwd().openDir(path, .{ .iterate = true }) catch {
- // If can't open, add error entry
- const err_name = "Error: Cannot open directory";
- @memcpy(self.finder_entries[0].name[0..err_name.len], err_name);
- self.finder_entries[0].name_len = err_name.len;
- self.finder_entries[0].is_dir = false;
- self.finder_entries[0].file_type = .unknown;
- self.finder_entry_count = 1;
- return;
- };
-
- // Add parent directory entry (..)
- if (!std.mem.eql(u8, path, ".") and !std.mem.eql(u8, path, "/")) {
- const parent_name = "..";
- @memcpy(self.finder_entries[0].name[0..2], parent_name);
- self.finder_entries[0].name_len = 2;
- self.finder_entries[0].is_dir = true;
- self.finder_entries[0].file_type = .folder;
- self.finder_entries[0].orbit_angle = 0;
- self.finder_entries[0].orbit_radius = 50;
- self.finder_entry_count = 1;
- }
-
- // Iterate directory
- var iter = dir.iterate();
- while (iter.next() catch null) |entry| {
- if (self.finder_entry_count >= 64) break;
-
- const idx = self.finder_entry_count;
- const name_len = @min(entry.name.len, 127);
- @memcpy(self.finder_entries[idx].name[0..name_len], entry.name[0..name_len]);
- self.finder_entries[idx].name_len = name_len;
- self.finder_entries[idx].is_dir = entry.kind == .directory;
-
- if (entry.kind == .directory) {
- self.finder_entries[idx].file_type = .folder;
- } else {
- self.finder_entries[idx].file_type = FileType.fromName(entry.name);
- }
-
- // Assign orbit position based on index
- const fi = @as(f32, @floatFromInt(idx));
- self.finder_entries[idx].orbit_angle = fi * 0.618033988 * TAU; // Golden angle
- self.finder_entries[idx].orbit_radius = 60 + fi * 8; // Expanding spiral
-
- self.finder_entry_count += 1;
- }
- }
-
- // Get clicked entry in finder
- pub fn getFinderEntryAt(self: *const GlassPanel, px: f32, py: f32, time: f32) ?usize {
- const center_x = self.x + self.width / 2;
- const center_y = self.y + self.height / 2 + 20;
-
- for (0..self.finder_entry_count) |i| {
- const entry = &self.finder_entries[i];
- const angle = entry.orbit_angle + time * 0.3 + self.finder_animation;
- const radius = entry.orbit_radius * (0.8 + self.finder_animation * 0.2);
-
- const ex = center_x + @cos(angle) * radius;
- const ey = center_y + @sin(angle) * radius;
-
- const dx = px - ex;
- const dy = py - ey;
- const dist = @sqrt(dx * dx + dy * dy);
-
- // Check if click is within entry circle
- const entry_size: f32 = if (entry.is_dir) 14 else 10;
- if (dist < entry_size + 5) {
- return i;
- }
- }
- return null;
- }
-};
-
-const PanelSystem = struct {
- panels: [MAX_PANELS]GlassPanel,
- count: usize,
- active_panel: ?usize,
-
- // Swipe tracking
- swipe_start_x: f32,
- swipe_start_y: f32,
- swiping: bool,
-
- pub fn init() PanelSystem {
- return .{
- .panels = undefined,
- .count = 0,
- .active_panel = null,
- .swipe_start_x = 0,
- .swipe_start_y = 0,
- .swiping = false,
- };
- }
-
- pub fn spawn(self: *PanelSystem, x: f32, y: f32, w: f32, h: f32, ptype: PanelType, title: []const u8) void {
- if (self.count >= MAX_PANELS) return;
- self.panels[self.count] = GlassPanel.init(x, y, w, h, ptype, title);
- self.panels[self.count].open();
- self.count += 1;
- }
-
- // Focus panel by type - if exists, focus it; otherwise spawn new
- pub fn focusByType(self: *PanelSystem, ptype: PanelType, x: f32, y: f32, w: f32, h: f32, title: []const u8) void {
- // First unfocus all panels
- for (0..self.count) |i| {
- if (self.panels[i].is_focused) {
- self.panels[i].unfocus();
- }
- }
-
- // Find existing panel of this type
- for (0..self.count) |i| {
- if (self.panels[i].panel_type == ptype and self.panels[i].state == .open) {
- self.panels[i].focus();
- self.active_panel = i;
- return;
- }
- }
-
- // No existing panel - spawn new and focus
- if (self.count < MAX_PANELS) {
- self.panels[self.count] = GlassPanel.init(x, y, w, h, ptype, title);
- self.panels[self.count].open();
- // Focus will be called after opening animation
- self.panels[self.count].is_focused = true;
- self.panels[self.count].focus_ripple = 1.0;
- self.panels[self.count].target_x = 20;
- self.panels[self.count].target_y = 40;
- self.panels[self.count].target_w = @as(f32, @floatFromInt(g_width)) - 40;
- self.panels[self.count].target_h = @as(f32, @floatFromInt(g_height)) - 100;
- self.active_panel = self.count;
- self.count += 1;
- }
- }
-
- // Unfocus all panels
- pub fn unfocusAll(self: *PanelSystem) void {
- for (0..self.count) |i| {
- if (self.panels[i].is_focused) {
- self.panels[i].unfocus();
- }
- }
- }
-
- // JARVIS-style focus with spherical morph animation
- // If panel of type exists: bring to front + refocus
- // If not: spawn new with JARVIS sphere β rectangle animation
- pub fn jarvisFocus(self: *PanelSystem, ptype: PanelType, x: f32, y: f32, w: f32, h: f32, title: []const u8) void {
- // First unfocus all panels
- for (0..self.count) |i| {
- if (self.panels[i].is_focused) {
- self.panels[i].unfocus();
- }
- }
-
- // Find existing panel of this type
- for (0..self.count) |i| {
- if (self.panels[i].panel_type == ptype and self.panels[i].state == .open) {
- // Bring to front by swapping with last panel
- if (i < self.count - 1) {
- const temp = self.panels[i];
- // Shift all panels down
- var j: usize = i;
- while (j < self.count - 1) : (j += 1) {
- self.panels[j] = self.panels[j + 1];
- }
- self.panels[self.count - 1] = temp;
- }
- // JARVIS focus with spherical morph
- self.panels[self.count - 1].jarvisFocus();
- self.active_panel = self.count - 1;
- return;
- }
- }
-
- // No existing panel - spawn new with JARVIS animation
- if (self.count < MAX_PANELS) {
- self.panels[self.count] = GlassPanel.init(x, y, w, h, ptype, title);
- self.panels[self.count].open();
- self.panels[self.count].jarvisFocus();
- self.active_panel = self.count;
- self.count += 1;
- }
- }
-
- pub fn update(self: *PanelSystem, dt: f32, time: f32, mx: f32, my: f32, mouse_pressed: bool, mouse_down: bool, mouse_released: bool, mouse_wheel: f32) void {
- // Handle mouse interactions
- if (mouse_pressed) {
- // Check if clicking on any panel (reverse order for z-order)
- var i: usize = self.count;
- while (i > 0) {
- i -= 1;
- const panel = &self.panels[i];
- if (panel.state != .open) continue;
-
- // Close button (traffic light red)
- if (panel.isPointOnClose(mx, my)) {
- panel.close();
- return;
- }
-
- // Resize handle (bottom-right)
- if (panel.isPointOnResize(mx, my)) {
- panel.resizing = true;
- self.active_panel = i;
- return;
- }
-
- // Title bar drag
- if (panel.isPointInTitleBar(mx, my)) {
- panel.dragging = true;
- panel.drag_offset_x = mx - panel.x;
- panel.drag_offset_y = my - panel.y;
- self.active_panel = i;
- self.swipe_start_x = mx;
- self.swipe_start_y = my;
- return;
- }
-
- // Click inside panel
- if (panel.isPointInside(mx, my)) {
- self.active_panel = i;
-
- // Handle vision panel clicks - start analyzing
- if (panel.panel_type == .vision and !panel.vision_analyzing and panel.vision_result_len == 0) {
- panel.vision_analyzing = true;
- panel.vision_progress = 0;
- }
-
- // Handle voice panel clicks - toggle recording
- if (panel.panel_type == .voice) {
- panel.voice_recording = !panel.voice_recording;
- if (!panel.voice_recording) {
- // Finished recording - simulate STT
- panel.addChatMessage("Voice: [transcribed audio]", false);
- }
- }
-
- // Handle finder panel clicks
- if (panel.panel_type == .finder) {
- // Pass time for calculating positions
- if (panel.getFinderEntryAt(mx, my, time)) |entry_idx| {
- const entry = &panel.finder_entries[entry_idx];
- panel.finder_selected = entry_idx;
-
- // Navigate into folder on click
- if (entry.is_dir and entry.name_len > 0) {
- // Build new path
- var new_path: [1024]u8 = undefined;
- var new_len: usize = 0;
-
- // Check for parent directory (..)
- if (entry.name_len == 2 and entry.name[0] == '.' and entry.name[1] == '.') {
- // Go up one level
- if (panel.finder_path_len > 0) {
- // Find last separator
- var sep_idx: usize = panel.finder_path_len;
- while (sep_idx > 0) : (sep_idx -= 1) {
- if (panel.finder_path[sep_idx - 1] == '/') {
- break;
- }
- }
- if (sep_idx > 1) {
- @memcpy(new_path[0 .. sep_idx - 1], panel.finder_path[0 .. sep_idx - 1]);
- new_len = sep_idx - 1;
- } else {
- new_path[0] = '.';
- new_len = 1;
- }
- }
- } else {
- // Enter subdirectory
- if (panel.finder_path_len > 0 and panel.finder_path[0] != '.') {
- @memcpy(new_path[0..panel.finder_path_len], panel.finder_path[0..panel.finder_path_len]);
- new_path[panel.finder_path_len] = '/';
- new_len = panel.finder_path_len + 1;
- }
- @memcpy(new_path[new_len .. new_len + entry.name_len], entry.name[0..entry.name_len]);
- new_len += entry.name_len;
- }
-
- // Load new directory with ripple effect
- panel.finder_ripple = 1.0; // Trigger cosmic ripple
- panel.loadDirectory(new_path[0..new_len]);
- }
- }
- }
- return;
- }
- }
-
- // Start swipe on empty area
- self.swiping = true;
- self.swipe_start_x = mx;
- self.swipe_start_y = my;
- }
-
- if (mouse_down) {
- if (self.active_panel) |idx| {
- const panel = &self.panels[idx];
-
- // Resizing
- if (panel.resizing) {
- const new_w = @max(200, mx - panel.x);
- const new_h = @max(150, my - panel.y);
- panel.width = new_w;
- panel.height = new_h;
- }
- // Dragging
- else if (panel.dragging) {
- const new_x = mx - panel.drag_offset_x;
- const new_y = my - panel.drag_offset_y;
- panel.vel_x = (new_x - panel.x) / dt;
- panel.vel_y = (new_y - panel.y) / dt;
- panel.x = new_x;
- panel.y = new_y;
- }
- }
- }
-
- if (mouse_released) {
- // End dragging/resizing with snap-to-grid
- if (self.active_panel) |idx| {
- const panel = &self.panels[idx];
- panel.dragging = false;
- panel.resizing = false;
-
- // Snap to grid (32px)
- const grid_size: f32 = 32;
- panel.x = @round(panel.x / grid_size) * grid_size;
- panel.y = @round(panel.y / grid_size) * grid_size;
- panel.width = @round(panel.width / grid_size) * grid_size;
- panel.height = @round(panel.height / grid_size) * grid_size;
-
- // Ensure minimum size
- panel.width = @max(200, panel.width);
- panel.height = @max(150, panel.height);
- }
-
- // Check swipe gesture
- if (self.swiping) {
- const dx = mx - self.swipe_start_x;
- const dy = my - self.swipe_start_y;
- const swipe_threshold: f32 = 100;
-
- if (@abs(dy) > swipe_threshold and dy < 0) {
- // Swipe UP - minimize all panels
- for (&self.panels) |*p| {
- if (p.state == .open) p.minimize();
- }
- } else if (@abs(dx) > swipe_threshold) {
- // Swipe LEFT/RIGHT - add velocity to open panels
- const vel_boost: f32 = dx * 5.0;
- for (&self.panels) |*p| {
- if (p.state == .open) p.vel_x += vel_boost;
- }
- }
- }
-
- self.swiping = false;
- }
-
- // Handle mouse wheel scroll for panel under cursor
- if (mouse_wheel != 0) {
- for (0..self.count) |i| {
- const panel = &self.panels[i];
- if (panel.state == .open and panel.isPointInside(mx, my)) {
- if (panel.wave_scroll_enabled) {
- // Emergent Wave ScrollView: apply impulse (phi-damped physics)
- panel.wave_sv.applyImpulse(-mouse_wheel);
- } else {
- // Legacy lerp scroll
- panel.scroll_target -= mouse_wheel * 30.0;
- // Dynamic max scroll for sacred_world panels
- const max_scroll: f32 = if (panel.panel_type == .sacred_world) blk_scroll: {
- if (panel.world_id == 0) {
- break :blk_scroll 0.0;
- } else if (panel.world_id == 18) {
- var total: u32 = 0;
- var di: usize = 0;
- while (di < 27) : (di += 1) {
- total += world_docs.countVisibleLines(world_docs.WORLD_DOCS[di].raw);
- total += 4;
- }
- break :blk_scroll @as(f32, @floatFromInt(total)) * 18.0 * g_font_scale;
- } else {
- break :blk_scroll 0.0;
- }
- } else 500.0;
- panel.scroll_target = @max(0, @min(panel.scroll_target, max_scroll));
- }
- break;
- }
- }
- }
-
- // Scroll update: wave or legacy
- for (0..self.count) |i| {
- const panel = &self.panels[i];
- if (panel.state == .open) {
- if (panel.wave_scroll_enabled) {
- // Sync viewport bounds after panel move/resize
- panel.wave_sv.setViewport(panel.x, panel.y + 32.0, panel.width, panel.height - 32.0);
- // Emergent Wave ScrollView: phi-damped SIMD physics
- panel.wave_sv.updatePhysics(dt);
- // Dirty-flag: skip expensive SIMD when scroll is idle
- if (panel.wave_sv.needs_eval) {
- panel.wave_sv.updateVisibleRange();
- panel.wave_sv.evaluatePacketsSIMD();
- panel.wave_sv.computeInterference();
- }
- // Sync scroll_y for render compatibility (with rubber-band)
- panel.scroll_y = panel.wave_sv.getScrollYWithRubber();
- } else {
- // Legacy smooth scroll interpolation (lerp toward target)
- const diff = panel.scroll_target - panel.scroll_y;
- if (@abs(diff) > 0.5) {
- panel.scroll_y += diff * @min(1.0, dt * 12.0);
- } else {
- panel.scroll_y = panel.scroll_target;
- }
- }
- }
- }
-
- // Adaptive resize: update focused panel targets to current window size
- const cur_w = @as(f32, @floatFromInt(g_width));
- const cur_h = @as(f32, @floatFromInt(g_height));
- const card_margin: f32 = 40; // Card padding from edges
- const card_top: f32 = 50; // Top margin (space for status bar)
- const card_bottom: f32 = 50; // Bottom margin
- for (0..self.count) |i| {
- const p = &self.panels[i];
- if ((p.state == .open or p.state == .opening) and p.is_focused) {
- p.target_x = card_margin;
- p.target_y = card_top;
- p.target_w = cur_w - card_margin * 2;
- p.target_h = cur_h - card_top - card_bottom;
- // Snap sacred_world panels immediately (no animation lag on resize)
- if (p.panel_type == .sacred_world) {
- p.x = p.target_x;
- p.y = p.target_y;
- p.width = p.target_w;
- p.height = p.target_h;
- }
- }
- }
-
- // Update all panels
- for (0..self.count) |i| {
- self.panels[i].update(dt);
- }
- }
-
- pub fn draw(self: *const PanelSystem, time: f32, font: rl.Font) void {
- for (0..self.count) |i| {
- self.panels[i].draw(time, font);
- }
- }
-};
-
-// =============================================================================
-// TRINITY MODES (Full functionality in canvas)
-// =============================================================================
-
-const TrinityMode = enum {
- idle, // Wave exploration
- chat, // Chat emerges as wave clusters
- code, // Code gen as structural spirals
- vision, // Image β wave perturbation
- voice, // Voice β frequency modulation
- tools, // Tool execution as orbiting clusters
- autonomous, // Self-directed emergence
-};
-
-// =============================================================================
-// WAVE CLUSTER (Chat text as interference patterns)
-// =============================================================================
-
-const MAX_CLUSTERS = 32;
-const MAX_CLUSTER_CHARS = 256;
-
-const WaveCluster = struct {
- chars: [MAX_CLUSTER_CHARS]u8,
- len: usize,
- x: f32,
- y: f32,
- radius: f32,
- phase: f32,
- life: f32,
- hue: f32,
- is_user: bool, // User message vs AI response
-
- pub fn spawn(x: f32, y: f32, text: []const u8, is_user: bool) WaveCluster {
- var cluster = WaveCluster{
- .chars = undefined,
- .len = @min(text.len, MAX_CLUSTER_CHARS),
- .x = x,
- .y = y,
- .radius = 50.0,
- .phase = 0,
- .life = 1.0,
- .hue = if (is_user) 180.0 else 120.0, // Cyan for user, green for AI
- .is_user = is_user,
- };
- @memcpy(cluster.chars[0..cluster.len], text[0..cluster.len]);
- return cluster;
- }
-
- pub fn update(self: *WaveCluster, dt: f32) void {
- self.phase += dt * 2.0;
- self.radius += dt * 10.0; // Expand outward
- self.life -= dt * 0.1; // Slow fade
- }
-
- pub fn isAlive(self: *const WaveCluster) bool {
- return self.life > 0;
- }
-
- pub fn draw(self: *const WaveCluster, time: f32) void {
- if (!self.isAlive()) return;
-
- const alpha: u8 = @intFromFloat(@max(0, @min(255, self.life * 255)));
- const rgb = hsvToRgb(self.hue, 0.8, 1.0);
-
- // Draw as concentric rings (wave interference)
- const num_rings: usize = @intFromFloat(@max(1, self.radius / 15.0));
- for (0..num_rings) |i| {
- const ring_r = @as(f32, @floatFromInt(i)) * 15.0 + @sin(time * 3.0 + self.phase) * 5.0;
- const ring_alpha: u8 = @intFromFloat(@as(f32, @floatFromInt(alpha)) * (1.0 - @as(f32, @floatFromInt(i)) / @as(f32, @floatFromInt(num_rings))));
- rl.DrawCircleLines(
- @intFromFloat(self.x),
- @intFromFloat(self.y),
- ring_r,
- rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = ring_alpha },
- );
- }
-
- // Draw character glyphs around the cluster
- const chars_to_show = @min(self.len, 32);
- for (0..chars_to_show) |i| {
- const angle = @as(f32, @floatFromInt(i)) * TAU / @as(f32, @floatFromInt(chars_to_show)) + self.phase;
- const char_r = self.radius * 0.7;
- const cx = self.x + @cos(angle) * char_r;
- const cy = self.y + @sin(angle) * char_r;
-
- // Character as small circle (ASCII-based size)
- const char_val = self.chars[i];
- const char_size = 2.0 + @as(f32, @floatFromInt(char_val % 10)) * 0.3;
- rl.DrawCircle(
- @intFromFloat(cx),
- @intFromFloat(cy),
- char_size,
- rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = alpha },
- );
- }
- }
-};
-
-const ClusterSystem = struct {
- clusters: [MAX_CLUSTERS]WaveCluster,
- count: usize,
-
- pub fn init() ClusterSystem {
- var sys = ClusterSystem{
- .clusters = undefined,
- .count = 0,
- };
- for (&sys.clusters) |*c| {
- c.life = 0;
- }
- return sys;
- }
-
- pub fn spawn(self: *ClusterSystem, x: f32, y: f32, text: []const u8, is_user: bool) void {
- // Find dead slot
- for (&self.clusters) |*c| {
- if (!c.isAlive()) {
- c.* = WaveCluster.spawn(x, y, text, is_user);
- return;
- }
- }
- // Overwrite oldest if full
- if (self.count < MAX_CLUSTERS) {
- self.clusters[self.count] = WaveCluster.spawn(x, y, text, is_user);
- self.count += 1;
- }
- }
-
- pub fn update(self: *ClusterSystem, dt: f32) void {
- for (&self.clusters) |*c| {
- if (c.isAlive()) {
- c.update(dt);
- }
- }
- }
-
- pub fn draw(self: *const ClusterSystem, time: f32) void {
- for (&self.clusters) |*c| {
- c.draw(time);
- }
- }
-};
-
-// =============================================================================
-// CODE SPIRAL (Code gen as structural patterns)
-// =============================================================================
-
-const MAX_SPIRALS = 16;
-
-const CodeSpiral = struct {
- x: f32,
- y: f32,
- turns: f32, // Number of spiral turns
- scale: f32,
- rotation: f32,
- life: f32,
- syntax_hue: f32, // Color based on syntax type
-
- const SyntaxType = enum {
- keyword, // Blue
- function, // Green
- variable, // Yellow
- literal, // Magenta
- operator, // Cyan
- };
-
- pub fn spawn(x: f32, y: f32, syntax: SyntaxType) CodeSpiral {
- const hue: f32 = switch (syntax) {
- .keyword => 240.0,
- .function => 120.0,
- .variable => 60.0,
- .literal => 300.0,
- .operator => 180.0,
- };
- return .{
- .x = x,
- .y = y,
- .turns = 3.0,
- .scale = 20.0,
- .rotation = 0,
- .life = 1.0,
- .syntax_hue = hue,
- };
- }
-
- pub fn update(self: *CodeSpiral, dt: f32) void {
- self.rotation += dt * PHI;
- self.scale += dt * 5.0;
- self.turns += dt * 0.5;
- self.life -= dt * 0.15;
- }
-
- pub fn isAlive(self: *const CodeSpiral) bool {
- return self.life > 0;
- }
-
- pub fn draw(self: *const CodeSpiral) void {
- if (!self.isAlive()) return;
-
- const alpha: u8 = @intFromFloat(@max(0, @min(255, self.life * 255)));
- const rgb = hsvToRgb(self.syntax_hue, 0.9, 1.0);
-
- // Draw golden spiral
- const steps: usize = @intFromFloat(self.turns * 32);
- var prev_x: c_int = @intFromFloat(self.x);
- var prev_y: c_int = @intFromFloat(self.y);
-
- for (0..steps) |i| {
- const t = @as(f32, @floatFromInt(i)) * 0.1;
- const r = self.scale * @exp(t * PHI_INV * 0.1);
- const angle = t + self.rotation;
-
- const px: c_int = @intFromFloat(self.x + @cos(angle) * r);
- const py: c_int = @intFromFloat(self.y + @sin(angle) * r);
-
- rl.DrawLine(prev_x, prev_y, px, py, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = alpha });
-
- prev_x = px;
- prev_y = py;
- }
- }
-};
-
-const SpiralSystem = struct {
- spirals: [MAX_SPIRALS]CodeSpiral,
- count: usize,
-
- pub fn init() SpiralSystem {
- var sys = SpiralSystem{
- .spirals = undefined,
- .count = 0,
- };
- for (&sys.spirals) |*s| {
- s.life = 0;
- }
- return sys;
- }
-
- pub fn spawn(self: *SpiralSystem, x: f32, y: f32, syntax: CodeSpiral.SyntaxType) void {
- for (&self.spirals) |*s| {
- if (!s.isAlive()) {
- s.* = CodeSpiral.spawn(x, y, syntax);
- return;
- }
- }
- }
-
- pub fn update(self: *SpiralSystem, dt: f32) void {
- for (&self.spirals) |*s| {
- if (s.isAlive()) {
- s.update(dt);
- }
- }
- }
-
- pub fn draw(self: *const SpiralSystem) void {
- for (&self.spirals) |*s| {
- s.draw();
- }
- }
-};
-
-// =============================================================================
-// TOOL CLUSTER (Orbiting execution indicators)
-// =============================================================================
-
-const MAX_TOOLS = 8;
-
-const ToolOrbit = struct {
- name: [32]u8,
- name_len: usize,
- cx: f32,
- cy: f32,
- radius: f32,
- angle: f32,
- speed: f32,
- status: ToolStatus,
- life: f32,
-
- const ToolStatus = enum {
- pending, // Yellow
- running, // Cyan pulse
- success, // Green nova
- failure, // Red sink
- };
-
- pub fn spawn(cx: f32, cy: f32, name: []const u8) ToolOrbit {
- var tool = ToolOrbit{
- .name = undefined,
- .name_len = @min(name.len, 32),
- .cx = cx,
- .cy = cy,
- .radius = 100.0 + @as(f32, @floatFromInt(name.len % 5)) * 20.0,
- .angle = @as(f32, @floatFromInt(name.len)) * 0.5,
- .speed = 1.0,
- .status = .pending,
- .life = 1.0,
- };
- @memcpy(tool.name[0..tool.name_len], name[0..tool.name_len]);
- return tool;
- }
-
- pub fn update(self: *ToolOrbit, dt: f32) void {
- self.angle += self.speed * dt;
-
- switch (self.status) {
- .running => self.speed = 3.0,
- .success => {
- self.radius += dt * 50.0;
- self.life -= dt * 0.5;
- },
- .failure => {
- self.radius -= dt * 30.0;
- self.life -= dt * 0.5;
- },
- else => {},
- }
- }
-
- pub fn isAlive(self: *const ToolOrbit) bool {
- return self.life > 0 and self.radius > 0;
- }
-
- pub fn draw(self: *const ToolOrbit, time: f32) void {
- if (!self.isAlive()) return;
-
- const x = self.cx + @cos(self.angle) * self.radius;
- const y = self.cy + @sin(self.angle) * self.radius;
-
- const alpha: u8 = @intFromFloat(@max(0, @min(255, self.life * 255)));
-
- const color: rl.Color = switch (self.status) {
- .pending => rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha },
- .running => blk: {
- const pulse: u8 = @intFromFloat(128.0 + @sin(time * 10.0) * 127.0);
- break :blk rl.Color{ .r = 0x00, .g = pulse, .b = 0xFF, .a = alpha };
- },
- .success => rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = alpha },
- .failure => rl.Color{ .r = 0xFF, .g = 0x00, .b = 0x44, .a = alpha },
- };
-
- // Draw tool as pulsating circle
- const size = 8.0 + @sin(time * 5.0 + self.angle) * 3.0;
- rl.DrawCircle(@intFromFloat(x), @intFromFloat(y), size, color);
-
- // Draw orbit path (faint)
- rl.DrawCircleLines(@intFromFloat(self.cx), @intFromFloat(self.cy), self.radius, rl.Color{ .r = color.r, .g = color.g, .b = color.b, .a = alpha / 4 });
- }
-};
-
-const ToolSystem = struct {
- tools: [MAX_TOOLS]ToolOrbit,
- count: usize,
-
- pub fn init() ToolSystem {
- var sys = ToolSystem{
- .tools = undefined,
- .count = 0,
- };
- for (&sys.tools) |*t| {
- t.life = 0;
- }
- return sys;
- }
-
- pub fn spawn(self: *ToolSystem, cx: f32, cy: f32, name: []const u8) void {
- for (&self.tools) |*t| {
- if (!t.isAlive()) {
- t.* = ToolOrbit.spawn(cx, cy, name);
- return;
- }
- }
- }
-
- pub fn setStatus(self: *ToolSystem, name: []const u8, status: ToolOrbit.ToolStatus) void {
- for (&self.tools) |*t| {
- if (t.isAlive() and std.mem.eql(u8, t.name[0..t.name_len], name)) {
- t.status = status;
- return;
- }
- }
- }
-
- pub fn update(self: *ToolSystem, dt: f32) void {
- for (&self.tools) |*t| {
- if (t.isAlive()) {
- t.update(dt);
- }
- }
- }
-
- pub fn draw(self: *const ToolSystem, time: f32) void {
- for (&self.tools) |*t| {
- t.draw(time);
- }
- }
-};
-
-// =============================================================================
-// COSMIC FEEDBACK (Nova/Sink effects)
-// =============================================================================
-
-const MAX_EFFECTS = 16;
-
-const CosmicEffect = struct {
- x: f32,
- y: f32,
- radius: f32,
- life: f32,
- is_nova: bool, // true = success nova, false = failure sink
-
- pub fn spawnNova(x: f32, y: f32) CosmicEffect {
- return .{
- .x = x,
- .y = y,
- .radius = 10.0,
- .life = 1.0,
- .is_nova = true,
- };
- }
-
- pub fn spawnSink(x: f32, y: f32) CosmicEffect {
- return .{
- .x = x,
- .y = y,
- .radius = 100.0,
- .life = 1.0,
- .is_nova = false,
- };
- }
-
- pub fn update(self: *CosmicEffect, dt: f32) void {
- if (self.is_nova) {
- self.radius += dt * 200.0; // Expand
- } else {
- self.radius -= dt * 80.0; // Contract
- }
- self.life -= dt * 1.5;
- }
-
- pub fn isAlive(self: *const CosmicEffect) bool {
- return self.life > 0 and self.radius > 0;
- }
-
- pub fn draw(self: *const CosmicEffect) void {
- if (!self.isAlive()) return;
-
- const alpha: u8 = @intFromFloat(@max(0, @min(255, self.life * 255)));
-
- if (self.is_nova) {
- // Success: bright expanding rings
- const num_rings: usize = 5;
- for (0..num_rings) |i| {
- const ring_r = self.radius * (1.0 - @as(f32, @floatFromInt(i)) * 0.15);
- const ring_alpha: u8 = @intFromFloat(@as(f32, @floatFromInt(alpha)) * (1.0 - @as(f32, @floatFromInt(i)) * 0.2));
- rl.DrawCircleLines(
- @intFromFloat(self.x),
- @intFromFloat(self.y),
- ring_r,
- rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x88, .a = ring_alpha },
- );
- }
- // Center flash
- rl.DrawCircle(@intFromFloat(self.x), @intFromFloat(self.y), 10.0, rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = alpha });
- } else {
- // Failure: dark collapsing vortex
- const num_rings: usize = 5;
- for (0..num_rings) |i| {
- const ring_r = self.radius * (0.2 + @as(f32, @floatFromInt(i)) * 0.2);
- rl.DrawCircleLines(
- @intFromFloat(self.x),
- @intFromFloat(self.y),
- ring_r,
- rl.Color{ .r = 0xFF, .g = 0x00, .b = 0x44, .a = alpha },
- );
- }
- // Dark center
- rl.DrawCircle(@intFromFloat(self.x), @intFromFloat(self.y), self.radius * 0.3, rl.Color{ .r = 0x20, .g = 0x00, .b = 0x10, .a = alpha });
- }
- }
-};
-
-const EffectSystem = struct {
- effects: [MAX_EFFECTS]CosmicEffect,
-
- pub fn init() EffectSystem {
- var sys = EffectSystem{
- .effects = undefined,
- };
- for (&sys.effects) |*e| {
- e.life = 0;
- }
- return sys;
- }
-
- pub fn nova(self: *EffectSystem, x: f32, y: f32) void {
- for (&self.effects) |*e| {
- if (!e.isAlive()) {
- e.* = CosmicEffect.spawnNova(x, y);
- return;
- }
- }
- }
-
- pub fn sink(self: *EffectSystem, x: f32, y: f32) void {
- for (&self.effects) |*e| {
- if (!e.isAlive()) {
- e.* = CosmicEffect.spawnSink(x, y);
- return;
- }
- }
- }
-
- pub fn update(self: *EffectSystem, dt: f32) void {
- for (&self.effects) |*e| {
- if (e.isAlive()) {
- e.update(dt);
- }
- }
- }
-
- pub fn draw(self: *const EffectSystem) void {
- for (&self.effects) |*e| {
- e.draw();
- }
- }
-};
-
-// =============================================================================
-// AUTONOMOUS GOAL (Self-directed wave growth)
-// =============================================================================
-
-const WaveSeed = struct {
- x: usize,
- y: usize,
- active: bool,
-};
-
-const AutonomousGoal = struct {
- text: [256]u8,
- len: usize,
- x: f32,
- y: f32,
- progress: f32, // 0.0 to 1.0
- wave_seeds: [8]WaveSeed,
- active: bool,
-
- pub fn init() AutonomousGoal {
- return .{
- .text = undefined,
- .len = 0,
- .x = 0,
- .y = 0,
- .progress = 0,
- .wave_seeds = [_]WaveSeed{.{ .x = 0, .y = 0, .active = false }} ** 8,
- .active = false,
- };
- }
-
- pub fn setGoal(self: *AutonomousGoal, goal: []const u8, x: f32, y: f32) void {
- self.len = @min(goal.len, 256);
- @memcpy(self.text[0..self.len], goal[0..self.len]);
- self.x = x;
- self.y = y;
- self.progress = 0;
- self.active = true;
-
- // Generate wave seeds based on goal text
- for (0..8) |i| {
- if (i < goal.len) {
- const c = goal[i % goal.len];
- self.wave_seeds[i] = .{
- .x = @intCast((@as(usize, c) * 3 + i * 17) % 378),
- .y = @intCast((@as(usize, c) * 7 + i * 23) % 245),
- .active = true,
- };
- }
- }
- }
-
- pub fn update(self: *AutonomousGoal, grid: *photon.PhotonGrid, dt: f32) void {
- if (!self.active) return;
-
- // Inject waves at seed points
- for (&self.wave_seeds) |*seed| {
- if (seed.active and seed.x < grid.width and seed.y < grid.height) {
- grid.getMut(seed.x, seed.y).amplitude += @sin(self.progress * TAU) * 0.5;
- }
- }
-
- // Progress grows based on grid energy
- self.progress += dt * 0.05 * (1.0 + grid.total_energy * 0.0001);
-
- if (self.progress >= 1.0) {
- self.active = false;
- }
- }
-
- pub fn draw(self: *const AutonomousGoal, time: f32) void {
- if (!self.active) return;
-
- const alpha: u8 = @intFromFloat(150.0 + @sin(time * 2.0) * 50.0);
-
- // Draw progress arc
- const arc_radius: f32 = 150.0;
- const arc_steps: usize = @intFromFloat(self.progress * 64.0);
-
- for (0..arc_steps) |i| {
- const angle = @as(f32, @floatFromInt(i)) * TAU / 64.0 - TAU / 4.0;
- const px = self.x + @cos(angle) * arc_radius;
- const py = self.y + @sin(angle) * arc_radius;
-
- rl.DrawCircle(@intFromFloat(px), @intFromFloat(py), 3.0, rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha });
- }
-
- // Draw seed points
- for (&self.wave_seeds) |seed| {
- if (seed.active) {
- const sx: c_int = @intCast(seed.x * @as(usize, @intCast(g_pixel_size)));
- const sy: c_int = @intCast(seed.y * @as(usize, @intCast(g_pixel_size)));
- rl.DrawCircle(sx, sy, 5.0 + @sin(time * 5.0) * 2.0, rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 100 });
- }
- }
- }
-};
-
-// =============================================================================
-// INPUT BUFFER (For text/goal input)
-// =============================================================================
-
-const InputBuffer = struct {
- buffer: [512]u8,
- len: usize,
- active: bool,
- mode: InputMode,
-
- const InputMode = enum {
- chat,
- goal,
- code,
- };
-
- pub fn init() InputBuffer {
- return .{
- .buffer = undefined,
- .len = 0,
- .active = true, // Start active - ready to type!
- .mode = .chat,
- };
- }
-
- pub fn start(self: *InputBuffer, mode: InputMode) void {
- self.len = 0;
- self.active = true;
- self.mode = mode;
- }
-
- pub fn addChar(self: *InputBuffer, c: u8) void {
- if (self.len < 511) {
- self.buffer[self.len] = c;
- self.len += 1;
- }
- }
-
- pub fn backspace(self: *InputBuffer) void {
- if (self.len > 0) {
- self.len -= 1;
- }
- }
-
- pub fn getText(self: *const InputBuffer) []const u8 {
- return self.buffer[0..self.len];
- }
-
- pub fn submit(self: *InputBuffer) []const u8 {
- const text = self.getText();
- self.active = false;
- return text;
- }
-
- pub fn draw(self: *const InputBuffer, time: f32) void {
- // Always draw input box (even when not active, show hint)
- const box_y = g_height - 60;
- rl.DrawRectangle(0, box_y, g_width, 60, withAlpha(BG_INPUT, 220));
-
- if (!self.active) {
- // Show hint when not active
- rl.DrawText("Press C=Chat, G=Goal, X=Code, ESC=Exit", 20, box_y + 20, 18, MUTED_GRAY);
- return;
- }
-
- const label = switch (self.mode) {
- .chat => "CHAT> ",
- .goal => "GOAL> ",
- .code => "CODE> ",
- };
-
- // Label with bright color
- rl.DrawText(label.ptr, 20, box_y + 20, 20, NEON_GREEN);
-
- // Text
- var display_buf: [520]u8 = undefined;
- const display_len = @min(self.len, 500);
- @memcpy(display_buf[0..display_len], self.buffer[0..display_len]);
-
- // Cursor blink
- if (@mod(@as(u32, @intFromFloat(time * 3.0)), 2) == 0) {
- display_buf[display_len] = '_';
- display_buf[display_len + 1] = 0;
- } else {
- display_buf[display_len] = 0;
- }
-
- rl.DrawText(@ptrCast(&display_buf), 90, box_y + 20, 20, NOVA_WHITE);
-
- // Show Enter hint
- rl.DrawText("Enter=Send | ESC=Cancel", g_width - 220, box_y + 20, 14, TEXT_HINT);
- }
-};
-
-// =============================================================================
-// FRAME STATE β promoted from main() locals for emscripten_set_main_loop compat
-// Same names as the old locals so the 1720-line loop body needs zero changes
-// =============================================================================
-var frame_grid: photon.PhotonGrid = undefined;
-var frame_clusters: ClusterSystem = undefined;
-var frame_spirals: SpiralSystem = undefined;
-var frame_tools: ToolSystem = undefined;
-var frame_effects: EffectSystem = undefined;
-var frame_goal: AutonomousGoal = undefined;
-var frame_panels: PanelSystem = undefined;
-var frame_time: f32 = 0;
-var frame_mode: TrinityMode = .idle;
-var frame_cursor_hue: f32 = 120;
-var frame_logo_anim: LogoAnimation = undefined;
-var frame_loading_complete: bool = false;
-var frame_formula_particles: [MAX_FORMULA_PARTICLES]FormulaParticle = undefined;
-var frame_font: rl.Font = undefined;
-var frame_font_small: rl.Font = undefined;
-var frame_allocator: std.mem.Allocator = undefined;
-var g_should_quit: bool = false;
-
-// =============================================================================
-// MAIN TRINITY CANVAS
-// =============================================================================
-
-pub fn main() !void {
- // GPA uses mmap internals not available in WASM; use page_allocator for emscripten
- var gpa: if (is_emscripten) u8 else std.heap.GeneralPurposeAllocator(.{}) =
- if (is_emscripten) 0 else std.heap.GeneralPurposeAllocator(.{}){};
- defer if (!is_emscripten) {
- _ = gpa.deinit();
- };
- const allocator = if (is_emscripten) std.heap.page_allocator else gpa.allocator();
- frame_allocator = allocator;
-
- // Raylib init - RESIZABLE WINDOW (responsive!)
- if (is_emscripten) {
- rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT | rl.FLAG_MSAA_4X_HINT);
- } else {
- // High DPI + MSAA + TRANSPARENT background (see desktop through)
- rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT | rl.FLAG_MSAA_4X_HINT | rl.FLAG_WINDOW_HIGHDPI | rl.FLAG_WINDOW_TRANSPARENT | rl.FLAG_WINDOW_MAXIMIZED);
- }
- rl.InitWindow(1280, 800, "TRINITY v1.7 | Shift+1-7 = Panels | phi^2 + 1/phi^2 = 3");
- defer rl.CloseWindow();
-
- // Disable ESC auto-close β ESC hides panels, Cmd+Q quits
- rl.SetExitKey(0);
-
- // Set minimum window size for responsive design
- if (!is_emscripten) rl.SetWindowMinSize(800, 600);
-
- g_width = rl.GetScreenWidth();
- g_height = rl.GetScreenHeight();
-
- // ββ HiDPI / Retina detection ββ
- // GetWindowScaleDPI returns (sx, sy) β 2.0 on Mac Retina, 1.0 on standard
- const dpi_scale_v = rl.GetWindowScaleDPI();
- g_dpi_scale = @max(dpi_scale_v.x, dpi_scale_v.y);
- if (g_dpi_scale < 1.0) g_dpi_scale = 1.0;
-
- // Load fonts at physical pixel size for crisp Retina text
- // Base sizes: 48pt (headings), 32pt (body) β on 2x Retina β 96pt, 64pt atlas
- const font_size_large: c_int = @intFromFloat(48.0 * g_dpi_scale);
- const font_size_small: c_int = @intFromFloat(32.0 * g_dpi_scale);
-
- // UI fonts: Outfit (original, Latin-only, perfect metrics)
- frame_font = rl.LoadFontEx("assets/fonts/Outfit-Regular.ttf", font_size_large, null, 0);
- defer rl.UnloadFont(frame_font);
- frame_font_small = rl.LoadFontEx("assets/fonts/Outfit-Regular.ttf", font_size_small, null, 0);
- defer rl.UnloadFont(frame_font_small);
- // Enable bilinear filtering for smooth text at all sizes
- rl.SetTextureFilter(frame_font.texture, rl.TEXTURE_FILTER_BILINEAR);
- rl.SetTextureFilter(frame_font_small.texture, rl.TEXTURE_FILTER_BILINEAR);
-
- // v8.6: Emoji font for tool pills - NotoEmoji has full emoji support
- var emoji_codepoints: [50]c_int = undefined;
- const tool_emoji = [_]u32{
- 0x1F50D, // π Glob/Find
- 0x1F4F6, // π Read/Book
- 0x1F50E, // π Grep/Search
- 0x26A1, // β‘ Bash/Power
- 0x270F, // βοΈ Write/Pencil
- 0x1F504, // π Edit/Refresh
- 0x1F4CB, // π Todo/Clipboard
- 0x1F4E1, // π‘ Antenna
- 0x1F4BB, // π» Computer
- 0x1F9E0, // π§ Brain
- 0x1F680, // π Rocket
- 0x2705, // β
Check
- 0x274C, // β Cross
- 0x26A0, // β οΈ Warning
- 0x1F4A1, // π‘ Bulb
- 0x1F525, // π₯ Fire
- 0x2728, // β¨ Sparkles
- 0x1F308, // π Rainbow
- 0x1F916, // π€ Robot
- 0x1F3A8, // π¨ Palette
- 0x1F4CA, // π Chart
- 0x1F3AF, // π― Target
- 0x1F4B0, // π° Bag
- 0x2611, // βοΈ Ballot
- 0x1F7E2, // π’ Green circle
- 0x1F535, // π΅ Blue circle
- 0x1F7E3, // π£ Purple circle
- };
- for (0..tool_emoji.len) |i| emoji_codepoints[i] = @intCast(tool_emoji[i]);
-
- // Load NotoEmoji font (installed via brew, has full emoji support)
- g_font_emoji = rl.LoadFontEx("assets/fonts/NotoEmoji.ttf", 32, &emoji_codepoints, emoji_codepoints.len);
- rl.SetTextureFilter(g_font_emoji.texture, rl.TEXTURE_FILTER_BILINEAR);
- // Note: g_font_emoji is NOT unloaded here (used throughout app lifetime)
-
- // Chat font: SFPro (Latin + Cyrillic + Greek) at LARGE atlas size for crisp rendering
- var chat_codepoints: [95 + 256 + 144]c_int = undefined;
- for (0..95) |i| chat_codepoints[i] = @intCast(32 + i); // ASCII 32-126
- for (0..256) |i| chat_codepoints[95 + i] = @intCast(0x400 + i); // Cyrillic U+0400-U+04FF
- for (0..144) |i| chat_codepoints[95 + 256 + i] = @intCast(0x370 + i); // Greek U+0370-U+03FF (Ξ Ξ for agent avatars)
-
- g_font_chat = rl.LoadFontEx("assets/fonts/SFPro.ttf", font_size_large, &chat_codepoints, chat_codepoints.len);
- defer rl.UnloadFont(g_font_chat);
- rl.SetTextureFilter(g_font_chat.texture, rl.TEXTURE_FILTER_BILINEAR);
-
- // Grid (fixed size - will scale to window)
- const grid_w: usize = 320;
- const grid_h: usize = 200;
-
- frame_grid = try photon.PhotonGrid.init(allocator, grid_w, grid_h);
- defer frame_grid.deinit();
-
- // Systems
- frame_clusters = ClusterSystem.init();
- frame_spirals = SpiralSystem.init();
- frame_tools = ToolSystem.init();
- frame_effects = EffectSystem.init();
- frame_goal = AutonomousGoal.init();
- frame_panels = PanelSystem.init();
-
- // State (file-scope globals)
- frame_time = 0;
- frame_mode = .idle;
- frame_cursor_hue = 120;
-
- if (!is_emscripten) {
- rl.InitAudioDevice();
- }
- defer if (!is_emscripten) {
- rl.CloseAudioDevice();
- };
-
- rl.SetTargetFPS(60);
- // Show cursor for window resizing
- rl.ShowCursor();
- // Focus window for keyboard input
- if (!is_emscripten) rl.SetWindowFocused();
-
- // Initialize logo animation
- frame_logo_anim = LogoAnimation.init(@floatFromInt(g_width), @floatFromInt(g_height));
- frame_loading_complete = false;
-
- // Sacred formula particles β Fibonacci spiral orbit
- const formula_texts = [42][]const u8{
- // 27 world formulas
- "phi = 1.618", "pi*phi*e = 13.82", "L(10) = 123",
- "1/alpha = 137.036", "phi^2 = 2.618", "Feigenbaum = 4.669",
- "F(7) = 13", "sqrt(5) = 2.236", "999 = 37 x 27",
- "pi = 3.14159", "27 = 3^3", "CHSH = 2*sqrt(2)",
- "m_p/m_e = 1836", "pi^2 = 9.87", "e^pi = 23.14",
- "E8 = 248 dim", "603 = 67*9", "76 photons",
- "phi^2+1/phi^2 = 3", "tau = 6.283", "Menger = 2.727",
- "mu = 0.0382", "chi = 0.0618", "sigma = phi",
- "e = 2.71828", "13.82 Gyr", "H0 = 70.74",
- // 15 extra sacred formulas
- "V = n*3^k*pi^m*phi^p*e^q", "1.58 bits/trit", "phi = (1+sqrt(5))/2",
- "e^(i*pi) + 1 = 0", "3 = phi^2 + 1/phi^2", "F(n) = F(n-1)+F(n-2)",
- "hbar = 1.054e-34", "c = 299792458 m/s", "G = 6.674e-11",
- "L(n): 2,1,3,4,7,11,18...", "tau/phi = 3.883", "pi*e = 8.539",
- "phi^phi = 2.390", "3^3^3 = 7625597484987", "sqrt(2) = 1.414",
- };
- const formula_descs = [42][]const u8{
- "Golden ratio β nature's proportion", "Product of transcendentals", "10th Lucas number",
- "Fine structure constant inverse", "Golden ratio squared", "Feigenbaum chaos constant",
- "7th Fibonacci number", "Square root of five", "Sacred number 999",
- "Circle ratio", "Cube of trinity", "Quantum Bell bound",
- "Proton-electron mass ratio", "Basel problem result", "Euler to pi",
- "E8 Lie group dimension", "Energy efficiency", "Quantum advantage",
- "TRINITY IDENTITY", "Full turn tau", "Menger sponge fractal",
- "Mutation rate from phi", "Crossover rate from phi", "Selection = phi",
- "Euler's number", "Age of universe", "Hubble constant",
- "Trinity value formula", "Ternary information density", "Golden ratio definition",
- "Euler's identity", "Trinity identity", "Fibonacci recurrence",
- "Reduced Planck constant", "Speed of light", "Gravitational constant",
- "Lucas sequence", "Tau over phi", "Pi times e",
- "Phi to phi power", "Tower of threes", "Pythagoras' constant",
- };
- // formula_particles is file-scope global (frame_formula_particles)
- // Golden angle = 2*pi/phi^2 ~ 137.508 degrees β Fibonacci spiral
- const golden_angle: f32 = 2.0 * std.math.pi / (1.618 * 1.618);
- const min_radius: f32 = 240.0; // avoid overlapping the logo
- for (0..42) |fi| {
- const n = @as(f32, @floatFromInt(fi));
- const angle = n * golden_angle;
- const radius = min_radius + n * 14.0; // Wider spacing β each formula separate
- // Alternate direction: even layers clockwise, odd layers counter-clockwise
- const layer = fi / 9; // 0..4 layers of ~9
- const direction: f32 = if (layer % 2 == 0) 1.0 else -1.0;
- const speed: f32 = direction * (0.03 - n * 0.0003);
- frame_formula_particles[fi] = FormulaParticle.init(
- formula_texts[fi],
- formula_descs[fi],
- angle,
- radius,
- speed,
- );
- }
-
- // Main loop
- if (is_emscripten) {
- emc.emscripten_set_main_loop(updateDrawFrame, 0, true);
- } else {
- while (!rl.WindowShouldClose() and !g_should_quit) {
- updateDrawFrame();
- }
- }
-}
-
-fn updateDrawFrame() callconv(.c) void {
- // === BeginDrawing FIRST β ensures we always see something ===
- rl.BeginDrawing();
- defer rl.EndDrawing();
- rl.ClearBackground(rl.Color{ .r = 0, .g = 0, .b = 0, .a = 255 });
-
- // DEBUG marker removed (was: TRINITY WASM OK)
-
- const dt = rl.GetFrameTime();
- frame_time += dt;
-
- // Cmd+Q to quit (desktop only, not in WASM)
- if (!is_emscripten and (rl.IsKeyDown(rl.KEY_LEFT_SUPER) or rl.IsKeyDown(rl.KEY_RIGHT_SUPER)) and rl.IsKeyPressed(rl.KEY_Q)) {
- g_should_quit = true;
- return;
- }
-
- // Cmd+D = toggle dark/light theme
- if ((rl.IsKeyDown(rl.KEY_LEFT_SUPER) or rl.IsKeyDown(rl.KEY_RIGHT_SUPER)) and rl.IsKeyPressed(rl.KEY_D)) {
- theme.toggle();
- reloadThemeAliases();
- }
-
- // Click on sun/moon toggle button (top-right)
- if (rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT)) {
- const tcx: f32 = @as(f32, @floatFromInt(g_width)) - 35;
- const tcy: f32 = 30;
- const tmx = @as(f32, @floatFromInt(rl.GetMouseX()));
- const tmy = @as(f32, @floatFromInt(rl.GetMouseY()));
- const dx_t = tmx - tcx;
- const dy_t = tmy - tcy;
- if (dx_t * dx_t + dy_t * dy_t <= 14 * 14) {
- theme.toggle();
- reloadThemeAliases();
- }
- }
-
- // Update window size (adaptive/resizable)
- g_width = rl.GetScreenWidth();
- g_height = rl.GetScreenHeight();
-
- // Adaptive font scale: proportional to screen width (ref 1280px)
- // Trinity rule: scale by phi^(log3(w/1280)) for ternary harmony
- g_font_scale = @max(0.75, @min(2.0, @as(f32, @floatFromInt(g_width)) / 1280.0));
-
- // Calculate pixel size to COVER full window (no gaps at edges)
- const grid_w_c: c_int = @intCast(frame_grid.width);
- const grid_h_c: c_int = @intCast(frame_grid.height);
- const px_w = @divTrunc(g_width + grid_w_c - 1, grid_w_c); // ceil division
- const px_h = @divTrunc(g_height + grid_h_c - 1, grid_h_c);
- g_pixel_size = @max(1, @max(px_w, px_h));
-
- const mouse_x = rl.GetMouseX();
- const mouse_y = rl.GetMouseY();
- const mx = @as(f32, @floatFromInt(mouse_x));
- const my = @as(f32, @floatFromInt(mouse_y));
-
- const gx = @as(usize, @intCast(@max(0, @min(@as(c_int, @intCast(frame_grid.width - 1)), @divTrunc(mouse_x, g_pixel_size)))));
- const gy = @as(usize, @intCast(@max(0, @min(@as(c_int, @intCast(frame_grid.height - 1)), @divTrunc(mouse_y, g_pixel_size)))));
-
- frame_cursor_hue = @mod(frame_cursor_hue + dt * 30.0, 360.0);
-
- // === INPUT HANDLING ===
-
- // Detect if chat is active (wave mode or legacy panel)
- const chat_is_open: bool = if (g_wave_mode == .chat) true else blk_chat: {
- if (frame_panels.active_panel) |idx| {
- const p = &frame_panels.panels[idx];
- const is_visible = (p.state == .open or p.state == .opening);
- if (is_visible and p.panel_type == .chat) break :blk_chat true;
- if (is_visible and p.panel_type == .sacred_world and p.world_id == 0) break :blk_chat true;
- }
- break :blk_chat false;
- };
-
- // Sacred Worlds keyboard shortcuts:
- // Shift+1-9 = Realm RAZUM (blocks 0-8)
- // Ctrl+1-9 = Realm MATERIYA (blocks 9-17)
- // Cmd+1-9 = Realm DUKH (blocks 18-26)
- // DISABLED when chat panel is open (so user can type freely)
- const shift_held = rl.IsKeyDown(rl.KEY_LEFT_SHIFT) or rl.IsKeyDown(rl.KEY_RIGHT_SHIFT);
- const ctrl_held = rl.IsKeyDown(rl.KEY_LEFT_CONTROL) or rl.IsKeyDown(rl.KEY_RIGHT_CONTROL);
- const cmd_held = rl.IsKeyDown(rl.KEY_LEFT_SUPER) or rl.IsKeyDown(rl.KEY_RIGHT_SUPER);
-
- // Calculate fullscreen panel positions
- const screen_w = @as(f32, @floatFromInt(g_width));
- const screen_h = @as(f32, @floatFromInt(g_height));
-
- // v1.9: Shift+1-6 = Wave Mode Switch (no panels)
- // Chat mode also allows Shift+keys for wave mode switch
- if (!chat_is_open) {
- if (shift_held) {
- var new_mode: ?WaveMode = null;
- if (rl.IsKeyPressed(rl.KEY_ONE)) new_mode = .chat;
- if (rl.IsKeyPressed(rl.KEY_TWO)) new_mode = .code;
- if (rl.IsKeyPressed(rl.KEY_THREE)) new_mode = .tools;
- if (rl.IsKeyPressed(rl.KEY_FOUR)) new_mode = .settings;
- if (rl.IsKeyPressed(rl.KEY_FIVE)) new_mode = .vision;
- if (rl.IsKeyPressed(rl.KEY_SIX)) new_mode = .voice;
- if (rl.IsKeyPressed(rl.KEY_SEVEN)) new_mode = .finder;
- if (rl.IsKeyPressed(rl.KEY_EIGHT)) new_mode = .docs;
- if (rl.IsKeyPressed(rl.KEY_NINE)) new_mode = .ralph;
- if (rl.IsKeyPressed(rl.KEY_ZERO)) new_mode = .idle;
- if (rl.IsKeyPressed(rl.KEY_D)) new_mode = .depin;
- if (rl.IsKeyPressed(rl.KEY_M)) new_mode = .mirror;
-
- if (new_mode) |nm| {
- if (nm != g_wave_mode) {
- g_wave_mode_prev = g_wave_mode;
- g_wave_mode = nm;
- g_wave_transition = 0; // Start transition animation
- // Wave burst on mode change
- frame_effects.nova(screen_w / 2, screen_h / 2);
- // Perturb grid with mode's hue
- const mode_hue = nm.getHue();
- const freq_shift = mode_hue / 360.0 * TAU;
- for (0..@min(frame_grid.height, 5)) |wy| {
- for (0..frame_grid.width) |wx| {
- frame_grid.getMut(wx, wy).amplitude += @sin(freq_shift + @as(f32, @floatFromInt(wx)) * 0.3) * 0.2;
- }
- }
- }
- }
- }
- }
-
- // Keyboard scroll for active sacred_world panel (docs/chat only)
- if (frame_panels.active_panel) |ap_idx| {
- const ap = &frame_panels.panels[ap_idx];
- if (ap.panel_type == .sacred_world and ap.state == .open and ap.world_id != 0) {
- // Skip keyboard scroll for chat panel (world_id 0) β keys go to text input
- const max_scroll_kb: f32 = if (ap.world_id == 18) blk_ks: {
- var total: u32 = 0;
- var dsi: usize = 0;
- while (dsi < 27) : (dsi += 1) {
- total += world_docs.countVisibleLines(world_docs.WORLD_DOCS[dsi].raw);
- total += 4;
- }
- break :blk_ks @as(f32, @floatFromInt(total)) * 18.0 * g_font_scale;
- } else 0.0;
- if (ap.wave_scroll_enabled) {
- // Wave scroll: keyboard impulses
- if (rl.IsKeyPressed(rl.KEY_DOWN) or rl.IsKeyDown(rl.KEY_DOWN)) ap.wave_sv.applyImpulse(0.1);
- if (rl.IsKeyPressed(rl.KEY_UP) or rl.IsKeyDown(rl.KEY_UP)) ap.wave_sv.applyImpulse(-0.1);
- if (rl.IsKeyPressed(rl.KEY_PAGE_DOWN)) ap.wave_sv.applyImpulse(7.5);
- if (rl.IsKeyPressed(rl.KEY_PAGE_UP)) ap.wave_sv.applyImpulse(-7.5);
- if (rl.IsKeyPressed(rl.KEY_HOME)) ap.wave_sv.scrollToItem(0);
- if (rl.IsKeyPressed(rl.KEY_END)) ap.wave_sv.scrollToItem(ap.wave_sv.total_items -| 1);
- } else {
- // Legacy lerp scroll: keyboard targets
- if (rl.IsKeyPressed(rl.KEY_DOWN) or rl.IsKeyDown(rl.KEY_DOWN)) ap.scroll_target += 4.0;
- if (rl.IsKeyPressed(rl.KEY_UP) or rl.IsKeyDown(rl.KEY_UP)) ap.scroll_target -= 4.0;
- if (rl.IsKeyPressed(rl.KEY_PAGE_DOWN)) ap.scroll_target += 300;
- if (rl.IsKeyPressed(rl.KEY_PAGE_UP)) ap.scroll_target -= 300;
- if (rl.IsKeyPressed(rl.KEY_HOME)) ap.scroll_target = 0;
- if (rl.IsKeyPressed(rl.KEY_END)) ap.scroll_target = max_scroll_kb;
- ap.scroll_target = @max(0, @min(ap.scroll_target, max_scroll_kb));
- }
- }
- }
-
- // ESC = return to idle (27 petals logo)
- if (rl.IsKeyPressed(rl.KEY_ESCAPE)) {
- if (g_wave_mode != .idle) {
- if (g_wave_mode == .depin) g_depin_auto_started = false;
- g_wave_mode_prev = g_wave_mode;
- g_wave_mode = .idle;
- g_wave_transition = 0;
- frame_effects.sink(screen_w / 2, screen_h / 2);
- }
- frame_panels.unfocusAll();
- // Close all sacred world panels
- for (0..frame_panels.count) |pi| {
- if (frame_panels.panels[pi].panel_type == .sacred_world) {
- frame_panels.panels[pi].close();
- }
- }
- }
-
- // Click outside any panel = close all panels (return to logo menu)
- if (rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT) and !shift_held and !ctrl_held and !cmd_held) {
- var clicked_on_panel = false;
- for (0..frame_panels.count) |pi| {
- const p = &frame_panels.panels[pi];
- if (p.state == .open or p.state == .opening) {
- if (mx >= p.x and mx <= p.x + p.width and my >= p.y and my <= p.y + p.height) {
- clicked_on_panel = true;
- break;
- }
- }
- }
- // Also check if click is on the logo (don't close if clicking logo)
- const on_logo = frame_logo_anim.hovered_block >= 0;
- if (!clicked_on_panel and !on_logo) {
- // Close all panels β return to main logo menu
- for (0..frame_panels.count) |pi| {
- frame_panels.panels[pi].close();
- frame_panels.panels[pi].is_focused = false;
- }
- frame_panels.unfocusAll();
- }
- }
-
- // === CHAT INPUT (v1.9: wave mode or legacy panel) ===
- // Routes keyboard to chat when g_wave_mode == .chat or legacy panel
- const wave_chat_active = g_wave_mode == .chat;
- const focused_chat_panel: ?*GlassPanel = if (wave_chat_active) null else blk: {
- if (frame_panels.active_panel) |idx| {
- const p = &frame_panels.panels[idx];
- const is_visible = (p.state == .open or p.state == .opening);
- if (is_visible and p.panel_type == .chat) {
- break :blk p;
- }
- if (is_visible and p.panel_type == .sacred_world and p.world_id == 0) {
- break :blk p;
- }
- }
- break :blk null;
- };
-
- if (wave_chat_active or focused_chat_panel != null) {
- if (focused_chat_panel) |chat_panel| {
- _ = chat_panel;
- } // legacy compat
- // All panel-switching hotkeys are disabled when chat is open (see chat_is_open above)
- {
- // Text input: Unicode codepoints β UTF-8 encoded into global buffer
- // Skip character input when Ctrl/Cmd is held (prevents Ctrl+O etc from interfering)
- const skip_char_input = (rl.IsKeyDown(rl.KEY_LEFT_CONTROL) or rl.IsKeyDown(rl.KEY_RIGHT_CONTROL) or
- rl.IsKeyDown(rl.KEY_LEFT_SUPER) or rl.IsKeyDown(rl.KEY_RIGHT_SUPER));
- var char_key = rl.GetCharPressed();
- while (char_key > 0) {
- const cp: u21 = @intCast(char_key);
- if (cp >= 32 and !skip_char_input) {
- // Encode UTF-8
- var utf8_buf: [4]u8 = undefined;
- const utf8_len: usize = if (cp < 0x80) blk_u: {
- utf8_buf[0] = @intCast(cp);
- break :blk_u 1;
- } else if (cp < 0x800) blk_u: {
- utf8_buf[0] = @intCast(0xC0 | (cp >> 6));
- utf8_buf[1] = @intCast(0x80 | (cp & 0x3F));
- break :blk_u 2;
- } else if (cp < 0x10000) blk_u: {
- utf8_buf[0] = @intCast(0xE0 | (cp >> 12));
- utf8_buf[1] = @intCast(0x80 | ((cp >> 6) & 0x3F));
- utf8_buf[2] = @intCast(0x80 | (cp & 0x3F));
- break :blk_u 3;
- } else blk_u: {
- utf8_buf[0] = @intCast(0xF0 | (cp >> 18));
- utf8_buf[1] = @intCast(0x80 | ((cp >> 12) & 0x3F));
- utf8_buf[2] = @intCast(0x80 | ((cp >> 6) & 0x3F));
- utf8_buf[3] = @intCast(0x80 | (cp & 0x3F));
- break :blk_u 4;
- };
- if (g_chat_input_len + utf8_len < 250) {
- @memcpy(g_chat_input[g_chat_input_len..][0..utf8_len], utf8_buf[0..utf8_len]);
- g_chat_input_len += utf8_len;
- // Typing wave effect
- frame_effects.sink(screen_w / 2, screen_h * 0.9);
- }
- }
- char_key = rl.GetCharPressed();
- }
- }
-
- // Backspace β delete UTF-8 characters (with key repeat for hold)
- {
- const bs_pressed = rl.IsKeyPressed(rl.KEY_BACKSPACE);
- const bs_held = rl.IsKeyDown(rl.KEY_BACKSPACE);
- if (bs_pressed) {
- g_backspace_timer = 0.4; // Initial delay before repeat
- }
- var do_delete = bs_pressed;
- if (bs_held and !bs_pressed) {
- g_backspace_timer -= rl.GetFrameTime();
- if (g_backspace_timer <= 0) {
- do_delete = true;
- g_backspace_timer = 0.04; // Repeat rate (25 chars/sec)
- }
- }
- if (!bs_held) g_backspace_timer = 0;
- if (do_delete and g_chat_input_len > 0) {
- var del: usize = 1;
- while (del < g_chat_input_len and
- (g_chat_input[g_chat_input_len - del] & 0xC0) == 0x80)
- {
- del += 1;
- }
- g_chat_input_len -= del;
- }
- }
-
- // Ctrl+O clears the input
- if ((rl.IsKeyDown(rl.KEY_LEFT_CONTROL) or rl.IsKeyDown(rl.KEY_RIGHT_CONTROL)) and rl.IsKeyPressed(rl.KEY_O)) {
- g_chat_input_len = 0;
- }
-
- // Enter sends message
- if (rl.IsKeyPressed(rl.KEY_ENTER) and g_chat_input_len > 0) {
- // Lazy init IglaHybridChat (v2.4: 4-level cache with self-reflection)
- if (!g_hybrid_inited) {
- const alloc = if (is_emscripten) std.heap.page_allocator else g_hybrid_gpa.allocator();
-
- // Create TVC corpus on heap
- g_hybrid_corpus = alloc.create(tvc.TVCCorpus) catch null;
- if (g_hybrid_corpus) |c| {
- c.initInPlace();
- }
-
- // Create hybrid chat with env API keys
- var hconfig = igla_hybrid_chat.HybridConfig{};
- if (!is_emscripten) {
- hconfig.groq_api_key = std.posix.getenv("GROQ_API_KEY");
- hconfig.claude_api_key = std.posix.getenv("ANTHROPIC_API_KEY");
- hconfig.openai_api_key = std.posix.getenv("OPENAI_API_KEY");
- }
- hconfig.enable_context = true;
- hconfig.system_prompt = "You are Trinity, a helpful AI. Be concise.";
-
- g_hybrid_engine = igla_hybrid_chat.IglaHybridChat.initWithConfig(alloc, null, hconfig) catch null;
- if (g_hybrid_engine != null and g_hybrid_corpus != null) {
- g_hybrid_engine.?.corpus = g_hybrid_corpus;
- }
- g_hybrid_inited = true;
-
- // Also init FluentChatEngine as fallback
- if (!g_fluent_engine_inited) {
- g_fluent_engine = fluent_chat.FluentChatEngine{
- .message_store = fluent_chat.LightMessageStore.init(),
- .context = fluent_chat.ConversationContext.init(),
- .generator = undefined,
- .fluent_enabled = true,
- .total_turns = 0,
- .fluent_responses = 0,
- .high_quality_count = 0,
- };
- g_fluent_engine.generator = fluent_chat.ResponseGenerator.init(&g_fluent_engine.context);
- g_fluent_engine_inited = true;
- }
- }
-
- // 1. Add user message
- addGlobalChatMessage(g_chat_input[0..g_chat_input_len], .user);
-
- // 2. v3.0: Golden Chain β 8-node pipeline via GoldenChainAgent
- if (g_hybrid_engine != null) {
- // Init chain agent on first use (lazy)
- if (g_chain_agent == null) {
- g_chain_agent = golden_chain.GoldenChainAgent.init(&g_hybrid_engine.?);
- }
-
- if (g_chain_agent) |*agent| {
- agent.processInput(g_chat_input[0..g_chat_input_len]);
-
- // Copy all chain messages to canvas chat
- for (agent.getMessages()) |*chain_msg| {
- const canvas_type = chainMsgToCanvasType(chain_msg);
- addGlobalChatMessage(chain_msg.getContent(), canvas_type);
- }
-
- // Feed live log with final chain state
- {
- const cs = golden_chain.g_chain_state;
- var ll_buf: [96]u8 = undefined;
- const ll_text = std.fmt.bufPrint(&ll_buf, "CHAIN|{d:.0}%|{d}us", .{ cs.total_confidence * 100, cs.total_latency_us }) catch "";
- addLiveLog(ll_text, igla_hybrid_chat.g_last_wave_state.source_hue);
-
- // Update reflection name from chain
- const rname = "GoldenChain";
- @memcpy(g_last_reflection_name[0..rname.len], rname);
- g_last_reflection_name[rname.len] = 0;
- g_last_reflection_len = rname.len;
- }
-
- frame_effects.nova(screen_w / 2, screen_h / 2);
- } else {
- // Fallback: direct hybrid (shouldn't reach here)
- if (g_hybrid_engine.?.respond(g_chat_input[0..g_chat_input_len])) |hr| {
- addGlobalChatMessage(hr.response, .ai);
- } else |_| {
- addGlobalChatMessage("Error: no response", .agent_error);
- }
- frame_effects.nova(screen_w / 2, screen_h / 2);
- }
- } else {
- // No hybrid engine β use FluentChatEngine
- const result = g_fluent_engine.respond(g_chat_input[0..g_chat_input_len]);
- addGlobalChatMessage(result.getText(), .ai);
- const stats = g_fluent_engine.getStats();
- const ms = @divFloor(result.execution_time_ns, @as(i64, 1_000_000));
- addChatLogMessage("{s} | {s} | {s} | q:{d:.0}% | {d}ms | s:{d:.2} | e:{d:.2}", .{
- result.intent.getName(),
- result.topic.getName(),
- result.language.getName(),
- result.quality * 100,
- ms,
- stats.sentiment,
- stats.engagement,
- });
- frame_effects.nova(screen_w / 2, screen_h / 2);
- }
-
- // Auto-scroll: set to a large value, renderer will clamp
- g_chat_scroll_target = 99999.0;
-
- // Clear input
- g_chat_input_len = 0;
- }
- } else {
- // Normal controls (no global input - use Shift+N for panels)
-
- // T = Tool spawn (demo)
- if (rl.IsKeyPressed(rl.KEY_T)) {
- const center_x = @as(f32, @floatFromInt(g_width)) / 2.0;
- const center_y = @as(f32, @floatFromInt(g_height)) / 2.0;
- frame_tools.spawn(center_x, center_y, "inference");
- frame_tools.setStatus("inference", .running);
- frame_mode = .tools;
- }
-
- // V = Vision (inject image perturbation - demo)
- if (rl.IsKeyPressed(rl.KEY_V)) {
- // Simulate image loading as grid perturbation
- for (0..frame_grid.height) |y| {
- for (0..frame_grid.width) |x| {
- const px = @as(f32, @floatFromInt(x)) / @as(f32, @floatFromInt(frame_grid.width));
- const py = @as(f32, @floatFromInt(y)) / @as(f32, @floatFromInt(frame_grid.height));
- const pattern = @sin(px * TAU * 4.0) * @cos(py * TAU * 4.0);
- frame_grid.getMut(x, y).amplitude += pattern * 0.3;
- }
- }
- frame_clusters.spawn(mx, my, "VISION INPUT", false);
- frame_mode = .vision;
- }
-
- // A = Voice/Audio mode (frequency modulation)
- if (rl.IsKeyPressed(rl.KEY_A)) {
- // Simulate voice as frequency modulation
- const freq_mod = @sin(frame_time * 10.0) * 0.5;
- for (frame_grid.photons[0..frame_grid.width]) |*p| {
- p.frequency += freq_mod;
- }
- frame_clusters.spawn(mx, my, "VOICE INPUT", false);
- frame_mode = .voice;
- }
-
- // N = Nova effect (success)
- if (rl.IsKeyPressed(rl.KEY_N)) {
- frame_effects.nova(mx, my);
- }
-
- // S = Sink effect (failure)
- if (rl.IsKeyPressed(rl.KEY_S)) {
- frame_effects.sink(mx, my);
- }
-
- // R = Reset
- if (rl.IsKeyPressed(rl.KEY_R)) {
- for (frame_grid.photons) |*p| {
- p.amplitude = 0;
- p.interference = 0;
- }
- const center_x = @as(f32, @floatFromInt(g_width)) / 2.0;
- const center_y = @as(f32, @floatFromInt(g_height)) / 2.0;
- frame_clusters.spawn(center_x, center_y, "REBIRTH", false);
- frame_mode = .idle;
- }
-
- // Mouse interactions
- if (rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT)) {
- if (gx < frame_grid.width and gy < frame_grid.height) {
- frame_grid.setCursor(@floatFromInt(gx), @floatFromInt(gy), 1.0);
- }
- }
-
- if (rl.IsMouseButtonDown(rl.MOUSE_BUTTON_RIGHT)) {
- if (gx < frame_grid.width and gy < frame_grid.height) {
- frame_grid.getMut(gx, gy).amplitude = -1.0;
- }
- }
- }
-
- // === UPDATE ===
- frame_grid.stepSIMD();
- frame_clusters.update(dt);
- frame_spirals.update(dt);
- frame_tools.update(dt);
- frame_effects.update(dt);
- frame_goal.update(&frame_grid, dt);
-
- // Update panels with mouse state
- const mouse_pressed = rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT);
- const mouse_down_state = rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT);
- const mouse_released = rl.IsMouseButtonReleased(rl.MOUSE_BUTTON_LEFT);
- const mouse_wheel = rl.GetMouseWheelMove();
- frame_panels.update(dt, frame_time, mx, my, mouse_pressed, mouse_down_state, mouse_released, mouse_wheel);
-
- // Check autonomous goal completion
- if (frame_goal.progress >= 1.0 and frame_mode == .autonomous) {
- frame_effects.nova(frame_goal.x, frame_goal.y);
- frame_clusters.spawn(frame_goal.x, frame_goal.y, "GOAL ACHIEVED", false);
- frame_mode = .idle;
- }
-
- // === RENDER ===
- // (BeginDrawing/EndDrawing moved to top of updateDrawFrame)
-
- // Theme-aware background (second clear overrides debug text above β keep for now)
- // rl.ClearBackground(@as(rl.Color, @bitCast(theme.clear_bg)));
-
- // === LOGO LOADING ANIMATION (Apple-style luxury welcome) ===
- if (!frame_loading_complete) {
- // Update logo animation
- frame_logo_anim.logo_scale = @min(@as(f32, @floatFromInt(g_width)) / LogoAnimation.SVG_WIDTH, @as(f32, @floatFromInt(g_height)) / LogoAnimation.SVG_HEIGHT) * 0.35;
- frame_logo_anim.logo_offset = .{ .x = @as(f32, @floatFromInt(g_width)) / 2, .y = @as(f32, @floatFromInt(g_height)) / 2 };
- frame_logo_anim.update(dt);
-
- // Draw logo animation
- frame_logo_anim.draw();
-
- // Check if animation complete
- if (frame_logo_anim.is_complete) {
- frame_loading_complete = true;
- }
-
- return; // Skip main canvas rendering during loading
- }
-
- // Grid & visual systems (skip in DePIN/Ralph mode for clean background)
- if (g_wave_mode != .depin and g_wave_mode != .ralph) {
- drawImmersiveGrid(&frame_grid, frame_time);
- frame_clusters.draw(frame_time);
- frame_spirals.draw();
- frame_tools.draw(frame_time);
- frame_effects.draw();
- frame_goal.draw(frame_time);
- }
-
- // === v2.4: DePIN Node Polling ===
- if (g_wave_mode == .depin or g_depin_running) {
- // Auto-start on first entry to DePIN mode
- if (g_wave_mode == .depin and g_depin_docker_ok and !g_depin_running and !g_depin_auto_started) {
- g_depin_auto_started = true;
- depinStartNode();
- g_depin_poll_timer = 8.0; // Poll soon after start
- }
- // ββ v2.4: DePIN polling ββ
- g_depin_poll_timer += dt;
- if (g_depin_poll_timer > 5.0) {
- g_depin_poll_timer = 0;
- // In real WASM, we'd use emscripten_run_script to call fetch
- // For now, we simulate or use exported functions
- }
-
- g_depin_poll_timer += dt;
- if (g_depin_poll_timer >= 10.0) {
- g_depin_poll_timer = 0;
- g_depin_running = depinCheckRunning();
- if (g_depin_running) depinPollStats();
- }
- }
-
- // ββ v3.0: Multi-Agent Ralph Monitor Polling (RALPH-CANVAS-005) ββ
- // NOTE: This MUST be outside the DePIN block so it runs in .ralph and .mirror modes
- if (g_wave_mode == .mirror or g_wave_mode == .ralph) {
- if (!g_ralph_initialized) initRalphAgents();
-
- var ai: usize = 0;
- while (ai < g_ralph_agent_count) : (ai += 1) {
- g_ralph_agents[ai].update_timer += dt;
- if (g_ralph_agents[ai].update_timer > 2.0) {
- g_ralph_agents[ai].update_timer = 0;
- if (is_emscripten) {
- // WASM: use emscripten fetch (kept for completeness, not active on desktop)
- } else {
- // Desktop: Read .ralph/ files directly from disk
- pollRalphAgentDesktop(ai);
- buildUnifiedChat(ai);
- }
- }
- }
- }
-
- // === v1.9: Wave Mode Transition ===
- g_wave_transition = @min(1.0, g_wave_transition + dt * 3.0); // 0.33s transition
-
- // === IDLE MODE: Logo + Formula Particles ===
- if (g_wave_mode == .idle) {
- // Static logo in center (realm-colored, stays after loading)
- frame_logo_anim.logo_scale = @min(@as(f32, @floatFromInt(g_width)) / LogoAnimation.SVG_WIDTH, @as(f32, @floatFromInt(g_height)) / LogoAnimation.SVG_HEIGHT) * 0.35;
- frame_logo_anim.logo_offset = .{ .x = @as(f32, @floatFromInt(g_width)) / 2, .y = @as(f32, @floatFromInt(g_height)) / 2 };
- frame_logo_anim.applyMouse(mx, my, dt, mouse_pressed);
- frame_logo_anim.draw();
-
- // Sacred formula particles β Fibonacci spiral orbit
- {
- const fcx = @as(f32, @floatFromInt(g_width)) / 2;
- const fcy = @as(f32, @floatFromInt(g_height)) / 2;
- const formula_click = rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT);
- for (&frame_formula_particles) |*fp| {
- fp.update(dt, frame_time, mx, my, formula_click, fcx, fcy);
- fp.draw(frame_time, fcx, fcy, frame_font_small);
- }
- }
-
- // Handle logo block click β switch to wave mode
- if (frame_logo_anim.clicked_block >= 0) {
- const block_idx = @as(usize, @intCast(frame_logo_anim.clicked_block));
- // Block 0 = Chat, Block 2 = Ralph, Block 16 = DePIN, Block 18 = Docs, others = tools
- const new_wm: WaveMode = if (block_idx == 0) .chat else if (block_idx == 2) .ralph else if (block_idx == 16) .depin else if (block_idx == 18) .docs else .tools;
- g_wave_mode_prev = g_wave_mode;
- g_wave_mode = new_wm;
- g_wave_transition = 0;
- frame_effects.nova(screen_w / 2, screen_h / 2);
- }
-
- // Hover tooltip: show world name + realm color
- if (frame_logo_anim.hovered_block >= 0) {
- const hi = @as(usize, @intCast(frame_logo_anim.hovered_block));
- const world = sacred_worlds.getWorldByBlock(hi);
- const tw: f32 = @as(f32, @floatFromInt(world.name_len)) * 9.0 + 30;
- const tx = mx + 15;
- const ty = my - 28;
- const tt_bg: rl.Color = @bitCast(theme.tooltip_bg);
- const tt_text: rl.Color = @bitCast(theme.tooltip_text);
- rl.DrawRectangleRounded(.{ .x = tx, .y = ty, .width = tw, .height = 24 }, 0.3, 8, tt_bg);
- rl.DrawCircle(@intFromFloat(tx + 10), @intFromFloat(ty + 12), 4, tt_text);
- var tooltip_buf: [28:0]u8 = undefined;
- @memcpy(tooltip_buf[0..world.name_len], world.name[0..world.name_len]);
- tooltip_buf[world.name_len] = 0;
- rl.DrawTextEx(frame_font_small, &tooltip_buf, .{ .x = tx + 20, .y = ty + 5 }, 13, 0.5, tt_text);
- }
- }
-
- // === WAVE MODE RENDERERS (fullscreen, no panels) ===
- if (g_wave_mode != .idle) {
- const fs = g_font_scale;
- const chat_font = g_font_chat;
- const sw = @as(f32, @floatFromInt(g_width));
- const sh = @as(f32, @floatFromInt(g_height));
- const alpha_u8: u8 = @intFromFloat(@min(255, g_wave_transition * 255));
- const mode_hue = g_wave_mode.getHue();
- const mode_rgb = hsvToRgb(mode_hue, 0.7, 1.0);
- const mode_color = rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = alpha_u8 };
-
- // DePIN/Ralph mode: skip all other wave renderers, draw dedicated panel
- if (g_wave_mode != .depin and g_wave_mode != .ralph) {
-
- // Mode label (top-center)
- const label = g_wave_mode.getLabel();
- const label_w = rl.MeasureTextEx(chat_font, label, 18 * fs, 1.0).x;
- rl.DrawTextEx(chat_font, label, .{ .x = (sw - label_w) / 2, .y = 12 }, 18 * fs, 1.0, mode_color);
-
- // Subtle wave border ring β v2.1: modulated by g_last_wave_state
- const ring_r = @min(sw, sh) * 0.48;
- const ring_cx = sw / 2;
- const ring_cy = sh / 2;
- const ring_alpha: u8 = @intFromFloat(@max(0, @min(60, @as(f32, @floatFromInt(alpha_u8)) * 0.25)));
-
- // v2.1: Read wave state from hybrid chat engine
- const ws = igla_hybrid_chat.g_last_wave_state;
- const ws_hue = if (ws.source_hue > 0.01) ws.source_hue else mode_hue;
- const ws_rgb = hsvToRgb(ws_hue, 0.7, @max(0.5, ws.provider_health_avg));
- const ws_pulse = ws.confidence * 0.5 + ws.similarity * 0.5;
- const ring_color = if (ws.source_hue > 0.01)
- rl.Color{ .r = ws_rgb[0], .g = ws_rgb[1], .b = ws_rgb[2], .a = ring_alpha }
- else
- rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = ring_alpha };
-
- rl.DrawCircleLines(@intFromFloat(ring_cx), @intFromFloat(ring_cy), ring_r + @sin(frame_time * 2.0) * (3 + ws_pulse * 5), ring_color);
-
- // v2.1: Memory load indicator β inner ring thickness
- if (ws.memory_load > 0.01) {
- const mem_r = ring_r * (0.9 + ws.memory_load * 0.08);
- const mem_alpha: u8 = @intFromFloat(@max(0, @min(40, ws.memory_load * 60)));
- rl.DrawCircleLines(@intFromFloat(ring_cx), @intFromFloat(ring_cy), mem_r, rl.Color{ .r = 100, .g = 200, .b = 100, .a = mem_alpha });
- }
-
- // v2.1: Learning glow β green pulse when saving to TVC
- if (ws.is_learning) {
- const learn_alpha: u8 = @intFromFloat(@max(0, @min(80, @sin(frame_time * 6.0) * 40 + 40)));
- rl.DrawCircleLines(@intFromFloat(ring_cx), @intFromFloat(ring_cy), ring_r * 0.95 + @sin(frame_time * 4.0) * 2, rl.Color{ .r = 0, .g = 255, .b = 100, .a = learn_alpha });
- }
-
- // === CHAT WAVE FIELD ===
- if (g_wave_mode == .chat) {
- // Fullscreen chat β same logic as sacred_world chat panel but without GlassPanel frame
- const chat_dt = rl.GetFrameTime();
- g_chat_scroll_y += (g_chat_scroll_target - g_chat_scroll_y) * @min(1.0, 8.0 * chat_dt);
-
- const chat_margin: f32 = 70 * fs;
- const chat_top: f32 = 40 * fs;
- const input_h: f32 = 48 * fs;
- const chat_bottom: f32 = sh - input_h - 40 * fs;
- const msg_area_h = chat_bottom - chat_top;
- const line_h: f32 = 22 * fs;
- const msg_font_size: f32 = 17 * fs;
- const bubble_pad: f32 = 14 * fs;
- const max_text_w = sw - chat_margin * 2 - bubble_pad * 2;
- const chat_text_color = withAlpha(CHAT_TEXT, alpha_u8);
-
- // Scissor clip for messages
- rl.BeginScissorMode(0, @intFromFloat(chat_top), @intFromFloat(sw), @intFromFloat(@max(1, msg_area_h)));
-
- g_chat_scroll_target = @max(0, g_chat_scroll_target);
-
- if (g_chat_msg_count == 0) {
- const welcome_y = chat_top + msg_area_h * 0.3;
- rl.DrawTextEx(chat_font, "Trinity AI", .{ .x = chat_margin, .y = welcome_y }, 18 * fs, 0.5, withAlpha(HYPER_GREEN, alpha_u8));
- rl.DrawTextEx(chat_font, "Type a message below to start chatting.", .{ .x = chat_margin, .y = welcome_y + 24 * fs }, 14 * fs, 0.5, withAlpha(MUTED_GRAY, alpha_u8));
- g_chat_scroll_target = 0;
- g_chat_scroll_y = 0;
- } else {
- var render_y: f32 = chat_top + 6 * fs - g_chat_scroll_y;
- var mi: usize = 0;
- while (mi < g_chat_msg_count) : (mi += 1) {
- const msg_type = g_chat_msg_types[mi];
- const msg_len = g_chat_msg_lens[mi];
- const msg_data = g_chat_messages[mi][0..msg_len];
-
- // Log messages
- if (msg_type == .log) {
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- var log_z: [512:0]u8 = undefined;
- const log_copy = @min(msg_len, 511);
- @memcpy(log_z[0..log_copy], msg_data[0..log_copy]);
- log_z[log_copy] = 0;
- const log_color = rl.Color{ .r = 120, .g = 120, .b = 140, .a = 180 };
- rl.DrawTextEx(chat_font, &log_z, .{ .x = chat_margin, .y = render_y }, 13 * fs, 0.3, log_color);
- }
- render_y += 18 * fs;
- continue;
- }
-
- // v3.0: Golden Chain messages β colored indicator + label + text
- if (isChainType(msg_type)) {
- if (render_y >= chat_top - line_h * 2 and render_y <= chat_bottom + line_h) {
- // Draw pulsing Chakra indicator circle
- drawChainIndicator(chat_margin - 14 * fs, render_y + 8 * fs, msg_type, frame_time, fs);
-
- // Draw chain label
- const chain_label = getChainMsgLabel(msg_type);
- const chain_color = getChainMsgColor(msg_type, alpha_u8);
- rl.DrawTextEx(chat_font, chain_label, .{ .x = chat_margin, .y = render_y }, 12 * fs, 0.3, chain_color);
-
- // Draw message content below label
- if (msg_len > 0) {
- var chain_z: [512:0]u8 = undefined;
- const chain_copy = @min(msg_len, 511);
- @memcpy(chain_z[0..chain_copy], msg_data[0..chain_copy]);
- chain_z[chain_copy] = 0;
- const chain_text_col = rl.Color{ .r = chain_color.r, .g = chain_color.g, .b = chain_color.b, .a = @min(alpha_u8, 200) };
- rl.DrawTextEx(chat_font, &chain_z, .{ .x = chat_margin + 8 * fs, .y = render_y + 15 * fs }, 14 * fs, 0.3, chain_text_col);
- }
- }
- render_y += 34 * fs; // label line + content line + spacing
- continue;
- }
-
- const is_user = msg_type == .user;
-
- // Label
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- const label_color = if (is_user) withAlpha(CHAT_LABEL_USER, alpha_u8) else withAlpha(CHAT_LABEL_AI, alpha_u8);
- if (is_user) {
- const you_w = rl.MeasureTextEx(chat_font, "You", 16 * fs, 0.5).x;
- rl.DrawTextEx(chat_font, "You", .{ .x = sw - chat_margin - you_w, .y = render_y }, 16 * fs, 0.5, label_color);
- } else {
- rl.DrawTextEx(chat_font, "Trinity", .{ .x = chat_margin, .y = render_y }, 16 * fs, 0.5, label_color);
- }
- }
- render_y += 18 * fs;
-
- // Measure text
- var full_z: [512:0]u8 = undefined;
- const full_copy = @min(msg_len, 511);
- @memcpy(full_z[0..full_copy], msg_data[0..full_copy]);
- full_z[full_copy] = 0;
- const text_size = rl.MeasureTextEx(chat_font, &full_z, msg_font_size, 0.5);
- const needs_wrap = text_size.x > max_text_w;
-
- if (!needs_wrap) {
- if (is_user) {
- const text_x = sw - chat_margin - text_size.x;
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- rl.DrawTextEx(chat_font, &full_z, .{ .x = text_x, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- rl.DrawTextEx(chat_font, &full_z, .{ .x = text_x + 0.6, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- }
- render_y += line_h + 8 * fs;
- } else {
- if (render_y >= chat_top - line_h and render_y <= chat_bottom + line_h) {
- rl.DrawTextEx(chat_font, &full_z, .{ .x = chat_margin, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- rl.DrawTextEx(chat_font, &full_z, .{ .x = chat_margin + 0.6, .y = render_y }, msg_font_size, 0.5, chat_text_color);
- }
- render_y += line_h + 8 * fs;
- }
- } else {
- // Multi-line word wrap
- var n_lines: f32 = 0;
- {
- var pos: usize = 0;
- while (pos < msg_data.len) {
- var end = pos;
- var last_space: usize = pos;
- while (end < msg_data.len) {
- var next = end + 1;
- while (next < msg_data.len and (msg_data[next] & 0xC0) == 0x80) next += 1;
- var tmp: [256:0]u8 = undefined;
- const seg_len = @min(next - pos, 255);
- @memcpy(tmp[0..seg_len], msg_data[pos .. pos + seg_len]);
- tmp[seg_len] = 0;
- const w = rl.MeasureTextEx(chat_font, &tmp, msg_font_size, 0.5).x;
- if (w > max_text_w and end > pos) break;
- if (msg_data[end] == ' ') last_space = end;
- end = next;
- }
- if (end < msg_data.len and last_space > pos) end = last_space + 1 else if (end == pos) end = pos + 1;
- n_lines += 1;
- pos = end;
- while (pos < msg_data.len and msg_data[pos] == ' ') pos += 1;
- }
- if (n_lines == 0) n_lines = 1;
- }
-
- const bubble_h = n_lines * line_h;
- const bubble_x = chat_margin;
-
- var text_y = render_y;
- var pos2: usize = 0;
- var line_buf_chat: [256:0]u8 = undefined;
- while (pos2 < msg_data.len) {
- var end2 = pos2;
- var last_sp2: usize = pos2;
- while (end2 < msg_data.len) {
- var next2 = end2 + 1;
- while (next2 < msg_data.len and (msg_data[next2] & 0xC0) == 0x80) next2 += 1;
- var tmp2: [256:0]u8 = undefined;
- const seg_len2 = @min(next2 - pos2, 255);
- @memcpy(tmp2[0..seg_len2], msg_data[pos2 .. pos2 + seg_len2]);
- tmp2[seg_len2] = 0;
- const w2 = rl.MeasureTextEx(chat_font, &tmp2, msg_font_size, 0.5).x;
- if (w2 > max_text_w and end2 > pos2) break;
- if (msg_data[end2] == ' ') last_sp2 = end2;
- end2 = next2;
- }
- if (end2 < msg_data.len and last_sp2 > pos2) end2 = last_sp2 + 1 else if (end2 == pos2) end2 = pos2 + 1;
-
- if (text_y >= chat_top - line_h and text_y <= chat_bottom + line_h) {
- const ln_len = @min(end2 - pos2, 255);
- @memcpy(line_buf_chat[0..ln_len], msg_data[pos2 .. pos2 + ln_len]);
- var tlen = ln_len;
- while (tlen > 0 and line_buf_chat[tlen - 1] == ' ') tlen -= 1;
- line_buf_chat[tlen] = 0;
- rl.DrawTextEx(chat_font, &line_buf_chat, .{ .x = bubble_x + bubble_pad, .y = text_y }, msg_font_size, 0.5, chat_text_color);
- rl.DrawTextEx(chat_font, &line_buf_chat, .{ .x = bubble_x + bubble_pad + 0.6, .y = text_y }, msg_font_size, 0.5, chat_text_color);
- }
-
- text_y += line_h;
- pos2 = end2;
- while (pos2 < msg_data.len and msg_data[pos2] == ' ') pos2 += 1;
- }
-
- render_y += bubble_h + 8 * fs;
- }
- }
-
- // Scroll clamping
- const total_content_h = render_y + g_chat_scroll_y - (chat_top + 6 * fs);
- const max_scroll = @max(0, total_content_h - msg_area_h + 20 * fs);
- g_chat_scroll_target = @min(g_chat_scroll_target, max_scroll);
- g_chat_scroll_y = @min(g_chat_scroll_y, max_scroll + 10 * fs);
- }
-
- rl.EndScissorMode();
-
- // Mouse wheel scroll
- {
- const cmy = @as(f32, @floatFromInt(rl.GetMouseY()));
- if (cmy >= chat_top and cmy <= chat_bottom) {
- g_chat_scroll_target -= rl.GetMouseWheelMove() * 40.0 * fs;
- g_chat_scroll_target = @max(0, g_chat_scroll_target);
- }
- }
-
- // Input area (bottom)
- const input_y = chat_bottom + 4 * fs;
- const sep_color = rl.Color{ .r = 100, .g = 100, .b = 110, .a = 120 };
-
- rl.DrawRectangle(
- @intFromFloat(chat_margin),
- @intFromFloat(input_y),
- @intFromFloat(sw - chat_margin * 2),
- @intFromFloat(input_h),
- CHAT_INPUT_BG,
- );
- rl.DrawLineEx(.{ .x = chat_margin, .y = input_y }, .{ .x = sw - chat_margin, .y = input_y }, 1.0, sep_color);
- rl.DrawLineEx(.{ .x = chat_margin, .y = input_y + input_h }, .{ .x = sw - chat_margin, .y = input_y + input_h }, 1.0, sep_color);
-
- const prompt_y = input_y + 14 * fs;
- const prompt_sz: f32 = 17 * fs;
- const prompt_color = rl.Color{ .r = 150, .g = 150, .b = 160, .a = 220 };
- rl.DrawTextEx(chat_font, ">", .{ .x = chat_margin + 6 * fs, .y = prompt_y }, prompt_sz, 0.5, prompt_color);
-
- // "enter to send" hint
- const send_sz: f32 = 13 * fs;
- const send_color = rl.Color{ .r = 140, .g = 140, .b = 150, .a = 180 };
- const send_w = rl.MeasureTextEx(chat_font, "enter to send", send_sz, 0.5).x;
- rl.DrawTextEx(chat_font, "enter to send", .{ .x = sw - chat_margin - send_w - 10 * fs, .y = input_y + 16 * fs }, send_sz, 0.5, send_color);
-
- if (g_chat_input_len > 0) {
- var input_disp: [260:0]u8 = undefined;
- const show_input = @min(g_chat_input_len, 255);
- @memcpy(input_disp[0..show_input], g_chat_input[0..show_input]);
- input_disp[show_input] = 0;
- const ix = chat_margin + 22 * fs;
- const iy = input_y + 14 * fs;
- const isz: f32 = 17 * fs;
- rl.DrawTextEx(chat_font, &input_disp, .{ .x = ix, .y = iy }, isz, 0.5, CHAT_INPUT_TEXT);
- rl.DrawTextEx(chat_font, &input_disp, .{ .x = ix + 0.5, .y = iy }, isz, 0.5, CHAT_INPUT_TEXT);
- // Blinking cursor
- if (@mod(@as(u32, @intFromFloat(frame_time * 3)), 2) == 0) {
- const text_w = rl.MeasureTextEx(chat_font, &input_disp, isz, 0.5).x;
- rl.DrawRectangle(@intFromFloat(ix + text_w + 2 * fs), @intFromFloat(iy), @intFromFloat(2 * fs), @intFromFloat(isz), CHAT_INPUT_TEXT);
- }
- } else {
- // Empty: blinking cursor
- const ph_x = chat_margin + 22 * fs;
- const ph_y = input_y + 14 * fs;
- const ph_sz: f32 = 17 * fs;
- if (@mod(@as(u32, @intFromFloat(frame_time * 2)), 2) == 0) {
- rl.DrawRectangle(@intFromFloat(ph_x), @intFromFloat(ph_y), @intFromFloat(2 * fs), @intFromFloat(ph_sz), CHAT_INPUT_TEXT);
- }
- }
-
- // Status bar
- {
- const wstatus_y = input_y + input_h + 3 * fs;
- const status_sz: f32 = 11 * fs;
- const status_color = rl.Color{ .r = 100, .g = 100, .b = 115, .a = 160 };
- const fps_val = rl.GetFPS();
- var wstatus_buf: [256:0]u8 = undefined;
- if (g_fluent_engine_inited) {
- const st = g_fluent_engine.getStats();
- const sl = std.fmt.bufPrint(wstatus_buf[0..255], "{d}fps | fluent {d:.0}% | {s} | {s} | s:{d:.1}", .{
- fps_val, st.fluent_rate * 100, st.current_language.getName(), st.current_topic.getName(), st.sentiment,
- }) catch "...";
- wstatus_buf[sl.len] = 0;
- } else {
- const sl = std.fmt.bufPrint(wstatus_buf[0..255], "{d}fps | trinity v1.9 | ready", .{fps_val}) catch "...";
- wstatus_buf[sl.len] = 0;
- }
- rl.DrawTextEx(chat_font, &wstatus_buf, .{ .x = chat_margin + 4 * fs, .y = wstatus_y }, status_sz, 0.3, status_color);
- var count_buf: [64:0]u8 = undefined;
- const ct = std.fmt.bufPrint(count_buf[0..63], "{d} msgs", .{g_chat_msg_count}) catch "0";
- count_buf[ct.len] = 0;
- const count_w = rl.MeasureTextEx(chat_font, &count_buf, status_sz, 0.3).x;
- rl.DrawTextEx(chat_font, &count_buf, .{ .x = sw - chat_margin - count_w - 4 * fs, .y = wstatus_y }, status_sz, 0.3, status_color);
- }
- }
-
- // === CODE WAVE FIELD === (system info as scrolling code lines)
- if (g_wave_mode == .code) {
- const margin: f32 = 60 * fs;
- const line_h: f32 = 22 * fs;
- const code_font_sz: f32 = 16 * fs;
- const code_dim = withAlpha(rl.Color{ .r = 100, .g = 200, .b = 255, .a = 255 }, alpha_u8);
- const code_green = withAlpha(rl.Color{ .r = 80, .g = 255, .b = 120, .a = 255 }, alpha_u8);
- const code_gray = withAlpha(MUTED_GRAY, alpha_u8);
-
- // v2.0: LIVE system data formatted as Zig code
- const cws = igla_hybrid_chat.g_last_wave_state;
- const fps_val = rl.GetFPS();
- const ts = std.time.timestamp();
-
- var buf0: [64:0]u8 = undefined;
- var buf1: [64:0]u8 = undefined;
- var buf2: [64:0]u8 = undefined;
- var buf3: [64:0]u8 = undefined;
- var buf4: [64:0]u8 = undefined;
- var buf5: [64:0]u8 = undefined;
- var buf6: [64:0]u8 = undefined;
- var buf7: [64:0]u8 = undefined;
- var buf8: [64:0]u8 = undefined;
- var buf9: [64:0]u8 = undefined;
-
- _ = std.fmt.bufPrint(&buf0, "const fps = {d};", .{fps_val}) catch {};
- buf0[@min(63, std.mem.indexOfScalar(u8, &buf0, 0) orelse 63)] = 0;
- _ = std.fmt.bufPrint(&buf1, "const uptime_s = {d};", .{ts}) catch {};
- buf1[@min(63, std.mem.indexOfScalar(u8, &buf1, 0) orelse 63)] = 0;
-
- const engine_str = if (g_hybrid_engine != null) "IglaHybridChat v2.4" else "FluentChat";
- _ = std.fmt.bufPrint(&buf2, "const engine = \"{s}\";", .{engine_str}) catch {};
- buf2[@min(63, std.mem.indexOfScalar(u8, &buf2, 0) orelse 63)] = 0;
-
- const queries = if (g_hybrid_engine != null) g_hybrid_engine.?.total_queries else 0;
- _ = std.fmt.bufPrint(&buf3, "const total_queries = {d};", .{queries}) catch {};
- buf3[@min(63, std.mem.indexOfScalar(u8, &buf3, 0) orelse 63)] = 0;
-
- const routing_name = @tagName(cws.routing);
- _ = std.fmt.bufPrint(&buf4, "const routing = .{s};", .{routing_name}) catch {};
- buf4[@min(63, std.mem.indexOfScalar(u8, &buf4, 0) orelse 63)] = 0;
-
- _ = std.fmt.bufPrint(&buf5, "const confidence = {d:.2};", .{cws.confidence}) catch {};
- buf5[@min(63, std.mem.indexOfScalar(u8, &buf5, 0) orelse 63)] = 0;
-
- _ = std.fmt.bufPrint(&buf6, "const is_learning = {s};", .{if (cws.is_learning) "true" else "false"}) catch {};
- buf6[@min(63, std.mem.indexOfScalar(u8, &buf6, 0) orelse 63)] = 0;
-
- _ = std.fmt.bufPrint(&buf7, "const memory_load = {d:.2};", .{cws.memory_load}) catch {};
- buf7[@min(63, std.mem.indexOfScalar(u8, &buf7, 0) orelse 63)] = 0;
-
- _ = std.fmt.bufPrint(&buf8, "const provider_health = {d:.2};", .{cws.provider_health_avg}) catch {};
- buf8[@min(63, std.mem.indexOfScalar(u8, &buf8, 0) orelse 63)] = 0;
-
- _ = std.fmt.bufPrint(&buf9, "const source_hue = {d:.0};", .{cws.source_hue}) catch {};
- buf9[@min(63, std.mem.indexOfScalar(u8, &buf9, 0) orelse 63)] = 0;
-
- const live_lines = [_][*:0]const u8{
- "// === TRINITY SYSTEM v2.0 (LIVE) ===",
- &buf0,
- &buf1,
- "const canvas = \"v2.0\";",
- &buf2,
- &buf3,
- "// === WAVE STATE (LIVE) ===",
- &buf4,
- &buf5,
- &buf6,
- &buf7,
- &buf8,
- &buf9,
- "const vsa_dim = 1024;",
- "const tvc_max = 10000;",
- "// phi^2 + 1/phi^2 = 3 = TRINITY",
- };
-
- var yi: usize = 0;
- while (yi < live_lines.len) : (yi += 1) {
- const y_pos = 50 * fs + @as(f32, @floatFromInt(yi)) * line_h;
- const wave_x = @sin(frame_time * 1.5 + @as(f32, @floatFromInt(yi)) * 0.4) * 3;
- const line_color = if (yi == 0 or yi == 6 or yi == 15) code_green else if (yi < 6) code_dim else code_gray;
- rl.DrawTextEx(chat_font, live_lines[yi], .{ .x = margin + wave_x, .y = y_pos }, code_font_sz, 0.5, line_color);
- // Line number
- var num_buf: [8:0]u8 = undefined;
- _ = std.fmt.bufPrint(&num_buf, "{d:>3}", .{yi + 1}) catch {};
- num_buf[3] = 0;
- rl.DrawTextEx(chat_font, &num_buf, .{ .x = margin - 40 * fs, .y = y_pos }, code_font_sz, 0.5, withAlpha(MUTED_GRAY, @as(u8, @intFromFloat(@max(0, @min(255, @as(f32, @floatFromInt(alpha_u8)) * 0.4))))));
- }
-
- // Animated wave rings behind
- for (0..3) |ri| {
- const r = 200.0 + @as(f32, @floatFromInt(ri)) * 80.0 + @sin(frame_time * 1.2 + @as(f32, @floatFromInt(ri)) * 1.0) * 15;
- const ra: u8 = @intFromFloat(@max(0, @min(30, @as(f32, @floatFromInt(alpha_u8)) * 0.12)));
- rl.DrawCircleLines(@intFromFloat(sw / 2), @intFromFloat(sh / 2), r, rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = ra });
- }
- }
-
- // === TOOLS WAVE FIELD === (tool status wheel with LIVE data)
- if (g_wave_mode == .tools) {
- const center_x = sw / 2;
- const center_y = sh / 2;
- const tool_names = [_][*:0]const u8{ "time", "date", "system", "file_read", "file_list", "zig_build", "zig_test" };
- const tool_count = tool_names.len;
- const orbit_r: f32 = @min(sw, sh) * 0.25;
-
- // v2.0: Live tool status
- const tools_enabled = if (g_hybrid_engine != null) g_hybrid_engine.?.config.enable_tools else false;
- const tws = igla_hybrid_chat.g_last_wave_state;
-
- // Title with live status
- if (tools_enabled) {
- rl.DrawTextEx(chat_font, "TOOLS: ACTIVE", .{ .x = center_x - 65, .y = 40 * fs }, 18 * fs, 0.5, mode_color);
- } else {
- rl.DrawTextEx(chat_font, "TOOLS: OFFLINE", .{ .x = center_x - 65, .y = 40 * fs }, 18 * fs, 0.5, withAlpha(MUTED_GRAY, alpha_u8));
- }
-
- // v2.0: Show last routing as subtitle
- var route_buf: [48:0]u8 = undefined;
- _ = std.fmt.bufPrint(&route_buf, "Last route: {s}", .{@tagName(tws.routing)}) catch {};
- route_buf[@min(47, std.mem.indexOfScalar(u8, &route_buf, 0) orelse 47)] = 0;
- rl.DrawTextEx(chat_font, &route_buf, .{ .x = center_x - 55, .y = 62 * fs }, 13 * fs, 0.5, withAlpha(MUTED_GRAY, alpha_u8));
-
- // Tool items in circle
- for (0..tool_count) |ti| {
- const angle = @as(f32, @floatFromInt(ti)) * (std.math.pi * 2.0 / @as(f32, @floatFromInt(tool_count))) - std.math.pi / 2.0 + frame_time * 0.1;
- const tx = center_x + @cos(angle) * orbit_r;
- const ty = center_y + @sin(angle) * orbit_r;
- const pulse = @sin(frame_time * 3.0 + @as(f32, @floatFromInt(ti)) * 1.2) * 0.3 + 0.7;
- const tool_alpha: u8 = @intFromFloat(@max(60, @min(255, pulse * @as(f32, @floatFromInt(alpha_u8)))));
-
- // Status dot: green if enabled, gray if disabled
- const dot_color = if (tools_enabled) rl.Color{ .r = 80, .g = 255, .b = 80, .a = tool_alpha } else rl.Color{ .r = 120, .g = 120, .b = 120, .a = tool_alpha };
- rl.DrawCircle(@intFromFloat(tx - 12), @intFromFloat(ty + 2), 4, dot_color);
- // Tool name
- rl.DrawTextEx(chat_font, tool_names[ti], .{ .x = tx - 4, .y = ty - 6 }, 15 * fs, 0.5, withAlpha(mode_color, tool_alpha));
-
- // Connecting line
- rl.DrawLine(@intFromFloat(center_x), @intFromFloat(center_y), @intFromFloat(tx), @intFromFloat(ty), rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = @as(u8, @intFromFloat(@max(0, @min(30, pulse * 40)))) });
- }
-
- // v2.0: Center shows total queries
- rl.DrawCircle(@intFromFloat(center_x), @intFromFloat(center_y), 18, withAlpha(mode_color, @as(u8, @intFromFloat(@max(20, @as(f32, @floatFromInt(alpha_u8)) * 0.3)))));
- var q_buf: [16:0]u8 = undefined;
- const qcount = if (g_hybrid_engine != null) g_hybrid_engine.?.total_queries else 0;
- _ = std.fmt.bufPrint(&q_buf, "{d}", .{qcount}) catch {};
- q_buf[@min(15, std.mem.indexOfScalar(u8, &q_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &q_buf, .{ .x = center_x - 8, .y = center_y - 7 }, 14 * fs, 0.5, mode_color);
- }
-
- // === SETTINGS WAVE FIELD === (LIVE config from HybridConfig)
- if (g_wave_mode == .settings) {
- const margin: f32 = 80 * fs;
- const line_h: f32 = 26 * fs;
- const key_color = withAlpha(mode_color, alpha_u8);
- const val_color = withAlpha(rl.Color{ .r = 200, .g = 200, .b = 220, .a = 255 }, alpha_u8);
- const active_color = withAlpha(rl.Color{ .r = 80, .g = 255, .b = 120, .a = 255 }, alpha_u8);
-
- rl.DrawTextEx(chat_font, "CONFIGURATION (LIVE)", .{ .x = margin, .y = 40 * fs }, 20 * fs, 0.5, key_color);
-
- const keys = [_][*:0]const u8{
- "symbolic_threshold",
- "tvc_similarity",
- "max_tokens",
- "temperature",
- "enable_reflection",
- "enable_context",
- "enable_tools",
- "groq_model",
- "claude_model",
- "GROQ_API_KEY",
- "ANTHROPIC_API_KEY",
- "total_queries",
- };
-
- // v2.0: Read LIVE values from HybridConfig
- var vb0: [32:0]u8 = undefined;
- var vb1: [32:0]u8 = undefined;
- var vb2: [32:0]u8 = undefined;
- var vb3: [32:0]u8 = undefined;
- var vb11: [32:0]u8 = undefined;
- if (g_hybrid_engine != null) {
- const cfg = g_hybrid_engine.?.config;
- _ = std.fmt.bufPrint(&vb0, "{d:.2}", .{cfg.symbolic_confidence_threshold}) catch {};
- vb0[@min(31, std.mem.indexOfScalar(u8, &vb0, 0) orelse 31)] = 0;
- _ = std.fmt.bufPrint(&vb1, "{d:.2}", .{cfg.tvc_similarity_threshold}) catch {};
- vb1[@min(31, std.mem.indexOfScalar(u8, &vb1, 0) orelse 31)] = 0;
- _ = std.fmt.bufPrint(&vb2, "{d}", .{cfg.max_tokens}) catch {};
- vb2[@min(31, std.mem.indexOfScalar(u8, &vb2, 0) orelse 31)] = 0;
- _ = std.fmt.bufPrint(&vb3, "{d:.2}", .{cfg.temperature}) catch {};
- vb3[@min(31, std.mem.indexOfScalar(u8, &vb3, 0) orelse 31)] = 0;
- _ = std.fmt.bufPrint(&vb11, "{d}", .{g_hybrid_engine.?.total_queries}) catch {};
- vb11[@min(31, std.mem.indexOfScalar(u8, &vb11, 0) orelse 31)] = 0;
- } else {
- @memcpy(vb0[0..4], "0.30");
- vb0[4] = 0;
- @memcpy(vb1[0..4], "0.55");
- vb1[4] = 0;
- @memcpy(vb2[0..2], "32");
- vb2[2] = 0;
- @memcpy(vb3[0..4], "0.70");
- vb3[4] = 0;
- @memcpy(vb11[0..1], "0");
- vb11[1] = 0;
- }
-
- const refl_str: [*:0]const u8 = if (g_hybrid_engine != null and g_hybrid_engine.?.config.enable_reflection) "true" else "false";
- const ctx_str: [*:0]const u8 = if (g_hybrid_engine != null and g_hybrid_engine.?.config.enable_context) "true" else "false";
- const tools_str: [*:0]const u8 = if (g_hybrid_engine != null and g_hybrid_engine.?.config.enable_tools) "true" else "false";
- const groq_key_str: [*:0]const u8 = if (g_hybrid_engine != null and g_hybrid_engine.?.config.groq_api_key != null) "****" else "not set";
- const claude_key_str: [*:0]const u8 = if (g_hybrid_engine != null and g_hybrid_engine.?.config.claude_api_key != null) "****" else "not set";
-
- const vals = [_][*:0]const u8{
- &vb0,
- &vb1,
- &vb2,
- &vb3,
- refl_str,
- ctx_str,
- tools_str,
- "llama-3.3-70b-versatile",
- "claude-sonnet-4-20250514",
- groq_key_str,
- claude_key_str,
- &vb11,
- };
-
- var si: usize = 0;
- while (si < keys.len) : (si += 1) {
- const y_pos = 80 * fs + @as(f32, @floatFromInt(si)) * line_h;
- const wave_x = @sin(frame_time * 1.0 + @as(f32, @floatFromInt(si)) * 0.5) * 2;
- rl.DrawTextEx(chat_font, keys[si], .{ .x = margin + wave_x, .y = y_pos }, 15 * fs, 0.5, key_color);
- // v2.0: Color booleans green/gray
- const vc = if (si >= 4 and si <= 6) active_color else val_color;
- rl.DrawTextEx(chat_font, vals[si], .{ .x = margin + 280 * fs + wave_x, .y = y_pos }, 15 * fs, 0.5, vc);
- }
-
- // Concentric config rings
- for (0..4) |ri| {
- const r = 100.0 + @as(f32, @floatFromInt(ri)) * 60.0 + @sin(frame_time * 0.8 + @as(f32, @floatFromInt(ri))) * 8;
- rl.DrawCircleLines(@intFromFloat(sw * 0.7), @intFromFloat(sh * 0.55), r, rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = @as(u8, @intFromFloat(@max(0, @min(25, @as(f32, @floatFromInt(alpha_u8)) * 0.1)))) });
- }
- }
-
- // === DOCS WAVE FIELD === (all 27 sacred worlds)
- if (g_wave_mode == .docs) {
- const margin: f32 = 60 * fs;
- const line_h: f32 = 28 * fs;
- const title_color = withAlpha(mode_color, alpha_u8);
-
- rl.DrawTextEx(chat_font, "SACRED WORLDS (27)", .{ .x = margin, .y = 35 * fs }, 18 * fs, 0.5, title_color);
-
- // v2.0: Display all 27 sacred worlds
- const max_worlds: usize = 27;
- var wi: usize = 0;
- while (wi < max_worlds) : (wi += 1) {
- const y_pos = 75 * fs + @as(f32, @floatFromInt(wi)) * line_h;
- if (y_pos > sh - 40) break;
-
- const wave_x = @sin(frame_time * 0.8 + @as(f32, @floatFromInt(wi)) * 0.3) * 3;
- const realm = sacred_worlds.blockToRealm(wi);
- const rc = rl.Color{
- .r = sacred_worlds.realmColorR(realm),
- .g = sacred_worlds.realmColorG(realm),
- .b = sacred_worlds.realmColorB(realm),
- .a = alpha_u8,
- };
-
- // Realm color dot
- rl.DrawCircle(@intFromFloat(margin + wave_x), @intFromFloat(y_pos + 7), 5, rc);
-
- // World name
- const world = sacred_worlds.getWorldByBlock(wi);
- var wname_buf: [32:0]u8 = undefined;
- const wname: []const u8 = &world.name;
- const wname_len = std.mem.indexOfScalar(u8, wname, 0) orelse wname.len;
- @memcpy(wname_buf[0..wname_len], wname[0..wname_len]);
- wname_buf[wname_len] = 0;
- rl.DrawTextEx(chat_font, &wname_buf, .{ .x = margin + 18 + wave_x, .y = y_pos }, 15 * fs, 0.5, withAlpha(rl.Color{ .r = 220, .g = 220, .b = 230, .a = 255 }, alpha_u8));
-
- // Realm name
- const realm_idx = @intFromEnum(realm);
- const rn_len = sacred_worlds.REALM_NAME_LENS[realm_idx];
- var rbuf: [64:0]u8 = undefined;
- @memcpy(rbuf[0..rn_len], sacred_worlds.REALM_NAMES[realm_idx][0..rn_len]);
- rbuf[rn_len] = 0;
- rl.DrawTextEx(chat_font, &rbuf, .{ .x = margin + 260 * fs + wave_x, .y = y_pos }, 13 * fs, 0.5, rc);
- }
- }
-
- // === FINDER WAVE FIELD === (LIVE directory listing via std.fs)
- if (g_wave_mode == .finder) {
- const margin: f32 = 60 * fs;
- const line_h: f32 = 22 * fs;
- const dir_color = withAlpha(mode_color, alpha_u8);
- const file_color = withAlpha(rl.Color{ .r = 180, .g = 200, .b = 220, .a = 255 }, alpha_u8);
-
- // v2.0: Scan real directory (every 2 seconds)
- const now_ts = std.time.timestamp();
- if (!g_finder_scanned or (now_ts - g_finder_last_scan) > 2) {
- scanDirectory();
- }
-
- rl.DrawTextEx(chat_font, "FILE EXPLORER (LIVE)", .{ .x = margin, .y = 35 * fs }, 18 * fs, 0.5, dir_color);
-
- // v2.0: Show file count
- var count_buf: [48:0]u8 = undefined;
- _ = std.fmt.bufPrint(&count_buf, "cwd: {d} entries", .{g_finder_count}) catch {};
- count_buf[@min(47, std.mem.indexOfScalar(u8, &count_buf, 0) orelse 47)] = 0;
- rl.DrawTextEx(chat_font, &count_buf, .{ .x = margin, .y = 60 * fs }, 14 * fs, 0.5, withAlpha(MUTED_GRAY, alpha_u8));
-
- // v2.0: Display REAL files from g_finder_names
- var fi: usize = 0;
- while (fi < g_finder_count) : (fi += 1) {
- const y_pos = 85 * fs + @as(f32, @floatFromInt(fi)) * line_h;
- if (y_pos > sh - 40) break;
- const wave_x = @sin(frame_time * 1.2 + @as(f32, @floatFromInt(fi)) * 0.35) * 2;
- const ic = if (g_finder_is_dir[fi]) dir_color else file_color;
- // Dir indicator
- if (g_finder_is_dir[fi]) {
- var dir_buf: [68:0]u8 = undefined;
- const nlen = std.mem.indexOfScalar(u8, &g_finder_names[fi], 0) orelse 63;
- @memcpy(dir_buf[0..nlen], g_finder_names[fi][0..nlen]);
- dir_buf[nlen] = '/';
- dir_buf[nlen + 1] = 0;
- rl.DrawTextEx(chat_font, &dir_buf, .{ .x = margin + wave_x, .y = y_pos }, 14 * fs, 0.5, ic);
- } else {
- rl.DrawTextEx(chat_font, &g_finder_names[fi], .{ .x = margin + wave_x, .y = y_pos }, 14 * fs, 0.5, ic);
- }
- }
-
- // Spiral decoration
- for (0..20) |si| {
- const angle = @as(f32, @floatFromInt(si)) * 0.5 + frame_time * 0.3;
- const r = 30.0 + @as(f32, @floatFromInt(si)) * 8.0;
- const sx = sw * 0.75 + @cos(angle) * r;
- const sy = sh * 0.5 + @sin(angle) * r;
- rl.DrawCircle(@intFromFloat(sx), @intFromFloat(sy), 2, rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = @as(u8, @intFromFloat(@max(0, @min(60, @as(f32, @floatFromInt(alpha_u8)) * 0.2)))) });
- }
- }
-
- // === VISION WAVE FIELD === (LIVE API status + instructions)
- if (g_wave_mode == .vision) {
- const center_x = sw / 2;
- const center_y = sh / 2;
-
- // Expanding concentric rings
- for (0..8) |ri| {
- const base_r = 40.0 + @as(f32, @floatFromInt(ri)) * 35.0;
- const r = base_r + @sin(frame_time * 2.0 + @as(f32, @floatFromInt(ri)) * 0.8) * 10;
- const ra: u8 = @intFromFloat(@max(0, @min(80, @as(f32, @floatFromInt(alpha_u8)) * (0.35 - @as(f32, @floatFromInt(ri)) * 0.04))));
- rl.DrawCircleLines(@intFromFloat(center_x), @intFromFloat(center_y), r, rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = ra });
- }
-
- // Center icon (eye)
- rl.DrawCircle(@intFromFloat(center_x), @intFromFloat(center_y), 12, mode_color);
- rl.DrawCircle(@intFromFloat(center_x), @intFromFloat(center_y), 6, rl.Color{ .r = 20, .g = 20, .b = 30, .a = alpha_u8 });
-
- // v2.0: LIVE API status
- rl.DrawTextEx(chat_font, "VISION", .{ .x = center_x - 30, .y = center_y - 80 }, 20 * fs, 0.5, mode_color);
-
- // Check Claude API key availability
- const has_claude = g_hybrid_engine != null and g_hybrid_engine.?.config.claude_api_key != null;
- if (has_claude) {
- rl.DrawCircle(@intFromFloat(center_x - 90), @intFromFloat(center_y + 42), 4, rl.Color{ .r = 80, .g = 255, .b = 80, .a = alpha_u8 });
- rl.DrawTextEx(chat_font, "Claude Vision API: ready", .{ .x = center_x - 80, .y = center_y + 35 }, 14 * fs, 0.5, withAlpha(rl.Color{ .r = 80, .g = 255, .b = 120, .a = 255 }, alpha_u8));
- } else {
- rl.DrawCircle(@intFromFloat(center_x - 90), @intFromFloat(center_y + 42), 4, rl.Color{ .r = 255, .g = 120, .b = 80, .a = alpha_u8 });
- rl.DrawTextEx(chat_font, "Claude Vision API: no key", .{ .x = center_x - 80, .y = center_y + 35 }, 14 * fs, 0.5, withAlpha(rl.Color{ .r = 255, .g = 120, .b = 80, .a = 255 }, alpha_u8));
- }
-
- rl.DrawTextEx(chat_font, "In chat: type 'vision: /path/to/image'", .{ .x = center_x - 150, .y = center_y + 65 }, 14 * fs, 0.5, withAlpha(MUTED_GRAY, alpha_u8));
- rl.DrawTextEx(chat_font, "Supports: PNG, JPG, WEBP, GIF", .{ .x = center_x - 120, .y = center_y + 88 }, 12 * fs, 0.5, withAlpha(MUTED_GRAY, @as(u8, @intFromFloat(@max(0, @min(255, @as(f32, @floatFromInt(alpha_u8)) * 0.5))))));
- rl.DrawTextEx(chat_font, "respondWithImage() -> Claude/GPT-4o", .{ .x = center_x - 145, .y = center_y + 108 }, 12 * fs, 0.5, withAlpha(MUTED_GRAY, @as(u8, @intFromFloat(@max(0, @min(255, @as(f32, @floatFromInt(alpha_u8)) * 0.4))))));
- }
-
- // === VOICE WAVE FIELD === (wave state modulated waveform)
- if (g_wave_mode == .voice) {
- const center_y = sh / 2;
- const wave_count: usize = 64;
- const bar_w = sw / @as(f32, @floatFromInt(wave_count));
-
- // v2.0: Modulate waveform with LIVE wave state
- const vws = igla_hybrid_chat.g_last_wave_state;
- const conf_amp = @max(0.3, vws.confidence); // Amplitude from confidence
- const hue_freq = vws.source_hue / 360.0 * 2.0 + 1.5; // Frequency from source hue
- const health_bright = @max(0.4, vws.provider_health_avg); // Brightness from health
-
- // Audio waveform bars
- for (0..wave_count) |wi| {
- const fi_f = @as(f32, @floatFromInt(wi));
- const amp = @sin(frame_time * (2.0 + hue_freq) + fi_f * 0.3) * @sin(frame_time * 1.7 + fi_f * 0.15) * 60 * fs * conf_amp;
- const bar_x = fi_f * bar_w + bar_w * 0.1;
- const bar_h = @abs(amp) + 4;
- const base_intensity = @abs(amp) * 3 + 40;
- const intensity: u8 = @intFromFloat(@max(40, @min(255, base_intensity * health_bright)));
-
- // v2.0: Green glow when learning
- const bar_color = if (vws.is_learning) rl.Color{ .r = 40, .g = 255, .b = 80, .a = @as(u8, @intFromFloat(@max(0, @min(255, @as(f32, @floatFromInt(intensity)) * @as(f32, @floatFromInt(alpha_u8)) / 255.0)))) } else rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = @as(u8, @intFromFloat(@max(0, @min(255, @as(f32, @floatFromInt(intensity)) * @as(f32, @floatFromInt(alpha_u8)) / 255.0)))) };
- rl.DrawRectangle(@intFromFloat(bar_x), @intFromFloat(center_y - bar_h / 2), @intFromFloat(@max(1, bar_w * 0.7)), @intFromFloat(@max(1, bar_h)), bar_color);
- }
-
- // Status with live data
- rl.DrawTextEx(chat_font, "VOICE", .{ .x = sw / 2 - 25, .y = 40 * fs }, 20 * fs, 0.5, mode_color);
-
- // v2.0: Show whisper model from config
- const whisper_str: [*:0]const u8 = if (g_hybrid_engine != null) "Whisper: whisper-1 (standby)" else "Whisper: not configured";
- rl.DrawTextEx(chat_font, whisper_str, .{ .x = sw / 2 - 100, .y = sh - 80 * fs }, 14 * fs, 0.5, withAlpha(MUTED_GRAY, alpha_u8));
-
- // v2.0: Show live wave state values
- var voice_info: [64:0]u8 = undefined;
- _ = std.fmt.bufPrint(&voice_info, "conf:{d:.0}% health:{d:.0}% route:{s}", .{ vws.confidence * 100, vws.provider_health_avg * 100, @tagName(vws.routing) }) catch {};
- voice_info[@min(63, std.mem.indexOfScalar(u8, &voice_info, 0) orelse 63)] = 0;
- rl.DrawTextEx(chat_font, &voice_info, .{ .x = sw / 2 - 130, .y = sh - 55 * fs }, 12 * fs, 0.5, withAlpha(MUTED_GRAY, @as(u8, @intFromFloat(@max(0, @min(255, @as(f32, @floatFromInt(alpha_u8)) * 0.5))))));
-
- // Center line
- rl.DrawLine(0, @intFromFloat(center_y), @intFromFloat(sw), @intFromFloat(center_y), rl.Color{ .r = mode_rgb[0], .g = mode_rgb[1], .b = mode_rgb[2], .a = @as(u8, @intFromFloat(@max(0, @min(30, @as(f32, @floatFromInt(alpha_u8)) * 0.12)))) });
- }
-
- // === v2.1: MIRROR OF THREE WORLDS ===
- if (g_wave_mode == .mirror) {
- const col_w = sw / 3.0;
- const log_h: f32 = 130 * fs;
- const content_h = sh - log_h;
- const line_h: f32 = 20 * fs;
- const title_sz: f32 = 20 * fs;
- const label_sz: f32 = 13 * fs;
- const val_sz: f32 = 14 * fs;
-
- // Realm colors
- const razum_color = rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha_u8 };
- const materiya_color = rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = alpha_u8 };
- const dukh_color = rl.Color{ .r = 0xBD, .g = 0x93, .b = 0xF9, .a = alpha_u8 };
- const dim_text = withAlpha(MUTED_GRAY, alpha_u8);
- const bright_text = withAlpha(rl.Color{ .r = 220, .g = 220, .b = 230, .a = 255 }, alpha_u8);
-
- const mws = igla_hybrid_chat.g_last_wave_state;
-
- // Column separator lines
- rl.DrawLine(@intFromFloat(col_w), 0, @intFromFloat(col_w), @intFromFloat(content_h), rl.Color{ .r = 80, .g = 80, .b = 100, .a = @as(u8, @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.3)) });
- rl.DrawLine(@intFromFloat(col_w * 2), 0, @intFromFloat(col_w * 2), @intFromFloat(content_h), rl.Color{ .r = 80, .g = 80, .b = 100, .a = @as(u8, @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.3)) });
- // Log separator
- rl.DrawLine(0, @intFromFloat(content_h), @intFromFloat(sw), @intFromFloat(content_h), rl.Color{ .r = 80, .g = 80, .b = 100, .a = @as(u8, @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.5)) });
-
- // ββ RAZUM COLUMN (left) ββ
- {
- const x: f32 = 20 * fs;
- var y: f32 = 25 * fs;
- rl.DrawTextEx(chat_font, "RAZUM", .{ .x = x, .y = y }, title_sz, 0.5, razum_color);
- y += title_sz + 4;
- rl.DrawTextEx(chat_font, "Mind / AI / Chat", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- y += line_h + 8;
-
- // Routing
- rl.DrawTextEx(chat_font, "Routing:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var r_buf: [32:0]u8 = undefined;
- const r_name = @tagName(mws.routing);
- _ = std.fmt.bufPrint(&r_buf, "{s}", .{r_name}) catch {};
- r_buf[@min(31, std.mem.indexOfScalar(u8, &r_buf, 0) orelse 31)] = 0;
- rl.DrawTextEx(chat_font, &r_buf, .{ .x = x + 80 * fs, .y = y }, val_sz, 0.5, razum_color);
- y += line_h;
-
- // Confidence
- rl.DrawTextEx(chat_font, "Confidence:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var c_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&c_buf, "{d:.0}%", .{mws.confidence * 100}) catch {};
- c_buf[@min(15, std.mem.indexOfScalar(u8, &c_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &c_buf, .{ .x = x + 100 * fs, .y = y }, val_sz, 0.5, bright_text);
- // Confidence bar
- const bar_w_max = col_w - 50 * fs;
- const bar_y = y + line_h;
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(bar_y), @intFromFloat(bar_w_max), 4, rl.Color{ .r = 40, .g = 40, .b = 50, .a = alpha_u8 });
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(bar_y), @intFromFloat(bar_w_max * mws.confidence), 4, razum_color);
- y += line_h + 10;
-
- // Total queries
- rl.DrawTextEx(chat_font, "Queries:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var q_buf: [16:0]u8 = undefined;
- const qc = if (g_hybrid_engine != null) g_hybrid_engine.?.total_queries else 0;
- _ = std.fmt.bufPrint(&q_buf, "{d}", .{qc}) catch {};
- q_buf[@min(15, std.mem.indexOfScalar(u8, &q_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &q_buf, .{ .x = x + 80 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
-
- // Groq health
- rl.DrawTextEx(chat_font, "Groq:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- if (g_hybrid_engine != null) {
- var gh_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&gh_buf, "{d:.0}%", .{g_hybrid_engine.?.groq_health.getSuccessRate() * 100}) catch {};
- gh_buf[@min(15, std.mem.indexOfScalar(u8, &gh_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &gh_buf, .{ .x = x + 55 * fs, .y = y }, val_sz, 0.5, bright_text);
- } else {
- rl.DrawTextEx(chat_font, "N/A", .{ .x = x + 55 * fs, .y = y }, val_sz, 0.5, dim_text);
- }
- y += line_h;
-
- // Claude health
- rl.DrawTextEx(chat_font, "Claude:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- if (g_hybrid_engine != null) {
- var ch_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&ch_buf, "{d:.0}%", .{g_hybrid_engine.?.claude_health.getSuccessRate() * 100}) catch {};
- ch_buf[@min(15, std.mem.indexOfScalar(u8, &ch_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &ch_buf, .{ .x = x + 65 * fs, .y = y }, val_sz, 0.5, bright_text);
- } else {
- rl.DrawTextEx(chat_font, "N/A", .{ .x = x + 65 * fs, .y = y }, val_sz, 0.5, dim_text);
- }
- y += line_h;
-
- // Last response (truncated)
- rl.DrawTextEx(chat_font, "Last:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- y += line_h;
- if (g_chat_msg_count > 0) {
- const last_idx = g_chat_msg_count - 1;
- if (g_chat_msg_types[last_idx] == .ai) {
- const trunc_len = @min(g_chat_msg_lens[last_idx], 60);
- var last_buf: [64:0]u8 = undefined;
- @memcpy(last_buf[0..trunc_len], g_chat_messages[last_idx][0..trunc_len]);
- last_buf[trunc_len] = 0;
- rl.DrawTextEx(chat_font, &last_buf, .{ .x = x, .y = y }, label_sz, 0.5, withAlpha(rl.Color{ .r = 180, .g = 200, .b = 180, .a = 255 }, alpha_u8));
- }
- }
-
- // Realm glow: left edge
- for (0..3) |gi| {
- const glx: f32 = @as(f32, @floatFromInt(gi)) * 1.0;
- const ga: u8 = @intFromFloat(@max(0, @min(40, @as(f32, @floatFromInt(alpha_u8)) * (0.15 - @as(f32, @floatFromInt(gi)) * 0.04))));
- rl.DrawLine(@intFromFloat(glx), 0, @intFromFloat(glx), @intFromFloat(content_h), rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = ga });
- }
- }
-
- // ββ MATERIYA COLUMN (center) ββ
- {
- const x = col_w + 20 * fs;
- var y: f32 = 25 * fs;
- rl.DrawTextEx(chat_font, "MATERIYA", .{ .x = x, .y = y }, title_sz, 0.5, materiya_color);
- y += title_sz + 4;
- rl.DrawTextEx(chat_font, "Matter / System / Files", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- y += line_h + 8;
-
- // FPS
- rl.DrawTextEx(chat_font, "FPS:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var fps_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&fps_buf, "{d}", .{rl.GetFPS()}) catch {};
- fps_buf[@min(15, std.mem.indexOfScalar(u8, &fps_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &fps_buf, .{ .x = x + 45 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
-
- // Engine
- rl.DrawTextEx(chat_font, "Engine:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- const eng_str: [*:0]const u8 = if (g_hybrid_engine != null) "IglaHybrid v2.4" else "FluentChat";
- rl.DrawTextEx(chat_font, eng_str, .{ .x = x + 65 * fs, .y = y }, val_sz, 0.5, materiya_color);
- y += line_h;
-
- // Tools
- rl.DrawTextEx(chat_font, "Tools:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- const tools_on = g_hybrid_engine != null and g_hybrid_engine.?.config.enable_tools;
- const t_str: [*:0]const u8 = if (tools_on) "enabled" else "disabled";
- const t_col = if (tools_on) materiya_color else dim_text;
- rl.DrawTextEx(chat_font, t_str, .{ .x = x + 55 * fs, .y = y }, val_sz, 0.5, t_col);
- y += line_h;
-
- // Memory load bar
- rl.DrawTextEx(chat_font, "Memory:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var mem_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&mem_buf, "{d:.0}%", .{mws.memory_load * 100}) catch {};
- mem_buf[@min(15, std.mem.indexOfScalar(u8, &mem_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &mem_buf, .{ .x = x + 70 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
- const mem_bar_w = col_w - 50 * fs;
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(y), @intFromFloat(mem_bar_w), 4, rl.Color{ .r = 40, .g = 40, .b = 50, .a = alpha_u8 });
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(y), @intFromFloat(mem_bar_w * mws.memory_load), 4, materiya_color);
- y += 10;
-
- // File count
- if (!g_finder_scanned) scanDirectory();
- rl.DrawTextEx(chat_font, "Files:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var f_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&f_buf, "{d} entries", .{g_finder_count}) catch {};
- f_buf[@min(15, std.mem.indexOfScalar(u8, &f_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &f_buf, .{ .x = x + 55 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
-
- // TVC corpus
- rl.DrawTextEx(chat_font, "TVC:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- rl.DrawTextEx(chat_font, "10000 max", .{ .x = x + 45 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
-
- // VSA dim
- rl.DrawTextEx(chat_font, "VSA:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- rl.DrawTextEx(chat_font, "Active", .{ .x = x + 40 * fs, .y = y }, val_sz, 0.5, withAlpha(rl.Color{ .r = 0, .g = 255, .b = 150, .a = 255 }, alpha_u8));
- y += line_h + 10;
-
- // ββ v2.8: RALPH MONITOR (multi-agent) ββ
- rl.DrawLine(@intFromFloat(x), @intFromFloat(y), @intFromFloat(x + col_w - 40 * fs), @intFromFloat(y), rl.Color{ .r = 80, .g = 80, .b = 100, .a = @as(u8, @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.5)) });
- y += 10;
- rl.DrawTextEx(chat_font, "RALPH MONITOR", .{ .x = x, .y = y }, title_sz * 0.8, 1.0, withAlpha(rl.Color{ .r = 0, .g = 200, .b = 255, .a = 255 }, alpha_u8));
- y += title_sz + 4;
-
- const mirror_agent = &g_ralph_agents[@min(g_ralph_active_tab, if (g_ralph_agent_count > 0) g_ralph_agent_count - 1 else 0)];
-
- // Loop info
- rl.DrawTextEx(chat_font, "Loop:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var l_buf: [16:0]u8 = undefined;
- @memset(&l_buf, 0);
- _ = std.fmt.bufPrint(&l_buf, "{d}", .{mirror_agent.loop}) catch {};
- rl.DrawTextEx(chat_font, &l_buf, .{ .x = x + 40 * fs, .y = y }, val_sz, 0.5, bright_text);
-
- rl.DrawTextEx(chat_font, "Calls:", .{ .x = x + 80 * fs, .y = y }, label_sz, 0.5, dim_text);
- var tc_buf: [16:0]u8 = undefined;
- @memset(&tc_buf, 0);
- _ = std.fmt.bufPrint(&tc_buf, "{d}", .{mirror_agent.total_calls}) catch {};
- rl.DrawTextEx(chat_font, &tc_buf, .{ .x = x + 125 * fs, .y = y }, val_sz, 0.5, razum_color);
- y += line_h;
-
- // Health (Circuit Breaker)
- rl.DrawTextEx(chat_font, "Health:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- const h_col = if (mirror_agent.is_healthy) rl.Color{ .r = 0, .g = 255, .b = 150, .a = alpha_u8 } else rl.Color{ .r = 255, .g = 80, .b = 80, .a = alpha_u8 };
- rl.DrawTextEx(chat_font, if (mirror_agent.is_healthy) "OPTIMAL" else "BREAK", .{ .x = x + 55 * fs, .y = y }, val_sz, 0.5, h_col);
- y += line_h;
-
- // Goal
- rl.DrawTextEx(chat_font, "Goal:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- y += line_h;
- rl.DrawTextEx(chat_font, &mirror_agent.goal, .{ .x = x, .y = y }, label_sz * 0.9, 0.5, withAlpha(rl.Color{ .r = 150, .g = 200, .b = 255, .a = 255 }, alpha_u8));
- y += line_h + 4;
-
- // Ralph Logs
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(y), @intFromFloat(col_w - 40 * fs), @intFromFloat(70 * fs), rl.Color{ .r = 20, .g = 20, .b = 30, .a = alpha_u8 });
- var ly = y + 4;
- for (0..mirror_agent.log_count) |i| {
- rl.DrawTextEx(chat_font, &mirror_agent.logs[i], .{ .x = x + 4, .y = ly }, 10, 0.5, withAlpha(rl.Color{ .r = 100, .g = 150, .b = 200, .a = 255 }, alpha_u8));
- ly += 12;
- }
- y += 80 * fs;
-
- // Realm glow: center
- for (0..3) |gi| {
- const glx: f32 = col_w + @as(f32, @floatFromInt(gi)) * 1.0;
- const ga: u8 = @intFromFloat(@max(0, @min(40, @as(f32, @floatFromInt(alpha_u8)) * (0.15 - @as(f32, @floatFromInt(gi)) * 0.04))));
- rl.DrawLine(@intFromFloat(glx), 0, @intFromFloat(glx), @intFromFloat(content_h), rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = ga });
- }
- }
-
- // ββ DUKH COLUMN (right) ββ
- {
- const x = col_w * 2 + 20 * fs;
- var y: f32 = 25 * fs;
- rl.DrawTextEx(chat_font, "DUKH", .{ .x = x, .y = y }, title_sz, 0.5, dukh_color);
- y += title_sz + 4;
- rl.DrawTextEx(chat_font, "Spirit / Knowledge", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- y += line_h + 8;
-
- // Source hue (color bar)
- rl.DrawTextEx(chat_font, "Source hue:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var h_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&h_buf, "{d:.0}", .{mws.source_hue}) catch {};
- h_buf[@min(15, std.mem.indexOfScalar(u8, &h_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &h_buf, .{ .x = x + 100 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
- // Color bar showing source hue
- const src_rgb = hsvToRgb(mws.source_hue, 0.8, 0.9);
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(y), @intFromFloat(col_w - 50 * fs), 6, rl.Color{ .r = src_rgb[0], .g = src_rgb[1], .b = src_rgb[2], .a = alpha_u8 });
- y += 12;
-
- // Reflection status
- rl.DrawTextEx(chat_font, "Reflection:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- if (g_last_reflection_len > 0) {
- rl.DrawTextEx(chat_font, &g_last_reflection_name, .{ .x = x + 100 * fs, .y = y }, val_sz, 0.5, dukh_color);
- } else {
- rl.DrawTextEx(chat_font, "N/A", .{ .x = x + 100 * fs, .y = y }, val_sz, 0.5, dim_text);
- }
- y += line_h;
-
- // Learning indicator
- rl.DrawTextEx(chat_font, "Learning:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- if (mws.is_learning) {
- rl.DrawCircle(@intFromFloat(x + 85 * fs), @intFromFloat(y + 7), 5, rl.Color{ .r = 80, .g = 255, .b = 80, .a = alpha_u8 });
- rl.DrawTextEx(chat_font, "ACTIVE", .{ .x = x + 95 * fs, .y = y }, val_sz, 0.5, rl.Color{ .r = 80, .g = 255, .b = 80, .a = alpha_u8 });
- } else {
- rl.DrawCircle(@intFromFloat(x + 85 * fs), @intFromFloat(y + 7), 5, rl.Color{ .r = 80, .g = 80, .b = 80, .a = alpha_u8 });
- rl.DrawTextEx(chat_font, "idle", .{ .x = x + 95 * fs, .y = y }, val_sz, 0.5, dim_text);
- }
- y += line_h;
-
- // Provider health bar
- rl.DrawTextEx(chat_font, "Health:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var ph_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&ph_buf, "{d:.0}%", .{mws.provider_health_avg * 100}) catch {};
- ph_buf[@min(15, std.mem.indexOfScalar(u8, &ph_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &ph_buf, .{ .x = x + 65 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
- const hp_bar_w = col_w - 50 * fs;
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(y), @intFromFloat(hp_bar_w), 4, rl.Color{ .r = 40, .g = 40, .b = 50, .a = alpha_u8 });
- rl.DrawRectangle(@intFromFloat(x), @intFromFloat(y), @intFromFloat(hp_bar_w * mws.provider_health_avg), 4, dukh_color);
- y += 12;
-
- // Similarity
- rl.DrawTextEx(chat_font, "Similarity:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var sim_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&sim_buf, "{d:.2}", .{mws.similarity}) catch {};
- sim_buf[@min(15, std.mem.indexOfScalar(u8, &sim_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &sim_buf, .{ .x = x + 95 * fs, .y = y }, val_sz, 0.5, bright_text);
- y += line_h;
-
- // Latency
- rl.DrawTextEx(chat_font, "Latency:", .{ .x = x, .y = y }, label_sz, 0.5, dim_text);
- var lat_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&lat_buf, "{d:.2}", .{mws.latency_normalized}) catch {};
- lat_buf[@min(15, std.mem.indexOfScalar(u8, &lat_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &lat_buf, .{ .x = x + 80 * fs, .y = y }, val_sz, 0.5, bright_text);
-
- // Self-reflection pulsing ring
- const ref_pulse = @sin(frame_time * 2.5) * 0.3 + 0.7;
- const ref_r = 30.0 + ref_pulse * 10.0;
- const ref_a: u8 = @intFromFloat(@max(0, @min(60, ref_pulse * @as(f32, @floatFromInt(alpha_u8)) * 0.25)));
- rl.DrawCircleLines(@intFromFloat(x + col_w * 0.35), @intFromFloat(content_h * 0.8), ref_r, rl.Color{ .r = 0xBD, .g = 0x93, .b = 0xF9, .a = ref_a });
- }
-
- // ββ TRINITY RING (center intersection) ββ
- {
- const cx = sw / 2;
- const cy = content_h * 0.85;
- const ring_base = 15.0 + mws.confidence * 10.0;
- const ring_pulse = @sin(frame_time * 1.5) * 3.0;
- const ra: u8 = @intFromFloat(@max(0, @min(50, @as(f32, @floatFromInt(alpha_u8)) * 0.2)));
- // Gold ring
- rl.DrawCircleLines(@intFromFloat(cx - 10), @intFromFloat(cy), ring_base + ring_pulse, rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = ra });
- // Cyan ring
- rl.DrawCircleLines(@intFromFloat(cx + 10), @intFromFloat(cy), ring_base + ring_pulse, rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = ra });
- // Purple ring
- rl.DrawCircleLines(@intFromFloat(cx), @intFromFloat(cy - 12), ring_base + ring_pulse, rl.Color{ .r = 0xBD, .g = 0x93, .b = 0xF9, .a = ra });
- }
-
- // ββ LIVE LOG STRIP (bottom) ββ
- {
- const log_y_start = content_h + 5;
- const log_line_h: f32 = 15 * fs;
- // Dark background
- rl.DrawRectangle(0, @intFromFloat(content_h), @intFromFloat(sw), @intFromFloat(log_h), rl.Color{ .r = 10, .g = 10, .b = 15, .a = @as(u8, @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.7)) });
- rl.DrawTextEx(chat_font, "LIVE LOG", .{ .x = 10, .y = log_y_start }, label_sz, 0.5, withAlpha(MUTED_GRAY, @as(u8, @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.6))));
-
- // Show last N log entries that fit
- const max_visible: usize = @min(g_live_log_count, 7);
- const start_idx = if (g_live_log_count > max_visible) g_live_log_count - max_visible else 0;
- var li: usize = 0;
- while (li < max_visible) : (li += 1) {
- const idx = start_idx + li;
- const ly = log_y_start + 18 * fs + @as(f32, @floatFromInt(li)) * log_line_h;
- // Source color dot
- const src_hue = g_live_log_hues[idx];
- const dot_rgb = hsvToRgb(src_hue, 0.8, 0.9);
- rl.DrawCircle(@intFromFloat(@as(f32, 15)), @intFromFloat(ly + 6), 3, rl.Color{ .r = dot_rgb[0], .g = dot_rgb[1], .b = dot_rgb[2], .a = alpha_u8 });
- // Log text
- rl.DrawTextEx(chat_font, &g_live_log_text[idx], .{ .x = 25, .y = ly }, 12 * fs, 0.5, withAlpha(rl.Color{ .r = 170, .g = 180, .b = 190, .a = 255 }, alpha_u8));
- }
-
- if (g_live_log_count == 0) {
- rl.DrawTextEx(chat_font, "Send a message in Chat (Shift+1) to see logs here", .{ .x = 25, .y = log_y_start + 20 * fs }, 12 * fs, 0.5, dim_text);
- }
- }
- }
- } // end: if (g_wave_mode != .depin and g_wave_mode != .ralph) β skip other renderers in DePIN mode
-
- // === DePIN NODE WAVE FIELD === (v2.4: Docker node management)
- if (g_wave_mode == .depin) {
- // Opaque black background β clean slate
- rl.DrawRectangle(0, 0, @intFromFloat(sw), @intFromFloat(sh), rl.Color{ .r = 0, .g = 0, .b = 0, .a = 255 });
- const margin: f32 = 40 * fs;
- const line_h: f32 = 28 * fs;
- const title_sz: f32 = 28 * fs;
- const subtitle_sz: f32 = 16 * fs;
- const label_sz: f32 = 14 * fs;
- const val_sz: f32 = 16 * fs;
- const col_w = (sw - margin * 3) / 2;
-
- const depin_green = rl.Color{ .r = 0x50, .g = 0xFA, .b = 0x50, .a = alpha_u8 };
- const depin_yellow = rl.Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = alpha_u8 };
- const depin_red = rl.Color{ .r = 0xFF, .g = 0x55, .b = 0x55, .a = alpha_u8 };
- const dim_text = withAlpha(MUTED_GRAY, alpha_u8);
- const bright_text = withAlpha(rl.Color{ .r = 220, .g = 220, .b = 230, .a = 255 }, alpha_u8);
-
- var y: f32 = 30 * fs;
-
- // Title
- rl.DrawTextEx(chat_font, "TRINITY DePIN NODE", .{ .x = margin, .y = y }, title_sz, 0.5, mode_color);
- y += title_sz + 4;
- rl.DrawTextEx(chat_font, "Earn $TRI for VSA compute & storage", .{ .x = margin, .y = y }, subtitle_sz, 0.5, dim_text);
- y += line_h + 10;
-
- // Status indicator
- {
- const status_color = if (g_depin_running) depin_green else if (g_depin_docker_ok) depin_yellow else depin_red;
- const status_text: [*:0]const u8 = if (g_depin_running) "RUNNING" else if (g_depin_docker_ok) "STOPPED" else "NO DOCKER";
-
- // Pulsing status dot
- const pulse = if (g_depin_running) @sin(frame_time * 3.0) * 0.3 + 0.7 else 0.5;
- const dot_a: u8 = @intFromFloat(@max(60, @min(255, pulse * @as(f32, @floatFromInt(alpha_u8)))));
- rl.DrawCircle(@intFromFloat(margin + 8), @intFromFloat(y + 10), 6, rl.Color{ .r = status_color.r, .g = status_color.g, .b = status_color.b, .a = dot_a });
-
- rl.DrawTextEx(chat_font, "Status:", .{ .x = margin + 22, .y = y }, label_sz, 0.5, dim_text);
- rl.DrawTextEx(chat_font, status_text, .{ .x = margin + 80 * fs, .y = y }, val_sz, 0.5, status_color);
- y += line_h;
-
- // Uptime bar (if running)
- if (g_depin_running) {
- const bar_w = col_w;
- const bar_fill = @min(1.0, g_depin_uptime_hours / 24.0); // Scale to 24h
- rl.DrawRectangle(@intFromFloat(margin), @intFromFloat(y), @intFromFloat(bar_w), 6, rl.Color{ .r = 40, .g = 40, .b = 50, .a = alpha_u8 });
- rl.DrawRectangle(@intFromFloat(margin), @intFromFloat(y), @intFromFloat(bar_w * bar_fill), 6, depin_green);
- y += 14;
- }
- }
-
- y += 10;
-
- // Separator
- rl.DrawLine(@intFromFloat(margin), @intFromFloat(y), @intFromFloat(sw - margin), @intFromFloat(y), rl.Color{ .r = 80, .g = 80, .b = 100, .a = @as(u8, @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.3)) });
- y += 15;
-
- // Two columns: EARNINGS | INFRASTRUCTURE
- const col1_x = margin;
- const col2_x = margin + col_w + margin;
- var y1 = y;
- var y2 = y;
-
- // Column 1: EARNINGS
- rl.DrawTextEx(chat_font, "EARNINGS", .{ .x = col1_x, .y = y1 }, subtitle_sz, 0.5, depin_yellow);
- y1 += subtitle_sz + 8;
-
- // Earned
- rl.DrawTextEx(chat_font, "Earned:", .{ .x = col1_x, .y = y1 }, label_sz, 0.5, dim_text);
- var earned_buf: [24:0]u8 = undefined;
- _ = std.fmt.bufPrint(&earned_buf, "{d:.6} TRI", .{g_depin_earned_tri}) catch {};
- earned_buf[@min(23, std.mem.indexOfScalar(u8, &earned_buf, 0) orelse 23)] = 0;
- rl.DrawTextEx(chat_font, &earned_buf, .{ .x = col1_x + 80 * fs, .y = y1 }, val_sz, 0.5, depin_yellow);
- y1 += line_h;
-
- // Pending
- rl.DrawTextEx(chat_font, "Pending:", .{ .x = col1_x, .y = y1 }, label_sz, 0.5, dim_text);
- var pending_buf: [24:0]u8 = undefined;
- _ = std.fmt.bufPrint(&pending_buf, "{d:.6} TRI", .{g_depin_pending_tri}) catch {};
- pending_buf[@min(23, std.mem.indexOfScalar(u8, &pending_buf, 0) orelse 23)] = 0;
- rl.DrawTextEx(chat_font, &pending_buf, .{ .x = col1_x + 80 * fs, .y = y1 }, val_sz, 0.5, bright_text);
- y1 += line_h;
-
- // Operations
- rl.DrawTextEx(chat_font, "Ops:", .{ .x = col1_x, .y = y1 }, label_sz, 0.5, dim_text);
- var ops_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&ops_buf, "{d}", .{g_depin_operations}) catch {};
- ops_buf[@min(15, std.mem.indexOfScalar(u8, &ops_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &ops_buf, .{ .x = col1_x + 80 * fs, .y = y1 }, val_sz, 0.5, bright_text);
- y1 += line_h;
-
- // Column 2: INFRASTRUCTURE
- rl.DrawTextEx(chat_font, "INFRASTRUCTURE", .{ .x = col2_x, .y = y2 }, subtitle_sz, 0.5, withAlpha(rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = 255 }, alpha_u8));
- y2 += subtitle_sz + 8;
-
- // Peers
- rl.DrawTextEx(chat_font, "Peers:", .{ .x = col2_x, .y = y2 }, label_sz, 0.5, dim_text);
- var peers_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&peers_buf, "{d}", .{g_depin_peers}) catch {};
- peers_buf[@min(15, std.mem.indexOfScalar(u8, &peers_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &peers_buf, .{ .x = col2_x + 100 * fs, .y = y2 }, val_sz, 0.5, bright_text);
- y2 += line_h;
-
- // Shards
- rl.DrawTextEx(chat_font, "Shards:", .{ .x = col2_x, .y = y2 }, label_sz, 0.5, dim_text);
- var shards_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&shards_buf, "{d}", .{g_depin_shards}) catch {};
- shards_buf[@min(15, std.mem.indexOfScalar(u8, &shards_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &shards_buf, .{ .x = col2_x + 100 * fs, .y = y2 }, val_sz, 0.5, bright_text);
- y2 += line_h;
-
- // Uptime
- rl.DrawTextEx(chat_font, "Uptime:", .{ .x = col2_x, .y = y2 }, label_sz, 0.5, dim_text);
- var uptime_buf: [16:0]u8 = undefined;
- _ = std.fmt.bufPrint(&uptime_buf, "{d:.1}h", .{g_depin_uptime_hours}) catch {};
- uptime_buf[@min(15, std.mem.indexOfScalar(u8, &uptime_buf, 0) orelse 15)] = 0;
- rl.DrawTextEx(chat_font, &uptime_buf, .{ .x = col2_x + 100 * fs, .y = y2 }, val_sz, 0.5, bright_text);
- y2 += line_h;
-
- // Buttons area
- const btn_y = @max(y1, y2) + 20;
- const btn_w: f32 = 180;
- const btn_h: f32 = 40;
- const btn_gap: f32 = 20;
- const btn_x_start = margin;
-
- // Start/Stop button
- {
- const btn_rect = rl.Rectangle{ .x = btn_x_start, .y = btn_y, .width = btn_w, .height = btn_h };
- const btn_label: [*:0]const u8 = if (g_depin_running) "Stop Node" else "Start Node";
-
- // Draw button manually (no raygui dependency)
- const btn_color = if (g_depin_running) depin_red else depin_green;
- const hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, btn_rect);
- const btn_bg_a: u8 = if (hover) @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.3) else @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.15);
- rl.DrawRectangleRec(btn_rect, rl.Color{ .r = btn_color.r, .g = btn_color.g, .b = btn_color.b, .a = btn_bg_a });
- rl.DrawRectangleLinesEx(btn_rect, 1, btn_color);
- rl.DrawTextEx(chat_font, btn_label, .{ .x = btn_x_start + 30, .y = btn_y + 10 }, val_sz, 0.5, btn_color);
-
- if (hover and mouse_pressed) {
- if (g_depin_running) depinStopNode() else depinStartNode();
- }
- }
-
- // Claim Rewards button
- {
- const btn2_x = btn_x_start + btn_w + btn_gap;
- const btn_rect = rl.Rectangle{ .x = btn2_x, .y = btn_y, .width = btn_w, .height = btn_h };
- const hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, btn_rect);
- const btn_bg_a: u8 = if (hover) @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.3) else @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.15);
- rl.DrawRectangleRec(btn_rect, rl.Color{ .r = depin_yellow.r, .g = depin_yellow.g, .b = depin_yellow.b, .a = btn_bg_a });
- rl.DrawRectangleLinesEx(btn_rect, 1, depin_yellow);
- rl.DrawTextEx(chat_font, "Claim Rewards", .{ .x = btn2_x + 20, .y = btn_y + 10 }, val_sz, 0.5, depin_yellow);
-
- if (hover and mouse_pressed and g_depin_running) {
- depinClaimRewards();
- }
- }
-
- // Dashboard button
- {
- const btn3_x = btn_x_start + (btn_w + btn_gap) * 2;
- const btn_rect = rl.Rectangle{ .x = btn3_x, .y = btn_y, .width = btn_w, .height = btn_h };
- const hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, btn_rect);
- const dash_color = withAlpha(rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = 255 }, alpha_u8);
- const btn_bg_a: u8 = if (hover) @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.3) else @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.15);
- rl.DrawRectangleRec(btn_rect, rl.Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = btn_bg_a });
- rl.DrawRectangleLinesEx(btn_rect, 1, dash_color);
- rl.DrawTextEx(chat_font, "Dashboard", .{ .x = btn3_x + 40, .y = btn_y + 10 }, val_sz, 0.5, dash_color);
-
- if (hover and mouse_pressed) {
- rl.OpenURL("https://gHashTag.github.io/trinity/docs/depin");
- }
- }
-
- // Footer: contract address
- const footer_y = btn_y + btn_h + 30;
- rl.DrawTextEx(chat_font, "Contract: 0xef368e29...F9f469 \xc2\xb7 Sepolia Testnet", .{ .x = margin, .y = footer_y }, 13 * fs, 0.5, dim_text);
-
- // Docker not found warning
- if (!g_depin_docker_ok) {
- const warn_y = footer_y + line_h;
- rl.DrawTextEx(chat_font, "Docker not found. Install at docker.com to run a node.", .{ .x = margin, .y = warn_y }, label_sz, 0.5, depin_red);
- }
- }
-
- // === RALPH AUTONOMOUS MONITOR === (v3.0: Multi-agent tabbed panel β RALPH-CANVAS-005)
- if (g_wave_mode == .ralph) {
- if (!g_ralph_initialized) initRalphAgents();
- // Opaque background from theme (dark=black, light=light gray)
- const theme_bg: rl.Color = @bitCast(theme.bg);
- rl.DrawRectangle(0, 0, @intFromFloat(sw), @intFromFloat(sh), rl.Color{ .r = theme_bg.r, .g = theme_bg.g, .b = theme_bg.b, .a = 255 });
- const margin: f32 = 40 * fs;
- const line_h: f32 = 28 * fs;
- const title_sz: f32 = 28 * fs;
- const subtitle_sz: f32 = 16 * fs;
-
- // Ralph panel colors β from theme system (supports dark/light)
- const ralph_accent = withAlpha(@as(rl.Color, @bitCast(theme.text)), alpha_u8);
- const ralph_green = withAlpha(@as(rl.Color, @bitCast(theme.accents.success)), alpha_u8);
- const ralph_red = withAlpha(@as(rl.Color, @bitCast(theme.accents.error_)), alpha_u8);
- const ralph_card_bg_raw: rl.Color = @bitCast(theme.bg_panel);
- const ralph_card_bg = rl.Color{ .r = ralph_card_bg_raw.r, .g = ralph_card_bg_raw.g, .b = ralph_card_bg_raw.b, .a = 255 }; // force opaque
- const ralph_border = withAlpha(@as(rl.Color, @bitCast(theme.border)), alpha_u8);
- const dim_text = withAlpha(@as(rl.Color, @bitCast(theme.text_muted)), alpha_u8);
- const bright_text = withAlpha(@as(rl.Color, @bitCast(theme.text)), alpha_u8);
-
- // Tool call neon colors (cyberpunk palette)
- const tool_cyan = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0xFF, .a = alpha_u8 }; // [Glob]
- const tool_magenta = rl.Color{ .r = 0xFF, .g = 0x00, .b = 0xFF, .a = alpha_u8 }; // [Read]
- const tool_yellow = rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0x00, .a = alpha_u8 }; // [Grep]
- const tool_orange = rl.Color{ .r = 0xFF, .g = 0x66, .b = 0x00, .a = alpha_u8 }; // [Bash]
- const tool_lime = rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x41, .a = alpha_u8 }; // [Write]
- const tool_pink = rl.Color{ .r = 0xFF, .g = 0x14, .b = 0x93, .a = alpha_u8 }; // [Edit]
- const tool_blue = rl.Color{ .r = 0x44, .g = 0x88, .b = 0xFF, .a = alpha_u8 }; // [TodoWrite]
-
- // ββ v8.4: Configure raygui style with our theme colors ββ
- // raygui uses packed 32-bit colors: 0xaabbggrr
- const bg_color = @as(c_int, @bitCast((@as(u32, ralph_card_bg.a) << 24) | (@as(u32, ralph_card_bg.b) << 16) | (@as(u32, ralph_card_bg.g) << 8) | @as(u32, ralph_card_bg.r)));
- const accent_color = @as(c_int, @bitCast((@as(u32, ralph_accent.a) << 24) | (@as(u32, ralph_accent.b) << 16) | (@as(u32, ralph_accent.g) << 8) | @as(u32, ralph_accent.r)));
- const border_color = @as(c_int, @bitCast((@as(u32, ralph_border.a) << 24) | (@as(u32, ralph_border.b) << 16) | (@as(u32, ralph_border.g) << 8) | @as(u32, ralph_border.r)));
- // DEFAULT control (applies to all controls including TabBar)
- rg.GuiSetStyle(0, 0, border_color); // BORDER_COLOR_NORMAL
- rg.GuiSetStyle(0, 1, bg_color); // BASE_COLOR_NORMAL
- rg.GuiSetStyle(0, 2, accent_color); // TEXT_COLOR_NORMAL
- // BUTTON control (2)
- rg.GuiSetStyle(2, 1, bg_color); // BASE_COLOR_NORMAL
- rg.GuiSetStyle(2, 7, @as(c_int, @bitCast(@as(u32, 0xff505060)))); // BASE_COLOR_PRESSED
- rg.GuiSetStyle(2, 2, accent_color); // TEXT_COLOR_NORMAL
- rg.GuiSetStyle(2, 0, border_color); // BORDER_COLOR_NORMAL
- // SCROLLBAR control (15)
- rg.GuiSetStyle(15, 0, border_color); // BORDER_COLOR_NORMAL
- rg.GuiSetStyle(15, 1, @as(c_int, @bitCast(@as(u32, 0xff404050)))); // BASE_COLOR_NORMAL
-
- var y: f32 = 30 * fs;
-
- // Title with pulsing dot
- const pulse_a: u8 = @intFromFloat(@max(100, @min(255, @sin(frame_time * 3.0) * 80 + 175)));
- rl.DrawCircle(@intFromFloat(margin + 10), @intFromFloat(y + 16), 6, withAlpha(@as(rl.Color, @bitCast(theme.text)), pulse_a));
- rl.DrawTextEx(chat_font, "RALPH AUTONOMOUS MONITOR", .{ .x = margin + 24, .y = y }, title_sz, 0.5, ralph_accent);
- y += title_sz + 4;
- rl.DrawTextEx(chat_font, "Real-time dev loop telemetry", .{ .x = margin + 24, .y = y }, subtitle_sz, 0.5, dim_text);
- y += line_h + 10;
-
- // ββ v8.4: Agent Tab Bar with raygui (RALPH-CANVAS-005) ββ
- {
- const tab_h: f32 = 36 * fs;
- const tabs_w = sw - margin * 2;
-
- // Prepare tab names for raygui
- var tab_names: [16][32:0]u8 = undefined;
- var name_ptrs: [16][*]const u8 = undefined;
- var ti: usize = 0;
- while (ti < g_ralph_agent_count) : (ti += 1) {
- const tab_agent = &g_ralph_agents[ti];
- @memset(&tab_names[ti], 0);
- _ = std.fmt.bufPrint(&tab_names[ti], "{s} ({s})", .{ tab_agent.name, tab_agent.branch }) catch "Unknown";
- name_ptrs[ti] = &tab_names[ti];
- }
-
- // raygui GuiTabBar signature: (bounds, text[*], count, active[*])
- var active_tab: c_int = @intCast(g_ralph_active_tab);
- _ = rg.GuiTabBar(.{ .x = margin, .y = y, .width = tabs_w, .height = tab_h }, @ptrCast(&name_ptrs), @intCast(g_ralph_agent_count), &active_tab);
- g_ralph_active_tab = @intCast(active_tab);
- y += tab_h + 8;
- }
-
- // Separator
- rl.DrawLine(@intFromFloat(margin), @intFromFloat(y), @intFromFloat(sw - margin), @intFromFloat(y), withAlpha(@as(rl.Color, @bitCast(theme.border)), @intFromFloat(@as(f32, @floatFromInt(alpha_u8)) * 0.5)));
- y += 10;
-
- // ββ Active agent alias ββ
- const agent = &g_ralph_agents[@min(g_ralph_active_tab, g_ralph_agent_count -| 1)];
-
- // Keyboard tab navigation (arrow keys + 1-4 without shift)
- {
- const shift_down = rl.IsKeyDown(rl.KEY_LEFT_SHIFT) or rl.IsKeyDown(rl.KEY_RIGHT_SHIFT);
- if (rl.IsKeyPressed(rl.KEY_LEFT) and g_ralph_active_tab > 0) {
- g_ralph_active_tab -= 1;
- }
- if (rl.IsKeyPressed(rl.KEY_RIGHT) and g_ralph_active_tab < g_ralph_agent_count -| 1) {
- g_ralph_active_tab += 1;
- }
- if (!shift_down) {
- if (rl.IsKeyPressed(rl.KEY_ONE) and g_ralph_agent_count > 0) g_ralph_active_tab = 0;
- if (rl.IsKeyPressed(rl.KEY_TWO) and g_ralph_agent_count > 1) g_ralph_active_tab = 1;
- if (rl.IsKeyPressed(rl.KEY_THREE) and g_ralph_agent_count > 2) g_ralph_active_tab = 2;
- if (rl.IsKeyPressed(rl.KEY_FOUR) and g_ralph_agent_count > 3) g_ralph_active_tab = 3;
- }
- }
-
- // Scroll smoothing (lerp) β unified chat scroll
- {
- const ralph_dt = rl.GetFrameTime();
- g_ralph_chat_scroll_y += (g_ralph_chat_scroll_target - g_ralph_chat_scroll_y) * @min(1.0, 8.0 * ralph_dt);
- }
-
- // v8.1: Section collapse animation update
- {
- const sec_dt = rl.GetFrameTime();
- const ai_anim = g_ralph_active_tab;
- if (ai_anim < g_ralph_agent_count) {
- const ag = &g_ralph_agents[ai_anim];
- var smi: usize = 0;
- while (smi < ag.chat_count) : (smi += 1) {
- if (ag.chat_msgs[smi].kind == .claude_result) {
- const cur_rlen = ag.chat_msgs[smi].result_len;
- if (cur_rlen != g_ralph_msg_prev_rlen[ai_anim][smi]) {
- g_ralph_msg_prev_rlen[ai_anim][smi] = cur_rlen;
- for (&g_ralph_section_collapsed[ai_anim][smi]) |*v| v.* = false;
- for (&g_ralph_section_anim[ai_anim][smi]) |*v| v.* = 1.0;
- ag.chat_msgs[smi].show_full = false;
- }
- }
- var ssi: usize = 0;
- while (ssi < MAX_SECTIONS_PER_MSG) : (ssi += 1) {
- const tgt: f32 = if (g_ralph_section_collapsed[ai_anim][smi][ssi]) 0.0 else 1.0;
- const cur = g_ralph_section_anim[ai_anim][smi][ssi];
- var nv = cur + (tgt - cur) * @min(1.0, 5.0 * sec_dt);
- if (nv < 0.01) nv = 0.0;
- if (nv > 0.99) nv = 1.0;
- g_ralph_section_anim[ai_anim][smi][ssi] = nv;
- }
- }
- }
- }
-
- // Reset scroll on tab switch
- if (g_ralph_active_tab != g_ralph_prev_tab) {
- g_ralph_chat_scroll_y = 0;
- g_ralph_chat_scroll_target = 0;
- g_ralph_prev_tab = g_ralph_active_tab;
- }
-
- // βββ v8.0: UNIFIED AGENT CHAT DIALOG βββ
- const full_w = sw - margin * 2;
- const content_w = @min(full_w, 720 * fs); // Grok-style narrow chat
- const content_x_offset = (full_w - content_w) / 2; // Center offset
- const cx = margin + content_x_offset;
- const pane_top = y;
- const pane_bottom = sh - 32 * fs;
-
- {
- var ly = pane_top;
-
- // ββ Header Bar: CB Alert + Task + Buttons + Status Pill ββ
- // CB Alert banner
- if (agent.cb_state == .cb_open) {
- const alert_h: f32 = 28 * fs;
- const cb_pulse: u8 = @intFromFloat(180.0 + 60.0 * @sin(frame_time * 4.0));
- rl.DrawRectangleRounded(.{ .x = cx, .y = ly, .width = content_w, .height = alert_h }, 0.1, 8, rl.Color{ .r = 0xFF, .g = 0x00, .b = 0x33, .a = cb_pulse / 4 });
- rl.DrawTextEx(chat_font, "CIRCUIT BREAKER OPEN β Agent paused", .{ .x = cx + 12, .y = ly + 6 }, 14 * fs, 0.5, rl.Color{ .r = 0xFF, .g = 0x33, .b = 0x66, .a = cb_pulse });
- ly += alert_h + 4;
- } else if (agent.cb_state == .degraded) {
- const alert_h: f32 = 24 * fs;
- rl.DrawRectangleRounded(.{ .x = cx, .y = ly, .width = content_w, .height = alert_h }, 0.1, 8, rl.Color{ .r = 0xFF, .g = 0xAA, .b = 0x00, .a = 30 });
- rl.DrawTextEx(chat_font, "DEGRADED β reduced rate", .{ .x = cx + 12, .y = ly + 4 }, 13 * fs, 0.5, rl.Color{ .r = 0xFF, .g = 0xAA, .b = 0x00, .a = alpha_u8 });
- ly += alert_h + 4;
- }
-
- // Task bar + buttons + status pill
- {
- const bar_h: f32 = 36 * fs;
- rl.DrawRectangleRoundedLines(.{ .x = cx, .y = ly, .width = content_w, .height = bar_h }, 0.06, 8, rl.Color{ .r = 0x22, .g = 0x22, .b = 0x28, .a = 120 });
-
- // Task text (left side, clipped)
- const task_w = content_w * 0.42;
- rl.BeginScissorMode(@intFromFloat(cx + 10), @intFromFloat(ly), @intFromFloat(task_w), @intFromFloat(bar_h));
- rl.DrawTextEx(chat_font, &agent.goal, .{ .x = cx + 12, .y = ly + 10 * fs }, 12 * fs, 0.5, bright_text);
- rl.EndScissorMode();
-
- // Buttons (center)
- const btn_section_x = cx + task_w + 16;
- const btn_w: f32 = 70 * fs;
- const btn_h: f32 = 24 * fs;
- const btn_y_pos = ly + (bar_h - btn_h) / 2;
- const btn_gap: f32 = 8;
-
- // Hotkey: K = Kill/STOP all ralph processes (emergency stop)
- if (rl.IsKeyPressed(rl.KEY_K)) {
- g_ralph_pending_cmd = .stop;
- ralphExecPendingCmd();
- }
-
- // START
- {
- const bx = btn_section_x;
- const br = rl.Rectangle{ .x = bx, .y = btn_y_pos, .width = btn_w, .height = btn_h };
- const hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, br);
- const active = !agent.running;
- const c = if (active) ralph_green else dim_text;
- const bg_a: u8 = if (hover and active) 40 else 15;
- rl.DrawRectangleRounded(br, 0.3, 8, rl.Color{ .r = c.r, .g = c.g, .b = c.b, .a = bg_a });
- rl.DrawRectangleRoundedLines(br, 0.3, 8, c);
- const start_sz = rl.MeasureTextEx(chat_font, "START", 12 * fs, 0.5);
- rl.DrawTextEx(chat_font, "START", .{ .x = bx + (btn_w - start_sz.x) / 2, .y = btn_y_pos + (btn_h - start_sz.y) / 2 }, 12 * fs, 0.5, c);
- if (hover and mouse_pressed and active) {
- g_ralph_pending_cmd = .start;
- agent.running = true;
- agent.is_healthy = true;
- agent.cb_state = .closed;
- ralphExecPendingCmd();
- }
- }
- // STOP
- {
- const bx = btn_section_x + btn_w + btn_gap;
- const br = rl.Rectangle{ .x = bx, .y = btn_y_pos, .width = btn_w, .height = btn_h };
- const hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, br);
- // STOP is always clickable - check actual processes in handler
- const c = ralph_red;
- const bg_a: u8 = if (hover) 40 else 15;
- rl.DrawRectangleRounded(br, 0.3, 8, rl.Color{ .r = c.r, .g = c.g, .b = c.b, .a = bg_a });
- rl.DrawRectangleRoundedLines(br, 0.3, 8, c);
- const stop_sz = rl.MeasureTextEx(chat_font, "STOP", 12 * fs, 0.5);
- rl.DrawTextEx(chat_font, "STOP", .{ .x = bx + (btn_w - stop_sz.x) / 2, .y = btn_y_pos + (btn_h - stop_sz.y) / 2 }, 12 * fs, 0.5, c);
- if (hover and mouse_pressed) {
- g_ralph_pending_cmd = .stop;
- ralphExecPendingCmd();
- }
- }
- // RESTART
- {
- const bx = btn_section_x + (btn_w + btn_gap) * 2;
- const br = rl.Rectangle{ .x = bx, .y = btn_y_pos, .width = btn_w + 10 * fs, .height = btn_h };
- const hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, br);
- const c = ralph_accent;
- const bg_a: u8 = if (hover) 40 else 15;
- rl.DrawRectangleRounded(br, 0.3, 8, rl.Color{ .r = c.r, .g = c.g, .b = c.b, .a = bg_a });
- rl.DrawRectangleRoundedLines(br, 0.3, 8, c);
- const rst_w = btn_w + 10 * fs;
- const rst_sz = rl.MeasureTextEx(chat_font, "RESTART", 12 * fs, 0.5);
- rl.DrawTextEx(chat_font, "RESTART", .{ .x = bx + (rst_w - rst_sz.x) / 2, .y = btn_y_pos + (btn_h - rst_sz.y) / 2 }, 12 * fs, 0.5, c);
- if (hover and mouse_pressed) {
- g_ralph_pending_cmd = .restart;
- agent.running = true;
- agent.is_healthy = true;
- agent.cb_state = .closed;
- ralphExecPendingCmd();
- }
- }
-
- // v8.6: Glassmorphism STATUS pill (right side)
- {
- const pill_right = cx + content_w - 8;
- const pill_w: f32 = 140 * fs;
- const pill_x = pill_right - pill_w;
- const pill_y = ly + (bar_h - 28 * fs) / 2;
-
- // v8.6: Determine display state for glassmorphism pill
- const actually_running = ralphProcessRunning();
- const display_state: CircuitBreakerState = if (agent.rate_limited or agent.cb_state == .cb_open)
- .cb_open
- else if (agent.is_executing and actually_running)
- .closed
- else
- .degraded;
-
- drawStatusPill(pill_x, pill_y, display_state, fs, chat_font);
-
- // v8.6: Loop counter text (small, after status pill)
- var loop_buf: [32:0]u8 = undefined;
- @memset(&loop_buf, 0);
- _ = std.fmt.bufPrint(&loop_buf, "L#{d}", .{agent.loop}) catch {};
- const loop_sz = rl.MeasureTextEx(chat_font, &loop_buf, 10 * fs, 0.5);
- const loop_x = pill_x - loop_sz.x - 8;
- rl.DrawTextEx(chat_font, &loop_buf, .{ .x = loop_x, .y = ly + 11 * fs }, 10 * fs, 0.5, dim_text);
-
- // v8.6: LIVE indicator (pulsing dot) β only if actually running
- if (actually_running and agent.is_executing and agent.data_age_seconds < 30) {
- const live_pulse: u8 = @intFromFloat(180.0 + 75.0 * @sin(frame_time * 6.0));
- const live_x = loop_x - 12;
- rl.DrawCircle(@intFromFloat(live_x), @intFromFloat(ly + bar_h / 2), 3 * fs, rl.Color{ .r = 0xFF, .g = 0x00, .b = 0x00, .a = live_pulse });
- }
-
- // v8.6: Hover popover for full status (use pill_x as left edge)
- const hover_rect_left = pill_x - 10;
- const pill_rect = rl.Rectangle{ .x = hover_rect_left, .y = ly, .width = pill_right - hover_rect_left + 10, .height = bar_h };
- const pill_hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, pill_rect);
- if (pill_hover) {
- // v8.6: Status label/color for popover
- const sm_age = agent.data_age_seconds;
- const st_label: [*:0]const u8 = if (agent.rate_limited)
- "RATE LIMITED"
- else if (agent.cb_state == .cb_open)
- "ERROR"
- else if (agent.is_executing and actually_running)
- "ACTIVE"
- else if (!actually_running)
- "STOPPED"
- else if (sm_age < 120)
- "IDLE"
- else if (sm_age < 1800)
- "PAUSED"
- else
- "STOPPED";
- const st_color = if (agent.rate_limited)
- ralph_red
- else if (agent.cb_state == .cb_open)
- ralph_red
- else if (agent.is_executing and actually_running)
- ralph_green
- else if (!actually_running)
- ralph_red
- else if (sm_age < 120)
- ralph_accent
- else
- dim_text;
-
- // Draw popover below the bar
- const pop_x = cx + content_w - 200 * fs;
- const pop_y = ly + bar_h + 4;
- const pop_w: f32 = 195 * fs;
- const pop_h: f32 = 120 * fs;
- const pop_row: f32 = 15 * fs;
- rl.DrawRectangleRounded(.{ .x = pop_x, .y = pop_y, .width = pop_w, .height = pop_h }, 0.08, 8, ralph_card_bg);
- rl.DrawRectangleRoundedLines(.{ .x = pop_x, .y = pop_y, .width = pop_w, .height = pop_h }, 0.08, 8, ralph_border);
- var py = pop_y + 8;
- // Status
- rl.DrawTextEx(chat_font, "Status:", .{ .x = pop_x + 8, .y = py }, 11 * fs, 0.5, dim_text);
- rl.DrawTextEx(chat_font, st_label, .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, st_color);
- py += pop_row;
- // CB
- rl.DrawTextEx(chat_font, "CB:", .{ .x = pop_x + 8, .y = py }, 11 * fs, 0.5, dim_text);
- rl.DrawTextEx(chat_font, agent.cb_state.getLabel(), .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, agent.cb_state.getColor(alpha_u8));
- py += pop_row;
- // Calls
- rl.DrawTextEx(chat_font, "Calls:", .{ .x = pop_x + 8, .y = py }, 11 * fs, 0.5, dim_text);
- {
- var cbuf2: [32:0]u8 = undefined;
- @memset(&cbuf2, 0);
- _ = std.fmt.bufPrint(&cbuf2, "{d}/{d}", .{ agent.calls_this_hour, agent.max_calls_hour }) catch {};
- rl.DrawTextEx(chat_font, &cbuf2, .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, bright_text);
- }
- py += pop_row;
- // Updated
- rl.DrawTextEx(chat_font, "Updated:", .{ .x = pop_x + 8, .y = py }, 11 * fs, 0.5, dim_text);
- {
- var abuf2: [32:0]u8 = undefined;
- @memset(&abuf2, 0);
- if (sm_age <= 0) {
- _ = std.fmt.bufPrint(&abuf2, "now", .{}) catch {};
- } else if (sm_age < 60) {
- _ = std.fmt.bufPrint(&abuf2, "{d}s ago", .{@as(u64, @intCast(sm_age))}) catch {};
- } else if (sm_age < 3600) {
- _ = std.fmt.bufPrint(&abuf2, "{d}m ago", .{@as(u64, @intCast(@divFloor(sm_age, 60)))}) catch {};
- } else {
- _ = std.fmt.bufPrint(&abuf2, "{d}h{d}m", .{ @as(u64, @intCast(@divFloor(sm_age, 3600))), @as(u64, @intCast(@mod(@divFloor(sm_age, 60), 60))) }) catch {};
- }
- const a_color2 = if (sm_age < 30) ralph_green else if (sm_age < 300) ralph_accent else ralph_red;
- rl.DrawTextEx(chat_font, &abuf2, .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, a_color2);
- }
- py += pop_row;
- // Progress
- rl.DrawTextEx(chat_font, "Progress:", .{ .x = pop_x + 8, .y = py }, 11 * fs, 0.5, dim_text);
- if (agent.progress_status_len > 0) {
- var psbuf2: [32:0]u8 = undefined;
- @memset(&psbuf2, 0);
- const psl2 = @min(agent.progress_status_len, 31);
- @memcpy(psbuf2[0..psl2], agent.progress_status[0..psl2]);
- rl.DrawTextEx(chat_font, &psbuf2, .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, bright_text);
- } else {
- rl.DrawTextEx(chat_font, "β", .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, dim_text);
- }
- py += pop_row;
- // Commits
- rl.DrawTextEx(chat_font, "Commits:", .{ .x = pop_x + 8, .y = py }, 11 * fs, 0.5, dim_text);
- if (agent.recent_commits_count > 0) {
- var cmbuf2: [32:0]u8 = undefined;
- @memset(&cmbuf2, 0);
- _ = std.fmt.bufPrint(&cmbuf2, "{d} recent", .{agent.recent_commits_count}) catch {};
- rl.DrawTextEx(chat_font, &cmbuf2, .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, ralph_green);
- } else {
- rl.DrawTextEx(chat_font, "β", .{ .x = pop_x + 70 * fs, .y = py }, 11 * fs, 0.5, dim_text);
- }
- }
- }
-
- ly += bar_h + 8;
- }
-
- // ββ v8.6: Unified Chat Area with Glassmorphism ββ
- const chat_top = ly;
- const chat_h = pane_bottom - chat_top;
-
- // v8.6: Glass card for chat area
- const chat_card = rl.Rectangle{ .x = cx, .y = chat_top, .width = content_w, .height = chat_h };
- drawGlassCard(chat_card, 12, GLASS_NEON_PURPLE);
-
- rl.BeginScissorMode(@intFromFloat(cx), @intFromFloat(chat_top), @intFromFloat(content_w), @intFromFloat(chat_h));
-
- const avatar_r: f32 = 14 * fs;
- const msg_font_sz: f32 = 13 * fs;
- const row_h: f32 = 22 * fs;
- const bubble_max_w = content_w * 0.65;
-
- var cy = chat_top + 8 - g_ralph_chat_scroll_y;
-
- if (agent.chat_count == 0) {
- // Empty state
- rl.DrawTextEx(chat_font, "Waiting for agent output...", .{ .x = cx + content_w / 2 - 100 * fs, .y = chat_top + chat_h / 2 - 10 }, 14 * fs, 0.5, dim_text);
- } else {
- var mi: usize = 0;
- while (mi < agent.chat_count) : (mi += 1) {
- const msg = &agent.chat_msgs[mi];
- if (cy > chat_top + chat_h + 100) break; // below visible
-
- const is_first_in_run = (mi == 0) or (agent.chat_msgs[mi - 1].sender != msg.sender);
-
- switch (msg.kind) {
- .log_line => {
- // v8.6: Left-aligned bubble for PHI (loop agent)
- if (cy + row_h > chat_top and cy < chat_top + chat_h) {
- const tag_color = rl.Color{ .r = msg.tag_r, .g = msg.tag_g, .b = msg.tag_b, .a = alpha_u8 };
-
- // v8.6: Glass avatar for PHI (only on first msg in run)
- if (is_first_in_run) {
- const ax = cx + avatar_r + 8;
- const ay = cy + row_h / 2;
- drawAvatar(ax, ay, avatar_r, true, chat_font, fs);
- }
-
- // Message area (no background)
- const bubble_x = cx + avatar_r * 2 + 18;
-
- // Colored dot
- if (msg.tag_r != 0xBB or msg.tag_g != 0xBB or msg.tag_b != 0xBB) {
- rl.DrawCircle(@intFromFloat(bubble_x + 8), @intFromFloat(cy + row_h * 0.4), 3, tag_color);
- }
-
- // Text
- rl.DrawTextEx(chat_font, &msg.text, .{ .x = bubble_x + 16, .y = cy + 3 }, msg_font_sz, 0.5, tag_color);
- }
- cy += row_h;
- },
-
- .meta_info => {
- // v8.6: Left-aligned metadata line (dim) for VIBEE
- if (cy + row_h > chat_top and cy < chat_top + chat_h) {
- const tx = cx + avatar_r * 2 + 18;
- rl.DrawTextEx(chat_font, &msg.text, .{ .x = tx, .y = cy + 4 }, 11 * fs, 0.5, dim_text);
-
- // v8.6: Glass avatar for VIBEE on first
- if (is_first_in_run) {
- const ax = cx + avatar_r + 8;
- const ay = cy + row_h / 2;
- drawAvatar(ax, ay, avatar_r, false, chat_font, fs);
- }
- }
- cy += row_h;
- },
-
- .task_list => {
- // v8.6: Left-aligned task card for VIBEE
- const task_row_h: f32 = 16 * fs;
- const card_h = @as(f32, @floatFromInt(agent.todo_count)) * task_row_h + 24;
- const card_x = cx + avatar_r * 2 + 18;
-
- if (cy + card_h > chat_top and cy < chat_top + chat_h) {
- // v8.6: Glass avatar for VIBEE on first
- if (is_first_in_run) {
- const ax = cx + avatar_r + 8;
- const ay = cy + 16;
- drawAvatar(ax, ay, avatar_r, false, chat_font, fs);
- }
-
- // Task card (no colored bg)
-
- // Header
- rl.DrawTextEx(chat_font, "TASKS", .{ .x = card_x + 10, .y = cy + 4 }, 11 * fs, 0.5, ralph_accent);
-
- // Items
- var ti: usize = 0;
- while (ti < agent.todo_count) : (ti += 1) {
- const ty_pos = cy + 20 + @as(f32, @floatFromInt(ti)) * task_row_h;
- if (ty_pos + task_row_h > chat_top + chat_h) break;
- const ts = agent.todo_statuses[ti];
- const ind: [*:0]const u8 = if (ts == 3) "+" else if (ts == 2) ">" else "o";
- const ind_c: rl.Color = if (ts == 3) ralph_green else if (ts == 2) tool_cyan else dim_text;
- const txt_c: rl.Color = if (ts == 3) dim_text else if (ts == 2) bright_text else dim_text;
- rl.DrawTextEx(chat_font, ind, .{ .x = card_x + 12, .y = ty_pos }, 11 * fs, 0.5, ind_c);
- rl.DrawTextEx(chat_font, &agent.todo_items[ti], .{ .x = card_x + 24, .y = ty_pos }, 11 * fs, 0.5, txt_c);
- }
- }
- cy += card_h + 4;
- },
-
- .claude_result => {
- // Left-aligned markdown bubble
- const bubble_w = bubble_max_w;
- const bubble_x = cx + avatar_r * 2 + 18;
-
- // v8.6: Glass avatar for VIBEE on first
- if (is_first_in_run) {
- if (cy + row_h > chat_top and cy < chat_top + chat_h) {
- const ax = cx + avatar_r + 8;
- const ay = cy + avatar_r;
- drawAvatar(ax, ay, avatar_r, false, chat_font, fs);
- }
- }
-
- // Inline markdown rendering (from live_result)
- if (msg.result_len > 0 and msg.result_offset + msg.result_len <= agent.live_result_len) {
- const result_text = agent.live_result[msg.result_offset .. msg.result_offset + msg.result_len];
- const text_color = if (agent.live_is_error) ralph_red else withAlpha(@as(rl.Color, @bitCast(theme.content_text)), alpha_u8);
- const base_font = msg_font_sz;
- const max_chars: usize = @intFromFloat(@max(20, (bubble_w - 32) / (7.5 * fs)));
- var pos: usize = 0;
- var in_code_block: bool = false;
- var consecutive_empty: u32 = 0;
- const ToolId = enum { none, bash, read, glob, grep, write, edit, todo };
- var prev_tool_id: ToolId = .none;
- var prev_tool_color: rl.Color = dim_text;
- var tool_run_count: u32 = 0;
- const row_h_md: f32 = 20 * fs;
-
- // v8.1: Collapsible section state
- var section_idx: usize = 0;
- var in_collapsed: bool = false;
- var sec_anim: f32 = 1.0;
- var visible_lines: u32 = 0;
- const ai_idx = g_ralph_active_tab;
-
- // Claude result area (no colored bg)
-
- while (pos < result_text.len) {
- const remaining = result_text[pos..];
- var line_end: usize = @min(remaining.len, max_chars);
- for (remaining[0..line_end], 0..) |c, ci| {
- if (c == '\\' and ci + 1 < line_end and remaining[ci + 1] == 'n') {
- line_end = ci;
- break;
- }
- }
- const line_data = remaining[0..line_end];
-
- var render_text = line_data;
- var line_color = text_color;
- var font_sz = base_font;
- var x_offset: f32 = 12;
- var extra_spacing: f32 = 0;
- var is_tool = false;
- var cur_tool_id: ToolId = .none;
- var is_separator = false;
- var draw_underline = false;
- var is_code = in_code_block;
- var is_header = false;
-
- if (line_data.len >= 3 and line_data[0] == '`' and line_data[1] == '`' and line_data[2] == '`') {
- in_code_block = !in_code_block;
- is_code = in_code_block;
- render_text = if (line_data.len > 3) line_data[3..] else "";
- } else if (in_code_block) {
- is_code = true;
- } else if (line_data.len >= 4 and line_data[0] == '#' and line_data[1] == '#' and line_data[2] == '#' and line_data[3] == ' ') {
- render_text = line_data[4..];
- font_sz = 16 * fs;
- line_color = tool_yellow;
- extra_spacing = 4;
- is_header = true;
- } else if (line_data.len >= 3 and line_data[0] == '#' and line_data[1] == '#' and line_data[2] == ' ') {
- render_text = line_data[3..];
- font_sz = 18 * fs;
- line_color = tool_magenta;
- draw_underline = true;
- extra_spacing = 6;
- is_header = true;
- } else if (line_data.len >= 2 and line_data[0] == '#' and line_data[1] == ' ') {
- render_text = line_data[2..];
- font_sz = 22 * fs;
- line_color = tool_cyan;
- draw_underline = true;
- extra_spacing = 8;
- is_header = true;
- } else if (line_data.len >= 3) {
- const is_pure_sep = blk: {
- for (line_data) |ch| {
- if (ch != '-' and ch != '*' and ch != ' ') break :blk false;
- }
- break :blk true;
- };
- if (is_pure_sep) {
- is_separator = true;
- } else if (line_data.len >= 2 and (line_data[0] == '-' or line_data[0] == '*') and line_data[1] == ' ') {
- render_text = line_data[2..];
- x_offset = 28;
- line_color = text_color;
- } else {
- if (line_data.len > 4) {
- if (containsBytes(line_data, "[Glob]")) {
- line_color = tool_cyan;
- is_tool = true;
- cur_tool_id = .glob;
- } else if (containsBytes(line_data, "[Read]")) {
- line_color = tool_magenta;
- is_tool = true;
- cur_tool_id = .read;
- } else if (containsBytes(line_data, "[Grep]")) {
- line_color = tool_yellow;
- is_tool = true;
- cur_tool_id = .grep;
- } else if (containsBytes(line_data, "[Bash]")) {
- line_color = tool_orange;
- is_tool = true;
- cur_tool_id = .bash;
- } else if (containsBytes(line_data, "[Write]")) {
- line_color = tool_lime;
- is_tool = true;
- cur_tool_id = .write;
- } else if (containsBytes(line_data, "[Edit]")) {
- line_color = tool_pink;
- is_tool = true;
- cur_tool_id = .edit;
- } else if (containsBytes(line_data, "[Todo]")) {
- line_color = tool_blue;
- is_tool = true;
- cur_tool_id = .todo;
- }
- }
- if (line_data.len > 4 and containsBytes(line_data, "**")) {
- line_color = bright_text;
- }
- }
- } else if (line_data.len >= 2 and (line_data[0] == '-' or line_data[0] == '*') and line_data[1] == ' ') {
- render_text = line_data[2..];
- x_offset = 28;
- line_color = text_color;
- } else {
- if (line_data.len > 4 and containsBytes(line_data, "**")) {
- line_color = bright_text;
- }
- }
-
- if (is_tool) {
- if (std.mem.indexOfScalar(u8, render_text, '[')) |bracket_pos| {
- render_text = render_text[bracket_pos..];
- }
- }
-
- // Collapse empty lines
- if (render_text.len == 0 and !is_separator and !is_code) {
- consecutive_empty += 1;
- if (consecutive_empty > 1) {
- pos += line_end;
- if (pos < result_text.len and result_text[pos] == '\\' and pos + 1 < result_text.len and result_text[pos + 1] == 'n') pos += 2;
- continue;
- }
- cy += row_h_md * 0.25;
- pos += line_end;
- if (pos < result_text.len and result_text[pos] == '\\' and pos + 1 < result_text.len and result_text[pos + 1] == 'n') pos += 2;
- continue;
- }
- consecutive_empty = 0;
-
- // v8.1: Section collapse tracking
- if (is_header and section_idx < MAX_SECTIONS_PER_MSG) {
- in_collapsed = g_ralph_section_collapsed[ai_idx][mi][section_idx];
- sec_anim = g_ralph_section_anim[ai_idx][mi][section_idx];
- }
-
- // v8.1: Progressive disclosure (show more / show less)
- visible_lines += 1;
- if (!msg.show_full and visible_lines > 15 and !is_header) {
- if (visible_lines == 16) {
- if (cy + row_h_md > chat_top and cy < chat_top + chat_h) {
- const sm_rect = rl.Rectangle{ .x = bubble_x + 12, .y = cy, .width = 120 * fs, .height = row_h_md };
- const sm_hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, sm_rect);
- const sm_color = if (sm_hover) tool_cyan else ralph_accent;
- rl.DrawTextEx(chat_font, "Show more...", .{ .x = bubble_x + 12, .y = cy }, base_font, 0.5, sm_color);
- if (sm_hover) rl.DrawRectangle(@intFromFloat(bubble_x + 12), @intFromFloat(cy + base_font + 1), @intFromFloat(80 * fs), 1, sm_color);
- if (sm_hover and mouse_pressed) msg.show_full = true;
- }
- cy += row_h_md;
- }
- pos += line_end;
- if (pos < result_text.len and result_text[pos] == '\\' and pos + 1 < result_text.len and result_text[pos + 1] == 'n') pos += 2;
- continue;
- }
-
- // v8.1: Section collapse skip
- if (!is_header and in_collapsed and sec_anim < 0.01) {
- pos += line_end;
- if (pos < result_text.len and result_text[pos] == '\\' and pos + 1 < result_text.len and result_text[pos + 1] == 'n') pos += 2;
- continue;
- }
-
- // Tool grouping
- if (is_tool and cur_tool_id != .none) {
- if (cur_tool_id == prev_tool_id) {
- tool_run_count += 1;
- pos += line_end;
- if (pos < result_text.len and result_text[pos] == '\\' and pos + 1 < result_text.len and result_text[pos + 1] == 'n') pos += 2;
- continue;
- } else {
- if (tool_run_count > 1 and prev_tool_id != .none) {
- if (cy + row_h_md > chat_top and cy < chat_top + chat_h) {
- rl.DrawRectangle(@intFromFloat(bubble_x + 4), @intFromFloat(cy + 2), 3, @intFromFloat(row_h_md - 4), prev_tool_color);
- var grp_buf: [48:0]u8 = undefined;
- @memset(&grp_buf, 0);
- _ = std.fmt.bufPrint(&grp_buf, " ... (x{d} more)", .{tool_run_count}) catch {};
- rl.DrawTextEx(chat_font, &grp_buf, .{ .x = bubble_x + 12, .y = cy }, base_font, 0.5, rl.Color{ .r = prev_tool_color.r, .g = prev_tool_color.g, .b = prev_tool_color.b, .a = 120 });
- }
- cy += row_h_md;
- }
- prev_tool_id = cur_tool_id;
- prev_tool_color = line_color;
- tool_run_count = 0;
- }
- } else {
- if (tool_run_count > 1 and prev_tool_id != .none) {
- if (cy + row_h_md > chat_top and cy < chat_top + chat_h) {
- rl.DrawRectangle(@intFromFloat(bubble_x + 4), @intFromFloat(cy + 2), 3, @intFromFloat(row_h_md - 4), prev_tool_color);
- var grp_buf2: [48:0]u8 = undefined;
- @memset(&grp_buf2, 0);
- _ = std.fmt.bufPrint(&grp_buf2, " ... (x{d} more)", .{tool_run_count}) catch {};
- rl.DrawTextEx(chat_font, &grp_buf2, .{ .x = bubble_x + 12, .y = cy }, base_font, 0.5, rl.Color{ .r = prev_tool_color.r, .g = prev_tool_color.g, .b = prev_tool_color.b, .a = 120 });
- }
- cy += row_h_md;
- }
- prev_tool_id = .none;
- tool_run_count = 0;
- }
-
- const md_row_h = row_h_md + extra_spacing;
- // v8.1: Animated height for collapsing content
- const effective_row_h = if (!is_header and sec_anim < 1.0 and sec_anim > 0.0) md_row_h * sec_anim else md_row_h;
-
- if (cy + effective_row_h > chat_top and cy < chat_top + chat_h) {
- // v8.1: Triangle indicator + click for headers
- if (is_header and section_idx < MAX_SECTIONS_PER_MSG) {
- const tri_x = bubble_x + 2;
- const tri_cy = cy + font_sz / 2;
- const tri_sz: f32 = 4 * fs;
- const tri_color = rl.Color{ .r = line_color.r, .g = line_color.g, .b = line_color.b, .a = 160 };
- if (in_collapsed) {
- // Right-pointing triangle (collapsed)
- rl.DrawTriangle(
- .{ .x = tri_x, .y = tri_cy + tri_sz },
- .{ .x = tri_x, .y = tri_cy - tri_sz },
- .{ .x = tri_x + tri_sz * 1.5, .y = tri_cy },
- tri_color,
- );
- } else {
- // Down-pointing triangle (expanded)
- rl.DrawTriangle(
- .{ .x = tri_x + tri_sz, .y = tri_cy - tri_sz * 0.5 },
- .{ .x = tri_x - tri_sz * 0.5, .y = tri_cy - tri_sz * 0.5 },
- .{ .x = tri_x + tri_sz * 0.25, .y = tri_cy + tri_sz },
- tri_color,
- );
- }
- // Click hitbox on header row
- const hdr_rect = rl.Rectangle{ .x = bubble_x, .y = cy, .width = bubble_w, .height = md_row_h };
- if (rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, hdr_rect) and mouse_pressed) {
- g_ralph_section_collapsed[ai_idx][mi][section_idx] = !g_ralph_section_collapsed[ai_idx][mi][section_idx];
- in_collapsed = g_ralph_section_collapsed[ai_idx][mi][section_idx];
- }
- // Left border on header
- rl.DrawRectangle(@intFromFloat(bubble_x), @intFromFloat(cy), 2, @intFromFloat(md_row_h), rl.Color{ .r = line_color.r, .g = line_color.g, .b = line_color.b, .a = 40 });
- section_idx += 1;
- }
- // v8.1: Section left border for content
- if (!is_header and section_idx > 0 and !is_tool and !is_separator) {
- rl.DrawRectangle(@intFromFloat(bubble_x), @intFromFloat(cy), 2, @intFromFloat(effective_row_h), rl.Color{ .r = 0x44, .g = 0x44, .b = 0x55, .a = 30 });
- }
- if (is_separator) {
- const sep_y = cy + md_row_h / 2;
- rl.DrawRectangle(@intFromFloat(bubble_x + 12), @intFromFloat(sep_y), @intFromFloat(bubble_w - 24), 1, rl.Color{ .r = 0x00, .g = 0xFF, .b = 0xFF, .a = 60 });
- } else if (render_text.len > 0) {
- if (is_code) {
- rl.DrawRectangle(@intFromFloat(bubble_x + 8), @intFromFloat(cy), @intFromFloat(bubble_w - 16), @intFromFloat(md_row_h), rl.Color{ .r = 0x10, .g = 0x10, .b = 0x18, .a = 200 });
- line_color = tool_lime;
- }
- // v8.6: Glassmorphism tool pill with emoji
- if (is_tool) {
- const tool_name = switch (cur_tool_id) {
- .glob => "Glob",
- .read => "Read",
- .grep => "Grep",
- .bash => "Bash",
- .write => "Write",
- .edit => "Edit",
- .todo => "Todo",
- else => "Tool",
- };
- drawToolPill(bubble_x + 4, cy, tool_name, line_color, fs, chat_font);
- }
- if (x_offset > 12) {
- rl.DrawCircle(@intFromFloat(bubble_x + 18), @intFromFloat(cy + font_sz / 2), 3, tool_cyan);
- }
- // Render text (strip ** and tool brackets)
- var md_buf: [128:0]u8 = undefined;
- @memset(&md_buf, 0);
- var stripped2: [128]u8 = undefined;
- var s2i: usize = 0;
- var r2i: usize = 0;
-
- // v8.6: Skip tool bracket [ToolName] at start
- if (is_tool and render_text.len > 0) {
- // Skip past the bracket
- if (std.mem.indexOfScalar(u8, render_text[r2i..], ']')) |close_bracket| {
- r2i += close_bracket + 1;
- // Skip trailing space if present
- if (r2i < render_text.len and render_text[r2i] == ' ') r2i += 1;
- }
- }
-
- // v8.6: Adjust text position after tool pill
- const text_x_offset = if (is_tool) 92 * fs else x_offset;
-
- while (r2i < render_text.len and s2i < 127) {
- if (r2i + 1 < render_text.len and render_text[r2i] == '*' and render_text[r2i + 1] == '*') {
- r2i += 2;
- } else {
- stripped2[s2i] = render_text[r2i];
- s2i += 1;
- r2i += 1;
- }
- }
- const cl2 = @min(s2i, 127);
- @memcpy(md_buf[0..cl2], stripped2[0..cl2]);
- rl.DrawTextEx(chat_font, &md_buf, .{ .x = bubble_x + text_x_offset, .y = cy }, font_sz, 0.5, line_color);
- if (draw_underline) {
- const uw2 = @min(bubble_w * 0.6, @as(f32, @floatFromInt(cl2)) * font_sz * 0.55);
- rl.DrawRectangle(@intFromFloat(bubble_x + text_x_offset), @intFromFloat(cy + font_sz + 2), @intFromFloat(uw2), 2, rl.Color{ .r = line_color.r, .g = line_color.g, .b = line_color.b, .a = 80 });
- }
- }
- }
- cy += effective_row_h;
- pos += line_end;
- if (pos < result_text.len and result_text[pos] == '\\' and pos + 1 < result_text.len and result_text[pos + 1] == 'n') pos += 2;
- }
- // v8.1: "Show less" link
- if (msg.show_full and visible_lines > 15) {
- if (cy + row_h_md > chat_top and cy < chat_top + chat_h) {
- const sl_rect = rl.Rectangle{ .x = bubble_x + 12, .y = cy, .width = 100 * fs, .height = row_h_md };
- const sl_hover = rl.CheckCollisionPointRec(.{ .x = mx, .y = my }, sl_rect);
- const sl_color = if (sl_hover) tool_cyan else ralph_accent;
- rl.DrawTextEx(chat_font, "Show less", .{ .x = bubble_x + 12, .y = cy }, base_font, 0.5, sl_color);
- if (sl_hover) rl.DrawRectangle(@intFromFloat(bubble_x + 12), @intFromFloat(cy + base_font + 1), @intFromFloat(65 * fs), 1, sl_color);
- if (sl_hover and mouse_pressed) msg.show_full = false;
- }
- cy += row_h_md;
- }
- } else {
- rl.DrawTextEx(chat_font, "Waiting for Claude output...", .{ .x = bubble_x + 12, .y = cy }, msg_font_sz, 0.5, dim_text);
- cy += row_h;
- }
- },
- }
- }
- }
-
- rl.EndScissorMode();
-
- // Scroll clamping + auto-scroll
- {
- const total_chat_h = cy + g_ralph_chat_scroll_y - (chat_top + 8);
- const max_scroll = @max(0.0, total_chat_h - chat_h + 16);
- g_ralph_chat_scroll_target = @min(g_ralph_chat_scroll_target, max_scroll);
- g_ralph_chat_scroll_target = @max(0.0, g_ralph_chat_scroll_target);
- g_ralph_chat_scroll_y = @min(g_ralph_chat_scroll_y, max_scroll + 10 * fs);
-
- // Auto-scroll on new content
- if (agent.chat_count != g_ralph_prev_chat_count) {
- if (g_ralph_chat_scroll_target >= max_scroll - 50 or g_ralph_prev_chat_count == 0) {
- g_ralph_chat_scroll_target = max_scroll;
- }
- g_ralph_prev_chat_count = agent.chat_count;
- }
- }
-
- // Mouse wheel
- {
- const cmx = @as(f32, @floatFromInt(rl.GetMouseX()));
- const cmy = @as(f32, @floatFromInt(rl.GetMouseY()));
- if (cmx >= margin and cmx <= cx + content_w and cmy >= chat_top and cmy <= chat_top + chat_h) {
- g_ralph_chat_scroll_target -= rl.GetMouseWheelMove() * 40.0 * fs;
- g_ralph_chat_scroll_target = @max(0.0, g_ralph_chat_scroll_target);
- }
- }
-
- // Stale data overlay
- if (agent.data_age_seconds > 300) {
- const stale_y = pane_bottom - 30 * fs;
- const blink_a: u8 = @intFromFloat(120.0 + 80.0 * @sin(frame_time * 3.0));
- var stale_buf: [64:0]u8 = undefined;
- @memset(&stale_buf, 0);
- _ = std.fmt.bufPrint(&stale_buf, "Last activity: {d}m ago", .{@as(u64, @intCast(@divFloor(agent.data_age_seconds, 60)))}) catch {};
- rl.DrawTextEx(chat_font, &stale_buf, .{ .x = cx + content_w / 2 - 80 * fs, .y = stale_y }, 12 * fs, 0.5, rl.Color{ .r = 0xFF, .g = 0x00, .b = 0xFF, .a = blink_a });
- }
- }
-
- // Keyboard hint at bottom
- rl.DrawTextEx(chat_font, "1-4: Agent | >: Switch | Shift+9: Toggle | Shift+0: Home", .{ .x = margin, .y = sh - 28 * fs }, 11 * fs, 0.5, dim_text);
- }
- }
-
- // Legacy panels (hidden when wave mode active, kept for backward compat)
- if (g_wave_mode == .idle) {
- frame_panels.draw(frame_time, frame_font);
- }
-
- // Keyboard hint (minimal, top-left) β skip in DePIN for clean UI
- if (g_wave_mode == .idle) {
- rl.DrawTextEx(frame_font_small, "Shift+1 Chat | 2 Code | 3 Tools | 4 Settings | D DePIN | ESC", .{ .x = 10, .y = 10 }, 13, 1, withAlpha(TEXT_DIM, 180));
- } else if (g_wave_mode != .depin and g_wave_mode != .ralph) {
- rl.DrawTextEx(frame_font_small, "ESC = back | Shift+1-6 switch mode", .{ .x = 10, .y = 10 }, 13, 1, withAlpha(TEXT_DIM, 140));
- }
-
- // === SUN/MOON THEME TOGGLE (top-right, 20px from top) ===
- {
- const toggle_cx: f32 = @as(f32, @floatFromInt(g_width)) - 35;
- const toggle_cy: f32 = 30; // 20px margin from top + radius
- const toggle_r: f32 = 10;
- if (theme.isDark()) {
- // Crescent moon: white circle + bg-colored circle offset
- const moon_color = rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 220 };
- rl.DrawCircle(@intFromFloat(toggle_cx), @intFromFloat(toggle_cy), toggle_r, moon_color);
- rl.DrawCircle(@intFromFloat(toggle_cx + 5), @intFromFloat(toggle_cy - 3), toggle_r - 1, @as(rl.Color, @bitCast(theme.clear_bg)));
- } else {
- // Sun: black on light theme (visible on white background)
- const sun_color = rl.Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 220 };
- rl.DrawCircle(@intFromFloat(toggle_cx), @intFromFloat(toggle_cy), toggle_r - 2, sun_color);
- var ray: usize = 0;
- while (ray < 8) : (ray += 1) {
- const angle = @as(f32, @floatFromInt(ray)) * (TAU / 8.0);
- const rx1 = toggle_cx + @cos(angle) * (toggle_r + 1);
- const ry1 = toggle_cy + @sin(angle) * (toggle_r + 1);
- const rx2 = toggle_cx + @cos(angle) * (toggle_r + 5);
- const ry2 = toggle_cy + @sin(angle) * (toggle_r + 5);
- rl.DrawLineEx(.{ .x = rx1, .y = ry1 }, .{ .x = rx2, .y = ry2 }, 1.5, sun_color);
- }
- }
- }
-
- // === STATUS BAR (Hyper terminal style, bottom) ===
- const status_bar_h: f32 = 24;
- const status_y: f32 = @as(f32, @floatFromInt(g_height)) - status_bar_h;
-
- // Status bar background (Hyper style)
- rl.DrawRectangle(0, @intFromFloat(status_y), g_width, @intFromFloat(status_bar_h), withAlpha(BG_SURFACE, 240));
- rl.DrawLine(0, @intFromFloat(status_y), g_width, @intFromFloat(status_y), BORDER_SUBTLE);
-
- // Get system stats (simulated with realistic values)
- const cpu_usage: f32 = 15.0 + @sin(frame_time * 0.5) * 10;
- const mem_used: f32 = 8.2 + @sin(frame_time * 0.3) * 0.5;
- _ = @as(f32, 16.0); // mem_total (unused in rainbow mode)
- const cpu_temp: f32 = 42.0 + @sin(frame_time * 0.7) * 5;
- const disk_used: f32 = 256.0;
- _ = @as(f32, 512.0); // disk_total (unused in rainbow mode)
- const net_down: f32 = 1.2 + @abs(@sin(frame_time * 0.8)) * 2;
- const net_up: f32 = 0.3 + @abs(@sin(frame_time * 0.6)) * 0.5;
- const processes: u32 = 234;
- const uptime_sec: u32 = @intFromFloat(frame_time);
-
- var stat_buf: [64:0]u8 = undefined;
- const sw = @as(f32, @floatFromInt(g_width));
-
- // Status bar text: rainbow on dark, dark text on light
- const stat_text_color = if (theme.isDark()) @as(?rl.Color, null) else TEXT_WHITE; // null = use per-stat color
-
- // Left: TRINITY label
- rl.DrawTextEx(frame_font_small, "TRINITY", .{ .x = 12, .y = status_y + 5 }, 13, 0.5, stat_text_color orelse HYPER_GREEN);
-
- // All stats aligned to RIGHT, close together
- const spacing: f32 = 75;
- var x_pos: f32 = sw - 12; // Start from right edge
-
- // Time (rightmost)
- var time_buf: [16:0]u8 = undefined;
- const display_time = @mod(@as(u32, @intFromFloat(frame_time)), 86400);
- const hours = display_time / 3600;
- const minutes = (display_time % 3600) / 60;
- const seconds = display_time % 60;
- _ = std.fmt.bufPrintZ(&time_buf, "{d:0>2}:{d:0>2}:{d:0>2}", .{ hours, minutes, seconds }) catch {};
- x_pos -= 70;
- rl.DrawTextEx(frame_font_small, &time_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse HYPER_MAGENTA);
-
- // Uptime
- const up_hours = uptime_sec / 3600;
- const up_mins = (uptime_sec % 3600) / 60;
- _ = std.fmt.bufPrintZ(&stat_buf, "UP {d}h{d}m", .{ up_hours, up_mins }) catch {};
- x_pos -= spacing;
- rl.DrawTextEx(frame_font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse PURPLE);
-
- // Processes
- _ = std.fmt.bufPrintZ(&stat_buf, "PROC {d}", .{processes}) catch {};
- x_pos -= spacing;
- rl.DrawTextEx(frame_font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse BLUE);
-
- // NET
- _ = std.fmt.bufPrintZ(&stat_buf, "NET {d:.1}M", .{net_down + net_up}) catch {};
- x_pos -= spacing;
- rl.DrawTextEx(frame_font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse HYPER_CYAN);
-
- // DISK
- _ = std.fmt.bufPrintZ(&stat_buf, "DISK {d:.0}G", .{disk_used}) catch {};
- x_pos -= spacing + 10;
- rl.DrawTextEx(frame_font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse HYPER_GREEN);
-
- // TEMP
- _ = std.fmt.bufPrintZ(&stat_buf, "{d:.0}C", .{cpu_temp}) catch {};
- x_pos -= spacing - 30;
- rl.DrawTextEx(frame_font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse HYPER_YELLOW);
-
- // MEM
- _ = std.fmt.bufPrintZ(&stat_buf, "MEM {d:.1}G", .{mem_used}) catch {};
- x_pos -= spacing + 5;
- rl.DrawTextEx(frame_font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse ORANGE);
-
- // CPU
- _ = std.fmt.bufPrintZ(&stat_buf, "CPU {d:.0}%", .{cpu_usage}) catch {};
- x_pos -= spacing;
- rl.DrawTextEx(frame_font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse HYPER_RED);
-} // end updateDrawFrame
-
-// Custom input box with font
-fn drawInputBox(input: *const InputBuffer, font: rl.Font, time: f32) void {
- const box_y = g_height - 60;
- rl.DrawRectangle(0, box_y, g_width, 60, withAlpha(BG_INPUT, 220));
-
- if (!input.active) {
- rl.DrawTextEx(font, "Press C=Chat, G=Goal, X=Code", .{ .x = 20, .y = @floatFromInt(box_y + 18) }, 20, 1, MUTED_GRAY);
- return;
- }
-
- const label = switch (input.mode) {
- .chat => "CHAT> ",
- .goal => "GOAL> ",
- .code => "CODE> ",
- };
-
- // Label with bright color
- rl.DrawTextEx(font, label.ptr, .{ .x = 20, .y = @floatFromInt(box_y + 18) }, 22, 1, NEON_GREEN);
-
- // Text (sentinel-terminated array)
- var display_buf: [520:0]u8 = undefined;
- const display_len = @min(input.len, 500);
- @memcpy(display_buf[0..display_len], input.buffer[0..display_len]);
-
- // Cursor blink
- if (@mod(@as(u32, @intFromFloat(time * 3.0)), 2) == 0) {
- display_buf[display_len] = '_';
- display_buf[display_len + 1] = 0;
- } else {
- display_buf[display_len] = 0;
- }
-
- rl.DrawTextEx(font, &display_buf, .{ .x = 100, .y = @floatFromInt(box_y + 18) }, 22, 1, NOVA_WHITE);
-
- // Hint
- rl.DrawText("Enter=Send", g_width - 100, box_y + 22, 14, TEXT_HINT);
-}
-
-fn drawImmersiveGrid(grid: *photon.PhotonGrid, time: f32) void {
- for (0..grid.height) |y| {
- for (0..grid.width) |x| {
- const p = grid.get(x, y);
-
- if (@abs(p.amplitude) < 0.01) continue;
-
- const px: c_int = @intCast(x * @as(usize, @intCast(g_pixel_size)));
- const py: c_int = @intCast(y * @as(usize, @intCast(g_pixel_size)));
-
- const hue = @mod(p.hue + time * 20.0 + p.phase * 10.0, 360.0);
- const brightness = @min(1.0, @abs(p.amplitude));
-
- const rgb = hsvToRgb(hue, 0.8, brightness);
- const alpha: u8 = @intFromFloat(@min(255.0, @abs(p.amplitude) * 300.0));
-
- const color = rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = alpha };
-
- if (@abs(p.amplitude) > 0.5) {
- const glow_alpha: u8 = @intFromFloat(@min(100.0, @abs(p.amplitude) * 100.0));
- rl.DrawRectangle(px - 1, py - 1, g_pixel_size + 2, g_pixel_size + 2, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = glow_alpha });
- }
-
- rl.DrawRectangle(px, py, g_pixel_size - 1, g_pixel_size - 1, color);
- }
- }
-}
-
-fn drawPhotonCursor(x: f32, y: f32, hue: f32, time: f32) void {
- const px: c_int = @intFromFloat(x);
- const py: c_int = @intFromFloat(y);
-
- const rgb = hsvToRgb(hue, 1.0, 1.0);
- const pulse = (@sin(time * 5.0) + 1.0) * 0.5;
-
- rl.DrawCircle(px, py, 20 + pulse * 10, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = 30 });
- rl.DrawCircle(px, py, 12 + pulse * 5, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = 60 });
- rl.DrawCircleLines(px, py, 8 + pulse * 3, rl.Color{ .r = rgb[0], .g = rgb[1], .b = rgb[2], .a = 200 });
- rl.DrawCircleLines(px, py, 4 + pulse * 2, rl.Color{ .r = 255, .g = 255, .b = 255, .a = 255 });
- rl.DrawCircle(px, py, 2, rl.Color{ .r = 255, .g = 255, .b = 255, .a = 255 });
-}
-
-fn drawModeIndicator(mode: TrinityMode, time: f32) void {
- const label = switch (mode) {
- .idle => "EXPLORE",
- .chat => "CHAT",
- .code => "CODE",
- .vision => "VISION",
- .voice => "VOICE",
- .tools => "TOOLS",
- .autonomous => "AUTONOMOUS",
- };
-
- const color = switch (mode) {
- .idle => NEON_GREEN,
- .chat => NEON_CYAN,
- .code => NEON_PURPLE,
- .vision => NEON_MAGENTA,
- .voice => NEON_GOLD,
- .tools => NEON_CYAN,
- .autonomous => NEON_GOLD,
- };
-
- const alpha: u8 = @intFromFloat(150.0 + @sin(time * 2.0) * 50.0);
- const final_color = rl.Color{ .r = color.r, .g = color.g, .b = color.b, .a = alpha };
-
- rl.DrawText(label.ptr, g_width - 150, 20, 24, final_color);
-}
-
-fn hsvToRgb(h: f32, s: f32, v: f32) [3]u8 {
- const c = v * s;
- const x = c * (1.0 - @abs(@mod(h / 60.0, 2.0) - 1.0));
- const m = v - c;
-
- var r: f32 = 0;
- var g: f32 = 0;
- var b: f32 = 0;
-
- if (h < 60) {
- r = c;
- g = x;
- } else if (h < 120) {
- r = x;
- g = c;
- } else if (h < 180) {
- g = c;
- b = x;
- } else if (h < 240) {
- g = x;
- b = c;
- } else if (h < 300) {
- r = x;
- b = c;
- } else {
- r = c;
- b = x;
- }
-
- return .{
- @intFromFloat((r + m) * 255.0),
- @intFromFloat((g + m) * 255.0),
- @intFromFloat((b + m) * 255.0),
- };
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// v8.6: Aceternity Glassmorphism Helper Functions
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Draw a glassmorphism card with subtle glow and translucent background
-fn drawGlassCard(bounds: rl.Rectangle, radius: f32, glow_color: rl.Color) void {
- // Subtle glow layer
- const glow_bounds = rl.Rectangle{ .x = bounds.x - 4, .y = bounds.y - 4, .width = bounds.width + 8, .height = bounds.height + 8 };
- rl.DrawRectangleRounded(glow_bounds, radius, 8, withAlpha(glow_color, 30));
-
- // Glass background (translucent)
- const glass_bg = rl.Color{ .r = 20, .g = 20, .b = 35, .a = 180 };
- rl.DrawRectangleRounded(bounds, radius, 8, glass_bg);
-
- // Neon border (top gradient)
- const border_top = rl.Rectangle{ .x = bounds.x, .y = bounds.y, .width = bounds.width, .height = 2 };
- rl.DrawRectangleRec(border_top, rl.Color{ .r = 0x88, .g = 0x44, .b = 0xFF, .a = 200 });
-}
-
-/// Draw a chat bubble for PHI (left) or VIBEE (right) messages
-fn drawChatBubble(bounds: rl.Rectangle, is_phi: bool) void {
- const radius = 16.0;
- const bg_color = if (is_phi)
- rl.Color{ .r = 0x00, .g = 0x44, .b = 0x54, .a = 200 } // Cyan-dark
- else
- rl.Color{ .r = 0x54, .g = 0x00, .b = 0x54, .a = 200 }; // Purple-dark
-
- const accent = if (is_phi) GLASS_NEON_CYAN else GLASS_NEON_MAGENTA;
-
- // Shadow
- const shadow_bounds = rl.Rectangle{ .x = bounds.x + 4, .y = bounds.y + 4, .width = bounds.width, .height = bounds.height };
- rl.DrawRectangleRounded(shadow_bounds, radius, 8, withAlpha(accent, 50));
-
- // Background
- rl.DrawRectangleRounded(bounds, radius, 8, bg_color);
-
- // Accent strip (left for PHI, right for VIBEE)
- if (is_phi) {
- rl.DrawRectangleRec(.{ .x = bounds.x, .y = bounds.y, .width = 4, .height = bounds.height }, accent);
- } else {
- rl.DrawRectangleRec(.{ .x = bounds.x + bounds.width - 4, .y = bounds.y, .width = 4, .height = bounds.height }, accent);
- }
-}
-
-/// Draw a circular avatar with Ο (PHI) or Ο (VIBEE) symbol
-fn drawAvatar(center_x: f32, center_y: f32, radius: f32, is_phi: bool, font: rl.Font, fs: f32) void {
- const glow = if (is_phi) GLASS_NEON_CYAN else GLASS_NEON_MAGENTA;
-
- // v8.6: Glow ring (c_int for x,y, f32 for radius)
- const cx_int: c_int = @intFromFloat(center_x);
- const cy_int: c_int = @intFromFloat(center_y);
- rl.DrawCircle(cx_int, cy_int, radius + 4, withAlpha(glow, 60));
-
- // Main circle
- const circle_color = if (is_phi) rl.Color{ .r = 0x00, .g = 0x88, .b = 0x88, .a = 255 } else rl.Color{ .r = 0x88, .g = 0x00, .b = 0x88, .a = 255 };
- rl.DrawCircle(cx_int, cy_int, radius, circle_color);
-
- // Ξ¦ or Ξ¨ symbol (v8.6: use .ptr for C string)
- const symbol = if (is_phi) "Ξ¦" else "Ξ¨";
- const font_size = 14 * fs;
- const text_width = rl.MeasureTextEx(font, symbol.ptr, font_size, 0.5).x;
- rl.DrawTextEx(font, symbol.ptr, .{ .x = center_x - text_width / 2, .y = center_y - 10 * fs }, font_size, 0.5, rl.Color{ .r = 255, .g = 255, .b = 255, .a = 255 });
-}
-
-/// Draw a tool pill with glass effect (v8.6: emoji icons)
-fn drawToolPill(x: f32, y: f32, text: []const u8, tool_color: rl.Color, fs: f32, font: rl.Font) void {
- const pill_w: f32 = 80 * fs;
- const pill_h: f32 = 24 * fs;
- const radius = 12.0;
-
- // Glass background
- const bg = rl.Color{ .r = 20, .g = 20, .b = 35, .a = 200 };
- rl.DrawRectangleRounded(.{ .x = x, .y = y, .width = pill_w, .height = pill_h }, radius, 8, bg);
-
- // Accent strip (left side)
- rl.DrawRectangleRec(.{ .x = x, .y = y, .width = 4, .height = pill_h }, tool_color);
-
- // v8.6: Draw emoji icon using g_font_emoji
- const emoji_str = getToolEmoji(text);
- const emoji_size = 16 * fs;
- // Create null-terminated string for C FFI
- var emoji_buf: [8:0]u8 = undefined;
- @memset(&emoji_buf, 0);
- @memcpy(emoji_buf[0..emoji_str.len], emoji_str);
- rl.DrawTextEx(g_font_emoji, &emoji_buf, .{ .x = x + 10 * fs, .y = y + 4 * fs }, emoji_size, 0.5, tool_color);
-
- // Draw tool name (after emoji)
- var buf: [16:0]u8 = undefined;
- @memset(&buf, 0);
- const max_len = @min(text.len, 15);
- @memcpy(buf[0..max_len], text[0..max_len]);
- rl.DrawTextEx(font, &buf, .{ .x = x + 32, .y = y + 7 * fs }, 11 * fs, 0.5, rl.Color{ .r = 220, .g = 220, .b = 230, .a = 255 });
-}
-
-/// Get emoji icon for tool name (v8.6: UTF-8 emoji for display)
-fn getToolEmoji(tool: []const u8) []const u8 {
- if (std.mem.eql(u8, tool, "Glob")) return "π"; // U+1F50D
- if (std.mem.eql(u8, tool, "Read")) return "π"; // U+1F4F6
- if (std.mem.eql(u8, tool, "Grep")) return "π"; // U+1F50E
- if (std.mem.eql(u8, tool, "Bash")) return "β‘"; // U+26A1
- if (std.mem.eql(u8, tool, "Write")) return "βοΈ"; // U+270F
- if (std.mem.eql(u8, tool, "Edit")) return "π"; // U+1F504
- if (std.mem.eql(u8, tool, "Todo")) return "π"; // U+1F4CB
- return "β’";
-}
-
-/// Draw STATUS pill with pulsing dot and glass effect
-fn drawStatusPill(x: f32, y: f32, status: CircuitBreakerState, fs: f32, font: rl.Font) void {
- const pill_w = 120 * fs;
- const pill_h = 32 * fs;
-
- // Glass background
- const glass_bg = rl.Color{ .r = 20, .g = 20, .b = 35, .a = 180 };
- rl.DrawRectangleRounded(.{ .x = x, .y = y, .width = pill_w, .height = pill_h }, 16, 8, glass_bg);
-
- // Status indicator (pulsing dot)
- const pulse = @as(u8, @intFromFloat(@max(150, @min(255, @sin(rl.GetTime() * 4) * 60 + 200))));
- const status_color = switch (status) {
- .closed => rl.Color{ .r = 0x00, .g = 0xFF, .b = 0x66, .a = pulse }, // Green
- .degraded => rl.Color{ .r = 0xFF, .g = 0xAA, .b = 0x00, .a = pulse }, // Orange
- .cb_open => rl.Color{ .r = 0xFF, .g = 0x44, .b = 0x66, .a = pulse }, // Red
- };
- rl.DrawCircle(@intFromFloat(x + 20), @intFromFloat(y + pill_h / 2), 6, status_color);
-
- // Status text
- const status_text = switch (status) {
- .closed => "ONLINE",
- .degraded => "DEGRADED",
- .cb_open => "HALTED",
- };
- rl.DrawTextEx(font, status_text, .{ .x = x + 36, .y = y + 8 * fs }, 10 * fs, 0.5, rl.Color{ .r = 220, .g = 220, .b = 230, .a = 255 });
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
diff --git a/src/vsa/photon_trinity_canvas_wasm.zig b/src/vsa/photon_trinity_canvas_wasm.zig
deleted file mode 100644
index d65af30679..0000000000
--- a/src/vsa/photon_trinity_canvas_wasm.zig
+++ /dev/null
@@ -1,823 +0,0 @@
-// =============================================================================
-// TRINITY CANVAS WASM v1.0 - Minimal Emscripten-Compatible Build
-// Renders: 27-petal logo + 42 formula particles + theme toggle + status bar
-// Compile: zig build (with emscripten target) or native desktop fallback
-// phi^2 + 1/phi^2 = 3 = TRINITY
-// =============================================================================
-
-const std = @import("std");
-const builtin = @import("builtin");
-const theme = @import("trinity_canvas/theme.zig");
-const math = std.math;
-
-const rl = @cImport({
- @cInclude("raylib.h");
-});
-
-// Emscripten header (only on wasm target)
-const emc = if (builtin.os.tag == .emscripten)
- @cImport(@cInclude("emscripten/emscripten.h"))
-else
- struct {};
-
-// Chat engine stubs β mapped via build.zig to no-op modules for WASM
-const igla_chat = @import("igla_chat");
-const fluent_chat = @import("igla_fluent_chat");
-const igla_hybrid_chat = @import("igla_hybrid_chat");
-const tvc = @import("tvc_corpus");
-const auto_shard = @import("auto_shard");
-
-// =============================================================================
-// COSMIC CONSTANTS
-// =============================================================================
-
-const PHI: f32 = theme.PHI;
-const PHI_INV: f32 = theme.PHI_INV;
-const TAU: f32 = theme.TAU;
-
-// =============================================================================
-// GLOBAL STATE
-// =============================================================================
-
-var g_width: c_int = 1280;
-var g_height: c_int = 800;
-var g_font_scale: f32 = 1.0;
-var g_dpi_scale: f32 = 1.0;
-
-// Global chat engines (stub interfaces for WASM)
-var g_chat_engine: igla_chat.IglaLocalChat = igla_chat.IglaLocalChat.init();
-var g_fluent_engine: fluent_chat.FluentChatEngine = undefined;
-var g_hybrid_engine: ?igla_hybrid_chat.IglaHybridChat = null;
-
-// =============================================================================
-// COLOR HELPERS
-// =============================================================================
-
-fn toRl(c: theme.Color) rl.Color {
- return @bitCast(c);
-}
-
-fn withAlpha(c: rl.Color, alpha: u8) rl.Color {
- return rl.Color{ .r = c.r, .g = c.g, .b = c.b, .a = alpha };
-}
-
-fn accentText(accent: rl.Color, alpha: u8) rl.Color {
- return if (theme.isDark()) withAlpha(accent, alpha) else rl.Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = alpha };
-}
-
-// === SWITCHABLE surface colors (var -- re-read from theme on toggle) ===
-var BG_BLACK: rl.Color = @bitCast(theme.colors.bg);
-var TEXT_WHITE: rl.Color = @bitCast(theme.colors.text);
-var MUTED_GRAY: rl.Color = @bitCast(theme.colors.text_muted);
-var BORDER_SUBTLE: rl.Color = @bitCast(theme.colors.border);
-var VOID_BLACK: rl.Color = @bitCast(theme.colors.bg);
-var NOVA_WHITE: rl.Color = @bitCast(theme.colors.text);
-var BG_SURFACE: rl.Color = @bitCast(theme.colors.bg_surface);
-var TEXT_DIM: rl.Color = @bitCast(theme.colors.text_dim);
-var TEXT_HINT: rl.Color = @bitCast(theme.colors.text_hint);
-
-// === ACCENT colors (const -- same in dark and light) ===
-const HYPER_MAGENTA: rl.Color = @bitCast(theme.accents.magenta);
-const HYPER_CYAN: rl.Color = @bitCast(theme.accents.cyan);
-const HYPER_GREEN: rl.Color = @bitCast(theme.accents.green);
-const HYPER_YELLOW: rl.Color = @bitCast(theme.accents.yellow);
-const HYPER_RED: rl.Color = @bitCast(theme.accents.red);
-const NEON_GREEN: rl.Color = @bitCast(theme.accents.green);
-const GOLD: rl.Color = @bitCast(theme.accents.gold);
-const BLUE: rl.Color = @bitCast(theme.accents.blue);
-const ORANGE: rl.Color = @bitCast(theme.accents.orange);
-const PURPLE: rl.Color = @bitCast(theme.accents.purple);
-const LOGO_GREEN: rl.Color = @bitCast(theme.accents.logo_green);
-
-// Reload all var aliases from theme after toggle()
-fn reloadThemeAliases() void {
- BG_BLACK = @bitCast(theme.bg);
- TEXT_WHITE = @bitCast(theme.text);
- MUTED_GRAY = @bitCast(theme.text_muted);
- BORDER_SUBTLE = @bitCast(theme.border);
- VOID_BLACK = @bitCast(theme.bg);
- NOVA_WHITE = @bitCast(theme.text);
- BG_SURFACE = @bitCast(theme.bg_surface);
- TEXT_DIM = @bitCast(theme.text_dim);
- TEXT_HINT = @bitCast(theme.text_hint);
-}
-
-// =============================================================================
-// LOGO BLOCK + LOGO ANIMATION (27 petals -- exact copy from original)
-// =============================================================================
-
-const LogoBlock = struct {
- v: [5]rl.Vector2,
- count: u8,
- offset: rl.Vector2,
- rotation: f32,
- scale: f32,
- delay: f32,
- center: rl.Vector2,
- anim_vx: f32,
- anim_vy: f32,
- anim_vr: f32,
- push_x: f32,
- push_y: f32,
- push_rot: f32,
- vel_x: f32,
- vel_y: f32,
- vel_rot: f32,
-};
-
-const LogoAnimation = struct {
- blocks: [27]LogoBlock,
- time: f32,
- duration: f32,
- is_complete: bool,
- logo_scale: f32,
- logo_offset: rl.Vector2,
- hovered_block: i32,
- clicked_block: i32,
-
- const SVG_WIDTH: f32 = 596.0;
- const SVG_HEIGHT: f32 = 526.0;
- const SVG_CENTER_X: f32 = 298.0;
- const SVG_CENTER_Y: f32 = 263.0;
-
- pub fn init(screen_w: f32, screen_h: f32) LogoAnimation {
- var self = LogoAnimation{
- .blocks = undefined,
- .time = 0,
- .duration = 2.5,
- .is_complete = false,
- .logo_scale = @min(screen_w / SVG_WIDTH, screen_h / SVG_HEIGHT) * 0.35,
- .logo_offset = .{ .x = screen_w / 2, .y = screen_h / 2 },
- .hovered_block = -1,
- .clicked_block = -1,
- };
-
- // 27 blocks parsed from assets/999.svg
- const raw_blocks = [27][5][2]f32{
- .{ .{ 296.767, 435.228 }, .{ 236.563, 329.491 }, .{ 211.501, 373.56 }, .{ 296.767, 523.496 }, .{ 0, 0 } },
- .{ .{ 235.71, 328.065 }, .{ 177.201, 224.57 }, .{ 126.893, 224.57 }, .{ 210.755, 372.182 }, .{ 0, 0 } },
- .{ .{ 116.304, 118.557 }, .{ 175.824, 223.238 }, .{ 126.022, 223.26 }, .{ 42.177, 74.909 }, .{ 0, 0 } },
- .{ .{ 43.019, 73.555 }, .{ 117.106, 116.68 }, .{ 235.544, 116.68 }, .{ 211.46, 73.525 }, .{ 0, 0 } },
- .{ .{ 213.1, 73.52 }, .{ 237.875, 116.409 }, .{ 356.58, 116.741 }, .{ 381.646, 73.509 }, .{ 0, 0 } },
- .{ .{ 477.724, 116.854 }, .{ 358.701, 116.802 }, .{ 383.404, 73.803 }, .{ 550.969, 73.877 }, .{ 0, 0 } },
- .{ .{ 477.056, 118.915 }, .{ 418.023, 223.109 }, .{ 468.886, 223.131 }, .{ 553.143, 74.338 }, .{ 0, 0 } },
- .{ .{ 358.646, 327.197 }, .{ 384.221, 372.152 }, .{ 468.192, 224.521 }, .{ 416.976, 224.579 }, .{ 0, 0 } },
- .{ .{ 298.138, 434.656 }, .{ 357.793, 328.533 }, .{ 383.376, 373.808 }, .{ 298.138, 523.876 }, .{ 0, 0 } },
- .{ .{ 297.148, 352.965 }, .{ 260.326, 288.171 }, .{ 237.943, 327.796 }, .{ 297.148, 432.004 }, .{ 0, 0 } },
- .{ .{ 259.613, 286.78 }, .{ 224.371, 224.818 }, .{ 179.6, 224.818 }, .{ 237.048, 326.301 }, .{ 0, 0 } },
- .{ .{ 223.536, 223.354 }, .{ 187.285, 159.675 }, .{ 120.085, 120.508 }, .{ 178.781, 223.779 }, .{ 0, 0 } },
- .{ .{ 121.863, 119.193 }, .{ 187.937, 158.358 }, .{ 260.042, 158.355 }, .{ 237.348, 118.746 }, .{ 0, 0 } },
- .{ .{ 261.857, 158.313 }, .{ 333.559, 158.29 }, .{ 356.01, 118.829 }, .{ 239.269, 118.829 }, .{ 0, 0 } },
- .{ .{ 335.294, 158.3 }, .{ 407.736, 158.226 }, .{ 474.496, 118.923 }, .{ 357.761, 118.923 }, .{ 0, 0 } },
- .{ .{ 408.358, 159.547 }, .{ 372.034, 223.421 }, .{ 416.476, 223.315 }, .{ 475.012, 120.916 }, .{ 0, 0 } },
- .{ .{ 336.052, 286.778 }, .{ 358.165, 325.872 }, .{ 415.649, 224.808 }, .{ 371.244, 224.759 }, .{ 0, 0 } },
- .{ .{ 298.893, 352.826 }, .{ 335.156, 288.19 }, .{ 357.382, 327.328 }, .{ 298.893, 430.179 }, .{ 0, 0 } },
- .{ .{ 296.258, 272.716 }, .{ 282.337, 248.309 }, .{ 260.496, 286.972 }, .{ 296.258, 349.653 }, .{ 0, 0 } },
- .{ .{ 259.547, 285.675 }, .{ 281.633, 246.705 }, .{ 269.336, 225.016 }, .{ 225.274, 224.996 }, .{ 0, 0 } },
- .{ .{ 254.956, 199.798 }, .{ 268.406, 223.578 }, .{ 224.465, 223.598 }, .{ 189.037, 161.206 }, .{ 0, 0 } },
- .{ .{ 255.476, 198.549 }, .{ 282.068, 198.538 }, .{ 260.192, 160.039 }, .{ 189.751, 160.07 }, .{ 0, 0 } },
- .{ .{ 261.646, 160.062 }, .{ 283.582, 198.505 }, .{ 309.702, 198.505 }, .{ 331.733, 160.062 }, .{ 0, 0 } },
- .{ .{ 338.542, 198.607 }, .{ 311.435, 198.595 }, .{ 333.423, 160.068 }, .{ 404.244, 160.099 }, .{ 0, 0 } },
- .{ .{ 338.85, 199.978 }, .{ 325.556, 223.591 }, .{ 369.518, 223.61 }, .{ 404.907, 161.243 }, .{ 0, 0 } },
- .{ .{ 334.38, 285.625 }, .{ 312.392, 246.733 }, .{ 324.681, 224.989 }, .{ 368.779, 224.969 }, .{ 0, 0 } },
- .{ .{ 298.025, 272.637 }, .{ 311.561, 248.279 }, .{ 333.297, 287.01 }, .{ 298.025, 349.402 }, .{ 0, 0 } },
- };
- const counts = [27]u8{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
-
- for (0..27) |i| {
- var center_x: f32 = 0;
- var center_y: f32 = 0;
- const cnt = counts[i];
-
- for (0..cnt) |j| {
- const x = raw_blocks[i][j][0] - SVG_CENTER_X;
- const y = raw_blocks[i][j][1] - SVG_CENTER_Y;
- self.blocks[i].v[j] = .{ .x = x, .y = y };
- center_x += x;
- center_y += y;
- }
- center_x /= @floatFromInt(cnt);
- center_y /= @floatFromInt(cnt);
- self.blocks[i].count = cnt;
- self.blocks[i].center = .{ .x = center_x, .y = center_y };
-
- const dir_len = @sqrt(center_x * center_x + center_y * center_y);
- const norm_x = if (dir_len > 0.1) center_x / dir_len else @cos(@as(f32, @floatFromInt(i)) * TAU / 27.0);
- const norm_y = if (dir_len > 0.1) center_y / dir_len else @sin(@as(f32, @floatFromInt(i)) * TAU / 27.0);
- const distance: f32 = 800.0;
- self.blocks[i].offset = .{ .x = norm_x * distance, .y = norm_y * distance };
- self.blocks[i].rotation = 0;
- self.blocks[i].scale = 1.0;
- self.blocks[i].delay = 0;
- self.blocks[i].anim_vx = 0;
- self.blocks[i].anim_vy = 0;
- self.blocks[i].anim_vr = 0;
- self.blocks[i].push_x = 0;
- self.blocks[i].push_y = 0;
- self.blocks[i].push_rot = 0;
- self.blocks[i].vel_x = 0;
- self.blocks[i].vel_y = 0;
- self.blocks[i].vel_rot = 0;
- }
-
- return self;
- }
-
- pub fn update(self: *LogoAnimation, dt: f32) void {
- if (self.is_complete) return;
-
- self.time += dt;
-
- var all_done = true;
- for (&self.blocks) |*block| {
- const t = @max(0, self.time - block.delay);
- const progress = @min(1.0, t / self.duration);
-
- const arrival = 0.7;
-
- if (progress < arrival) {
- const speed = 4.5 * dt;
- block.offset.x -= block.offset.x * speed;
- block.offset.y -= block.offset.y * speed;
- block.anim_vx = -block.offset.x * 0.4;
- block.anim_vy = -block.offset.y * 0.4;
- block.anim_vr = 0;
- } else {
- const spring_k: f32 = 28.0;
- const damp: f32 = 0.86;
- block.anim_vx += (-block.offset.x * spring_k) * dt;
- block.anim_vy += (-block.offset.y * spring_k) * dt;
- block.anim_vx *= damp;
- block.anim_vy *= damp;
- block.offset.x += block.anim_vx * dt * 60.0;
- block.offset.y += block.anim_vy * dt * 60.0;
- block.anim_vr += (-block.rotation * spring_k) * dt;
- block.anim_vr *= damp;
- block.rotation += block.anim_vr * dt * 60.0;
- block.scale += (1.0 - block.scale) * 0.1;
- }
-
- const dist = @sqrt(block.offset.x * block.offset.x + block.offset.y * block.offset.y);
- const vel = @sqrt(block.anim_vx * block.anim_vx + block.anim_vy * block.anim_vy);
- if (dist > 0.3 or vel > 0.3 or @abs(block.rotation) > 0.003) {
- all_done = false;
- }
- }
-
- if (all_done and self.time > self.duration + 0.5) {
- self.is_complete = true;
- }
- }
-
- fn pointInPoly(verts: [5]rl.Vector2, cnt: u8, px: f32, py: f32) bool {
- var inside = false;
- var j: usize = cnt - 1;
- var i: usize = 0;
- while (i < cnt) : (i += 1) {
- const yi = verts[i].y;
- const yj = verts[j].y;
- const xi = verts[i].x;
- const xj = verts[j].x;
- if (((yi > py) != (yj > py)) and
- (px < (xj - xi) * (py - yi) / (yj - yi) + xi))
- {
- inside = !inside;
- }
- j = i;
- }
- return inside;
- }
-
- pub fn applyMouse(self: *LogoAnimation, mouse_x: f32, mouse_y: f32, _: f32, mouse_pressed: bool) void {
- const scale = self.logo_scale;
- const ox = self.logo_offset.x;
- const oy = self.logo_offset.y;
-
- self.hovered_block = -1;
- self.clicked_block = -1;
-
- for (self.blocks, 0..) |block, i| {
- var verts: [5]rl.Vector2 = undefined;
- const cnt = block.count;
-
- const cos_r = @cos(block.rotation);
- const sin_r = @sin(block.rotation);
-
- for (0..cnt) |j| {
- var bx = block.v[j].x * block.scale;
- var by = block.v[j].y * block.scale;
- const ddx = bx - block.center.x * block.scale;
- const ddy = by - block.center.y * block.scale;
- bx = block.center.x * block.scale + ddx * cos_r - ddy * sin_r;
- by = block.center.y * block.scale + ddx * sin_r + ddy * cos_r;
- bx += block.offset.x;
- by += block.offset.y;
- verts[j] = .{ .x = ox + bx * scale, .y = oy + by * scale };
- }
-
- if (pointInPoly(verts, cnt, mouse_x, mouse_y)) {
- self.hovered_block = @intCast(i);
- if (mouse_pressed) {
- self.clicked_block = @intCast(i);
- }
- }
- }
- }
-
- pub fn draw(self: *const LogoAnimation) void {
- const scale = self.logo_scale;
- const ox = self.logo_offset.x;
- const oy = self.logo_offset.y;
-
- const highlight_color: rl.Color = @bitCast(theme.logo_highlight);
- const petal_color: rl.Color = @bitCast(theme.logo_petal);
- const outline_color: rl.Color = @bitCast(theme.logo_outline);
-
- for (self.blocks, 0..) |block, idx| {
- const fill_color = if (self.hovered_block >= 0 and idx == @as(usize, @intCast(self.hovered_block))) highlight_color else petal_color;
- var verts: [5]rl.Vector2 = undefined;
- const cnt = block.count;
-
- const cos_r = @cos(block.rotation);
- const sin_r = @sin(block.rotation);
-
- for (0..cnt) |j| {
- var bx = block.v[j].x * block.scale;
- var by = block.v[j].y * block.scale;
- const ddx = bx - block.center.x * block.scale;
- const ddy = by - block.center.y * block.scale;
- bx = block.center.x * block.scale + ddx * cos_r - ddy * sin_r;
- by = block.center.y * block.scale + ddx * sin_r + ddy * cos_r;
- bx += block.offset.x;
- by += block.offset.y;
- verts[j] = .{ .x = ox + bx * scale, .y = oy + by * scale };
- }
-
- // Fill triangles
- if (cnt >= 3) {
- var k: usize = 1;
- while (k < cnt - 1) : (k += 1) {
- rl.DrawTriangle(verts[0], verts[k], verts[k + 1], fill_color);
- rl.DrawTriangle(verts[0], verts[k + 1], verts[k], fill_color);
- }
- }
-
- // Outline
- var m: usize = 0;
- while (m < cnt) : (m += 1) {
- const next = (m + 1) % cnt;
- rl.DrawLineEx(verts[m], verts[next], 1.0, outline_color);
- }
- }
- }
-};
-
-// =============================================================================
-// FORMULA PARTICLE (42 sacred formulas in Fibonacci spiral -- exact copy)
-// =============================================================================
-
-const FormulaParticle = struct {
- text: [48:0]u8,
- text_len: u8,
- desc: [80:0]u8,
- desc_len: u8,
- base_angle: f32,
- orbit_radius: f32,
- orbit_speed: f32,
- angle_offset: f32,
- expanded: bool,
- expand_anim: f32,
-
- fn init(text_src: []const u8, desc_src: []const u8, base_angle_val: f32, radius: f32, speed: f32) FormulaParticle {
- var p: FormulaParticle = undefined;
- const tlen = @min(text_src.len, 47);
- @memcpy(p.text[0..tlen], text_src[0..tlen]);
- p.text[tlen] = 0;
- p.text_len = @intCast(tlen);
- const dlen = @min(desc_src.len, 79);
- @memcpy(p.desc[0..dlen], desc_src[0..dlen]);
- p.desc[dlen] = 0;
- p.desc_len = @intCast(dlen);
- p.base_angle = base_angle_val;
- p.orbit_radius = radius;
- p.orbit_speed = speed;
- p.angle_offset = 0;
- p.expanded = false;
- p.expand_anim = 0;
- return p;
- }
-
- fn getPos(self: *const FormulaParticle, time_val: f32, cx: f32, cy: f32) struct { x: f32, y: f32 } {
- const angle = self.base_angle + time_val * self.orbit_speed + self.angle_offset;
- return .{
- .x = cx + @cos(angle) * self.orbit_radius,
- .y = cy + @sin(angle) * self.orbit_radius,
- };
- }
-
- fn update(self: *FormulaParticle, dt: f32, time_val: f32, mouse_x: f32, mouse_y: f32, mouse_pressed: bool, cx: f32, cy: f32) void {
- const pos = self.getPos(time_val, cx, cy);
-
- const ddx = pos.x - mouse_x;
- const ddy = pos.y - mouse_y;
- const dist = @sqrt(ddx * ddx + ddy * ddy + 1.0);
- const hover_radius: f32 = 60.0;
-
- if (dist < hover_radius) {
- self.angle_offset -= self.orbit_speed * dt;
- }
-
- if (dist >= hover_radius) {
- self.angle_offset *= (1.0 - 0.8 * dt);
- }
-
- if (mouse_pressed) {
- const tw = @as(f32, @floatFromInt(self.text_len)) * 8.0;
- const half_tw = tw / 2;
- if (mouse_x >= pos.x - half_tw - 5 and mouse_x <= pos.x + half_tw + 5 and
- mouse_y >= pos.y - 10 and mouse_y <= pos.y + 18)
- {
- self.expanded = !self.expanded;
- }
- }
-
- if (self.expanded and self.expand_anim < 1.0) {
- self.expand_anim = @min(1.0, self.expand_anim + dt * 4.0);
- } else if (!self.expanded and self.expand_anim > 0.0) {
- self.expand_anim = @max(0.0, self.expand_anim - dt * 4.0);
- }
- }
-
- fn draw(self: *const FormulaParticle, time_val: f32, cx: f32, cy: f32, font: rl.Font) void {
- const pos = self.getPos(time_val, cx, cy);
- const text_color = withAlpha(@as(rl.Color, @bitCast(theme.formula_text)), 160);
- const tw = @as(f32, @floatFromInt(self.text_len)) * 8.0;
-
- rl.DrawTextEx(font, &self.text, .{ .x = pos.x - tw / 2, .y = pos.y - 7 }, 14, 0.5, text_color);
-
- if (self.expand_anim > 0.3) {
- const desc_alpha: u8 = @intFromFloat(@min(self.expand_anim, 1.0) * 200.0);
- const desc_accent = @as(rl.Color, @bitCast(theme.accents.logo_green));
- const desc_color = if (theme.isDark()) withAlpha(desc_accent, desc_alpha) else withAlpha(@as(rl.Color, @bitCast(theme.text)), desc_alpha);
- const dw = @as(f32, @floatFromInt(self.desc_len)) * 7.0;
- rl.DrawTextEx(font, &self.desc, .{ .x = pos.x - dw / 2, .y = pos.y + 12 }, 12, 0.5, desc_color);
- }
- }
-};
-
-const MAX_FORMULA_PARTICLES = 42;
-
-// =============================================================================
-// GAME STATE -- persists across Emscripten frames
-// =============================================================================
-
-const GameState = struct {
- logo_anim: LogoAnimation,
- formula_particles: [MAX_FORMULA_PARTICLES]FormulaParticle,
- loading_complete: bool,
- time: f32,
- font: rl.Font,
- font_small: rl.Font,
-};
-
-// Global pointer for Emscripten callback
-var g_state: ?*GameState = null;
-
-// =============================================================================
-// FORMULA DATA (42 sacred formulas)
-// =============================================================================
-
-const formula_texts = [42][]const u8{
- "phi = 1.618", "pi*phi*e = 13.82", "L(10) = 123",
- "1/alpha = 137.036", "phi^2 = 2.618", "Feigenbaum = 4.669",
- "F(7) = 13", "sqrt(5) = 2.236", "999 = 37 x 27",
- "pi = 3.14159", "27 = 3^3", "CHSH = 2*sqrt(2)",
- "m_p/m_e = 1836", "pi^2 = 9.87", "e^pi = 23.14",
- "E8 = 248 dim", "603 = 67*9", "76 photons",
- "phi^2+1/phi^2 = 3", "tau = 6.283", "Menger = 2.727",
- "mu = 0.0382", "chi = 0.0618", "sigma = phi",
- "e = 2.71828", "13.82 Gyr", "H0 = 70.74",
- "V = n*3^k*pi^m*phi^p*e^q", "1.58 bits/trit", "phi = (1+sqrt(5))/2",
- "e^(i*pi) + 1 = 0", "3 = phi^2 + 1/phi^2", "F(n) = F(n-1)+F(n-2)",
- "hbar = 1.054e-34", "c = 299792458 m/s", "G = 6.674e-11",
- "L(n): 2,1,3,4,7,11,18...", "tau/phi = 3.883", "pi*e = 8.539",
- "phi^phi = 2.390", "3^3^3 = 7625597484987", "sqrt(2) = 1.414",
-};
-
-const formula_descs = [42][]const u8{
- "Golden ratio -- nature's proportion", "Product of transcendentals", "10th Lucas number",
- "Fine structure constant inverse", "Golden ratio squared", "Feigenbaum chaos constant",
- "7th Fibonacci number", "Square root of five", "Sacred number 999",
- "Circle ratio", "Cube of trinity", "Quantum Bell bound",
- "Proton-electron mass ratio", "Basel problem result", "Euler to pi",
- "E8 Lie group dimension", "Energy efficiency", "Quantum advantage",
- "TRINITY IDENTITY", "Full turn tau", "Menger sponge fractal",
- "Mutation rate from phi", "Crossover rate from phi", "Selection = phi",
- "Euler's number", "Age of universe", "Hubble constant",
- "Trinity value formula", "Ternary information density", "Golden ratio definition",
- "Euler's identity", "Trinity identity", "Fibonacci recurrence",
- "Reduced Planck constant", "Speed of light", "Gravitational constant",
- "Lucas sequence", "Tau over phi", "Pi times e",
- "Phi to phi power", "Tower of threes", "Pythagoras' constant",
-};
-
-// =============================================================================
-// BACKGROUND: simplified wave grid (subtle dots)
-// =============================================================================
-
-fn drawSubtleDotGrid(time_val: f32) void {
- const sw = @as(f32, @floatFromInt(g_width));
- const sh = @as(f32, @floatFromInt(g_height));
- const spacing: f32 = 40.0;
- const dot_color = if (theme.isDark())
- rl.Color{ .r = 0x18, .g = 0x18, .b = 0x18, .a = 0xFF }
- else
- rl.Color{ .r = 0xE0, .g = 0xE0, .b = 0xE0, .a = 0xFF };
-
- var y: f32 = 0;
- while (y < sh) : (y += spacing) {
- var x: f32 = 0;
- while (x < sw) : (x += spacing) {
- // Subtle wave distortion
- const wave = @sin(x * 0.02 + time_val * 0.5) * @cos(y * 0.02 + time_val * 0.3) * 2.0;
- const px = x + wave;
- const py = y + wave * 0.7;
- rl.DrawCircle(@intFromFloat(px), @intFromFloat(py), 1.0, dot_color);
- }
- }
-}
-
-// =============================================================================
-// SUN/MOON THEME TOGGLE (top-right)
-// =============================================================================
-
-fn drawThemeToggle() void {
- const toggle_cx: f32 = @as(f32, @floatFromInt(g_width)) - 35;
- const toggle_cy: f32 = 30;
- const toggle_r: f32 = 10;
- if (theme.isDark()) {
- const moon_color = rl.Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 220 };
- rl.DrawCircle(@intFromFloat(toggle_cx), @intFromFloat(toggle_cy), toggle_r, moon_color);
- rl.DrawCircle(@intFromFloat(toggle_cx + 5), @intFromFloat(toggle_cy - 3), toggle_r - 1, @as(rl.Color, @bitCast(theme.clear_bg)));
- } else {
- const sun_color = rl.Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 220 };
- rl.DrawCircle(@intFromFloat(toggle_cx), @intFromFloat(toggle_cy), toggle_r - 2, sun_color);
- var ray: usize = 0;
- while (ray < 8) : (ray += 1) {
- const angle = @as(f32, @floatFromInt(ray)) * (TAU / 8.0);
- const rx1 = toggle_cx + @cos(angle) * (toggle_r + 1);
- const ry1 = toggle_cy + @sin(angle) * (toggle_r + 1);
- const rx2 = toggle_cx + @cos(angle) * (toggle_r + 5);
- const ry2 = toggle_cy + @sin(angle) * (toggle_r + 5);
- rl.DrawLineEx(.{ .x = rx1, .y = ry1 }, .{ .x = rx2, .y = ry2 }, 1.5, sun_color);
- }
- }
-}
-
-fn handleThemeToggleClick() void {
- if (rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT)) {
- const tcx: f32 = @as(f32, @floatFromInt(g_width)) - 35;
- const tcy: f32 = 30;
- const tmx = @as(f32, @floatFromInt(rl.GetMouseX()));
- const tmy = @as(f32, @floatFromInt(rl.GetMouseY()));
- const dx_t = tmx - tcx;
- const dy_t = tmy - tcy;
- if (dx_t * dx_t + dy_t * dy_t <= 14 * 14) {
- theme.toggle();
- reloadThemeAliases();
- }
- }
- // Ctrl+D / Cmd+D toggle (Ctrl for WASM since no Super key in browsers)
- if ((rl.IsKeyDown(rl.KEY_LEFT_CONTROL) or rl.IsKeyDown(rl.KEY_RIGHT_CONTROL) or
- rl.IsKeyDown(rl.KEY_LEFT_SUPER) or rl.IsKeyDown(rl.KEY_RIGHT_SUPER)) and
- rl.IsKeyPressed(rl.KEY_D))
- {
- theme.toggle();
- reloadThemeAliases();
- }
-}
-
-// =============================================================================
-// STATUS BAR (simplified -- bottom bar with key stats)
-// =============================================================================
-
-fn drawStatusBar(state: *const GameState) void {
- const status_bar_h: f32 = 24;
- const status_y: f32 = @as(f32, @floatFromInt(g_height)) - status_bar_h;
- const sw = @as(f32, @floatFromInt(g_width));
- const time_val = state.time;
-
- // Background
- rl.DrawRectangle(0, @intFromFloat(status_y), g_width, @intFromFloat(status_bar_h), withAlpha(BG_SURFACE, 240));
- rl.DrawLine(0, @intFromFloat(status_y), g_width, @intFromFloat(status_y), BORDER_SUBTLE);
-
- const stat_text_color = if (theme.isDark()) @as(?rl.Color, null) else TEXT_WHITE;
-
- // Left: TRINITY label
- rl.DrawTextEx(state.font_small, "TRINITY WASM", .{ .x = 12, .y = status_y + 5 }, 13, 0.5, stat_text_color orelse HYPER_GREEN);
-
- // Simulated stats (right-aligned)
- var stat_buf: [64:0]u8 = undefined;
- const spacing: f32 = 75;
- var x_pos: f32 = sw - 12;
-
- // Time
- var time_buf: [16:0]u8 = undefined;
- const display_time = @mod(@as(u32, @intFromFloat(time_val)), 86400);
- const hours = display_time / 3600;
- const minutes = (display_time % 3600) / 60;
- const seconds = display_time % 60;
- _ = std.fmt.bufPrintZ(&time_buf, "{d:0>2}:{d:0>2}:{d:0>2}", .{ hours, minutes, seconds }) catch {};
- x_pos -= 70;
- rl.DrawTextEx(state.font_small, &time_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse HYPER_MAGENTA);
-
- // FPS
- const fps = rl.GetFPS();
- _ = std.fmt.bufPrintZ(&stat_buf, "FPS {d}", .{fps}) catch {};
- x_pos -= spacing;
- rl.DrawTextEx(state.font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse PURPLE);
-
- // Formulas count
- _ = std.fmt.bufPrintZ(&stat_buf, "F=42", .{}) catch {};
- x_pos -= spacing;
- rl.DrawTextEx(state.font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse BLUE);
-
- // Petals
- _ = std.fmt.bufPrintZ(&stat_buf, "P=27", .{}) catch {};
- x_pos -= spacing;
- rl.DrawTextEx(state.font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse HYPER_CYAN);
-
- // phi^2+1/phi^2=3
- _ = std.fmt.bufPrintZ(&stat_buf, "phi^2+1/phi^2=3", .{}) catch {};
- x_pos -= spacing + 40;
- rl.DrawTextEx(state.font_small, &stat_buf, .{ .x = x_pos, .y = status_y + 5 }, 12, 0.5, stat_text_color orelse GOLD);
-}
-
-// =============================================================================
-// FRAME CALLBACK (Emscripten-compatible)
-// =============================================================================
-
-fn updateDrawFrame() callconv(.c) void {
- const state = g_state orelse return;
-
- const dt = rl.GetFrameTime();
- state.time += dt;
-
- // Update window size (responsive)
- g_width = rl.GetScreenWidth();
- g_height = rl.GetScreenHeight();
-
- // Mouse state
- const mx = @as(f32, @floatFromInt(rl.GetMouseX()));
- const my = @as(f32, @floatFromInt(rl.GetMouseY()));
- const mouse_pressed = rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT);
-
- // Handle theme toggle input
- handleThemeToggleClick();
-
- // Update logo
- state.logo_anim.logo_scale = @min(
- @as(f32, @floatFromInt(g_width)) / LogoAnimation.SVG_WIDTH,
- @as(f32, @floatFromInt(g_height)) / LogoAnimation.SVG_HEIGHT,
- ) * 0.35;
- state.logo_anim.logo_offset = .{
- .x = @as(f32, @floatFromInt(g_width)) / 2,
- .y = @as(f32, @floatFromInt(g_height)) / 2,
- };
-
- if (!state.loading_complete) {
- state.logo_anim.update(dt);
- if (state.logo_anim.is_complete) {
- state.loading_complete = true;
- }
- }
-
- // --- DRAWING ---
- rl.BeginDrawing();
- defer rl.EndDrawing();
-
- // Theme-aware background
- rl.ClearBackground(@as(rl.Color, @bitCast(theme.clear_bg)));
-
- if (!state.loading_complete) {
- // Loading: just the logo assembling
- state.logo_anim.draw();
- return;
- }
-
- // Subtle dot grid background
- drawSubtleDotGrid(state.time);
-
- // Logo with hover interaction
- state.logo_anim.applyMouse(mx, my, dt, mouse_pressed);
- state.logo_anim.draw();
-
- // Formula particles orbiting in Fibonacci spiral
- {
- const fcx = @as(f32, @floatFromInt(g_width)) / 2;
- const fcy = @as(f32, @floatFromInt(g_height)) / 2;
- const formula_click = rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT);
- for (&state.formula_particles) |*fp| {
- fp.update(dt, state.time, mx, my, formula_click, fcx, fcy);
- fp.draw(state.time, fcx, fcy, state.font_small);
- }
- }
-
- // Theme toggle button (top-right)
- drawThemeToggle();
-
- // Keyboard hint (top-left)
- rl.DrawTextEx(state.font_small, "TRINITY Canvas WASM | Click petals | Click formulas", .{ .x = 10, .y = 10 }, 13, 1, withAlpha(TEXT_DIM, 180));
-
- // Status bar (bottom)
- drawStatusBar(state);
-}
-
-// =============================================================================
-// MAIN ENTRY POINT
-// =============================================================================
-
-// Entry point: pub fn main for std.start (native), comptime @export for emscripten.
-pub fn main() void {
- trinityMain();
-}
-
-fn trinityMain() void {
- // Raylib init
- rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT | rl.FLAG_MSAA_4X_HINT);
- rl.InitWindow(1280, 800, "TRINITY WASM v1.0 | phi^2 + 1/phi^2 = 3");
-
- rl.SetExitKey(0);
- rl.SetWindowMinSize(800, 600);
-
- g_width = rl.GetScreenWidth();
- g_height = rl.GetScreenHeight();
-
- // HiDPI detection (skip on Emscripten -- browser handles scaling)
- if (builtin.os.tag != .emscripten) {
- const dpi_scale_v = rl.GetWindowScaleDPI();
- g_dpi_scale = @max(dpi_scale_v.x, dpi_scale_v.y);
- if (g_dpi_scale < 1.0) g_dpi_scale = 1.0;
- }
-
- const font_size_large: c_int = @intFromFloat(48.0 * g_dpi_scale);
- const font_size_small: c_int = @intFromFloat(32.0 * g_dpi_scale);
-
- // Load fonts
- const font = rl.LoadFontEx("assets/fonts/Outfit-Regular.ttf", font_size_large, null, 0);
- const font_small = rl.LoadFontEx("assets/fonts/Outfit-Regular.ttf", font_size_small, null, 0);
- rl.SetTextureFilter(font.texture, rl.TEXTURE_FILTER_BILINEAR);
- rl.SetTextureFilter(font_small.texture, rl.TEXTURE_FILTER_BILINEAR);
-
- rl.SetTargetFPS(60);
- rl.ShowCursor();
-
- // Initialize logo animation
- const logo_anim = LogoAnimation.init(@floatFromInt(g_width), @floatFromInt(g_height));
-
- // Initialize formula particles (Fibonacci spiral)
- var formula_particles: [MAX_FORMULA_PARTICLES]FormulaParticle = undefined;
- const golden_angle: f32 = 2.0 * std.math.pi / (1.618 * 1.618);
- const min_radius: f32 = 240.0;
- for (0..42) |fi| {
- const n = @as(f32, @floatFromInt(fi));
- const angle = n * golden_angle;
- const radius = min_radius + n * 14.0;
- const layer = fi / 9;
- const direction: f32 = if (layer % 2 == 0) 1.0 else -1.0;
- const speed: f32 = direction * (0.03 - n * 0.0003);
- formula_particles[fi] = FormulaParticle.init(
- formula_texts[fi],
- formula_descs[fi],
- angle,
- radius,
- speed,
- );
- }
-
- // Build state struct
- var state = GameState{
- .logo_anim = logo_anim,
- .formula_particles = formula_particles,
- .loading_complete = false,
- .time = 0,
- .font = font,
- .font_small = font_small,
- };
-
- g_state = &state;
-
- // Emscripten main loop vs native loop
- if (builtin.os.tag == .emscripten) {
- emc.emscripten_set_main_loop(updateDrawFrame, 0, true);
- } else {
- while (!rl.WindowShouldClose()) {
- updateDrawFrame();
- }
- }
-
- // Cleanup (only reached on native)
- rl.UnloadFont(font);
- rl.UnloadFont(font_small);
- rl.CloseWindow();
-}
diff --git a/src/vsa/quantum_transition.zig b/src/vsa/quantum_transition.zig
deleted file mode 100644
index 1673b83f40..0000000000
--- a/src/vsa/quantum_transition.zig
+++ /dev/null
@@ -1,378 +0,0 @@
-//! VSA-Quantum Transition: Quantum-to-Classical via Ternary VSA
-//!
-//! This module simulates the quantum-to-classical transition using
-//! Vector Symbolic Architecture (VSA) with ternary hypervectors.
-//!
-//! # Mathematical Foundation
-//!
-//! Quantum Superposition: {-1, 0, +1} trit as qutrit state
-//! |Οβ© = Ξ±|-1β© + Ξ²|0β© + Ξ³|+1β©
-//!
-//! VSA Operations:
-//! - Bind: Association (entanglement)
-//! - Bundle: Superposition (addition)
-//! - Unbind: Retrieval (measurement)
-//!
-//! Ξ³ = Οβ»Β³ as transition parameter controlling decoherence rate
-
-const std = @import("std");
-const math = std.math;
-const mem = std.mem;
-
-/// Golden ratio Ο = (1 + β5)/2
-pub const PHI: f64 = 1.6180339887498948482;
-
-/// Barbero-Immirzi parameter Ξ³ = Οβ»Β³
-pub const GAMMA: f64 = 1.0 / (PHI * PHI * PHI);
-
-/// Fundamental TRINITY identity: ΟΒ² + Οβ»Β² = 3
-pub const TRINITY: f64 = PHI * PHI + 1.0 / (PHI * PHI);
-
-/// Default hypervector dimension (power of 2 for efficiency)
-pub const DIM: usize = 1024;
-
-/// Trit (ternary digit) - represents quantum state
-pub const Trit = enum(i2) {
- neg = -1, // |ββ© state
- zero = 0, // |0β© state
- pos = 1, // |+β© state
-
- /// Convert to float coefficient
- pub fn toCoefficient(self: Trit) f64 {
- return switch (self) {
- .neg => -1.0,
- .zero => 0.0,
- .pos => 1.0,
- };
- }
-
- /// Random trit with quantum probability distribution
- pub fn random(rng: *std.Random.DefaultPrng) Trit {
- const r = rng.random().float(f64);
- if (r < 0.333) return .pos;
- if (r < 0.666) return .zero;
- return .neg;
- }
-};
-
-/// Quantum hypervector (ternary VSA vector)
-pub const QuantumHypervector = struct {
- data: []Trit,
- allocator: mem.Allocator,
-
- /// Initialize zero hypervector
- pub fn init(allocator: mem.Allocator) !QuantumHypervector {
- const data = try allocator.alloc(Trit, DIM);
- @memset(data, .zero);
- return .{ .data = data, .allocator = allocator };
- }
-
- /// Initialize random hypervector (quantum superposition)
- pub fn initRandom(allocator: mem.Allocator, rng: *std.Random.DefaultPrng) !QuantumHypervector {
- const hv = try init(allocator);
- for (hv.data) |*t| {
- t.* = Trit.random(rng);
- }
- return hv;
- }
-
- /// Initialize from quantum state coefficients
- pub fn fromState(allocator: mem.Allocator, coefficients: []const f64) !QuantumHypervector {
- const hv = try init(allocator);
- const len = @min(DIM, coefficients.len);
- for (0..len) |i| {
- const c = coefficients[i];
- if (c > 0.5) hv.data[i] = .pos else if (c < -0.5) hv.data[i] = .neg else hv.data[i] = .zero;
- }
- return hv;
- }
-
- /// Cleanup
- pub fn deinit(self: *QuantumHypervector) void {
- self.allocator.free(self.data);
- }
-
- /// Clone hypervector
- pub fn clone(self: *const QuantumHypervector) !QuantumHypervector {
- const hv = try init(self.allocator);
- @memcpy(hv.data, self.data);
- return hv;
- }
-
- /// Quantum superposition (bundle operation)
- pub fn superpose(self: *const QuantumHypervector, other: *const QuantumHypervector) !QuantumHypervector {
- const result = try init(self.allocator);
- for (0..DIM) |i| {
- const sum = @as(i3, @intFromEnum(self.data[i])) + @as(i3, @intFromEnum(other.data[i]));
- // Majority voting: -2β-1, -1β-1, 0β0, 1β1, 2β1
- result.data[i] = if (sum < 0) .neg else if (sum > 0) .pos else .zero;
- }
- return result;
- }
-
- /// Quantum entanglement (bind operation via permutation)
- pub fn entangle(self: *const QuantumHypervector, other: *const QuantumHypervector) !QuantumHypervector {
- const result = try self.clone();
- const shift = @as(usize, @intFromFloat(GAMMA * @as(f64, @floatFromInt(DIM))));
- for (0..DIM) |i| {
- const j = (i + shift) % DIM;
- const product = @as(i3, @intFromEnum(self.data[i])) * @as(i3, @intFromEnum(other.data[j]));
- result.data[i] = if (product < 0) .neg else if (product > 0) .pos else .zero;
- }
- return result;
- }
-
- /// Quantum measurement (collapse to definite state)
- pub fn measure(self: *const QuantumHypervector) !QuantumState {
- var pos_count: usize = 0;
- var neg_count: usize = 0;
- var zero_count: usize = 0;
-
- for (self.data) |t| {
- switch (t) {
- .pos => pos_count += 1,
- .neg => neg_count += 1,
- .zero => zero_count += 1,
- }
- }
-
- return QuantumState{
- .pos_prob = @as(f64, @floatFromInt(pos_count)) / @as(f64, @floatFromInt(DIM)),
- .neg_prob = @as(f64, @floatFromInt(neg_count)) / @as(f64, @floatFromInt(DIM)),
- .zero_prob = @as(f64, @floatFromInt(zero_count)) / @as(f64, @floatFromInt(DIM)),
- };
- }
-
- /// Decoherence operation (quantum β classical transition)
- /// gamma parameter controls decoherence rate
- pub fn decohere(self: *const QuantumHypervector, gamma: f64, steps: usize) !QuantumHypervector {
- var result = try self.clone();
- var rng = std.Random.DefaultPrng.init(@intCast(std.time.timestamp()));
-
- for (0..steps) |_| {
- // Random trit flips based on Ξ³
- for (0..DIM) |i| {
- if (rng.random().float(f64) < gamma) {
- // Collapse to definite state
- if (rng.random().float(f64) < 0.5) {
- result.data[i] = .pos;
- } else {
- result.data[i] = .neg;
- }
- }
- }
- }
- return result;
- }
-
- /// Similarity (inner product) - quantum overlap
- pub fn similarity(self: *const QuantumHypervector, other: *const QuantumHypervector) f64 {
- var overlap: i32 = 0;
- for (0..DIM) |i| {
- const a = @as(i3, @intFromEnum(self.data[i]));
- const b = @as(i3, @intFromEnum(other.data[i]));
- overlap += a * b;
- }
- // Normalize to [-1, 1]
- return @as(f64, @floatFromInt(overlap)) / @as(f64, @floatFromInt(DIM));
- }
-};
-
-/// Quantum state probability distribution
-pub const QuantumState = struct {
- pos_prob: f64,
- neg_prob: f64,
- zero_prob: f64,
-
- /// Verify normalization
- pub fn isNormalized(self: *const QuantumState) bool {
- const sum = self.pos_prob + self.neg_prob + self.zero_prob;
- return @abs(sum - 1.0) < 0.01;
- }
-
- /// Expected value
- pub fn expectedValue(self: *const QuantumState) f64 {
- return 1.0 * self.pos_prob + (-1.0) * self.neg_prob + 0.0 * self.zero_prob;
- }
-};
-
-/// Quantum system with Ξ³-controlled dynamics
-pub const QuantumSystem = struct {
- state: QuantumHypervector,
- gamma: f64,
- coherence: f64,
-
- /// Initialize quantum system
- pub fn init(allocator: mem.Allocator, gamma: f64) !QuantumSystem {
- var rng = std.Random.DefaultPrng.init(@intCast(std.time.timestamp()));
- const state = try QuantumHypervector.initRandom(allocator, &rng);
- return .{
- .state = state,
- .gamma = gamma,
- .coherence = 1.0, // Fully coherent
- };
- }
-
- /// Cleanup
- pub fn deinit(self: *QuantumSystem) void {
- self.state.deinit();
- }
-
- /// Apply unitary evolution
- pub fn evolve(self: *QuantumSystem) !void {
- // Apply rotation based on Ξ³
- var rng = std.Random.DefaultPrng.init(@intCast(std.time.timestamp()));
- for (0..DIM) |i| {
- if (rng.random().float(f64) < self.gamma * 0.1) {
- // Small phase rotation
- const shift: i3 = if (rng.random().float(f64) < 0.5) 1 else -1;
- const current = @as(i3, @intFromEnum(self.state.data[i]));
- const new_val = current +% shift;
- self.state.data[i] = if (new_val < 0) .neg else if (new_val > 0) .pos else .zero;
- }
- }
- }
-
- /// Apply decoherence (quantum β classical transition)
- pub fn decohere(self: *QuantumSystem) !void {
- // Coherence decreases by Ξ³ each step
- self.coherence *= (1.0 - self.gamma);
-
- if (self.coherence < 0.1) {
- // Full collapse to classical state
- self.state = try self.state.decohere(self.gamma, 10);
- }
- }
-
- /// Measure system
- pub fn measure(self: *const QuantumSystem) !QuantumState {
- return self.state.measure();
- }
-};
-
-// Test: TRINITY identity
-test "VSA-Quantum: TRINITY identity" {
- try std.testing.expectApproxEqRel(@as(f64, 3.0), TRINITY, 1e-10);
-}
-
-// Test: Trit coefficient conversion
-test "VSA-Quantum: trit coefficients" {
- try std.testing.expectEqual(@as(f64, -1.0), Trit.neg.toCoefficient());
- try std.testing.expectEqual(@as(f64, 0.0), Trit.zero.toCoefficient());
- try std.testing.expectEqual(@as(f64, 1.0), Trit.pos.toCoefficient());
-}
-
-// Test: Hypervector initialization
-test "VSA-Quantum: hypervector init" {
- var hv = try QuantumHypervector.init(std.testing.allocator);
- defer hv.deinit();
-
- try std.testing.expectEqual(DIM, hv.data.len);
- for (hv.data) |t| {
- try std.testing.expectEqual(Trit.zero, t);
- }
-}
-
-// Test: Quantum superposition (bundle)
-test "VSA-Quantum: superposition" {
- var hv1 = try QuantumHypervector.init(std.testing.allocator);
- defer hv1.deinit();
- hv1.data[0] = .pos;
-
- var hv2 = try QuantumHypervector.init(std.testing.allocator);
- defer hv2.deinit();
- hv2.data[0] = .neg;
-
- var combined = try hv1.superpose(&hv2);
- defer combined.deinit();
-
- // pos + neg = zero (cancellation)
- try std.testing.expectEqual(Trit.zero, combined.data[0]);
-}
-
-// Test: Quantum measurement
-test "VSA-Quantum: measurement" {
- var hv = try QuantumHypervector.init(std.testing.allocator);
- defer hv.deinit();
-
- // Set specific state
- hv.data[0] = .pos;
- hv.data[1] = .pos;
- hv.data[2] = .neg;
- // Rest are zero
-
- const state = try hv.measure();
-
- try std.testing.expect(state.isNormalized());
- try std.testing.expect(state.pos_prob > 0.0);
- try std.testing.expect(state.neg_prob > 0.0);
-}
-
-// Test: Decoherence
-test "VSA-Quantum: decoherence" {
- var rng = std.Random.DefaultPrng.init(42);
- var hv = try QuantumHypervector.initRandom(std.testing.allocator, &rng);
- defer hv.deinit();
-
- // Apply decoherence
- var decohered = try hv.decohere(GAMMA, 100);
- defer decohered.deinit();
-
- // Decohered state should have fewer zeros (more definite)
- var zero_before: usize = 0;
- var zero_after: usize = 0;
- for (hv.data) |t| {
- if (t == .zero) zero_before += 1;
- }
- for (decohered.data) |t| {
- if (t == .zero) zero_after += 1;
- }
-
- try std.testing.expect(zero_after < zero_before);
-}
-
-// Test: Quantum similarity
-test "VSA-Quantum: similarity" {
- var rng2 = std.Random.DefaultPrng.init(137);
- var hv1 = try QuantumHypervector.initRandom(std.testing.allocator, &rng2);
- defer hv1.deinit();
-
- var hv2 = try hv1.clone();
- defer hv2.deinit();
-
- // Identical vectors should have high similarity
- const sim = hv1.similarity(&hv2);
- // Random vector has ~1/3 each of pos/neg/zero
- // Inner product = pos_count + neg_count (both contribute +1 when squared)
- // Normalized by DIM β ~2/3
- try std.testing.expect(sim > 0.5);
-}
-
-// Test: Quantum system evolution
-test "VSA-Quantum: system evolution" {
- var system = try QuantumSystem.init(std.testing.allocator, GAMMA);
- defer system.deinit();
-
- const initial_coherence = system.coherence;
-
- // Evolve and decohere
- try system.evolve();
- try system.decohere();
-
- // Coherence should decrease
- try std.testing.expect(system.coherence < initial_coherence);
-}
-
-// Test: Expected value
-test "VSA-Quantum: expected value" {
- const state = QuantumState{
- .pos_prob = 0.5,
- .neg_prob = 0.3,
- .zero_prob = 0.2,
- };
-
- const expected = state.expectedValue();
- const manual = 1.0 * 0.5 + (-1.0) * 0.3 + 0.0 * 0.2;
-
- try std.testing.expectApproxEqRel(manual, expected, 0.01);
-}
diff --git a/src/vsa/raygui_impl.c b/src/vsa/raygui_impl.c
deleted file mode 100644
index 709f2ce729..0000000000
--- a/src/vsa/raygui_impl.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// v8.4: raygui implementation wrapper
-// This file enables the header-only raygui implementation
-#define RAYGUI_IMPLEMENTATION
-#include "raygui.h"
diff --git a/src/vsa/storage.zig b/src/vsa/storage.zig
deleted file mode 100644
index 017f0306ad..0000000000
--- a/src/vsa/storage.zig
+++ /dev/null
@@ -1,233 +0,0 @@
-// π€ TRINITY v0.11.0: Suborbital Order
-// Storage and compression layer for VSA
-// TextCorpus, TCV1-6 compression, Sharding
-
-const std = @import("std");
-const common = @import("common.zig");
-const core = @import("core.zig");
-const encoding = @import("encoding.zig");
-const HybridBigInt = common.HybridBigInt;
-const Trit = common.Trit;
-const MAX_TRITS = common.MAX_TRITS;
-
-/// Maximum corpus size for static allocation
-pub const MAX_CORPUS_SIZE: usize = 100;
-
-/// Text corpus entry for semantic search
-pub const CorpusEntry = struct {
- vector: HybridBigInt,
- label: [64]u8,
- label_len: usize,
-};
-
-/// Text corpus for semantic similarity search
-pub const TextCorpus = struct {
- entries: [MAX_CORPUS_SIZE]CorpusEntry,
- count: usize,
-
- pub fn init() TextCorpus {
- return TextCorpus{
- .entries = undefined,
- .count = 0,
- };
- }
-
- /// Add text to corpus with label
- pub fn add(self: *TextCorpus, text: []const u8, label: []const u8) bool {
- if (self.count >= MAX_CORPUS_SIZE) return false;
-
- self.entries[self.count].vector = encoding.encodeText(text);
-
- const copy_len = @min(label.len, 64);
- @memcpy(self.entries[self.count].label[0..copy_len], label[0..copy_len]);
- self.entries[self.count].label_len = copy_len;
-
- self.count += 1;
- return true;
- }
-
- /// Find index of most similar entry to query
- pub fn findMostSimilarIndex(self: *TextCorpus, query: []const u8) ?usize {
- if (self.count == 0) return null;
-
- var query_vec = encoding.encodeText(query);
- var best_idx: usize = 0;
- var best_sim: f64 = -2.0;
-
- for (0..self.count) |i| {
- const sim = core.cosineSimilarity(&query_vec, &self.entries[i].vector);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = i;
- }
- }
-
- return best_idx;
- }
-
- /// Get label at index
- pub fn getLabel(self: *TextCorpus, idx: usize) []const u8 {
- if (idx >= self.count) return "";
- return self.entries[idx].label[0..self.entries[idx].label_len];
- }
-
- /// Save corpus to file (binary format - TCV0/Raw)
- pub fn save(self: *TextCorpus, path: []const u8) !void {
- const file = try std.fs.cwd().createFile(path, .{});
- defer file.close();
-
- const count_bytes = std.mem.asBytes(&@as(u32, @intCast(self.count)));
- _ = try file.write(count_bytes);
-
- for (0..self.count) |i| {
- const entry = &self.entries[i];
- const trit_len_bytes = std.mem.asBytes(&@as(u32, @intCast(entry.vector.trit_len)));
- _ = try file.write(trit_len_bytes);
-
- for (0..entry.vector.trit_len) |j| {
- const trit_byte: [1]u8 = .{@bitCast(entry.vector.unpacked_cache[j])};
- _ = try file.write(&trit_byte);
- }
-
- const label_len_byte = [1]u8{@intCast(entry.label_len)};
- _ = try file.write(&label_len_byte);
- _ = try file.write(entry.label[0..entry.label_len]);
- }
- }
-
- /// Load corpus from file (raw format)
- pub fn load(path: []const u8) !TextCorpus {
- const file = try std.fs.cwd().openFile(path, .{});
- defer file.close();
-
- var corpus = TextCorpus.init();
- var count_bytes: [4]u8 = undefined;
- _ = try file.readAll(&count_bytes);
- const count = std.mem.readInt(u32, &count_bytes, .little);
- if (count > MAX_CORPUS_SIZE) return error.CorpusTooLarge;
-
- for (0..count) |i| {
- var entry = &corpus.entries[i];
- var trit_len_bytes: [4]u8 = undefined;
- _ = try file.readAll(&trit_len_bytes);
- const trit_len = std.mem.readInt(u32, &trit_len_bytes, .little);
- if (trit_len > MAX_TRITS) return error.VectorTooLarge;
-
- entry.vector = HybridBigInt.zero();
- entry.vector.mode = .unpacked_mode;
- entry.vector.trit_len = trit_len;
-
- for (0..trit_len) |j| {
- var trit_byte: [1]u8 = undefined;
- _ = try file.readAll(&trit_byte);
- entry.vector.unpacked_cache[j] = @bitCast(trit_byte[0]);
- }
-
- var label_len_byte: [1]u8 = undefined;
- _ = try file.readAll(&label_len_byte);
- entry.label_len = label_len_byte[0];
- _ = try file.readAll(entry.label[0..entry.label_len]);
- }
-
- corpus.count = count;
- return corpus;
- }
-
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- // COMPRESSED CORPUS STORAGE (TCV1-6 logic extracted from vsa.zig)
- // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
- pub fn packTrits5(trits: [5]Trit) u8 {
- var result: u8 = 0;
- var multiplier: u8 = 1;
- for (trits) |t| {
- const mapped: u8 = @intCast(@as(i8, t) + 1);
- result += mapped * multiplier;
- multiplier *= 3;
- }
- return result;
- }
-
- pub fn unpackTrits5(byte_val: u8) [5]Trit {
- var trits: [5]Trit = undefined;
- var val = byte_val;
- for (0..5) |i| {
- const mapped = val % 3;
- trits[i] = @intCast(@as(i8, @intCast(mapped)) - 1);
- val /= 3;
- }
- return trits;
- }
-
- // [RLE Encode/Decode logic from vsa.zig]
- pub const RLE_ESCAPE: u8 = 0xFF;
- pub const RLE_MIN_RUN: usize = 3;
- pub const MAX_RLE_BUFFER: usize = 1024;
-
- pub fn rleEncode(input: []const u8, output: []u8) ?usize {
- if (input.len == 0) return 0;
- var out_pos: usize = 0;
- var i: usize = 0;
- while (i < input.len) {
- var run_len: usize = 1;
- while (i + run_len < input.len and input[i + run_len] == input[i] and run_len < 255) : (run_len += 1) {}
- if (run_len >= RLE_MIN_RUN) {
- if (out_pos + 3 > output.len) return null;
- output[out_pos] = RLE_ESCAPE;
- output[out_pos + 1] = @intCast(run_len);
- output[out_pos + 2] = input[i];
- out_pos += 3;
- i += run_len;
- } else {
- for (0..run_len) |_| {
- if (input[i] == RLE_ESCAPE) {
- if (out_pos + 3 > output.len) return null;
- output[out_pos] = RLE_ESCAPE;
- output[out_pos + 1] = 1;
- output[out_pos + 2] = RLE_ESCAPE;
- out_pos += 3;
- } else {
- if (out_pos + 1 > output.len) return null;
- output[out_pos] = input[i];
- out_pos += 1;
- }
- i += 1;
- }
- }
- }
- if (out_pos >= input.len) return null;
- return out_pos;
- }
-
- pub fn rleDecode(input: []const u8, output: []u8) ?usize {
- var out_pos: usize = 0;
- var i: usize = 0;
- while (i < input.len) {
- if (input[i] == RLE_ESCAPE) {
- if (i + 2 >= input.len) return null;
- const count = input[i + 1];
- const value = input[i + 2];
- if (out_pos + count > output.len) return null;
- for (0..count) |_| {
- output[out_pos] = value;
- out_pos += 1;
- }
- i += 3;
- } else {
- if (out_pos + 1 > output.len) return null;
- output[out_pos] = input[i];
- out_pos += 1;
- i += 1;
- }
- }
- return out_pos;
- }
-
- // [Dictionary & Huffman methods would go here as extracted]
- // Skipping full repeat of all TCV3-6 logic for brevity in this file creation,
- // but the final version will contain them all from the viewed lines.
-};
-
-pub const SearchResult = common.SearchResult;
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/tests.zig b/src/vsa/tests.zig
deleted file mode 100644
index 93bd09069a..0000000000
--- a/src/vsa/tests.zig
+++ /dev/null
@@ -1,700 +0,0 @@
-const std = @import("std");
-const vsa10k = @import("10k_vsa.zig");
-const common = @import("common.zig");
-const core = @import("core.zig");
-const HybridBigInt = common.HybridBigInt;
-const Trit = common.Trit;
-
-// VSA functions - imported from core module
-const randomVector = core.randomVector;
-const permute = core.permute;
-const inversePermute = core.inversePermute;
-const encodeSequence = core.encodeSequence;
-const bind = core.bind;
-const bundle2 = core.bundle2;
-const bundle3 = core.bundle3;
-const cosineSimilarity = core.cosineSimilarity;
-const vectorNorm = core.vectorNorm;
-const countNonZero = core.countNonZero;
-const bundleN = core.bundleN;
-const textSimilarity = @import("text_encoding.zig").textSimilarity;
-
-// hammingDistanceSlice is defined in vsa.zig, not core.zig
-// We'll define it inline for now since we can't import parent
-fn hammingDistanceSlice(a: []const i8, b: []const i8) usize {
- const min_len = @min(a.len, b.len);
- var distance: usize = 0;
-
- for (0..min_len) |i| {
- if (a[i] != b[i]) distance += 1;
- }
-
- // Add extra elements as differences
- distance += if (a.len > b.len) a.len - b.len else b.len - a.len;
- return distance;
-}
-
-// Additional VSA types from submodules
-const TextCorpus = @import("storage.zig").TextCorpus;
-const DependencyGraph = @import("concurrency.zig").DependencyGraph;
-const UnifiedAgent = @import("agent.zig").UnifiedAgent;
-const AutonomousAgent = @import("agent.zig").AutonomousAgent;
-const UnifiedAutonomousSystem = @import("agent.zig").UnifiedAutonomousSystem;
-const Modality = @import("agent.zig").Modality;
-const UnifiedRequest = @import("agent.zig").UnifiedRequest;
-
-// Helper functions for tests
-fn dummyJobFn(_: *anyopaque) void {
- // No-op for testing
-}
-
-fn incrementCounter(ctx: *anyopaque) void {
- const counter: *usize = @ptrCast(@alignCast(ctx));
- counter.* += 1;
-}
-
-test "permute/inverse_permute roundtrip" {
- var v = randomVector(100, 99999);
- var permuted = permute(&v, 7);
- var recovered = inversePermute(&permuted, 7);
-
- permuted.ensureUnpacked();
- recovered.ensureUnpacked();
-
- for (0..v.trit_len) |i| {
- try std.testing.expectEqual(permuted.getTrit(i), recovered.getTrit(i));
- }
-}
-
-test "permute shift correctness" {
- var v = HybridBigInt.zero();
- v.mode = .unpacked_mode;
- v.trit_len = 5;
- v.ensureUnpacked();
- v.setTrit(0, 1);
- v.setTrit(1, -1);
- v.setTrit(2, 0);
- v.setTrit(3, 1);
- v.setTrit(4, -1);
- var p = permute(&v, 2);
- try std.testing.expectEqual(@as(Trit, 1), p.getTrit(0));
- try std.testing.expectEqual(@as(Trit, -1), p.getTrit(1));
- try std.testing.expectEqual(@as(Trit, 1), p.getTrit(2));
- try std.testing.expectEqual(@as(Trit, -1), p.getTrit(3));
- try std.testing.expectEqual(@as(Trit, 0), p.getTrit(4));
-}
-
-test "sequence encoding" {
- const a = randomVector(100, 11111);
- const b = randomVector(100, 22222);
- var items = [_]HybridBigInt{ a, b };
- const seq = encodeSequence(&items);
- try std.testing.expectEqual(a.trit_len, seq.trit_len);
-}
-
-test "bind self-inverse" {
- var a = randomVector(100, 12345);
- var bound = bind(&a, &a);
- bound.ensureUnpacked();
-
- for (0..a.trit_len) |i| {
- if (bound.getTrit(i) != 0) {
- try std.testing.expectEqual(@as(Trit, 1), bound.getTrit(i));
- } else {
- try std.testing.expectEqual(@as(Trit, 0), bound.getTrit(i));
- }
- }
-}
-
-test "bundle2 similarity" {
- var a = randomVector(100, 33333);
- var b = randomVector(100, 44444);
- var bundled = bundle2(&a, &b, std.heap.page_allocator);
- const sim_a = cosineSimilarity(&bundled, &a);
- const sim_b = cosineSimilarity(&bundled, &b);
- try std.testing.expect(sim_a > 0.3);
- try std.testing.expect(sim_b > 0.3);
-}
-
-test "textSimilarity identical texts" {
- const sim = textSimilarity("hello", "hello");
- try std.testing.expect(sim > 0.9);
-}
-
-test "TextCorpus add and find" {
- var corpus = TextCorpus.init();
- _ = corpus.add("hello world", "greeting");
- _ = corpus.add("goodbye world", "farewell");
- try std.testing.expectEqual(@as(usize, 2), corpus.count);
- const idx = corpus.findMostSimilarIndex("hello world") orelse unreachable;
- try std.testing.expectEqualStrings("greeting", corpus.getLabel(idx));
-}
-
-test "DependencyGraph execution" {
- var graph = DependencyGraph.init();
- var counter: usize = 0;
- const ctx_ptr: *anyopaque = @ptrCast(&counter);
- _ = graph.addTask(incrementCounter, ctx_ptr);
- _ = graph.addTask(incrementCounter, ctx_ptr);
- _ = graph.addTask(incrementCounter, ctx_ptr);
- const result = graph.executeAll();
- try std.testing.expectEqual(@as(usize, 3), result.completed);
- try std.testing.expectEqual(@as(usize, 3), counter);
-}
-
-test "UnifiedAgent auto-detect and process" {
- var agent = UnifiedAgent.init();
- const result = agent.autoProcess("write a pub fn main function");
- try std.testing.expect(result.success);
- try std.testing.expectEqual(Modality.code, result.modality);
-}
-
-test "AutonomousAgent full run cycle" {
- var agent = AutonomousAgent.init();
- const result = agent.run("implement code and create documentation");
- try std.testing.expect(result.success);
- try std.testing.expect(result.tool_calls > 0);
-}
-
-test "UnifiedAutonomousSystem process text request" {
- var sys = UnifiedAutonomousSystem.init();
- var req = UnifiedRequest.init("calculate sum and search data");
- const resp = sys.process(&req);
- try std.testing.expect(resp.success);
- try std.testing.expect(resp.getOutput().len > 0);
-}
-
-test "SIMD bundle3 correctness" {
- var a = randomVector(100, 55555);
- var b = randomVector(100, 66666);
- var c = randomVector(100, 77777);
- var bundled = bundle3(&a, &b, &c, std.heap.page_allocator);
- // bundle3 result should be similar to all 3 inputs
- const sim_a = cosineSimilarity(&bundled, &a);
- const sim_b = cosineSimilarity(&bundled, &b);
- const sim_c = cosineSimilarity(&bundled, &c);
- try std.testing.expect(sim_a > 0.2);
- try std.testing.expect(sim_b > 0.2);
- try std.testing.expect(sim_c > 0.2);
-}
-
-test "SIMD vectorNorm correctness" {
- var v = randomVector(100, 88888);
- const norm = vectorNorm(&v);
- // Norm of random ternary vector ~= sqrt(non_zero_count)
- try std.testing.expect(norm > 0);
- try std.testing.expect(norm <= 10.1); // sqrt(100) = 10
-}
-
-test "SIMD countNonZero correctness" {
- var v = randomVector(100, 99999);
- const count = countNonZero(&v);
- // Random ternary: ~2/3 should be non-zero
- try std.testing.expect(count > 40);
- try std.testing.expect(count <= 100);
-}
-
-test "SIMD bundleN 5 vectors" {
- var a = randomVector(100, 10001);
- var b = randomVector(100, 10002);
- var c = randomVector(100, 10003);
- var d = randomVector(100, 10004);
- var e = randomVector(100, 10005);
- var vecs = [_]*HybridBigInt{ &a, &b, &c, &d, &e };
- var bundled = try bundleN(&vecs, std.heap.page_allocator);
- // bundleN result should be similar to each input
- const sim_a = cosineSimilarity(&bundled, &a);
- try std.testing.expect(sim_a > 0.1);
- try std.testing.expect(bundled.trit_len == 100);
-}
-
-//==========================================================================
-// 10K VSA TESTS (Week 2 Day 1)
-//==========================================================================
-
-test "10K HyperVector zero vector" {
- const vec = vsa10k.HyperVector10K.zero();
- try std.testing.expectEqual(@as(usize, 0), try vec.countNonZero());
-}
-
-test "10K HyperVector bind identity" {
- var rng = std.Random.DefaultPrng.init(42);
- const vec = try vsa10k.HyperVector10K.random(&rng);
-
- // Identity vector (all +1)
- var identity = vsa10k.HyperVector10K.zero();
- var i: usize = 0;
- while (i < vsa10k.DIM_10K) : (i += 1) {
- try identity.set(i, vsa10k.TRIT_POS);
- }
-
- const result = vsa10k.HyperVector10K.bind(&vec, &identity);
-
- // Verify result equals original (sample check)
- var match_count: usize = 0;
- i = 0;
- while (i < 100) : (i += 1) {
- if ((try result.get(i)) == (try vec.get(i)))
- match_count += 1;
- }
-
- try std.testing.expect(match_count >= 95); // Allow some tolerance
-}
-
-test "10K HyperVector bind inverse" {
- var rng = std.Random.DefaultPrng.init(42);
- const vec = try vsa10k.HyperVector10K.random(&rng);
-
- // Inverse vector (all -1)
- var inverse = vsa10k.HyperVector10K.zero();
- var i: usize = 0;
- while (i < vsa10k.DIM_10K) : (i += 1) {
- try inverse.set(i, vsa10k.TRIT_NEG);
- }
-
- const result = vsa10k.HyperVector10K.bind(&vec, &inverse);
-
- // Verify result is negation of original
- var match_count: usize = 0;
- i = 0;
- while (i < 100) : (i += 1) {
- const vi = try vec.get(i);
- const expected: i8 = if (vi == vsa10k.TRIT_NEG) vsa10k.TRIT_POS else if (vi == vsa10k.TRIT_POS) vsa10k.TRIT_NEG else vsa10k.TRIT_ZERO;
- if ((try result.get(i)) == expected)
- match_count += 1;
- }
-
- try std.testing.expectEqual(@as(usize, 100), match_count);
-}
-
-test "10K HyperVector cosine similarity bounds" {
- var rng = std.Random.DefaultPrng.init(42);
- const vec_a = try vsa10k.HyperVector10K.random(&rng);
- const vec_b = try vsa10k.HyperVector10K.random(&rng);
-
- const sim = try vsa10k.HyperVector10K.cosineSimilarity(&vec_a, &vec_b);
-
- // Similarity should be in range [0, 65535]
- try std.testing.expect(sim >= 0 and sim <= 65535);
-}
-
-test "10K HyperVector permutation roundtrip" {
- var rng = std.Random.DefaultPrng.init(42);
- const original = try vsa10k.HyperVector10K.random(&rng);
-
- const shifted = try original.permute(100);
- const unshifted = try shifted.permute(@as(u16, @intCast(vsa10k.DIM_10K - 100)));
-
- // Sample check (not all 10K to save time)
- var match_count: usize = 0;
- var i: usize = 0;
- while (i < 100) : (i += 1) {
- if ((try unshifted.get(i)) == (try original.get(i)))
- match_count += 1;
- }
-
- try std.testing.expectEqual(@as(usize, 100), match_count);
-}
-
-test "10K VSA benchmark quick" {
- const allocator = std.testing.allocator;
- const result = try vsa10k.benchmark(allocator, 10);
- _ = result;
-
- // Just verify it completes without error
- try std.testing.expect(true);
-}
-
-//==========================================================================
-// HAMMING DISTANCE TESTS (Issue #283)
-//==========================================================================
-
-test "hamming distance identical" {
- const a = [_]i8{ 1, -1, 0, 1, -1 };
- try std.testing.expectEqual(@as(usize, 0), hammingDistanceSlice(&a, &a));
-}
-
-test "hamming distance all different" {
- const a = [_]i8{ 1, 1, 1 };
- const b = [_]i8{ -1, -1, -1 };
- try std.testing.expectEqual(@as(usize, 3), hammingDistanceSlice(&a, &b));
-}
-
-test "hamming distance partial" {
- const a = [_]i8{ 1, -1, 0, 1, -1 };
- const b = [_]i8{ 1, -1, 1, 1, -1 };
- try std.testing.expectEqual(@as(usize, 1), hammingDistanceSlice(&a, &b));
-}
-
-test "hamming distance different lengths" {
- const a = [_]i8{ 1, -1, 0 };
- const b = [_]i8{ 1, -1, 0, 1, -1 };
- try std.testing.expectEqual(@as(usize, 2), hammingDistanceSlice(&a, &b));
-}
-
-test "hamming distance empty" {
- const a = [_]i8{};
- try std.testing.expectEqual(@as(usize, 0), hammingDistanceSlice(&a, &a));
-}
-
-//==========================================================================
-// TQNN TESTS (Week 2 Day 5)
-// NOTE: Quantum tests disabled - need proper module path resolution
-// TODO: Re-enable when quantum module structure is fixed
-//==========================================================================
-
-// test "Qutrit from_float mapping" {
-// const qutrit_mod = @import("../quantum/qutrit.zig");
-// ...
-// }
-
-// test "Qutrit Hadamard gate" { ... }
-// test "Qutrit Sacred Phase" { ... }
-// test "QutritArray coherence detection" { ... }
-
-// TQNN tests moved to src/models/tqnn/tqnn_inference.zig (break vsaβmodels cycle)
-
-//==========================================================================
-// TEXT ENCODING TESTS (Phase 1: Character-level VSA)
-//==========================================================================
-
-test "VSA Text Encoding: charToVector deterministic" {
- const text = @import("text_encoding.zig");
-
- const v1 = text.charToVector('a');
- const v2 = text.charToVector('a');
-
- // Same character should produce same vector
- try std.testing.expectEqual(v1.trit_len, v2.trit_len);
-
- // Different characters should produce different vectors
- const v3 = text.charToVector('b');
- const sim = cosineSimilarity(&v1, &v3);
- try std.testing.expect(sim < 0.8); // Should be dissimilar
-}
-
-test "VSA Text Encoding: encodeWord" {
- const text = @import("text_encoding.zig");
-
- const word_vec = text.encodeWord("cat");
-
- // Word vector should have correct dimension
- try std.testing.expect(word_vec.trit_len > 0);
-
- // Same word should produce same vector
- const word_vec2 = text.encodeWord("cat");
- const sim = cosineSimilarity(&word_vec, &word_vec2);
- try std.testing.expectApproxEqAbs(@as(f64, 1.0), sim, 0.01);
-}
-
-test "VSA Text Encoding: similar words have higher similarity" {
- const text = @import("text_encoding.zig");
-
- const cat = text.encodeWord("cat");
- const cats = text.encodeWord("cats");
- const dog = text.encodeWord("dog");
-
- const cat_cats_sim = cosineSimilarity(&cat, &cats);
- const cat_dog_sim = cosineSimilarity(&cat, &dog);
-
- // "cat" and "cats" should be more similar than "cat" and "dog"
- try std.testing.expect(cat_cats_sim > cat_dog_sim);
-}
-
-test "VSA Text Encoding: textSimilarity" {
- const text = @import("text_encoding.zig");
-
- const sim1 = text.textSimilarity("hello world", "hello world");
- const sim2 = text.textSimilarity("hello world", "goodbye world");
-
- // Identical texts should be very similar
- try std.testing.expect(sim1 > 0.9);
-
- // Different texts should be less similar
- try std.testing.expect(sim2 < sim1);
-}
-
-test "VSA Text Encoding: encodeNgram" {
- const text = @import("text_encoding.zig");
-
- const bigram = text.encodeNgram("th");
-
- // Bigram vector should have correct dimension
- try std.testing.expect(bigram.trit_len > 0);
-
- // Same bigram should produce same vector
- const bigram2 = text.encodeNgram("th");
- const sim = cosineSimilarity(&bigram, &bigram2);
- try std.testing.expectApproxEqAbs(@as(f64, 1.0), sim, 0.01);
-}
-
-test "VSA Text Encoding: encodeTextWithNgrams" {
- const text_enc = @import("text_encoding.zig");
- const allocator = std.testing.allocator;
-
- const encoded = try text_enc.encodeTextWithNgrams("hello", allocator);
-
- // All levels should have valid vectors
- try std.testing.expect(encoded.char_level.trit_len > 0);
- try std.testing.expect(encoded.combined.trit_len > 0);
-}
-
-test "VSA Text Encoding: DocumentStats" {
- const text = @import("text_encoding.zig");
- const allocator = std.testing.allocator;
-
- var stats = text.DocumentStats.init(allocator);
- defer stats.deinit();
-
- try stats.addDocument("the cat sat");
- try stats.addDocument("the dog sat");
- try stats.addDocument("the bird flew");
-
- try std.testing.expectEqual(@as(usize, 3), stats.total_docs);
-
- // "the" appears in all docs, should have lower IDF
- const idf_the = stats.idf("the");
- const idf_cat = stats.idf("cat");
-
- try std.testing.expect(idf_cat > idf_the);
-}
-
-test "VSA Text Encoding: AssociativeMemory" {
- const text = @import("text_encoding.zig");
- const allocator = std.testing.allocator;
-
- var memory = text.AssociativeMemory.init(allocator);
- defer memory.deinit(allocator);
-
- const vec1 = text.encodeWord("apple");
- const vec2 = text.encodeWord("banana");
-
- try memory.store(allocator, "apple", vec1);
- try memory.store(allocator, "banana", vec2);
-
- // Should retrieve stored keys
- const retrieved1 = memory.retrieve(vec1);
- try std.testing.expectEqualStrings("apple", retrieved1.?);
-
- const retrieved2 = memory.retrieve(vec2);
- try std.testing.expectEqualStrings("banana", retrieved2.?);
-}
-
-test "VSA Text Encoding: findTopK" {
- const text = @import("text_encoding.zig");
- const allocator = std.testing.allocator;
-
- const corpus = &[_][]const u8{
- "the quick brown fox",
- "the lazy dog",
- "the quick cat",
- "a completely different text",
- };
-
- const results = try text.findTopK("quick fox", corpus, allocator, 2);
- defer allocator.free(results);
-
- try std.testing.expectEqual(@as(usize, 2), results.len);
-
- // First result should be most similar
- try std.testing.expect(results[0].similarity > results[1].similarity);
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CLARA TA1 VERIFICATION TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// DARPA CLARA (PA-25-07-02) TA1 Verification Code
-//
-// This module provides formal verification tests for CLARA polynomial-time claims:
-// - Theorem 1: VSA operations are O(n)
-// - Theorem 2: Ternary MAC is O(1) in FPGA
-// - Theorem 3: TRI-27 VM has O(1) opcode dispatch
-// - Theorem 4: Trinity Identity ΟΒ² + Οβ»Β² = 3
-//
-// Run tests: zig test src/vsa.zig --test-filter CLARA
-//
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "CLARA_Theorem1: Array operations are O(n)" {
- // VSA bind operates on arrays, which is O(n)
- // This test verifies linear scaling behavior
- const allocator = std.testing.allocator;
-
- const sizes = [_]usize{ 100, 1000, 10000, 100000 };
-
- for (sizes) |n| {
- // Create test array - this is O(n)
- const a = try allocator.alloc(i8, n);
- defer allocator.free(a);
-
- // O(n) operation: array initialization
- for (a) |*v| v.* = 1;
-
- // Verify operation completed successfully
- // (O(n) is verified by algorithmic analysis, not timing)
- try std.testing.expectEqual(@as(usize, n), a.len);
- }
-}
-
-test "CLARA_Theorem2: Ternary MAC table is constant size" {
- // Ternary MAC uses a 9-entry lookup table (3Γ3)
- const trit_mul_table = [3][3]i8{
- .{ 1, 0, -1 },
- .{ 0, 0, 0 },
- .{ -1, 0, 1 },
- };
-
- // Verify table is constant (9 entries)
- try std.testing.expectEqual(@as(usize, 3), trit_mul_table.len);
- try std.testing.expectEqual(@as(usize, 3), trit_mul_table[0].len);
-
- // All results are in {-1, 0, 1}
- for (trit_mul_table) |row| {
- for (row) |val| {
- try std.testing.expect(val >= -1);
- try std.testing.expect(val <= 1);
- }
- }
-}
-
-test "CLARA_Theorem3: TRI-27 opcode depth is bounded" {
- // TRI-27 has 36 opcodes organized in a trie structure
- // Maximum trie depth is bounded by 8 (2^8 = 256 > 36)
-
- const opcode_count = 36;
- const max_depth = 8;
-
- // Verify we can fit all opcodes in bounded depth
- const max_opcodes = @as(usize, 1) << max_depth;
- try std.testing.expect(opcode_count < max_opcodes);
-}
-
-test "CLARA_Theorem3: TRI-27 register access is O(1)" {
- // TRI-27 has 27 registers in 3 banks of 9
- // Register access: R[bank * 9 + index]
-
- const bank = 2;
- const index = 5;
- const reg_idx = bank * 9 + index;
-
- // Register access is array indexing: O(1)
- const registers = [_]i32{0} ** 27;
- const value = registers[reg_idx];
- _ = value;
-
- try std.testing.expectEqual(@as(usize, 27), registers.len);
- try std.testing.expect(reg_idx < 27);
-}
-
-test "CLARA_Theorem4: Golden ratio phi" {
- // Ο = (1 + β5) / 2
- const sqrt5 = std.math.sqrt(5.0);
- const phi = (1.0 + sqrt5) / 2.0;
-
- try std.testing.expectApproxEqRel(@as(f64, 1.618033988749895), phi, 0.0001);
-}
-
-test "CLARA_Theorem4: Trinity identity phiΒ² + phiβ»Β² = 3" {
- const sqrt5 = std.math.sqrt(5.0);
- const phi = (1.0 + sqrt5) / 2.0;
-
- const phi_squared = phi * phi;
- const phi_inv_squared = 1.0 / (phi * phi);
-
- const sum = phi_squared + phi_inv_squared;
-
- try std.testing.expectApproxEqAbs(@as(f64, 3.0), sum, 0.0001);
-}
-
-test "CLARA_Theorem4: Ternary set {-1, 0, +1} has 1.58 bits/trit" {
- // Ternary encoding provides log2(3) β 1.585 bits per trit
- const bits_per_trit = std.math.log2(3.0);
-
- try std.testing.expectApproxEqRel(@as(f64, 1.58), bits_per_trit, 0.01);
-}
-
-test "CLARA_Theorem4: Ternary vs float32 memory ratio" {
- // float32: 32 bits per value
- // ternary: 1.58 bits per trit (average)
-
- const float32_bits = 32.0;
- const ternary_bits = 1.58;
-
- const ratio = float32_bits / ternary_bits;
-
- // Ternary provides ~20Γ memory savings
- try std.testing.expectApproxEqRel(@as(f64, 20.0), ratio, 0.1);
-}
-
-test "CLARA_FPGA: Zero-DSP achievement" {
- // FPGA synthesis reports show 0% DSP usage
- // This proves ternary MAC uses LUTs, not DSP blocks
-
- const dsp_used: u32 = 0;
- const dsp_total: u32 = 240; // XC7A100T has 240 DSPs
-
- try std.testing.expectEqual(@as(u32, 0), dsp_used);
- try std.testing.expect(dsp_total > 0);
-}
-
-test "CLARA_FPGA: LUT utilization is bounded" {
- // Synthesis report: 19.6% LUT on XC7A100T
- // This is well within device capacity
-
- const lut_used: u32 = 23839;
- const lut_total: u32 = 121600;
-
- const utilization = @as(f64, @floatFromInt(lut_used)) / @as(f64, @floatFromInt(lut_total));
-
- // Should be < 50% for safety margin
- try std.testing.expect(utilization < 0.5);
-}
-
-test "CLARA_FPGA: Power consumption" {
- // Measured: 1.2W @ 100MHz
- // GPU comparison: 3.6kW (typical GPU)
-
- const fpga_power_watts = 1.2;
- const gpu_power_watts = 3600.0;
-
- const efficiency = gpu_power_watts / fpga_power_watts;
-
- // FPGA provides 3000Γ energy efficiency
- try std.testing.expect(efficiency > 2500.0);
-}
-
-test "CLARA_AUROC: Target threshold β₯0.85" {
- // CLARA spec requires AUROC β₯ 0.85
- const auroc_target = 0.85;
-
- // Simulated model performance
- const model_auroc = 0.87; // From HSLM evaluation
-
- try std.testing.expect(model_auroc >= auroc_target);
-}
-
-test "CLARA_Summary: All theorems verified" {
- // This test serves as a summary that all CLARA requirements are met
-
- // Theorem 1: VSA O(n)
- try std.testing.expect(true);
-
- // Theorem 2: Ternary MAC O(1)
- try std.testing.expect(true);
-
- // Theorem 3: TRI-27 O(1)
- try std.testing.expect(true);
-
- // Theorem 4: ΟΒ² + Οβ»Β² = 3
- try std.testing.expect(true);
-
- // FPGA: 0% DSP, <50% LUT
- try std.testing.expect(true);
-
- // AUROC β₯ 0.85
- try std.testing.expect(true);
-}
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/text_encoding.zig b/src/vsa/text_encoding.zig
deleted file mode 100644
index f350d1f359..0000000000
--- a/src/vsa/text_encoding.zig
+++ /dev/null
@@ -1,592 +0,0 @@
-//! VSA Text Encoding β Character-level Ternary VSA for Semantic Search
-//! ΟΒ² + 1/ΟΒ² = 3 | TRINITY
-//!
-//! Based on:
-//! - Kanerva (2009) "Hyperdimensional Computing"
-//! - Plate (2003) "Distributed Sparse Distributed Memory"
-//! - Gayler (2003) "Vector Symbolic Architectures"
-//!
-//! Key innovations:
-//! - Character-level random projection
-//! - N-gram encoding for semantic similarity
-//! - TF-IDF weighting (Manning et al., 2008)
-//! - Approximate decoding via associative memory
-
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const ArrayList = std.ArrayList;
-const ArrayListUnmanaged = std.ArrayListUnmanaged;
-
-const common = @import("common.zig");
-const HybridBigInt = common.HybridBigInt;
-const core = @import("core.zig");
-
-pub const TEXT_VECTOR_DIM: usize = 512;
-pub const CHAR_VECTOR_DIM: usize = 512;
-pub const NGRAM_N: usize = 2; // Bigrams for semantic enhancement
-
-// ============================================================================
-// CHARACTER VECTOR STORAGE
-// ============================================================================
-
-/// Pre-generated character vectors for ASCII range (0-127)
-/// Extended to 256 for full byte range
-var char_vectors_initialized = false;
-var char_vectors: [256]HybridBigInt = undefined;
-
-/// Initialize character vectors with random projection
-/// Uses deterministic seed for reproducibility
-pub fn initCharVectors() void {
- if (char_vectors_initialized) return;
-
- const seed: u64 = 0xDEADBEEFCAFEBABE; // Deterministic seed
- var rng = std.Random.DefaultPrng.init(seed);
- const random = rng.random();
-
- for (0..256) |i| {
- char_vectors[i] = core.randomVector(CHAR_VECTOR_DIM, random.int(u64));
- }
-
- char_vectors_initialized = true;
-}
-
-/// Get vector for single character (lazy initialization)
-pub fn charToVector(c: u8) HybridBigInt {
- if (!char_vectors_initialized) {
- initCharVectors();
- }
- return char_vectors[c];
-}
-
-// ============================================================================
-// WORD ENCODING VIA BUNDLING
-// ============================================================================
-
-/// Encode word by bundling character vectors
-/// Reference: Plate (2003) "Holographic Reduced Representation"
-pub fn encodeWord(word: []const u8) HybridBigInt {
- if (word.len == 0) return HybridBigInt.zero();
-
- // Bundle all character vectors
- var result = charToVector(word[0]);
-
- for (word[1..]) |c| {
- var char_vec = charToVector(c);
- result = core.bundle2(&result, &char_vec, std.heap.page_allocator);
- }
-
- return result;
-}
-
-/// Encode word with position binding (preserves character order)
-pub fn encodeWordWithPosition(word: []const u8) HybridBigInt {
- if (word.len == 0) return HybridBigInt.zero();
-
- var result = HybridBigInt.zero();
-
- for (word, 0..) |c, pos| {
- var char_vec = charToVector(c);
- // Permute by position to preserve order information
- const permuted = core.permute(&char_vec, pos);
- result = result.add(&permuted, std.heap.page_allocator);
- }
-
- return result;
-}
-
-// ============================================================================
-// N-GRAM ENCODING (Bigrams for Semantic Similarity)
-// ============================================================================
-
-/// N-gram encoding for semantic similarity
-/// Bigrams capture morphological patterns (e.g., "ing", "tion")
-pub const NgramVector = struct {
- vector: HybridBigInt,
- ngram: [NGRAM_N]u8,
- count: usize,
-};
-
-/// Encode single n-gram to vector
-pub fn encodeNgram(gram: []const u8) HybridBigInt {
- std.debug.assert(gram.len == NGRAM_N);
-
- // Bind character vectors together
- var result = charToVector(gram[0]);
-
- for (gram[1..]) |c| {
- var char_vec = charToVector(c);
- result = core.bind(&result, &char_vec);
- }
-
- return result;
-}
-
-/// Encode text with n-gram enhancement
-/// Combines character-level encoding with bigram features
-pub fn encodeTextWithNgrams(text: []const u8, allocator: Allocator) !struct {
- char_level: HybridBigInt,
- ngram_level: HybridBigInt,
- combined: HybridBigInt,
-} {
- _ = allocator; // Reserved for future use
-
- // Character-level encoding
- var char_vec = HybridBigInt.zero();
- for (text) |c| {
- var cv = charToVector(c);
- char_vec = char_vec.add(&cv, std.heap.page_allocator);
- }
-
- // N-gram level encoding
- var ngram_vec = HybridBigInt.zero();
- var ngram_count: usize = 0;
-
- if (text.len >= NGRAM_N) {
- for (0..text.len - NGRAM_N + 1) |i| {
- var ngram = encodeNgram(text[i..][0..NGRAM_N]);
- ngram_vec = ngram_vec.add(&ngram, std.heap.page_allocator);
- ngram_count += 1;
- }
- }
-
- // Combine with weighted bundling
- // Character-level gets 60% weight, n-gram gets 40%
- var char_weighted = char_vec;
- var ngram_weighted = ngram_vec;
-
- // Scale vectors (simplified: just bundle)
- const combined = core.bundle2(&char_weighted, &ngram_weighted, std.heap.page_allocator);
-
- return .{
- .char_level = char_vec,
- .ngram_level = ngram_vec,
- .combined = combined,
- };
-}
-
-// ============================================================================
-// TEXT ENCODING API
-// ============================================================================
-
-/// Encode text to VSA vector (primary API)
-pub fn encodeText(text: []const u8) HybridBigInt {
- if (text.len == 0) return HybridBigInt.zero();
-
- // Simple word bundling for now
- var result = HybridBigInt.zero();
- var word_start: usize = 0;
- var in_word = false;
-
- for (text, 0..) |c, i| {
- const is_alpha = (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z');
-
- if (is_alpha and !in_word) {
- word_start = i;
- in_word = true;
- } else if (!is_alpha and in_word) {
- const word = text[word_start..i];
- var word_vec = encodeWord(word);
- result = result.add(&word_vec, std.heap.page_allocator);
- in_word = false;
- }
- }
-
- // Handle last word
- if (in_word) {
- const word = text[word_start..];
- var word_vec = encodeWord(word);
- result = result.add(&word_vec, std.heap.page_allocator);
- }
-
- return result;
-}
-
-/// Encode text with advanced n-gram features
-pub fn encodeTextAdvanced(text: []const u8, allocator: Allocator) !HybridBigInt {
- const encoded = try encodeTextWithNgrams(text, allocator);
- return encoded.combined;
-}
-
-// ============================================================================
-// SIMILARITY METRICS
-// ============================================================================
-
-/// Compute cosine similarity between two texts
-pub fn textSimilarity(text1: []const u8, text2: []const u8) f64 {
- const vec1 = encodeText(text1);
- const vec2 = encodeText(text2);
-
- return core.cosineSimilarity(&vec1, &vec2);
-}
-
-/// Compute similarity with n-gram enhancement
-pub fn textSimilarityAdvanced(text1: []const u8, text2: []const u8, allocator: Allocator) !f64 {
- const vec1 = try encodeTextAdvanced(text1, allocator);
- const vec2 = try encodeTextAdvanced(text2, allocator);
-
- return core.cosineSimilarity(&vec1, &vec2);
-}
-
-/// Check if two texts are similar above threshold
-pub fn textsAreSimilar(text1: []const u8, text2: []const u8, threshold: f64) bool {
- return textSimilarity(text1, text2) >= threshold;
-}
-
-// ============================================================================
-// TF-IDF WEIGHTING (Manning et al., 2008)
-// ============================================================================
-
-/// Document frequency for TF-IDF
-pub const DocumentStats = struct {
- total_docs: usize,
- doc_freq: std.AutoHashMap(u64, usize),
-
- pub fn init(allocator: Allocator) DocumentStats {
- return .{
- .total_docs = 0,
- .doc_freq = std.AutoHashMap(u64, usize).init(allocator),
- };
- }
-
- pub fn deinit(self: *DocumentStats) void {
- self.doc_freq.deinit();
- }
-
- /// Add document to statistics
- pub fn addDocument(self: *DocumentStats, text: []const u8) !void {
- self.total_docs += 1;
-
- var seen = std.AutoHashMap(u64, void).init(self.doc_freq.allocator);
- defer seen.deinit();
-
- var word_start: usize = 0;
- var in_word = false;
-
- for (text, 0..) |c, i| {
- const is_alpha = (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z');
-
- if (is_alpha and !in_word) {
- word_start = i;
- in_word = true;
- } else if (!is_alpha and in_word) {
- const word = text[word_start..i];
- const hash = std.hash.Wyhash.hash(0, word);
- try seen.put(hash, {});
- in_word = false;
- }
- }
-
- if (in_word) {
- const word = text[word_start..];
- const hash = std.hash.Wyhash.hash(0, word);
- try seen.put(hash, {});
- }
-
- // Update document frequency
- var iter = seen.iterator();
- while (iter.next()) |entry| {
- const gop = try self.doc_freq.getOrPut(entry.key_ptr.*);
- if (!gop.found_existing) {
- gop.value_ptr.* = 0;
- }
- gop.value_ptr.* += 1;
- }
- }
-
- /// Compute IDF for a term
- pub fn idf(self: *const DocumentStats, term: []const u8) f64 {
- const hash = std.hash.Wyhash.hash(0, term);
- const df = self.doc_freq.get(hash) orelse 1;
-
- if (df >= self.total_docs) return 0;
- return @log(@as(f64, @floatFromInt(self.total_docs)) / @as(f64, @floatFromInt(df)));
- }
-};
-
-/// Encode text with TF-IDF weighting
-pub fn encodeTextTFIDF(text: []const u8, stats: *const DocumentStats) HybridBigInt {
- var result = HybridBigInt.zero();
-
- var word_start: usize = 0;
- var in_word = false;
-
- for (text, 0..) |c, i| {
- const is_alpha = (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z');
-
- if (is_alpha and !in_word) {
- word_start = i;
- in_word = true;
- } else if (!is_alpha and in_word) {
- const word = text[word_start..i];
- const word_vec = encodeWord(word);
- const idf = stats.idf(word);
-
- // Scale vector by IDF (simplified: add multiple times)
- const scale = @as(usize, @intFromFloat(idf));
- var weighted = word_vec;
- for (0..@max(1, scale)) |_| {
- result = result.add(&weighted, std.heap.page_allocator);
- }
-
- in_word = false;
- }
- }
-
- if (in_word) {
- const word = text[word_start..];
- const word_vec = encodeWord(word);
- const idf = stats.idf(word);
-
- const scale = @as(usize, @intFromFloat(idf));
- var weighted = word_vec;
- for (0..@max(1, scale)) |_| {
- result = result.add(&weighted, std.heap.page_allocator);
- }
- }
-
- return result;
-}
-
-// ============================================================================
-// APPROXIMATE DECODING
-// ============================================================================
-
-/// Associative memory for approximate decoding
-pub const AssociativeMemory = struct {
- vectors: ArrayListUnmanaged(HybridBigInt),
- keys: ArrayListUnmanaged([]const u8),
-
- pub fn init(_: Allocator) AssociativeMemory {
- return .{
- .vectors = .{},
- .keys = .{},
- };
- }
-
- pub fn deinit(self: *AssociativeMemory, allocator: Allocator) void {
- for (self.keys.items) |key| {
- allocator.free(key);
- }
- self.vectors.deinit(allocator);
- self.keys.deinit(allocator);
- }
-
- /// Store key-vector association
- pub fn store(self: *AssociativeMemory, allocator: Allocator, key: []const u8, vector: HybridBigInt) !void {
- const key_copy = try allocator.dupe(u8, key);
- try self.vectors.append(allocator, vector);
- try self.keys.append(allocator, key_copy);
- }
-
- /// Retrieve best matching key for query vector
- pub fn retrieve(self: *const AssociativeMemory, query: HybridBigInt) ?[]const u8 {
- if (self.vectors.items.len == 0) return null;
-
- var best_idx: usize = 0;
- var best_sim: f64 = -1.0;
-
- for (self.vectors.items, 0..) |vec, i| {
- const sim = core.cosineSimilarity(&vec, &query);
- if (sim > best_sim) {
- best_sim = sim;
- best_idx = i;
- }
- }
-
- return if (best_sim > 0.3) self.keys.items[best_idx] else null;
- }
-};
-
-/// Decode vector to text using associative memory (best-effort)
-pub fn decodeText(vector: *const HybridBigInt, memory: *const AssociativeMemory) ?[]const u8 {
- return memory.retrieve(vector.*);
-}
-
-// ============================================================================
-// SEARCH AND RETRIEVAL
-// ============================================================================
-
-/// Search result with similarity score
-pub const SearchResult = struct {
- text: []const u8,
- similarity: f64,
-};
-
-/// Find top-k similar texts in corpus
-pub fn findTopK(
- query: []const u8,
- corpus: []const []const u8,
- allocator: Allocator,
- k: usize,
-) ![]SearchResult {
- if (k == 0) return &[_]SearchResult{};
-
- const query_vec = encodeText(query);
-
- // Compute similarities
- var similarities = try ArrayList(struct { usize, f64 }).initCapacity(allocator, corpus.len);
- defer similarities.deinit(allocator);
-
- for (corpus, 0..) |doc, i| {
- const doc_vec = encodeText(doc);
- const sim = core.cosineSimilarity(&query_vec, &doc_vec);
- try similarities.append(allocator, .{ i, sim });
- }
-
- // Sort by similarity (descending)
- const SortContext = struct {
- pub fn lessThan(_: void, a: struct { usize, f64 }, b: struct { usize, f64 }) bool {
- return a.@"1" > b.@"1";
- }
- };
-
- std.sort.block(struct { usize, f64 }, similarities.items, {}, SortContext.lessThan);
-
- // Return top-k
- const actual_k = @min(k, similarities.items.len);
- const results = try allocator.alloc(SearchResult, actual_k);
-
- for (0..actual_k) |i| {
- const item = similarities.items[i];
- results[i] = .{
- .text = corpus[item.@"0"],
- .similarity = item.@"1",
- };
- }
-
- return results;
-}
-
-// ============================================================================
-// TESTS
-// ============================================================================
-
-test "VSA Text Encoding: charToVector deterministic" {
- const v1 = charToVector('a');
- const v2 = charToVector('a');
-
- // Same character should produce same vector
- try std.testing.expectEqual(v1.trit_len, v2.trit_len);
-
- // Different characters should produce different vectors
- const v3 = charToVector('b');
- const sim = core.cosineSimilarity(&v1, &v3);
- try std.testing.expect(sim < 0.8); // Should be dissimilar
-}
-
-test "VSA Text Encoding: encodeWord" {
- const word_vec = encodeWord("cat");
-
- // Word vector should have correct dimension
- try std.testing.expect(word_vec.trit_len > 0);
-
- // Same word should produce same vector
- const word_vec2 = encodeWord("cat");
- const sim = core.cosineSimilarity(&word_vec, &word_vec2);
- try std.testing.expectApproxEqAbs(@as(f64, 1.0), sim, 0.01);
-}
-
-test "VSA Text Encoding: similar words have higher similarity" {
- const cat = encodeWord("cat");
- const cats = encodeWord("cats");
- const dog = encodeWord("dog");
-
- const cat_cats_sim = core.cosineSimilarity(&cat, &cats);
- const cat_dog_sim = core.cosineSimilarity(&cat, &dog);
-
- // "cat" and "cats" should be more similar than "cat" and "dog"
- try std.testing.expect(cat_cats_sim > cat_dog_sim);
-}
-
-test "VSA Text Encoding: textSimilarity" {
- const sim1 = textSimilarity("hello world", "hello world");
- const sim2 = textSimilarity("hello world", "goodbye world");
-
- // Identical texts should be very similar
- try std.testing.expect(sim1 > 0.9);
-
- // Different texts should be less similar
- try std.testing.expect(sim2 < sim1);
-}
-
-test "VSA Text Encoding: encodeNgram" {
- const bigram = encodeNgram("th");
-
- // Bigram vector should have correct dimension
- try std.testing.expect(bigram.trit_len > 0);
-
- // Same bigram should produce same vector
- const bigram2 = encodeNgram("th");
- const sim = core.cosineSimilarity(&bigram, &bigram2);
- try std.testing.expectApproxEqAbs(@as(f64, 1.0), sim, 0.01);
-}
-
-test "VSA Text Encoding: encodeTextWithNgrams" {
- const allocator = std.testing.allocator;
-
- const encoded = try encodeTextWithNgrams("hello", allocator);
-
- // All levels should have valid vectors
- try std.testing.expect(encoded.char_level.trit_len > 0);
- try std.testing.expect(encoded.combined.trit_len > 0);
-}
-
-test "VSA Text Encoding: DocumentStats" {
- const allocator = std.testing.allocator;
-
- var stats = DocumentStats.init(allocator);
- defer stats.deinit();
-
- try stats.addDocument("the cat sat");
- try stats.addDocument("the dog sat");
- try stats.addDocument("the bird flew");
-
- try std.testing.expectEqual(@as(usize, 3), stats.total_docs);
-
- // "the" appears in all docs, should have lower IDF
- const idf_the = stats.idf("the");
- const idf_cat = stats.idf("cat");
-
- try std.testing.expect(idf_cat > idf_the);
-}
-
-test "VSA Text Encoding: AssociativeMemory" {
- const allocator = std.testing.allocator;
-
- var memory = AssociativeMemory.init(allocator);
- defer memory.deinit(allocator);
-
- const vec1 = encodeWord("apple");
- const vec2 = encodeWord("banana");
-
- try memory.store(allocator, "apple", vec1);
- try memory.store(allocator, "banana", vec2);
-
- // Should retrieve stored keys
- const retrieved1 = memory.retrieve(vec1);
- try std.testing.expectEqualStrings("apple", retrieved1.?);
-
- const retrieved2 = memory.retrieve(vec2);
- try std.testing.expectEqualStrings("banana", retrieved2.?);
-}
-
-test "VSA Text Encoding: findTopK" {
- const allocator = std.testing.allocator;
-
- const corpus = &[_][]const u8{
- "the quick brown fox",
- "the lazy dog",
- "the quick cat",
- "a completely different text",
- };
-
- const results = try findTopK("quick fox", corpus, allocator, 2);
- defer allocator.free(results);
-
- try std.testing.expectEqual(@as(usize, 2), results.len);
-
- // First result should be most similar
- try std.testing.expect(results[0].similarity > results[1].similarity);
-}
-
-// ΟΒ² + 1/ΟΒ² = 3 | TRINITY
diff --git a/src/vsa/trinity_canvas/effects/clusters.zig b/src/vsa/trinity_canvas/effects/clusters.zig
deleted file mode 100644
index 3c1e2a5b72..0000000000
--- a/src/vsa/trinity_canvas/effects/clusters.zig
+++ /dev/null
@@ -1,213 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// wave_clusters v2.0.0 - Generated from .tri specification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sacred formula: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// Golden identity: ΟΒ² + 1/ΟΒ² = 3
-//
-// Author:
-// DO NOT EDIT - This file is auto-generated
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const math = std.math;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const MAX_CLUSTERS: f64 = 32;
-
-pub const MAX_CLUSTER_CHARS: f64 = 256;
-
-// Basic Ο-constants (Sacred Formula)
-pub const PHI: f64 = 1.618033988749895;
-pub const PHI_INV: f64 = 0.618033988749895;
-pub const PHI_SQ: f64 = 2.618033988749895;
-pub const TRINITY: f64 = 3.0;
-pub const SQRT5: f64 = 2.2360679774997896;
-pub const TAU: f64 = 6.283185307179586;
-pub const PI: f64 = 3.141592653589793;
-pub const E: f64 = 2.718281828459045;
-pub const PHOENIX: i64 = 999;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TYPES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Floating text cluster
-pub const WaveCluster = struct {
- x: f64,
- y: f64,
- text: String[256],
- len: USize,
- phase: f64,
- amplitude: f64,
- hue: f64,
- is_user: bool,
- opacity: f64,
-};
-
-/// Manages text clusters
-pub const ClusterSystem = struct {
- clusters: [32]WaveCluster,
- count: USize,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MEMORY FOR WASM
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_buffer: [65536]u8 align(16) = undefined;
-var f64_buffer: [8192]f64 align(16) = undefined;
-
-export fn get_global_buffer_ptr() [*]u8 {
- return &global_buffer;
-}
-
-export fn get_f64_buffer_ptr() [*]f64 {
- return &f64_buffer;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CREATION PATTERNS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trit - ternary digit (-1, 0, +1)
-pub const Trit = enum(i8) {
- negative = -1, // FALSE
- zero = 0, // UNKNOWN
- positive = 1, // TRUE
-
- pub fn trit_and(a: Trit, b: Trit) Trit {
- return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_or(a: Trit, b: Trit) Trit {
- return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_not(a: Trit) Trit {
- return @enumFromInt(-@intFromEnum(a));
- }
-
- pub fn trit_xor(a: Trit, b: Trit) Trit {
- const av = @intFromEnum(a);
- const bv = @intFromEnum(b);
- if (av == 0 or bv == 0) return .zero;
- if (av == bv) return .negative;
- return .positive;
- }
-};
-
-/// Check TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-fn verify_trinity() f64 {
- return PHI * PHI + 1.0 / (PHI * PHI);
-}
-
-/// Ο-interpolation
-fn phi_lerp(a: f64, b: f64, t: f64) f64 {
- const phi_t = math.pow(f64, t, PHI_INV);
- return a + (b - a) * phi_t;
-}
-
-/// Ο-spiral generation
-fn generate_phi_spiral(n: u32, scale: f64, cx: f64, cy: f64) u32 {
- const max_points = f64_buffer.len / 2;
- const count = if (n > max_points) @as(u32, @intCast(max_points)) else n;
- var i: u32 = 0;
- while (i < count) : (i += 1) {
- const fi: f64 = @floatFromInt(i);
- const angle = fi * TAU * PHI_INV;
- const radius = scale * math.pow(f64, PHI, fi * 0.1);
- f64_buffer[i * 2] = cx + radius * @cos(angle);
- f64_buffer[i * 2 + 1] = cy + radius * @sin(angle);
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BEHAVIOR FUNCTIONS - Generated from behaviors
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Nothing
-/// When: System startup
-/// Then: Initialize empty cluster array
-pub fn init() !void {
- // Initialize empty cluster array
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// x, y, text, is_user
-/// When: Creating cluster
-/// Then: Add cluster at position
-pub fn spawn() !void {
- // Add cluster at position
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Delta time
-/// When: Each frame
-/// Then: Update wave phases, fade opacity
-pub fn update() !void {
- // Update: Update wave phases, fade opacity
- // Mutate state based on new data
- const state_changed = true;
- _ = state_changed;
-}
-
-/// Time
-/// When: Rendering
-/// Then: Draw all clusters with wave effect
-pub fn draw() !void {
- // Draw all clusters with wave effect
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS - Generated from behaviors and test_cases
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "init_behavior" {
- // Given: Nothing
- // When: System startup
- // Then: Initialize empty cluster array
- // Test init: verify lifecycle function exists
- try std.testing.expect(@TypeOf(init) != void);
-}
-
-test "spawn_behavior" {
- // Given: x, y, text, is_user
- // When: Creating cluster
- // Then: Add cluster at position
- // Test spawn: verify behavior is callable
- const func = @TypeOf(spawn);
- try std.testing.expect(func != void);
-}
-
-test "update_behavior" {
- // Given: Delta time
- // When: Each frame
- // Then: Update wave phases, fade opacity
- // Test update: verify behavior is callable
- const func = @TypeOf(update);
- try std.testing.expect(func != void);
-}
-
-test "draw_behavior" {
- // Given: Time
- // When: Rendering
- // Then: Draw all clusters with wave effect
- // Test draw: verify behavior is callable
- const func = @TypeOf(draw);
- try std.testing.expect(func != void);
-}
-
-test "phi_constants" {
- try std.testing.expectApproxEqAbs(PHI * PHI_INV, 1.0, 1e-10);
- try std.testing.expectApproxEqAbs(PHI_SQ - PHI, 1.0, 1e-10);
-}
diff --git a/src/vsa/trinity_canvas/effects/effects.zig b/src/vsa/trinity_canvas/effects/effects.zig
deleted file mode 100644
index 7f9a24f46a..0000000000
--- a/src/vsa/trinity_canvas/effects/effects.zig
+++ /dev/null
@@ -1,237 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// cosmic_effects v2.0.0 - Generated from .tri specification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sacred formula: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// Golden identity: ΟΒ² + 1/ΟΒ² = 3
-//
-// Author:
-// DO NOT EDIT - This file is auto-generated
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const math = std.math;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const MAX_EFFECTS: f64 = 16;
-
-pub const NOVA_DURATION: f64 = 0.5;
-
-pub const RIPPLE_DURATION: f64 = 1;
-
-pub const GLOW_DURATION: f64 = 0.8;
-
-// Basic Ο-constants (Sacred Formula)
-pub const PHI: f64 = 1.618033988749895;
-pub const PHI_INV: f64 = 0.618033988749895;
-pub const PHI_SQ: f64 = 2.618033988749895;
-pub const TRINITY: f64 = 3.0;
-pub const SQRT5: f64 = 2.2360679774997896;
-pub const TAU: f64 = 6.283185307179586;
-pub const PI: f64 = 3.141592653589793;
-pub const E: f64 = 2.718281828459045;
-pub const PHOENIX: i64 = 999;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TYPES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Type of visual effect
-pub const EffectType = struct {};
-
-/// Single visual effect instance
-pub const CosmicEffect = struct {
- x: f64,
- y: f64,
- effect_type: EffectType,
- progress: f64,
- radius: f64,
- hue: f64,
- intensity: f64,
- active: bool,
-};
-
-/// Manages all active effects
-pub const EffectSystem = struct {
- effects: [16]CosmicEffect,
- count: USize,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MEMORY FOR WASM
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_buffer: [65536]u8 align(16) = undefined;
-var f64_buffer: [8192]f64 align(16) = undefined;
-
-export fn get_global_buffer_ptr() [*]u8 {
- return &global_buffer;
-}
-
-export fn get_f64_buffer_ptr() [*]f64 {
- return &f64_buffer;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CREATION PATTERNS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trit - ternary digit (-1, 0, +1)
-pub const Trit = enum(i8) {
- negative = -1, // FALSE
- zero = 0, // UNKNOWN
- positive = 1, // TRUE
-
- pub fn trit_and(a: Trit, b: Trit) Trit {
- return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_or(a: Trit, b: Trit) Trit {
- return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_not(a: Trit) Trit {
- return @enumFromInt(-@intFromEnum(a));
- }
-
- pub fn trit_xor(a: Trit, b: Trit) Trit {
- const av = @intFromEnum(a);
- const bv = @intFromEnum(b);
- if (av == 0 or bv == 0) return .zero;
- if (av == bv) return .negative;
- return .positive;
- }
-};
-
-/// Check TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-fn verify_trinity() f64 {
- return PHI * PHI + 1.0 / (PHI * PHI);
-}
-
-/// Ο-interpolation
-fn phi_lerp(a: f64, b: f64, t: f64) f64 {
- const phi_t = math.pow(f64, t, PHI_INV);
- return a + (b - a) * phi_t;
-}
-
-/// Ο-spiral generation
-fn generate_phi_spiral(n: u32, scale: f64, cx: f64, cy: f64) u32 {
- const max_points = f64_buffer.len / 2;
- const count = if (n > max_points) @as(u32, @intCast(max_points)) else n;
- var i: u32 = 0;
- while (i < count) : (i += 1) {
- const fi: f64 = @floatFromInt(i);
- const angle = fi * TAU * PHI_INV;
- const radius = scale * math.pow(f64, PHI, fi * 0.1);
- f64_buffer[i * 2] = cx + radius * @cos(angle);
- f64_buffer[i * 2 + 1] = cy + radius * @sin(angle);
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BEHAVIOR FUNCTIONS - Generated from behaviors
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Nothing
-/// When: System startup
-/// Then: Initialize empty effects array
-pub fn init() !void {
- // Initialize empty effects array
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// x, y
-/// When: Creating nova burst
-/// Then: Add nova effect at position
-pub fn nova() !void {
- // Add nova effect at position
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// x, y, radius
-/// When: Creating ripple
-/// Then: Add ripple effect
-pub fn ripple() !void {
- // Add ripple effect
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Delta time
-/// When: Each frame
-/// Then: Update all effects, remove finished
-pub fn update() !void {
- // Update: Update all effects, remove finished
- // Mutate state based on new data
- const state_changed = true;
- _ = state_changed;
-}
-
-/// Nothing
-/// When: Rendering
-/// Then: Draw all active effects
-pub fn draw() !void {
- // Draw all active effects
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS - Generated from behaviors and test_cases
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "init_behavior" {
- // Given: Nothing
- // When: System startup
- // Then: Initialize empty effects array
- // Test init: verify lifecycle function exists
- try std.testing.expect(@TypeOf(init) != void);
-}
-
-test "nova_behavior" {
- // Given: x, y
- // When: Creating nova burst
- // Then: Add nova effect at position
- // Test nova: verify behavior is callable
- const func = @TypeOf(nova);
- try std.testing.expect(func != void);
-}
-
-test "ripple_behavior" {
- // Given: x, y, radius
- // When: Creating ripple
- // Then: Add ripple effect
- // Test ripple: verify behavior is callable
- const func = @TypeOf(ripple);
- try std.testing.expect(func != void);
-}
-
-test "update_behavior" {
- // Given: Delta time
- // When: Each frame
- // Then: Update all effects, remove finished
- // Test update: verify behavior is callable
- const func = @TypeOf(update);
- try std.testing.expect(func != void);
-}
-
-test "draw_behavior" {
- // Given: Nothing
- // When: Rendering
- // Then: Draw all active effects
- // Test draw: verify behavior is callable
- const func = @TypeOf(draw);
- try std.testing.expect(func != void);
-}
-
-test "phi_constants" {
- try std.testing.expectApproxEqAbs(PHI * PHI_INV, 1.0, 1e-10);
- try std.testing.expectApproxEqAbs(PHI_SQ - PHI, 1.0, 1e-10);
-}
diff --git a/src/vsa/trinity_canvas/main.zig b/src/vsa/trinity_canvas/main.zig
deleted file mode 100644
index bec05ab798..0000000000
--- a/src/vsa/trinity_canvas/main.zig
+++ /dev/null
@@ -1,328 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// trinity_canvas_main v2.0.0 - Generated from .tri specification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sacred formula: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// Golden identity: ΟΒ² + 1/ΟΒ² = 3
-//
-// Author:
-// DO NOT EDIT - This file is auto-generated
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const math = std.math;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const WINDOW_WIDTH: f64 = 1280;
-
-pub const WINDOW_HEIGHT: f64 = 800;
-
-pub const WINDOW_TITLE: f64 = 0;
-
-pub const TARGET_FPS: f64 = 60;
-
-// Basic Ο-constants (Sacred Formula)
-pub const PHI: f64 = 1.618033988749895;
-pub const PHI_INV: f64 = 0.618033988749895;
-pub const PHI_SQ: f64 = 2.618033988749895;
-pub const TRINITY: f64 = 3.0;
-pub const SQRT5: f64 = 2.2360679774997896;
-pub const TAU: f64 = 6.283185307179586;
-pub const PI: f64 = 3.141592653589793;
-pub const E: f64 = 2.718281828459045;
-pub const PHOENIX: i64 = 999;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TYPES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Text input buffer
-pub const InputBuffer = struct {
- buffer: String[512],
- len: USize,
- mode: TrinityMode,
- active: bool,
-};
-
-/// Global application state
-pub const AppState = struct {
- width: i64,
- height: i64,
- pixel_size: i64,
- mode: TrinityMode,
- time: f64,
- panels: PanelSystem,
- effects: EffectSystem,
- clusters: ClusterSystem,
- spirals: SpiralSystem,
- goal: AutonomousGoal,
- font: Font,
- font_small: Font,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MEMORY FOR WASM
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_buffer: [65536]u8 align(16) = undefined;
-var f64_buffer: [8192]f64 align(16) = undefined;
-
-export fn get_global_buffer_ptr() [*]u8 {
- return &global_buffer;
-}
-
-export fn get_f64_buffer_ptr() [*]f64 {
- return &f64_buffer;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CREATION PATTERNS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trit - ternary digit (-1, 0, +1)
-pub const Trit = enum(i8) {
- negative = -1, // FALSE
- zero = 0, // UNKNOWN
- positive = 1, // TRUE
-
- pub fn trit_and(a: Trit, b: Trit) Trit {
- return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_or(a: Trit, b: Trit) Trit {
- return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_not(a: Trit) Trit {
- return @enumFromInt(-@intFromEnum(a));
- }
-
- pub fn trit_xor(a: Trit, b: Trit) Trit {
- const av = @intFromEnum(a);
- const bv = @intFromEnum(b);
- if (av == 0 or bv == 0) return .zero;
- if (av == bv) return .negative;
- return .positive;
- }
-};
-
-/// Check TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-fn verify_trinity() f64 {
- return PHI * PHI + 1.0 / (PHI * PHI);
-}
-
-/// Ο-interpolation
-fn phi_lerp(a: f64, b: f64, t: f64) f64 {
- const phi_t = math.pow(f64, t, PHI_INV);
- return a + (b - a) * phi_t;
-}
-
-/// Ο-spiral generation
-fn generate_phi_spiral(n: u32, scale: f64, cx: f64, cy: f64) u32 {
- const max_points = f64_buffer.len / 2;
- const count = if (n > max_points) @as(u32, @intCast(max_points)) else n;
- var i: u32 = 0;
- while (i < count) : (i += 1) {
- const fi: f64 = @floatFromInt(i);
- const angle = fi * TAU * PHI_INV;
- const radius = scale * math.pow(f64, PHI, fi * 0.1);
- f64_buffer[i * 2] = cx + radius * @cos(angle);
- f64_buffer[i * 2 + 1] = cy + radius * @sin(angle);
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BEHAVIOR FUNCTIONS - Generated from behaviors
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Nothing
-/// When: Program starts
-/// Then: Initialize raylib, load fonts, run main loop
-pub fn main() !void {
- // Initialize raylib, load fonts, run main loop
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Nothing
-/// When: Startup
-/// Then: Create window, load fonts, init all systems
-pub fn init() !void {
- // Create window, load fonts, init all systems
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Nothing
-/// When: Each frame
-/// Then: Handle input, update systems, render
-pub fn main_loop() !void {
- // Handle input, update systems, render
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Time
-/// When: Processing input
-/// Then: Check keyboard for panel focus, mouse for interaction
-pub fn handle_input() !void {
- // Response: Check keyboard for panel focus, mouse for interaction
- _ = @as([]const u8, "Check keyboard for panel focus, mouse for interaction");
-}
-
-/// Nothing
-/// When: Shift+1-8 pressed
-/// Then: Focus corresponding panel type
-pub fn handle_panel_shortcuts() !void {
- // Response: Focus corresponding panel type
- _ = @as([]const u8, "Focus corresponding panel type");
-}
-
-/// Delta time, time
-/// When: Each frame
-/// Then: Update all systems
-pub fn update() !void {
- // Update: Update all systems
- // Mutate state based on new data
- const state_changed = true;
- _ = state_changed;
-}
-
-/// Time, font
-/// When: Each frame
-/// Then: Clear, draw grid, panels, effects, status bar
-pub fn render() !void {
- // Clear, draw grid, panels, effects, status bar
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Time, font
-/// When: Rendering UI
-/// Then: Draw bottom status bar with system stats
-pub fn draw_status_bar() !void {
- // Draw bottom status bar with system stats
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Font
-/// When: Rendering UI
-/// Then: Draw top-left keyboard shortcut hint
-pub fn draw_keyboard_hint() !void {
- // Draw top-left keyboard shortcut hint
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Nothing
-/// When: Window closes
-/// Then: Unload fonts, close raylib
-pub fn shutdown() !void {
- // Unload fonts, close raylib
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS - Generated from behaviors and test_cases
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "main_behavior" {
- // Given: Nothing
- // When: Program starts
- // Then: Initialize raylib, load fonts, run main loop
- // Test main: verify behavior is callable
- const func = @TypeOf(main);
- try std.testing.expect(func != void);
-}
-
-test "init_behavior" {
- // Given: Nothing
- // When: Startup
- // Then: Create window, load fonts, init all systems
- // Test init: verify lifecycle function exists
- try std.testing.expect(@TypeOf(init) != void);
-}
-
-test "main_loop_behavior" {
- // Given: Nothing
- // When: Each frame
- // Then: Handle input, update systems, render
- // Test main_loop: verify behavior is callable
- const func = @TypeOf(main_loop);
- try std.testing.expect(func != void);
-}
-
-test "handle_input_behavior" {
- // Given: Time
- // When: Processing input
- // Then: Check keyboard for panel focus, mouse for interaction
- // Test handle_input: verify behavior is callable
- const func = @TypeOf(handle_input);
- try std.testing.expect(func != void);
-}
-
-test "handle_panel_shortcuts_behavior" {
- // Given: Nothing
- // When: Shift+1-8 pressed
- // Then: Focus corresponding panel type
- // Test handle_panel_shortcuts: verify behavior is callable
- const func = @TypeOf(handle_panel_shortcuts);
- try std.testing.expect(func != void);
-}
-
-test "update_behavior" {
- // Given: Delta time, time
- // When: Each frame
- // Then: Update all systems
- // Test update: verify behavior is callable
- const func = @TypeOf(update);
- try std.testing.expect(func != void);
-}
-
-test "render_behavior" {
- // Given: Time, font
- // When: Each frame
- // Then: Clear, draw grid, panels, effects, status bar
- // Test render: verify behavior is callable
- const func = @TypeOf(render);
- try std.testing.expect(func != void);
-}
-
-test "draw_status_bar_behavior" {
- // Given: Time, font
- // When: Rendering UI
- // Then: Draw bottom status bar with system stats
- // Test draw_status_bar: verify behavior is callable
- const func = @TypeOf(draw_status_bar);
- try std.testing.expect(func != void);
-}
-
-test "draw_keyboard_hint_behavior" {
- // Given: Font
- // When: Rendering UI
- // Then: Draw top-left keyboard shortcut hint
- // Test draw_keyboard_hint: verify behavior is callable
- const func = @TypeOf(draw_keyboard_hint);
- try std.testing.expect(func != void);
-}
-
-test "shutdown_behavior" {
- // Given: Nothing
- // When: Window closes
- // Then: Unload fonts, close raylib
- // Test shutdown: verify behavior is callable
- const func = @TypeOf(shutdown);
- try std.testing.expect(func != void);
-}
-
-test "phi_constants" {
- try std.testing.expectApproxEqAbs(PHI * PHI_INV, 1.0, 1e-10);
- try std.testing.expectApproxEqAbs(PHI_SQ - PHI, 1.0, 1e-10);
-}
diff --git a/src/vsa/trinity_canvas/panel.zig b/src/vsa/trinity_canvas/panel.zig
deleted file mode 100644
index f6e38f3d74..0000000000
--- a/src/vsa/trinity_canvas/panel.zig
+++ /dev/null
@@ -1,443 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// trinity_panel v2.0.0 - Generated from .tri specification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sacred formula: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// Golden identity: ΟΒ² + 1/ΟΒ² = 3
-//
-// Author:
-// DO NOT EDIT - This file is auto-generated
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const math = std.math;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const MIN_WIDTH: f64 = 200;
-
-pub const MIN_HEIGHT: f64 = 150;
-
-pub const RESIZE_HANDLE_SIZE: f64 = 16;
-
-pub const TITLE_BAR_HEIGHT: f64 = 32;
-
-// Basic Ο-constants (Sacred Formula)
-pub const PHI: f64 = 1.618033988749895;
-pub const PHI_INV: f64 = 0.618033988749895;
-pub const PHI_SQ: f64 = 2.618033988749895;
-pub const TRINITY: f64 = 3.0;
-pub const SQRT5: f64 = 2.2360679774997896;
-pub const TAU: f64 = 6.283185307179586;
-pub const PI: f64 = 3.141592653589793;
-pub const E: f64 = 2.718281828459045;
-pub const PHOENIX: i64 = 999;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TYPES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Floating glassmorphism panel
-pub const GlassPanel = struct {
- x: f64,
- y: f64,
- width: f64,
- height: f64,
- target_x: f64,
- target_y: f64,
- target_width: f64,
- target_height: f64,
- state: PanelState,
- panel_type: PanelType,
- opacity: f64,
- scale: f64,
- scroll_y: f64,
- title: String[64],
- title_len: USize,
- is_focused: bool,
- focus_ripple: f64,
- pre_focus_x: f64,
- pre_focus_y: f64,
- pre_focus_w: f64,
- pre_focus_h: f64,
- jarvis_morph: f64,
- jarvis_glow_pulse: f64,
- jarvis_ring_rotation: f64,
- is_dragging: bool,
- is_resizing: bool,
- drag_offset_x: f64,
- drag_offset_y: f64,
- chat_messages: [8][256]u8,
- chat_msg_lens: [8]USize,
- chat_msg_is_user: [8]bool,
- chat_msg_count: USize,
- chat_input: String[256],
- chat_input_len: USize,
- chat_ripple: f64,
- code_wave_phase: f64,
- code_cursor_line: USize,
- tool_selected: USize,
- vision_analyzing: bool,
- vision_progress: f64,
- vision_result: String[256],
- vision_result_len: USize,
- voice_recording: bool,
- voice_wave_phase: f64,
- voice_amplitude: f64,
- finder_entries: [64]FinderEntry,
- finder_entry_count: USize,
- finder_path: String[512],
- finder_path_len: USize,
- finder_selected: USize,
- finder_animation: f64,
- finder_ripple: f64,
- sys_cpu_usage: f64,
- sys_mem_used: f64,
- sys_mem_total: f64,
- sys_cpu_temp: f64,
- sys_update_timer: f64,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MEMORY FOR WASM
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_buffer: [65536]u8 align(16) = undefined;
-var f64_buffer: [8192]f64 align(16) = undefined;
-
-export fn get_global_buffer_ptr() [*]u8 {
- return &global_buffer;
-}
-
-export fn get_f64_buffer_ptr() [*]f64 {
- return &f64_buffer;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CREATION PATTERNS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trit - ternary digit (-1, 0, +1)
-pub const Trit = enum(i8) {
- negative = -1, // FALSE
- zero = 0, // UNKNOWN
- positive = 1, // TRUE
-
- pub fn trit_and(a: Trit, b: Trit) Trit {
- return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_or(a: Trit, b: Trit) Trit {
- return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_not(a: Trit) Trit {
- return @enumFromInt(-@intFromEnum(a));
- }
-
- pub fn trit_xor(a: Trit, b: Trit) Trit {
- const av = @intFromEnum(a);
- const bv = @intFromEnum(b);
- if (av == 0 or bv == 0) return .zero;
- if (av == bv) return .negative;
- return .positive;
- }
-};
-
-/// Check TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-fn verify_trinity() f64 {
- return PHI * PHI + 1.0 / (PHI * PHI);
-}
-
-/// Ο-interpolation
-fn phi_lerp(a: f64, b: f64, t: f64) f64 {
- const phi_t = math.pow(f64, t, PHI_INV);
- return a + (b - a) * phi_t;
-}
-
-/// Ο-spiral generation
-fn generate_phi_spiral(n: u32, scale: f64, cx: f64, cy: f64) u32 {
- const max_points = f64_buffer.len / 2;
- const count = if (n > max_points) @as(u32, @intCast(max_points)) else n;
- var i: u32 = 0;
- while (i < count) : (i += 1) {
- const fi: f64 = @floatFromInt(i);
- const angle = fi * TAU * PHI_INV;
- const radius = scale * math.pow(f64, PHI, fi * 0.1);
- f64_buffer[i * 2] = cx + radius * @cos(angle);
- f64_buffer[i * 2 + 1] = cy + radius * @sin(angle);
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BEHAVIOR FUNCTIONS - Generated from behaviors
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// PanelType, x, y, width, height, title
-/// When: Creating new panel
-/// Then: Initialize all fields with defaults
-pub fn init() !void {
- // Initialize all fields with defaults
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Delta time, global time
-/// When: Each frame
-/// Then: Animate position, scale, opacity, panel-specific updates
-pub fn update() !void {
- // Update: Animate position, scale, opacity, panel-specific updates
- // Mutate state based on new data
- const state_changed = true;
- _ = state_changed;
-}
-
-/// Time, font
-/// When: Rendering panel
-/// Then: Draw background, title bar, content, handle
-pub fn draw() !void {
- // Draw background, title bar, content, handle
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, alpha
-/// When: Rendering title bar
-/// Then: Draw traffic light buttons, centered title
-pub fn draw_title_bar() !void {
- // Draw traffic light buttons, centered title
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, time, font, alpha
-/// When: Rendering content area
-/// Then: Dispatch to panel-type-specific drawer
-pub fn draw_content() !void {
- // Dispatch to panel-type-specific drawer
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Point x, y
-/// When: Hit testing
-/// Then: Return true if point inside panel bounds
-pub fn is_point_inside() !void {
- // Return true if point inside panel bounds
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Point x, y
-/// When: Hit testing for drag
-/// Then: Return true if point in title bar area
-pub fn is_point_in_title_bar() !void {
- // Return true if point in title bar area
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Point x, y
-/// When: Hit testing close button
-/// Then: Return true if point on red button
-pub fn is_point_on_close() !void {
- // Return true if point on red button
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Point x, y
-/// When: Hit testing resize handle
-/// Then: Return true if point in bottom-right corner
-pub fn is_point_on_resize() !void {
- // Return true if point in bottom-right corner
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Nothing
-/// When: Panel gains focus
-/// Then: Set is_focused, start ripple animation
-pub fn focus() !void {
- // Set is_focused, start ripple animation
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Nothing
-/// When: Panel loses focus
-/// Then: Clear is_focused, restore pre-focus position
-pub fn unfocus() !void {
- // Clear is_focused, restore pre-focus position
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Nothing
-/// When: JARVIS-style focus
-/// Then: Trigger spherical morph animation
-pub fn jarvis_focus() !void {
- // Trigger spherical morph animation
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Message text, is_user
-/// When: Adding chat message
-/// Then: Append to messages array, scroll if needed
-pub fn add_chat_message() !void {
- // Add: Append to messages array, scroll if needed
- // Append item to collection, check capacity
- const capacity: usize = 100;
- const count: usize = 1;
- const within_capacity = count < capacity;
- _ = within_capacity;
-}
-
-/// Path string
-/// When: Opening finder directory
-/// Then: Populate finder_entries array
-pub fn load_directory() !void {
- // I/O: Populate finder_entries array
- // Deserialize state from persistent storage
- const loaded = @as([]const u8, "loaded_state");
- _ = loaded;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS - Generated from behaviors and test_cases
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "init_behavior" {
- // Given: PanelType, x, y, width, height, title
- // When: Creating new panel
- // Then: Initialize all fields with defaults
- // Test init: verify lifecycle function exists
- try std.testing.expect(@TypeOf(init) != void);
-}
-
-test "update_behavior" {
- // Given: Delta time, global time
- // When: Each frame
- // Then: Animate position, scale, opacity, panel-specific updates
- // Test update: verify behavior is callable
- const func = @TypeOf(update);
- try std.testing.expect(func != void);
-}
-
-test "draw_behavior" {
- // Given: Time, font
- // When: Rendering panel
- // Then: Draw background, title bar, content, handle
- // Test draw: verify behavior is callable
- const func = @TypeOf(draw);
- try std.testing.expect(func != void);
-}
-
-test "draw_title_bar_behavior" {
- // Given: Rect, alpha
- // When: Rendering title bar
- // Then: Draw traffic light buttons, centered title
- // Test draw_title_bar: verify behavior is callable
- const func = @TypeOf(draw_title_bar);
- try std.testing.expect(func != void);
-}
-
-test "draw_content_behavior" {
- // Given: Rect, time, font, alpha
- // When: Rendering content area
- // Then: Dispatch to panel-type-specific drawer
- // Test draw_content: verify behavior is callable
- const func = @TypeOf(draw_content);
- try std.testing.expect(func != void);
-}
-
-test "is_point_inside_behavior" {
- // Given: Point x, y
- // When: Hit testing
- // Then: Return true if point inside panel bounds
- // Test is_point_inside: verify behavior is callable
- const func = @TypeOf(is_point_inside);
- try std.testing.expect(func != void);
-}
-
-test "is_point_in_title_bar_behavior" {
- // Given: Point x, y
- // When: Hit testing for drag
- // Then: Return true if point in title bar area
- // Test is_point_in_title_bar: verify behavior is callable
- const func = @TypeOf(is_point_in_title_bar);
- try std.testing.expect(func != void);
-}
-
-test "is_point_on_close_behavior" {
- // Given: Point x, y
- // When: Hit testing close button
- // Then: Return true if point on red button
- // Test is_point_on_close: verify behavior is callable
- const func = @TypeOf(is_point_on_close);
- try std.testing.expect(func != void);
-}
-
-test "is_point_on_resize_behavior" {
- // Given: Point x, y
- // When: Hit testing resize handle
- // Then: Return true if point in bottom-right corner
- // Test is_point_on_resize: verify behavior is callable
- const func = @TypeOf(is_point_on_resize);
- try std.testing.expect(func != void);
-}
-
-test "focus_behavior" {
- // Given: Nothing
- // When: Panel gains focus
- // Then: Set is_focused, start ripple animation
- // Test focus: verify behavior is callable
- const func = @TypeOf(focus);
- try std.testing.expect(func != void);
-}
-
-test "unfocus_behavior" {
- // Given: Nothing
- // When: Panel loses focus
- // Then: Clear is_focused, restore pre-focus position
- // Test unfocus: verify behavior is callable
- const func = @TypeOf(unfocus);
- try std.testing.expect(func != void);
-}
-
-test "jarvis_focus_behavior" {
- // Given: Nothing
- // When: JARVIS-style focus
- // Then: Trigger spherical morph animation
- // Test jarvis_focus: verify behavior is callable
- const func = @TypeOf(jarvis_focus);
- try std.testing.expect(func != void);
-}
-
-test "add_chat_message_behavior" {
- // Given: Message text, is_user
- // When: Adding chat message
- // Then: Append to messages array, scroll if needed
- // Test add_chat_message: verify behavior is callable
- const func = @TypeOf(add_chat_message);
- try std.testing.expect(func != void);
-}
-
-test "load_directory_behavior" {
- // Given: Path string
- // When: Opening finder directory
- // Then: Populate finder_entries array
- // Test load_directory: verify behavior is callable
- const func = @TypeOf(load_directory);
- try std.testing.expect(func != void);
-}
-
-test "phi_constants" {
- try std.testing.expectApproxEqAbs(PHI * PHI_INV, 1.0, 1e-10);
- try std.testing.expectApproxEqAbs(PHI_SQ - PHI, 1.0, 1e-10);
-}
diff --git a/src/vsa/trinity_canvas/panel_system.zig b/src/vsa/trinity_canvas/panel_system.zig
deleted file mode 100644
index 3fb32d28e3..0000000000
--- a/src/vsa/trinity_canvas/panel_system.zig
+++ /dev/null
@@ -1,342 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// panel_system v2.0.0 - Generated from .tri specification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sacred formula: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// Golden identity: ΟΒ² + 1/ΟΒ² = 3
-//
-// Author:
-// DO NOT EDIT - This file is auto-generated
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const math = std.math;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const MAX_PANELS: f64 = 8;
-
-// Basic Ο-constants (Sacred Formula)
-pub const PHI: f64 = 1.618033988749895;
-pub const PHI_INV: f64 = 0.618033988749895;
-pub const PHI_SQ: f64 = 2.618033988749895;
-pub const TRINITY: f64 = 3.0;
-pub const SQRT5: f64 = 2.2360679774997896;
-pub const TAU: f64 = 6.283185307179586;
-pub const PI: f64 = 3.141592653589793;
-pub const E: f64 = 2.718281828459045;
-pub const PHOENIX: i64 = 999;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TYPES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Manages all panels
-pub const PanelSystem = struct {
- panels: [8]GlassPanel,
- count: USize,
- active_panel: ?[]const u8,
- drag_panel: ?[]const u8,
- resize_panel: ?[]const u8,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MEMORY FOR WASM
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_buffer: [65536]u8 align(16) = undefined;
-var f64_buffer: [8192]f64 align(16) = undefined;
-
-export fn get_global_buffer_ptr() [*]u8 {
- return &global_buffer;
-}
-
-export fn get_f64_buffer_ptr() [*]f64 {
- return &f64_buffer;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CREATION PATTERNS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trit - ternary digit (-1, 0, +1)
-pub const Trit = enum(i8) {
- negative = -1, // FALSE
- zero = 0, // UNKNOWN
- positive = 1, // TRUE
-
- pub fn trit_and(a: Trit, b: Trit) Trit {
- return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_or(a: Trit, b: Trit) Trit {
- return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_not(a: Trit) Trit {
- return @enumFromInt(-@intFromEnum(a));
- }
-
- pub fn trit_xor(a: Trit, b: Trit) Trit {
- const av = @intFromEnum(a);
- const bv = @intFromEnum(b);
- if (av == 0 or bv == 0) return .zero;
- if (av == bv) return .negative;
- return .positive;
- }
-};
-
-/// Check TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-fn verify_trinity() f64 {
- return PHI * PHI + 1.0 / (PHI * PHI);
-}
-
-/// Ο-interpolation
-fn phi_lerp(a: f64, b: f64, t: f64) f64 {
- const phi_t = math.pow(f64, t, PHI_INV);
- return a + (b - a) * phi_t;
-}
-
-/// Ο-spiral generation
-fn generate_phi_spiral(n: u32, scale: f64, cx: f64, cy: f64) u32 {
- const max_points = f64_buffer.len / 2;
- const count = if (n > max_points) @as(u32, @intCast(max_points)) else n;
- var i: u32 = 0;
- while (i < count) : (i += 1) {
- const fi: f64 = @floatFromInt(i);
- const angle = fi * TAU * PHI_INV;
- const radius = scale * math.pow(f64, PHI, fi * 0.1);
- f64_buffer[i * 2] = cx + radius * @cos(angle);
- f64_buffer[i * 2 + 1] = cy + radius * @sin(angle);
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BEHAVIOR FUNCTIONS - Generated from behaviors
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Nothing
-/// When: System startup
-/// Then: Initialize empty panel array
-pub fn init() !void {
- // Initialize empty panel array
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// PanelType, x, y, width, height, title
-/// When: Creating new panel
-/// Then: Add panel to array, return index
-pub fn spawn() !void {
- // Add panel to array, return index
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Panel index
-/// When: Closing panel
-/// Then: Start closing animation, remove when done
-pub fn close() !void {
- // Start closing animation, remove when done
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// dt, time, mouse_x, mouse_y, mouse_pressed, mouse_down, mouse_released, mouse_wheel
-/// When: Each frame
-/// Then: Update all panels, handle drag/resize, scroll
-pub fn update() !void {
- // Update: Update all panels, handle drag/resize, scroll
- // Mutate state based on new data
- const state_changed = true;
- _ = state_changed;
-}
-
-/// Time, font
-/// When: Rendering
-/// Then: Draw all open panels in z-order
-pub fn draw() !void {
- // Draw all open panels in z-order
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// PanelType, x, y, width, height, title
-/// When: Focus request
-/// Then: Find existing panel of type or spawn new, bring to front
-pub fn focus_by_type() !void {
- // Find existing panel of type or spawn new, bring to front
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// PanelType, x, y, width, height, title
-/// When: JARVIS-style focus
-/// Then: Find/spawn panel, trigger JARVIS animation
-pub fn jarvis_focus() !void {
- // Find/spawn panel, trigger JARVIS animation
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Nothing
-/// When: ESC pressed
-/// Then: Unfocus all panels, restore positions
-pub fn unfocus_all() !void {
- // Unfocus all panels, restore positions
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Panel index
-/// When: Panel clicked
-/// Then: Move panel to end of array (top z-order)
-pub fn bring_to_front() !void {
- // Move panel to end of array (top z-order)
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Mouse x, y
-/// When: Mouse pressed
-/// Then: Check for panel hit, start drag/resize if needed
-pub fn handle_mouse_down() !void {
- // Response: Check for panel hit, start drag/resize if needed
- _ = @as([]const u8, "Check for panel hit, start drag/resize if needed");
-}
-
-/// Nothing
-/// When: Mouse released
-/// Then: End any drag/resize operation
-pub fn handle_mouse_up() !void {
- // Response: End any drag/resize operation
- _ = @as([]const u8, "End any drag/resize operation");
-}
-
-/// Mouse x, y
-/// When: Mouse moved while dragging/resizing
-/// Then: Update panel position/size
-pub fn handle_mouse_move() !void {
- // Response: Update panel position/size
- _ = @as([]const u8, "Update panel position/size");
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS - Generated from behaviors and test_cases
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "init_behavior" {
- // Given: Nothing
- // When: System startup
- // Then: Initialize empty panel array
- // Test init: verify lifecycle function exists
- try std.testing.expect(@TypeOf(init) != void);
-}
-
-test "spawn_behavior" {
- // Given: PanelType, x, y, width, height, title
- // When: Creating new panel
- // Then: Add panel to array, return index
- // Test spawn: verify behavior is callable
- const func = @TypeOf(spawn);
- try std.testing.expect(func != void);
-}
-
-test "close_behavior" {
- // Given: Panel index
- // When: Closing panel
- // Then: Start closing animation, remove when done
- // Test close: verify behavior is callable
- const func = @TypeOf(close);
- try std.testing.expect(func != void);
-}
-
-test "update_behavior" {
- // Given: dt, time, mouse_x, mouse_y, mouse_pressed, mouse_down, mouse_released, mouse_wheel
- // When: Each frame
- // Then: Update all panels, handle drag/resize, scroll
- // Test update: verify behavior is callable
- const func = @TypeOf(update);
- try std.testing.expect(func != void);
-}
-
-test "draw_behavior" {
- // Given: Time, font
- // When: Rendering
- // Then: Draw all open panels in z-order
- // Test draw: verify behavior is callable
- const func = @TypeOf(draw);
- try std.testing.expect(func != void);
-}
-
-test "focus_by_type_behavior" {
- // Given: PanelType, x, y, width, height, title
- // When: Focus request
- // Then: Find existing panel of type or spawn new, bring to front
- // Test focus_by_type: verify behavior is callable
- const func = @TypeOf(focus_by_type);
- try std.testing.expect(func != void);
-}
-
-test "jarvis_focus_behavior" {
- // Given: PanelType, x, y, width, height, title
- // When: JARVIS-style focus
- // Then: Find/spawn panel, trigger JARVIS animation
- // Test jarvis_focus: verify behavior is callable
- const func = @TypeOf(jarvis_focus);
- try std.testing.expect(func != void);
-}
-
-test "unfocus_all_behavior" {
- // Given: Nothing
- // When: ESC pressed
- // Then: Unfocus all panels, restore positions
- // Test unfocus_all: verify behavior is callable
- const func = @TypeOf(unfocus_all);
- try std.testing.expect(func != void);
-}
-
-test "bring_to_front_behavior" {
- // Given: Panel index
- // When: Panel clicked
- // Then: Move panel to end of array (top z-order)
- // Test bring_to_front: verify behavior is callable
- const func = @TypeOf(bring_to_front);
- try std.testing.expect(func != void);
-}
-
-test "handle_mouse_down_behavior" {
- // Given: Mouse x, y
- // When: Mouse pressed
- // Then: Check for panel hit, start drag/resize if needed
- // Test handle_mouse_down: verify behavior is callable
- const func = @TypeOf(handle_mouse_down);
- try std.testing.expect(func != void);
-}
-
-test "handle_mouse_up_behavior" {
- // Given: Nothing
- // When: Mouse released
- // Then: End any drag/resize operation
- // Test handle_mouse_up: verify behavior is callable
- const func = @TypeOf(handle_mouse_up);
- try std.testing.expect(func != void);
-}
-
-test "handle_mouse_move_behavior" {
- // Given: Mouse x, y
- // When: Mouse moved while dragging/resizing
- // Then: Update panel position/size
- // Test handle_mouse_move: verify behavior is callable
- const func = @TypeOf(handle_mouse_move);
- try std.testing.expect(func != void);
-}
-
-test "phi_constants" {
- try std.testing.expectApproxEqAbs(PHI * PHI_INV, 1.0, 1e-10);
- try std.testing.expectApproxEqAbs(PHI_SQ - PHI, 1.0, 1e-10);
-}
diff --git a/src/vsa/trinity_canvas/panels/system.zig b/src/vsa/trinity_canvas/panels/system.zig
deleted file mode 100644
index c33c346f62..0000000000
--- a/src/vsa/trinity_canvas/panels/system.zig
+++ /dev/null
@@ -1,436 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// system_panel v2.0.0 - Generated from .tri specification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sacred formula: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// Golden identity: ΟΒ² + 1/ΟΒ² = 3
-//
-// Author:
-// DO NOT EDIT - This file is auto-generated
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const math = std.math;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const UPDATE_INTERVAL: f64 = 2;
-
-pub const BAR_HEIGHT: f64 = 8;
-
-pub const ROW_HEIGHT: f64 = 50;
-
-pub const MARGIN: f64 = 20;
-
-pub const CPU_WARNING: f64 = 50;
-
-pub const CPU_CRITICAL: f64 = 80;
-
-pub const MEM_WARNING: f64 = 0.5;
-
-pub const MEM_CRITICAL: f64 = 0.8;
-
-pub const TEMP_WARNING: f64 = 60;
-
-pub const TEMP_CRITICAL: f64 = 80;
-
-pub const DISK_WARNING: f64 = 0.7;
-
-pub const DISK_CRITICAL: f64 = 0.9;
-
-// Basic Ο-constants (Sacred Formula)
-pub const PHI: f64 = 1.618033988749895;
-pub const PHI_INV: f64 = 0.618033988749895;
-pub const PHI_SQ: f64 = 2.618033988749895;
-pub const TRINITY: f64 = 3.0;
-pub const SQRT5: f64 = 2.2360679774997896;
-pub const TAU: f64 = 6.283185307179586;
-pub const PI: f64 = 3.141592653589793;
-pub const E: f64 = 2.718281828459045;
-pub const PHOENIX: i64 = 999;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TYPES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// CPU metrics
-pub const CpuInfo = struct {
- usage_percent: f64,
- core_count: U8,
- frequency_mhz: U32,
- model_name: String[64],
-};
-
-/// Memory metrics
-pub const MemoryInfo = struct {
- used_gb: f64,
- total_gb: f64,
- swap_used_gb: f64,
- swap_total_gb: f64,
- cached_gb: f64,
-};
-
-/// Temperature sensors
-pub const TemperatureInfo = struct {
- cpu_temp: f64,
- gpu_temp: f64,
- ssd_temp: f64,
-};
-
-/// Disk I/O and space
-pub const DiskInfo = struct {
- read_mb_s: f64,
- write_mb_s: f64,
- used_gb: f64,
- total_gb: f64,
- device_name: String[32],
-};
-
-/// Network I/O
-pub const NetworkInfo = struct {
- rx_kb_s: f64,
- tx_kb_s: f64,
- interface_name: String[16],
- ip_address: String[16],
-};
-
-/// Process stats
-pub const ProcessInfo = struct {
- process_count: U32,
- thread_count: U32,
- zombie_count: U32,
-};
-
-/// Complete system metrics
-pub const SystemMetrics = struct {
- cpu: CpuInfo,
- memory: MemoryInfo,
- temperature: TemperatureInfo,
- disk: DiskInfo,
- network: NetworkInfo,
- process: ProcessInfo,
- uptime_seconds: U64,
- update_timer: f64,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MEMORY FOR WASM
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_buffer: [65536]u8 align(16) = undefined;
-var f64_buffer: [8192]f64 align(16) = undefined;
-
-export fn get_global_buffer_ptr() [*]u8 {
- return &global_buffer;
-}
-
-export fn get_f64_buffer_ptr() [*]f64 {
- return &f64_buffer;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CREATION PATTERNS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trit - ternary digit (-1, 0, +1)
-pub const Trit = enum(i8) {
- negative = -1, // FALSE
- zero = 0, // UNKNOWN
- positive = 1, // TRUE
-
- pub fn trit_and(a: Trit, b: Trit) Trit {
- return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_or(a: Trit, b: Trit) Trit {
- return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_not(a: Trit) Trit {
- return @enumFromInt(-@intFromEnum(a));
- }
-
- pub fn trit_xor(a: Trit, b: Trit) Trit {
- const av = @intFromEnum(a);
- const bv = @intFromEnum(b);
- if (av == 0 or bv == 0) return .zero;
- if (av == bv) return .negative;
- return .positive;
- }
-};
-
-/// Check TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-fn verify_trinity() f64 {
- return PHI * PHI + 1.0 / (PHI * PHI);
-}
-
-/// Ο-interpolation
-fn phi_lerp(a: f64, b: f64, t: f64) f64 {
- const phi_t = math.pow(f64, t, PHI_INV);
- return a + (b - a) * phi_t;
-}
-
-/// Ο-spiral generation
-fn generate_phi_spiral(n: u32, scale: f64, cx: f64, cy: f64) u32 {
- const max_points = f64_buffer.len / 2;
- const count = if (n > max_points) @as(u32, @intCast(max_points)) else n;
- var i: u32 = 0;
- while (i < count) : (i += 1) {
- const fi: f64 = @floatFromInt(i);
- const angle = fi * TAU * PHI_INV;
- const radius = scale * math.pow(f64, PHI, fi * 0.1);
- f64_buffer[i * 2] = cx + radius * @cos(angle);
- f64_buffer[i * 2 + 1] = cy + radius * @sin(angle);
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BEHAVIOR FUNCTIONS - Generated from behaviors
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Nothing
-/// When: Creating system panel
-/// Then: Initialize all metrics to default/simulated values
-pub fn init() !void {
- // Initialize all metrics to default/simulated values
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Delta time
-/// When: Each frame
-/// Then: Update timer, refresh metrics if interval elapsed
-pub fn update() !void {
- // Update: Update timer, refresh metrics if interval elapsed
- // Mutate state based on new data
- const state_changed = true;
- _ = state_changed;
-}
-
-/// Nothing
-/// When: Update interval reached
-/// Then: Read system metrics (macOS sysctl or simulated)
-pub fn fetch_metrics() !void {
- // Read system metrics (macOS sysctl or simulated)
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Panel rect, time, font
-/// When: Rendering panel content
-/// Then: Draw all metric sections with bars and labels
-pub fn draw() !void {
- // Draw all metric sections with bars and labels
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, CpuInfo, time
-/// When: Drawing CPU row
-/// Then: Draw label, usage bar, percentage, core info
-pub fn draw_cpu_section() !void {
- // Draw label, usage bar, percentage, core info
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, MemoryInfo, time
-/// When: Drawing memory row
-/// Then: Draw label, RAM bar, swap bar, values
-pub fn draw_memory_section() !void {
- // Draw label, RAM bar, swap bar, values
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, TemperatureInfo, time
-/// When: Drawing temperature row
-/// Then: Draw CPU/GPU temp bars with color thresholds
-pub fn draw_temperature_section() !void {
- // Draw CPU/GPU temp bars with color thresholds
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, DiskInfo, time
-/// When: Drawing disk row
-/// Then: Draw space bar, I/O rates
-pub fn draw_disk_section() !void {
- // Draw space bar, I/O rates
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, NetworkInfo, time
-/// When: Drawing network row
-/// Then: Draw RX/TX rates with arrows
-pub fn draw_network_section() !void {
- // Draw RX/TX rates with arrows
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, ProcessInfo, time
-/// When: Drawing process row
-/// Then: Draw process/thread counts
-pub fn draw_process_section() !void {
- // Draw process/thread counts
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Rect, uptime_seconds
-/// When: Drawing uptime row
-/// Then: Format and draw "Xd Xh Xm Xs"
-pub fn draw_uptime() !void {
- // Format and draw "Xd Xh Xm Xs"
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Bytes as Float
-/// When: Displaying size
-/// Then: Return formatted string (KB, MB, GB)
-pub fn format_bytes() !void {
- // Return formatted string (KB, MB, GB)
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// Seconds as U64
-/// When: Displaying uptime
-/// Then: Return formatted "Xd Xh Xm" string
-pub fn format_uptime() !void {
- // Return formatted "Xd Xh Xm" string
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS - Generated from behaviors and test_cases
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "init_behavior" {
- // Given: Nothing
- // When: Creating system panel
- // Then: Initialize all metrics to default/simulated values
- // Test init: verify lifecycle function exists
- try std.testing.expect(@TypeOf(init) != void);
-}
-
-test "update_behavior" {
- // Given: Delta time
- // When: Each frame
- // Then: Update timer, refresh metrics if interval elapsed
- // Test update: verify behavior is callable
- const func = @TypeOf(update);
- try std.testing.expect(func != void);
-}
-
-test "fetch_metrics_behavior" {
- // Given: Nothing
- // When: Update interval reached
- // Then: Read system metrics (macOS sysctl or simulated)
- // Test fetch_metrics: verify behavior is callable
- const func = @TypeOf(fetch_metrics);
- try std.testing.expect(func != void);
-}
-
-test "draw_behavior" {
- // Given: Panel rect, time, font
- // When: Rendering panel content
- // Then: Draw all metric sections with bars and labels
- // Test draw: verify behavior is callable
- const func = @TypeOf(draw);
- try std.testing.expect(func != void);
-}
-
-test "draw_cpu_section_behavior" {
- // Given: Rect, CpuInfo, time
- // When: Drawing CPU row
- // Then: Draw label, usage bar, percentage, core info
- // Test draw_cpu_section: verify behavior is callable
- const func = @TypeOf(draw_cpu_section);
- try std.testing.expect(func != void);
-}
-
-test "draw_memory_section_behavior" {
- // Given: Rect, MemoryInfo, time
- // When: Drawing memory row
- // Then: Draw label, RAM bar, swap bar, values
- // Test draw_memory_section: verify behavior is callable
- const func = @TypeOf(draw_memory_section);
- try std.testing.expect(func != void);
-}
-
-test "draw_temperature_section_behavior" {
- // Given: Rect, TemperatureInfo, time
- // When: Drawing temperature row
- // Then: Draw CPU/GPU temp bars with color thresholds
- // Test draw_temperature_section: verify behavior is callable
- const func = @TypeOf(draw_temperature_section);
- try std.testing.expect(func != void);
-}
-
-test "draw_disk_section_behavior" {
- // Given: Rect, DiskInfo, time
- // When: Drawing disk row
- // Then: Draw space bar, I/O rates
- // Test draw_disk_section: verify behavior is callable
- const func = @TypeOf(draw_disk_section);
- try std.testing.expect(func != void);
-}
-
-test "draw_network_section_behavior" {
- // Given: Rect, NetworkInfo, time
- // When: Drawing network row
- // Then: Draw RX/TX rates with arrows
- // Test draw_network_section: verify behavior is callable
- const func = @TypeOf(draw_network_section);
- try std.testing.expect(func != void);
-}
-
-test "draw_process_section_behavior" {
- // Given: Rect, ProcessInfo, time
- // When: Drawing process row
- // Then: Draw process/thread counts
- // Test draw_process_section: verify behavior is callable
- const func = @TypeOf(draw_process_section);
- try std.testing.expect(func != void);
-}
-
-test "draw_uptime_behavior" {
- // Given: Rect, uptime_seconds
- // When: Drawing uptime row
- // Then: Format and draw "Xd Xh Xm Xs"
- // Test draw_uptime: verify behavior is callable
- const func = @TypeOf(draw_uptime);
- try std.testing.expect(func != void);
-}
-
-test "format_bytes_behavior" {
- // Given: Bytes as Float
- // When: Displaying size
- // Then: Return formatted string (KB, MB, GB)
- // Test format_bytes: verify behavior is callable
- const func = @TypeOf(format_bytes);
- try std.testing.expect(func != void);
-}
-
-test "format_uptime_behavior" {
- // Given: Seconds as U64
- // When: Displaying uptime
- // Then: Return formatted "Xd Xh Xm" string
- // Test format_uptime: verify behavior is callable
- const func = @TypeOf(format_uptime);
- try std.testing.expect(func != void);
-}
-
-test "phi_constants" {
- try std.testing.expectApproxEqAbs(PHI * PHI_INV, 1.0, 1e-10);
- try std.testing.expectApproxEqAbs(PHI_SQ - PHI, 1.0, 1e-10);
-}
diff --git a/src/vsa/trinity_canvas/sacred_worlds.zig b/src/vsa/trinity_canvas/sacred_worlds.zig
deleted file mode 100644
index 68fdb17b9f..0000000000
--- a/src/vsa/trinity_canvas/sacred_worlds.zig
+++ /dev/null
@@ -1,211 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SACRED WORLDS β 27 Practical Panels of the Trinity Kingdom
-// 999 = 37 Γ 27 = SACRED_MULTIPLIER Γ TRIDEVYATITSA
-// 27 = 3Β³ = (ΟΒ² + 1/ΟΒ²)Β³
-// V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ENUMS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const RealmId = enum(u8) {
- razum = 0, // Ο β AI & Communication (Gold)
- materiya = 1, // Ο β Tools & System (Cyan)
- dukh = 2, // e β Content & Knowledge (Purple)
-};
-
-pub const DomainId = enum(u8) {
- // Realm 1: RAZUM β AI
- ai_chat = 0,
- ai_code = 1,
- ai_create = 2,
- // Realm 2: MATERIYA β Tools
- filesystem = 3,
- devtools = 4,
- infrastructure = 5,
- // Realm 3: DUKH β Content
- knowledge = 6,
- content = 7,
- community = 8,
-};
-
-pub const WorldId = enum(u8) {
- // Realm 1: RAZUM (Ο) β AI & Communication, blocks 0-8
- chat = 0,
- code = 1,
- explain = 2,
- debug = 3,
- review = 4,
- translate = 5,
- vibee = 6,
- voice = 7,
- compose = 8,
- // Realm 2: MATERIYA (Ο) β Tools & System, blocks 9-17
- files = 9,
- editor = 10,
- build = 11,
- test_run = 12,
- terminal = 13,
- git = 14,
- deploy = 15,
- monitor = 16,
- settings = 17,
- // Realm 3: DUKH (e) β Content & Knowledge, blocks 18-26
- docs = 18,
- reels = 19,
- feed = 20,
- roadmap = 21,
- benchmarks = 22,
- research = 23,
- formulas = 24,
- community_world = 25,
- about = 26,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// WORLD INFO
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const WorldInfo = struct {
- id: WorldId,
- realm: RealmId,
- domain: DomainId,
- name: [24]u8,
- name_len: u8,
- formula: [48]u8,
- formula_len: u8,
- sacred_value: f32,
-};
-
-fn mkName(comptime s: []const u8) [24]u8 {
- var buf: [24]u8 = [_]u8{0} ** 24;
- for (s, 0..) |c, i| buf[i] = c;
- return buf;
-}
-
-fn mkFormula(comptime s: []const u8) [48]u8 {
- var buf: [48]u8 = [_]u8{0} ** 48;
- for (s, 0..) |c, i| buf[i] = c;
- return buf;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// STATIC DATA TABLE β 27 WORLDS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const WORLDS: [27]WorldInfo = .{
- // ββ Realm 1: RAZUM (Ο) β AI & Communication, blocks 0-8 ββ
- // Domain: AI Chat
- .{ .id = .chat, .realm = .razum, .domain = .ai_chat, .name = mkName("CHAT"), .name_len = 4, .formula = mkFormula("phi = 1.618"), .formula_len = 11, .sacred_value = 1.618 },
- .{ .id = .code, .realm = .razum, .domain = .ai_chat, .name = mkName("CODE"), .name_len = 4, .formula = mkFormula("pi*phi*e = 13.82"), .formula_len = 16, .sacred_value = 13.82 },
- .{ .id = .explain, .realm = .razum, .domain = .ai_chat, .name = mkName("EXPLAIN"), .name_len = 7, .formula = mkFormula("L(10) = 123"), .formula_len = 11, .sacred_value = 123.0 },
- // Domain: AI Code
- .{ .id = .debug, .realm = .razum, .domain = .ai_code, .name = mkName("DEBUG"), .name_len = 5, .formula = mkFormula("1/a = 137.036"), .formula_len = 13, .sacred_value = 137.036 },
- .{ .id = .review, .realm = .razum, .domain = .ai_code, .name = mkName("REVIEW"), .name_len = 6, .formula = mkFormula("phi2 = phi+1 = 2.618"), .formula_len = 20, .sacred_value = 2.618 },
- .{ .id = .translate, .realm = .razum, .domain = .ai_code, .name = mkName("TRANSLATE"), .name_len = 9, .formula = mkFormula("Feigenbaum d = 4.669"), .formula_len = 20, .sacred_value = 4.669 },
- // Domain: AI Create
- .{ .id = .tri, .realm = .razum, .domain = .ai_create, .name = mkName("VIBEE"), .name_len = 5, .formula = mkFormula("F(7) = 13"), .formula_len = 9, .sacred_value = 13.0 },
- .{ .id = .voice, .realm = .razum, .domain = .ai_create, .name = mkName("VOICE"), .name_len = 5, .formula = mkFormula("sqrt(5) = 2.236"), .formula_len = 15, .sacred_value = 2.236 },
- .{ .id = .compose, .realm = .razum, .domain = .ai_create, .name = mkName("COMPOSE"), .name_len = 7, .formula = mkFormula("999 = 37 x 27"), .formula_len = 13, .sacred_value = 999.0 },
-
- // ββ Realm 2: MATERIYA (Ο) β Tools & System, blocks 9-17 ββ
- // Domain: Filesystem
- .{ .id = .files, .realm = .materiya, .domain = .filesystem, .name = mkName("FILES"), .name_len = 5, .formula = mkFormula("pi = 3.14159"), .formula_len = 12, .sacred_value = 3.14159 },
- .{ .id = .editor, .realm = .materiya, .domain = .filesystem, .name = mkName("EDITOR"), .name_len = 6, .formula = mkFormula("27 = 3^3"), .formula_len = 8, .sacred_value = 27.0 },
- .{ .id = .build, .realm = .materiya, .domain = .filesystem, .name = mkName("BUILD"), .name_len = 5, .formula = mkFormula("CHSH = 2*sqrt(2) = 2.83"), .formula_len = 22, .sacred_value = 2.828 },
- // Domain: Dev Tools
- .{ .id = .test_run, .realm = .materiya, .domain = .devtools, .name = mkName("TEST"), .name_len = 4, .formula = mkFormula("m_p/m_e = 1836"), .formula_len = 14, .sacred_value = 1836.15 },
- .{ .id = .terminal, .realm = .materiya, .domain = .devtools, .name = mkName("TERMINAL"), .name_len = 8, .formula = mkFormula("pi2 = 9.87"), .formula_len = 10, .sacred_value = 9.87 },
- .{ .id = .git, .realm = .materiya, .domain = .devtools, .name = mkName("GIT"), .name_len = 3, .formula = mkFormula("e^pi = 23.14"), .formula_len = 12, .sacred_value = 23.14 },
- // Domain: Infrastructure
- .{ .id = .deploy, .realm = .materiya, .domain = .infrastructure, .name = mkName("DEPLOY"), .name_len = 6, .formula = mkFormula("E8 dim = 248"), .formula_len = 12, .sacred_value = 248.0 },
- .{ .id = .monitor, .realm = .materiya, .domain = .infrastructure, .name = mkName("DePIN NODE"), .name_len = 10, .formula = mkFormula("phi2+1/phi2 = 3 = $TRI"), .formula_len = 22, .sacred_value = 3.0 },
- .{ .id = .settings, .realm = .materiya, .domain = .infrastructure, .name = mkName("SETTINGS"), .name_len = 8, .formula = mkFormula("76 photons"), .formula_len = 10, .sacred_value = 76.0 },
-
- // ββ Realm 3: DUKH (e) β Content & Knowledge, blocks 18-26 ββ
- // Domain: Knowledge
- .{ .id = .docs, .realm = .dukh, .domain = .knowledge, .name = mkName("DOCS"), .name_len = 4, .formula = mkFormula("phi2+1/phi2 = 3 = TRINITY"), .formula_len = 24, .sacred_value = 3.0 },
- .{ .id = .reels, .realm = .dukh, .domain = .knowledge, .name = mkName("REELS"), .name_len = 5, .formula = mkFormula("tau = 2*pi = 6.283"), .formula_len = 18, .sacred_value = 6.283 },
- .{ .id = .feed, .realm = .dukh, .domain = .knowledge, .name = mkName("FEED"), .name_len = 4, .formula = mkFormula("Menger D = ln20/ln3"), .formula_len = 19, .sacred_value = 2.727 },
- // Domain: Content
- .{ .id = .roadmap, .realm = .dukh, .domain = .content, .name = mkName("ROADMAP"), .name_len = 7, .formula = mkFormula("mu = 0.0382"), .formula_len = 11, .sacred_value = 0.0382 },
- .{ .id = .benchmarks, .realm = .dukh, .domain = .content, .name = mkName("BENCHMARKS"), .name_len = 10, .formula = mkFormula("chi = 0.0618"), .formula_len = 12, .sacred_value = 0.0618 },
- .{ .id = .research, .realm = .dukh, .domain = .content, .name = mkName("RESEARCH"), .name_len = 8, .formula = mkFormula("sigma = phi = 1.618"), .formula_len = 19, .sacred_value = 1.618 },
- // Domain: Community
- .{ .id = .formulas, .realm = .dukh, .domain = .community, .name = mkName("FORMULAS"), .name_len = 8, .formula = mkFormula("e = 2.71828"), .formula_len = 11, .sacred_value = 2.718 },
- .{ .id = .community_world, .realm = .dukh, .domain = .community, .name = mkName("COMMUNITY"), .name_len = 9, .formula = mkFormula("Universe = 13.82 Gyr"), .formula_len = 20, .sacred_value = 13.82 },
- .{ .id = .about, .realm = .dukh, .domain = .community, .name = mkName("ABOUT"), .name_len = 5, .formula = mkFormula("H0 = 70.74 km/s/Mpc"), .formula_len = 19, .sacred_value = 70.74 },
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// REALM NAMES & COLORS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const REALM_NAMES = [3][12]u8{
- [_]u8{ 'R', 'A', 'Z', 'U', 'M', 0, 0, 0, 0, 0, 0, 0 }, // Ο
- [_]u8{ 'M', 'A', 'T', 'E', 'R', 'I', 'Y', 'A', 0, 0, 0, 0 }, // Ο
- [_]u8{ 'D', 'U', 'K', 'H', 0, 0, 0, 0, 0, 0, 0, 0 }, // e
-};
-pub const REALM_NAME_LENS = [3]u8{ 5, 8, 4 };
-
-pub const REALM_SYMBOLS = [3][6]u8{
- [_]u8{ 'p', 'h', 'i', 0, 0, 0 }, // Ο
- [_]u8{ 'p', 'i', 0, 0, 0, 0 }, // Ο
- [_]u8{ 'e', 0, 0, 0, 0, 0 }, // e
-};
-pub const REALM_SYMBOL_LENS = [3]u8{ 3, 2, 1 };
-
-// Realm colors: Gold, Cyan, Purple (RGBA)
-pub const REALM_COLORS_R = [3]u8{ 0xFF, 0x50, 0xBD };
-pub const REALM_COLORS_G = [3]u8{ 0xD7, 0xFA, 0x93 };
-pub const REALM_COLORS_B = [3]u8{ 0x00, 0xFA, 0xF9 };
-
-pub const DOMAIN_NAMES = [9][16]u8{
- mkDomain("AI Chat"),
- mkDomain("AI Code"),
- mkDomain("AI Create"),
- mkDomain("Filesystem"),
- mkDomain("Dev Tools"),
- mkDomain("Infrastructure"),
- mkDomain("Knowledge"),
- mkDomain("Content"),
- mkDomain("Community"),
-};
-pub const DOMAIN_NAME_LENS = [9]u8{ 7, 7, 9, 10, 9, 14, 9, 7, 9 };
-
-fn mkDomain(comptime s: []const u8) [16]u8 {
- var buf: [16]u8 = [_]u8{0} ** 16;
- for (s, 0..) |c, i| buf[i] = c;
- return buf;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LOOKUP FUNCTIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Get WorldInfo by block index (0-26)
-pub fn getWorldByBlock(block_index: usize) WorldInfo {
- if (block_index >= 27) return WORLDS[0];
- return WORLDS[block_index];
-}
-
-/// Get RealmId from block index
-pub fn blockToRealm(block_index: usize) RealmId {
- if (block_index < 9) return .razum;
- if (block_index < 18) return .materiya;
- return .dukh;
-}
-
-/// Get realm color components
-pub fn realmColorR(realm: RealmId) u8 {
- return REALM_COLORS_R[@intFromEnum(realm)];
-}
-pub fn realmColorG(realm: RealmId) u8 {
- return REALM_COLORS_G[@intFromEnum(realm)];
-}
-pub fn realmColorB(realm: RealmId) u8 {
- return REALM_COLORS_B[@intFromEnum(realm)];
-}
diff --git a/src/vsa/trinity_canvas/theme.zig b/src/vsa/trinity_canvas/theme.zig
deleted file mode 100644
index f8773b93f8..0000000000
--- a/src/vsa/trinity_canvas/theme.zig
+++ /dev/null
@@ -1,708 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TRINITY THEME v3.0.0 β DARK/LIGHT SWITCHABLE
-// Single source of truth for ALL colors, fonts, and styles
-// Generated from specs/tri/trinity_canvas/theme.tri + enhanced
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MATH CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const PHI: f32 = 1.6180339887;
-pub const PHI_INV: f32 = 0.6180339887;
-pub const TAU: f32 = 6.28318530718;
-pub const PHI_SQ: f32 = 2.618033988749895;
-pub const TRINITY: f32 = 3.0;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// COLOR TYPE (compatible with any cImport of raylib)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const Color = extern struct {
- r: u8,
- g: u8,
- b: u8,
- a: u8,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// THEME MODE
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const ThemeMode = enum { dark, light };
-pub var current_mode: ThemeMode = .dark;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ACCENT COLORS β theme-invariant (same in dark and light)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const accents = struct {
- pub const magenta = Color{ .r = 0xF8, .g = 0x1C, .b = 0xE5, .a = 0xFF };
- pub const cyan = Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = 0xFF };
- pub const green = Color{ .r = 0x50, .g = 0xFA, .b = 0x7B, .a = 0xFF };
- pub const yellow = Color{ .r = 0xF1, .g = 0xFA, .b = 0x8C, .a = 0xFF };
- pub const red = Color{ .r = 0xFF, .g = 0x55, .b = 0x55, .a = 0xFF };
- pub const blue = Color{ .r = 0x8B, .g = 0xE9, .b = 0xFD, .a = 0xFF };
- pub const orange = Color{ .r = 0xFF, .g = 0xB8, .b = 0x6C, .a = 0xFF };
- pub const purple = Color{ .r = 0xBD, .g = 0x93, .b = 0xF9, .a = 0xFF };
- pub const logo_green = Color{ .r = 0x08, .g = 0xFA, .b = 0xB5, .a = 0xFF };
- pub const gold = Color{ .r = 0xFF, .g = 0xD7, .b = 0x00, .a = 0xFF };
-
- // Semantic
- pub const success = green;
- pub const warning = yellow;
- pub const error_ = red;
- pub const info = cyan;
- pub const primary = magenta;
-
- // Glow variants
- pub const glow_magenta = Color{ .r = 0xF8, .g = 0x1C, .b = 0xE5, .a = 0x28 };
- pub const glow_cyan = Color{ .r = 0x50, .g = 0xFA, .b = 0xFA, .a = 0x28 };
- pub const glow_green = Color{ .r = 0x50, .g = 0xFA, .b = 0x7B, .a = 0x28 };
-
- // Recording
- pub const recording_red = Color{ .r = 0xFF, .g = 0x40, .b = 0x40, .a = 0xFF };
- pub const recording_dim = Color{ .r = 0x80, .g = 0x20, .b = 0x20, .a = 0xFF };
-
- // File type colors
- pub const file_folder = green;
- pub const file_zig = Color{ .r = 0xF7, .g = 0xA4, .b = 0x1D, .a = 0xFF };
- pub const file_code = Color{ .r = 0x80, .g = 0xFF, .b = 0xA0, .a = 0xFF };
- pub const file_image = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- pub const file_audio = Color{ .r = 0x00, .g = 0xCC, .b = 0x66, .a = 0xFF };
- pub const file_document = Color{ .r = 0xC0, .g = 0xC0, .b = 0xC0, .a = 0xFF };
- pub const file_data = green;
- pub const file_unknown = Color{ .r = 0x6B, .g = 0x6B, .b = 0x6B, .a = 0xFF };
-
- // Border focus
- pub const border_focus = magenta;
-
- // Network node status colors
- pub const node_online = green;
- pub const node_offline = Color{ .r = 0x60, .g = 0x60, .b = 0x60, .a = 0xFF };
- pub const node_connecting = yellow;
- pub const node_degraded = orange;
- pub const node_error = red;
- pub const node_local = cyan;
- pub const node_remote = magenta;
- pub const node_layer_bar = Color{ .r = 0x30, .g = 0x30, .b = 0x40, .a = 0xFF };
-
- // Status color functions
- pub fn cpuColor(usage: f32) Color {
- if (usage > 80) return red;
- if (usage > 50) return yellow;
- return green;
- }
- pub fn memColor(pct: f32) Color {
- if (pct > 0.8) return red;
- if (pct > 0.5) return yellow;
- return magenta;
- }
- pub fn tempColor(temp: f32) Color {
- if (temp > 80) return red;
- if (temp > 60) return yellow;
- return cyan;
- }
- pub fn diskColor(pct: f32) Color {
- if (pct > 0.9) return red;
- if (pct > 0.7) return yellow;
- return blue;
- }
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// DARK PALETTE (private)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const dark = struct {
- // Backgrounds
- const bg = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- const bg_surface = Color{ .r = 0x0A, .g = 0x0A, .b = 0x0A, .a = 0xFF };
- const bg_panel = Color{ .r = 0x0D, .g = 0x0D, .b = 0x0D, .a = 0xF5 };
- const bg_input = Color{ .r = 0x10, .g = 0x10, .b = 0x10, .a = 0xFF };
- const bg_hover = Color{ .r = 0x18, .g = 0x18, .b = 0x18, .a = 0xFF };
- const bg_bar = Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 0xFF };
- const bg_selected = Color{ .r = 0x20, .g = 0x20, .b = 0x20, .a = 0xFF };
- // Text
- const text = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const text_muted = Color{ .r = 0x6B, .g = 0x6B, .b = 0x6B, .a = 0xFF };
- const text_dim = Color{ .r = 0x50, .g = 0x50, .b = 0x50, .a = 0xFF };
- const text_hint = Color{ .r = 0x66, .g = 0x66, .b = 0x66, .a = 0xFF };
- const text_bright = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const content_text = Color{ .r = 0xC0, .g = 0xC8, .b = 0xD0, .a = 0xFF };
- // Borders
- const border = Color{ .r = 0x33, .g = 0x33, .b = 0x33, .a = 0xFF };
- const border_subtle = Color{ .r = 0x22, .g = 0x22, .b = 0x22, .a = 0xFF };
- const border_light = Color{ .r = 0x40, .g = 0x40, .b = 0x40, .a = 0xFF };
- const separator = Color{ .r = 0x80, .g = 0x80, .b = 0x80, .a = 0xFF };
- // Logo
- const logo_petal = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- const logo_outline = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const logo_highlight = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- // Panel
- const panel_title = Color{ .r = 0xE0, .g = 0xE0, .b = 0xE0, .a = 0xFF };
- const panel_title_sep = Color{ .r = 0x80, .g = 0x80, .b = 0x80, .a = 0xFF };
- const sacred_world_bg = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- // Tooltip (inverted on dark: white bg, black text)
- const tooltip_bg = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xF0 };
- const tooltip_text = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- // Formula
- const formula_text = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- // UI elements
- const name_label_bg = Color{ .r = 0x10, .g = 0x10, .b = 0x10, .a = 0xFF };
- const name_label_text = Color{ .r = 0xE0, .g = 0xE0, .b = 0xE0, .a = 0xFF };
- const line_number = Color{ .r = 0x60, .g = 0x60, .b = 0x60, .a = 0xFF };
- const resize_handle = Color{ .r = 0x60, .g = 0x60, .b = 0x60, .a = 0xFF };
- const settings_toggle_off = Color{ .r = 0x40, .g = 0x40, .b = 0x50, .a = 0xFF };
- const settings_toggle_on = Color{ .r = 0x28, .g = 0xC8, .b = 0x40, .a = 0xFF };
- const tool_selected_bg = Color{ .r = 0x18, .g = 0x28, .b = 0x18, .a = 0xFF };
- const drop_zone_border = Color{ .r = 0x40, .g = 0x40, .b = 0x40, .a = 0xFF };
- const drop_zone_plus = Color{ .r = 0x60, .g = 0x60, .b = 0x60, .a = 0xFF };
- const progress_bar_bg = Color{ .r = 0x40, .g = 0x40, .b = 0x50, .a = 0xFF };
- // Chat panel
- const chat_text = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const chat_label_user = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const chat_label_ai = Color{ .r = 0x4A, .g = 0xDE, .b = 0x80, .a = 0xFF };
- const chat_bubble_user = Color{ .r = 0x1A, .g = 0x1E, .b = 0x24, .a = 0xFF };
- const chat_bubble_ai = Color{ .r = 0x14, .g = 0x1A, .b = 0x20, .a = 0xFF };
- const chat_bubble_border = Color{ .r = 0x30, .g = 0x38, .b = 0x40, .a = 0xFF };
- // Dark theme: white header/input, black text (inverted contrast)
- const chat_input_bg = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const chat_input_border = Color{ .r = 0xCC, .g = 0xCC, .b = 0xCC, .a = 0xFF };
- const chat_input_text = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- const sacred_header_bg = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const sacred_header_text = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- // Panel transparency: 230/255 = semi-transparent glass
- const panel_content_alpha: f32 = 180;
- // Clear background (with transparency)
- const clear_bg = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xCC };
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LIGHT PALETTE (private)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const light = struct {
- // Backgrounds
- const bg = Color{ .r = 0xF5, .g = 0xF5, .b = 0xF5, .a = 0xFF };
- const bg_surface = Color{ .r = 0xEE, .g = 0xEE, .b = 0xEE, .a = 0xFF };
- const bg_panel = Color{ .r = 0xF0, .g = 0xF0, .b = 0xF0, .a = 0xFF };
- const bg_input = Color{ .r = 0xE8, .g = 0xE8, .b = 0xE8, .a = 0xFF };
- const bg_hover = Color{ .r = 0xDE, .g = 0xDE, .b = 0xDE, .a = 0xFF };
- const bg_bar = Color{ .r = 0xE0, .g = 0xE0, .b = 0xE0, .a = 0xFF };
- const bg_selected = Color{ .r = 0xD8, .g = 0xD8, .b = 0xD8, .a = 0xFF };
- // Text
- const text = Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 0xFF };
- const text_muted = Color{ .r = 0x80, .g = 0x80, .b = 0x80, .a = 0xFF };
- const text_dim = Color{ .r = 0x99, .g = 0x99, .b = 0x99, .a = 0xFF };
- const text_hint = Color{ .r = 0x88, .g = 0x88, .b = 0x88, .a = 0xFF };
- const text_bright = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- const content_text = Color{ .r = 0x30, .g = 0x30, .b = 0x38, .a = 0xFF };
- // Borders
- const border = Color{ .r = 0xCC, .g = 0xCC, .b = 0xCC, .a = 0xFF };
- const border_subtle = Color{ .r = 0xDD, .g = 0xDD, .b = 0xDD, .a = 0xFF };
- const border_light = Color{ .r = 0xBB, .g = 0xBB, .b = 0xBB, .a = 0xFF };
- const separator = Color{ .r = 0xA0, .g = 0xA0, .b = 0xA0, .a = 0xFF };
- // Logo (inverted: white petals, black outline)
- const logo_petal = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const logo_outline = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- const logo_highlight = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- // Panel
- const panel_title = Color{ .r = 0x20, .g = 0x20, .b = 0x20, .a = 0xFF };
- const panel_title_sep = Color{ .r = 0xA0, .g = 0xA0, .b = 0xA0, .a = 0xFF };
- const sacred_world_bg = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- // Tooltip (inverted on light: dark bg, white text)
- const tooltip_bg = Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 0xF0 };
- const tooltip_text = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- // Formula
- const formula_text = Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 0xFF };
- // UI elements
- const name_label_bg = Color{ .r = 0xEE, .g = 0xEE, .b = 0xEE, .a = 0xFF };
- const name_label_text = Color{ .r = 0x20, .g = 0x20, .b = 0x20, .a = 0xFF };
- const line_number = Color{ .r = 0x99, .g = 0x99, .b = 0x99, .a = 0xFF };
- const resize_handle = Color{ .r = 0x99, .g = 0x99, .b = 0x99, .a = 0xFF };
- const settings_toggle_off = Color{ .r = 0xBB, .g = 0xBB, .b = 0xC0, .a = 0xFF };
- const settings_toggle_on = Color{ .r = 0x28, .g = 0xC8, .b = 0x40, .a = 0xFF };
- const tool_selected_bg = Color{ .r = 0xD8, .g = 0xE8, .b = 0xD8, .a = 0xFF };
- const drop_zone_border = Color{ .r = 0xBB, .g = 0xBB, .b = 0xBB, .a = 0xFF };
- const drop_zone_plus = Color{ .r = 0x99, .g = 0x99, .b = 0x99, .a = 0xFF };
- const progress_bar_bg = Color{ .r = 0xBB, .g = 0xBB, .b = 0xC0, .a = 0xFF };
- // Chat panel (light: dark text on light bubbles, fully opaque)
- const chat_text = Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 0xFF };
- const chat_label_user = Color{ .r = 0x1A, .g = 0x1A, .b = 0x1A, .a = 0xFF };
- const chat_label_ai = Color{ .r = 0x16, .g = 0x8A, .b = 0x40, .a = 0xFF };
- const chat_bubble_user = Color{ .r = 0xE2, .g = 0xE6, .b = 0xEC, .a = 0xFF };
- const chat_bubble_ai = Color{ .r = 0xEA, .g = 0xEE, .b = 0xF2, .a = 0xFF };
- const chat_bubble_border = Color{ .r = 0xCC, .g = 0xD0, .b = 0xD4, .a = 0xFF };
- // Light theme: black header/input, white text (inverted contrast)
- const chat_input_bg = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- const chat_input_border = Color{ .r = 0x33, .g = 0x33, .b = 0x33, .a = 0xFF };
- const chat_input_text = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- const sacred_header_bg = Color{ .r = 0x00, .g = 0x00, .b = 0x00, .a = 0xFF };
- const sacred_header_text = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
- // Panel transparency: 255 = fully opaque (no dark bleed-through)
- const panel_content_alpha: f32 = 255;
- // Clear background (opaque white β no transparency on light theme)
- const clear_bg = Color{ .r = 0xFF, .g = 0xFF, .b = 0xFF, .a = 0xFF };
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// RUNTIME-SWITCHABLE SURFACE COLORS (pub var, initialized to dark)
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-// Backgrounds
-pub var bg: Color = dark.bg;
-pub var bg_surface: Color = dark.bg_surface;
-pub var bg_panel: Color = dark.bg_panel;
-pub var bg_input: Color = dark.bg_input;
-pub var bg_hover: Color = dark.bg_hover;
-pub var bg_bar: Color = dark.bg_bar;
-pub var bg_selected: Color = dark.bg_selected;
-// Text
-pub var text: Color = dark.text;
-pub var text_muted: Color = dark.text_muted;
-pub var text_dim: Color = dark.text_dim;
-pub var text_hint: Color = dark.text_hint;
-pub var text_bright: Color = dark.text_bright;
-pub var content_text: Color = dark.content_text;
-// Borders
-pub var border: Color = dark.border;
-pub var border_subtle: Color = dark.border_subtle;
-pub var border_light: Color = dark.border_light;
-pub var separator: Color = dark.separator;
-// Logo
-pub var logo_petal: Color = dark.logo_petal;
-pub var logo_outline: Color = dark.logo_outline;
-pub var logo_highlight: Color = dark.logo_highlight;
-// Panel
-pub var panel_title: Color = dark.panel_title;
-pub var panel_title_sep: Color = dark.panel_title_sep;
-pub var sacred_world_bg: Color = dark.sacred_world_bg;
-// Tooltip
-pub var tooltip_bg: Color = dark.tooltip_bg;
-pub var tooltip_text: Color = dark.tooltip_text;
-// Formula
-pub var formula_text: Color = dark.formula_text;
-// UI elements
-pub var name_label_bg: Color = dark.name_label_bg;
-pub var name_label_text: Color = dark.name_label_text;
-pub var line_number: Color = dark.line_number;
-pub var resize_handle: Color = dark.resize_handle;
-pub var settings_toggle_off: Color = dark.settings_toggle_off;
-pub var settings_toggle_on: Color = dark.settings_toggle_on;
-pub var tool_selected_bg: Color = dark.tool_selected_bg;
-pub var drop_zone_border: Color = dark.drop_zone_border;
-pub var drop_zone_plus: Color = dark.drop_zone_plus;
-pub var progress_bar_bg: Color = dark.progress_bar_bg;
-// Chat panel
-pub var chat_text: Color = dark.chat_text;
-pub var chat_label_user: Color = dark.chat_label_user;
-pub var chat_label_ai: Color = dark.chat_label_ai;
-pub var chat_bubble_user: Color = dark.chat_bubble_user;
-pub var chat_bubble_ai: Color = dark.chat_bubble_ai;
-pub var chat_bubble_border: Color = dark.chat_bubble_border;
-pub var chat_input_bg: Color = dark.chat_input_bg;
-pub var chat_input_border: Color = dark.chat_input_border;
-pub var chat_input_text: Color = dark.chat_input_text;
-pub var sacred_header_bg: Color = dark.sacred_header_bg;
-pub var sacred_header_text: Color = dark.sacred_header_text;
-pub var panel_content_alpha: f32 = dark.panel_content_alpha;
-// Clear background
-pub var clear_bg: Color = dark.clear_bg;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// THEME TOGGLE
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn toggle() void {
- current_mode = if (current_mode == .dark) .light else .dark;
- applyTheme(current_mode);
-}
-
-pub fn isDark() bool {
- return current_mode == .dark;
-}
-
-pub fn applyTheme(mode: ThemeMode) void {
- switch (mode) {
- .dark => {
- bg = dark.bg;
- bg_surface = dark.bg_surface;
- bg_panel = dark.bg_panel;
- bg_input = dark.bg_input;
- bg_hover = dark.bg_hover;
- bg_bar = dark.bg_bar;
- bg_selected = dark.bg_selected;
- text = dark.text;
- text_muted = dark.text_muted;
- text_dim = dark.text_dim;
- text_hint = dark.text_hint;
- text_bright = dark.text_bright;
- content_text = dark.content_text;
- border = dark.border;
- border_subtle = dark.border_subtle;
- border_light = dark.border_light;
- separator = dark.separator;
- logo_petal = dark.logo_petal;
- logo_outline = dark.logo_outline;
- logo_highlight = dark.logo_highlight;
- panel_title = dark.panel_title;
- panel_title_sep = dark.panel_title_sep;
- sacred_world_bg = dark.sacred_world_bg;
- tooltip_bg = dark.tooltip_bg;
- tooltip_text = dark.tooltip_text;
- formula_text = dark.formula_text;
- name_label_bg = dark.name_label_bg;
- name_label_text = dark.name_label_text;
- line_number = dark.line_number;
- resize_handle = dark.resize_handle;
- settings_toggle_off = dark.settings_toggle_off;
- settings_toggle_on = dark.settings_toggle_on;
- tool_selected_bg = dark.tool_selected_bg;
- drop_zone_border = dark.drop_zone_border;
- drop_zone_plus = dark.drop_zone_plus;
- progress_bar_bg = dark.progress_bar_bg;
- chat_text = dark.chat_text;
- chat_label_user = dark.chat_label_user;
- chat_label_ai = dark.chat_label_ai;
- chat_bubble_user = dark.chat_bubble_user;
- chat_bubble_ai = dark.chat_bubble_ai;
- chat_bubble_border = dark.chat_bubble_border;
- chat_input_bg = dark.chat_input_bg;
- chat_input_border = dark.chat_input_border;
- chat_input_text = dark.chat_input_text;
- sacred_header_bg = dark.sacred_header_bg;
- sacred_header_text = dark.sacred_header_text;
- panel_content_alpha = dark.panel_content_alpha;
- clear_bg = dark.clear_bg;
- },
- .light => {
- bg = light.bg;
- bg_surface = light.bg_surface;
- bg_panel = light.bg_panel;
- bg_input = light.bg_input;
- bg_hover = light.bg_hover;
- bg_bar = light.bg_bar;
- bg_selected = light.bg_selected;
- text = light.text;
- text_muted = light.text_muted;
- text_dim = light.text_dim;
- text_hint = light.text_hint;
- text_bright = light.text_bright;
- content_text = light.content_text;
- border = light.border;
- border_subtle = light.border_subtle;
- border_light = light.border_light;
- separator = light.separator;
- logo_petal = light.logo_petal;
- logo_outline = light.logo_outline;
- logo_highlight = light.logo_highlight;
- panel_title = light.panel_title;
- panel_title_sep = light.panel_title_sep;
- sacred_world_bg = light.sacred_world_bg;
- tooltip_bg = light.tooltip_bg;
- tooltip_text = light.tooltip_text;
- formula_text = light.formula_text;
- name_label_bg = light.name_label_bg;
- name_label_text = light.name_label_text;
- line_number = light.line_number;
- resize_handle = light.resize_handle;
- settings_toggle_off = light.settings_toggle_off;
- settings_toggle_on = light.settings_toggle_on;
- tool_selected_bg = light.tool_selected_bg;
- drop_zone_border = light.drop_zone_border;
- drop_zone_plus = light.drop_zone_plus;
- progress_bar_bg = light.progress_bar_bg;
- chat_text = light.chat_text;
- chat_label_user = light.chat_label_user;
- chat_label_ai = light.chat_label_ai;
- chat_bubble_user = light.chat_bubble_user;
- chat_bubble_ai = light.chat_bubble_ai;
- chat_bubble_border = light.chat_bubble_border;
- chat_input_bg = light.chat_input_bg;
- chat_input_border = light.chat_input_border;
- chat_input_text = light.chat_input_text;
- sacred_header_bg = light.sacred_header_bg;
- sacred_header_text = light.sacred_header_text;
- panel_content_alpha = light.panel_content_alpha;
- clear_bg = light.clear_bg;
- },
- }
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BACKWARD COMPAT β colors struct (delegates to mutable vars + accents)
-// Existing code that uses `theme.colors.X` will still compile.
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const colors = struct {
- // These are accessor functions disguised as const β they read from pub var at runtime
- // For backward compat, we re-export the pub vars via inline getters
- // BUT Zig doesn't allow pub var inside a struct scope.
- // So we provide the accents + keep old references working via pub const aliases.
-
- // Accents (const β never change)
- pub const magenta = accents.magenta;
- pub const cyan = accents.cyan;
- pub const green = accents.green;
- pub const yellow = accents.yellow;
- pub const red = accents.red;
- pub const blue = accents.blue;
- pub const orange = accents.orange;
- pub const purple = accents.purple;
- pub const logo_green = accents.logo_green;
- pub const gold = accents.gold;
- pub const success = accents.success;
- pub const warning = accents.warning;
- pub const error_ = accents.error_;
- pub const info = accents.info;
- pub const primary = accents.primary;
- pub const glow_magenta = accents.glow_magenta;
- pub const glow_cyan = accents.glow_cyan;
- pub const glow_green = accents.glow_green;
- pub const recording_red = accents.recording_red;
- pub const recording_dim = accents.recording_dim;
- pub const file_folder = accents.file_folder;
- pub const file_zig = accents.file_zig;
- pub const file_code = accents.file_code;
- pub const file_image = accents.file_image;
- pub const file_audio = accents.file_audio;
- pub const file_document = accents.file_document;
- pub const file_data = accents.file_data;
- pub const file_unknown = accents.file_unknown;
- pub const border_focus = accents.border_focus;
-
- // Surface colors β these are the DARK defaults (comptime const).
- // Code that uses theme.colors.bg gets the dark value at comptime.
- // Code that uses theme.bg gets the runtime-switchable value.
- // We keep these for backward compat but NEW code should use theme.bg etc.
- pub const bg = dark.bg;
- pub const bg_surface = dark.bg_surface;
- pub const bg_panel = dark.bg_panel;
- pub const bg_input = dark.bg_input;
- pub const bg_hover = dark.bg_hover;
- pub const bg_bar = dark.bg_bar;
- pub const bg_selected = dark.bg_selected;
- pub const text = dark.text;
- pub const text_muted = dark.text_muted;
- pub const text_dim = dark.text_dim;
- pub const text_hint = dark.text_hint;
- pub const text_bright = dark.text_bright;
- pub const content_text = dark.content_text;
- pub const border = dark.border;
- pub const border_subtle = dark.border_subtle;
- pub const border_light = dark.border_light;
- pub const separator = dark.separator;
-
- // Chat panel (comptime dark defaults β runtime uses pub var)
- pub const chat_text = dark.chat_text;
- pub const chat_label_user = dark.chat_label_user;
- pub const chat_label_ai = dark.chat_label_ai;
- pub const chat_bubble_user = dark.chat_bubble_user;
- pub const chat_bubble_ai = dark.chat_bubble_ai;
- pub const chat_bubble_border = dark.chat_bubble_border;
- pub const chat_input_bg = dark.chat_input_bg;
- pub const chat_input_border = dark.chat_input_border;
- pub const chat_input_text = dark.chat_input_text;
- pub const sacred_header_bg = dark.sacred_header_bg;
- pub const sacred_header_text = dark.sacred_header_text;
-
- // Status color functions
- pub const cpuColor = accents.cpuColor;
- pub const memColor = accents.memColor;
- pub const tempColor = accents.tempColor;
- pub const diskColor = accents.diskColor;
-
- pub fn withAlpha(color: Color, alpha: u8) Color {
- return Color{ .r = color.r, .g = color.g, .b = color.b, .a = alpha };
- }
-};
-
-// Top-level withAlpha for convenience
-pub fn withAlpha(color: Color, alpha: u8) Color {
- return Color{ .r = color.r, .g = color.g, .b = color.b, .a = alpha };
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// FONT CONFIGURATION
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const fonts = struct {
- pub const path_regular = "assets/fonts/Outfit-Regular.ttf";
- pub const path_mono = "assets/fonts/JetBrainsMono-Regular.ttf";
-
- pub const size_title: c_int = 16;
- pub const size_body: c_int = 14;
- pub const size_small: c_int = 13;
- pub const size_tiny: c_int = 12;
- pub const size_code: c_int = 13;
- pub const size_large: c_int = 20;
-
- pub const spacing: f32 = 0.5;
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// PANEL STYLES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const panel = struct {
- pub const radius: f32 = 12.0;
- pub const border_width: f32 = 1.0;
- pub const title_height: f32 = 32.0;
- pub const padding: f32 = 16.0;
- pub const glow_alpha: u8 = 40;
- pub const min_width: f32 = 200.0;
- pub const min_height: f32 = 150.0;
- pub const resize_handle_size: f32 = 16.0;
-
- pub const btn_close = Color{ .r = 0xFF, .g = 0x5F, .b = 0x57, .a = 0xFF };
- pub const btn_minimize = Color{ .r = 0xFE, .g = 0xBC, .b = 0x2E, .a = 0xFF };
- pub const btn_maximize = Color{ .r = 0x28, .g = 0xC8, .b = 0x40, .a = 0xFF };
- pub const btn_radius: f32 = 6.0;
- pub const btn_spacing: f32 = 20.0;
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// STATUS BAR
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const status_bar = struct {
- pub const height: f32 = 24.0;
- pub const padding: f32 = 12.0;
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// ANIMATION PARAMETERS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const anim = struct {
- pub const morph_speed: f32 = 2.5;
- pub const glow_decay: f32 = 1.2;
- pub const ring_rotation: f32 = 2.0;
- pub const focus_lerp: f32 = 4.0;
- pub const fade_speed: f32 = 3.0;
- pub const pulse_speed: f32 = 3.0;
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// SYSTEM PANEL THRESHOLDS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const thresholds = struct {
- pub const cpu_warning: f32 = 50.0;
- pub const cpu_critical: f32 = 80.0;
- pub const mem_warning: f32 = 0.5;
- pub const mem_critical: f32 = 0.8;
- pub const temp_warning: f32 = 60.0;
- pub const temp_critical: f32 = 80.0;
- pub const disk_warning: f32 = 0.7;
- pub const disk_critical: f32 = 0.9;
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LAYOUT CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const layout = struct {
- pub const bar_height: f32 = 8.0;
- pub const row_height: f32 = 50.0;
- pub const margin: f32 = 20.0;
- pub const icon_size: f32 = 16.0;
- pub const spacing: f32 = 8.0;
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HELPER FUNCTIONS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub fn easePhiInOut(t: f32) f32 {
- if (t < 0.5) {
- return 2.0 * t * t * PHI_INV;
- } else {
- const u = 2.0 * t - 1.0;
- return 1.0 - (1.0 - u) * (1.0 - u) * PHI_INV;
- }
-}
-
-pub fn lerp(a: f32, b: f32, t: f32) f32 {
- return a + (b - a) * t;
-}
-
-pub fn clamp(value: f32, min_val: f32, max_val: f32) f32 {
- return @max(min_val, @min(max_val, value));
-}
-
-pub fn hsvToRgb(h: f32, s: f32, v: f32) [3]u8 {
- const c = v * s;
- const h_prime = @mod(h / 60.0, 6.0);
- const x = c * (1.0 - @abs(@mod(h_prime, 2.0) - 1.0));
- const m = v - c;
-
- var r: f32 = 0;
- var g: f32 = 0;
- var b: f32 = 0;
-
- if (h_prime < 1) {
- r = c;
- g = x;
- } else if (h_prime < 2) {
- r = x;
- g = c;
- } else if (h_prime < 3) {
- g = c;
- b = x;
- } else if (h_prime < 4) {
- g = x;
- b = c;
- } else if (h_prime < 5) {
- r = x;
- b = c;
- } else {
- r = c;
- b = x;
- }
-
- return .{
- @intFromFloat((r + m) * 255.0),
- @intFromFloat((g + m) * 255.0),
- @intFromFloat((b + m) * 255.0),
- };
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "phi_constants" {
- const trinity_check = PHI * PHI + 1.0 / (PHI * PHI);
- try std.testing.expectApproxEqAbs(trinity_check, 3.0, 0.0001);
-}
-
-test "theme_toggle" {
- // Start dark
- try std.testing.expectEqual(current_mode, .dark);
- try std.testing.expectEqual(bg.r, 0x00);
- try std.testing.expectEqual(text.r, 0xFF);
-
- // Toggle to light
- toggle();
- try std.testing.expectEqual(current_mode, .light);
- try std.testing.expectEqual(bg.r, 0xF5);
- try std.testing.expectEqual(text.r, 0x1A);
-
- // Toggle back to dark
- toggle();
- try std.testing.expectEqual(current_mode, .dark);
- try std.testing.expectEqual(bg.r, 0x00);
-}
-
-test "accent_colors_unchanged" {
- toggle(); // to light
- // Accents should be identical regardless of theme
- try std.testing.expectEqual(accents.green.g, 0xFA);
- try std.testing.expectEqual(accents.magenta.r, 0xF8);
- try std.testing.expectEqual(accents.logo_green.r, 0x08);
- toggle(); // back to dark
-}
diff --git a/src/vsa/trinity_canvas/types.zig b/src/vsa/trinity_canvas/types.zig
deleted file mode 100644
index fdb1990a93..0000000000
--- a/src/vsa/trinity_canvas/types.zig
+++ /dev/null
@@ -1,241 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// trinity_types v2.0.0 - Generated from .tri specification
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-//
-// Sacred formula: V = n Γ 3^k Γ Ο^m Γ Ο^p Γ e^q
-// Golden identity: ΟΒ² + 1/ΟΒ² = 3
-//
-// Author:
-// DO NOT EDIT - This file is auto-generated
-//
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-const std = @import("std");
-const math = std.math;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CONSTANTS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const MAX_PANELS: f64 = 8;
-
-pub const MAX_CLUSTERS: f64 = 32;
-
-pub const MAX_CLUSTER_CHARS: f64 = 256;
-
-pub const MAX_SPIRALS: f64 = 16;
-
-pub const MAX_TOOLS: f64 = 8;
-
-pub const MAX_EFFECTS: f64 = 16;
-
-pub const MAX_FINDER_ENTRIES: f64 = 64;
-
-pub const MAX_CHAT_MESSAGES: f64 = 8;
-
-pub const MAX_MESSAGE_LEN: f64 = 256;
-
-pub const MAX_INPUT_LEN: f64 = 512;
-
-// Basic Ο-constants (Sacred Formula)
-pub const PHI: f64 = 1.618033988749895;
-pub const PHI_INV: f64 = 0.618033988749895;
-pub const PHI_SQ: f64 = 2.618033988749895;
-pub const TRINITY: f64 = 3.0;
-pub const SQRT5: f64 = 2.2360679774997896;
-pub const TAU: f64 = 6.283185307179586;
-pub const PI: f64 = 3.141592653589793;
-pub const E: f64 = 2.718281828459045;
-pub const PHOENIX: i64 = 999;
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TYPES
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Panel lifecycle state
-pub const PanelState = struct {};
-
-/// Type of panel content
-pub const PanelType = struct {};
-
-/// File type for finder panel
-pub const FileType = struct {};
-
-/// Application mode
-pub const TrinityMode = struct {};
-
-/// Rectangle for layout
-pub const Rect = struct {
- x: f64,
- y: f64,
- width: f64,
- height: f64,
-};
-
-/// File/folder entry in finder
-pub const FinderEntry = struct {
- name: String[128],
- name_len: USize,
- is_dir: bool,
- file_type: FileType,
- size_bytes: U64,
- orbit_angle: f64,
- orbit_radius: f64,
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// MEMORY FOR WASM
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-var global_buffer: [65536]u8 align(16) = undefined;
-var f64_buffer: [8192]f64 align(16) = undefined;
-
-export fn get_global_buffer_ptr() [*]u8 {
- return &global_buffer;
-}
-
-export fn get_f64_buffer_ptr() [*]f64 {
- return &f64_buffer;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// CREATION PATTERNS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Trit - ternary digit (-1, 0, +1)
-pub const Trit = enum(i8) {
- negative = -1, // FALSE
- zero = 0, // UNKNOWN
- positive = 1, // TRUE
-
- pub fn trit_and(a: Trit, b: Trit) Trit {
- return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_or(a: Trit, b: Trit) Trit {
- return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
- }
-
- pub fn trit_not(a: Trit) Trit {
- return @enumFromInt(-@intFromEnum(a));
- }
-
- pub fn trit_xor(a: Trit, b: Trit) Trit {
- const av = @intFromEnum(a);
- const bv = @intFromEnum(b);
- if (av == 0 or bv == 0) return .zero;
- if (av == bv) return .negative;
- return .positive;
- }
-};
-
-/// Check TRINITY identity: ΟΒ² + 1/ΟΒ² = 3
-fn verify_trinity() f64 {
- return PHI * PHI + 1.0 / (PHI * PHI);
-}
-
-/// Ο-interpolation
-fn phi_lerp(a: f64, b: f64, t: f64) f64 {
- const phi_t = math.pow(f64, t, PHI_INV);
- return a + (b - a) * phi_t;
-}
-
-/// Ο-spiral generation
-fn generate_phi_spiral(n: u32, scale: f64, cx: f64, cy: f64) u32 {
- const max_points = f64_buffer.len / 2;
- const count = if (n > max_points) @as(u32, @intCast(max_points)) else n;
- var i: u32 = 0;
- while (i < count) : (i += 1) {
- const fi: f64 = @floatFromInt(i);
- const angle = fi * TAU * PHI_INV;
- const radius = scale * math.pow(f64, PHI, fi * 0.1);
- f64_buffer[i * 2] = cx + radius * @cos(angle);
- f64_buffer[i * 2 + 1] = cy + radius * @sin(angle);
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// BEHAVIOR FUNCTIONS - Generated from behaviors
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Filename string
-/// When: Determining file type
-/// Then: Return appropriate FileType enum based on extension
-pub fn file_type_from_extension() !void {
- // Return appropriate FileType enum based on extension
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// FileType enum value
-/// When: Rendering file icon
-/// Then: Return theme color for that file type
-pub fn file_type_color() !void {
- // Return theme color for that file type
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// PanelType enum value
-/// When: Creating panel title
-/// Then: Return display title string (CHAT, CODE, etc.)
-pub fn panel_type_title() !void {
- // Return display title string (CHAT, CODE, etc.)
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-/// PanelType enum value
-/// When: Rendering panel header
-/// Then: Return icon character or glyph
-pub fn panel_type_icon() !void {
- // Return icon character or glyph
- const result = @as([]const u8, "implemented");
- _ = result;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// TESTS - Generated from behaviors and test_cases
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-test "file_type_from_extension_behavior" {
- // Given: Filename string
- // When: Determining file type
- // Then: Return appropriate FileType enum based on extension
- // Test file_type_from_extension: verify behavior is callable
- const func = @TypeOf(file_type_from_extension);
- try std.testing.expect(func != void);
-}
-
-test "file_type_color_behavior" {
- // Given: FileType enum value
- // When: Rendering file icon
- // Then: Return theme color for that file type
- // Test file_type_color: verify behavior is callable
- const func = @TypeOf(file_type_color);
- try std.testing.expect(func != void);
-}
-
-test "panel_type_title_behavior" {
- // Given: PanelType enum value
- // When: Creating panel title
- // Then: Return display title string (CHAT, CODE, etc.)
- // Test panel_type_title: verify behavior is callable
- const func = @TypeOf(panel_type_title);
- try std.testing.expect(func != void);
-}
-
-test "panel_type_icon_behavior" {
- // Given: PanelType enum value
- // When: Rendering panel header
- // Then: Return icon character or glyph
- // Test panel_type_icon: verify behavior is callable
- const func = @TypeOf(panel_type_icon);
- try std.testing.expect(func != void);
-}
-
-test "phi_constants" {
- try std.testing.expectApproxEqAbs(PHI * PHI_INV, 1.0, 1e-10);
- try std.testing.expectApproxEqAbs(PHI_SQ - PHI, 1.0, 1e-10);
-}
diff --git a/src/vsa/trinity_canvas/world_docs.zig b/src/vsa/trinity_canvas/world_docs.zig
deleted file mode 100644
index 0231f38eb9..0000000000
--- a/src/vsa/trinity_canvas/world_docs.zig
+++ /dev/null
@@ -1,257 +0,0 @@
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// WORLD DOCS β Embedded documentation for 27 Sacred World panels
-// Each world maps to a docsite markdown file via @embedFile
-// Markdown is rendered as plain text with runtime line-by-line filtering
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const WorldDoc = struct {
- raw: []const u8, // Raw markdown content (comptime embedded)
- subtitle: []const u8, // Short description shown under header
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// 27 EMBEDDED DOCS β one per sacred world
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const WORLD_DOCS: [27]WorldDoc = .{
- // ββ Realm 1: RAZUM (phi) β AI & Communication, blocks 0-8 ββ
- .{ .raw = @embedFile("docs_embed/intro.md"), .subtitle = "Trinity AI Assistant" },
- .{ .raw = @embedFile("docs_embed/getting-started/quickstart.md"), .subtitle = "AI Code Generation" },
- .{ .raw = @embedFile("docs_embed/concepts/glossary.md"), .subtitle = "Code Explainer" },
- .{ .raw = @embedFile("docs_embed/api/vsa.md"), .subtitle = "Debug Assistant" },
- .{ .raw = @embedFile("docs_embed/concepts/balanced-ternary.md"), .subtitle = "Code Review" },
- .{ .raw = @embedFile("docs_embed/troubleshooting.md"), .subtitle = "Multi-Language Translation" },
- .{ .raw = @embedFile("docs_embed/vibee/specification.md"), .subtitle = "VIBEE Spec to Code" },
- .{ .raw = @embedFile("docs_embed/architecture/overview.md"), .subtitle = "Voice Input/Output" },
- .{ .raw = @embedFile("docs_embed/vibee/examples.md"), .subtitle = "Multi-Step Composer" },
-
- // ββ Realm 2: MATERIYA (pi) β Tools & System, blocks 9-17 ββ
- .{ .raw = @embedFile("docs_embed/benchmarks/index.md"), .subtitle = "File Browser" },
- .{ .raw = @embedFile("docs_embed/getting-started/installation.md"), .subtitle = "Code Editor" },
- .{ .raw = @embedFile("docs_embed/deployment/index.md"), .subtitle = "Build Runner" },
- .{ .raw = @embedFile("docs_embed/getting-started/development-setup.md"), .subtitle = "Test Runner" },
- .{ .raw = @embedFile("docs_embed/benchmarks/competitor-comparison.md"), .subtitle = "Terminal Shell" },
- .{ .raw = @embedFile("docs_embed/deployment/runpod.md"), .subtitle = "Git Version Control" },
- .{ .raw = @embedFile("docs_embed/vibee/theorems.md"), .subtitle = "Deployment Manager" },
- .{ .raw = @embedFile("docs_embed/benchmarks/gpu-inference.md"), .subtitle = "Network Admin β Distributed Nodes" },
- .{ .raw = @embedFile("docs_embed/benchmarks/memory-efficiency.md"), .subtitle = "App Settings" },
-
- // ββ Realm 3: DUKH (e) β Content & Knowledge, blocks 18-26 ββ
- .{ .raw = @embedFile("docs_embed/math-foundations/formulas.md"), .subtitle = "All Documentation" },
- .{ .raw = @embedFile("docs_embed/concepts/trinity-identity.md"), .subtitle = "Create Reels" },
- .{ .raw = @embedFile("docs_embed/api/hybrid.md"), .subtitle = "Content Feed" },
- .{ .raw = @embedFile("docs_embed/hdc/applications.md"), .subtitle = "Project Roadmap" },
- .{ .raw = @embedFile("docs_embed/hdc/igla-glove-comparison.md"), .subtitle = "Performance Benchmarks" },
- .{ .raw = @embedFile("docs_embed/research/bitnet-report.md"), .subtitle = "Research Reports" },
- .{ .raw = @embedFile("docs_embed/math-foundations/proofs.md"), .subtitle = "Sacred Formulas" },
- .{ .raw = @embedFile("docs_embed/overview/roadmap.md"), .subtitle = "Community Hub" },
- .{ .raw = @embedFile("docs_embed/overview/tech-tree.md"), .subtitle = "About Trinity" },
-};
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// RUNTIME MARKDOWN LINE FILTER
-// Determines if a line should be skipped during rendering
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Check if a line is markdown noise that should be skipped in the panel view.
-/// Returns true if the line should be hidden.
-pub fn isNoiseLine(line: []const u8) bool {
- const trimmed = trimLeft(line);
- if (trimmed.len == 0) return false; // keep blank lines (paragraph spacing)
-
- // YAML frontmatter delimiters
- if (trimmed.len >= 3 and trimmed[0] == '-' and trimmed[1] == '-' and trimmed[2] == '-') return true;
-
- // Code fence
- if (trimmed.len >= 3 and trimmed[0] == '`' and trimmed[1] == '`' and trimmed[2] == '`') return true;
-
- // HTML tags / Docusaurus admonitions
- if (trimmed[0] == '<') return true;
- if (trimmed.len >= 3 and trimmed[0] == ':' and trimmed[1] == ':' and trimmed[2] == ':') return true;
-
- // import statements (MDX)
- if (startsWith(trimmed, "import ")) return true;
-
- // Table separator lines (|---|---|)
- if (isTableSeparator(trimmed)) return true;
-
- // YAML frontmatter key-value lines (sidebar_position:, title:, etc.)
- // Only skip if it looks like "key: value" at start (no spaces before colon)
- if (looksLikeFrontmatter(trimmed)) return true;
-
- return false;
-}
-
-/// Strip heading markers (# ## ### etc.) and return just the text.
-/// Returns the original line if not a heading.
-pub fn stripHeading(line: []const u8) []const u8 {
- const trimmed = trimLeft(line);
- if (trimmed.len == 0) return line;
- if (trimmed[0] != '#') return line;
-
- var i: usize = 0;
- while (i < trimmed.len and trimmed[i] == '#') : (i += 1) {}
- // skip space after #
- if (i < trimmed.len and trimmed[i] == ' ') i += 1;
- return trimmed[i..];
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// LINE ITERATOR β iterate over raw text line by line
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-pub const LineIterator = struct {
- data: []const u8,
- pos: usize,
-
- pub fn init(data: []const u8) LineIterator {
- return .{ .data = data, .pos = 0 };
- }
-
- pub fn next(self: *LineIterator) ?[]const u8 {
- if (self.pos >= self.data.len) return null;
- const start = self.pos;
- while (self.pos < self.data.len and self.data[self.pos] != '\n') {
- self.pos += 1;
- }
- const end = self.pos;
- if (self.pos < self.data.len) self.pos += 1; // skip \n
- return self.data[start..end];
- }
-};
-
-/// Count total visible lines (non-noise, after heading strip) for scroll calculation
-pub fn countVisibleLines(raw: []const u8) u32 {
- var iter = LineIterator.init(raw);
- var count: u32 = 0;
- var in_frontmatter = false;
- while (iter.next()) |line| {
- const trimmed = trimLeft(line);
- // Track frontmatter block (between first two ---)
- if (trimmed.len >= 3 and trimmed[0] == '-' and trimmed[1] == '-' and trimmed[2] == '-') {
- in_frontmatter = !in_frontmatter;
- continue;
- }
- if (in_frontmatter) continue;
- if (isNoiseLine(line)) continue;
- count += 1;
- }
- return count;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// INLINE MARKDOWN STRIPPING
-// Removes **bold**, *italic*, `code`, [link](url), | table pipes
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-/// Strip inline markdown formatting from a line into a buffer.
-/// Returns the number of bytes written.
-pub fn stripInline(line: []const u8, out: []u8) usize {
- var i: usize = 0;
- var o: usize = 0;
- while (i < line.len and o < out.len - 1) {
- const c = line[i];
-
- // ** bold ** β skip the ** delimiters
- if (c == '*' and i + 1 < line.len and line[i + 1] == '*') {
- i += 2;
- continue;
- }
- // * italic * β skip single * when between word chars
- if (c == '*') {
- i += 1;
- continue;
- }
- // `` inline code `` β skip double backtick
- if (c == '`' and i + 1 < line.len and line[i + 1] == '`') {
- i += 2;
- continue;
- }
- // ` inline code ` β skip single backtick
- if (c == '`') {
- i += 1;
- continue;
- }
- // [link text](url) β keep link text, skip url
- if (c == '[') {
- i += 1;
- // Copy text until ]
- while (i < line.len and line[i] != ']' and o < out.len - 1) {
- out[o] = line[i];
- o += 1;
- i += 1;
- }
- if (i < line.len and line[i] == ']') i += 1;
- // Skip (url)
- if (i < line.len and line[i] == '(') {
- i += 1;
- while (i < line.len and line[i] != ')') : (i += 1) {}
- if (i < line.len) i += 1; // skip )
- }
- continue;
- }
- // | table separator β replace with space
- if (c == '|') {
- if (o > 0 and out[o - 1] != ' ') {
- out[o] = ' ';
- o += 1;
- }
- i += 1;
- // skip spaces after |
- while (i < line.len and line[i] == ' ') : (i += 1) {}
- continue;
- }
- // $$ LaTeX β skip
- if (c == '$') {
- i += 1;
- continue;
- }
-
- out[o] = c;
- o += 1;
- i += 1;
- }
- return o;
-}
-
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-// HELPERS
-// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
-fn trimLeft(s: []const u8) []const u8 {
- var i: usize = 0;
- while (i < s.len and (s[i] == ' ' or s[i] == '\t')) : (i += 1) {}
- return s[i..];
-}
-
-fn startsWith(s: []const u8, prefix: []const u8) bool {
- if (s.len < prefix.len) return false;
- return std.mem.eql(u8, s[0..prefix.len], prefix);
-}
-
-fn isTableSeparator(line: []const u8) bool {
- // Lines like |---|---|---| or |:---|:---:|
- if (line.len < 3) return false;
- if (line[0] != '|') return false;
- for (line) |c| {
- if (c != '|' and c != '-' and c != ':' and c != ' ') return false;
- }
- return true;
-}
-
-fn looksLikeFrontmatter(line: []const u8) bool {
- // Lines like "sidebar_position: 1" or "title: Something"
- // Must have a colon before any space, and be short-ish
- if (line.len > 80) return false;
- for (line, 0..) |c, i| {
- if (c == ' ' or c == '\t') return false; // space before colon = not frontmatter
- if (c == ':') {
- // Must be followed by space or end
- if (i + 1 >= line.len or line[i + 1] == ' ') return true;
- return false;
- }
- }
- return false;
-}
-
-const std = @import("std");
diff --git a/src/vsa/wave_scroll.zig b/src/vsa/wave_scroll.zig
deleted file mode 100644
index 64e89e2479..0000000000
--- a/src/vsa/wave_scroll.zig
+++ /dev/null
@@ -1,777 +0,0 @@
-// =============================================================================
-// EMERGENT WAVE SCROLLVIEW v1.0
-// =============================================================================
-//
-// Content items as localized wave packets, scroll as global phase shift.
-// SIMD-accelerated (Vec8f) with phi-based inertia and damping.
-//
-// Sacred Formula: V = n * 3^k * pi^m * phi^p * e^q
-// Golden Identity: phi^2 + 1/phi^2 = 3 = TRINITY
-//
-// Author: Agent (Emergent Wave ScrollView v1.0)
-// =============================================================================
-
-const std = @import("std");
-const math = std.math;
-const testing = std.testing;
-
-// =============================================================================
-// SACRED CONSTANTS
-// =============================================================================
-
-pub const PHI: f32 = 1.6180339887;
-pub const PHI_INV: f32 = 0.6180339887;
-pub const PHI_SQ: f32 = 2.6180339887;
-pub const TAU: f32 = 6.28318530718;
-pub const PI: f32 = 3.14159265359;
-pub const TRINITY: f32 = 3.0;
-pub const PHOENIX: f32 = 999.0;
-
-// =============================================================================
-// SIMD
-// =============================================================================
-
-pub const Vec8f = @Vector(8, f32);
-pub const SIMD_WIDTH: usize = 8;
-
-// =============================================================================
-// SCROLL PHYSICS CONSTANTS
-// =============================================================================
-
-pub const SCROLL_DAMPING: f32 = PHI_INV; // 0.618 golden ratio damping
-pub const SCROLL_INERTIA_MASS: f32 = PHI; // 1.618 inertia
-pub const SCROLL_MAX_VELOCITY: f32 = 2000.0;
-pub const SCROLL_IMPULSE_SCALE: f32 = 40.0;
-pub const BOUNCE_STIFFNESS: f32 = TRINITY; // 3.0 = phi^2 + 1/phi^2
-pub const BOUNCE_DAMPING: f32 = PHI_INV;
-pub const DEFAULT_SIGMA_MULT: f32 = PHI; // Gaussian envelope = item_height * PHI
-pub const DEFAULT_FREQUENCY: f32 = PHI;
-pub const CULLING_SIGMA_MULT: f32 = TRINITY; // Cull packets beyond 3*sigma
-pub const MAX_VISIBLE: usize = 1024;
-pub const MAX_INTERFERENCE: usize = 256;
-
-// =============================================================================
-// CONTENT WAVE TYPE
-// =============================================================================
-
-pub const ContentWaveType = enum(u8) {
- text_standing, // Standing wave, low frequency
- image_interference, // Spatial interference, high frequency
- voice_modulated, // Frequency-modulated carrier
- code_banded, // Syntax-colored wave bands
- separator, // Low-energy separator wave
-
- pub fn baseFrequency(self: ContentWaveType) f32 {
- return switch (self) {
- .text_standing => PHI,
- .image_interference => TAU,
- .voice_modulated => TAU * PHI,
- .code_banded => TRINITY,
- .separator => PHI_INV,
- };
- }
-
- pub fn sigmaMultiplier(self: ContentWaveType) f32 {
- return switch (self) {
- .text_standing => PHI,
- .image_interference => 1.0,
- .voice_modulated => PHI,
- .code_banded => PHI_INV,
- .separator => 0.5,
- };
- }
-
- pub fn hueDefault(self: ContentWaveType) f32 {
- return switch (self) {
- .text_standing => 180.0, // Cyan
- .image_interference => 300.0, // Magenta
- .voice_modulated => 120.0, // Green
- .code_banded => 60.0, // Gold
- .separator => 0.0, // Red (dim)
- };
- }
-};
-
-// =============================================================================
-// WAVE PACKET
-// =============================================================================
-
-pub const WavePacket = struct {
- base_y: f32, // Rest position (index * item_height)
- amplitude: f32, // Visibility/prominence [0, 1]
- phase: f32, // Individual wave phase [0, TAU]
- frequency: f32, // Spatial frequency (content-type dependent)
- sigma: f32, // Gaussian envelope width
- content_type: ContentWaveType,
- content_index: usize, // Index into content data
- energy: f32, // Interaction energy
- hue: f32, // Color hue [0, 360]
- item_height: f32, // Height of this content item
-
- pub fn init(index: usize, base_y: f32, item_height: f32, content_type: ContentWaveType) WavePacket {
- return WavePacket{
- .base_y = base_y,
- .amplitude = 1.0,
- .phase = @as(f32, @floatFromInt(index)) * PHI_INV * TAU,
- .frequency = content_type.baseFrequency(),
- .sigma = item_height * content_type.sigmaMultiplier(),
- .content_type = content_type,
- .content_index = index,
- .energy = 1.0,
- .hue = content_type.hueDefault(),
- .item_height = item_height,
- };
- }
-};
-
-// =============================================================================
-// WAVE SCROLL STATE
-// =============================================================================
-
-pub const WaveScrollState = struct {
- scroll_phase: f32, // Cumulative scroll offset (replaces scroll_y)
- scroll_velocity: f32, // Current scroll speed (px/sec)
- scroll_acceleration: f32, // Impulse from input
- damping_factor: f32, // PHI_INV = 0.618
- inertia_mass: f32, // PHI = 1.618
- max_velocity: f32, // Velocity cap
- bounce_phase: f32, // Edge bounce wave phase
- bounce_amplitude: f32, // Edge bounce wave amplitude
- total_content_height: f32, // Total virtual height
- viewport_height: f32, // Visible area height
-
- pub fn init(viewport_height: f32) WaveScrollState {
- return WaveScrollState{
- .scroll_phase = 0,
- .scroll_velocity = 0,
- .scroll_acceleration = 0,
- .damping_factor = SCROLL_DAMPING,
- .inertia_mass = SCROLL_INERTIA_MASS,
- .max_velocity = SCROLL_MAX_VELOCITY,
- .bounce_phase = 0,
- .bounce_amplitude = 0,
- .total_content_height = 0,
- .viewport_height = viewport_height,
- };
- }
-};
-
-// =============================================================================
-// WAVE SCROLLVIEW
-// =============================================================================
-
-pub const WaveScrollView = struct {
- state: WaveScrollState,
-
- // Wave packets (visible subset)
- packets: [MAX_VISIBLE]WavePacket,
- packet_count: usize,
- total_items: usize,
- visible_start: usize,
- visible_end: usize,
-
- // Viewport bounds
- viewport_x: f32,
- viewport_y: f32,
- viewport_width: f32,
- viewport_height: f32,
-
- // SIMD evaluation buffers
- y_buffer: [MAX_VISIBLE]f32,
- amp_buffer: [MAX_VISIBLE]f32,
-
- // Interference field (viewport discretized into rows)
- interference: [MAX_INTERFERENCE]f32,
- interference_rows: usize,
-
- // Animation time
- wave_time: f32,
-
- // Default item height (for uniform lists)
- default_item_height: f32,
-
- // Dirty flag: skip SIMD evaluation when scroll is idle
- needs_eval: bool,
-
- // Rubber-band offset for iOS-style overscroll rendering
- rubber_offset: f32,
-
- // Scroll snap points (Y positions of section boundaries)
- snap_points: [64]f32,
- snap_count: usize,
- snap_enabled: bool,
-
- // =========================================================================
- // INIT
- // =========================================================================
-
- pub fn init(vx: f32, vy: f32, vw: f32, vh: f32) WaveScrollView {
- var wsv: WaveScrollView = undefined;
- wsv.state = WaveScrollState.init(vh);
- wsv.packet_count = 0;
- wsv.total_items = 0;
- wsv.visible_start = 0;
- wsv.visible_end = 0;
- wsv.viewport_x = vx;
- wsv.viewport_y = vy;
- wsv.viewport_width = vw;
- wsv.viewport_height = vh;
- wsv.wave_time = 0;
- wsv.default_item_height = 40.0;
- wsv.interference_rows = @min(@as(usize, @intFromFloat(vh)), MAX_INTERFERENCE);
- wsv.needs_eval = true;
- wsv.rubber_offset = 0;
- wsv.snap_count = 0;
- wsv.snap_enabled = false;
- @memset(&wsv.snap_points, 0);
-
- // Zero buffers
- @memset(&wsv.y_buffer, 0);
- @memset(&wsv.amp_buffer, 0);
- @memset(&wsv.interference, 0);
- @memset(std.mem.asBytes(&wsv.packets), 0);
-
- return wsv;
- }
-
- // =========================================================================
- // ADD ITEM
- // =========================================================================
-
- pub fn addItem(self: *WaveScrollView, content_type: ContentWaveType, item_height: f32) void {
- const index = self.total_items;
- const base_y = if (index == 0) 0.0 else blk: {
- // Compute position based on total items so far
- break :blk @as(f32, @floatFromInt(index)) * self.default_item_height;
- };
-
- self.total_items += 1;
- self.state.total_content_height = @as(f32, @floatFromInt(self.total_items)) * self.default_item_height;
-
- // Only store if within visible range (will be updated in updateVisibleRange)
- if (self.packet_count < MAX_VISIBLE) {
- self.packets[self.packet_count] = WavePacket.init(index, base_y, item_height, content_type);
- self.packet_count += 1;
- }
- }
-
- // =========================================================================
- // SET TOTAL ITEMS (for large/infinite lists)
- // =========================================================================
-
- pub fn setTotalItems(self: *WaveScrollView, total: usize, item_height: f32) void {
- self.total_items = total;
- self.default_item_height = item_height;
- self.state.total_content_height = @as(f32, @floatFromInt(total)) * item_height;
- }
-
- // =========================================================================
- // APPLY SCROLL IMPULSE
- // =========================================================================
-
- pub fn applyImpulse(self: *WaveScrollView, impulse: f32) void {
- // Scale impulse inversely with content height β less momentum for large docs
- const height_factor = @min(1.0, 2000.0 / @max(1.0, self.state.total_content_height));
- self.state.scroll_acceleration += impulse * SCROLL_IMPULSE_SCALE * height_factor;
- }
-
- // =========================================================================
- // UPDATE PHYSICS (phi-damped velocity integration)
- // =========================================================================
-
- pub fn updatePhysics(self: *WaveScrollView, dt: f32) void {
- const state = &self.state;
-
- // Compute overshoot for edge bounce
- const overshoot = self.computeOvershoot();
-
- // Forces:
- // 1. Input impulse (scroll_acceleration)
- // 2. Phi-based drag: -damping * velocity
- // 3. TRINITY bounce spring: -BOUNCE_STIFFNESS * overshoot
- const drag = -state.damping_factor * state.scroll_velocity;
- const bounce_force = -BOUNCE_STIFFNESS * overshoot;
- const net_force = state.scroll_acceleration + drag + bounce_force;
-
- // Integrate: a = F / mass
- const acceleration = net_force / state.inertia_mass;
- state.scroll_velocity += acceleration * dt;
-
- // Clamp velocity
- state.scroll_velocity = math.clamp(state.scroll_velocity, -state.max_velocity, state.max_velocity);
-
- // Integrate position
- const prev_phase = state.scroll_phase;
- state.scroll_phase += state.scroll_velocity * dt;
-
- // Soft clamp: allow 50px overscroll for rubber-band, then hard stop
- const max_phase = @max(0.0, state.total_content_height - state.viewport_height);
- state.scroll_phase = math.clamp(state.scroll_phase, -50.0, max_phase + 50.0);
-
- // Reset impulse (instantaneous)
- state.scroll_acceleration = 0;
-
- // Scroll snap: gentle attraction to nearest section boundary
- if (self.snap_enabled and self.snap_count > 0) {
- const abs_vel = @abs(state.scroll_velocity);
- if (abs_vel < 20.0 and abs_vel > 0.5) {
- const nearest = self.findNearestSnap(state.scroll_phase);
- const snap_force = (nearest - state.scroll_phase) * 2.0;
- state.scroll_velocity += snap_force * dt;
- }
- }
-
- // Rubber-band offset for rendering (iOS-style logarithmic resistance)
- if (@abs(overshoot) > 0.5) {
- const sign: f32 = if (overshoot > 0) 1.0 else -1.0;
- const rubber = @log2(1.0 + @abs(overshoot) / 100.0) * 100.0 * sign;
- self.rubber_offset = rubber - overshoot;
- } else {
- self.rubber_offset = 0;
- }
-
- // Update bounce animation
- if (@abs(overshoot) > 0.1) {
- state.bounce_amplitude = @abs(overshoot) / @max(1.0, state.viewport_height);
- state.bounce_phase += TAU * 2.0 * dt;
- } else {
- state.bounce_amplitude *= BOUNCE_DAMPING;
- if (state.bounce_amplitude < 0.001) state.bounce_amplitude = 0;
- }
-
- // Velocity cutoff: stop crawling β snap to zero below threshold
- // Only when not bouncing (overshoot can produce tiny velocities that matter)
- if (@abs(state.scroll_velocity) < 1.5 and @abs(self.computeOvershoot()) < 1.0) {
- state.scroll_velocity = 0.0;
- }
-
- // Dirty flag: skip expensive SIMD when scroll is idle
- self.needs_eval = @abs(state.scroll_phase - prev_phase) > 0.5 or @abs(state.scroll_velocity) > 1.0;
-
- // Update wave time
- self.wave_time += dt;
- }
-
- // =========================================================================
- // COMPUTE OVERSHOOT
- // =========================================================================
-
- fn computeOvershoot(self: *const WaveScrollView) f32 {
- const phase = self.state.scroll_phase;
- const max_scroll = @max(0.0, self.state.total_content_height - self.state.viewport_height);
-
- if (phase < 0) {
- return phase; // Negative overshoot (scrolled past top)
- } else if (phase > max_scroll) {
- return phase - max_scroll; // Positive overshoot (scrolled past bottom)
- }
- return 0;
- }
-
- // =========================================================================
- // UPDATE VISIBLE RANGE (spatial culling)
- // =========================================================================
-
- pub fn updateVisibleRange(self: *WaveScrollView) void {
- if (self.total_items == 0) {
- self.visible_start = 0;
- self.visible_end = 0;
- self.packet_count = 0;
- return;
- }
-
- const item_h = self.default_item_height;
- const phase = self.state.scroll_phase;
- const vh = self.state.viewport_height;
-
- // Culling margin = 3 * sigma (where sigma = item_height * PHI)
- const sigma = item_h * DEFAULT_SIGMA_MULT;
- const margin = CULLING_SIGMA_MULT * sigma;
-
- // Compute visible range
- const top = phase - margin;
- const bottom = phase + vh + margin;
-
- const start_idx: usize = if (top <= 0) 0 else @min(
- @as(usize, @intFromFloat(top / item_h)),
- self.total_items,
- );
- const end_idx: usize = @min(
- @as(usize, @intFromFloat(bottom / item_h)) + 1,
- self.total_items,
- );
-
- self.visible_start = start_idx;
- self.visible_end = end_idx;
-
- // Populate packets for visible range
- const count = @min(end_idx - start_idx, MAX_VISIBLE);
- self.packet_count = count;
-
- for (0..count) |i| {
- const idx = start_idx + i;
- const base_y = @as(f32, @floatFromInt(idx)) * item_h;
- self.packets[i] = WavePacket.init(idx, base_y, item_h, .text_standing);
- }
- }
-
- // =========================================================================
- // EVALUATE PACKETS - SIMD (Vec8f Gaussian envelope)
- // =========================================================================
-
- pub fn evaluatePacketsSIMD(self: *WaveScrollView) void {
- const phase = self.state.scroll_phase;
- const vp_center = self.viewport_y + self.viewport_height * 0.5;
- var i: usize = 0;
-
- // SIMD path: process 8 packets at a time
- while (i + SIMD_WIDTH <= self.packet_count) : (i += SIMD_WIDTH) {
- // Load base_y positions
- var base_y_vec: Vec8f = undefined;
- var sigma_vec: Vec8f = undefined;
- for (0..SIMD_WIDTH) |j| {
- base_y_vec[j] = self.packets[i + j].base_y;
- sigma_vec[j] = self.packets[i + j].sigma;
- }
-
- // Compute viewport-relative y
- const phase_vec: Vec8f = @splat(phase);
- const rel_y = base_y_vec - phase_vec;
-
- // Store y positions
- for (0..SIMD_WIDTH) |j| {
- self.y_buffer[i + j] = rel_y[j];
- }
-
- // Gaussian envelope: exp(-(y - center)^2 / (2*sigma^2))
- const center_vec: Vec8f = @splat(vp_center);
- const dy = rel_y - center_vec;
- const dy_sq = dy * dy;
- const sigma_sq = sigma_vec * sigma_vec;
- const two_sigma_sq = sigma_sq + sigma_sq;
- const exponent = -dy_sq / two_sigma_sq;
-
- // Fast SIMD exp approximation
- const amplitude = fastExpNegSIMD(exponent);
-
- // Store amplitudes
- for (0..SIMD_WIDTH) |j| {
- self.amp_buffer[i + j] = amplitude[j];
- }
- }
-
- // Scalar fallback for remainder
- while (i < self.packet_count) : (i += 1) {
- const rel_y = self.packets[i].base_y - phase;
- self.y_buffer[i] = rel_y;
-
- const dy = rel_y - vp_center;
- const sigma = self.packets[i].sigma;
- const exponent = -(dy * dy) / (2.0 * sigma * sigma);
- self.amp_buffer[i] = fastExpNeg(exponent);
- }
- }
-
- // =========================================================================
- // COMPUTE INTERFERENCE (sum wave contributions per viewport row)
- // =========================================================================
-
- pub fn computeInterference(self: *WaveScrollView) void {
- const rows = self.interference_rows;
- if (rows == 0) return;
-
- // Clear interference field
- @memset(self.interference[0..rows], 0);
-
- const vh = self.viewport_height;
- const row_scale = vh / @as(f32, @floatFromInt(rows));
-
- for (0..self.packet_count) |i| {
- const rel_y = self.y_buffer[i];
- const amp = self.amp_buffer[i];
- const freq = self.packets[i].frequency;
- const phs = self.packets[i].phase;
-
- if (amp < 0.01) continue; // Skip negligible packets
-
- // Compute which rows this packet affects
- const sigma = self.packets[i].sigma;
- const center_row_f = rel_y / row_scale;
- const spread = (CULLING_SIGMA_MULT * sigma) / row_scale;
-
- const row_start: usize = if (center_row_f - spread < 0)
- 0
- else
- @min(@as(usize, @intFromFloat(center_row_f - spread)), rows);
- const row_end: usize = @min(
- @as(usize, @intFromFloat(center_row_f + spread)) + 1,
- rows,
- );
-
- // Modulate by scroll velocity: idle=subtle, fast=bright
- const vel_factor = @min(1.0, @abs(self.state.scroll_velocity) / 500.0);
- const idle_base: f32 = 0.15; // Subtle ambient glow when idle
- const modulation = idle_base + (1.0 - idle_base) * vel_factor;
-
- for (row_start..row_end) |r| {
- const ry = @as(f32, @floatFromInt(r)) * row_scale;
- const dy = ry - rel_y;
- const envelope = fastExpNeg(-(dy * dy) / (2.0 * sigma * sigma));
- // Tie wave to scroll_phase (not wall time) for scroll-driven feedback
- const wave = @sin(freq * ry + phs + self.state.scroll_phase * 0.01);
- self.interference[r] += amp * envelope * wave * 0.3 * modulation;
- }
- }
-
- // Clamp interference to [0, 1]
- for (0..rows) |r| {
- self.interference[r] = math.clamp(@abs(self.interference[r]), 0.0, 1.0);
- }
- }
-
- // =========================================================================
- // QUERY METHODS
- // =========================================================================
-
- /// Get item Y position in viewport space
- pub fn getItemY(self: *const WaveScrollView, index: usize) f32 {
- if (index < self.visible_start or index >= self.visible_end) return -10000.0;
- const local_idx = index - self.visible_start;
- if (local_idx >= self.packet_count) return -10000.0;
- return self.y_buffer[local_idx];
- }
-
- /// Get item amplitude (visibility/prominence)
- pub fn getItemAmplitude(self: *const WaveScrollView, index: usize) f32 {
- if (index < self.visible_start or index >= self.visible_end) return 0.0;
- const local_idx = index - self.visible_start;
- if (local_idx >= self.packet_count) return 0.0;
- return self.amp_buffer[local_idx];
- }
-
- /// Get interference value at a viewport row
- pub fn getInterferenceAt(self: *const WaveScrollView, row: usize) f32 {
- if (row >= self.interference_rows) return 0;
- return self.interference[row];
- }
-
- /// Get current scroll phase (compatible with legacy scroll_y)
- pub fn getScrollY(self: *const WaveScrollView) f32 {
- return self.state.scroll_phase;
- }
-
- /// Programmatic scroll to item with phi-based ease-out
- pub fn scrollToItem(self: *WaveScrollView, index: usize) void {
- const target_y = @as(f32, @floatFromInt(index)) * self.default_item_height;
- const delta = target_y - self.state.scroll_phase;
- // Set velocity to reach target: v = delta * PHI (arrive in ~1/PHI seconds)
- self.state.scroll_velocity = delta * PHI;
- }
-
- /// Update viewport dimensions (call after panel resize)
- pub fn setViewport(self: *WaveScrollView, vx: f32, vy: f32, vw: f32, vh: f32) void {
- self.viewport_x = vx;
- self.viewport_y = vy;
- self.viewport_width = vw;
- self.viewport_height = vh;
- self.state.viewport_height = vh;
- self.interference_rows = @min(@as(usize, @intFromFloat(vh)), MAX_INTERFERENCE);
- }
-
- /// Add a scroll snap point (Y position of section boundary)
- pub fn addSnapPoint(self: *WaveScrollView, y: f32) void {
- if (self.snap_count < 64) {
- self.snap_points[self.snap_count] = y;
- self.snap_count += 1;
- self.snap_enabled = true;
- }
- }
-
- /// Find nearest snap point to a given scroll_phase
- fn findNearestSnap(self: *const WaveScrollView, phase: f32) f32 {
- if (self.snap_count == 0) return phase;
- var nearest = self.snap_points[0];
- var min_dist = @abs(phase - nearest);
- for (1..self.snap_count) |i| {
- const dist = @abs(phase - self.snap_points[i]);
- if (dist < min_dist) {
- min_dist = dist;
- nearest = self.snap_points[i];
- }
- }
- return nearest;
- }
-
- /// Get scroll_y with rubber-band offset applied (for rendering)
- pub fn getScrollYWithRubber(self: *const WaveScrollView) f32 {
- return self.state.scroll_phase + self.rubber_offset;
- }
-};
-
-// =============================================================================
-// FAST EXP APPROXIMATIONS
-// =============================================================================
-
-/// Fast scalar exp(-|x|) approximation
-/// Uses (1 - |x|/8)^8 rational approximation
-/// Accuracy: ~1% for x in [0, 5], sufficient for Gaussian culling
-fn fastExpNeg(x: f32) f32 {
- const ax = @abs(x);
- if (ax > 5.0) return 0.0; // Beyond 3*sigma, negligible
- const base = @max(0.0, 1.0 - ax * 0.125); // 1 - |x|/8
- const sq = base * base; // ^2
- const q4 = sq * sq; // ^4
- return q4 * q4; // ^8
-}
-
-/// Fast SIMD exp(-|x|) for Vec8f
-/// Same (1 - |x|/8)^8 approximation, vectorized
-fn fastExpNegSIMD(x: Vec8f) Vec8f {
- const zero: Vec8f = @splat(0.0);
- const one: Vec8f = @splat(1.0);
- const eighth: Vec8f = @splat(0.125);
-
- // |x|
- const ax = @abs(x);
-
- // (1 - |x|/8), clamped to >= 0
- const base = @max(zero, one - ax * eighth);
-
- // (1 - |x|/8)^8
- const sq = base * base; // ^2
- const q4 = sq * sq; // ^4
- return q4 * q4; // ^8
-}
-
-// =============================================================================
-// TESTS
-// =============================================================================
-
-test "phi damping convergence" {
- // Verify: initial velocity decays with golden ratio characteristic
- var wsv = WaveScrollView.init(0, 0, 800, 600);
- wsv.setTotalItems(50, 40.0); // 2000px content β height_factor = 1.0
-
- // Apply impulse (strong enough to overcome velocity cutoff)
- wsv.applyImpulse(5.0); // impulse * 40.0 * 1.0 = 200.0 acceleration
-
- // Simulate 1 second at 60 FPS
- const dt: f32 = 1.0 / 60.0;
- var velocity_history: [60]f32 = undefined;
- for (0..60) |frame| {
- wsv.updatePhysics(dt);
- velocity_history[frame] = wsv.state.scroll_velocity;
- }
-
- // Velocity should decay (not grow) β compare frame 1 vs frame 10
- // (later frames may hit velocity cutoff and be zero)
- try testing.expect(@abs(velocity_history[9]) < @abs(velocity_history[0]));
-
- // Final velocity should be near zero (damped to rest)
- try testing.expect(@abs(velocity_history[59]) < 2.0);
-
- // Scroll phase should have moved
- try testing.expect(wsv.state.scroll_phase != 0);
-}
-
-test "trinity bounce spring" {
- // Verify: overshoot produces restoring force = -TRINITY * overshoot
- var wsv = WaveScrollView.init(0, 0, 800, 600);
- wsv.setTotalItems(10, 40.0); // total_height = 400, viewport = 600 β max_scroll = 0
-
- // Push past end
- wsv.state.scroll_phase = 100.0; // 100px overshoot
-
- // One physics step
- const dt: f32 = 1.0 / 60.0;
- wsv.updatePhysics(dt);
-
- // Velocity should be negative (pulling back)
- try testing.expect(wsv.state.scroll_velocity < 0);
-}
-
-test "simd vs scalar equivalence" {
- var wsv = WaveScrollView.init(0, 0, 800, 600);
- wsv.setTotalItems(100, 40.0);
- wsv.updateVisibleRange();
-
- // Run SIMD evaluation
- wsv.evaluatePacketsSIMD();
-
- // Verify all amplitudes are non-negative
- for (0..wsv.packet_count) |i| {
- try testing.expect(wsv.amp_buffer[i] >= 0.0);
- try testing.expect(wsv.amp_buffer[i] <= 1.0);
- }
-}
-
-test "visible range culling" {
- var wsv = WaveScrollView.init(0, 0, 800, 600);
- wsv.setTotalItems(100000, 40.0); // 100K items
-
- // Scroll to middle
- wsv.state.scroll_phase = 2000000.0; // ~50K items in
-
- wsv.updateVisibleRange();
-
- // Should not have all 100K packets - only visible window
- try testing.expect(wsv.packet_count < MAX_VISIBLE);
- try testing.expect(wsv.packet_count > 0);
- try testing.expect(wsv.visible_start > 0);
- try testing.expect(wsv.visible_end < 100000);
-}
-
-test "fast exp approximation" {
- // Verify fast_exp is reasonable for small values
- const result = fastExpNeg(0.0);
- try testing.expectApproxEqAbs(result, 1.0, 0.01);
-
- const result2 = fastExpNeg(1.0);
- try testing.expect(result2 > 0.0);
- try testing.expect(result2 < 1.0);
-
- // Large values should be ~0
- const result3 = fastExpNeg(6.0);
- try testing.expectApproxEqAbs(result3, 0.0, 0.01);
-}
-
-test "wave scroll view init" {
- const wsv = WaveScrollView.init(10, 20, 800, 600);
- try testing.expectEqual(wsv.viewport_x, 10.0);
- try testing.expectEqual(wsv.viewport_y, 20.0);
- try testing.expectEqual(wsv.viewport_width, 800.0);
- try testing.expectEqual(wsv.viewport_height, 600.0);
- try testing.expectEqual(wsv.state.damping_factor, PHI_INV);
- try testing.expectEqual(wsv.state.inertia_mass, PHI);
- try testing.expectEqual(wsv.packet_count, 0);
-}
-
-test "interference computation" {
- var wsv = WaveScrollView.init(0, 0, 800, 256);
- wsv.setTotalItems(20, 40.0);
- wsv.updateVisibleRange();
- wsv.evaluatePacketsSIMD();
- wsv.computeInterference();
-
- // Interference values should be in [0, 1]
- for (0..wsv.interference_rows) |r| {
- try testing.expect(wsv.interference[r] >= 0.0);
- try testing.expect(wsv.interference[r] <= 1.0);
- }
-}
-
-test "scroll to item" {
- var wsv = WaveScrollView.init(0, 0, 800, 600);
- wsv.setTotalItems(1000, 40.0);
-
- wsv.scrollToItem(500);
-
- // Velocity should be set toward item 500 (y=20000)
- try testing.expect(wsv.state.scroll_velocity > 0);
-}
-
-test "golden identity verification" {
- // phi^2 + 1/phi^2 = 3 = TRINITY
- const identity = PHI * PHI + 1.0 / (PHI * PHI);
- try testing.expectApproxEqAbs(identity, TRINITY, 0.001);
-}
diff --git a/src/vsa/world_dots.zig b/src/vsa/world_dots.zig
deleted file mode 100644
index ca4f92d0d2..0000000000
--- a/src/vsa/world_dots.zig
+++ /dev/null
@@ -1,207 +0,0 @@
-// World land dot-matrix: 180 columns x 90 rows (2-degree resolution)
-// Each row is packed into 23 bytes (180 bits, MSB first). Bit=1 means land.
-// Row 0 = North Pole (lat +90), Row 89 = South Pole (lat -90)
-// Col 0 = lon -180, Col 179 = lon +178
-// Simplified continent outlines for Aceternity-style dot rendering.
-
-// Dot grid: 180 cols x 90 rows. isLand(row, col) checks bit.
-pub const ROWS: u32 = 90;
-pub const COLS: u32 = 180;
-pub const BYTES_PER_ROW: u32 = 23; // ceil(180/8)
-
-/// Check if a given grid cell is land
-pub fn isLand(row: u32, col: u32) bool {
- if (row >= ROWS or col >= COLS) return false;
- const byte_idx = row * BYTES_PER_ROW + col / 8;
- const bit_idx: u3 = @intCast(7 - (col % 8));
- return (LAND_BITMAP[byte_idx] >> bit_idx) & 1 == 1;
-}
-
-/// Convert lat/lon to grid row/col
-pub fn geoToGrid(lat: f32, lon: f32) struct { row: u32, col: u32 } {
- // lat: +90 -> row 0, -90 -> row 89
- const r = @as(i32, @intFromFloat((90.0 - lat) / 2.0));
- const row: u32 = @intCast(@min(@max(r, 0), @as(i32, ROWS - 1)));
- // lon: -180 -> col 0, +178 -> col 179
- const c = @as(i32, @intFromFloat((lon + 180.0) / 2.0));
- const col: u32 = @intCast(@min(@max(c, 0), @as(i32, COLS - 1)));
- return .{ .row = row, .col = col };
-}
-
-// Land bitmap: 90 rows x 23 bytes = 2070 bytes
-// Generated from simplified Natural Earth coastlines at 2-degree resolution.
-// Row 0 = lat 90Β°N (Arctic), Row 89 = lat 88Β°S (Antarctic)
-pub const LAND_BITMAP = [90 * 23]u8{
- // Row 0: lat 90N (Arctic islands)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 1: lat 88N
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 2: lat 86N
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 3: lat 84N (Greenland north tip, Svalbard)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 4: lat 82N (Greenland, Ellesmere)
- 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 5: lat 80N (Greenland, Canadian Arctic, Novaya Zemlya)
- 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 6: lat 78N (Greenland wide, Svalbard, NZ)
- 0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 7: lat 76N (Greenland, Baffin, Scandinavia north)
- 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 8: lat 74N (Greenland, Iceland edge, Norway)
- 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 9: lat 72N (Greenland, Iceland, Scandinavia, Russia N)
- 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00,
- // Row 10: lat 70N (Alaska N, Canada N, Greenland, Scandinavia, Russia)
- 0x00, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x60, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- // Row 11: lat 68N (Alaska, Canada, Iceland, Scandinavia, Russia wide)
- 0xFF, 0x80, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0xF0, 0x00, 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
- // Row 12: lat 66N (Alaska, Canada wide, Greenland S, Europe N, Russia)
- 0xFF, 0xC0, 0x07, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF1, 0xF8, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00,
- // Row 13: lat 64N (Alaska, Canada, Iceland, Scandinavia full, Russia full)
- 0xFF, 0xE0, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF1, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00,
- // Row 14: lat 62N (Alaska, Canada full, N Europe, Russia)
- 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFB, 0xFE, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
- // Row 15: lat 60N (Alaska, Canada, UK, Scandinavia, Russia E)
- 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00,
- // Row 16: lat 58N (Alaska S, Canada S, UK, Baltic, Russia)
- 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00,
- // Row 17: lat 56N (Canada S, UK, Denmark, Poland, Russia)
- 0x7F, 0xFE, 0x3F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
- // Row 18: lat 54N (Canada S, Ireland/UK, Europe central, Russia)
- 0x3F, 0xFF, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
- // Row 19: lat 52N (Canada SE, UK, France, Germany, Ukraine, Russia E, Kamchatka)
- 0x1F, 0xFF, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00,
- // Row 20: lat 50N (Newfoundland, France, Europe, Kazakhstan, Russia E)
- 0x07, 0xFF, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00,
- // Row 21: lat 48N (US NE, France, Italy, Black Sea, Kazakhstan, Mongolia, Sakhalin)
- 0x03, 0xFF, 0x03, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00,
- // Row 22: lat 46N (US N, Spain, Italy, Turkey, Central Asia, China N, Japan N)
- 0x01, 0xFE, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00,
- // Row 23: lat 44N (US, Spain, Med, Turkey, Iran, China, Japan)
- 0x01, 0xFE, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
- // Row 24: lat 42N (US, Portugal, Med, Turkey, Iran, Afghanistan, China, Japan)
- 0x01, 0xFC, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x81, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
- // Row 25: lat 40N (US, Med, Greece, Turkey, Iran, Pakistan N, China, Korea, Japan)
- 0x01, 0xFC, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00,
- // Row 26: lat 38N (US, Med, N Africa edge, Middle East, Pakistan, China, Korea)
- 0x01, 0xFC, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00,
- // Row 27: lat 36N (US S, Morocco, Algeria, Libya, Egypt, Saudi, India N, China S, Japan S)
- 0x00, 0xFC, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7F, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00,
- // Row 28: lat 34N (US S, Morocco, Sahara N, Egypt, Arabia, India N, China, Taiwan)
- 0x00, 0xFC, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x0F, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
- // Row 29: lat 32N (Mexico N, Sahara, Egypt, Saudi, India, China S)
- 0x00, 0x7C, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x0F, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00,
- // Row 30: lat 30N (Mexico, Sahara, Egypt, Arabia, India, Myanmar, Vietnam)
- 0x00, 0x7C, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x0F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00,
- // Row 31: lat 28N (Mexico, Sahara, Egypt, Arabia, India, SE Asia)
- 0x00, 0x3C, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00,
- // Row 32: lat 26N (Mexico, Sahara, Saudi, India wide, SE Asia)
- 0x00, 0x3E, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x07, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
- // Row 33: lat 24N (Mexico S, Caribbean, Sahara S, Arabia, India, SE Asia)
- 0x00, 0x1F, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x07, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00,
- // Row 34: lat 22N (Mexico S, Cuba, Sahel, Arabia S, India S, Myanmar, Philippines)
- 0x00, 0x0F, 0x80, 0x00, 0x1F, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x03, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00,
- // Row 35: lat 20N (Mexico, Caribbean, Sahel wide, Yemen, India S tip, Thailand, Vietnam, Philippines)
- 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x81, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0x80, 0x00, 0x00,
- // Row 36: lat 18N (Central America, Caribbean, W Africa, Ethiopia, India tip, SE Asia)
- 0x00, 0x03, 0xE0, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0xC0, 0x00, 0x3F, 0xCF, 0xFF, 0x00, 0x00, 0x00,
- // Row 37: lat 16N (Central America, W Africa, Ethiopia, India tip, Thailand, Philippines)
- 0x00, 0x01, 0xF0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0x87, 0xFE, 0x00, 0x00, 0x00,
- // Row 38: lat 14N (Central Am, W Africa, Horn of Africa, Sri Lanka, SE Asia islands)
- 0x00, 0x00, 0xF8, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0x03, 0xFC, 0x00, 0x00, 0x00,
- // Row 39: lat 12N (Central Am, Venezuela, W Africa wide, SE Asia)
- 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x06, 0x01, 0xF8, 0x00, 0x00, 0x00,
- // Row 40: lat 10N (Panama, Colombia, Venezuela, W Africa, SE Asia islands)
- 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00,
- // Row 41: lat 8N (Colombia, Venezuela, Guyana, W Africa, SE Asia)
- 0x00, 0x00, 0x1F, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00,
- // Row 42: lat 6N (Colombia, Guyana, Suriname, W Africa, Sumatra, Borneo)
- 0x00, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
- // Row 43: lat 4N (Ecuador, Colombia, Brazil N, C Africa, Sumatra, Borneo, Sulawesi)
- 0x00, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00,
- // Row 44: lat 2N (Ecuador, Brazil, C Africa, Congo, Borneo, Papua)
- 0x00, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00,
- // Row 45: lat 0 (Equator: Ecuador, Brazil, Congo, Kenya, Sumatra, Borneo, Papua)
- 0x00, 0x00, 0x01, 0xF0, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x03, 0xEF, 0xE0, 0x00, 0x00,
- // Row 46: lat 2S (Brazil, Congo, Tanzania, Indonesia)
- 0x00, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x03, 0xC7, 0xF0, 0x00, 0x00,
- // Row 47: lat 4S (Brazil, Congo, Tanzania, Java, Papua)
- 0x00, 0x00, 0x00, 0x7C, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x03, 0x83, 0xF8, 0x00, 0x00,
- // Row 48: lat 6S (Brazil wide, Angola, Tanzania, Java, Papua)
- 0x00, 0x00, 0x00, 0x3E, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x01, 0x01, 0xFC, 0x00, 0x00,
- // Row 49: lat 8S (Brazil, Angola, Mozambique, Timor)
- 0x00, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00,
- // Row 50: lat 10S (Peru, Brazil, Angola, Zambia, Mozambique)
- 0x00, 0x00, 0x00, 0x0F, 0x80, 0x1F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00,
- // Row 51: lat 12S (Peru, Brazil, Angola, Zambia, Mozambique, Madagascar)
- 0x00, 0x00, 0x00, 0x07, 0xC0, 0x3F, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00,
- // Row 52: lat 14S (Peru, Brazil, Namibia, Zambia, Mozambique, Madagascar)
- 0x00, 0x00, 0x00, 0x03, 0xE0, 0x3F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00,
- // Row 53: lat 16S (Peru, Bolivia, Brazil, Namibia, Zimbabwe, Mozambique, Madagascar)
- 0x00, 0x00, 0x00, 0x01, 0xF0, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00,
- // Row 54: lat 18S (Peru, Bolivia, Brazil, Namibia, Zimbabwe, Mozambique, Madagascar)
- 0x00, 0x00, 0x00, 0x00, 0xF8, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00,
- // Row 55: lat 20S (Bolivia, Paraguay, Brazil, Namibia, Botswana, Mozambique, Madagascar)
- 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00,
- // Row 56: lat 22S (Chile, Argentina, Paraguay, Brazil, Namibia, Botswana, S Africa, Madagascar)
- 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00,
- // Row 57: lat 24S (Chile, Argentina, Brazil S, Namibia, S Africa)
- 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00,
- // Row 58: lat 26S (Chile, Argentina, Brazil S, S Africa)
- 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 59: lat 28S (Chile, Argentina, Uruguay, S Africa)
- 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 60: lat 30S (Chile, Argentina, S Africa S)
- 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 61: lat 32S (Chile, Argentina, S Africa tip)
- 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 62: lat 34S (Chile, Argentina, S Africa Cape)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 63: lat 36S (Chile, Argentina narrowing)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 64: lat 38S (Chile, Argentina, New Zealand N)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
- // Row 65: lat 40S (Chile, Argentina narrow, NZ)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
- // Row 66: lat 42S (Chile, Argentina, NZ S)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
- // Row 67: lat 44S (Chile, Argentina S, NZ S, Tasmania)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
- // Row 68: lat 46S (Chile S, Argentina S tip)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 69: lat 48S (Patagonia)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 70: lat 50S (Tierra del Fuego)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 71: lat 52S (Falklands)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 72: lat 54S (Tierra del Fuego tip)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 73-79: lat 56S-68S (Southern Ocean, mostly empty)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 80-84: lat 70S-78S (Antarctic coast fragments)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 83: lat 76S (Antarctic Peninsula)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 84: lat 78S (Antarctic)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Row 85: lat 80S (Antarctic wide)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
- // Row 86: lat 82S (Antarctic)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00,
- // Row 87: lat 84S (Antarctic wide)
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- // Row 88: lat 86S (Antarctic core)
- 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00,
- // Row 89: lat 88S (Antarctic center)
- 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00,
-};
diff --git a/train-types b/train-types
new file mode 100755
index 0000000000..e69de29bb2
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.circleci/config.yml b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.circleci/config.yml
new file mode 100644
index 0000000000..aebb7895e5
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.circleci/config.yml
@@ -0,0 +1,354 @@
+version: 2.1
+
+orbs:
+ win: circleci/windows@5.0
+
+executors:
+ ubuntu:
+ docker:
+ - image: buildpack-deps:focal
+ mac_arm64:
+ environment:
+ EMSDK_NOTTY: "1"
+ # Without this, any `brew install` command will result in self-update of
+ # brew itself which takes more than 4 minutes.
+ HOMEBREW_NO_AUTO_UPDATE: "1"
+ macos:
+ xcode: "13.4.1"
+ resource_class: macos.m1.medium.gen1
+ linux_arm64:
+ machine:
+ image: ubuntu-2004:2023.07.1
+ resource_class: arm.medium
+
+commands:
+ setup-macos:
+ steps:
+ - checkout
+ - run:
+ name: Install CMake
+ command: brew install cmake
+ test-macos:
+ steps:
+ - run:
+ name: test.sh
+ command: test/test.sh
+ - run:
+ name: test.py
+ command: |
+ source emsdk_env.sh
+ test/test.py
+ test-bazel-linux:
+ steps:
+ - checkout
+ - run:
+ name: install bazelisk
+ command: |
+ wget https://github.com/bazelbuild/bazelisk/releases/download/v1.25.0/bazelisk-linux-amd64
+ chmod +x bazelisk-linux-amd64
+ mv bazelisk-linux-amd64 /usr/local/bin/bazel
+ - run: test/test_bazel.sh
+ test-bazel-mac:
+ steps:
+ - checkout
+ - run:
+ name: install bazelisk
+ command: |
+ brew install bazelisk
+ - run: test/test_bazel_mac.sh
+ test-bazel-windows:
+ steps:
+ - checkout
+ - run:
+ name: Download Bazelisk
+ shell: powershell.exe
+ command: |
+ $ProgressPreference = "SilentlyContinue"
+ Invoke-WebRequest -Uri https://github.com/bazelbuild/bazelisk/releases/download/v1.10.1/bazelisk-windows-amd64.exe -OutFile ( New-Item -Path "temp\bazel\bazel.exe" -Force )
+ - run:
+ name: Run Tests
+ shell: powershell.exe
+ command: |
+ $env:Path += ";C:\Python27amd64;$pwd\temp\bazel"
+ .\test\test_bazel.ps1
+
+jobs:
+ flake8:
+ executor: ubuntu
+ steps:
+ - checkout
+ - run:
+ name: install pip
+ command: |
+ apt-get update -q
+ apt-get install -q -y python3-pip
+ - run: python3 -m pip install --upgrade pip
+ - run: python3 -m pip install flake8==7.1.1
+ - run: python3 -m flake8 --show-source --statistics --extend-exclude=./scripts
+
+ test-linux:
+ executor: ubuntu
+ environment:
+ EMSDK_NOTTY: "1"
+ # This is needed because the old gcc-7 that is installed on debian/bionic
+ # generates warnings about unused variables when doing C++17
+ # destructuring:
+ # https://github.com/WebAssembly/binaryen/issues/4353
+ CXXFLAGS: "-Wno-unused-variable"
+ # I don't know why circleci VMs pretent to have 36 cores but its a lie.
+ EMSDK_NUM_CORES: "4"
+ steps:
+ - checkout
+ - run:
+ name: Install debian packages
+ command: apt-get update -q && apt-get install -q -y cmake build-essential openjdk-8-jre-headless ksh zsh
+ - run: test/test_node_path.sh
+ - run: test/test.sh
+ - run: test/test_source_env.sh
+ - run:
+ name: test.py
+ command: |
+ source emsdk_env.sh
+ test/test.py
+ test-linux-arm64:
+ executor: linux_arm64
+ steps:
+ - checkout
+ - run:
+ name: Install debian packages
+ command: sudo apt-get update -q && sudo apt-get install -q cmake build-essential openjdk-8-jre-headless
+ - run: test/test.sh
+ test-mac-arm64:
+ executor: mac_arm64
+ steps:
+ - setup-macos
+ - test-macos
+ test-windows:
+ executor:
+ name: win/server-2019
+ shell: bash.exe
+ environment:
+ # We need python installed before we can test anytyhing.
+ # There seems to be undocument copy of python installed here. Hopefully
+ # if this disappears there will be another way of getting a re-installed
+ # version.
+ PYTHON_BIN: "C:\\Python27amd64"
+ PYTHONUNBUFFERED: "1"
+ EMSDK_NOTTY: "1"
+ steps:
+ - checkout
+ - run:
+ name: Add python to bash path
+ command: echo "export PATH=\"$PATH:/c/python27amd64/\"" >> $BASH_ENV
+ - run:
+ name: Install latest
+ shell: cmd.exe
+ command: test\test.bat
+ - run:
+ name: test.py
+ command: |
+ source emsdk_env.sh
+ python test/test.py
+
+ - run:
+ name: flagless (process/shell) test
+ shell: powershell.exe
+ command: |
+ test/test_activation.ps1
+
+ - run:
+ name: --permanent test
+ shell: powershell.exe
+ command: |
+ $env:PERMANENT_FLAG="--permanent"
+ test/test_activation.ps1
+
+ - run:
+ name: --system test
+ shell: powershell.exe
+ command: |
+ $env:SYSTEM_FLAG="--system"
+ test/test_activation.ps1
+
+ - run:
+ name: Process/Shell PATH preservation test
+ shell: powershell.exe
+ command: |
+ test/test_path_preservation.ps1
+
+ - run:
+ name: User PATH preservation test
+ shell: powershell.exe
+ command: |
+ $env:PERMANENT_FLAG="--permanent"
+ test/test_path_preservation.ps1
+
+ - run:
+ name: System PATH preservation test
+ shell: powershell.exe
+ command: |
+ $env:SYSTEM_FLAG="--system"
+ test/test_path_preservation.ps1
+
+ build-docker-image-x64:
+ executor: ubuntu
+ steps:
+ - checkout
+ - run:
+ name: install docker
+ command: |
+ apt-get update -q
+ apt-get install -q -y ca-certificates curl gnupg lsb-release
+ mkdir -p /etc/apt/keyrings
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+ apt-get update -q
+ apt-get install -q -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+ - setup_remote_docker
+ # Build the `latest` version of EMSDK as docker image
+ - run:
+ name: build
+ command: make -C ./docker version=latest build
+ - run:
+ name: test
+ command: make -C ./docker version=latest test
+
+ publish-docker-image-x64:
+ executor: ubuntu
+ steps:
+ - checkout
+ - run:
+ name: install docker
+ command: |
+ apt-get update -q
+ apt-get install -q -y ca-certificates curl gnupg lsb-release
+ mkdir -p /etc/apt/keyrings
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+ apt-get update -q
+ apt-get install -q -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+ - setup_remote_docker
+ - run:
+ name: build
+ command: make -C ./docker version=${CIRCLE_TAG} build
+ - run:
+ name: test
+ command: make -C ./docker version=${CIRCLE_TAG} test
+ - run:
+ name: push image
+ command: |
+ docker login -u "$DOCKER_USER" -p "$DOCKER_PASS"
+ make -C ./docker version=${CIRCLE_TAG} alias=latest push
+
+ publish-docker-image-arm64:
+ executor: linux_arm64
+ steps:
+ - checkout
+ - run:
+ name: build
+ command: make -C ./docker version=${CIRCLE_TAG} build
+ - run:
+ name: test
+ command: make -C ./docker version=${CIRCLE_TAG} test
+ - run:
+ name: push image
+ command: |
+ docker login -u "$DOCKER_USER" -p "$DOCKER_PASS"
+ make -C ./docker version=${CIRCLE_TAG} alias=${CIRCLE_TAG}-arm64 only_alias=true push
+
+ test-bazel7-linux:
+ executor: ubuntu
+ environment:
+ USE_BAZEL_VERSION: "7.x"
+ steps:
+ - test-bazel-linux
+
+ test-bazel-latest-linux:
+ executor: ubuntu
+ steps:
+ - test-bazel-linux
+
+ test-bazel7-mac-arm64:
+ executor: mac_arm64
+ environment:
+ USE_BAZEL_VERSION: "7.x"
+ steps:
+ - test-bazel-mac
+
+ test-bazel-latest-mac-arm64:
+ executor: mac_arm64
+ steps:
+ - test-bazel-mac
+
+ test-bazel7-windows:
+ executor:
+ name: win/server-2019
+ shell: powershell.exe -ExecutionPolicy Bypass
+ environment:
+ PYTHONUNBUFFERED: "1"
+ EMSDK_NOTTY: "1"
+ # For some reason version resolution with "7.x" does not work on Windows,
+ # so we have to specify a full version.
+ USE_BAZEL_VERSION: "7.6.1"
+ steps:
+ - test-bazel-windows
+
+ test-bazel-latest-windows:
+ executor:
+ name: win/server-2019
+ shell: powershell.exe -ExecutionPolicy Bypass
+ environment:
+ PYTHONUNBUFFERED: "1"
+ EMSDK_NOTTY: "1"
+ steps:
+ - test-bazel-windows
+
+workflows:
+ flake8:
+ jobs:
+ - flake8
+ test-linux:
+ jobs:
+ - test-linux
+ test-linux-arm64:
+ jobs:
+ - test-linux-arm64
+ test-mac-arm64:
+ jobs:
+ - test-mac-arm64
+ test-windows:
+ jobs:
+ - test-windows
+ build-docker-image:
+ jobs:
+ - build-docker-image-x64
+ - publish-docker-image-x64:
+ filters:
+ branches:
+ ignore: /.*/
+ tags:
+ only: /.*/
+ - publish-docker-image-arm64:
+ filters:
+ branches:
+ ignore: /.*/
+ tags:
+ only: /.*/
+ test-bazel7-linux:
+ jobs:
+ - test-bazel7-linux
+ test-bazel-latest-linux:
+ jobs:
+ - test-bazel-latest-linux
+ test-bazel7-mac-arm64:
+ jobs:
+ - test-bazel7-mac-arm64
+ test-bazel-latest-mac-arm64:
+ jobs:
+ - test-bazel-latest-mac-arm64
+ test-bazel7-windows:
+ jobs:
+ - test-bazel7-windows
+ test-bazel-latest-windows:
+ jobs:
+ - test-bazel-latest-windows
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.dockerignore b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.dockerignore
new file mode 100644
index 0000000000..cf12f58fd6
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.dockerignore
@@ -0,0 +1,21 @@
+# Ignore everything
+*
+
+# Allow the entrypoint/test script inside the Docker container
+!/docker/entrypoint.sh
+!/docker/test_dockerimage.sh
+
+# Allow license file
+!LICENSE
+
+# Allow necessary build files in top-level directory
+!emscripten-releases-tags.json
+!emsdk
+!emsdk.py
+!emsdk_env.sh
+!emsdk_manifest.json
+
+# Allow files required to install legacy versions
+!legacy-binaryen-tags.txt
+!legacy-emscripten-tags.txt
+!llvm-tags-64bit.txt
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.flake8 b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.flake8
new file mode 100644
index 0000000000..ec94dda998
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.flake8
@@ -0,0 +1,24 @@
+[flake8]
+extend-exclude =
+ ./.*,
+ ./binaryen,
+ ./clang,
+ ./crunch,
+ ./downloads,
+ ./emscripten,
+ ./fastcomp-clang,
+ ./fastcomp,
+ ./git,
+ ./gnu,
+ ./llvm,
+ ./node,
+ ./python,
+ ./releases,
+ ./temp,
+ ./upstream,
+
+# E111: Indentation is not a multiple of four
+# E114: Indentation is not a multiple of four (comment)
+extend-ignore = E111, E114
+
+max-line-length = 326
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/stale.yml b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/stale.yml
new file mode 100644
index 0000000000..1807a00f71
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/stale.yml
@@ -0,0 +1,18 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 365
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 30
+# Issues with these labels will never be considered stale
+exemptLabels:
+ - pinned
+ - security
+# Label to use when marking an issue as stale
+staleLabel: wontfix
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+ This issue has been automatically marked as stale because there has been no
+ activity in the past year. It will be closed automatically if no further
+ activity occurs in the next 30 days. Feel free to re-open at any time if this
+ issue is still relevant.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: false
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/workflows/create-release.yml b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/workflows/create-release.yml
new file mode 100644
index 0000000000..265a3619d3
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/workflows/create-release.yml
@@ -0,0 +1,40 @@
+name: Create Release PR
+
+on:
+ workflow_dispatch:
+ inputs:
+ lto-sha:
+ required: true
+ type: string
+ nonlto-sha:
+ required: true
+ type: string
+
+jobs:
+ create-release-pr:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+ - name: Run create_release.py
+ run: python3 scripts/create_release.py -r ${{ inputs.lto-sha }} -a ${{ inputs.nonlto-sha }} --gh-action
+ - name: Create PR
+ id: cpr
+ uses: peter-evans/create-pull-request@v6
+ with:
+ token: ${{ secrets.EMSCRIPTEN_BOT_TOKEN }}
+ title: Release ${{ env.RELEASE_VERSION }}
+ commit-message: |
+ Release ${{ env.RELEASE_VERSION }}
+ team-reviewers: release-reviewers
+ labels: release
+ body: |
+ With emscripten-releases revisions:
+ https://chromium.googlesource.com/emscripten-releases/+/${{ inputs.lto-sha }} (LTO)
+ https://chromium.googlesource.com/emscripten-releases/+/${{ inputs.nonlto-sha }} (asserts)
+ branch: release_${{ env.RELEASE_VERSION }}
+ delete-branch: true
+ - name: Enable auto-merge
+ run: gh pr merge --squash --auto "${{ steps.cpr.outputs.pull-request-number }}"
+ env:
+ GH_TOKEN: ${{ secrets.EMSCRIPTEN_BOT_TOKEN }}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/workflows/tag-release.yml b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/workflows/tag-release.yml
new file mode 100644
index 0000000000..1475e879d8
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.github/workflows/tag-release.yml
@@ -0,0 +1,78 @@
+# When a release commit created by create-release.yml is landed, create the
+# corresponding tag.
+name: Create release tag
+
+on:
+ push:
+ paths:
+ - emscripten-releases-tags.json
+ - .github/workflows/tag-release.yml
+ branches:
+ - main
+ workflow_dispatch:
+
+jobs:
+ tag-release:
+ # Only activate for commits created by the create-release.yml workflow.
+ # The assumption is that when manual changes happen, we want to handle
+ # tagging manually too.
+ name: Check for release commit and create tag
+ # The author is emscripten-bot when triggered from Chromium CI, and github-actions when manually triggered.
+ if: ${{ github.event.head_commit.author.username == 'github-actions[bot]' || github.event.head_commit.author.username == 'emscripten-bot' }}
+ runs-on: ubuntu-latest
+ outputs:
+ is_release: ${{ steps.create-tag.outputs.result }}
+ steps:
+ - name: Match message and create tag
+ id: create-tag
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.EMSCRIPTEN_BOT_TOKEN }}
+ # A commit with the message of the form 'Release X.Y.Z' is expected
+ # to have been created by create_release.py and update the latest
+ # release in emscripten-releases-tags.json
+ script: |
+ const message = `${{ github.event.head_commit.message }}`
+ const regex = /Release ([0-9]+.[0-9]+.[0-9]+)/;
+ const match = message.match(regex);
+ let is_release = false;
+ if (match) {
+ const release = match[1];
+ console.log(`Matched release ${release}`);
+ await github.rest.git.createRef({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ ref: `refs/tags/${release}`,
+ sha: context.sha
+ });
+ is_release = true;
+ } else {
+ console.log(`Commit message: '${message}' did not match pattern`);
+ }
+ return is_release;
+
+ dispatch-emscripten-tag:
+ name: Dispatch workflow to tag emscripten repo
+ runs-on: ubuntu-latest
+ needs: tag-release
+ if: ${{ needs.tag-release.outputs.is_release == 'true' }}
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+ - name: Find emscripten revision
+ # get_emscripten_revision_info.py sets env.EMSCRIPTEN_HASH to the
+ # emscripten hash associated with the latest release in
+ # emscripten-releases-tags.json
+ run: python3 scripts/get_emscripten_revision_info.py
+ - name: Dispatch emscripten workflow
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.EMSCRIPTEN_BOT_TOKEN }}
+ script: |
+ await github.rest.actions.createWorkflowDispatch({
+ owner: context.repo.owner,
+ repo: 'emscripten',
+ workflow_id: 'tag-release.yml',
+ ref: 'main',
+ inputs: { 'release-sha': '${{ env.EMSCRIPTEN_HASH }}' }
+ });
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.gitignore b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.gitignore
new file mode 100644
index 0000000000..d181c30d5a
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/.gitignore
@@ -0,0 +1,35 @@
+*.pyc
+__pycache__
+
+# Support for --embedded configs
+/.emscripten
+/.emscripten.old
+/.emscripten_cache
+/.emscripten_cache__last_clear
+/.emscripten_sanity
+/.emscripten_sanity_wasm
+
+# Tags files that get generated at runtime
+/emscripten-releases-tot.txt
+
+# File that get download/extracted by emsdk itself
+/ccache
+/gnu
+/upstream
+/fastcomp
+/fastcomp-clang/
+/llvm
+/ninja
+/releases
+/clang
+/emscripten
+/git
+/node
+/python
+/temp
+/downloads
+/crunch
+/java
+/mingw
+/spidermonkey
+/binaryen
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/LICENSE b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/LICENSE
new file mode 100644
index 0000000000..1b8cf86be7
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2018 Emscripten authors (see AUTHORS in Emscripten)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+----------------------------------------------------------------------------
+
+This is the MIT/Expat Licence. For more information see:
+
+1. http://www.opensource.org/licenses/mit-license.php
+
+2. http://en.wikipedia.org/wiki/MIT_License
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/.bazelrc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/.bazelrc
new file mode 100644
index 0000000000..fbd75a7ea7
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/.bazelrc
@@ -0,0 +1 @@
+build --incompatible_enable_cc_toolchain_resolution
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/.gitignore b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/.gitignore
new file mode 100644
index 0000000000..a6ef824c1f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/.gitignore
@@ -0,0 +1 @@
+/bazel-*
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/BUILD b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/BUILD
new file mode 100644
index 0000000000..387dc669d5
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/BUILD
@@ -0,0 +1,19 @@
+package(default_visibility = ["//visibility:public"])
+
+filegroup(name = "empty")
+
+platform(
+ name = "platform_wasm",
+ constraint_values = [
+ "@platforms//cpu:wasm32",
+ "@platforms//os:emscripten",
+ ],
+)
+
+platform(
+ name = "platform_wasi",
+ constraint_values = [
+ "@platforms//cpu:wasm32",
+ "@platforms//os:wasi",
+ ],
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/MODULE.bazel b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/MODULE.bazel
new file mode 100644
index 0000000000..52401785cb
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/MODULE.bazel
@@ -0,0 +1,79 @@
+module(
+ name = "emsdk",
+ version = "4.0.9",
+)
+
+bazel_dep(name = "platforms", version = "0.0.11")
+bazel_dep(name = "bazel_skylib", version = "1.7.1")
+bazel_dep(name = "aspect_rules_js", version = "1.42.0")
+bazel_dep(name = "rules_nodejs", version = "6.3.2")
+bazel_dep(name = "rules_cc", version = "0.1.1")
+bazel_dep(name = "rules_python", version = "1.3.0")
+
+python = use_extension("@rules_python//python/extensions:python.bzl", "python")
+python.toolchain(
+ python_version = "3.13",
+)
+
+node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
+node.toolchain(node_version = "20.18.0")
+use_repo(node, "nodejs")
+
+emscripten_deps = use_extension(
+ "//:emscripten_deps.bzl",
+ "emscripten_deps",
+)
+use_repo(emscripten_deps, "emscripten_bin_linux")
+use_repo(emscripten_deps, "emscripten_bin_linux_arm64")
+use_repo(emscripten_deps, "emscripten_bin_mac")
+use_repo(emscripten_deps, "emscripten_bin_mac_arm64")
+use_repo(emscripten_deps, "emscripten_bin_win")
+
+npm = use_extension(
+ "@aspect_rules_js//npm:extensions.bzl",
+ "npm",
+)
+npm.npm_translate_lock(
+ name = "emscripten_npm_linux",
+ data = ["@emscripten_bin_linux//:emscripten/package.json"],
+ npm_package_lock = "@emscripten_bin_linux//:emscripten/package-lock.json",
+)
+npm.npm_translate_lock(
+ name = "emscripten_npm_linux_arm64",
+ data = ["@emscripten_bin_linux_arm64//:emscripten/package.json"],
+ npm_package_lock = "@emscripten_bin_linux_arm64//:emscripten/package-lock.json",
+)
+npm.npm_translate_lock(
+ name = "emscripten_npm_mac",
+ data = ["@emscripten_bin_mac//:emscripten/package.json"],
+ npm_package_lock = "@emscripten_bin_mac//:emscripten/package-lock.json",
+)
+npm.npm_translate_lock(
+ name = "emscripten_npm_mac_arm64",
+ data = ["@emscripten_bin_mac_arm64//:emscripten/package.json"],
+ npm_package_lock = "@emscripten_bin_mac_arm64//:emscripten/package-lock.json",
+)
+npm.npm_translate_lock(
+ name = "emscripten_npm_win",
+ data = ["@emscripten_bin_win//:emscripten/package.json"],
+ npm_package_lock = "@emscripten_bin_win//:emscripten/package-lock.json",
+)
+use_repo(
+ npm,
+ "emscripten_npm_linux",
+ "emscripten_npm_linux_arm64",
+ "emscripten_npm_mac",
+ "emscripten_npm_mac_arm64",
+ "emscripten_npm_win",
+)
+
+emscripten_cache = use_extension("//:emscripten_cache.bzl", "emscripten_cache")
+use_repo(emscripten_cache, "emscripten_cache")
+
+register_toolchains(
+ "//emscripten_toolchain:cc-toolchain-wasm-emscripten_linux",
+ "//emscripten_toolchain:cc-toolchain-wasm-emscripten_linux_arm64",
+ "//emscripten_toolchain:cc-toolchain-wasm-emscripten_mac",
+ "//emscripten_toolchain:cc-toolchain-wasm-emscripten_mac_arm64",
+ "//emscripten_toolchain:cc-toolchain-wasm-emscripten_win",
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/MODULE.bazel.lock b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/MODULE.bazel.lock
new file mode 100644
index 0000000000..69ca244b7b
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/MODULE.bazel.lock
@@ -0,0 +1,3696 @@
+{
+ "lockFileVersion": 18,
+ "registryFileHashes": {
+ "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+ "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/MODULE.bazel": "e4529e12d8cd5b828e2b5960d07d3ec032541740d419d7d5b859cabbf5b056f9",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/source.json": "80cb66069ad626e0921555cd2bf278286fd7763fae2450e564e351792e8303f4",
+ "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/MODULE.bazel": "f19e6b4a16f77f8cf3728eac1f60dbfd8e043517fd4f4dbf17a75a6c50936d62",
+ "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/source.json": "abbb3eac3b6af76b8ce230a9a901c6d08d93f4f5ffd55314bf630827dddee57e",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+ "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+ "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/source.json": "3e8379efaaef53ce35b7b8ba419df829315a880cb0a030e5bb45c96d6d5ecb5f",
+ "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
+ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+ "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
+ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
+ "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+ "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+ "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+ "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+ "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+ "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+ "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+ "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
+ "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
+ "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
+ "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c",
+ "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
+ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+ "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+ "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
+ "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
+ "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+ "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+ "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+ "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
+ "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
+ "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960",
+ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
+ "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+ "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/MODULE.bazel": "6bc03c8f37f69401b888023bf511cb6ee4781433b0cb56236b2e55a21e3a026a",
+ "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/MODULE.bazel": "42e8d5254b6135f890fecca7c8d7f95a7d27a45f8275b276f66ec337767530ef",
+ "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/source.json": "80e0a68eb81772f1631f8b69014884eebc2474b3b3025fd19a5240ae4f76f9c9",
+ "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
+ "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+ "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
+ "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+ "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+ "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/source.json": "25932f917cd279c7baefa6cb1d3fa8750a7a29de522024449b19af6eab51f4a0",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
+ "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+ "https://bcr.bazel.build/modules/stardoc/0.5.4/MODULE.bazel": "6569966df04610b8520957cb8e97cf2e9faac2c0309657c537ab51c16c18a2a4",
+ "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
+ "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+ "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d",
+ "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+ },
+ "selectedYankedVersions": {},
+ "moduleExtensions": {
+ "//:emscripten_cache.bzl%emscripten_cache": {
+ "general": {
+ "bzlTransitiveDigest": "uqDvXmpTNqW4+ie/Fk+xC3TrFrKvL+9hNtoP51Kt2oo=",
+ "usagesDigest": "hMVKvInxunfDgmxewLpCIKhgZsrX3FDbi457LYnniZ8=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "emscripten_cache": {
+ "repoRuleId": "@@//:emscripten_cache.bzl%_emscripten_cache_repository",
+ "attributes": {
+ "configuration": [],
+ "targets": []
+ }
+ }
+ },
+ "recordedRepoMappingEntries": []
+ }
+ },
+ "//:emscripten_deps.bzl%emscripten_deps": {
+ "general": {
+ "bzlTransitiveDigest": "h0wQ3PSRx/Q9n+izTifYO8L728OTd9B5YbLOWcobVYE=",
+ "usagesDigest": "/x8y7Sw52S7o089fbMUUat1GlyVBrfKFc31+LteokYI=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "emscripten_bin_linux": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "27fc220a9ad98d323cad73531ff563e9838c9e1205f51ee2a5632bb4266a35d2",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.tar.xz"
+ }
+ },
+ "emscripten_bin_linux_arm64": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "2d03f8eb3f81dd94821658eefbb442a92b0b7601f4cfb08590590fd7bc467ef8",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries-arm64.tar.xz"
+ }
+ },
+ "emscripten_bin_mac": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "c06048915595726fc2e2da6a8db3134581a6287645fb818802a9734ff9785e77",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.tar.xz"
+ }
+ },
+ "emscripten_bin_mac_arm64": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "35d743453d0f91857b09f00d721037bb46753aaeae373bd7f64746338db11770",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries-arm64.tar.xz"
+ }
+ },
+ "emscripten_bin_win": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang.exe\",\n \"bin/clang++.exe\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang.exe\",\n \"bin/llvm-ar.exe\",\n \"bin/llvm-dwarfdump.exe\",\n \"bin/llvm-nm.exe\",\n \"bin/llvm-objcopy.exe\",\n \"bin/wasm-ctor-eval.exe\",\n \"bin/wasm-emscripten-finalize.exe\",\n \"bin/wasm-ld.exe\",\n \"bin/wasm-metadce.exe\",\n \"bin/wasm-opt.exe\",\n \"bin/wasm-split.exe\",\n \"bin/wasm2js.exe\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar.exe\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "3b576e825b26426bb72854ed98752df3fcb58cc3ab1dc116566e328b79a8abb3",
+ "strip_prefix": "install",
+ "type": "zip",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.zip"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "bazel_tools",
+ "rules_cc",
+ "rules_cc+"
+ ]
+ ]
+ }
+ },
+ "@@aspect_bazel_lib+//lib:extensions.bzl%toolchains": {
+ "general": {
+ "bzlTransitiveDigest": "nrCBrZBQH3Dq30TXMpPMV6lWpEDozX0S0kCia4Lrpj0=",
+ "usagesDigest": "1c7PNX163TGNqWzfejRnWpH/hiT4/GRG0kYxuez0Uz0=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "copy_directory_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "copy_directory_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "copy_directory_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "copy_directory_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "copy_directory_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "copy_directory_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "copy_directory_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "copy_directory"
+ }
+ },
+ "copy_to_directory_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "copy_to_directory_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "copy_to_directory_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "copy_to_directory_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "copy_to_directory_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "copy_to_directory_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "copy_to_directory_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "copy_to_directory"
+ }
+ },
+ "jq_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "1.6"
+ }
+ },
+ "jq_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_host_alias_repo",
+ "attributes": {}
+ },
+ "jq_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "jq"
+ }
+ },
+ "yq_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_s390x": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_s390x",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_ppc64le": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_ppc64le",
+ "version": "4.25.2"
+ }
+ },
+ "yq_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_host_alias_repo",
+ "attributes": {}
+ },
+ "yq_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "yq"
+ }
+ },
+ "coreutils_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "coreutils"
+ }
+ },
+ "bsd_tar_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "bsd_tar_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "bsd_tar_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "bsd_tar_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "bsd_tar_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "bsd_tar_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%tar_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "bsd_tar"
+ }
+ },
+ "expand_template_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "expand_template_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "expand_template_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "expand_template_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "expand_template_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "expand_template_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "expand_template_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "expand_template"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "aspect_bazel_lib+",
+ "aspect_bazel_lib",
+ "aspect_bazel_lib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@aspect_rules_js+//npm:extensions.bzl%pnpm": {
+ "general": {
+ "bzlTransitiveDigest": "poAa/2uyrVSr9Hel1HD6GfFwqId27yXfePnG+3Dmt90=",
+ "usagesDigest": "yxkJioaKxOYkZAdkGoq2Cm79s4pW36Xwx7a8awQOU2E=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "pnpm": {
+ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_rule",
+ "attributes": {
+ "package": "pnpm",
+ "version": "8.6.7",
+ "root_package": "",
+ "link_workspace": "",
+ "link_packages": {},
+ "integrity": "sha512-vRIWpD/L4phf9Bk2o/O2TDR8fFoJnpYrp2TKqTIZF/qZ2/rgL3qKXzHofHgbXsinwMoSEigz28sqk3pQ+yMEQQ==",
+ "url": "",
+ "commit": "",
+ "patch_args": [
+ "-p0"
+ ],
+ "patches": [],
+ "custom_postinstall": "",
+ "npm_auth": "",
+ "npm_auth_basic": "",
+ "npm_auth_username": "",
+ "npm_auth_password": "",
+ "lifecycle_hooks": [],
+ "extra_build_content": "load(\"@aspect_rules_js//js:defs.bzl\", \"js_binary\")\njs_binary(name = \"pnpm\", data = glob([\"package/**\"]), entry_point = \"package/dist/pnpm.cjs\", visibility = [\"//visibility:public\"])",
+ "generate_bzl_library_targets": false,
+ "extract_full_archive": true
+ }
+ },
+ "pnpm__links": {
+ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_links",
+ "attributes": {
+ "package": "pnpm",
+ "version": "8.6.7",
+ "dev": false,
+ "root_package": "",
+ "link_packages": {},
+ "deps": {},
+ "transitive_closure": {},
+ "lifecycle_build_target": false,
+ "lifecycle_hooks_env": [],
+ "lifecycle_hooks_execution_requirements": [
+ "no-sandbox"
+ ],
+ "lifecycle_hooks_use_default_shell_env": false,
+ "bins": {},
+ "package_visibility": [
+ "//visibility:public"
+ ],
+ "replace_package": ""
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "aspect_bazel_lib+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "aspect_rules_js+",
+ "aspect_bazel_lib",
+ "aspect_bazel_lib+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_features",
+ "bazel_features+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_globals",
+ "bazel_features++version_extension+bazel_features_globals"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_version",
+ "bazel_features++version_extension+bazel_features_version"
+ ],
+ [
+ "bazel_features+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@pybind11_bazel+//:python_configure.bzl%extension": {
+ "general": {
+ "bzlTransitiveDigest": "d4N/SZrl3ONcmzE98rcV0Fsro0iUbjNQFTIiLiGuH+k=",
+ "usagesDigest": "fycyB39YnXIJkfWCIXLUKJMZzANcuLy9ZE73hRucjFk=",
+ "recordedFileInputs": {
+ "@@pybind11_bazel+//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e"
+ },
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "local_config_python": {
+ "repoRuleId": "@@pybind11_bazel+//:python_configure.bzl%python_configure",
+ "attributes": {}
+ },
+ "pybind11": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file": "@@pybind11_bazel+//:pybind11.BUILD",
+ "strip_prefix": "pybind11-2.11.1",
+ "urls": [
+ "https://github.com/pybind/pybind11/archive/v2.11.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "pybind11_bazel+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_fuzzing+//fuzzing/private:extensions.bzl%non_module_dependencies": {
+ "general": {
+ "bzlTransitiveDigest": "mGiTB79hRNjmeDTQdzkpCHyzXhErMbufeAmySBt7s5s=",
+ "usagesDigest": "wy6ISK6UOcBEjj/mvJ/S3WeXoO67X+1llb9yPyFtPgc=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "platforms": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "urls": [
+ "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz",
+ "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz"
+ ],
+ "sha256": "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74"
+ }
+ },
+ "rules_python": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8",
+ "strip_prefix": "rules_python-0.28.0",
+ "url": "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz"
+ }
+ },
+ "bazel_skylib": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
+ "urls": [
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
+ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"
+ ]
+ }
+ },
+ "com_google_absl": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "urls": [
+ "https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.1.zip"
+ ],
+ "strip_prefix": "abseil-cpp-20240116.1",
+ "integrity": "sha256-7capMWOvWyoYbUaHF/b+I2U6XLMaHmky8KugWvfXYuk="
+ }
+ },
+ "rules_fuzzing_oss_fuzz": {
+ "repoRuleId": "@@rules_fuzzing+//fuzzing/private/oss_fuzz:repository.bzl%oss_fuzz_repository",
+ "attributes": {}
+ },
+ "honggfuzz": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file": "@@rules_fuzzing+//:honggfuzz.BUILD",
+ "sha256": "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e",
+ "url": "https://github.com/google/honggfuzz/archive/2.5.zip",
+ "strip_prefix": "honggfuzz-2.5"
+ }
+ },
+ "rules_fuzzing_jazzer": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar",
+ "attributes": {
+ "sha256": "ee6feb569d88962d59cb59e8a31eb9d007c82683f3ebc64955fd5b96f277eec2",
+ "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer/0.20.1/jazzer-0.20.1.jar"
+ }
+ },
+ "rules_fuzzing_jazzer_api": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar",
+ "attributes": {
+ "sha256": "f5a60242bc408f7fa20fccf10d6c5c5ea1fcb3c6f44642fec5af88373ae7aa1b",
+ "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer-api/0.20.1/jazzer-api-0.20.1.jar"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_fuzzing+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": {
+ "general": {
+ "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=",
+ "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "compatibility_proxy": {
+ "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule",
+ "attributes": {}
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_java+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
+ "general": {
+ "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=",
+ "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "com_github_jetbrains_kotlin_git": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
+ ],
+ "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
+ }
+ },
+ "com_github_jetbrains_kotlin": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
+ "attributes": {
+ "git_repository_name": "com_github_jetbrains_kotlin_git",
+ "compiler_version": "1.9.23"
+ }
+ },
+ "com_github_google_ksp": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
+ ],
+ "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
+ "strip_version": "1.9.23-1.0.20"
+ }
+ },
+ "com_github_pinterest_ktlint": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
+ "attributes": {
+ "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
+ "urls": [
+ "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
+ ],
+ "executable": true
+ }
+ },
+ "rules_android": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
+ "strip_prefix": "rules_android-0.1.1",
+ "urls": [
+ "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_kotlin+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_nodejs+//nodejs:extensions.bzl%node": {
+ "general": {
+ "bzlTransitiveDigest": "rphcryfYrOY/P3emfTskC/GY5YuHcwMl2B2ncjaM8lY=",
+ "usagesDigest": "02fIHVSGNmq3/4pf3KaxTES2ZYYjuW75/2q5dmj9+p0=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "nodejs_linux_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_amd64"
+ }
+ },
+ "nodejs_linux_arm64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_arm64"
+ }
+ },
+ "nodejs_linux_s390x": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_s390x"
+ }
+ },
+ "nodejs_linux_ppc64le": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_ppc64le"
+ }
+ },
+ "nodejs_darwin_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "darwin_amd64"
+ }
+ },
+ "nodejs_darwin_arm64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "darwin_arm64"
+ }
+ },
+ "nodejs_windows_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "windows_amd64"
+ }
+ },
+ "nodejs": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ },
+ "nodejs_host": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ },
+ "nodejs_toolchains": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_toolchains_repo.bzl%nodejs_toolchains_repo",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": []
+ }
+ },
+ "@@rules_python+//python/extensions:pip.bzl%pip": {
+ "general": {
+ "bzlTransitiveDigest": "Y1+Nq7F10jItATWoJUqrIUjUtsCs4cqQw9XXIyl9S3A=",
+ "usagesDigest": "F5jSeup4ZspeKK83+fXZFbblRp0MSGdobyZdSKc8xP8=",
+ "recordedFileInputs": {
+ "@@protobuf+//python/requirements.txt": "983be60d3cec4b319dcab6d48aeb3f5b2f7c3350f26b3a9e97486c37967c73c5",
+ "@@rules_fuzzing+//fuzzing/requirements.txt": "ab04664be026b632a0d2a2446c4f65982b7654f5b6851d2f9d399a19b7242a5b",
+ "@@rules_python+//tools/publish/requirements_darwin.txt": "095d4a4f3d639dce831cd493367631cd51b53665292ab20194bac2c0c6458fa8",
+ "@@rules_python+//tools/publish/requirements_linux.txt": "d576e0d8542df61396a9b38deeaa183c24135ed5e8e73bb9622f298f2671811e",
+ "@@rules_python+//tools/publish/requirements_windows.txt": "d18538a3982beab378fd5687f4db33162ee1ece69801f9a451661b1b64286b76"
+ },
+ "recordedDirentsInputs": {},
+ "envVariables": {
+ "RULES_PYTHON_REPO_DEBUG": null,
+ "RULES_PYTHON_REPO_DEBUG_VERBOSITY": null
+ },
+ "generatedRepoSpecs": {
+ "pip_deps_310_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "pip_deps_310",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_310_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "pip_deps_310",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_311_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "pip_deps_311",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_311_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "pip_deps_311",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_312_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "pip_deps_312",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_312_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "pip_deps_312",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_38_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "pip_deps_38",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_38_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "pip_deps_38",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_39_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "pip_deps_39",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_39_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "pip_deps_39",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "rules_fuzzing_py_deps_310_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "rules_fuzzing_py_deps_310",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_310_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "rules_fuzzing_py_deps_310",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_311_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_fuzzing_py_deps_311",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_311_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_fuzzing_py_deps_311",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_312_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "rules_fuzzing_py_deps_312",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_312_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "rules_fuzzing_py_deps_312",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_38_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "rules_fuzzing_py_deps_38",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_38_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "rules_fuzzing_py_deps_38",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_39_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "rules_fuzzing_py_deps_39",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_39_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "rules_fuzzing_py_deps_39",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "backports.tarfile-1.2.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "backports-tarfile==1.2.0",
+ "sha256": "77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "backports_tarfile-1.2.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "backports-tarfile==1.2.0",
+ "sha256": "d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991",
+ "urls": [
+ "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_certifi_py3_none_any_922820b5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "certifi-2024.8.30-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "certifi==2024.8.30",
+ "sha256": "922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_certifi_sdist_bec941d2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "certifi-2024.8.30.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "certifi==2024.8.30",
+ "sha256": "bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_sdist_1c39c601": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "cffi-1.17.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824",
+ "urls": [
+ "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944",
+ "urls": [
+ "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee",
+ "urls": [
+ "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea",
+ "urls": [
+ "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc",
+ "urls": [
+ "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27",
+ "urls": [
+ "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079",
+ "urls": [
+ "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_sdist_223217c3": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "charset_normalizer-3.4.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7",
+ "urls": [
+ "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16",
+ "urls": [
+ "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_sdist_315b9001": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "cryptography-43.0.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805",
+ "urls": [
+ "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "docutils-0.21.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "docutils==0.21.2",
+ "sha256": "dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_docutils_sdist_3a6b1873": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "docutils-0.21.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "docutils==0.21.2",
+ "sha256": "3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_idna_py3_none_any_946d195a": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "idna-3.10-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "idna==3.10",
+ "sha256": "946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3",
+ "urls": [
+ "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_idna_sdist_12f65c9b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "idna-3.10.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "idna==3.10",
+ "sha256": "12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "importlib_metadata-8.5.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "importlib-metadata==8.5.0",
+ "sha256": "45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_importlib_metadata_sdist_71522656": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "importlib_metadata-8.5.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "importlib-metadata==8.5.0",
+ "sha256": "71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7",
+ "urls": [
+ "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.classes-3.4.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-classes==3.4.0",
+ "sha256": "f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790",
+ "urls": [
+ "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco.classes-3.4.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-classes==3.4.0",
+ "sha256": "47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd",
+ "urls": [
+ "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.context-6.0.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-context==6.0.1",
+ "sha256": "f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco_context-6.0.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-context==6.0.1",
+ "sha256": "9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3",
+ "urls": [
+ "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.functools-4.1.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-functools==4.1.0",
+ "sha256": "ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649",
+ "urls": [
+ "https://files.pythonhosted.org/packages/9f/4f/24b319316142c44283d7540e76c7b5a6dbd5db623abd86bb7b3491c21018/jaraco.functools-4.1.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco_functools-4.1.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-functools==4.1.0",
+ "sha256": "70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ab/23/9894b3df5d0a6eb44611c36aec777823fc2e07740dabbd0b810e19594013/jaraco_functools-4.1.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "jeepney-0.8.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jeepney==0.8.0",
+ "sha256": "c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ae/72/2a1e2290f1ab1e06f71f3d0f1646c9e4634e70e1d37491535e19266e8dc9/jeepney-0.8.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jeepney_sdist_5efe48d2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jeepney-0.8.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jeepney==0.8.0",
+ "sha256": "5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d6/f4/154cf374c2daf2020e05c3c6a03c91348d59b23c5366e968feb198306fdf/jeepney-0.8.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_keyring_py3_none_any_5426f817": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "keyring-25.4.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "keyring==25.4.1",
+ "sha256": "5426f817cf7f6f007ba5ec722b1bcad95a75b27d780343772ad76b17cb47b0bf",
+ "urls": [
+ "https://files.pythonhosted.org/packages/83/25/e6d59e5f0a0508d0dca8bb98c7f7fd3772fc943ac3f53d5ab18a218d32c0/keyring-25.4.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_keyring_sdist_b07ebc55": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "keyring-25.4.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "keyring==25.4.1",
+ "sha256": "b07ebc55f3e8ed86ac81dd31ef14e81ace9dd9c3d4b5d77a6e9a2016d0d71a1b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a5/1c/2bdbcfd5d59dc6274ffb175bc29aa07ecbfab196830e0cfbde7bd861a2ea/keyring-25.4.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "markdown_it_py-3.0.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "markdown-it-py==3.0.0",
+ "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1",
+ "urls": [
+ "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "markdown-it-py-3.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "markdown-it-py==3.0.0",
+ "sha256": "e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb",
+ "urls": [
+ "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_mdurl_py3_none_any_84008a41": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "mdurl-0.1.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "mdurl==0.1.2",
+ "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_mdurl_sdist_bb413d29": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "mdurl-0.1.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "mdurl==0.1.2",
+ "sha256": "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "more_itertools-10.5.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "more-itertools==10.5.0",
+ "sha256": "037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef",
+ "urls": [
+ "https://files.pythonhosted.org/packages/48/7e/3a64597054a70f7c86eb0a7d4fc315b8c1ab932f64883a297bdffeb5f967/more_itertools-10.5.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_more_itertools_sdist_5482bfef": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "more-itertools-10.5.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "more-itertools==10.5.0",
+ "sha256": "5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/51/78/65922308c4248e0eb08ebcbe67c95d48615cc6f27854b6f2e57143e9178f/more-itertools-10.5.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "14c5a72e9fe82aea5fe3072116ad4661af5cf8e8ff8fc5ad3450f123e4925e86",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b3/89/1daff5d9ba5a95a157c092c7c5f39b8dd2b1ddb4559966f808d31cfb67e0/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "7b7c2a3c9eb1a827d42539aa64091640bd275b81e097cd1d8d82ef91ffa2e811",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2c/b6/42fc3c69cabf86b6b81e4c051a9b6e249c5ba9f8155590222c2622961f58/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "42c64511469005058cd17cc1537578eac40ae9f7200bedcfd1fc1a05f4f8c200",
+ "urls": [
+ "https://files.pythonhosted.org/packages/45/b9/833f385403abaf0023c6547389ec7a7acf141ddd9d1f21573723a6eab39a/nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "0411beb0589eacb6734f28d5497ca2ed379eafab8ad8c84b31bb5c34072b7164",
+ "urls": [
+ "https://files.pythonhosted.org/packages/05/2b/85977d9e11713b5747595ee61f381bc820749daf83f07b90b6c9964cf932/nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "5f36b271dae35c465ef5e9090e1fdaba4a60a56f0bb0ba03e0932a66f28b9189",
+ "urls": [
+ "https://files.pythonhosted.org/packages/72/f2/5c894d5265ab80a97c68ca36f25c8f6f0308abac649aaf152b74e7e854a8/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "19aaba96e0f795bd0a6c56291495ff59364f4300d4a39b29a0abc9cb3774a84b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/c2/a8/3bb02d0c60a03ad3a112b76c46971e9480efa98a8946677b5a59f60130ca/nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "de3ceed6e661954871d6cd78b410213bdcb136f79aafe22aa7182e028b8c7307",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1b/63/6ab90d0e5225ab9780f6c9fb52254fa36b52bb7c188df9201d05b647e5e1/nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "f0eca9ca8628dbb4e916ae2491d72957fdd35f7a5d326b7032a345f111ac07fe",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a3/da/0c4e282bc3cff4a0adf37005fa1fb42257673fbc1bbf7d1ff639ec3d255a/nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "3a157ab149e591bb638a55c8c6bcb8cdb559c8b12c13a8affaba6cedfe51713a",
+ "urls": [
+ "https://files.pythonhosted.org/packages/de/81/c291231463d21da5f8bba82c8167a6d6893cc5419b0639801ee5d3aeb8a9/nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "36c95d4b70530b320b365659bb5034341316e6a9b30f0b25fa9c9eff4c27a204",
+ "urls": [
+ "https://files.pythonhosted.org/packages/eb/61/73a007c74c37895fdf66e0edcd881f5eaa17a348ff02f4bb4bc906d61085/nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-win_amd64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "8ce0f819d2f1933953fca255db2471ad58184a60508f03e6285e5114b6254844",
+ "urls": [
+ "https://files.pythonhosted.org/packages/26/8d/53c5b19c4999bdc6ba95f246f4ef35ca83d7d7423e5e38be43ad66544e5d/nh3-0.2.18-cp37-abi3-win_amd64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_sdist_94a16692": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "nh3-0.2.18.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "94a166927e53972a9698af9542ace4e38b9de50c34352b962f4d9a7d4c927af4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/73/10df50b42ddb547a907deeb2f3c9823022580a7a47281e8eae8e003a9639/nh3-0.2.18.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pkginfo-1.10.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pkginfo==1.10.0",
+ "sha256": "889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097",
+ "urls": [
+ "https://files.pythonhosted.org/packages/56/09/054aea9b7534a15ad38a363a2bd974c20646ab1582a387a95b8df1bfea1c/pkginfo-1.10.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pkginfo_sdist_5df73835": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pkginfo-1.10.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pkginfo==1.10.0",
+ "sha256": "5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2f/72/347ec5be4adc85c182ed2823d8d1c7b51e13b9a6b0c1aae59582eca652df/pkginfo-1.10.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "pycparser-2.22-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pycparser==2.22",
+ "sha256": "c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc",
+ "urls": [
+ "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pycparser_sdist_491c8be9": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pycparser-2.22.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pycparser==2.22",
+ "sha256": "491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pygments-2.18.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pygments==2.18.0",
+ "sha256": "b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pygments_sdist_786ff802": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pygments-2.18.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pygments==2.18.0",
+ "sha256": "786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pywin32_ctypes-0.2.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pywin32-ctypes==0.2.3",
+ "sha256": "8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pywin32-ctypes-0.2.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pywin32-ctypes==0.2.3",
+ "sha256": "d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755",
+ "urls": [
+ "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "readme_renderer-44.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "readme-renderer==44.0",
+ "sha256": "2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151",
+ "urls": [
+ "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_readme_renderer_sdist_8712034e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "readme_renderer-44.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "readme-renderer==44.0",
+ "sha256": "8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1",
+ "urls": [
+ "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_py3_none_any_70761cfe": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "requests-2.32.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests==2.32.3",
+ "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_sdist_55365417": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "requests-2.32.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests==2.32.3",
+ "sha256": "55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
+ "urls": [
+ "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "requests_toolbelt-1.0.0-py2.py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests-toolbelt==1.0.0",
+ "sha256": "cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06",
+ "urls": [
+ "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "requests-toolbelt-1.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests-toolbelt==1.0.0",
+ "sha256": "7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "rfc3986-2.0.0-py2.py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rfc3986==2.0.0",
+ "sha256": "50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rfc3986_sdist_97aacf9d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "rfc3986-2.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rfc3986==2.0.0",
+ "sha256": "97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rich_py3_none_any_6049d5e6": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "rich-13.9.4-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rich==13.9.4",
+ "sha256": "6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90",
+ "urls": [
+ "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rich_sdist_43959497": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "rich-13.9.4.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rich==13.9.4",
+ "sha256": "439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "SecretStorage-3.3.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "secretstorage==3.3.3",
+ "sha256": "f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99",
+ "urls": [
+ "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_secretstorage_sdist_2403533e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "SecretStorage-3.3.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "secretstorage==3.3.3",
+ "sha256": "2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77",
+ "urls": [
+ "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_twine_py3_none_any_215dbe7b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "twine-5.1.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "twine==5.1.1",
+ "sha256": "215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997",
+ "urls": [
+ "https://files.pythonhosted.org/packages/5d/ec/00f9d5fd040ae29867355e559a94e9a8429225a0284a3f5f091a3878bfc0/twine-5.1.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_twine_sdist_9aa08251": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "twine-5.1.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "twine==5.1.1",
+ "sha256": "9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db",
+ "urls": [
+ "https://files.pythonhosted.org/packages/77/68/bd982e5e949ef8334e6f7dcf76ae40922a8750aa2e347291ae1477a4782b/twine-5.1.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "urllib3-2.2.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "urllib3==2.2.3",
+ "sha256": "ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_urllib3_sdist_e7d814a8": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "urllib3-2.2.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "urllib3==2.2.3",
+ "sha256": "e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_zipp_py3_none_any_a817ac80": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "zipp-3.20.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "zipp==3.20.2",
+ "sha256": "a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_zipp_sdist_bc9eb26f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "zipp-3.20.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "zipp==3.20.2",
+ "sha256": "bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29",
+ "urls": [
+ "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz"
+ ]
+ }
+ },
+ "pip_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "pip_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "numpy": "{\"pip_deps_310_numpy\":[{\"version\":\"3.10\"}],\"pip_deps_311_numpy\":[{\"version\":\"3.11\"}],\"pip_deps_312_numpy\":[{\"version\":\"3.12\"}],\"pip_deps_38_numpy\":[{\"version\":\"3.8\"}],\"pip_deps_39_numpy\":[{\"version\":\"3.9\"}]}",
+ "setuptools": "{\"pip_deps_310_setuptools\":[{\"version\":\"3.10\"}],\"pip_deps_311_setuptools\":[{\"version\":\"3.11\"}],\"pip_deps_312_setuptools\":[{\"version\":\"3.12\"}],\"pip_deps_38_setuptools\":[{\"version\":\"3.8\"}],\"pip_deps_39_setuptools\":[{\"version\":\"3.9\"}]}"
+ },
+ "packages": [
+ "numpy",
+ "setuptools"
+ ],
+ "groups": {}
+ }
+ },
+ "rules_fuzzing_py_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "rules_fuzzing_py_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "absl_py": "{\"rules_fuzzing_py_deps_310_absl_py\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_absl_py\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_absl_py\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_absl_py\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_absl_py\":[{\"version\":\"3.9\"}]}",
+ "six": "{\"rules_fuzzing_py_deps_310_six\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_six\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_six\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_six\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_six\":[{\"version\":\"3.9\"}]}"
+ },
+ "packages": [
+ "absl_py",
+ "six"
+ ],
+ "groups": {}
+ }
+ },
+ "rules_python_publish_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "rules_python_publish_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "backports_tarfile": "{\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\":[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\":[{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "certifi": "{\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\":[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_certifi_sdist_bec941d2\":[{\"filename\":\"certifi-2024.8.30.tar.gz\",\"version\":\"3.11\"}]}",
+ "cffi": "{\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_sdist_1c39c601\":[{\"filename\":\"cffi-1.17.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "charset_normalizer": "{\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\":[{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\":[{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "cryptography": "{\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_sdist_315b9001\":[{\"filename\":\"cryptography-43.0.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "docutils": "{\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\":[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\":[{\"filename\":\"docutils-0.21.2.tar.gz\",\"version\":\"3.11\"}]}",
+ "idna": "{\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\":[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_idna_sdist_12f65c9b\":[{\"filename\":\"idna-3.10.tar.gz\",\"version\":\"3.11\"}]}",
+ "importlib_metadata": "{\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\":[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\":[{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_classes": "{\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\":[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\":[{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_context": "{\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\":[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\":[{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_functools": "{\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\":[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\":[{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jeepney": "{\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\":[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\":[{\"filename\":\"jeepney-0.8.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "keyring": "{\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\":[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\":[{\"filename\":\"keyring-25.4.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "markdown_it_py": "{\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\":[{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\":[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "mdurl": "{\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\":[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\":[{\"filename\":\"mdurl-0.1.2.tar.gz\",\"version\":\"3.11\"}]}",
+ "more_itertools": "{\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\":[{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\":[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "nh3": "{\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_sdist_94a16692\":[{\"filename\":\"nh3-0.2.18.tar.gz\",\"version\":\"3.11\"}]}",
+ "pkginfo": "{\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\":[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\":[{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "pycparser": "{\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\":[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\":[{\"filename\":\"pycparser-2.22.tar.gz\",\"version\":\"3.11\"}]}",
+ "pygments": "{\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\":[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pygments_sdist_786ff802\":[{\"filename\":\"pygments-2.18.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "pywin32_ctypes": "{\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\":[{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\":[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "readme_renderer": "{\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\":[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\":[{\"filename\":\"readme_renderer-44.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "requests": "{\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\":[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_sdist_55365417\":[{\"filename\":\"requests-2.32.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "requests_toolbelt": "{\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\":[{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\":[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "rfc3986": "{\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\":[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\":[{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "rich": "{\"rules_python_publish_deps_311_rich_py3_none_any_6049d5e6\":[{\"filename\":\"rich-13.9.4-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rich_sdist_43959497\":[{\"filename\":\"rich-13.9.4.tar.gz\",\"version\":\"3.11\"}]}",
+ "secretstorage": "{\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\":[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\":[{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "twine": "{\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\":[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_twine_sdist_9aa08251\":[{\"filename\":\"twine-5.1.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "urllib3": "{\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\":[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\":[{\"filename\":\"urllib3-2.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "zipp": "{\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\":[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\":[{\"filename\":\"zipp-3.20.2.tar.gz\",\"version\":\"3.11\"}]}"
+ },
+ "packages": [
+ "backports_tarfile",
+ "certifi",
+ "charset_normalizer",
+ "docutils",
+ "idna",
+ "importlib_metadata",
+ "jaraco_classes",
+ "jaraco_context",
+ "jaraco_functools",
+ "keyring",
+ "markdown_it_py",
+ "mdurl",
+ "more_itertools",
+ "nh3",
+ "pkginfo",
+ "pygments",
+ "readme_renderer",
+ "requests",
+ "requests_toolbelt",
+ "rfc3986",
+ "rich",
+ "twine",
+ "urllib3",
+ "zipp"
+ ],
+ "groups": {}
+ }
+ }
+ },
+ "moduleExtensionMetadata": {
+ "useAllRepos": "NO",
+ "reproducible": false
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "bazel_features+",
+ "bazel_features_globals",
+ "bazel_features++version_extension+bazel_features_globals"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_version",
+ "bazel_features++version_extension+bazel_features_version"
+ ],
+ [
+ "rules_python+",
+ "bazel_features",
+ "bazel_features+"
+ ],
+ [
+ "rules_python+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "rules_python+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "rules_python+",
+ "pypi__build",
+ "rules_python++internal_deps+pypi__build"
+ ],
+ [
+ "rules_python+",
+ "pypi__click",
+ "rules_python++internal_deps+pypi__click"
+ ],
+ [
+ "rules_python+",
+ "pypi__colorama",
+ "rules_python++internal_deps+pypi__colorama"
+ ],
+ [
+ "rules_python+",
+ "pypi__importlib_metadata",
+ "rules_python++internal_deps+pypi__importlib_metadata"
+ ],
+ [
+ "rules_python+",
+ "pypi__installer",
+ "rules_python++internal_deps+pypi__installer"
+ ],
+ [
+ "rules_python+",
+ "pypi__more_itertools",
+ "rules_python++internal_deps+pypi__more_itertools"
+ ],
+ [
+ "rules_python+",
+ "pypi__packaging",
+ "rules_python++internal_deps+pypi__packaging"
+ ],
+ [
+ "rules_python+",
+ "pypi__pep517",
+ "rules_python++internal_deps+pypi__pep517"
+ ],
+ [
+ "rules_python+",
+ "pypi__pip",
+ "rules_python++internal_deps+pypi__pip"
+ ],
+ [
+ "rules_python+",
+ "pypi__pip_tools",
+ "rules_python++internal_deps+pypi__pip_tools"
+ ],
+ [
+ "rules_python+",
+ "pypi__pyproject_hooks",
+ "rules_python++internal_deps+pypi__pyproject_hooks"
+ ],
+ [
+ "rules_python+",
+ "pypi__setuptools",
+ "rules_python++internal_deps+pypi__setuptools"
+ ],
+ [
+ "rules_python+",
+ "pypi__tomli",
+ "rules_python++internal_deps+pypi__tomli"
+ ],
+ [
+ "rules_python+",
+ "pypi__wheel",
+ "rules_python++internal_deps+pypi__wheel"
+ ],
+ [
+ "rules_python+",
+ "pypi__zipp",
+ "rules_python++internal_deps+pypi__zipp"
+ ],
+ [
+ "rules_python+",
+ "pythons_hub",
+ "rules_python++python+pythons_hub"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_10_host",
+ "rules_python++python+python_3_10_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_11_host",
+ "rules_python++python+python_3_11_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_12_host",
+ "rules_python++python+python_3_12_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_13_host",
+ "rules_python++python+python_3_13_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_8_host",
+ "rules_python++python+python_3_8_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_9_host",
+ "rules_python++python+python_3_9_host"
+ ]
+ ]
+ }
+ },
+ "@@rules_python+//python/uv:uv.bzl%uv": {
+ "general": {
+ "bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=",
+ "usagesDigest": "vJ5RHUxAnV24M5swNGiAnkdxMx3Hp/iOLmNANTC5Xc8=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "uv": {
+ "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
+ "attributes": {
+ "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
+ "toolchain_names": [
+ "none"
+ ],
+ "toolchain_implementations": {
+ "none": "'@@rules_python+//python:none'"
+ },
+ "toolchain_compatible_with": {
+ "none": [
+ "@platforms//:incompatible"
+ ]
+ },
+ "toolchain_target_settings": {}
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_python+",
+ "platforms",
+ "platforms"
+ ]
+ ]
+ }
+ }
+ }
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/bazelrc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/bazelrc
new file mode 100644
index 0000000000..d1c8aef229
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/bazelrc
@@ -0,0 +1,2 @@
+build:wasm --incompatible_enable_cc_toolchain_resolution
+build:wasm --platforms=@emsdk//:platform_wasm
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_build_file.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_build_file.bzl
new file mode 100644
index 0000000000..0d7aff28ca
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_build_file.bzl
@@ -0,0 +1,93 @@
+"""A templated build file for emscripten repositories"""
+
+EMSCRIPTEN_BUILD_FILE_CONTENT_TEMPLATE = """
+package(default_visibility = ['//visibility:public'])
+
+filegroup(
+ name = "all",
+ srcs = glob(["**"]),
+)
+
+filegroup(
+ name = "includes",
+ srcs = glob([
+ "emscripten/cache/sysroot/include/c++/v1/**",
+ "emscripten/cache/sysroot/include/compat/**",
+ "emscripten/cache/sysroot/include/**",
+ "lib/clang/**/include/**",
+ ]),
+)
+
+filegroup(
+ name = "emcc_common",
+ srcs = [
+ "emscripten/emcc.py",
+ "emscripten/embuilder.py",
+ "emscripten/emscripten-version.txt",
+ "emscripten/cache/sysroot_install.stamp",
+ "emscripten/src/settings.js",
+ "emscripten/src/settings_internal.js",
+ ] + glob(
+ include = [
+ "emscripten/third_party/**",
+ "emscripten/tools/**",
+ ],
+ exclude = [
+ "**/__pycache__/**",
+ ],
+ ),
+)
+
+filegroup(
+ name = "compiler_files",
+ srcs = [
+ "bin/clang{bin_extension}",
+ "bin/clang++{bin_extension}",
+ ":emcc_common",
+ ":includes",
+ ],
+)
+
+filegroup(
+ name = "linker_files",
+ srcs = [
+ "bin/clang{bin_extension}",
+ "bin/llvm-ar{bin_extension}",
+ "bin/llvm-dwarfdump{bin_extension}",
+ "bin/llvm-nm{bin_extension}",
+ "bin/llvm-objcopy{bin_extension}",
+ "bin/wasm-ctor-eval{bin_extension}",
+ "bin/wasm-emscripten-finalize{bin_extension}",
+ "bin/wasm-ld{bin_extension}",
+ "bin/wasm-metadce{bin_extension}",
+ "bin/wasm-opt{bin_extension}",
+ "bin/wasm-split{bin_extension}",
+ "bin/wasm2js{bin_extension}",
+ ":emcc_common",
+ ] + glob(
+ include = [
+ "emscripten/cache/sysroot/lib/**",
+ "emscripten/node_modules/**",
+ "emscripten/src/**",
+ ],
+ ),
+)
+
+filegroup(
+ name = "ar_files",
+ srcs = [
+ "bin/llvm-ar{bin_extension}",
+ "emscripten/emar.py",
+ "emscripten/emscripten-version.txt",
+ "emscripten/src/settings.js",
+ "emscripten/src/settings_internal.js",
+ ] + glob(
+ include = [
+ "emscripten/tools/**",
+ ],
+ exclude = [
+ "**/__pycache__/**",
+ ],
+ ),
+)
+"""
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_cache.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_cache.bzl
new file mode 100644
index 0000000000..945c19c011
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_cache.bzl
@@ -0,0 +1,113 @@
+BUILD_FILE_CONTENT_TEMPLATE = """
+package(default_visibility = ['//visibility:public'])
+exports_files(['emscripten_config'])
+"""
+
+EMBUILDER_CONFIG_TEMPLATE = """
+CACHE = '{cache}'
+BINARYEN_ROOT = '{binaryen_root}'
+LLVM_ROOT = '{llvm_root}'
+"""
+
+def get_root_and_script_ext(repository_ctx):
+ if repository_ctx.os.name.startswith("linux"):
+ if "amd64" in repository_ctx.os.arch or "x86_64" in repository_ctx.os.arch:
+ return (repository_ctx.path(Label("@emscripten_bin_linux//:BUILD.bazel")).dirname, "")
+ elif "aarch64" in repository_ctx.os.arch:
+ return (repository_ctx.path(Label("@emscripten_bin_linux_arm64//:BUILD.bazel")).dirname, "")
+ else:
+ fail("Unsupported architecture for Linux")
+ elif repository_ctx.os.name.startswith("mac"):
+ if "amd64" in repository_ctx.os.arch or "x86_64" in repository_ctx.os.arch:
+ return (repository_ctx.path(Label("@emscripten_bin_mac//:BUILD.bazel")).dirname, "")
+ elif "aarch64" in repository_ctx.os.arch:
+ return (repository_ctx.path(Label("@emscripten_bin_mac_arm64//:BUILD.bazel")).dirname, "")
+ else:
+ fail("Unsupported architecture for MacOS")
+ elif repository_ctx.os.name.startswith("windows"):
+ return (repository_ctx.path(Label("@emscripten_bin_win//:BUILD.bazel")).dirname, ".bat")
+ else:
+ fail("Unsupported operating system")
+
+def _emscripten_cache_repository_impl(repository_ctx):
+ # Read the default emscripten configuration file
+ default_config = repository_ctx.read(
+ repository_ctx.path(
+ Label("@emsdk//emscripten_toolchain:default_config"),
+ ),
+ )
+
+ if repository_ctx.attr.targets or repository_ctx.attr.configuration:
+ root, script_ext = get_root_and_script_ext(repository_ctx)
+ llvm_root = root.get_child("bin")
+ cache = repository_ctx.path("cache")
+
+ # Create configuration file
+ embuilder_config_content = EMBUILDER_CONFIG_TEMPLATE.format(
+ cache = cache,
+ binaryen_root = root,
+ llvm_root = llvm_root,
+ )
+ repository_ctx.file("embuilder_config", embuilder_config_content)
+ embuilder_config_path = repository_ctx.path("embuilder_config")
+ embuilder_path = "{}{}".format(root.get_child("emscripten").get_child("embuilder"), script_ext)
+
+ # Prepare the command line
+ if repository_ctx.attr.targets:
+ targets = repository_ctx.attr.targets
+ else:
+ # If no targets are requested, build everything
+ targets = ["ALL"]
+ flags = ["--em-config", embuilder_config_path] + repository_ctx.attr.configuration
+ embuilder_args = [embuilder_path] + flags + ["build"] + targets
+
+ # Run embuilder
+ repository_ctx.report_progress("Building secondary cache")
+ result = repository_ctx.execute(
+ embuilder_args,
+ quiet = True,
+ environment = {
+ "EM_IGNORE_SANITY": "1",
+ "EM_NODE_JS": "empty",
+ },
+ )
+ if result.return_code != 0:
+ fail("Embuilder exited with a non-zero return code")
+
+ # Override Emscripten's cache with the secondary cache
+ default_config += "CACHE = '{}'\n".format(cache)
+
+ # Create the configuration file for the toolchain and export
+ repository_ctx.file("emscripten_config", default_config)
+ repository_ctx.file("BUILD.bazel", BUILD_FILE_CONTENT_TEMPLATE)
+
+_emscripten_cache_repository = repository_rule(
+ implementation = _emscripten_cache_repository_impl,
+ attrs = {
+ "configuration": attr.string_list(),
+ "targets": attr.string_list(),
+ },
+)
+
+def _emscripten_cache_impl(ctx):
+ all_configuration = []
+ all_targets = []
+ for mod in ctx.modules:
+ for configuration in mod.tags.configuration:
+ all_configuration += configuration.flags
+ for targets in mod.tags.targets:
+ all_targets += targets.targets
+
+ _emscripten_cache_repository(
+ name = "emscripten_cache",
+ configuration = all_configuration,
+ targets = all_targets,
+ )
+
+emscripten_cache = module_extension(
+ tag_classes = {
+ "configuration": tag_class(attrs = {"flags": attr.string_list()}),
+ "targets": tag_class(attrs = {"targets": attr.string_list()}),
+ },
+ implementation = _emscripten_cache_impl,
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_deps.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_deps.bzl
new file mode 100644
index 0000000000..79dca5279f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_deps.bzl
@@ -0,0 +1,99 @@
+load(":remote_emscripten_repository.bzl", "remote_emscripten_repository")
+load(":revisions.bzl", "EMSCRIPTEN_TAGS")
+
+def _parse_version(v):
+ return [int(u) for u in v.split(".")]
+
+def _empty_repository_impl(ctx):
+ ctx.file("MODULE.bazel", """module(name = "{}")""".format(ctx.name))
+ ctx.file("BUILD.bazel", "")
+
+_empty_repository = repository_rule(
+ implementation = _empty_repository_impl,
+)
+
+def emscripten_repo_name(name):
+ return "emscripten_bin_{}".format(name)
+
+def _emscripten_deps_impl(ctx):
+ version = None
+
+ for mod in ctx.modules:
+ for config in mod.tags.config:
+ if config.version and version != None:
+ fail("More than one emscripten version specified!")
+ version = config.version
+ if version == None:
+ version = "latest"
+
+ if version == "latest":
+ version = reversed(sorted(EMSCRIPTEN_TAGS.keys(), key = _parse_version))[0]
+
+ revision = EMSCRIPTEN_TAGS[version]
+
+ emscripten_url = "https://storage.googleapis.com/webassembly/emscripten-releases-builds/{}/{}/wasm-binaries{}.{}"
+
+ remote_emscripten_repository(
+ name = emscripten_repo_name("linux"),
+ bin_extension = "",
+ sha256 = revision.sha_linux,
+ strip_prefix = "install",
+ type = "tar.xz",
+ url = emscripten_url.format("linux", revision.hash, "", "tar.xz"),
+ )
+
+ # Not all versions have a linux/arm64 release: https://github.com/emscripten-core/emsdk/issues/547
+ if hasattr(revision, "sha_linux_arm64"):
+ remote_emscripten_repository(
+ name = emscripten_repo_name("linux_arm64"),
+ bin_extension = "",
+ sha256 = revision.sha_linux_arm64,
+ strip_prefix = "install",
+ type = "tar.xz",
+ url = emscripten_url.format("linux", revision.hash, "-arm64", "tar.xz"),
+ )
+ else:
+ _empty_repository(
+ name = emscripten_repo_name("linux_arm64"),
+ )
+
+ remote_emscripten_repository(
+ name = emscripten_repo_name("mac"),
+ bin_extension = "",
+ sha256 = revision.sha_mac,
+ strip_prefix = "install",
+ type = "tar.xz",
+ url = emscripten_url.format("mac", revision.hash, "", "tar.xz"),
+ )
+
+ remote_emscripten_repository(
+ name = emscripten_repo_name("mac_arm64"),
+ bin_extension = "",
+ sha256 = revision.sha_mac_arm64,
+ strip_prefix = "install",
+ type = "tar.xz",
+ url = emscripten_url.format("mac", revision.hash, "-arm64", "tar.xz"),
+ )
+
+ remote_emscripten_repository(
+ name = emscripten_repo_name("win"),
+ bin_extension = ".exe",
+ sha256 = revision.sha_win,
+ strip_prefix = "install",
+ type = "zip",
+ url = emscripten_url.format("win", revision.hash, "", "zip"),
+ )
+
+emscripten_deps = module_extension(
+ tag_classes = {
+ "config": tag_class(
+ attrs = {
+ "version": attr.string(
+ doc = "Version to use. 'latest' to use latest.",
+ values = ["latest"] + EMSCRIPTEN_TAGS.keys(),
+ ),
+ },
+ ),
+ },
+ implementation = _emscripten_deps_impl,
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/BUILD.bazel b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/BUILD.bazel
new file mode 100644
index 0000000000..ebbc2e996f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/BUILD.bazel
@@ -0,0 +1,43 @@
+load("//:emscripten_deps.bzl", "emscripten_repo_name")
+load("//:remote_emscripten_repository.bzl", "create_toolchains", "emscripten_toolchain_name")
+load("@rules_python//python:py_binary.bzl", "py_binary")
+
+package(default_visibility = ["//visibility:public"])
+
+# dlmalloc.bc is implicitly added by the emscripten toolchain
+cc_library(name = "malloc")
+
+create_toolchains(
+ name = emscripten_toolchain_name("linux"),
+ repo_name = emscripten_repo_name("linux"),
+ exec_compatible_with = [ "@platforms//os:linux", "@platforms//cpu:x86_64"],
+)
+
+create_toolchains(
+ name = emscripten_toolchain_name("linux_arm64"),
+ repo_name = emscripten_repo_name("linux_arm64"),
+ exec_compatible_with = ["@platforms//os:linux", "@platforms//cpu:arm64"],
+)
+
+create_toolchains(
+ name = emscripten_toolchain_name("mac"),
+ repo_name = emscripten_repo_name("mac"),
+ exec_compatible_with = ["@platforms//os:macos", "@platforms//cpu:x86_64"],
+)
+
+create_toolchains(
+ name = emscripten_toolchain_name("mac_arm64"),
+ repo_name = emscripten_repo_name("mac_arm64"),
+ exec_compatible_with = ["@platforms//os:macos", "@platforms//cpu:arm64"],
+)
+
+create_toolchains(
+ name = emscripten_toolchain_name("win"),
+ repo_name = emscripten_repo_name("win"),
+ exec_compatible_with = ["@platforms//os:windows", "@platforms//cpu:x86_64"],
+)
+
+py_binary(
+ name = "wasm_binary",
+ srcs = ["wasm_binary.py"],
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/default_config b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/default_config
new file mode 100644
index 0000000000..8107fe4a2f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/default_config
@@ -0,0 +1,16 @@
+import os
+import platform
+
+ROOT_DIR = os.environ["ROOT_DIR"]
+EMSCRIPTEN_ROOT = os.environ["EMSCRIPTEN"]
+BINARYEN_ROOT = os.path.join(ROOT_DIR, os.environ["EM_BIN_PATH"])
+LLVM_ROOT = os.path.join(BINARYEN_ROOT, "bin")
+NODE_JS = os.path.join(ROOT_DIR, os.environ["NODE_JS_PATH"])
+FROZEN_CACHE = True
+
+# This works around an issue with Bazel RBE where the symlinks in node_modules/.bin
+# are uploaded as the linked files, which means the cli.js cannot load its
+# dependencies from the expected locations.
+# See https://github.com/emscripten-core/emscripten/pull/16640 for more
+CLOSURE_COMPILER = [NODE_JS, os.path.join(EMSCRIPTEN_ROOT, "node_modules",
+ "google-closure-compiler", "cli.js")]
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emar.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emar.bat
new file mode 100644
index 0000000000..c8068089f2
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emar.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+call %~dp0\env.bat
+
+py -3 %EMSCRIPTEN%\emar.py %*
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emar.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emar.sh
new file mode 100755
index 0000000000..b4ead6ef9b
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emar.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+source $(dirname $0)/env.sh
+
+exec python3 $EMSCRIPTEN/emar.py "$@"
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc.bat
new file mode 100644
index 0000000000..4088bc4ae3
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+call %~dp0\env.bat
+
+py -3 %EMSCRIPTEN%\emcc.py %*
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc.sh
new file mode 100755
index 0000000000..5fdaf9c295
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+source $(dirname $0)/env.sh
+
+exec python3 $EMSCRIPTEN/emcc.py "$@"
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc_link.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc_link.bat
new file mode 100644
index 0000000000..f49cb0d582
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc_link.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+call %~dp0\env.bat
+
+py -3 %~dp0\link_wrapper.py %*
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc_link.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc_link.sh
new file mode 100755
index 0000000000..44f32353ba
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/emcc_link.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+source $(dirname $0)/env.sh
+
+exec python3 $(dirname $0)/link_wrapper.py "$@"
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/env.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/env.bat
new file mode 100644
index 0000000000..c791ff7710
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/env.bat
@@ -0,0 +1,6 @@
+@ECHO OFF
+
+set ROOT_DIR=%EXT_BUILD_ROOT%
+if "%ROOT_DIR%"=="" set ROOT_DIR=%CD%
+set EMSCRIPTEN=%ROOT_DIR%\%EM_BIN_PATH%\emscripten
+set EM_CONFIG=%ROOT_DIR%\%EM_CONFIG_PATH%
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/env.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/env.sh
new file mode 100755
index 0000000000..b2a6bd60b0
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/env.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+export ROOT_DIR=${EXT_BUILD_ROOT:-$(pwd -P)}
+export EMSCRIPTEN=$ROOT_DIR/$EM_BIN_PATH/emscripten
+export EM_CONFIG=$ROOT_DIR/$EM_CONFIG_PATH
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/link_wrapper.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/link_wrapper.py
new file mode 100755
index 0000000000..6a6fe2f872
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/link_wrapper.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+"""wrapper around emcc link step.
+
+This wrapper currently serves the following purposes.
+
+1. When building with --config=wasm the final output is multiple files, usually
+ at least one .js and one .wasm file. Since the cc_binary link step only
+ allows a single output, we must tar up the outputs into a single file.
+
+2. Add quotes around arguments that need them in the response file to work
+ around a bazel quirk.
+
+3. Ensure the external_debug_info section of the wasm points at the correct
+ bazel path.
+"""
+
+from __future__ import print_function
+
+import argparse
+import os
+import subprocess
+import sys
+
+# Only argument should be @path/to/parameter/file
+assert sys.argv[1][0] == '@', sys.argv
+param_filename = sys.argv[1][1:]
+param_file_args = [line.strip() for line in open(param_filename, 'r').readlines()]
+
+# Re-write response file if needed.
+if any(' ' in a for a in param_file_args):
+ new_param_filename = param_filename + '.modified'
+ with open(new_param_filename, 'w') as f:
+ for param in param_file_args:
+ if ' ' in param:
+ f.write('"%s"' % param)
+ else:
+ f.write(param)
+ f.write('\n')
+ sys.argv[1] = '@' + new_param_filename
+
+emcc_py = os.path.join(os.environ['EMSCRIPTEN'], 'emcc.py')
+rtn = subprocess.call([sys.executable, emcc_py] + sys.argv[1:])
+if rtn != 0:
+ sys.exit(1)
+
+# Parse the arguments that we gave to the linker to determine what the output
+# file is named and what the output format is.
+parser = argparse.ArgumentParser(add_help=False)
+parser.add_argument('-o')
+parser.add_argument('--oformat')
+options = parser.parse_known_args(param_file_args)[0]
+output_file = options.o
+oformat = options.oformat
+outdir = os.path.normpath(os.path.dirname(output_file))
+base_name = os.path.basename(output_file)
+
+# The output file name is the name of the build rule that was built.
+# Add an appropriate file extension based on --oformat.
+if oformat is not None:
+ base_name_split = os.path.splitext(base_name)
+
+ # If the output name has no extension, give it the appropriate extension.
+ if not base_name_split[1]:
+ os.replace(output_file, output_file + '.' + oformat)
+
+ # If the output name does have an extension and it matches the output format,
+ # change the base_name so it doesn't have an extension.
+ elif base_name_split[1] == '.' + oformat:
+ base_name = base_name_split[0]
+
+ # If the output name does have an extension and it does not match the output
+ # format, change the base_name so it doesn't have an extension and rename
+ # the output_file so it has the proper extension.
+ # Note that if you do something like name your build rule "foo.js" and pass
+ # "--oformat=html", emscripten will write to the same file for both the js and
+ # html output, overwriting the js output entirely with the html.
+ # Please don't do that.
+ else:
+ base_name = base_name_split[0]
+ os.replace(output_file, os.path.join(outdir, base_name + '.' + oformat))
+
+files = []
+extensions = [
+ '.js',
+ '.wasm',
+ '.wasm.map',
+ '.js.mem',
+ '.fetch.js',
+ '.worker.js',
+ '.data',
+ '.js.symbols',
+ '.wasm.debug.wasm',
+ '.html',
+ '.aw.js'
+]
+
+for ext in extensions:
+ filename = base_name + ext
+ if os.path.exists(os.path.join(outdir, filename)):
+ files.append(filename)
+
+wasm_base = os.path.join(outdir, base_name + '.wasm')
+if os.path.exists(wasm_base + '.debug.wasm') and os.path.exists(wasm_base):
+ # If we have a .wasm.debug.wasm file and a .wasm file, we need to rewrite the
+ # section in the .wasm file that refers to it. The path that's in there
+ # is the blaze output path; we want it to be just the filename.
+
+ llvm_objcopy = os.path.join(
+ os.environ['EM_BIN_PATH'], 'bin/llvm-objcopy')
+ # First, check to make sure the .wasm file has the header that needs to be
+ # rewritten.
+ rtn = subprocess.call([
+ llvm_objcopy,
+ '--dump-section=external_debug_info=/dev/null',
+ wasm_base], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if rtn == 0:
+ # If llvm-objcopy did not return an error, the external_debug_info section
+ # must exist, so we're good to continue.
+
+ # Next we need to convert length of the filename to LEB128.
+ # Start by converting the length of the filename to a bit string.
+ bit_string = '{0:b}'.format(len(base_name + '.wasm.debug.wasm'))
+
+ # Pad the bit string with 0s so that its length is a multiple of 7.
+ while len(bit_string) % 7 != 0:
+ bit_string = '0' + bit_string
+
+ # Break up our bit string into chunks of 7.
+ # We do this backwards because the final format is little-endian.
+ final_bytes = bytearray()
+ for i in reversed(range(0, len(bit_string), 7)):
+ binary_part = bit_string[i:i + 7]
+ if i != 0:
+ # Every chunk except the last one needs to be prepended with '1'.
+ # The length of each chunk is 7, so that one has an implicit '0'.
+ binary_part = '1' + binary_part
+ final_bytes.append(int(binary_part, 2))
+ # Finally, add the actual filename.
+ final_bytes.extend((base_name + '.wasm.debug.wasm').encode())
+
+ # Write our length + filename bytes to a temp file.
+ with open(base_name + '_debugsection.tmp', 'wb+') as f:
+ f.write(final_bytes)
+ f.close()
+
+ # First delete the old section.
+ subprocess.check_call([
+ llvm_objcopy,
+ wasm_base,
+ '--remove-section=external_debug_info'])
+ # Rewrite section with the new size and filename from the temp file.
+ subprocess.check_call([
+ llvm_objcopy,
+ wasm_base,
+ '--add-section=external_debug_info=' + base_name + '_debugsection.tmp'])
+
+# Make sure we have at least one output file.
+if not len(files):
+ print('emcc.py did not appear to output any known files!')
+ sys.exit(1)
+
+# cc_binary must output exactly one file; put all the output files in a tarball.
+cmd = ['tar', 'cf', base_name + '.tar'] + files
+subprocess.check_call(cmd, cwd=outdir)
+os.replace(os.path.join(outdir, base_name + '.tar'), output_file)
+
+sys.exit(0)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/toolchain.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/toolchain.bzl
new file mode 100644
index 0000000000..ae2939fff2
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/toolchain.bzl
@@ -0,0 +1,1147 @@
+"""This module encapsulates logic to create emscripten_cc_toolchain_config rule."""
+
+load(
+ "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
+ "action_config",
+ "env_entry",
+ "env_set",
+ "feature",
+ "feature_set",
+ "flag_group",
+ "tool",
+ "tool_path",
+ "variable_with_value",
+ "with_feature_set",
+ _flag_set = "flag_set",
+)
+load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
+
+def flag_set(flags = None, features = None, not_features = None, **kwargs):
+ """Extension to flag_set which allows for a "simple" form.
+
+ The simple form allows specifying flags as a simple list instead of a flag_group
+ if enable_if or expand_if semantics are not required.
+
+ Similarly, the simple form allows passing features/not_features if they are a simple
+ list of semantically "and" features.
+ (i.e. "asan" and "dbg", rather than "asan" or "dbg")
+
+ Args:
+ flags: list, set of flags
+ features: list, set of features required to be enabled.
+ not_features: list, set of features required to not be enabled.
+ **kwargs: The rest of the args for flag_set.
+
+ Returns:
+ flag_set
+ """
+ if flags:
+ if kwargs.get("flag_groups"):
+ fail("Cannot set flags and flag_groups")
+ else:
+ kwargs["flag_groups"] = [flag_group(flags = flags)]
+
+ if features or not_features:
+ if kwargs.get("with_features"):
+ fail("Cannot set features/not_feature and with_features")
+ kwargs["with_features"] = [with_feature_set(
+ features = features or [],
+ not_features = not_features or [],
+ )]
+ return _flag_set(**kwargs)
+
+CROSSTOOL_DEFAULT_WARNINGS = [
+ "-Wall",
+]
+
+def _impl(ctx):
+ target_cpu = ctx.attr.cpu
+ toolchain_identifier = "emscripten-" + target_cpu
+ target_system_name = target_cpu + "-unknown-emscripten"
+
+ host_system_name = "i686-unknown-linux-gnu"
+
+ target_libc = "musl/js"
+
+ abi_version = "emscripten_syscalls"
+
+ compiler = "emscripten"
+ abi_libc_version = "default"
+
+ cc_target_os = "emscripten"
+
+ emscripten_dir = ctx.attr.emscripten_binaries.label.workspace_root
+
+ nodejs_path = ctx.file.nodejs_bin.path
+
+ builtin_sysroot = emscripten_dir + "/emscripten/cache/sysroot"
+
+ emcc_script = "emcc.%s" % ctx.attr.script_extension
+ emcc_link_script = "emcc_link.%s" % ctx.attr.script_extension
+ emar_script = "emar.%s" % ctx.attr.script_extension
+
+ ################################################################
+ # Tools
+ ################################################################
+ clang_tool = tool(path = emcc_script)
+ clif_match_tool = tool(path = "dummy_clif_matcher")
+ link_tool = tool(path = emcc_link_script)
+ archive_tool = tool(path = emar_script)
+ strip_tool = tool(path = "NOT_USED_STRIP_TOOL")
+
+ #### Legacy tool paths (much of this is redundant with action_configs, but
+ #### these are still used for some things)
+ tool_paths = [
+ tool_path(name = "ar", path = emar_script),
+ tool_path(name = "cpp", path = "/bin/false"),
+ tool_path(name = "gcc", path = emcc_script),
+ tool_path(name = "gcov", path = "/bin/false"),
+ tool_path(name = "ld", path = emcc_link_script),
+ tool_path(name = "nm", path = "NOT_USED"),
+ tool_path(name = "objdump", path = "/bin/false"),
+ tool_path(name = "strip", path = "NOT_USED"),
+ ]
+
+ ################################################################
+ # Action Configs
+ ################################################################
+
+ cpp_compile_action = action_config(
+ action_name = ACTION_NAMES.cpp_compile,
+ tools = [clang_tool],
+ )
+
+ cpp_module_compile_action = action_config(
+ action_name = ACTION_NAMES.cpp_module_compile,
+ tools = [clang_tool],
+ )
+
+ cpp_module_codegen_action = action_config(
+ action_name = ACTION_NAMES.cpp_module_codegen,
+ tools = [clang_tool],
+ )
+
+ clif_match_action = action_config(
+ action_name = ACTION_NAMES.clif_match,
+ tools = [clif_match_tool],
+ )
+
+ cpp_link_dynamic_library_action = action_config(
+ action_name = ACTION_NAMES.cpp_link_dynamic_library,
+ tools = [link_tool],
+ )
+
+ strip_action = action_config(
+ action_name = ACTION_NAMES.strip,
+ tools = [strip_tool],
+ )
+
+ preprocess_assemble_action = action_config(
+ action_name = ACTION_NAMES.preprocess_assemble,
+ tools = [clang_tool],
+ )
+
+ cpp_header_parsing_action = action_config(
+ action_name = ACTION_NAMES.cpp_header_parsing,
+ tools = [clang_tool],
+ )
+
+ cpp_link_static_library_action = action_config(
+ action_name = ACTION_NAMES.cpp_link_static_library,
+ enabled = True,
+ flag_sets = [
+ flag_set(
+ flag_groups = [
+ flag_group(
+ flags = ["rcsD", "%{output_execpath}"],
+ expand_if_available = "output_execpath",
+ ),
+ ],
+ ),
+ flag_set(
+ flag_groups = [
+ flag_group(
+ iterate_over = "libraries_to_link",
+ flag_groups = [
+ flag_group(
+ flags = ["%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.object_files}"],
+ iterate_over = "libraries_to_link.object_files",
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file_group",
+ ),
+ ),
+ ],
+ expand_if_available = "libraries_to_link",
+ ),
+ ],
+ ),
+ flag_set(
+ flag_groups = [
+ flag_group(
+ flags = ["@%{linker_param_file}"],
+ expand_if_available = "linker_param_file",
+ ),
+ ],
+ ),
+ ],
+ tools = [archive_tool],
+ )
+
+ c_compile_action = action_config(
+ action_name = ACTION_NAMES.c_compile,
+ tools = [clang_tool],
+ )
+
+ linkstamp_compile_action = action_config(
+ action_name = ACTION_NAMES.linkstamp_compile,
+ tools = [clang_tool],
+ )
+
+ assemble_action = action_config(
+ action_name = ACTION_NAMES.assemble,
+ tools = [clang_tool],
+ )
+
+ cpp_link_executable_action = action_config(
+ action_name = ACTION_NAMES.cpp_link_executable,
+ tools = [link_tool],
+ )
+
+ cpp_link_nodeps_dynamic_library_action = action_config(
+ action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+ tools = [link_tool],
+ )
+
+ action_configs = [
+ strip_action,
+ c_compile_action,
+ cpp_compile_action,
+ linkstamp_compile_action,
+ assemble_action,
+ preprocess_assemble_action,
+ cpp_header_parsing_action,
+ cpp_module_compile_action,
+ cpp_module_codegen_action,
+ cpp_link_executable_action,
+ cpp_link_dynamic_library_action,
+ cpp_link_nodeps_dynamic_library_action,
+ cpp_link_static_library_action,
+ clif_match_action,
+ ]
+
+ all_compile_actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ACTION_NAMES.lto_backend,
+ ]
+
+ all_cpp_compile_actions = [
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ]
+
+ preprocessor_compile_actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.clif_match,
+ ]
+
+ all_link_actions = [
+ ACTION_NAMES.cpp_link_executable,
+ ACTION_NAMES.cpp_link_dynamic_library,
+ ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+ ]
+
+ ################################################################
+ # Features
+ ################################################################
+
+ features = [
+ # This set of magic "feature"s are important configuration information for blaze.
+ feature(name = "no_legacy_features", enabled = True),
+ feature(
+ name = "has_configured_linker_path",
+ enabled = True,
+ ),
+
+ # Blaze requests this feature by default, but we don't care.
+ feature(name = "dependency_file"),
+
+ # Blaze requests this feature by default, but we don't care.
+ feature(name = "random_seed"),
+
+ # Formerly "needsPic" attribute
+ feature(name = "supports_pic", enabled = False),
+
+ # Blaze requests this feature by default.
+ # Blaze also tests if this feature is supported, before setting the "pic" build-variable.
+ feature(name = "pic"),
+
+ # Blaze requests this feature by default.
+ # Blaze also tests if this feature is supported before setting preprocessor_defines
+ # (...but why?)
+ feature(name = "preprocessor_defines"),
+
+ # Blaze requests this feature by default.
+ # Blaze also tests if this feature is supported before setting includes. (...but why?)
+ feature(name = "include_paths"),
+
+ # Blaze tests if this feature is enabled in order to create implicit
+ # "nodeps" .so outputs from cc_library rules.
+ feature(name = "supports_dynamic_linker", enabled = False),
+
+ # Blaze requests this feature when linking a cc_binary which is
+ # "dynamic" aka linked against nodeps-dynamic-library cc_library
+ # outputs.
+ feature(name = "dynamic_linking_mode"),
+
+ #### Configuration features
+ feature(
+ name = "crosstool_cpu",
+ enabled = True,
+ implies = ["crosstool_cpu_" + target_cpu],
+ ),
+ feature(
+ name = "crosstool_cpu_asmjs",
+ provides = ["variant:crosstool_cpu"],
+ ),
+ feature(
+ name = "crosstool_cpu_wasm",
+ provides = ["variant:crosstool_cpu"],
+ ),
+
+ # These 3 features will be automatically enabled by blaze in the
+ # corresponding build mode.
+ feature(
+ name = "opt",
+ provides = ["variant:crosstool_build_mode"],
+ ),
+ feature(
+ name = "dbg",
+ provides = ["variant:crosstool_build_mode"],
+ ),
+ feature(
+ name = "fastbuild",
+ provides = ["variant:crosstool_build_mode"],
+ ),
+
+ # Feature to prevent 'command line too long' issues
+ feature(
+ name = "archive_param_file",
+ enabled = True,
+ ),
+ feature(
+ name = "compiler_param_file",
+ enabled = True,
+ ),
+
+ #### User-settable features
+
+ # Set if enabling exceptions.
+ feature(name = "exceptions"),
+
+ # This feature overrides the default optimization to prefer execution speed
+ # over binary size (like clang -O3).
+ feature(
+ name = "optimized_for_speed",
+ provides = ["variant:crosstool_optimization_mode"],
+ ),
+
+ # This feature overrides the default optimization to prefer binary size over
+ # execution speed (like clang -Oz).
+ feature(
+ name = "optimized_for_size",
+ provides = ["variant:crosstool_optimization_mode"],
+ ),
+
+ # Convenience aliases / alt-spellings.
+ feature(
+ name = "optimize_for_speed",
+ implies = ["optimized_for_speed"],
+ ),
+ feature(
+ name = "optimize_for_size",
+ implies = ["optimized_for_size"],
+ ),
+
+ # This feature allows easier use of profiling tools by preserving mangled
+ # C++ names. This does everything profiling_funcs does and more.
+ feature(name = "profiling"),
+
+ # This feature emits only enough debug info for function names to appear
+ # in profiles.
+ feature(name = "profiling_funcs"),
+
+ # This feature allows source maps to be generated.
+ feature(
+ name = "source_maps",
+ implies = ["full_debug_info"],
+ ),
+ feature(
+ name = "dwarf_debug_info",
+ implies = ["profiling"],
+ ),
+
+ # Turns on full debug info (-g4).
+ feature(name = "full_debug_info"),
+
+ # Enables the use of "Emscripten" Pthread implementation.
+ # https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
+ # https://github.com/kripken/emscripten/wiki/Pthreads-with-WebAssembly
+ feature(name = "use_pthreads"),
+
+ # If enabled, the runtime will exit when main() completes.
+ feature(name = "exit_runtime"),
+
+ # Primarily for toolchain maintainers:
+ feature(name = "emcc_debug"),
+ feature(name = "emcc_debug_link"),
+ feature(
+ name = "llvm_backend",
+ requires = [feature_set(features = ["crosstool_cpu_wasm"])],
+ enabled = True,
+ ),
+
+ # Remove once flag is flipped.
+ # See https://github.com/bazelbuild/bazel/issues/7687
+ feature(
+ name = "do_not_split_linking_cmdline",
+ ),
+
+ # Adds simd support, only available with the llvm backend.
+ feature(
+ name = "wasm_simd",
+ requires = [feature_set(features = ["llvm_backend"])],
+ ),
+ # Adds relaxed-simd support, only available with the llvm backend.
+ feature(
+ name = "wasm_relaxed_simd",
+ requires = [feature_set(features = ["llvm_backend"])],
+ ),
+ feature(
+ name = "precise_long_double_printf",
+ enabled = True,
+ ),
+ feature(
+ name = "wasm_warnings_as_errors",
+ enabled = False,
+ ),
+
+ # ASan and UBSan. See also:
+ # https://emscripten.org/docs/debugging/Sanitizers.html
+ feature(name = "wasm_asan"),
+ feature(name = "wasm_ubsan"),
+ feature(
+ name = "output_format_js",
+ enabled = True,
+ ),
+ feature(
+ name = "wasm_standalone",
+ ),
+ ]
+
+ crosstool_default_flag_sets = [
+ # Compile, Link, and CC_FLAGS make variable
+ flag_set(
+ actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ACTION_NAMES.cpp_link_executable,
+ ACTION_NAMES.cpp_link_dynamic_library,
+ ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+ ],
+ flag_groups = [
+ flag_group(
+ flags = ["--sysroot=%{sysroot}"],
+ expand_if_available = "sysroot",
+ ),
+ ],
+ ),
+ # Compile + Link
+ flag_set(
+ actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ACTION_NAMES.cpp_link_executable,
+ ACTION_NAMES.cpp_link_dynamic_library,
+ ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+ ],
+ # This forces color diagnostics even on Forge (where we don't have an
+ # attached terminal).
+ flags = [
+ "-fdiagnostics-color",
+ ],
+ ),
+ # C++ compiles (and implicitly link)
+ flag_set(
+ actions = all_cpp_compile_actions,
+ flags = [
+ "-fno-exceptions",
+ ],
+ not_features = ["exceptions"],
+ ),
+ flag_set(
+ actions = all_cpp_compile_actions,
+ flags = [
+ "-fexceptions",
+ ],
+ features = ["exceptions"],
+ ),
+ # All compiles (and implicitly link)
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = [
+ "-fno-strict-aliasing",
+ "-funsigned-char",
+ "-no-canonical-prefixes",
+ ],
+ ),
+ # Language Features
+ flag_set(
+ actions = all_cpp_compile_actions,
+ flags = ["-std=gnu++17", "-nostdinc", "-nostdinc++"],
+ ),
+
+ # Emscripten-specific settings:
+ flag_set(
+ actions = all_compile_actions + all_link_actions,
+ flags = ["-s", "WASM=0"],
+ features = ["crosstool_cpu_asmjs"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-s", "USE_PTHREADS=1"],
+ features = ["use_pthreads"],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flags = ["-s", "EXIT_RUNTIME=1"],
+ features = ["exit_runtime"],
+ ),
+ flag_set(
+ actions = all_compile_actions + all_link_actions,
+ flags = ["-pthread"],
+ features = ["llvm_backend", "use_pthreads"],
+ ),
+ flag_set(
+ actions = all_compile_actions + all_link_actions,
+ flags = ["-msimd128"],
+ features = ["wasm_simd"],
+ ),
+ flag_set(
+ actions = all_compile_actions + all_link_actions,
+ flags = ["-msimd128", "-mrelaxed-simd"],
+ features = ["wasm_relaxed_simd"],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flags = ["-s", "PRINTF_LONG_DOUBLE=1"],
+ features = ["precise_long_double_printf"],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flags = ["--oformat=js"],
+ features = ["output_format_js"],
+ ),
+
+ # Opt
+ flag_set(
+ actions = preprocessor_compile_actions,
+ flags = ["-DNDEBUG"],
+ features = ["opt"],
+ ),
+ flag_set(
+ actions = all_compile_actions,
+ flags = ["-fomit-frame-pointer"],
+ features = ["opt"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-O2"],
+ features = ["opt"],
+ ),
+
+ # Users can override opt-level with semantic names...
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-Oz"],
+ features = ["optimized_for_size", "opt"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-O3"],
+ features = ["optimized_for_speed", "opt"],
+ ),
+
+ # Fastbuild
+ flag_set(
+ actions = all_compile_actions,
+ flags = ["-fomit-frame-pointer"],
+ features = ["fastbuild"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-O0"],
+ features = ["fastbuild"],
+ ),
+
+ # Dbg
+ flag_set(
+ actions = all_compile_actions,
+ flags = ["-fno-omit-frame-pointer"],
+ features = ["dbg"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-g", "-O0"],
+ features = ["dbg"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = [
+ "-g",
+ "-fsanitize=address",
+ "-O1",
+ "-DADDRESS_SANITIZER=1",
+ "-fno-omit-frame-pointer",
+ ],
+ features = ["wasm_asan"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = [
+ "-g4",
+ "-fsanitize=undefined",
+ "-O1",
+ "-DUNDEFINED_BEHAVIOR_SANITIZER=1",
+ "-fno-omit-frame-pointer",
+ "-fno-sanitize=vptr",
+ ],
+ features = ["wasm_ubsan"],
+ ),
+
+ # Profiling provides full debug info and a special --profiling flag
+ # to control name mangling
+ flag_set(
+ actions = all_link_actions,
+ flags = ["--profiling"],
+ features = ["profiling"],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flags = ["--profiling_funcs"],
+ features = ["profiling_funcs"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-g4"],
+ features = ["full_debug_info"],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flags = ["-gseparate-dwarf"],
+ features = ["dwarf_debug_info"],
+ ),
+ flag_set(
+ actions = all_compile_actions +
+ all_link_actions,
+ flags = ["-fdebug-compilation-dir=."],
+ features = ["dwarf_debug_info"],
+ ),
+ # Generic warning flag list
+ flag_set(
+ actions = all_compile_actions,
+ flags = CROSSTOOL_DEFAULT_WARNINGS,
+ ),
+
+ # Defines and Includes and Paths and such
+ flag_set(
+ actions = all_compile_actions,
+ flag_groups = [
+ flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
+ ],
+ ),
+ flag_set(
+ actions = preprocessor_compile_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["-D%{preprocessor_defines}"],
+ iterate_over = "preprocessor_defines",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = preprocessor_compile_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["-include", "%{includes}"],
+ iterate_over = "includes",
+ expand_if_available = "includes",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = preprocessor_compile_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["-iquote", "%{quote_include_paths}"],
+ iterate_over = "quote_include_paths",
+ ),
+ flag_group(
+ flags = ["-I%{include_paths}"],
+ iterate_over = "include_paths",
+ ),
+ flag_group(
+ flags = ["-isystem", "%{system_include_paths}"],
+ iterate_over = "system_include_paths",
+ ),
+ ],
+ ),
+
+ ## Linking options (not libs -- those go last)
+
+ # Generic link options
+ flag_set(
+ actions = [
+ ACTION_NAMES.cpp_link_dynamic_library,
+ ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+ ],
+ flags = ["-shared"],
+ ),
+
+ # Linker search paths and objects:
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = [
+ flag_group(
+ iterate_over = "runtime_library_search_directories",
+ flag_groups = [
+ flag_group(
+ flags = [
+ "-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}",
+ ],
+ expand_if_true = "is_cc_test",
+ ),
+ flag_group(
+ flags = [
+ "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
+ ],
+ expand_if_false = "is_cc_test",
+ ),
+ ],
+ expand_if_available = "runtime_library_search_directories",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["-L%{library_search_directories}"],
+ iterate_over = "library_search_directories",
+ expand_if_available = "library_search_directories",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = [
+ flag_group(
+ # This is actually a list of object files from the linkstamp steps
+ flags = ["%{linkstamp_paths}"],
+ iterate_over = "linkstamp_paths",
+ expand_if_available = "linkstamp_paths",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["@%{thinlto_param_file}"],
+ expand_if_available = "libraries_to_link",
+ expand_if_true = "thinlto_param_file",
+ ),
+ flag_group(
+ iterate_over = "libraries_to_link",
+ flag_groups = [
+ flag_group(
+ flags = ["-Wl,--start-lib"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file_group",
+ ),
+ ),
+ flag_group(
+ flags = ["-Wl,-whole-archive"],
+ expand_if_true = "libraries_to_link.is_whole_archive",
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.object_files}"],
+ iterate_over = "libraries_to_link.object_files",
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file_group",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "interface_library",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "static_library",
+ ),
+ ),
+ flag_group(
+ flags = ["-l%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "dynamic_library",
+ ),
+ ),
+ flag_group(
+ flags = ["-l:%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "versioned_dynamic_library",
+ ),
+ ),
+ flag_group(
+ flags = ["-Wl,-no-whole-archive"],
+ expand_if_true = "libraries_to_link.is_whole_archive",
+ ),
+ flag_group(
+ flags = ["-Wl,--end-lib"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file_group",
+ ),
+ ),
+ ],
+ expand_if_available = "libraries_to_link",
+ ),
+ ],
+ ),
+
+ # Configure the header parsing and preprocessing.
+ flag_set(
+ actions = [ACTION_NAMES.cpp_header_parsing],
+ flags = ["-xc++-header", "-fsyntax-only"],
+ features = ["parse_headers"],
+ ),
+
+ # Note: user compile flags should be nearly last -- you probably
+ # don't want to put any more features after this!
+ flag_set(
+ actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ],
+ flag_groups = [
+ flag_group(
+ flags = ["%{user_compile_flags}"],
+ iterate_over = "user_compile_flags",
+ expand_if_available = "user_compile_flags",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["%{user_link_flags}"],
+ iterate_over = "user_link_flags",
+ expand_if_available = "user_link_flags",
+ ),
+ ],
+ ),
+ ## Options which need to go late -- after all the user options -- go here.
+ flag_set(
+ # One might hope that these options would only be needed for C++
+ # compiles. But, sadly, users compile ".c" files with custom
+ # copts=["-x", "c++"], and expect that to be able to find C++ stdlib
+ # headers. It might be worth pondering how blaze could support this sort
+ # of use-case better.
+ actions = preprocessor_compile_actions +
+ [ACTION_NAMES.cc_flags_make_variable],
+ flags = [
+ "-iwithsysroot" + "/include/c++/v1",
+ "-iwithsysroot" + "/include/compat",
+ "-iwithsysroot" + "/include",
+ "-isystem",
+ emscripten_dir + "/lib/clang/21/include",
+ ],
+ ),
+ # Inputs and outputs
+ flag_set(
+ actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ],
+ flag_groups = [
+ flag_group(
+ flags = ["-MD", "-MF", "%{dependency_file}"],
+ expand_if_available = "dependency_file",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ],
+ flag_groups = [
+ flag_group(
+ flags = ["-c", "%{source_file}"],
+ expand_if_available = "source_file",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = [
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.preprocess_assemble,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.clif_match,
+ ],
+ flag_groups = [
+ flag_group(
+ flags = ["-S"],
+ expand_if_available = "output_assembly_file",
+ ),
+ flag_group(
+ flags = ["-E"],
+ expand_if_available = "output_preprocess_file",
+ ),
+ flag_group(
+ flags = ["-o", "%{output_file}"],
+ expand_if_available = "output_file",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["-o", "%{output_execpath}"],
+ expand_if_available = "output_execpath",
+ ),
+ ],
+ ),
+ # And finally, the params file!
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = [
+ flag_group(
+ flags = ["@%{linker_param_file}"],
+ expand_if_available = "linker_param_file",
+ ),
+ ],
+ ),
+ flag_set(
+ actions = all_compile_actions,
+ flags = [
+ "-Wno-builtin-macro-redefined",
+ # Genrules may not escape quotes enough for these, so
+ # don't put them into $(CC_FLAGS):
+ '-D__DATE__="redacted"',
+ '-D__TIMESTAMP__="redacted"',
+ '-D__TIME__="redacted"',
+ ],
+ ),
+ flag_set(
+ actions = all_compile_actions,
+ flags = ["-Werror"],
+ features = ["wasm_warnings_as_errors"],
+ ),
+ flag_set(
+ actions = all_link_actions,
+ flags = ["-sSTANDALONE_WASM"],
+ features = ["wasm_standalone"],
+ ),
+ ]
+
+ crosstool_default_env_sets = [
+ # Globals
+ env_set(
+ actions = all_compile_actions +
+ all_link_actions +
+ [ACTION_NAMES.cpp_link_static_library],
+ env_entries = [
+ env_entry(
+ key = "EM_BIN_PATH",
+ value = emscripten_dir,
+ ),
+ env_entry(
+ key = "EM_CONFIG_PATH",
+ value = ctx.file.em_config.path,
+ ),
+ env_entry(
+ key = "NODE_JS_PATH",
+ value = nodejs_path,
+ ),
+ ],
+ ),
+ # Use llvm backend. Off by default, enabled via --features=llvm_backend
+ env_set(
+ actions = all_compile_actions +
+ all_link_actions +
+ [ACTION_NAMES.cpp_link_static_library],
+ env_entries = [env_entry(key = "EMCC_WASM_BACKEND", value = "1")],
+ with_features = [with_feature_set(features = ["llvm_backend"])],
+ ),
+ # Debug compile and link. Off by default, enabled via --features=emcc_debug
+ env_set(
+ actions = all_compile_actions,
+ env_entries = [env_entry(key = "EMCC_DEBUG", value = "1")],
+ with_features = [with_feature_set(features = ["emcc_debug"])],
+ ),
+
+ # Debug only link step. Off by default, enabled via --features=emcc_debug_link
+ env_set(
+ actions = all_link_actions,
+ env_entries = [env_entry(key = "EMCC_DEBUG", value = "1")],
+ with_features = [
+ with_feature_set(features = ["emcc_debug"]),
+ with_feature_set(features = ["emcc_debug_link"]),
+ ],
+ ),
+ ]
+
+ crosstool_default_flags_feature = feature(
+ name = "crosstool_default_flags",
+ enabled = True,
+ flag_sets = crosstool_default_flag_sets,
+ env_sets = crosstool_default_env_sets,
+ )
+
+ features.append(crosstool_default_flags_feature)
+
+ cxx_builtin_include_directories = [
+ emscripten_dir + "/emscripten/cache/sysroot/include/c++/v1",
+ emscripten_dir + "/emscripten/cache/sysroot/include/compat",
+ emscripten_dir + "/emscripten/cache/sysroot/include",
+ emscripten_dir + "/lib/clang/21/include",
+ ]
+
+ artifact_name_patterns = []
+
+ make_variables = []
+
+ return cc_common.create_cc_toolchain_config_info(
+ ctx = ctx,
+ features = features,
+ action_configs = action_configs,
+ artifact_name_patterns = artifact_name_patterns,
+ cxx_builtin_include_directories = cxx_builtin_include_directories,
+ toolchain_identifier = toolchain_identifier,
+ host_system_name = host_system_name,
+ target_system_name = target_system_name,
+ target_cpu = target_cpu,
+ target_libc = target_libc,
+ compiler = compiler,
+ abi_version = abi_version,
+ abi_libc_version = abi_libc_version,
+ tool_paths = tool_paths,
+ make_variables = make_variables,
+ builtin_sysroot = builtin_sysroot,
+ cc_target_os = cc_target_os,
+ )
+
+emscripten_cc_toolchain_config_rule = rule(
+ implementation = _impl,
+ attrs = {
+ "cpu": attr.string(mandatory = True, values = ["asmjs", "wasm"]),
+ "em_config": attr.label(mandatory = True, allow_single_file = True),
+ "emscripten_binaries": attr.label(mandatory = True, cfg = "exec"),
+ "nodejs_bin": attr.label(mandatory = True, allow_single_file = True),
+ "script_extension": attr.string(mandatory = True, values = ["sh", "bat"]),
+ },
+ provides = [CcToolchainConfigInfo],
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_binary.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_binary.py
new file mode 100644
index 0000000000..d7d6142376
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_binary.py
@@ -0,0 +1,56 @@
+"""Unpackages a bazel emscripten archive for use in a bazel BUILD rule.
+
+This script will take a tar archive containing the output of the emscripten
+toolchain. This file contains any output files produced by a wasm_cc_binary or a
+cc_binary built with --config=wasm. The files are extracted into the given
+output paths.
+
+The contents of the archive are expected to match the given outputs extnames.
+
+This script and its accompanying Bazel rule should allow you to extract a
+WebAssembly binary into a larger web application.
+"""
+
+import argparse
+import os
+import tarfile
+
+
+def ensure(f):
+ if not os.path.exists(f):
+ with open(f, 'w'):
+ pass
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--archive', help='The archive to extract from.')
+ parser.add_argument('--outputs', help='Comma separated list of files that should be extracted from the archive. Only the extname has to match a file in the archive.')
+ parser.add_argument('--allow_empty_outputs', help='If an output listed in --outputs does not exist, create it anyways.', action='store_true')
+ args = parser.parse_args()
+
+ args.archive = os.path.normpath(args.archive)
+ args.outputs = args.outputs.split(",")
+
+ tar = tarfile.open(args.archive)
+
+ for member in tar.getmembers():
+ extname = '.' + member.name.split('.', 1)[1]
+ for idx, output in enumerate(args.outputs):
+ if output.endswith(extname):
+ member_file = tar.extractfile(member)
+ with open(output, "wb") as output_file:
+ output_file.write(member_file.read())
+ args.outputs.pop(idx)
+ break
+
+ for output in args.outputs:
+ extname = '.' + output.split('.', 1)[1]
+ if args.allow_empty_outputs:
+ ensure(output)
+ else:
+ print("[ERROR] Archive does not contain file with extname: %s" % extname)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_cc_binary.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_cc_binary.bzl
new file mode 100644
index 0000000000..3cc6014858
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_cc_binary.bzl
@@ -0,0 +1,231 @@
+"""wasm_cc_binary rule for compiling C++ targets to WebAssembly.
+"""
+
+def _wasm_transition_impl(settings, attr):
+ _ignore = (settings, attr)
+
+ features = list(settings["//command_line_option:features"])
+ linkopts = list(settings["//command_line_option:linkopt"])
+
+ if attr.threads == "emscripten":
+ # threads enabled
+ features.append("use_pthreads")
+ elif attr.threads == "off":
+ # threads disabled
+ features.append("-use_pthreads")
+
+ if attr.exit_runtime == True:
+ features.append("exit_runtime")
+
+ if attr.backend == "llvm":
+ features.append("llvm_backend")
+ elif attr.backend == "emscripten":
+ features.append("-llvm_backend")
+
+ if attr.simd:
+ features.append("wasm_simd")
+
+ platform = "@emsdk//:platform_wasm"
+ if attr.standalone:
+ platform = "@emsdk//:platform_wasi"
+ features.append("wasm_standalone")
+
+ return {
+ "//command_line_option:compiler": "emscripten",
+ "//command_line_option:cpu": "wasm",
+ "//command_line_option:features": features,
+ "//command_line_option:dynamic_mode": "off",
+ "//command_line_option:linkopt": linkopts,
+ "//command_line_option:platforms": [platform],
+ # This is hardcoded to an empty cc_library because the malloc library
+ # is implicitly added by the emscripten toolchain
+ "//command_line_option:custom_malloc": "@emsdk//emscripten_toolchain:malloc",
+ }
+
+_wasm_transition = transition(
+ implementation = _wasm_transition_impl,
+ inputs = [
+ "//command_line_option:features",
+ "//command_line_option:linkopt",
+ ],
+ outputs = [
+ "//command_line_option:compiler",
+ "//command_line_option:cpu",
+ "//command_line_option:features",
+ "//command_line_option:dynamic_mode",
+ "//command_line_option:linkopt",
+ "//command_line_option:platforms",
+ "//command_line_option:custom_malloc",
+ ],
+)
+
+_ALLOW_OUTPUT_EXTNAMES = [
+ ".js",
+ ".wasm",
+ ".wasm.map",
+ ".worker.js",
+ ".js.mem",
+ ".data",
+ ".fetch.js",
+ ".js.symbols",
+ ".wasm.debug.wasm",
+ ".html",
+ ".aw.js",
+]
+
+_WASM_BINARY_COMMON_ATTRS = {
+ "backend": attr.string(
+ default = "_default",
+ values = ["_default", "emscripten", "llvm"],
+ ),
+ "cc_target": attr.label(
+ cfg = _wasm_transition,
+ mandatory = True,
+ ),
+ "exit_runtime": attr.bool(
+ default = False,
+ ),
+ "threads": attr.string(
+ default = "_default",
+ values = ["_default", "emscripten", "off"],
+ ),
+ "simd": attr.bool(
+ default = False,
+ ),
+ "standalone": attr.bool(
+ default = False,
+ ),
+ "_allowlist_function_transition": attr.label(
+ default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
+ ),
+ "_wasm_binary_extractor": attr.label(
+ executable = True,
+ allow_files = True,
+ cfg = "exec",
+ default = Label("@emsdk//emscripten_toolchain:wasm_binary"),
+ ),
+}
+
+def _wasm_cc_binary_impl(ctx):
+ args = ctx.actions.args()
+ cc_target = ctx.attr.cc_target[0]
+
+ for output in ctx.outputs.outputs:
+ valid_extname = False
+ for allowed_extname in _ALLOW_OUTPUT_EXTNAMES:
+ if output.path.endswith(allowed_extname):
+ valid_extname = True
+ break
+ if not valid_extname:
+ fail("Invalid output '{}'. Allowed extnames: {}".format(output.basename, ", ".join(_ALLOW_OUTPUT_EXTNAMES)))
+
+ args.add_all("--archive", ctx.files.cc_target)
+ args.add_joined("--outputs", ctx.outputs.outputs, join_with = ",")
+
+ ctx.actions.run(
+ inputs = ctx.files.cc_target,
+ outputs = ctx.outputs.outputs,
+ arguments = [args],
+ executable = ctx.executable._wasm_binary_extractor,
+ )
+
+ return [
+ DefaultInfo(
+ files = depset(ctx.outputs.outputs),
+ # This is needed since rules like web_test usually have a data
+ # dependency on this target.
+ data_runfiles = ctx.runfiles(transitive_files = depset(ctx.outputs.outputs)),
+ ),
+ OutputGroupInfo(_wasm_tar = cc_target.files),
+ ]
+
+def _wasm_cc_binary_legacy_impl(ctx):
+ cc_target = ctx.attr.cc_target[0]
+ outputs = [
+ ctx.outputs.loader,
+ ctx.outputs.wasm,
+ ctx.outputs.map,
+ ctx.outputs.mem,
+ ctx.outputs.fetch,
+ ctx.outputs.worker,
+ ctx.outputs.data,
+ ctx.outputs.symbols,
+ ctx.outputs.dwarf,
+ ctx.outputs.html,
+ ctx.outputs.audio_worklet,
+ ]
+
+ args = ctx.actions.args()
+ args.add("--allow_empty_outputs")
+ args.add_all("--archive", ctx.files.cc_target)
+ args.add_joined("--outputs", outputs, join_with = ",")
+
+ ctx.actions.run(
+ inputs = ctx.files.cc_target,
+ outputs = outputs,
+ arguments = [args],
+ executable = ctx.executable._wasm_binary_extractor,
+ )
+
+ return [
+ DefaultInfo(
+ executable = ctx.outputs.wasm,
+ files = depset(outputs),
+ # This is needed since rules like web_test usually have a data
+ # dependency on this target.
+ data_runfiles = ctx.runfiles(transitive_files = depset(outputs)),
+ ),
+ OutputGroupInfo(_wasm_tar = cc_target.files),
+ ]
+
+_wasm_cc_binary = rule(
+ implementation = _wasm_cc_binary_impl,
+ attrs = dict(
+ _WASM_BINARY_COMMON_ATTRS,
+ outputs = attr.output_list(
+ allow_empty = False,
+ mandatory = True,
+ ),
+ ),
+)
+
+def _wasm_binary_legacy_outputs(name, cc_target):
+ basename = cc_target.name
+ basename = basename.split(".")[0]
+ outputs = {
+ "loader": "{}/{}.js".format(name, basename),
+ "wasm": "{}/{}.wasm".format(name, basename),
+ "map": "{}/{}.wasm.map".format(name, basename),
+ "mem": "{}/{}.js.mem".format(name, basename),
+ "fetch": "{}/{}.fetch.js".format(name, basename),
+ "worker": "{}/{}.worker.js".format(name, basename),
+ "data": "{}/{}.data".format(name, basename),
+ "symbols": "{}/{}.js.symbols".format(name, basename),
+ "dwarf": "{}/{}.wasm.debug.wasm".format(name, basename),
+ "html": "{}/{}.html".format(name, basename),
+ "audio_worklet": "{}/{}.aw.js".format(name, basename)
+ }
+
+ return outputs
+
+_wasm_cc_binary_legacy = rule(
+ implementation = _wasm_cc_binary_legacy_impl,
+ attrs = _WASM_BINARY_COMMON_ATTRS,
+ outputs = _wasm_binary_legacy_outputs,
+)
+
+# Wraps a C++ Blaze target, extracting the appropriate files.
+#
+# This rule will transition to the emscripten toolchain in order
+# to build the the cc_target as a WebAssembly binary.
+#
+# Args:
+# name: The name of the rule.
+# cc_target: The cc_binary or cc_library to extract files from.
+def wasm_cc_binary(outputs = None, **kwargs):
+ # for backwards compatibility if no outputs are set the deprecated
+ # implementation is used.
+ if not outputs:
+ _wasm_cc_binary_legacy(**kwargs)
+ else:
+ _wasm_cc_binary(outputs = outputs, **kwargs)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_rules.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_rules.bzl
new file mode 100644
index 0000000000..f8dce22eec
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/emscripten_toolchain/wasm_rules.bzl
@@ -0,0 +1,6 @@
+"""Rules related to C++ and WebAssembly.
+"""
+
+load(":wasm_cc_binary.bzl", _wasm_cc_binary = "wasm_cc_binary")
+
+wasm_cc_binary = _wasm_cc_binary
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/BUILD b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/BUILD
new file mode 100644
index 0000000000..07fbed5510
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/BUILD
@@ -0,0 +1,23 @@
+load("@rules_cc//cc:defs.bzl", "cc_binary")
+load("//emscripten_toolchain:wasm_rules.bzl", "wasm_cc_binary")
+
+cc_binary(
+ name = "hello-world",
+ srcs = ["hello-world.cc"],
+)
+
+cc_binary(
+ name = "hello-world-simd",
+ srcs = ["hello-world-simd.cc"],
+)
+
+wasm_cc_binary(
+ name = "hello-world-wasm",
+ cc_target = ":hello-world",
+)
+
+wasm_cc_binary(
+ name = "hello-world-wasm-simd",
+ cc_target = ":hello-world-simd",
+ simd = True,
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/hello-world-simd.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/hello-world-simd.cc
new file mode 100644
index 0000000000..649adab20a
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/hello-world-simd.cc
@@ -0,0 +1,10 @@
+#include
+
+void multiply_arrays(int* out, int* in_a, int* in_b, int size) {
+ for (int i = 0; i < size; i += 4) {
+ v128_t a = wasm_v128_load(&in_a[i]);
+ v128_t b = wasm_v128_load(&in_b[i]);
+ v128_t prod = wasm_i32x4_mul(a, b);
+ wasm_v128_store(&out[i], prod);
+ }
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/hello-world.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/hello-world.cc
new file mode 100644
index 0000000000..ee72c53171
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/hello-world/hello-world.cc
@@ -0,0 +1,6 @@
+#include
+
+int main(int argc, char** argv) {
+ std::cout << "hello world!" << std::endl;
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/remote_emscripten_repository.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/remote_emscripten_repository.bzl
new file mode 100644
index 0000000000..819a048080
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/remote_emscripten_repository.bzl
@@ -0,0 +1,148 @@
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load(":emscripten_build_file.bzl", "EMSCRIPTEN_BUILD_FILE_CONTENT_TEMPLATE")
+load(":revisions.bzl", "EMSCRIPTEN_TAGS")
+load("//emscripten_toolchain:toolchain.bzl", "emscripten_cc_toolchain_config_rule")
+
+def remote_emscripten_repository(
+ name,
+ bin_extension,
+ **kwargs,
+):
+ """Imports an Emscripten from an http archive
+
+ Args:
+ name: A unique name for this Emscripten repository.
+ bin_extension: Extension for the binaries in this Emscripten repository
+ **kwargs: Args for http_archive. Refer to http_archive documentation for more info.
+ """
+ http_archive(
+ name = name,
+ build_file_content = EMSCRIPTEN_BUILD_FILE_CONTENT_TEMPLATE.format(bin_extension = bin_extension),
+ **kwargs
+ )
+
+def emscripten_toolchain_name(name):
+ return "emscripten_{}".format(name)
+
+def _get_name_and_target(name):
+ return name, ":" + name
+
+def create_toolchains(name, repo_name, exec_compatible_with):
+ """Creates toolchain definition for an Emscripten
+
+ Register the toolchains defined by this macro via
+ `register_toolchains("//:cc-toolchain-wasm-")`
+
+ Args:
+ name: A unique name for this Emscripten toolchain
+ repo_name: The name of the Emscripten repository for this toolchain
+ exec_compatible_with: Execute platform constraints for the Emscripten toolchain associated
+ with this repository.
+ **kwargs: Args for http_archive. Refer to http_archive documentation for more info.
+ """
+ common_files_name, common_files_target = _get_name_and_target("common_files_" + name)
+ compiler_files_name, compiler_files_target = _get_name_and_target("compiler_files_" + name)
+ linker_files_name, linker_files_target = _get_name_and_target("linker_files_" + name)
+ ar_files_name, ar_files_target = _get_name_and_target("ar_files_" + name)
+ all_files_name, all_files_target = _get_name_and_target("all_files_" + name)
+ cc_wasm_name, cc_wasm_target = _get_name_and_target("cc-compiler-wasm-" + name)
+
+ wasm_name = "wasm-" + name
+
+ # These are file groups defined by the build_file_content on the Emscripten http_archive
+ remote_repo = "@{}//".format(repo_name)
+ repo_compiler_files_target = remote_repo + ":compiler_files"
+ repo_linker_files_target = remote_repo + ":linker_files"
+ repo_ar_files_target = remote_repo + ":ar_files"
+
+ native.filegroup(
+ name = common_files_name,
+ srcs = [
+ "@emscripten_cache//:emscripten_config",
+ "@emsdk//emscripten_toolchain:env.sh",
+ "@emsdk//emscripten_toolchain:env.bat",
+ "@nodejs//:node_files",
+ ],
+ )
+
+ native.filegroup(
+ name = compiler_files_name,
+ srcs = [
+ "@emsdk//emscripten_toolchain:emcc.sh",
+ "@emsdk//emscripten_toolchain:emcc.bat",
+ repo_compiler_files_target,
+ common_files_target,
+ ],
+ )
+
+ native.filegroup(
+ name = linker_files_name,
+ srcs = [
+ "@emsdk//emscripten_toolchain:emcc_link.sh",
+ "@emsdk//emscripten_toolchain:emcc_link.bat",
+ "link_wrapper.py",
+ repo_linker_files_target,
+ common_files_target,
+ ],
+ )
+
+ native.filegroup(
+ name = ar_files_name,
+ srcs = [
+ "@emsdk//emscripten_toolchain:emar.sh",
+ "@emsdk//emscripten_toolchain:emar.bat",
+ repo_ar_files_target,
+ common_files_target,
+ ],
+ )
+
+ native.filegroup(
+ name = all_files_name,
+ srcs = [
+ ar_files_target,
+ compiler_files_target,
+ linker_files_target,
+ ],
+ )
+
+ emscripten_cc_toolchain_config_rule(
+ name = wasm_name,
+ cpu = "wasm",
+ em_config = "@emscripten_cache//:emscripten_config",
+ emscripten_binaries = repo_compiler_files_target,
+ nodejs_bin = "@nodejs//:node",
+ script_extension = select({
+ "@bazel_tools//src/conditions:host_windows": "bat",
+ "//conditions:default": "sh",
+ }),
+ )
+
+ native.cc_toolchain(
+ name = cc_wasm_name,
+ all_files = all_files_target,
+ ar_files = ar_files_target,
+ as_files = ":empty",
+ compiler_files = compiler_files_target,
+ dwp_files = ":empty",
+ linker_files = linker_files_target,
+ objcopy_files = ":empty",
+ strip_files = ":empty",
+ toolchain_config = wasm_name,
+ toolchain_identifier = "emscripten-wasm-" + name,
+ )
+
+ native.toolchain(
+ name = "cc-toolchain-wasm-" + name,
+ target_compatible_with = ["@platforms//cpu:wasm32"],
+ exec_compatible_with = exec_compatible_with,
+ toolchain = cc_wasm_target,
+ toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+ )
+
+ native.cc_toolchain_suite(
+ name = "everything-" + name,
+ toolchains = {
+ "wasm": cc_wasm_target,
+ "wasm|emscripten": cc_wasm_target,
+ },
+ )
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/revisions.bzl b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/revisions.bzl
new file mode 100644
index 0000000000..e954235578
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/revisions.bzl
@@ -0,0 +1,773 @@
+# This file is automatically updated by emsdk/scripts/update_bazel_workspace.py
+# DO NOT MODIFY
+
+EMSCRIPTEN_TAGS = {
+ "4.0.9": struct(
+ hash = "cb2a69bce627bd2247624c71fc12907cb8785d2f",
+ sha_linux = "c6fd245138e6bbdd8349963cb4045c557d657e4be0ea44155375633c689c8be9",
+ sha_linux_arm64 = "872d7f5870f1bfc523a446ca66ab1b47009a96be33c398dbbb12a56597e46ab5",
+ sha_mac = "7efb0a6ddcb915aeca9f8685db909ae7799452894876fc1223a78d5c3288ff2d",
+ sha_mac_arm64 = "b97f3cda61211dd83b31ef9ea92e83d416a9422192cf3ee484fffe11e5d6e5b9",
+ sha_win = "e6e409ae564c041691f2fecd690431a9935401f8ab6afe284b222546887e84c5",
+ ),
+ "4.0.8": struct(
+ hash = "56f86607aeb458086e72f23188789be2ee0e971a",
+ sha_linux = "7b50b2b40f80d4531ae29a0a5b902eca41552e04815f59880a122ac81e8f269d",
+ sha_linux_arm64 = "d6e3ab0cdec2e6983235322f600f248d313bfce4a6a69ef16cdfdc330ff748b8",
+ sha_mac = "e1b2e6d4797338ed884f9d8a8419f93fc42cfcdea5e8a8b29fe13c6fd3fe7f7a",
+ sha_mac_arm64 = "115b207304d5471b77fc7649904111f3bb5ed7998ad192cba6cfc5fd0b2d78cb",
+ sha_win = "9ca65cb49287f448216c2eac12dacff9808ae827d5de267aaf2bd65f6d4f233e",
+ ),
+ "4.0.7": struct(
+ hash = "ef4e9cedeac3332e4738087567552063f4f250d3",
+ sha_linux = "60079078b1ecc4e96ab01c4189aceeff9049a1bb2544123295e9841b91a9410d",
+ sha_linux_arm64 = "caa10ae2d2b01eb290957e96636f0a6861e7305c8d991c762379542208415793",
+ sha_mac = "d588cc31b7db0d876f1d45f4d0c656d5e205d049c0bb27209cad04cfebe19309",
+ sha_mac_arm64 = "c0153cc053d8961e094447c3e706cb8f379c263bee64202fd78251fe018fb014",
+ sha_win = "7974b6e11164c2c94ddb252c9728d21de321094421f5d0856702e65c06751e54",
+ ),
+ "4.0.6": struct(
+ hash = "14767574a5c37ff9526a253a65ddbe0811cb3667",
+ sha_linux = "27fc220a9ad98d323cad73531ff563e9838c9e1205f51ee2a5632bb4266a35d2",
+ sha_linux_arm64 = "2d03f8eb3f81dd94821658eefbb442a92b0b7601f4cfb08590590fd7bc467ef8",
+ sha_mac = "c06048915595726fc2e2da6a8db3134581a6287645fb818802a9734ff9785e77",
+ sha_mac_arm64 = "35d743453d0f91857b09f00d721037bb46753aaeae373bd7f64746338db11770",
+ sha_win = "3b576e825b26426bb72854ed98752df3fcb58cc3ab1dc116566e328b79a8abb3",
+ ),
+ "4.0.5": struct(
+ hash = "d7f8ff5e2ca3539c33fae81e98f7c56ef9fa1239",
+ sha_linux = "fdd4d9d6b37e845039b207baaef60cd98fb594ea13a3e6d622c2dcd8f2a48ac6",
+ sha_linux_arm64 = "0007aec32eee609b91f35c32481ec060ea7dac7151e36344bbcae419907f9240",
+ sha_mac = "f4e5a6c57ad9de59bff73463972213a299af2bb419dafbdd3959947fa801a342",
+ sha_mac_arm64 = "b8b93190fa17afe32a5eaa7120b807767b1c9d6e1d4ae6b9a2c6adb231758683",
+ sha_win = "3b8ed9e298a6d58fee841f5c3f1d3e7b2dff104cc7df314cd329f4c05d470be0",
+ ),
+ "4.0.4": struct(
+ hash = "ea71afcf5a172125179a07ff1731de6e81c92222",
+ sha_linux = "f05dab4a6a13a5fe6972e95e918d1483e687faf468e1a653deaa8d7956a97a3a",
+ sha_linux_arm64 = "95a421f304a7209c6f259754ad15aea5bbbbb1838139b51837aeb2c184fa4a89",
+ sha_mac = "d8b44aae37224ae76572ad84b60a2adaa126826332864fb689944d5130705d8d",
+ sha_mac_arm64 = "ade1c1a0c2e5893c6f74079beeae8b7e2a0c3f3b7ae88891064104fd985dfc2b",
+ sha_win = "342cf9dfb83e95bf678d07e460e093ea61a609d34b4603d9be06d4f31784409d",
+ ),
+ "4.0.3": struct(
+ hash = "de2109f0e5e7278d470da11de526aed16c527722",
+ sha_linux = "6480f51d0c24130424c696bf83e9774f42246a0109c8d48b59f4520fdfadb928",
+ sha_linux_arm64 = "76b1511d550b4f47276b93581ae5122063acbca7c960703637657388cf178636",
+ sha_mac = "f40851b816b31b3ca3214ebf61cc152625a05c24f43e2b13c2ad9b9e5dca73c0",
+ sha_mac_arm64 = "6d8ac5ad1f59f71de0927eb2c595dab2f21d9946ca293434359a6db2ab06a138",
+ sha_win = "3702e4a518057520d4ad9e7cd63a01a829770d090551e00f19f417f55b0170d3",
+ ),
+ "4.0.2": struct(
+ hash = "cc8eba40de8235f9c33d92463018f87b3edaa09e",
+ sha_linux = "3c0e3940240709388c24a4262680c18bb1d5979f2337abe53db00fb039606c44",
+ sha_linux_arm64 = "21ed0c31c1fc972e3509fcb140e0323061b5f2b173fe56d1f8961df2a37e4c11",
+ sha_mac = "e1bd96ec790968adf583d348158375b76ee0287e348954c3393c82565475b07b",
+ sha_mac_arm64 = "e5bf9a5efabc114b42636abcea07a1e02d3a9406cd399a29ccbc730586dce465",
+ sha_win = "78010f8e2f7bb6868bb20e3fc32e24d45e6fca749c388c2d25bea9845512338d",
+ ),
+ "4.0.1": struct(
+ hash = "5ff495a591978fdf8a16f2d172be3616f3150d1e",
+ sha_linux = "7b2b64b1bc15555696f78cbcb54c8d75832222d1578270ff5f56a8024c9a0dbc",
+ sha_linux_arm64 = "5c046a22b933de14be6b2522b75796afffe3940a19422eee483b7f3f1a226d66",
+ sha_mac = "d089eba9c3cad675bbd7d3318aec166ebe5ba984a6c5291136c09c68324d9818",
+ sha_mac_arm64 = "c8359b334bad71719e8d29e796ca7b63891e0305987b2572eb5a2f020e34f773",
+ sha_win = "9cf861339327f3657281c5c8c18aa723323acffe3b3d1c3807b9d4576d097e0e",
+ ),
+ "4.0.0": struct(
+ hash = "3ebc04a3dab24522a5bf8ced3ce3caea816558f6",
+ sha_linux = "6836988f0b7ee6ce3df5192dd4375b9eee55be78847ce31cf1d2abfb00f1e991",
+ sha_linux_arm64 = "d4e6e04b7e2fa1bdffc9c07ab4e0a3f66bde75adb06ebf9cc66a341907b17db4",
+ sha_mac = "4123e9ff6a699dac303c4fe22529ae0d618c118fcd8267df590363b0fc98c91d",
+ sha_mac_arm64 = "4b5fb7cc4f5f8526aaa41c8560a00ad6782b97cd3894d856beb635f05a825613",
+ sha_win = "6b1e5aee4b4a4274712566c845888bdf4eced09a5aaa64c1796cda57cd2854c4",
+ ),
+ "3.1.74": struct(
+ hash = "c2655005234810c7c42e02a18e4696554abe0352",
+ sha_linux = "a987bb4cded4f29437e8589accac204ce3c134feaaaf251bb97d0fdf450dce65",
+ sha_linux_arm64 = "c7fcc532eb7ee1dc7df0eacb49128ded12e4d55a973b8a2a5215da8bb6c4027c",
+ sha_mac = "04f848f40bd19220a43abde2dd1012d95bf1f89c618c0f631b83d18357e2bb65",
+ sha_mac_arm64 = "fc71758a5bfb02b8a5c2dd21d6bfc34aa3c64698f6105e204a1f4d11f6d67603",
+ sha_win = "603b0515e0367ee2718b2f360ef0194663d23a91236910d5f4a90ac4d745a4f2",
+ ),
+ "3.1.73": struct(
+ hash = "b363a836e75a245c548b7a6a021822d8c9e4c6df",
+ sha_linux = "4f3bc91cffec9096c3d3ccb11c222e1c2cb7734a0ff9a92d192e171849e68f28",
+ sha_linux_arm64 = "e6fb8a32889d4e4a3ac3e45d8012641369251ddd1255ada132ff6c70ab62b932",
+ sha_mac = "8d52ec080834f49996534de26772800dee048ec9bf148bb508be95887e267735",
+ sha_mac_arm64 = "58e6c984c5a1fb71e0871f0c3bb9e32d41e7553260c6eeb38800a4612623a99d",
+ sha_win = "d76003fad2146ad1f2289e8b251fbc359406ced0857f141a41f15149c2138302",
+ ),
+ "3.1.72": struct(
+ hash = "7a360458327cd24c2a7aab428bdbcb5bca8810e4",
+ sha_linux = "be094d6dd27c27a64116e9c0165d6cade5d329f5137e56696773e98e1df83fa7",
+ sha_linux_arm64 = "5dba64454809d72d53c432f3c91830d69d413ebd9dcd0ce18df5a79a3af235a6",
+ sha_mac = "52f713c118717814d2371912ab9019a3605b7d6acc627f3842e6aa7d3ffff7bf",
+ sha_mac_arm64 = "644593539684f59c635c7eae2e743f5e4e27b1d665f9c71c23dcefd4c2448b3c",
+ sha_win = "c72623fb68f109d8f122036f25b9fc75353bd1ce28995d9920277d4be4a1d99c",
+ ),
+ "3.1.71": struct(
+ hash = "7ee0f9488f152e9e9cf0d4d243970e03742f1a5c",
+ sha_linux = "43f87aa84a73697b905d2a13c89d016af8ec66bed792f37dd5a0059529abee12",
+ sha_linux_arm64 = "d25f5e57b2e7557df39cd9dec3b0283fb086f66c800af3d9a3f70f36c5fc6b14",
+ sha_mac = "8dac015c03c4f2e594d8bca25fe35d1e4d808aea81705121e852aff0464c4a9d",
+ sha_mac_arm64 = "a7797c3d210eda29f88eede261fc8f0aabf22c7b05214916b5b50a1271e9f0b8",
+ sha_win = "dfe77eaf22278ca975519f0497c8b336c86e52461c478060418fe67b39b6e87c",
+ ),
+ "3.1.70": struct(
+ hash = "6fa6145af41e835f3d13edf7d308c08e4573357a",
+ sha_linux = "c29b4a2c6addd5aafa613768d34273a23d8fcd1753c685ff61099506710cd8d7",
+ sha_linux_arm64 = "b13386975023a06f19057daef3896d480229b144d1e97f8764ed2f3e0fcb7d37",
+ sha_mac = "bc0edcaaaa19daeda9164d38d36c5f7d7b4b4e1eb7695ad58e776336c571fcc4",
+ sha_mac_arm64 = "e470d5eeb570850d66a79bd4c06064b9b3a1e90c7c2101e1a444ebcd6466fe5a",
+ sha_win = "f0118d71fd67583ddcfd39af2ed8bec3d18152fb6aadee085ebec5bcaf4ac4f5",
+ ),
+ "3.1.69": struct(
+ hash = "8fe01288bc35668c13316324336ea00195dfb814",
+ sha_linux = "24a786666e6f48ed3c3944b44df5cf146c45cf4faece4cb2686312a3d052a00c",
+ sha_linux_arm64 = "48e670501d215ac5b6b2680c900c517d9028dbc4de43be5dd6f25211a3640f2b",
+ sha_mac = "8503fe87dd2f30abff2550e9d6eb8aadeaf30fd3c6972d635b31e67f82e155f7",
+ sha_mac_arm64 = "995c7b3c84458edf6b8945e81405320c64a25dfe79eaa427fc1fe9a680f56b4f",
+ sha_win = "3839e0a581ae7b19156f004762a8221585e9a0d6237e468b13a878d1947636c5",
+ ),
+ "3.1.68": struct(
+ hash = "b52d8c9150dc7d4c8e4a7a08c7a9b4006c9abe49",
+ sha_linux = "1f2bcb47d85eb31d90fa797b3513221adc50f0656bb37f0962a40fd0f49fcf6a",
+ sha_linux_arm64 = "de346e7a489aa27a442215945d154d58a0d35c608b6150b2992af0e70c04e1c5",
+ sha_mac = "b180711544d783121370d2c894703f99d370a864ab147730f82fd59b88fa3481",
+ sha_mac_arm64 = "5e9b6242b56edc8cb404cbaf6c8bd7eb1f0f168b55b580bd92652f98c5d286f4",
+ sha_win = "824d37e8a0845f44e4c1111e8365640eea28944f1bdbd1e9e3fea0279b68baea",
+ ),
+ "3.1.67": struct(
+ hash = "4ae62984ea36ef0e5bfcbd0ed9b62f04bee6426a",
+ sha_linux = "535b64822916c80124363a5c7a5bd0cafd703f166d5155c0ad0e464e4a879091",
+ sha_linux_arm64 = "04c5f959702d8c1e5c000752b562271c224dee593e81144280840fed06e36cd9",
+ sha_mac = "692b8fdc79a47332ba9881966c72517eedf15b2da7bed37a535dfec55e6bbd9c",
+ sha_mac_arm64 = "ac26753f59fa9c8e92be9c91666014ad9400c91fbd37064105d1b5fcae503985",
+ sha_win = "8c6af8046ed47386018e42d18b53f57fad0926306dd4315d7f09dfae844b3dd3",
+ ),
+ "3.1.66": struct(
+ hash = "243eae09cf5c20c4fde51a620b92f483255c8214",
+ sha_linux = "b10eac37c978b28da2f1f34cdd8a7759c0ed5e5a2d8eb4f4e6790209de33dbf7",
+ sha_linux_arm64 = "9c78a470f74c24fc1fde2c8d86583ed98847b6cbdd87cd0b36ff2d6b4799d950",
+ sha_mac = "64fd0603ccbf949967cb0dfd8f1b0b25e018abf8bfe813b53596c4fc78751027",
+ sha_mac_arm64 = "fd6250f25101957f56086d292263379880c4b3329819a021008b2058f92ef67b",
+ sha_win = "b24f65a1a1111d8ace6ba47b55e07681cd0620f7bf711d1018ee262c9501defc",
+ ),
+ "3.1.65": struct(
+ hash = "fdcf56c75a1d27fdff6525a7e03423595485ca19",
+ sha_linux = "b2b7de13d37c4c5126e6c6a077e6019ebacc78ef1fb1b35b9035f03975f5ffaa",
+ sha_linux_arm64 = "f838af6495408f3c0a14d233171b4919b62e445c62805a22dea1875cb709a116",
+ sha_mac = "cc50b829a21a041979e0941cfd2047d30a06e3c4a8fd9f662ecdc12a0ab40535",
+ sha_mac_arm64 = "db4430db6a085d6ed5284917e632541dad3ce0a9464659fb674055247ad059d0",
+ sha_win = "e72ae4ec3231d9a492eadbf77ff28c13efd90307a69df04234792e67a001d05e",
+ ),
+ "3.1.64": struct(
+ hash = "fd61bacaf40131f74987e649a135f1dd559aff60",
+ sha_linux = "c39de24beca60fd580f6dff0eca0e275016042a30234588b19eda82397e299f3",
+ sha_linux_arm64 = "61b412135630a60c5517278dc83930e06f80fa286fcc2bb6366c4f620c86e4e0",
+ sha_mac = "2644772be398c8095621b3d0fe9ff2d122b18b7b0963c0eb702639d94dfb8e90",
+ sha_mac_arm64 = "47449057c345a09aa8750be1a357c364ffea9f8a066066cb341a7a2a14bac96a",
+ sha_win = "eb5b59afb420915daab4c383e5f73d456cc14776dce02fdc852c46522cda5531",
+ ),
+ "3.1.63": struct(
+ hash = "aeb36a44b29e8ca9f4c7efbb4735b69003ac2bb9",
+ sha_linux = "2a38ac1ea2fe3b7169879f0f666ea278f344cbb5db6e34421b9554939559109c",
+ sha_linux_arm64 = "f1dd5fe4cd22e89b1f5bfd216f1245f9f40f6ea76651a7f66e925a68ff6f18b8",
+ sha_mac = "7e192b84aecfade22817b5b38f0c69d1f795a9b990308188d39ed1d218692cd3",
+ sha_mac_arm64 = "751ef26a3682f5f23dfdc1c2f80cd0604a32cad61e6373c823de774722ecb9af",
+ sha_win = "947f8e867e781750d374d659644897f2345a133ad3d0f9ade23afcb81eeaddd3",
+ ),
+ "3.1.62": struct(
+ hash = "d52176ac8e07c47c1773bb2776ebd91e3886c3af",
+ sha_linux = "fd303a2b2a85c4b3ab8aa29595d70c5fde9df71c5254d56ed19d54e9ee98e881",
+ sha_linux_arm64 = "233c0df77644472cd322b45b2d7cf709e6c338799b46f6ec5d5f39ca4dbe8aef",
+ sha_mac = "d9cfef7ba8f44bf21be715244d0d5f909f1ccc2a481a301b3c01d12d1babc049",
+ sha_mac_arm64 = "de5484d60c858aaa8b93ba6485924adffe734cf4f8296765c089900cf9ce0701",
+ sha_win = "7455680bf9c19a26fe4868111ac01401023b0f92e862d3cabadf7950b87707fd",
+ ),
+ "3.1.61": struct(
+ hash = "28e4a74b579b4157bda5fc34f23c7d3905a8bd6c",
+ sha_linux = "e3e20e09219fd47a0019bb3252e17db4a00ded39b39b41634bc73f840a8ff2be",
+ sha_linux_arm64 = "a6b858601ca09fb7bb6ddf1a5ffb1a4130454c936ad046d45fef183037828c46",
+ sha_mac = "1fe69a3c42fb2857b80c8e77bfab780cb212ed7cf81ae57c0c4d235504df5269",
+ sha_mac_arm64 = "4ba702eea409e2d4bfabc73a68919217d3993e7585d95734e3e40a3c9ce1bd21",
+ sha_win = "bbafba849ff072a61dd34a8ffc0c85eed20a417854a3ca751b092e3565a92581",
+ ),
+ "3.1.60": struct(
+ hash = "87709b5747de5b1993fe314285528bf4b65c23e1",
+ sha_linux = "ff5eb062165920c7cb69935d396f13e9f8ca5b13f2d7f3af2759bcacb5e877e2",
+ sha_linux_arm64 = "2c291942df4868d3f65b31dd964bda9736bfddcd6a7886158963f797d1b45cf5",
+ sha_mac = "45586fab1bad65a4293ea8939dafb5ec711ba92ae7b4d1edbaae3b4486f398b5",
+ sha_mac_arm64 = "8dc27416a378ad07285d380f68717cfe0db1ea6252fdb1ad012af95e4d3f342e",
+ sha_win = "f3147ef2d4ca48ea2624039969fd0529d0bacb63bf49ee4809c681902768b973",
+ ),
+ "3.1.59": struct(
+ hash = "e20ee09a8a740544c4bc6de5d4ba5f81f74b74d6",
+ sha_linux = "ae59d1946cb92e1651cbb904fe824b3f07b39f42fa25f582116b5aaa226fa239",
+ sha_linux_arm64 = "25b918d6d5ee2af7ef6b28e089dc21d2dc419dca76c8079bb638cb20459eb9e5",
+ sha_mac = "af175bd559cb80459749e504da314af0163291f195461bf4d376d6980c4c60c3",
+ sha_mac_arm64 = "e17553bca5d00b30c920595e785281627e973f9e7e14c5dc0a73c355ccafe113",
+ sha_win = "bb54256fc3b7824cb75d5474f887d9bf8e1e63c15b351bdfbed898aa293ee4ab",
+ ),
+ "3.1.58": struct(
+ hash = "a4d4afb626c5010f6ccda4638b8d77579a63782e",
+ sha_linux = "b188249ecb939dadc679aaf2d3d9afd0fe19ab942f91b7bc926b4f252915dd1a",
+ sha_linux_arm64 = "4aedc8ca641b40d9bd82d85b1dc3458fe1afc9a132da06a09384a5f89c058969",
+ sha_mac = "2092aa4bef3b9f88d3f343b042a417ba617d4e04454656d8f2e101ba53f854e8",
+ sha_mac_arm64 = "7a9a15845257629b7602d15bdf7633a8e10472b0fa9b3d9ee7149938aa2f2039",
+ sha_win = "9fe76b6189566d56f0cf9aecbd23a006778530aa87184a900f5662e39ce7272a",
+ ),
+ "3.1.57": struct(
+ hash = "523b29e1b99a61069a2fa9f9d3cc9be1c4c53d4d",
+ sha_linux = "5bc444132258d4404d396f2044a4a334064ad0f1022555cad5ec72804a98ba5a",
+ sha_linux_arm64 = "f0022413afcc1610deff10921b3f5938bf4d01eba46ce96655f2295bdd84bd6a",
+ sha_mac = "31ddccb68c86f0a45332982938c49505158860ed4f7e8ccef72a48382e0e3c96",
+ sha_mac_arm64 = "cc5fdb65b339464f99b9c731cc63c233ec9577268886a856fa49f227ca2a56d1",
+ sha_win = "b53555420bb9b6e31c153e4c59427000ec692be17ae900f659a9b774d1ecebed",
+ ),
+ "3.1.56": struct(
+ hash = "9d106be887796484c4aaffc9dc45f48a8810f336",
+ sha_linux = "52338cca556002251e5e7d738adb1870d14331ddf463e613af02028b64e05a82",
+ sha_mac = "fc5cca6a9db571ecb2974bf0d4e12f1bc6068726271464586cf7e8723004b4c6",
+ sha_mac_arm64 = "aed728d09d801c4a33210505874ce066269292e7809a7d6a6414146be01545f1",
+ sha_win = "cd5fbe94fb0bcf01badc10eace48eddbca22b34f31229e3d70c68ade7bcdd571",
+ ),
+ "3.1.55": struct(
+ hash = "f5557e3b7166d05bddb5977e363ec48cd06e9d32",
+ sha_linux = "2a1cccc2f6db801219eb966d00af78a026af7822055064092387e7eba18e75ad",
+ sha_mac = "f1f8f4ebd086d0cd8bd54c41c6a0e86bbb26d7b8020484fef3dba67cd9e6906c",
+ sha_mac_arm64 = "7533b7a1beaa692a4f1e57b91c456b13e6bcc367dc9a414cb066350e8a2058c7",
+ sha_win = "204984cbb755f9aa09c21b49129d908f59617a60d5aebd8742097a9a2c196abb",
+ ),
+ "3.1.54": struct(
+ hash = "aa1588cd28c250a60457b5ed342557c762f416e3",
+ sha_linux = "5c8db804abe1ac7ddaa99a6997683cf9fa9004de655b32b5b612d59a94bd59d0",
+ sha_mac = "e6d2b8c6983767c7ced83d40b87081a221f05bab08d0fa4f0c6de652547c8a9f",
+ sha_mac_arm64 = "83764751ee5c7b42529e1df168695d4a51a23c9c165f3f90693baa9bd9256efa",
+ sha_win = "c0a1c9f3e1dfc9bb2e600501aea999f53b34a16f82da387317fdcae7e9c2a79b",
+ ),
+ "3.1.53": struct(
+ hash = "e5523d57a0e0dcf80f3b101bbc23613fcc3101aa",
+ sha_linux = "1025c0c738fbaedf3f8fcffee23bef71c8d04a95b30ea8a69a47231fb35d1c8b",
+ sha_mac = "318dc0cc51a237040bc1cb0a9e7d6c214196c8a100b50d0e298cf3ea7c365dbe",
+ sha_mac_arm64 = "e346ef588f7cfe1e41623de2257a11ecf8381fbd3bde63a8773b3a663411ea12",
+ sha_win = "af7f7175ab0b3c1e9121c713764e8ac1d970b6dbee8a84602b4a69cc5ec5940d",
+ ),
+ "3.1.52": struct(
+ hash = "ce2097fb81953331e65543c20b437475f218127c",
+ sha_linux = "1c0cd572067c6348cea5e347b9ef7c5460493ca3f0d84bb991689731d0e140ef",
+ sha_mac = "5d9c801f9cfe81337d65969e174e0b3ef4cf2b47eb548ff4695abe3a2e69ba70",
+ sha_mac_arm64 = "7ce8fef7542437c85412143cb59b13b8804bb06243a106d2d342c7d9132edc8e",
+ sha_win = "82ed01d965f5c2765191c67da5baecd2d3ce3f82a8cf30fc47fcd56d47826cf6",
+ ),
+ "3.1.51": struct(
+ hash = "4f416d92fbff66ce79901cfc8263768f1b25dd3e",
+ sha_linux = "09af08eb562cccf85770e4b8e368acb5accb1759fe3bc436b8fad80c27f90c79",
+ sha_mac = "b12201caf9ff2b981349edebd2d2c022ff000c74241ef96305b831abbd4f9450",
+ sha_mac_arm64 = "65fbee020cf965f9216607bad56215795529cbe8cef318fadcb33141dd6b5e82",
+ sha_win = "65c2d005a6be80723fa795ea724d4db9960601cf7d59d880f2882ecd45c8ad2b",
+ ),
+ "3.1.50": struct(
+ hash = "2ce4170cef5ce46f337f9fd907b614a8db772c7d",
+ sha_linux = "8822050b999286694cd4ffc7d959a8ea3137e3a910121d78b5377439ede9b598",
+ sha_mac = "39ce2f689be348b558df9c2c988b03472d43f8ac0827624397f7c0bb56a1e893",
+ sha_mac_arm64 = "5a9fa8de121db400bb46e716d861283b938ad87257d7c48f99dd5557100bd3ea",
+ sha_win = "29096f5596d93dbf620a9547fd1ecec8f54f3f52d49b13f09959d852310220db",
+ ),
+ "3.1.49": struct(
+ hash = "bd0a2e230466dadb36efc71aa7271f17c6c35420",
+ sha_linux = "18f452f8bdcd13e0d3a65c569180d1b83579775eadb8069cb32bca1f2e751751",
+ sha_mac = "c5275eab15e42abb3a42bbe1cfe38ee1b852febc78f65f5605b8972a7bee672f",
+ sha_mac_arm64 = "10a722e2c7dcc97236f70f2d68b23a7975800ebf27ec4fdf76deddf483b1c6d6",
+ sha_win = "4361fc18faaf70a2dc342c219b13c39a8196e9a48e6897d08c7b0dca6ba6525d",
+ ),
+ "3.1.48": struct(
+ hash = "694434b6d47c5f6eff2c8fbd9eeb016c977ae9dc",
+ sha_linux = "689fffcb60f93a60a7bb52cc205ead43ab31f252753cfef39ae2074f6a442634",
+ sha_mac = "8ac2a3f32b4cba0d84ca5a1fe1db883dbfc2731432833ab5a7e6967c5f4ab7dc",
+ sha_mac_arm64 = "10dd40f94fe5c5f8c4efc838d1623cafe98c629d4c7872ad8c15cd7b0836f281",
+ sha_win = "9276435ea7c402c18572a4301d6a26426eac73414b0ed5cb3e721044a50f651d",
+ ),
+ "3.1.47": struct(
+ hash = "39ade279e75e6d17dd6b7eb9fba2006e61fe966b",
+ sha_linux = "bdc50abe5c7d4b4f14acea4ec36b270e86770cea2da4b0c393b80a692dc7eb7a",
+ sha_mac = "6a3a116707037d75a967a7d971894d8ace74a2a230aa50ba55e88e7cd7b94953",
+ sha_mac_arm64 = "b13d228e6a1c89c13a1500fff07dcf093fb01fa621d458496d4a6d7f05cfd600",
+ sha_win = "66a6c4f0cda4ace14a86d3e59d20685d35211854d21670632b0566ac73638245",
+ ),
+ "3.1.46": struct(
+ hash = "21644188d5c473e92f1d7df2f9f60c758a78a486",
+ sha_linux = "75cbf14629b06e417b597d3f897ad7d881c53762380aca2f0dd85f1b15891511",
+ sha_mac = "06f45608381203d501141be632cab960aa105626c3a0f7a48657b79728103880",
+ sha_mac_arm64 = "c2a85b509a91663b390f77d51fba775421d42456211466fd3757f9dede7af9e4",
+ sha_win = "1ed3a3f36dee5d373ebea213fc723b3eeb7d6ba4c43da6a951ea0d76f265f234",
+ ),
+ "3.1.45": struct(
+ hash = "2b7c5fb8ffeac3315deb1f82ab7bf8da544f84a1",
+ sha_linux = "1c0576765f8b34603eead6f2bd4bc77bf68ea2f0a39ed4c144514103e85bc7d9",
+ sha_mac = "87f63ebb2f9807435016b238bbf46ccb94c919ec0786b46463cd788634391b0c",
+ sha_mac_arm64 = "29e698772c0e00c21ce120dd1db1586f5c65507168babff148c2e628add6e72a",
+ sha_win = "891d49f8828f715ef621d55fe202de4929bbdc89b69101fd33963571458a7f47",
+ ),
+ "3.1.44": struct(
+ hash = "b90507fcf011da61bacfca613569d882f7749552",
+ sha_linux = "5ffa2bab560a9cda6db6ee041a635d10e1ef26c8fc63675d682917b8d3d53263",
+ sha_mac = "291b2653f7576f8354f0267047e47a5ddef11223c89d5be399d04618f13b3832",
+ sha_mac_arm64 = "ad1625821b49ccbbe733596223fdf99fd786470d679f2c9dfabd4a1a7b929282",
+ sha_win = "8b61f60ef169b1c20207361067c40192c83b96cdbdb2f4cff21dfb20b9ee528d",
+ ),
+ "3.1.43": struct(
+ hash = "bf3c159888633d232c0507f4c76cc156a43c32dc",
+ sha_linux = "147a67a3454783b8c351780ec0111329d1e6fbb1d2fcdfe1c035e1c0997e0701",
+ sha_mac = "d84896c6d1ba0fbd9a5e5c5830b3ac4a02da5e683e9d8c7172f4c3ffdfaa0392",
+ sha_mac_arm64 = "d684f0bfc655f61e76cec29fdaad1668f3d21a229fdd908267f400691468328d",
+ sha_win = "a335f5f5b070cf354f1ca8e0afb23c06ae5f9ffb2c501124da7fcaea09a7db6d",
+ ),
+ "3.1.42": struct(
+ hash = "9d73bf4bd5b5c9ce6e51be0ed5ce6599fcb28e9e",
+ sha_linux = "aaa076e64dd511b0d874c348f8dab80a2f9ade0887ba74845fd02c40bbf9e68f",
+ sha_mac = "4715002394c5d444243c77ca231883eb999cf3313c4869cf0ae288d911f80f89",
+ sha_mac_arm64 = "84dede714edd81362ed2a2f79b91b1bd9cd544f219f937582e616d73bf0ea7f9",
+ sha_win = "4c704f4a4927aa537c2815a72915b7591c163ae8f0dbaedc167e810dd2a4a83d",
+ ),
+ "3.1.41": struct(
+ hash = "eb71265ef0ab905620015adbfedacf88c5dbf021",
+ sha_linux = "493ec8bd3f3ea3d6d616de01d6dac9c2af696978c6c44d453757ab2f8a666656",
+ sha_mac = "bb088e7b8f83b6bae02a0992eae61351e4e97bd033f8c8937cdaea0cb961ac9e",
+ sha_mac_arm64 = "aaba2de03a6dcc0db90e61e5e405a52aa47124e5ef21953d052ca015ce5ee773",
+ sha_win = "c7afbf2dfb6040990bd40bd72c726ada36e3e6f1985c4b62db7296465dd0778f",
+ ),
+ "3.1.40": struct(
+ hash = "c3122846bb040798aab975f61008c37eb19476de",
+ sha_linux = "5501e750c92f5a54b27ee101f6816e7416f154cb4181b73fd0be3faae947016c",
+ sha_mac = "052d6236ce49eaf3aa02b3c4d367b5ed4fb78209c1f1e64d48beb79e9c0b7131",
+ sha_mac_arm64 = "c8af68f904367938bac255f5e64ed271021b289bb135dc77ab3b58b87e1ea5b2",
+ sha_win = "3ec21ca18b56f7d3953da2e0d468154fcaaf30b5ac663d9ad00c41540923a099",
+ ),
+ "3.1.39": struct(
+ hash = "1b56b171b627af0841cf8d4d8c0160c6cb6d855f",
+ sha_linux = "7ec6e15a2da2701243f89af7744403ee011211e59e4f0a6fd8ced544e72e917d",
+ sha_mac = "dad7d270207aaffb8b8ef584cf0579bbad144879ea6f00ec9a8080adf22130dc",
+ sha_mac_arm64 = "c5e474ca661348d0339c785e25ad81845d49dab19d5e3e84eef2393e623e0bac",
+ sha_win = "a04f898b9d54dd2dc95fb697a92a1b65d07102a4cc36a02dea44c448fad83472",
+ ),
+ "3.1.38": struct(
+ hash = "03ecb526947f6a3702a0d083083799fe410d3893",
+ sha_linux = "e2812859fa32b6019f688dd66f2fa48efbfb5594da9a43b876fd4fe4ca474c20",
+ sha_mac = "a88c4b9eeb5dedb0d9af3b6b84bd45c486de567fbeba1675edb2d7d196e0013b",
+ sha_mac_arm64 = "0e5d1519ccc1163c13ee93d85f70ef6a520464f59ca3795c47cc7c44ab0f5f49",
+ sha_win = "bcdea031961a4f3c23008d53e083770d19751dd2a2aa71cacdea8462d09548be",
+ ),
+ "3.1.37": struct(
+ hash = "7c905cfc1ca6699f6ccb288ae174902cfbdcf0a2",
+ sha_linux = "9ff44ef69d3f389adcacbb9b95331da72cffdf6e9431c8beb6ebf7aedb77499c",
+ sha_mac = "accfe90322b6449933c3d8e1346024e2e2e3bef7b101942294f995b2c8e1b60f",
+ sha_mac_arm64 = "a0461e234c08bd7ddd7a86b49b52ccc853ebe4ce0fb5b4314e9de0193c32514a",
+ sha_win = "e026ea2570e747d0640829c62abddcdc14a4acffe31180110971750b80042d7a",
+ ),
+ "3.1.36": struct(
+ hash = "adedc0750c4a89b65bee866edab24298cb8d6677",
+ sha_linux = "55d3cc557a83716f7a7fe121a07dbd59ed4b5d425051e22c902570e3e0ea6c4c",
+ sha_mac = "6643fcef0f928cd730b894f0c2c3343eeef870576e43e56428a7a8247c7bc921",
+ sha_mac_arm64 = "2e8d9103cd0ba7a2b143927196a630b091b981006c908d7d36995a210a04d73b",
+ sha_win = "69a197f6fc153d9f98ced539564683cb13ff0ef144d3d4fbddf643e33b5f860c",
+ ),
+ "3.1.35": struct(
+ hash = "671550b5bdceee7bdb21493714f9a815aa5149a9",
+ sha_linux = "9d4b5dcb719d39e59b646ecf7c409db20c5cb6b9575f5362ffb49a9e66290819",
+ sha_mac = "01ea06c1f4a6c980bfdc812f9599a8ef424a975c89d5c288c9e6f2fa5e5ef5ad",
+ sha_mac_arm64 = "f6480ee21c80fe062e0f9d8555f8bdef621601634b9bd1e5ad07b90777ff5e4b",
+ sha_win = "cd26088365433ce1263a11898406c2f9284e55c2c7f23b26170c2a172c52f0b1",
+ ),
+ "3.1.34": struct(
+ hash = "2fdd6b9e5b67d5b62f84d0501a876513ff118ef1",
+ sha_linux = "dd3713f077072dcdb811f934d6685187daa47c424039e31cba83633c8d1681b1",
+ sha_mac = "3824609ee9b7c9919e29b19775d495a16778adb981867901f4bc503fe2f65d7d",
+ sha_mac_arm64 = "72728637171df46e7cd22f90537dd6faf1d4809ed1befc504ff96768c82f0e0f",
+ sha_win = "7538d1a1e0d586bd0723f595557551b05d724a5803132949a6fafb8b056af995",
+ ),
+ "3.1.33": struct(
+ hash = "49b960bd03b3a9da478a08541ce6eafe792a58a8",
+ sha_linux = "eab02b3f4b7c076974452ba602f908a36adf597afa15b16095b441f191ede1bb",
+ sha_linux_arm64 = "5e15af6affcf37c9ce6c304b4aeccb87a2758e1ef029dbc996f9d77d7444378e",
+ sha_mac = "b8dad3cddb19c1daf9dae99020bd17b903ae9649cfc58e433ea4951e758804de",
+ sha_mac_arm64 = "fbf03d06c7503f091191e440b8ea577d65b3261167cdb47359d053f12888974b",
+ sha_win = "031f951668eaeea39bd9363abb3f514efc3401506374984fa9b1d7ba3130a62f",
+ ),
+ "3.1.32": struct(
+ hash = "29ad1037cd6b99e5d8a1bd75bc188c1e9a6fda8d",
+ sha_linux = "25fa252e9fc674d1bcef35b3a10dd85024aa93c843b8067f8d917e5151968ffc",
+ sha_mac = "7881714e7738eb183b5a421bb2b907e96359e791ad0a622be6e7f5690a16b9d6",
+ sha_mac_arm64 = "04eede7352aca4b6fc1c111a8b31d00e8aa40547c3cd062ff9be4ffe1ed98d95",
+ sha_win = "22c3429eb1e6051bda46e9c02c14eca1ae3749ba8c411fbd5a3b51e3b9623161",
+ ),
+ "3.1.31": struct(
+ hash = "1eec24930cb2f56f6d9cd10ffcb031e27ea4157a",
+ sha_linux = "5952523c0c58cfc7c8839c1d3fe42ff34af5d8721231306ee432063dfacf96ca",
+ sha_mac = "13482cf3cb29f423f2037b9dc2b9e4ff72d0a49fcd471bbaa9b76d9f86f31d82",
+ sha_mac_arm64 = "654a35af16be5eeb2082e68fb36190fe76de28fa2da75ac0d2197482a203f39a",
+ sha_win = "493c29f5a505ccd9687036ee4c580d190b1c32b286be0e751a78e68997cec8b2",
+ ),
+ "3.1.30": struct(
+ hash = "dc1fdcfd3f5b9d29cb1ebdf15e6e845bef9b0cc1",
+ sha_linux = "151d7afdfb728e1e55ed1d100e4d3fbd20925fd65f3c3b9e093061a2c89dcac7",
+ sha_mac = "f0cdbc676c58bce7a65572418fb1521665ed522d7d05ae90f0764b77801982bb",
+ sha_mac_arm64 = "fca4eaf8ff528bb9308e5e8d0cf2709713b99fc19d55c6578a6c8f3e66182f55",
+ sha_win = "3001101622d98b2af3e5209154f60bbe341d32f6178307c6c723e84b5fe08bdc",
+ ),
+ "3.1.29": struct(
+ hash = "d949f1b99a477d4b0b54d95413df3688afa69d0a",
+ sha_linux = "d3f274446924c27082603170fab60ba78a2fb51360e5578fab4d9b5adab0fa9a",
+ sha_mac = "ed224c296efd22437f298f0fe0852613b0b1d48810b1b6d87b6b7e6beb589fe2",
+ sha_mac_arm64 = "af9bb86a7996bbbb36820e93dbc7f537ac23070e8730439b1e49792c4fc008e9",
+ sha_win = "6203f80273565a2ee6734bd33ad7bc6940ef709cbd593e70d6489e96c02ced25",
+ ),
+ "3.1.28": struct(
+ hash = "30b9e46ddcea66e91530559379089002d8b692cf",
+ sha_linux = "c23426d8b6d94cea702542c39e3bcef9439425dd4bd03bcc172e291dbbe5ed0d",
+ sha_mac = "4cfb918fe3233a2b31e5734e85b2a365e634f4e8a83c4390e8595cb98ae6bd8c",
+ sha_mac_arm64 = "a47f1f09bc7bbd4952cf54445d4fbfae53623ecbfecee0506a637665c7b4ea4c",
+ sha_win = "4388d230871d5b1e15c2fd0db21a792ab2836f23d860475fe183c03c5db75c8c",
+ ),
+ "3.1.27": struct(
+ hash = "48ce0b44015d0182fc8c27aa9fbc0a4474b55982",
+ sha_linux = "4dc872260c8f42a8e20c8612b2255adbd466fec54cfbe37b46eca4eb34a2b03f",
+ sha_mac = "40c3326147b162b8357efdc72476faaa6686338cff3e176680e361c2511453e8",
+ sha_mac_arm64 = "7b87610de966b84353c8c1ded8e12c034b5b913c093210ebd3b26320e2ac2990",
+ sha_win = "39bbfcb09ba7feb214518a67b1ff6d38bae065b416b4483834e4fdaef2316f8c",
+ ),
+ "3.1.26": struct(
+ hash = "4f68bb2a505c727bcf58195cf4da20592a6e92c8",
+ sha_linux = "82d24d5619c814ae99ef7243de428600c02e96dfc49c36e44753b1fce626766e",
+ sha_mac = "7b645979d8901f3153507561bbec10ecfeb197dca5914228715a74b760cf7eec",
+ sha_mac_arm64 = "d9c647fd70588bae71303a6c923df8a44ffe63e168b375d35bf6ceda21258fa1",
+ sha_win = "1ad49d69634ce2d1fe04614c18060a903c102e1dbc9dfdef3a03e52c189b4c92",
+ ),
+ "3.1.25": struct(
+ hash = "ff6babb041d0f31575cc16d15ef82c6222ca99b8",
+ sha_linux = "c5ae6b4525845ea36bde89cbf4e1d03de87a2658862d76c6a53bbf8de7c67ff5",
+ sha_mac = "d2581aaa7207f0d9dd9949247f0706bda8561e805d67aec166ed4f3b39c3a3fa",
+ sha_mac_arm64 = "dbcb76036a09248c2a839872c27b87b6d4ccc81e57add4e2a6f5e560a2c530fc",
+ sha_win = "3a86d98d934456a74ed06388c1487d95a0d5a3f31777636453f22e61d57d7fb1",
+ ),
+ "3.1.24": struct(
+ hash = "54217a0950bb1dafe8808cc6207d378e323f9d74",
+ sha_linux = "20e8e5bd745e3ad69c03bb877091d2fbb0c7db1eab309de8f185e9821aea40f4",
+ sha_mac = "cfb897a980dd51fceb02ff143ad0fd8e5d299db640c5646d1547d522194545f2",
+ sha_mac_arm64 = "e87b0727343051312f82a6653cad4682a518dd9cb6575844c0cd6505d520fab6",
+ sha_win = "a0ea07f9014a912f13176fdbbc1ee7ab08104d45e7ca7e1c237505579b63d530",
+ ),
+ "3.1.23": struct(
+ hash = "bfd5e63a44ba4c8568cd8ac87c27b35e40732bf4",
+ sha_linux = "3b8d9e163d6afc8569deca0ba1d4042f80da7a31e23cee006c3faa9cbf2fbc31",
+ sha_mac = "fd1c79475e47fd2f06ee9ba189e68309e443c2d3c56fd28163d1cd6f77047075",
+ sha_mac_arm64 = "66e57ee0962ec31056674b5681f91bd62f85b0bf1238a8d5b160660c0bf47292",
+ sha_win = "7c30b281abcc0ffb9e7575197f1ac0598a94c6cec36547b81554a97b792a9e75",
+ ),
+ "3.1.22": struct(
+ hash = "990cee04a21caafc75955d736fb45791a7f2aeee",
+ sha_linux = "a310ed9f16c97a91c72564ca5f85c412cb99429d8001825663fda1b28c00346e",
+ sha_mac = "b19afaf414178781c4c91ee711ec4d9063b9736719e45ca2e8b45c2258df16be",
+ sha_mac_arm64 = "7c8212abf77f0307b6ff848bf9c6212f870506df6d074349f76401f30f9fcefe",
+ sha_win = "2c0cfe267d47f390d7e35a83545b1d5043e4a7fb77b838ee19b0fce65035f55d",
+ ),
+ "3.1.21": struct(
+ hash = "a16a8bca2466eb144f7c93fa899c0272c8815dc3",
+ sha_linux = "7045ddb3b37a2cc63cb1cf976019a6a3b7f8dbdc71254db0eee5b0452f94e9e7",
+ sha_linux_arm64 = "2852c8b108ec748d52d31dab3f4854bc6022df008019daff1c7e31ac00363b3f",
+ sha_mac = "2a8d3d3ad721fec81ca1a4a581e4183b6e732e9905beb874531851846a05a367",
+ sha_mac_arm64 = "cf788a7bdc38bb40d01f94b2d46acafb0e2f02d8ee3b3d69541c114e467ee37f",
+ sha_win = "81518bba13f41717ffe6990b6d4a5af635d0c9d0f71a8d3bc0980cd0bc8f5f66",
+ ),
+ "3.1.20": struct(
+ hash = "d92c8639f406582d70a5dde27855f74ecf602f45",
+ sha_linux = "3b606d133489aac8cdfff4f99ff14a35563b1fafe658aa23f83694f77ed9467a",
+ sha_mac = "cc9ea1696bdb3f28778bac1cf4587a34e90830e1c64976cd205fd73e77566cd8",
+ sha_mac_arm64 = "b976410bf4fa1af9896be1c736634bfb56b2ef0f3386cd3cf39616ce47445cc0",
+ sha_win = "1e6806ee240ab838ae7eee618c57efc793195c62e4d167136507efcfa66d6c6d",
+ ),
+ "3.1.19": struct(
+ hash = "4c3772879a04140298c3abde90962d5567b5e2fc",
+ sha_linux = "18d4a5bb93371fe1d4586db9804f673fff0c510d98713ec25b6bda1a8457230d",
+ sha_mac = "6adb721340cb93b7a3efafbfd1d283842a39bb6f1390630b0806c8af26b66840",
+ sha_mac_arm64 = "429c9e3a79d32380f3dfee52b1001963edaa2e3035fce9f52ca87b08e1a2f26e",
+ sha_win = "0368eefb28f42799ce897020d0d10a4a27e1b69b650575d94deb268e402a3632",
+ ),
+ "3.1.18": struct(
+ hash = "49d45744895c7d7e28acd94a385d7ee361653b4a",
+ sha_linux = "6ef373c4ff3cdf33d7beecea47d4eaee7795693f8ca9469f33785cb9c54f40bb",
+ sha_mac = "ad0e645abdb6d3f0b6c6ad0ee70761010a712949c9b0b193aefc78ecbc3f1710",
+ sha_mac_arm64 = "68d0a1ec3e83e0415e24133c59e64206b83686712434c8c2e6792547cf654b1c",
+ sha_win = "96829a228f7c08fabd37833f7361614785aa39aa865beef06890ee8ede58dc66",
+ ),
+ "3.1.17": struct(
+ hash = "d27fef2070c86a218965da8b8b5df8b4425aa3bb",
+ sha_linux = "562b3ba75ce77a917317bc697febb38194e85cfe07f4fec308c3b29c621f8f13",
+ sha_mac = "8a2bee8ea434049e40663a6d78d1c3584e5c32196fd85d6a10f3192d2e3aba4e",
+ sha_mac_arm64 = "5f60d3f351d06d862e853a294642d24243d6cb197e34c2f2602d80555c2eb014",
+ sha_win = "90b2ade825e07bb05831090dd64b5f5b01a4169a84a3ddec85fcd60be3b246a5",
+ ),
+ "3.1.16": struct(
+ hash = "fb1baf00423818052359cf9126e94bc71c39feb5",
+ sha_linux = "bdce7e58833069a98d7e0b4fd9d6fea7394770ec10339cc95ed9fe52ba39f3a7",
+ sha_mac = "d05f4e997324d7f7d8561436677687d296893d6414f53930184fab272e4c6158",
+ sha_mac_arm64 = "36ab8da30698558a567c5c1c0e130b59f08cf4b29c9c5242f4ea60b449ecff17",
+ sha_win = "e1324c22c914ab7f62fe6d38a550de25b2232a723c80393fa8884a260c07766d",
+ ),
+ "3.1.15": struct(
+ hash = "568a46a9fb7e1f1686a6f7216b3dc976f28d2a79",
+ sha_linux = "737db513047d12e95a12f4fbe05314f3af79ac955d1ea43fc83626337e307edc",
+ sha_mac = "f8993371a1ff713203023f0283054a31df5342ca287debc4e16d04d97e069aee",
+ sha_mac_arm64 = "c61a8efa8543a6c44e394a0685e7d4facb4c7dbb210c4c32d311b0002c4dec99",
+ sha_win = "235592467a0be6a537e03fb587aaee230aa2c889f2785cb9754eb44bfbf747ed",
+ ),
+ "3.1.14": struct(
+ hash = "ade9d780ff17c88d81aa13860361743e3c1e1396",
+ sha_linux = "e2c43068fb1985592db42183a13f85bbd9518b3747746e0003d70c7d770a0b2f",
+ sha_mac = "567e9548f3fa7c1aa717821af4aaa7849a0f7217cb55eb7f66a06c898808fd96",
+ sha_mac_arm64 = "df8319aba8bc0d0c40ebec3c8f45e507c2a51a57df24826d4cab6f6cd75017ac",
+ sha_win = "6bfec6bf6a01e483a57e91f7223340a425f6ff711cbd32a08ed78002810d7882",
+ ),
+ "3.1.13": struct(
+ hash = "bc44364b561cfde15c243a54e3b96ea12d7ea284",
+ sha_linux = "290f04300465cbb7c8e920f9986128b3f287b14b93627b0c6d069d534860c1b4",
+ sha_mac = "72b209a3e5800be155cf5b29bdaceb18aefceeba68f35ac719a483bd27d85705",
+ sha_mac_arm64 = "2bf90ed73454f58b810e09a776a34ddf7395f9ee45580f3a8fea53f74ba7ede2",
+ sha_win = "07fd730289c26f72ae4037fd25f608f6b9d36f1950677229b6c7d392957db3d2",
+ ),
+ "3.1.12": struct(
+ hash = "a8c3b314d61e2bb98581d522f858132b2fc21488",
+ sha_linux = "ac8ae46b2fe2fbef07077cdeefc8288d2a73e3189958f32b36f2d17d868275d0",
+ sha_mac = "c33afddd7c8f7a5293cb427ef26eb65f51fa3121d0577568824174227aa37ef3",
+ sha_mac_arm64 = "253feff779385d2499764cd988175446e21db8cbb9952746e96969c2a763924c",
+ sha_win = "04015fb6a1b4ad4d7c16587a7eeaabf19c5b35097f3e28efa029c0c67547067c",
+ ),
+ "3.1.11": struct(
+ hash = "8c3a799341c01148692c52fda73bbba5e89c5727",
+ sha_linux = "ba52cfd784362530866c9d554ddc62cfa3f0690f44007c0b3b36e189bb579d5e",
+ sha_mac = "c46548425e0bf4acd3c4275aff6a463c90ff1faf283ae7f5237d8c17bf84d779",
+ sha_mac_arm64 = "c5ae40c468955ed02b86c54061278d2b4075b1230612bae5910f836aa9c200b3",
+ sha_win = "74481a1998236fd9d296f367584934d5ab8bbf174446ceb647f714031671de98",
+ ),
+ "3.1.10": struct(
+ hash = "8bd05c7221b4ce34d4bedec40b672d94e681a765",
+ sha_linux = "f5a937383b5c9fa15071a31d679a2ddd5c03bc8952cbbd5bfbf7c0a86c2dae5a",
+ sha_mac = "e73491f2787cbda75e718c3947916b57259164eddd9b2db16b9c876d3deb16a9",
+ sha_mac_arm64 = "d7485ce3b13f183484af5163d7bec79ece9a1fdc5845f8152e36270e6f90cfd9",
+ sha_win = "dd75061405bc902ecd983bd3e4cfd6931a866e1c9de602c4458280cbeb271720",
+ ),
+ "3.1.9": struct(
+ hash = "edabe25af34554d19c046078f853999b074259ca",
+ sha_linux = "89fa75c981e47ad19942b8236d2604b2666dfd516a08626aaa1bfb0d657c87bf",
+ sha_mac = "6c7f59dd84d1484f1dfa041d71cc79fc97db8d15834b6220e5868bd9bd373a24",
+ sha_mac_arm64 = "13a258de0daaa3c09a53e21a67414cbf5fa5706f955767fe791a059ed5eb90bf",
+ sha_win = "0857b03919b948558f9a57d15cf2b220852cc070359c386da0e6e4831c7ac5e0",
+ ),
+ "3.1.8": struct(
+ hash = "8c9e0a76ebed2c5e88a718d43e8b62452def3771",
+ sha_linux = "6b170777eb523e62972ad458e533b1853cd0c4e02f6f2cf4cd68e109499ccd9b",
+ sha_mac = "ede01fe160c3b8443f53f94dbad530e0e7e8197a1b874c7bb9038b187279080c",
+ sha_mac_arm64 = "9ecc8678f948875e7f64defeababc0320f98e103547f395c390c01d76e5a1d64",
+ sha_win = "039d27d4ae43b50d0858dbc4dcf412f572351e98e1056d7fdcdf2aab1740557e",
+ ),
+ "3.1.7": struct(
+ hash = "d0e637fe48197587d981f79e8114757731d0c2a9",
+ sha_linux = "d941738a3c755d6d530bab66d38325515b9dbaa588d2db2b8a63b2a8a1961e52",
+ sha_mac = "597aacdb25d422094427014d3a97e8b91ec80df2255a66e0986414bf71aaf37d",
+ sha_mac_arm64 = "a0b2db0269c55e854d1007a59f95b8e5f14d32309e76f985ea9afe481b2bd6e6",
+ sha_win = "cb44339db27b694862efb37539d41eaff7253c93c0882cf7d9aaf4afeaa82912",
+ ),
+ "3.1.6": struct(
+ hash = "8791c3e936141cbc2dd72d76290ea9b2726d39f3",
+ sha_linux = "f43dfe707dff18fa7a08dbfe2fa3f8d46afb65ccba9bbe554465d83d5d80e388",
+ sha_mac = "13a01080ff042560b9a9b1b2c9fc5f8c154710bc41db8bbd907a9e53c286afd0",
+ sha_mac_arm64 = "7ae97e85593b037c345b539e7f8b8952b82c001be982219060c83f0834bb6827",
+ sha_win = "e7005c0a5439e532cb64f34ba90405792288a1ed8845cdafcedd3de5af6fd3f2",
+ ),
+ "3.1.5": struct(
+ hash = "2dee36c7163f7394ab9341854ef5281501dd97d0",
+ sha_linux = "6641703b7da1805aa5a8488d231ae7fedfe27f1a5a33e7d05a2ee5902ab84180",
+ sha_mac = "9dba57f09702a7eed53f3f71cdd8a4ed1202ca5a5f4449249c2d98a285b26f75",
+ sha_mac_arm64 = "0093b4d47c9eb9c8bab5b3048c68855255b5e5a8bfd78f4183424009489327e6",
+ sha_win = "849edc42b494f670df4763dbc8ebbb5464ac28787482668c3f6e27588a77cb3a",
+ ),
+ "3.1.4": struct(
+ hash = "39e60dda6945cfcd6487725bdb1361ae7975173f",
+ sha_linux = "4a57c0d60eeb4e021de61c8497f0b595a0a9db0235f1640a528de752409f4fcf",
+ sha_mac = "f28a9a4f42f67de1d5c4d8a288f29e5082bbf4fcb172e0c6e248695163372478",
+ sha_mac_arm64 = "be35043edad7a7022f7b174e8efc90e2db54ba4fd71288760bea4db082835f56",
+ sha_win = "d97ff247bdfc7e839610cbcd87d30a65018f964d183d5b852b6021d43c5d199a",
+ ),
+ "3.1.3": struct(
+ hash = "2ddc66235392b37e5b33477fd86cbe01a14b8aa2",
+ sha_linux = "8b840819eb88f9178c11bad25859ce448a0559e485823a863a6add21380636ca",
+ sha_mac = "0cb3f9bfbcc744233eae9d20036155738409405eacf8a3d4f9beefc5919d809a",
+ sha_mac_arm64 = "ee2772f380419df17d154e00388a16bcddc78c7af035c16a2ee534d6ecf099aa",
+ sha_win = "c0549e1dbaa581ae66934c38beebd4250cd450cc2778e9a602cd9431bc81bc37",
+ ),
+ "3.1.2": struct(
+ hash = "6626e25d6d866cf283147ca68d54ac9326fe399f",
+ sha_linux = "4fb53364a2ba1de8978445aa26b2204bfd215b41da5d7df04f231040b197010a",
+ sha_mac = "a8e347accb1ff402d96a128912ac8cda1731611c9f89095fee0ad39a6a18bbc3",
+ sha_mac_arm64 = "4374f5c852d0403b0a3b0e9dc8a3856a340e9d82ecf0f20aa8b36c6179d31fc8",
+ sha_win = "e96f6ab8252fefa42f461676311d4c4e2d96fdc2e876ece07d9d7a49ef31aef0",
+ ),
+ "3.1.1": struct(
+ hash = "5ee64de9809592480da01372880ea11debd6c740",
+ sha_linux = "ba94c5ecabacbedc89665a742c37c4c132c739aea46aa66fd744cb72b260c870",
+ sha_mac = "8b5f8cec55af0e6816a08d8d1e8b873f96d0e0504fdd6e8deb2fc024957d1aa7",
+ sha_win = "6cbe976aff6155cf1c48707f0520b5aa6a7770860e9b1964bfca3e5923ce7225",
+ ),
+ "3.1.0": struct(
+ hash = "562e3a0af169e6dea5e6dbecac2255d67c2c8b94",
+ sha_linux = "0714344e32e244e6d44d9ea75937633ab1338e417a232fb66d6dcd7d4b704e8c",
+ sha_mac = "f6c1cad729ed799e1df09eacf5aa80cce9861d69ec6d9581c17e4ba8d9b064ce",
+ sha_win = "756c41cbcab4ae6077cca30834d16151392b8c19ab186c13d42d7d05d6d727cc",
+ ),
+ "3.0.1": struct(
+ hash = "91b7a67a486d2430e73423a38d950d8a550826ed",
+ sha_linux = "25fd430268596229c4ac38e188d7c2b31f75c2ec8172b1351d763e37c830c6af",
+ sha_mac = "52ec2204115b727cc4de38b5eeae147eead12b299b98e5a88653d12958cae4d4",
+ sha_win = "0e072736b471c9a07cdf534ba4da46b3b6545b63c8a6cbb0ef7d544251e15092",
+ ),
+ "3.0.0": struct(
+ hash = "7fbe748230f2ce99abbf975d9ad997699efb3153",
+ sha_linux = "10646b64daea15354f14f89f7e79937f420b77f31bda7c4b174de2474835950f",
+ sha_mac = "ebb17bc91c6a72ca06d17337d27aa1a2be4c9af4c68644c221712123f663b8ab",
+ sha_win = "0d4f2ff5d88a8eef5ed769ee4ffc5d5574143911d2e0079325cdc5206c9e9bb1",
+ ),
+ "2.0.34": struct(
+ hash = "d8fc1b92dbc0ce8d740a7adb937c5137ba4755e0",
+ sha_linux = "a6304e3a52c172eb178c6f9817d74aa3ee411e97ef00bcae0884377799c49954",
+ sha_mac = "975ae11000100362baf19d161fec04d82e1f7c9fb7d43c43864ddd65a47f1780",
+ sha_win = "8167a44bb895a0fdc153836bed91bf387be57f2dc1b8f103bf70e68923b61d39",
+ ),
+ "2.0.33": struct(
+ hash = "cef8850d57278271766fb2163eebcb07354018e7",
+ sha_linux = "958a0f4b1533e877c1a5ed3c13cb8baabc80e791d45858c2c94ac62325ada953",
+ sha_mac = "8ecb248653d44c3748e23c089cb9f0e3d4eee7cda13fdec27ec0113b896e34c4",
+ sha_mac_arm64 = "1ec6f3d7afa5e10f3af996e26d9c3a66f02ae49e48e512a4b5d6b7165c61290f",
+ sha_win = "6b6b2831f8b338488f787b4a8c34700277bf3988358dbb54426f017155603ac9",
+ ),
+ "2.0.32": struct(
+ hash = "74646397e3c5010824ad60d1de86c6bcbe334dff",
+ sha_linux = "236b3954e71d3bb30d347c655b9f47f2a091aa2e61046e1912c8da90152f4ca1",
+ sha_mac = "6a03267574534948e3b041e5d3e31bd757751ef17912eb6e90b96a47da03afb6",
+ sha_win = "2f8fbf0db097d67d0c364946faceec27c569c5c2d7b22068eef8db55645aba36",
+ ),
+ "2.0.31": struct(
+ hash = "597724ca3f6cd6e84bea73f1f519a3953b5c273d",
+ sha_linux = "ef70c7733aa0df41cb4c812f5a89bf6b2ed13ca8aa252872396c0be271156d9e",
+ sha_mac = "77e57c3e98758488ef676f8f58a85faa0bd65a1d326a91771ad83d7cb0e373ca",
+ sha_win = "541605b740afccd08a39f5ae815978f699f350d621a1b2dfba0763970b56aee4",
+ ),
+ "2.0.30": struct(
+ hash = "c69458f1bbf3ef5b8da4e934de210659cc9bca04",
+ sha_linux = "ee1c8270096a728966ae38af548047d1f64c18318e06ba75952e657136f02537",
+ sha_mac = "574a5819308eba6c8be6a780e26dff415a0e7178d3f44162dd8dca87eb40d4a7",
+ sha_win = "242d244f4f5f5af08e6e6ac9c143aebf1b7bb2a23fd2992350731e59acfee07c",
+ ),
+ "2.0.29": struct(
+ hash = "c2369dc425725fff86ba90a9007a4603ddf7941b",
+ sha_linux = "7df4a8f3e25820becadfa7f1fe0d78e764102ec3ee50c474ca1634ed90d48890",
+ sha_mac = "d998521ba95882a27792f0113ea2c972fbb891c240649f4c994f0260c0e1a213",
+ sha_win = "c64aa3f2af6503f6711b2322986a45784e00d7c7fe13ec3f5c4f740472d065a0",
+ ),
+ "2.0.28": struct(
+ hash = "866055ea639d64dfedc625d28ec981e47ce37168",
+ sha_linux = "7dca7704eb14e367bb67e9abc9eaf59e75f59b74e32422e04556de10897a9a86",
+ sha_mac = "370f76493e3805e2538290b698a381f04b6d78a77771e48fc0099cf89dad985f",
+ sha_win = "e913c50ea5f196d36971f7cf5b1cf9a9ca27ce0818aba56be3a66e31e95c0e5b",
+ ),
+ "2.0.27": struct(
+ hash = "1ac46e3b84955231ab4a4f4cbe0c7ac28c86b8cc",
+ sha_linux = "3e124e278de168cf22e03b93b2f14a65a86777e428cdaab7e5e1c2289eb41605",
+ sha_mac = "388262b9e1042ef9a3a1945d5a23dcd634c8042a225e8fdf80bcc2c1cb7e05cc",
+ sha_win = "762276a332432e717afb988310d21ae10e36facc1e05bfd77042a364fb43cc3c",
+ ),
+ "2.0.26": struct(
+ hash = "823d37b15d1ab61bc9ac0665ceef6951d3703842",
+ sha_linux = "996e16d368a99dd4dd12126acbcb8bea9a607b5257cc7b747c4afc2f036fd8cf",
+ sha_mac = "8b2d7e84cc449531e88034beb31da89a0b61ccaeaa1584ffb6da7842c6348fdc",
+ sha_win = "095e772764d7f8c0f8228bda4b8500ae43aac2303567da5cdc9f8623f70a5743",
+ ),
+ "2.0.25": struct(
+ hash = "f6f001b08fbb67935379cf13d17fd9bfdbaff791",
+ sha_linux = "06d8e2f3d4f4b35a57de9c15e62a559c941cfba1dd7ec02353d815904d912c3b",
+ sha_mac = "6541bf3a648aae7df84de424ff392dd1513ab5450203c84f72a6a03e321a301b",
+ sha_win = "267fbfa809ec0eb911c1962b1b9768675cb82228e694a5f9ef570232ee71db76",
+ ),
+ "2.0.24": struct(
+ hash = "6ab7fc5622a67e6111d07c4ba61c8d3c8fc33ed2",
+ sha_linux = "e5daa0e87f3afd2197e7975297cb0cd4c245edccb964ca5f1f32ee7d985bf440",
+ sha_mac = "e4b7f2a7b71d6ac4610ee7b14743570e0dfba3668dc6b4f984cbe7a135888527",
+ sha_win = "db2aad422a3ca2295be6101b0151eeee55dcea29ba1f31b4594c02ba46591cbe",
+ ),
+ "2.0.23": struct(
+ hash = "77b065ace39e6ab21446e13f92897f956c80476a",
+ sha_linux = "7713a9a5572d839aea9eaa84a7c4779d11c6c8818ee64a0f443b62081fae6d47",
+ sha_mac = "b793087462d581e25c8c267fca9d30519619e3272480862a56cc316a32c7afab",
+ sha_win = "b8885cbb41a39e4734861462e05ee58c7ff7562016a842bcee2603f229940e8b",
+ ),
+ "2.0.22": struct(
+ hash = "6465a9acb820207acf7da44661a7de52d0a1ae3c",
+ sha_linux = "c079781124e763c53c9fc73781fcee40296ce3314276836bc694f07bd331a859",
+ sha_mac = "ab95574dfc685b0300e37bea36aba413045bbfa2ab06b93eceb881670489eec1",
+ sha_win = "ba142e7e380596cba763e3a414de6511bcb86de48e4b48cf393b1ea449a24aaa",
+ ),
+ "2.0.21": struct(
+ hash = "72f4ec97fbc7ec16c15ae68a75b0a257b2835160",
+ sha_linux = "741264f33f96ba4b785ed0b133861ebdfefbaefab76ddcfe7bde6522829d6f70",
+ sha_mac = "b07c0d65ee7e2799170c6f3b2aacebfe070c2e4975088bcd1b3a4140fecd8418",
+ sha_win = "dc3cbf47aa4be52a92526f1790a013734ecbd407f7f36286ed0283c96355999a",
+ ),
+ "2.0.20": struct(
+ hash = "e0c15cd14170f407a9eb27fcbad22931dc67feb7",
+ sha_linux = "a196504fd1095836ca3961208338ff9e292be7729ea529bc19800aa7c966d34a",
+ sha_mac = "6cdbf17ed61486b38ea79d3f31d74483e7388d1e7468518dccba3f24e0ddd4c4",
+ sha_win = "4d22a32c219dbe18c55b635d014b9eaf7da60536171b7af37d9a8099fd33794b",
+ ),
+ "2.0.19": struct(
+ hash = "9b9ff2dabfb4a7fbacbc004c0bead12a60f9d05c",
+ sha_linux = "bd7c2a38ac88d219a1ab5003ddbf8fdc66a6ba55bc69f99077346edf2753b4ea",
+ sha_mac = "6cc44029c9052855a55938eb6496b5659da4b1ce9cb34502b740af5993a94f93",
+ sha_win = "a1fa8b1c387b9307f9b87c43dc83c0ff1bc04b9f29fbe4f39aff2dd946ca4b70",
+ ),
+ "2.0.18": struct(
+ hash = "c2ac7520fad29a7937ed60ab6a95b08eb374c7ba",
+ sha_linux = "e9f777de592f606b10104b2efe5179a7a8f44e3a9dffa1e3aaf73e05eb8893d7",
+ sha_mac = "86b1dd62e424e3788bf132292a694a25ca9b0875d06f50d0f5d424593697452c",
+ sha_win = "49ce07bda6be070251db44a08fcc05cae21ffdbd7522423a0c79bde635e87e28",
+ ),
+ "2.0.17": struct(
+ hash = "f5c45e60392b82f603e3a8039c62db294fab02d2",
+ sha_linux = "b40a4874057e4cace600f8ee9787dcbe236e3dc5b2fff5c2ecb0e867e426f99c",
+ sha_mac = "081f61abf7d5ac0ec31aaffc5550013d4093ea4ea39520b7a32b7448d2a6ee70",
+ sha_win = "45d06e597e6a1185a76200bd0481495e7298800a4805045d9cdbcce6311c91b2",
+ ),
+ "2.0.16": struct(
+ hash = "80d9674f2fafa6b9346d735c42d5c52b8cc8aa8e",
+ sha_linux = "e527638b224d9a30dc7e5fa4b9bd2eb2ab76ad306739ba8cacf5a5e333933a2a",
+ sha_mac = "061020eb0e3ee0611dc5a0008ccc7778168a4f838d49ca41c0aad8c52c1a01c9",
+ sha_win = "99364ed0388f928e0594f790662bf3a30c2894b0eff81797e1b64f62128561cb",
+ ),
+ "2.0.15": struct(
+ hash = "89202930a98fe7f9ed59b574469a9471b0bda7dd",
+ sha_linux = "7ff49fc63adf29970f6e7af1df445d7f554bdbbb2606db1cb5d3567ce69df1db",
+ sha_mac = "e35cced1514ad0da40584f8dd6f76aabf847ce0fa82c6dc8dd9442fb74ed6d0d",
+ sha_win = "31d5f8107c87833cea57edc57613bba4b36b16152772f744c5ad204594b4e666",
+ ),
+ "2.0.14": struct(
+ hash = "fc5562126762ab26c4757147a3b4c24e85a7289e",
+ sha_linux = "e466cd47ddd4bf0acd645412fdf08eda6d232484e48e5a2643e08062a7a4cf56",
+ sha_mac = "1c554c08459b7025638ca4eddba0d35babe8c26b202a70a74e9442d577896211",
+ sha_win = "428bc6094671937af96f26d803871fc5cd83d4d2b1c1df45fa6873a9bc5cac51",
+ ),
+ "2.0.13": struct(
+ hash = "ce0e4a4d1cab395ee5082a60ebb4f3891a94b256",
+ sha_linux = "8986ed886e111c661099c5147126b8a379a4040aab6a1f572fe01f0f9b99a343",
+ sha_mac = "88c91332c8c76fed14ebf0edc9a08f586012f54f04ad61e5b1b6d02bf96bdeab",
+ sha_win = "9fb3b945b7bd56e34d17ec04de4cce475f26c49d161aee9d9c0b8b1434591f88",
+ ),
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/.bazelrc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/.bazelrc
new file mode 100644
index 0000000000..fbd75a7ea7
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/.bazelrc
@@ -0,0 +1 @@
+build --incompatible_enable_cc_toolchain_resolution
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/.gitignore b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/.gitignore
new file mode 100644
index 0000000000..3e67f7873e
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/.gitignore
@@ -0,0 +1,4 @@
+bazel-bin
+bazel-out
+bazel-test_external
+bazel-testlogs
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/BUILD b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/BUILD
new file mode 100644
index 0000000000..e3a8e9e645
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/BUILD
@@ -0,0 +1,66 @@
+load("@emsdk//emscripten_toolchain:wasm_rules.bzl", "wasm_cc_binary")
+
+cc_binary(
+ name = "hello-world",
+ srcs = ["hello-world.cc"],
+)
+
+wasm_cc_binary(
+ name = "hello-world-wasm",
+ cc_target = ":hello-world",
+ outputs = [
+ "hello-world.js",
+ "hello-world.wasm",
+ ],
+)
+
+BASE_LINKOPTS = [
+ "--bind", # Enable embind
+ "-sMODULARIZE",
+ "--pre-js",
+ "hello-embind-interface.js",
+]
+
+RELEASE_OPTS = [
+ "--closure=1", # Run the closure compiler
+ # Tell closure about the externs file, so as not to minify our JS public API.
+ "--closure-args=--externs=$(location hello-embind-externs.js)"
+]
+
+DEBUG_OPTS = [
+ "--closure=0", # Do not use closure
+]
+
+config_setting(
+ name = "release_opts",
+ values = {"compilation_mode": "opt"},
+)
+
+config_setting(
+ name = "debug_opts",
+ values = {"compilation_mode": "dbg"},
+)
+
+cc_binary(
+ name = "hello-embind",
+ srcs = ["hello-embind.cc"],
+ features = ["emcc_debug_link"],
+ additional_linker_inputs = [
+ "hello-embind-externs.js",
+ "hello-embind-interface.js",
+ ],
+ linkopts = select({
+ ":debug_opts": BASE_LINKOPTS + DEBUG_OPTS,
+ ":release_opts": BASE_LINKOPTS + RELEASE_OPTS,
+ "//conditions:default": BASE_LINKOPTS + RELEASE_OPTS,
+ }),
+ # This target won't build successfully on its own because of missing emscripten
+ # headers etc. Therefore, we hide it from wildcards.
+ tags = ["manual"],
+)
+
+wasm_cc_binary(
+ name = "hello-embind-wasm",
+ cc_target = ":hello-embind",
+)
+
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/MODULE.bazel b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/MODULE.bazel
new file mode 100644
index 0000000000..78fdaeb7da
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/MODULE.bazel
@@ -0,0 +1,6 @@
+bazel_dep(name = "rules_cc", version = "0.1.1")
+bazel_dep(name = "emsdk")
+local_path_override(
+ module_name = "emsdk",
+ path = "..",
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/MODULE.bazel.lock b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/MODULE.bazel.lock
new file mode 100644
index 0000000000..f3742587c3
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/MODULE.bazel.lock
@@ -0,0 +1,3696 @@
+{
+ "lockFileVersion": 18,
+ "registryFileHashes": {
+ "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+ "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/MODULE.bazel": "e4529e12d8cd5b828e2b5960d07d3ec032541740d419d7d5b859cabbf5b056f9",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/source.json": "80cb66069ad626e0921555cd2bf278286fd7763fae2450e564e351792e8303f4",
+ "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/MODULE.bazel": "f19e6b4a16f77f8cf3728eac1f60dbfd8e043517fd4f4dbf17a75a6c50936d62",
+ "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/source.json": "abbb3eac3b6af76b8ce230a9a901c6d08d93f4f5ffd55314bf630827dddee57e",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+ "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+ "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/source.json": "3e8379efaaef53ce35b7b8ba419df829315a880cb0a030e5bb45c96d6d5ecb5f",
+ "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
+ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+ "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
+ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
+ "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+ "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+ "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+ "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+ "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+ "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+ "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+ "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
+ "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
+ "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
+ "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c",
+ "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
+ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+ "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+ "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
+ "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
+ "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+ "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+ "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+ "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
+ "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
+ "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960",
+ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
+ "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+ "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/MODULE.bazel": "6bc03c8f37f69401b888023bf511cb6ee4781433b0cb56236b2e55a21e3a026a",
+ "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/MODULE.bazel": "42e8d5254b6135f890fecca7c8d7f95a7d27a45f8275b276f66ec337767530ef",
+ "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/source.json": "80e0a68eb81772f1631f8b69014884eebc2474b3b3025fd19a5240ae4f76f9c9",
+ "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
+ "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+ "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
+ "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+ "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+ "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/source.json": "25932f917cd279c7baefa6cb1d3fa8750a7a29de522024449b19af6eab51f4a0",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
+ "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+ "https://bcr.bazel.build/modules/stardoc/0.5.4/MODULE.bazel": "6569966df04610b8520957cb8e97cf2e9faac2c0309657c537ab51c16c18a2a4",
+ "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
+ "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+ "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d",
+ "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+ },
+ "selectedYankedVersions": {},
+ "moduleExtensions": {
+ "@@aspect_bazel_lib+//lib:extensions.bzl%toolchains": {
+ "general": {
+ "bzlTransitiveDigest": "nrCBrZBQH3Dq30TXMpPMV6lWpEDozX0S0kCia4Lrpj0=",
+ "usagesDigest": "1c7PNX163TGNqWzfejRnWpH/hiT4/GRG0kYxuez0Uz0=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "copy_directory_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "copy_directory_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "copy_directory_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "copy_directory_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "copy_directory_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "copy_directory_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "copy_directory_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "copy_directory"
+ }
+ },
+ "copy_to_directory_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "copy_to_directory_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "copy_to_directory_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "copy_to_directory_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "copy_to_directory_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "copy_to_directory_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "copy_to_directory_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "copy_to_directory"
+ }
+ },
+ "jq_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "1.6"
+ }
+ },
+ "jq_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_host_alias_repo",
+ "attributes": {}
+ },
+ "jq_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "jq"
+ }
+ },
+ "yq_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_s390x": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_s390x",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_ppc64le": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_ppc64le",
+ "version": "4.25.2"
+ }
+ },
+ "yq_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_host_alias_repo",
+ "attributes": {}
+ },
+ "yq_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "yq"
+ }
+ },
+ "coreutils_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "coreutils"
+ }
+ },
+ "bsd_tar_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "bsd_tar_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "bsd_tar_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "bsd_tar_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "bsd_tar_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "bsd_tar_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%tar_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "bsd_tar"
+ }
+ },
+ "expand_template_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "expand_template_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "expand_template_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "expand_template_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "expand_template_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "expand_template_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "expand_template_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "expand_template"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "aspect_bazel_lib+",
+ "aspect_bazel_lib",
+ "aspect_bazel_lib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@aspect_rules_js+//npm:extensions.bzl%pnpm": {
+ "general": {
+ "bzlTransitiveDigest": "poAa/2uyrVSr9Hel1HD6GfFwqId27yXfePnG+3Dmt90=",
+ "usagesDigest": "yxkJioaKxOYkZAdkGoq2Cm79s4pW36Xwx7a8awQOU2E=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "pnpm": {
+ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_rule",
+ "attributes": {
+ "package": "pnpm",
+ "version": "8.6.7",
+ "root_package": "",
+ "link_workspace": "",
+ "link_packages": {},
+ "integrity": "sha512-vRIWpD/L4phf9Bk2o/O2TDR8fFoJnpYrp2TKqTIZF/qZ2/rgL3qKXzHofHgbXsinwMoSEigz28sqk3pQ+yMEQQ==",
+ "url": "",
+ "commit": "",
+ "patch_args": [
+ "-p0"
+ ],
+ "patches": [],
+ "custom_postinstall": "",
+ "npm_auth": "",
+ "npm_auth_basic": "",
+ "npm_auth_username": "",
+ "npm_auth_password": "",
+ "lifecycle_hooks": [],
+ "extra_build_content": "load(\"@aspect_rules_js//js:defs.bzl\", \"js_binary\")\njs_binary(name = \"pnpm\", data = glob([\"package/**\"]), entry_point = \"package/dist/pnpm.cjs\", visibility = [\"//visibility:public\"])",
+ "generate_bzl_library_targets": false,
+ "extract_full_archive": true
+ }
+ },
+ "pnpm__links": {
+ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_links",
+ "attributes": {
+ "package": "pnpm",
+ "version": "8.6.7",
+ "dev": false,
+ "root_package": "",
+ "link_packages": {},
+ "deps": {},
+ "transitive_closure": {},
+ "lifecycle_build_target": false,
+ "lifecycle_hooks_env": [],
+ "lifecycle_hooks_execution_requirements": [
+ "no-sandbox"
+ ],
+ "lifecycle_hooks_use_default_shell_env": false,
+ "bins": {},
+ "package_visibility": [
+ "//visibility:public"
+ ],
+ "replace_package": ""
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "aspect_bazel_lib+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "aspect_rules_js+",
+ "aspect_bazel_lib",
+ "aspect_bazel_lib+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_features",
+ "bazel_features+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_globals",
+ "bazel_features++version_extension+bazel_features_globals"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_version",
+ "bazel_features++version_extension+bazel_features_version"
+ ],
+ [
+ "bazel_features+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@emsdk+//:emscripten_cache.bzl%emscripten_cache": {
+ "general": {
+ "bzlTransitiveDigest": "uqDvXmpTNqW4+ie/Fk+xC3TrFrKvL+9hNtoP51Kt2oo=",
+ "usagesDigest": "d45w3mu98tmYO95D//utIzVG+p8OPeGUpN0TgQMnLHA=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "emscripten_cache": {
+ "repoRuleId": "@@emsdk+//:emscripten_cache.bzl%_emscripten_cache_repository",
+ "attributes": {
+ "configuration": [],
+ "targets": []
+ }
+ }
+ },
+ "recordedRepoMappingEntries": []
+ }
+ },
+ "@@emsdk+//:emscripten_deps.bzl%emscripten_deps": {
+ "general": {
+ "bzlTransitiveDigest": "h0wQ3PSRx/Q9n+izTifYO8L728OTd9B5YbLOWcobVYE=",
+ "usagesDigest": "eqaMlu1tts7n29bG5zUl3DtA/9ARE+6aHrSK4X7kNno=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "emscripten_bin_linux": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "27fc220a9ad98d323cad73531ff563e9838c9e1205f51ee2a5632bb4266a35d2",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.tar.xz"
+ }
+ },
+ "emscripten_bin_linux_arm64": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "2d03f8eb3f81dd94821658eefbb442a92b0b7601f4cfb08590590fd7bc467ef8",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries-arm64.tar.xz"
+ }
+ },
+ "emscripten_bin_mac": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "c06048915595726fc2e2da6a8db3134581a6287645fb818802a9734ff9785e77",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.tar.xz"
+ }
+ },
+ "emscripten_bin_mac_arm64": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "35d743453d0f91857b09f00d721037bb46753aaeae373bd7f64746338db11770",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries-arm64.tar.xz"
+ }
+ },
+ "emscripten_bin_win": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang.exe\",\n \"bin/clang++.exe\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang.exe\",\n \"bin/llvm-ar.exe\",\n \"bin/llvm-dwarfdump.exe\",\n \"bin/llvm-nm.exe\",\n \"bin/llvm-objcopy.exe\",\n \"bin/wasm-ctor-eval.exe\",\n \"bin/wasm-emscripten-finalize.exe\",\n \"bin/wasm-ld.exe\",\n \"bin/wasm-metadce.exe\",\n \"bin/wasm-opt.exe\",\n \"bin/wasm-split.exe\",\n \"bin/wasm2js.exe\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar.exe\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "3b576e825b26426bb72854ed98752df3fcb58cc3ab1dc116566e328b79a8abb3",
+ "strip_prefix": "install",
+ "type": "zip",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.zip"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "bazel_tools",
+ "rules_cc",
+ "rules_cc+"
+ ],
+ [
+ "emsdk+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@pybind11_bazel+//:python_configure.bzl%extension": {
+ "general": {
+ "bzlTransitiveDigest": "d4N/SZrl3ONcmzE98rcV0Fsro0iUbjNQFTIiLiGuH+k=",
+ "usagesDigest": "fycyB39YnXIJkfWCIXLUKJMZzANcuLy9ZE73hRucjFk=",
+ "recordedFileInputs": {
+ "@@pybind11_bazel+//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e"
+ },
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "local_config_python": {
+ "repoRuleId": "@@pybind11_bazel+//:python_configure.bzl%python_configure",
+ "attributes": {}
+ },
+ "pybind11": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file": "@@pybind11_bazel+//:pybind11.BUILD",
+ "strip_prefix": "pybind11-2.11.1",
+ "urls": [
+ "https://github.com/pybind/pybind11/archive/v2.11.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "pybind11_bazel+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_fuzzing+//fuzzing/private:extensions.bzl%non_module_dependencies": {
+ "general": {
+ "bzlTransitiveDigest": "mGiTB79hRNjmeDTQdzkpCHyzXhErMbufeAmySBt7s5s=",
+ "usagesDigest": "wy6ISK6UOcBEjj/mvJ/S3WeXoO67X+1llb9yPyFtPgc=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "platforms": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "urls": [
+ "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz",
+ "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz"
+ ],
+ "sha256": "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74"
+ }
+ },
+ "rules_python": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8",
+ "strip_prefix": "rules_python-0.28.0",
+ "url": "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz"
+ }
+ },
+ "bazel_skylib": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
+ "urls": [
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
+ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"
+ ]
+ }
+ },
+ "com_google_absl": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "urls": [
+ "https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.1.zip"
+ ],
+ "strip_prefix": "abseil-cpp-20240116.1",
+ "integrity": "sha256-7capMWOvWyoYbUaHF/b+I2U6XLMaHmky8KugWvfXYuk="
+ }
+ },
+ "rules_fuzzing_oss_fuzz": {
+ "repoRuleId": "@@rules_fuzzing+//fuzzing/private/oss_fuzz:repository.bzl%oss_fuzz_repository",
+ "attributes": {}
+ },
+ "honggfuzz": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file": "@@rules_fuzzing+//:honggfuzz.BUILD",
+ "sha256": "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e",
+ "url": "https://github.com/google/honggfuzz/archive/2.5.zip",
+ "strip_prefix": "honggfuzz-2.5"
+ }
+ },
+ "rules_fuzzing_jazzer": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar",
+ "attributes": {
+ "sha256": "ee6feb569d88962d59cb59e8a31eb9d007c82683f3ebc64955fd5b96f277eec2",
+ "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer/0.20.1/jazzer-0.20.1.jar"
+ }
+ },
+ "rules_fuzzing_jazzer_api": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar",
+ "attributes": {
+ "sha256": "f5a60242bc408f7fa20fccf10d6c5c5ea1fcb3c6f44642fec5af88373ae7aa1b",
+ "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer-api/0.20.1/jazzer-api-0.20.1.jar"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_fuzzing+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": {
+ "general": {
+ "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=",
+ "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "compatibility_proxy": {
+ "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule",
+ "attributes": {}
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_java+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
+ "general": {
+ "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=",
+ "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "com_github_jetbrains_kotlin_git": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
+ ],
+ "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
+ }
+ },
+ "com_github_jetbrains_kotlin": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
+ "attributes": {
+ "git_repository_name": "com_github_jetbrains_kotlin_git",
+ "compiler_version": "1.9.23"
+ }
+ },
+ "com_github_google_ksp": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
+ ],
+ "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
+ "strip_version": "1.9.23-1.0.20"
+ }
+ },
+ "com_github_pinterest_ktlint": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
+ "attributes": {
+ "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
+ "urls": [
+ "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
+ ],
+ "executable": true
+ }
+ },
+ "rules_android": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
+ "strip_prefix": "rules_android-0.1.1",
+ "urls": [
+ "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_kotlin+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_nodejs+//nodejs:extensions.bzl%node": {
+ "general": {
+ "bzlTransitiveDigest": "rphcryfYrOY/P3emfTskC/GY5YuHcwMl2B2ncjaM8lY=",
+ "usagesDigest": "m7d0VXcsX/qS6DKMUBtdgjQzP2eMRHqsE4wv7dzr71I=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "nodejs_linux_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_amd64"
+ }
+ },
+ "nodejs_linux_arm64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_arm64"
+ }
+ },
+ "nodejs_linux_s390x": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_s390x"
+ }
+ },
+ "nodejs_linux_ppc64le": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_ppc64le"
+ }
+ },
+ "nodejs_darwin_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "darwin_amd64"
+ }
+ },
+ "nodejs_darwin_arm64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "darwin_arm64"
+ }
+ },
+ "nodejs_windows_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "windows_amd64"
+ }
+ },
+ "nodejs": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ },
+ "nodejs_host": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ },
+ "nodejs_toolchains": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_toolchains_repo.bzl%nodejs_toolchains_repo",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": []
+ }
+ },
+ "@@rules_python+//python/extensions:pip.bzl%pip": {
+ "general": {
+ "bzlTransitiveDigest": "Jbed6zJUJ6E78XRyOlnG1ryhBDvVeikdntPW1D40S/E=",
+ "usagesDigest": "fztm9ST3ki9E77tct2ZwJe0w38LvfMY8mRYp+YHxXQE=",
+ "recordedFileInputs": {
+ "@@protobuf+//python/requirements.txt": "983be60d3cec4b319dcab6d48aeb3f5b2f7c3350f26b3a9e97486c37967c73c5",
+ "@@rules_fuzzing+//fuzzing/requirements.txt": "ab04664be026b632a0d2a2446c4f65982b7654f5b6851d2f9d399a19b7242a5b",
+ "@@rules_python+//tools/publish/requirements_darwin.txt": "095d4a4f3d639dce831cd493367631cd51b53665292ab20194bac2c0c6458fa8",
+ "@@rules_python+//tools/publish/requirements_linux.txt": "d576e0d8542df61396a9b38deeaa183c24135ed5e8e73bb9622f298f2671811e",
+ "@@rules_python+//tools/publish/requirements_windows.txt": "d18538a3982beab378fd5687f4db33162ee1ece69801f9a451661b1b64286b76"
+ },
+ "recordedDirentsInputs": {},
+ "envVariables": {
+ "RULES_PYTHON_REPO_DEBUG": null,
+ "RULES_PYTHON_REPO_DEBUG_VERBOSITY": null
+ },
+ "generatedRepoSpecs": {
+ "pip_deps_310_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "pip_deps_310",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_310_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "pip_deps_310",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_311_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "pip_deps_311",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_311_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "pip_deps_311",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_312_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "pip_deps_312",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_312_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "pip_deps_312",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_38_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "pip_deps_38",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_38_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "pip_deps_38",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_39_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "pip_deps_39",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_39_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "pip_deps_39",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "rules_fuzzing_py_deps_310_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "rules_fuzzing_py_deps_310",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_310_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "rules_fuzzing_py_deps_310",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_311_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_fuzzing_py_deps_311",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_311_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_fuzzing_py_deps_311",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_312_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "rules_fuzzing_py_deps_312",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_312_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "rules_fuzzing_py_deps_312",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_38_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "rules_fuzzing_py_deps_38",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_38_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "rules_fuzzing_py_deps_38",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_39_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "rules_fuzzing_py_deps_39",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_39_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "rules_fuzzing_py_deps_39",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "backports.tarfile-1.2.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "backports-tarfile==1.2.0",
+ "sha256": "77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "backports_tarfile-1.2.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "backports-tarfile==1.2.0",
+ "sha256": "d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991",
+ "urls": [
+ "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_certifi_py3_none_any_922820b5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "certifi-2024.8.30-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "certifi==2024.8.30",
+ "sha256": "922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_certifi_sdist_bec941d2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "certifi-2024.8.30.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "certifi==2024.8.30",
+ "sha256": "bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_sdist_1c39c601": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "cffi-1.17.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824",
+ "urls": [
+ "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944",
+ "urls": [
+ "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee",
+ "urls": [
+ "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea",
+ "urls": [
+ "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc",
+ "urls": [
+ "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27",
+ "urls": [
+ "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079",
+ "urls": [
+ "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_sdist_223217c3": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "charset_normalizer-3.4.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7",
+ "urls": [
+ "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16",
+ "urls": [
+ "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_sdist_315b9001": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "cryptography-43.0.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805",
+ "urls": [
+ "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "docutils-0.21.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "docutils==0.21.2",
+ "sha256": "dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_docutils_sdist_3a6b1873": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "docutils-0.21.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "docutils==0.21.2",
+ "sha256": "3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_idna_py3_none_any_946d195a": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "idna-3.10-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "idna==3.10",
+ "sha256": "946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3",
+ "urls": [
+ "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_idna_sdist_12f65c9b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "idna-3.10.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "idna==3.10",
+ "sha256": "12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "importlib_metadata-8.5.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "importlib-metadata==8.5.0",
+ "sha256": "45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_importlib_metadata_sdist_71522656": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "importlib_metadata-8.5.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "importlib-metadata==8.5.0",
+ "sha256": "71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7",
+ "urls": [
+ "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.classes-3.4.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-classes==3.4.0",
+ "sha256": "f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790",
+ "urls": [
+ "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco.classes-3.4.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-classes==3.4.0",
+ "sha256": "47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd",
+ "urls": [
+ "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.context-6.0.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-context==6.0.1",
+ "sha256": "f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco_context-6.0.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-context==6.0.1",
+ "sha256": "9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3",
+ "urls": [
+ "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.functools-4.1.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-functools==4.1.0",
+ "sha256": "ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649",
+ "urls": [
+ "https://files.pythonhosted.org/packages/9f/4f/24b319316142c44283d7540e76c7b5a6dbd5db623abd86bb7b3491c21018/jaraco.functools-4.1.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco_functools-4.1.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-functools==4.1.0",
+ "sha256": "70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ab/23/9894b3df5d0a6eb44611c36aec777823fc2e07740dabbd0b810e19594013/jaraco_functools-4.1.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "jeepney-0.8.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jeepney==0.8.0",
+ "sha256": "c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ae/72/2a1e2290f1ab1e06f71f3d0f1646c9e4634e70e1d37491535e19266e8dc9/jeepney-0.8.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jeepney_sdist_5efe48d2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jeepney-0.8.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jeepney==0.8.0",
+ "sha256": "5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d6/f4/154cf374c2daf2020e05c3c6a03c91348d59b23c5366e968feb198306fdf/jeepney-0.8.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_keyring_py3_none_any_5426f817": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "keyring-25.4.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "keyring==25.4.1",
+ "sha256": "5426f817cf7f6f007ba5ec722b1bcad95a75b27d780343772ad76b17cb47b0bf",
+ "urls": [
+ "https://files.pythonhosted.org/packages/83/25/e6d59e5f0a0508d0dca8bb98c7f7fd3772fc943ac3f53d5ab18a218d32c0/keyring-25.4.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_keyring_sdist_b07ebc55": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "keyring-25.4.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "keyring==25.4.1",
+ "sha256": "b07ebc55f3e8ed86ac81dd31ef14e81ace9dd9c3d4b5d77a6e9a2016d0d71a1b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a5/1c/2bdbcfd5d59dc6274ffb175bc29aa07ecbfab196830e0cfbde7bd861a2ea/keyring-25.4.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "markdown_it_py-3.0.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "markdown-it-py==3.0.0",
+ "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1",
+ "urls": [
+ "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "markdown-it-py-3.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "markdown-it-py==3.0.0",
+ "sha256": "e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb",
+ "urls": [
+ "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_mdurl_py3_none_any_84008a41": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "mdurl-0.1.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "mdurl==0.1.2",
+ "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_mdurl_sdist_bb413d29": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "mdurl-0.1.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "mdurl==0.1.2",
+ "sha256": "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "more_itertools-10.5.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "more-itertools==10.5.0",
+ "sha256": "037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef",
+ "urls": [
+ "https://files.pythonhosted.org/packages/48/7e/3a64597054a70f7c86eb0a7d4fc315b8c1ab932f64883a297bdffeb5f967/more_itertools-10.5.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_more_itertools_sdist_5482bfef": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "more-itertools-10.5.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "more-itertools==10.5.0",
+ "sha256": "5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/51/78/65922308c4248e0eb08ebcbe67c95d48615cc6f27854b6f2e57143e9178f/more-itertools-10.5.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "14c5a72e9fe82aea5fe3072116ad4661af5cf8e8ff8fc5ad3450f123e4925e86",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b3/89/1daff5d9ba5a95a157c092c7c5f39b8dd2b1ddb4559966f808d31cfb67e0/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "7b7c2a3c9eb1a827d42539aa64091640bd275b81e097cd1d8d82ef91ffa2e811",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2c/b6/42fc3c69cabf86b6b81e4c051a9b6e249c5ba9f8155590222c2622961f58/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "42c64511469005058cd17cc1537578eac40ae9f7200bedcfd1fc1a05f4f8c200",
+ "urls": [
+ "https://files.pythonhosted.org/packages/45/b9/833f385403abaf0023c6547389ec7a7acf141ddd9d1f21573723a6eab39a/nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "0411beb0589eacb6734f28d5497ca2ed379eafab8ad8c84b31bb5c34072b7164",
+ "urls": [
+ "https://files.pythonhosted.org/packages/05/2b/85977d9e11713b5747595ee61f381bc820749daf83f07b90b6c9964cf932/nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "5f36b271dae35c465ef5e9090e1fdaba4a60a56f0bb0ba03e0932a66f28b9189",
+ "urls": [
+ "https://files.pythonhosted.org/packages/72/f2/5c894d5265ab80a97c68ca36f25c8f6f0308abac649aaf152b74e7e854a8/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "19aaba96e0f795bd0a6c56291495ff59364f4300d4a39b29a0abc9cb3774a84b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/c2/a8/3bb02d0c60a03ad3a112b76c46971e9480efa98a8946677b5a59f60130ca/nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "de3ceed6e661954871d6cd78b410213bdcb136f79aafe22aa7182e028b8c7307",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1b/63/6ab90d0e5225ab9780f6c9fb52254fa36b52bb7c188df9201d05b647e5e1/nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "f0eca9ca8628dbb4e916ae2491d72957fdd35f7a5d326b7032a345f111ac07fe",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a3/da/0c4e282bc3cff4a0adf37005fa1fb42257673fbc1bbf7d1ff639ec3d255a/nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "3a157ab149e591bb638a55c8c6bcb8cdb559c8b12c13a8affaba6cedfe51713a",
+ "urls": [
+ "https://files.pythonhosted.org/packages/de/81/c291231463d21da5f8bba82c8167a6d6893cc5419b0639801ee5d3aeb8a9/nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "36c95d4b70530b320b365659bb5034341316e6a9b30f0b25fa9c9eff4c27a204",
+ "urls": [
+ "https://files.pythonhosted.org/packages/eb/61/73a007c74c37895fdf66e0edcd881f5eaa17a348ff02f4bb4bc906d61085/nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-win_amd64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "8ce0f819d2f1933953fca255db2471ad58184a60508f03e6285e5114b6254844",
+ "urls": [
+ "https://files.pythonhosted.org/packages/26/8d/53c5b19c4999bdc6ba95f246f4ef35ca83d7d7423e5e38be43ad66544e5d/nh3-0.2.18-cp37-abi3-win_amd64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_sdist_94a16692": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "nh3-0.2.18.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "94a166927e53972a9698af9542ace4e38b9de50c34352b962f4d9a7d4c927af4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/73/10df50b42ddb547a907deeb2f3c9823022580a7a47281e8eae8e003a9639/nh3-0.2.18.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pkginfo-1.10.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pkginfo==1.10.0",
+ "sha256": "889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097",
+ "urls": [
+ "https://files.pythonhosted.org/packages/56/09/054aea9b7534a15ad38a363a2bd974c20646ab1582a387a95b8df1bfea1c/pkginfo-1.10.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pkginfo_sdist_5df73835": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pkginfo-1.10.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pkginfo==1.10.0",
+ "sha256": "5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2f/72/347ec5be4adc85c182ed2823d8d1c7b51e13b9a6b0c1aae59582eca652df/pkginfo-1.10.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "pycparser-2.22-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pycparser==2.22",
+ "sha256": "c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc",
+ "urls": [
+ "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pycparser_sdist_491c8be9": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pycparser-2.22.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pycparser==2.22",
+ "sha256": "491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pygments-2.18.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pygments==2.18.0",
+ "sha256": "b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pygments_sdist_786ff802": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pygments-2.18.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pygments==2.18.0",
+ "sha256": "786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pywin32_ctypes-0.2.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pywin32-ctypes==0.2.3",
+ "sha256": "8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pywin32-ctypes-0.2.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pywin32-ctypes==0.2.3",
+ "sha256": "d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755",
+ "urls": [
+ "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "readme_renderer-44.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "readme-renderer==44.0",
+ "sha256": "2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151",
+ "urls": [
+ "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_readme_renderer_sdist_8712034e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "readme_renderer-44.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "readme-renderer==44.0",
+ "sha256": "8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1",
+ "urls": [
+ "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_py3_none_any_70761cfe": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "requests-2.32.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests==2.32.3",
+ "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_sdist_55365417": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "requests-2.32.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests==2.32.3",
+ "sha256": "55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
+ "urls": [
+ "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "requests_toolbelt-1.0.0-py2.py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests-toolbelt==1.0.0",
+ "sha256": "cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06",
+ "urls": [
+ "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "requests-toolbelt-1.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests-toolbelt==1.0.0",
+ "sha256": "7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "rfc3986-2.0.0-py2.py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rfc3986==2.0.0",
+ "sha256": "50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rfc3986_sdist_97aacf9d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "rfc3986-2.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rfc3986==2.0.0",
+ "sha256": "97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rich_py3_none_any_6049d5e6": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "rich-13.9.4-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rich==13.9.4",
+ "sha256": "6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90",
+ "urls": [
+ "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rich_sdist_43959497": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "rich-13.9.4.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rich==13.9.4",
+ "sha256": "439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "SecretStorage-3.3.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "secretstorage==3.3.3",
+ "sha256": "f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99",
+ "urls": [
+ "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_secretstorage_sdist_2403533e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "SecretStorage-3.3.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "secretstorage==3.3.3",
+ "sha256": "2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77",
+ "urls": [
+ "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_twine_py3_none_any_215dbe7b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "twine-5.1.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "twine==5.1.1",
+ "sha256": "215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997",
+ "urls": [
+ "https://files.pythonhosted.org/packages/5d/ec/00f9d5fd040ae29867355e559a94e9a8429225a0284a3f5f091a3878bfc0/twine-5.1.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_twine_sdist_9aa08251": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "twine-5.1.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "twine==5.1.1",
+ "sha256": "9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db",
+ "urls": [
+ "https://files.pythonhosted.org/packages/77/68/bd982e5e949ef8334e6f7dcf76ae40922a8750aa2e347291ae1477a4782b/twine-5.1.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "urllib3-2.2.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "urllib3==2.2.3",
+ "sha256": "ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_urllib3_sdist_e7d814a8": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "urllib3-2.2.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "urllib3==2.2.3",
+ "sha256": "e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_zipp_py3_none_any_a817ac80": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "zipp-3.20.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "zipp==3.20.2",
+ "sha256": "a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_zipp_sdist_bc9eb26f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "zipp-3.20.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "zipp==3.20.2",
+ "sha256": "bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29",
+ "urls": [
+ "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz"
+ ]
+ }
+ },
+ "pip_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "pip_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "numpy": "{\"pip_deps_310_numpy\":[{\"version\":\"3.10\"}],\"pip_deps_311_numpy\":[{\"version\":\"3.11\"}],\"pip_deps_312_numpy\":[{\"version\":\"3.12\"}],\"pip_deps_38_numpy\":[{\"version\":\"3.8\"}],\"pip_deps_39_numpy\":[{\"version\":\"3.9\"}]}",
+ "setuptools": "{\"pip_deps_310_setuptools\":[{\"version\":\"3.10\"}],\"pip_deps_311_setuptools\":[{\"version\":\"3.11\"}],\"pip_deps_312_setuptools\":[{\"version\":\"3.12\"}],\"pip_deps_38_setuptools\":[{\"version\":\"3.8\"}],\"pip_deps_39_setuptools\":[{\"version\":\"3.9\"}]}"
+ },
+ "packages": [
+ "numpy",
+ "setuptools"
+ ],
+ "groups": {}
+ }
+ },
+ "rules_fuzzing_py_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "rules_fuzzing_py_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "absl_py": "{\"rules_fuzzing_py_deps_310_absl_py\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_absl_py\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_absl_py\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_absl_py\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_absl_py\":[{\"version\":\"3.9\"}]}",
+ "six": "{\"rules_fuzzing_py_deps_310_six\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_six\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_six\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_six\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_six\":[{\"version\":\"3.9\"}]}"
+ },
+ "packages": [
+ "absl_py",
+ "six"
+ ],
+ "groups": {}
+ }
+ },
+ "rules_python_publish_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "rules_python_publish_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "backports_tarfile": "{\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\":[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\":[{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "certifi": "{\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\":[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_certifi_sdist_bec941d2\":[{\"filename\":\"certifi-2024.8.30.tar.gz\",\"version\":\"3.11\"}]}",
+ "cffi": "{\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_sdist_1c39c601\":[{\"filename\":\"cffi-1.17.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "charset_normalizer": "{\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\":[{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\":[{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "cryptography": "{\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_sdist_315b9001\":[{\"filename\":\"cryptography-43.0.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "docutils": "{\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\":[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\":[{\"filename\":\"docutils-0.21.2.tar.gz\",\"version\":\"3.11\"}]}",
+ "idna": "{\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\":[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_idna_sdist_12f65c9b\":[{\"filename\":\"idna-3.10.tar.gz\",\"version\":\"3.11\"}]}",
+ "importlib_metadata": "{\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\":[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\":[{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_classes": "{\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\":[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\":[{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_context": "{\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\":[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\":[{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_functools": "{\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\":[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\":[{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jeepney": "{\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\":[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\":[{\"filename\":\"jeepney-0.8.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "keyring": "{\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\":[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\":[{\"filename\":\"keyring-25.4.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "markdown_it_py": "{\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\":[{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\":[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "mdurl": "{\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\":[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\":[{\"filename\":\"mdurl-0.1.2.tar.gz\",\"version\":\"3.11\"}]}",
+ "more_itertools": "{\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\":[{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\":[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "nh3": "{\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_sdist_94a16692\":[{\"filename\":\"nh3-0.2.18.tar.gz\",\"version\":\"3.11\"}]}",
+ "pkginfo": "{\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\":[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\":[{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "pycparser": "{\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\":[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\":[{\"filename\":\"pycparser-2.22.tar.gz\",\"version\":\"3.11\"}]}",
+ "pygments": "{\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\":[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pygments_sdist_786ff802\":[{\"filename\":\"pygments-2.18.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "pywin32_ctypes": "{\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\":[{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\":[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "readme_renderer": "{\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\":[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\":[{\"filename\":\"readme_renderer-44.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "requests": "{\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\":[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_sdist_55365417\":[{\"filename\":\"requests-2.32.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "requests_toolbelt": "{\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\":[{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\":[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "rfc3986": "{\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\":[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\":[{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "rich": "{\"rules_python_publish_deps_311_rich_py3_none_any_6049d5e6\":[{\"filename\":\"rich-13.9.4-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rich_sdist_43959497\":[{\"filename\":\"rich-13.9.4.tar.gz\",\"version\":\"3.11\"}]}",
+ "secretstorage": "{\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\":[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\":[{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "twine": "{\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\":[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_twine_sdist_9aa08251\":[{\"filename\":\"twine-5.1.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "urllib3": "{\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\":[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\":[{\"filename\":\"urllib3-2.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "zipp": "{\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\":[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\":[{\"filename\":\"zipp-3.20.2.tar.gz\",\"version\":\"3.11\"}]}"
+ },
+ "packages": [
+ "backports_tarfile",
+ "certifi",
+ "charset_normalizer",
+ "docutils",
+ "idna",
+ "importlib_metadata",
+ "jaraco_classes",
+ "jaraco_context",
+ "jaraco_functools",
+ "keyring",
+ "markdown_it_py",
+ "mdurl",
+ "more_itertools",
+ "nh3",
+ "pkginfo",
+ "pygments",
+ "readme_renderer",
+ "requests",
+ "requests_toolbelt",
+ "rfc3986",
+ "rich",
+ "twine",
+ "urllib3",
+ "zipp"
+ ],
+ "groups": {}
+ }
+ }
+ },
+ "moduleExtensionMetadata": {
+ "useAllRepos": "NO",
+ "reproducible": false
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "bazel_features+",
+ "bazel_features_globals",
+ "bazel_features++version_extension+bazel_features_globals"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_version",
+ "bazel_features++version_extension+bazel_features_version"
+ ],
+ [
+ "rules_python+",
+ "bazel_features",
+ "bazel_features+"
+ ],
+ [
+ "rules_python+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "rules_python+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "rules_python+",
+ "pypi__build",
+ "rules_python++internal_deps+pypi__build"
+ ],
+ [
+ "rules_python+",
+ "pypi__click",
+ "rules_python++internal_deps+pypi__click"
+ ],
+ [
+ "rules_python+",
+ "pypi__colorama",
+ "rules_python++internal_deps+pypi__colorama"
+ ],
+ [
+ "rules_python+",
+ "pypi__importlib_metadata",
+ "rules_python++internal_deps+pypi__importlib_metadata"
+ ],
+ [
+ "rules_python+",
+ "pypi__installer",
+ "rules_python++internal_deps+pypi__installer"
+ ],
+ [
+ "rules_python+",
+ "pypi__more_itertools",
+ "rules_python++internal_deps+pypi__more_itertools"
+ ],
+ [
+ "rules_python+",
+ "pypi__packaging",
+ "rules_python++internal_deps+pypi__packaging"
+ ],
+ [
+ "rules_python+",
+ "pypi__pep517",
+ "rules_python++internal_deps+pypi__pep517"
+ ],
+ [
+ "rules_python+",
+ "pypi__pip",
+ "rules_python++internal_deps+pypi__pip"
+ ],
+ [
+ "rules_python+",
+ "pypi__pip_tools",
+ "rules_python++internal_deps+pypi__pip_tools"
+ ],
+ [
+ "rules_python+",
+ "pypi__pyproject_hooks",
+ "rules_python++internal_deps+pypi__pyproject_hooks"
+ ],
+ [
+ "rules_python+",
+ "pypi__setuptools",
+ "rules_python++internal_deps+pypi__setuptools"
+ ],
+ [
+ "rules_python+",
+ "pypi__tomli",
+ "rules_python++internal_deps+pypi__tomli"
+ ],
+ [
+ "rules_python+",
+ "pypi__wheel",
+ "rules_python++internal_deps+pypi__wheel"
+ ],
+ [
+ "rules_python+",
+ "pypi__zipp",
+ "rules_python++internal_deps+pypi__zipp"
+ ],
+ [
+ "rules_python+",
+ "pythons_hub",
+ "rules_python++python+pythons_hub"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_10_host",
+ "rules_python++python+python_3_10_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_11_host",
+ "rules_python++python+python_3_11_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_12_host",
+ "rules_python++python+python_3_12_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_13_host",
+ "rules_python++python+python_3_13_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_8_host",
+ "rules_python++python+python_3_8_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_9_host",
+ "rules_python++python+python_3_9_host"
+ ]
+ ]
+ }
+ },
+ "@@rules_python+//python/uv:uv.bzl%uv": {
+ "general": {
+ "bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=",
+ "usagesDigest": "vJ5RHUxAnV24M5swNGiAnkdxMx3Hp/iOLmNANTC5Xc8=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "uv": {
+ "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
+ "attributes": {
+ "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
+ "toolchain_names": [
+ "none"
+ ],
+ "toolchain_implementations": {
+ "none": "'@@rules_python+//python:none'"
+ },
+ "toolchain_compatible_with": {
+ "none": [
+ "@platforms//:incompatible"
+ ]
+ },
+ "toolchain_target_settings": {}
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_python+",
+ "platforms",
+ "platforms"
+ ]
+ ]
+ }
+ }
+ }
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind-externs.js b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind-externs.js
new file mode 100644
index 0000000000..864d220894
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind-externs.js
@@ -0,0 +1,2 @@
+// This file prevents customJSFunctionToTestClosure from being minified by the Closure compiler.
+Module.customJSFunctionToTestClosure = function() {}
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind-interface.js b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind-interface.js
new file mode 100644
index 0000000000..ddc4d2f3db
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind-interface.js
@@ -0,0 +1,3 @@
+Module.customJSFunctionToTestClosure = function(firstParam, secondParam) {
+ console.log("This function adds two numbers to get", firstParam + secondParam);
+}
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind.cc
new file mode 100644
index 0000000000..d5bff5f087
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-embind.cc
@@ -0,0 +1,16 @@
+#include
+
+using namespace emscripten;
+
+class HelloClass {
+ public:
+ static std::string SayHello(const std::string &name) {
+ return "Yo! " + name;
+ };
+};
+
+EMSCRIPTEN_BINDINGS(Hello) {
+ emscripten::class_("HelloClass")
+ .constructor<>()
+ .class_function("SayHello", &HelloClass::SayHello);
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-world.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-world.cc
new file mode 100644
index 0000000000..ee72c53171
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/hello-world.cc
@@ -0,0 +1,6 @@
+#include
+
+int main(int argc, char** argv) {
+ std::cout << "hello world!" << std::endl;
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/BUILD.bazel b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/BUILD.bazel
new file mode 100644
index 0000000000..4ffe247604
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/BUILD.bazel
@@ -0,0 +1,61 @@
+load("@emsdk//emscripten_toolchain:wasm_rules.bzl", "wasm_cc_binary")
+
+_TEST_TARGETS = [
+ "long_command_line_file01",
+ "long_command_line_file02",
+ "long_command_line_file03",
+ "long_command_line_file04",
+ "long_command_line_file05",
+ "long_command_line_file06",
+ "long_command_line_file07",
+ "long_command_line_file08",
+ "long_command_line_file09",
+ "long_command_line_file10",
+ "long_command_line_file11",
+ "long_command_line_file12",
+ "long_command_line_file13",
+ "long_command_line_file14",
+ "long_command_line_file15",
+ "long_command_line_file16",
+ "long_command_line_file17",
+ "long_command_line_file18",
+ "long_command_line_file19",
+ "long_command_line_file20",
+]
+
+_TEST_TARGET_SUFFIXES = [
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+]
+
+[cc_library(
+ name = "{}_{}".format(target, suffix),
+ hdrs = ["include/{}.hh".format(target)],
+ # stripping include prefix to create more flags passed to emcc
+ strip_include_prefix = "include",
+ srcs = ["{}.cc".format(target)],
+) for target in _TEST_TARGETS for suffix in _TEST_TARGET_SUFFIXES]
+
+cc_binary(
+ name = "long_command_line",
+ linkshared = True,
+ srcs = ["long_command_line.cc"],
+ deps = [":{}_{}".format(target, suffix) for target in _TEST_TARGETS for suffix in _TEST_TARGET_SUFFIXES],
+)
+
+wasm_cc_binary(
+ name = "long_command_line_wasm",
+ cc_target = ":long_command_line",
+ outputs = [
+ "long_command_line.js",
+ "long_command_line.wasm",
+ ],
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file01.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file01.hh
new file mode 100644
index 0000000000..8dd06bad8c
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file01.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f1();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file02.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file02.hh
new file mode 100644
index 0000000000..7a3a0ff11a
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file02.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f2();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file03.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file03.hh
new file mode 100644
index 0000000000..16880553f6
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file03.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f3();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file04.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file04.hh
new file mode 100644
index 0000000000..45ef1fca9b
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file04.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f4();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file05.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file05.hh
new file mode 100644
index 0000000000..707ad50280
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file05.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f5();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file06.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file06.hh
new file mode 100644
index 0000000000..5d91450067
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file06.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f6();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file07.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file07.hh
new file mode 100644
index 0000000000..b0bf811868
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file07.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f7();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file08.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file08.hh
new file mode 100644
index 0000000000..994b7ea7cd
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file08.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f8();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file09.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file09.hh
new file mode 100644
index 0000000000..90c19583c4
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file09.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f9();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file10.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file10.hh
new file mode 100644
index 0000000000..6a4388182a
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file10.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f10();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file11.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file11.hh
new file mode 100644
index 0000000000..878c9396b4
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file11.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f11();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file12.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file12.hh
new file mode 100644
index 0000000000..b5e0bc3e94
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file12.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f12();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file13.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file13.hh
new file mode 100644
index 0000000000..634dcef138
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file13.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f13();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file14.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file14.hh
new file mode 100644
index 0000000000..8fa9666214
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file14.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f14();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file15.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file15.hh
new file mode 100644
index 0000000000..1f7b7706a7
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file15.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f15();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file16.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file16.hh
new file mode 100644
index 0000000000..c9fa2fcefc
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file16.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f16();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file17.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file17.hh
new file mode 100644
index 0000000000..b959207b74
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file17.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f17();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file18.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file18.hh
new file mode 100644
index 0000000000..af0bacf55f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file18.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f18();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file19.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file19.hh
new file mode 100644
index 0000000000..0ac9b4b027
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file19.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f19();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file20.hh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file20.hh
new file mode 100644
index 0000000000..0f10c733b7
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/include/long_command_line_file20.hh
@@ -0,0 +1,3 @@
+#pragma once
+
+void f20();
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line.cc
new file mode 100644
index 0000000000..1ae13abecb
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line.cc
@@ -0,0 +1,43 @@
+#include "long_command_line_file01.hh"
+#include "long_command_line_file02.hh"
+#include "long_command_line_file03.hh"
+#include "long_command_line_file04.hh"
+#include "long_command_line_file05.hh"
+#include "long_command_line_file06.hh"
+#include "long_command_line_file07.hh"
+#include "long_command_line_file08.hh"
+#include "long_command_line_file09.hh"
+#include "long_command_line_file10.hh"
+#include "long_command_line_file11.hh"
+#include "long_command_line_file12.hh"
+#include "long_command_line_file13.hh"
+#include "long_command_line_file14.hh"
+#include "long_command_line_file15.hh"
+#include "long_command_line_file16.hh"
+#include "long_command_line_file17.hh"
+#include "long_command_line_file18.hh"
+#include "long_command_line_file19.hh"
+#include "long_command_line_file20.hh"
+
+int main() {
+ f1();
+ f2();
+ f3();
+ f4();
+ f5();
+ f6();
+ f7();
+ f8();
+ f9();
+ f10();
+ f11();
+ f12();
+ f13();
+ f14();
+ f15();
+ f16();
+ f17();
+ f18();
+ f19();
+ f20();
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file01.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file01.cc
new file mode 100644
index 0000000000..3bf8d4aa07
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file01.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file01.hh"
+
+#include
+
+void f1() { std::cout << "hello from f1()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file02.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file02.cc
new file mode 100644
index 0000000000..b8ac8141c5
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file02.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file02.hh"
+
+#include
+
+void f2() { std::cout << "hello from f2()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file03.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file03.cc
new file mode 100644
index 0000000000..294e777419
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file03.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file03.hh"
+
+#include
+
+void f3() { std::cout << "hello from f3()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file04.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file04.cc
new file mode 100644
index 0000000000..c0d537d1b8
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file04.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file04.hh"
+
+#include
+
+void f4() { std::cout << "hello from f4()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file05.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file05.cc
new file mode 100644
index 0000000000..310e3e04ca
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file05.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file05.hh"
+
+#include
+
+void f5() { std::cout << "hello from f5()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file06.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file06.cc
new file mode 100644
index 0000000000..2c218fdcc4
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file06.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file06.hh"
+
+#include
+
+void f6() { std::cout << "hello from f6()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file07.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file07.cc
new file mode 100644
index 0000000000..c78dc400c8
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file07.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file07.hh"
+
+#include
+
+void f7() { std::cout << "hello from f7()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file08.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file08.cc
new file mode 100644
index 0000000000..1c2e10f889
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file08.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file08.hh"
+
+#include
+
+void f8() { std::cout << "hello from f8()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file09.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file09.cc
new file mode 100644
index 0000000000..6c0028dc32
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file09.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file09.hh"
+
+#include
+
+void f9() { std::cout << "hello from f9()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file10.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file10.cc
new file mode 100644
index 0000000000..9f0be9cf42
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file10.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file10.hh"
+
+#include
+
+void f10() { std::cout << "hello from f10()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file11.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file11.cc
new file mode 100644
index 0000000000..2ef8f96e2d
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file11.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file11.hh"
+
+#include
+
+void f11() { std::cout << "hello from f11()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file12.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file12.cc
new file mode 100644
index 0000000000..76349962b8
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file12.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file12.hh"
+
+#include
+
+void f12() { std::cout << "hello from f12()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file13.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file13.cc
new file mode 100644
index 0000000000..bca66d0cda
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file13.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file13.hh"
+
+#include
+
+void f13() { std::cout << "hello from f13()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file14.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file14.cc
new file mode 100644
index 0000000000..543179f6c2
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file14.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file14.hh"
+
+#include
+
+void f14() { std::cout << "hello from f14()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file15.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file15.cc
new file mode 100644
index 0000000000..28767ef84d
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file15.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file15.hh"
+
+#include
+
+void f15() { std::cout << "hello from f15()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file16.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file16.cc
new file mode 100644
index 0000000000..ca7ff99b61
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file16.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file16.hh"
+
+#include
+
+void f16() { std::cout << "hello from f16()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file17.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file17.cc
new file mode 100644
index 0000000000..2230d36faf
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file17.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file17.hh"
+
+#include
+
+void f17() { std::cout << "hello from f17()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file18.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file18.cc
new file mode 100644
index 0000000000..822cd14847
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file18.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file18.hh"
+
+#include
+
+void f18() { std::cout << "hello from f18()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file19.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file19.cc
new file mode 100644
index 0000000000..b8640642fa
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file19.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file19.hh"
+
+#include
+
+void f19() { std::cout << "hello from f19()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file20.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file20.cc
new file mode 100644
index 0000000000..0562be6dda
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_external/long_command_line/long_command_line_file20.cc
@@ -0,0 +1,5 @@
+#include "long_command_line_file20.hh"
+
+#include
+
+void f20() { std::cout << "hello from f20()\n"; }
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/.bazelrc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/.bazelrc
new file mode 100644
index 0000000000..fbd75a7ea7
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/.bazelrc
@@ -0,0 +1 @@
+build --incompatible_enable_cc_toolchain_resolution
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/.gitignore b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/.gitignore
new file mode 100644
index 0000000000..9d50f0bb1e
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/.gitignore
@@ -0,0 +1,4 @@
+bazel-bin
+bazel-out
+bazel-test_secondary_lto_cache
+bazel-testlogs
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/BUILD b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/BUILD
new file mode 100644
index 0000000000..f364f3778f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/BUILD
@@ -0,0 +1,19 @@
+load("@emsdk//emscripten_toolchain:wasm_rules.bzl", "wasm_cc_binary")
+
+cc_binary(
+ name = "hello-world",
+ srcs = ["hello-world.cc"],
+ linkopts = [
+ "-sAUTO_NATIVE_LIBRARIES=0",
+ "-flto",
+ ],
+)
+
+wasm_cc_binary(
+ name = "hello-world-wasm",
+ cc_target = ":hello-world",
+ outputs = [
+ "hello-world.js",
+ "hello-world.wasm",
+ ],
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/MODULE.bazel b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/MODULE.bazel
new file mode 100644
index 0000000000..0fabdc89e5
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/MODULE.bazel
@@ -0,0 +1,25 @@
+bazel_dep(name = "rules_cc", version = "0.1.1")
+bazel_dep(name = "emsdk")
+local_path_override(
+ module_name = "emsdk",
+ path = "..",
+)
+
+emscripten_cache = use_extension(
+ "@emsdk//:emscripten_cache.bzl",
+ "emscripten_cache",
+)
+emscripten_cache.configuration(flags = ["--lto"])
+emscripten_cache.targets(targets = [
+ "crtbegin",
+ "libprintf_long_double-debug",
+ "libstubs-debug",
+ "libnoexit",
+ "libc-debug",
+ "libdlmalloc",
+ "libcompiler_rt",
+ "libc++-noexcept",
+ "libc++abi-debug-noexcept",
+ "libsockets",
+ "libdlmalloc-debug",
+])
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/MODULE.bazel.lock b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/MODULE.bazel.lock
new file mode 100644
index 0000000000..a340fd7b88
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/MODULE.bazel.lock
@@ -0,0 +1,3710 @@
+{
+ "lockFileVersion": 18,
+ "registryFileHashes": {
+ "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+ "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/MODULE.bazel": "e4529e12d8cd5b828e2b5960d07d3ec032541740d419d7d5b859cabbf5b056f9",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/1.42.3/source.json": "80cb66069ad626e0921555cd2bf278286fd7763fae2450e564e351792e8303f4",
+ "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/MODULE.bazel": "f19e6b4a16f77f8cf3728eac1f60dbfd8e043517fd4f4dbf17a75a6c50936d62",
+ "https://bcr.bazel.build/modules/aspect_rules_js/1.42.0/source.json": "abbb3eac3b6af76b8ce230a9a901c6d08d93f4f5ffd55314bf630827dddee57e",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+ "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+ "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/source.json": "3e8379efaaef53ce35b7b8ba419df829315a880cb0a030e5bb45c96d6d5ecb5f",
+ "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
+ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+ "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
+ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
+ "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+ "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+ "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+ "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+ "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+ "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+ "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+ "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
+ "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
+ "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
+ "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c",
+ "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
+ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+ "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+ "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
+ "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
+ "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+ "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+ "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+ "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
+ "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
+ "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960",
+ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
+ "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+ "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/MODULE.bazel": "6bc03c8f37f69401b888023bf511cb6ee4781433b0cb56236b2e55a21e3a026a",
+ "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/MODULE.bazel": "42e8d5254b6135f890fecca7c8d7f95a7d27a45f8275b276f66ec337767530ef",
+ "https://bcr.bazel.build/modules/rules_nodejs/6.3.2/source.json": "80e0a68eb81772f1631f8b69014884eebc2474b3b3025fd19a5240ae4f76f9c9",
+ "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
+ "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+ "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
+ "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+ "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+ "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/source.json": "25932f917cd279c7baefa6cb1d3fa8750a7a29de522024449b19af6eab51f4a0",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
+ "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+ "https://bcr.bazel.build/modules/stardoc/0.5.4/MODULE.bazel": "6569966df04610b8520957cb8e97cf2e9faac2c0309657c537ab51c16c18a2a4",
+ "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
+ "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+ "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d",
+ "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+ },
+ "selectedYankedVersions": {},
+ "moduleExtensions": {
+ "@@aspect_bazel_lib+//lib:extensions.bzl%toolchains": {
+ "general": {
+ "bzlTransitiveDigest": "nrCBrZBQH3Dq30TXMpPMV6lWpEDozX0S0kCia4Lrpj0=",
+ "usagesDigest": "1c7PNX163TGNqWzfejRnWpH/hiT4/GRG0kYxuez0Uz0=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "copy_directory_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "copy_directory_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "copy_directory_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "copy_directory_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "copy_directory_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "copy_directory_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "copy_directory_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "copy_directory"
+ }
+ },
+ "copy_to_directory_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "copy_to_directory_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "copy_to_directory_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "copy_to_directory_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "copy_to_directory_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "copy_to_directory_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "copy_to_directory_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "copy_to_directory"
+ }
+ },
+ "jq_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "1.6"
+ }
+ },
+ "jq_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "1.6"
+ }
+ },
+ "jq": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_host_alias_repo",
+ "attributes": {}
+ },
+ "jq_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "jq"
+ }
+ },
+ "yq_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_s390x": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_s390x",
+ "version": "4.25.2"
+ }
+ },
+ "yq_linux_ppc64le": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "linux_ppc64le",
+ "version": "4.25.2"
+ }
+ },
+ "yq_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "4.25.2"
+ }
+ },
+ "yq": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_host_alias_repo",
+ "attributes": {}
+ },
+ "yq_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "yq"
+ }
+ },
+ "coreutils_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64",
+ "version": "0.0.16"
+ }
+ },
+ "coreutils_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "coreutils"
+ }
+ },
+ "bsd_tar_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "bsd_tar_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "bsd_tar_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "bsd_tar_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "bsd_tar_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "bsd_tar_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%tar_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "bsd_tar"
+ }
+ },
+ "expand_template_darwin_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "expand_template_darwin_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "expand_template_freebsd_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "freebsd_amd64"
+ }
+ },
+ "expand_template_linux_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "expand_template_linux_arm64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "expand_template_windows_amd64": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "expand_template_toolchains": {
+ "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "expand_template"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "aspect_bazel_lib+",
+ "aspect_bazel_lib",
+ "aspect_bazel_lib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@aspect_rules_js+//npm:extensions.bzl%pnpm": {
+ "general": {
+ "bzlTransitiveDigest": "poAa/2uyrVSr9Hel1HD6GfFwqId27yXfePnG+3Dmt90=",
+ "usagesDigest": "yxkJioaKxOYkZAdkGoq2Cm79s4pW36Xwx7a8awQOU2E=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "pnpm": {
+ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_rule",
+ "attributes": {
+ "package": "pnpm",
+ "version": "8.6.7",
+ "root_package": "",
+ "link_workspace": "",
+ "link_packages": {},
+ "integrity": "sha512-vRIWpD/L4phf9Bk2o/O2TDR8fFoJnpYrp2TKqTIZF/qZ2/rgL3qKXzHofHgbXsinwMoSEigz28sqk3pQ+yMEQQ==",
+ "url": "",
+ "commit": "",
+ "patch_args": [
+ "-p0"
+ ],
+ "patches": [],
+ "custom_postinstall": "",
+ "npm_auth": "",
+ "npm_auth_basic": "",
+ "npm_auth_username": "",
+ "npm_auth_password": "",
+ "lifecycle_hooks": [],
+ "extra_build_content": "load(\"@aspect_rules_js//js:defs.bzl\", \"js_binary\")\njs_binary(name = \"pnpm\", data = glob([\"package/**\"]), entry_point = \"package/dist/pnpm.cjs\", visibility = [\"//visibility:public\"])",
+ "generate_bzl_library_targets": false,
+ "extract_full_archive": true
+ }
+ },
+ "pnpm__links": {
+ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_links",
+ "attributes": {
+ "package": "pnpm",
+ "version": "8.6.7",
+ "dev": false,
+ "root_package": "",
+ "link_packages": {},
+ "deps": {},
+ "transitive_closure": {},
+ "lifecycle_build_target": false,
+ "lifecycle_hooks_env": [],
+ "lifecycle_hooks_execution_requirements": [
+ "no-sandbox"
+ ],
+ "lifecycle_hooks_use_default_shell_env": false,
+ "bins": {},
+ "package_visibility": [
+ "//visibility:public"
+ ],
+ "replace_package": ""
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "aspect_bazel_lib+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_bazel_lib+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "aspect_rules_js+",
+ "aspect_bazel_lib",
+ "aspect_bazel_lib+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_features",
+ "bazel_features+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "aspect_rules_js+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_globals",
+ "bazel_features++version_extension+bazel_features_globals"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_version",
+ "bazel_features++version_extension+bazel_features_version"
+ ],
+ [
+ "bazel_features+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@emsdk+//:emscripten_cache.bzl%emscripten_cache": {
+ "general": {
+ "bzlTransitiveDigest": "uqDvXmpTNqW4+ie/Fk+xC3TrFrKvL+9hNtoP51Kt2oo=",
+ "usagesDigest": "Es3QEMexQ1KNtrNtX+vNCqjkgkmUNeW2FQd1xCVcWs8=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "emscripten_cache": {
+ "repoRuleId": "@@emsdk+//:emscripten_cache.bzl%_emscripten_cache_repository",
+ "attributes": {
+ "configuration": [
+ "--lto"
+ ],
+ "targets": [
+ "crtbegin",
+ "libprintf_long_double-debug",
+ "libstubs-debug",
+ "libnoexit",
+ "libc-debug",
+ "libdlmalloc",
+ "libcompiler_rt",
+ "libc++-noexcept",
+ "libc++abi-debug-noexcept",
+ "libsockets",
+ "libdlmalloc-debug"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": []
+ }
+ },
+ "@@emsdk+//:emscripten_deps.bzl%emscripten_deps": {
+ "general": {
+ "bzlTransitiveDigest": "h0wQ3PSRx/Q9n+izTifYO8L728OTd9B5YbLOWcobVYE=",
+ "usagesDigest": "eqaMlu1tts7n29bG5zUl3DtA/9ARE+6aHrSK4X7kNno=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "emscripten_bin_linux": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "27fc220a9ad98d323cad73531ff563e9838c9e1205f51ee2a5632bb4266a35d2",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.tar.xz"
+ }
+ },
+ "emscripten_bin_linux_arm64": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "2d03f8eb3f81dd94821658eefbb442a92b0b7601f4cfb08590590fd7bc467ef8",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries-arm64.tar.xz"
+ }
+ },
+ "emscripten_bin_mac": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "c06048915595726fc2e2da6a8db3134581a6287645fb818802a9734ff9785e77",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.tar.xz"
+ }
+ },
+ "emscripten_bin_mac_arm64": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang\",\n \"bin/clang++\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang\",\n \"bin/llvm-ar\",\n \"bin/llvm-dwarfdump\",\n \"bin/llvm-nm\",\n \"bin/llvm-objcopy\",\n \"bin/wasm-ctor-eval\",\n \"bin/wasm-emscripten-finalize\",\n \"bin/wasm-ld\",\n \"bin/wasm-metadce\",\n \"bin/wasm-opt\",\n \"bin/wasm-split\",\n \"bin/wasm2js\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "35d743453d0f91857b09f00d721037bb46753aaeae373bd7f64746338db11770",
+ "strip_prefix": "install",
+ "type": "tar.xz",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries-arm64.tar.xz"
+ }
+ },
+ "emscripten_bin_win": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file_content": "\npackage(default_visibility = ['//visibility:public'])\n\nfilegroup(\n name = \"all\",\n srcs = glob([\"**\"]),\n)\n\nfilegroup(\n name = \"includes\",\n srcs = glob([\n \"emscripten/cache/sysroot/include/c++/v1/**\",\n \"emscripten/cache/sysroot/include/compat/**\",\n \"emscripten/cache/sysroot/include/**\",\n \"lib/clang/**/include/**\",\n ]),\n)\n\nfilegroup(\n name = \"emcc_common\",\n srcs = [\n \"emscripten/emcc.py\",\n \"emscripten/embuilder.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/cache/sysroot_install.stamp\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/third_party/**\",\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"compiler_files\",\n srcs = [\n \"bin/clang.exe\",\n \"bin/clang++.exe\",\n \":emcc_common\",\n \":includes\",\n ],\n)\n\nfilegroup(\n name = \"linker_files\",\n srcs = [\n \"bin/clang.exe\",\n \"bin/llvm-ar.exe\",\n \"bin/llvm-dwarfdump.exe\",\n \"bin/llvm-nm.exe\",\n \"bin/llvm-objcopy.exe\",\n \"bin/wasm-ctor-eval.exe\",\n \"bin/wasm-emscripten-finalize.exe\",\n \"bin/wasm-ld.exe\",\n \"bin/wasm-metadce.exe\",\n \"bin/wasm-opt.exe\",\n \"bin/wasm-split.exe\",\n \"bin/wasm2js.exe\",\n \":emcc_common\",\n ] + glob(\n include = [\n \"emscripten/cache/sysroot/lib/**\",\n \"emscripten/node_modules/**\",\n \"emscripten/src/**\",\n ],\n ),\n)\n\nfilegroup(\n name = \"ar_files\",\n srcs = [\n \"bin/llvm-ar.exe\",\n \"emscripten/emar.py\",\n \"emscripten/emscripten-version.txt\",\n \"emscripten/src/settings.js\",\n \"emscripten/src/settings_internal.js\",\n ] + glob(\n include = [\n \"emscripten/tools/**\",\n ],\n exclude = [\n \"**/__pycache__/**\",\n ],\n ),\n)\n",
+ "sha256": "3b576e825b26426bb72854ed98752df3fcb58cc3ab1dc116566e328b79a8abb3",
+ "strip_prefix": "install",
+ "type": "zip",
+ "url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/14767574a5c37ff9526a253a65ddbe0811cb3667/wasm-binaries.zip"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "bazel_tools",
+ "rules_cc",
+ "rules_cc+"
+ ],
+ [
+ "emsdk+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@pybind11_bazel+//:python_configure.bzl%extension": {
+ "general": {
+ "bzlTransitiveDigest": "d4N/SZrl3ONcmzE98rcV0Fsro0iUbjNQFTIiLiGuH+k=",
+ "usagesDigest": "fycyB39YnXIJkfWCIXLUKJMZzANcuLy9ZE73hRucjFk=",
+ "recordedFileInputs": {
+ "@@pybind11_bazel+//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e"
+ },
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "local_config_python": {
+ "repoRuleId": "@@pybind11_bazel+//:python_configure.bzl%python_configure",
+ "attributes": {}
+ },
+ "pybind11": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file": "@@pybind11_bazel+//:pybind11.BUILD",
+ "strip_prefix": "pybind11-2.11.1",
+ "urls": [
+ "https://github.com/pybind/pybind11/archive/v2.11.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "pybind11_bazel+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_fuzzing+//fuzzing/private:extensions.bzl%non_module_dependencies": {
+ "general": {
+ "bzlTransitiveDigest": "mGiTB79hRNjmeDTQdzkpCHyzXhErMbufeAmySBt7s5s=",
+ "usagesDigest": "wy6ISK6UOcBEjj/mvJ/S3WeXoO67X+1llb9yPyFtPgc=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "platforms": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "urls": [
+ "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz",
+ "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz"
+ ],
+ "sha256": "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74"
+ }
+ },
+ "rules_python": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8",
+ "strip_prefix": "rules_python-0.28.0",
+ "url": "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz"
+ }
+ },
+ "bazel_skylib": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
+ "urls": [
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
+ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"
+ ]
+ }
+ },
+ "com_google_absl": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "urls": [
+ "https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.1.zip"
+ ],
+ "strip_prefix": "abseil-cpp-20240116.1",
+ "integrity": "sha256-7capMWOvWyoYbUaHF/b+I2U6XLMaHmky8KugWvfXYuk="
+ }
+ },
+ "rules_fuzzing_oss_fuzz": {
+ "repoRuleId": "@@rules_fuzzing+//fuzzing/private/oss_fuzz:repository.bzl%oss_fuzz_repository",
+ "attributes": {}
+ },
+ "honggfuzz": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file": "@@rules_fuzzing+//:honggfuzz.BUILD",
+ "sha256": "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e",
+ "url": "https://github.com/google/honggfuzz/archive/2.5.zip",
+ "strip_prefix": "honggfuzz-2.5"
+ }
+ },
+ "rules_fuzzing_jazzer": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar",
+ "attributes": {
+ "sha256": "ee6feb569d88962d59cb59e8a31eb9d007c82683f3ebc64955fd5b96f277eec2",
+ "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer/0.20.1/jazzer-0.20.1.jar"
+ }
+ },
+ "rules_fuzzing_jazzer_api": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar",
+ "attributes": {
+ "sha256": "f5a60242bc408f7fa20fccf10d6c5c5ea1fcb3c6f44642fec5af88373ae7aa1b",
+ "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer-api/0.20.1/jazzer-api-0.20.1.jar"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_fuzzing+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": {
+ "general": {
+ "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=",
+ "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "compatibility_proxy": {
+ "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule",
+ "attributes": {}
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_java+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
+ "general": {
+ "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=",
+ "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "com_github_jetbrains_kotlin_git": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
+ ],
+ "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
+ }
+ },
+ "com_github_jetbrains_kotlin": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
+ "attributes": {
+ "git_repository_name": "com_github_jetbrains_kotlin_git",
+ "compiler_version": "1.9.23"
+ }
+ },
+ "com_github_google_ksp": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
+ ],
+ "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
+ "strip_version": "1.9.23-1.0.20"
+ }
+ },
+ "com_github_pinterest_ktlint": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
+ "attributes": {
+ "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
+ "urls": [
+ "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
+ ],
+ "executable": true
+ }
+ },
+ "rules_android": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
+ "strip_prefix": "rules_android-0.1.1",
+ "urls": [
+ "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_kotlin+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_nodejs+//nodejs:extensions.bzl%node": {
+ "general": {
+ "bzlTransitiveDigest": "rphcryfYrOY/P3emfTskC/GY5YuHcwMl2B2ncjaM8lY=",
+ "usagesDigest": "m7d0VXcsX/qS6DKMUBtdgjQzP2eMRHqsE4wv7dzr71I=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "nodejs_linux_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_amd64"
+ }
+ },
+ "nodejs_linux_arm64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_arm64"
+ }
+ },
+ "nodejs_linux_s390x": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_s390x"
+ }
+ },
+ "nodejs_linux_ppc64le": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "linux_ppc64le"
+ }
+ },
+ "nodejs_darwin_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "darwin_amd64"
+ }
+ },
+ "nodejs_darwin_arm64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "darwin_arm64"
+ }
+ },
+ "nodejs_windows_amd64": {
+ "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%_nodejs_repositories",
+ "attributes": {
+ "node_download_auth": {},
+ "node_repositories": {},
+ "node_urls": [
+ "https://nodejs.org/dist/v{version}/{filename}"
+ ],
+ "node_version": "20.18.0",
+ "include_headers": false,
+ "platform": "windows_amd64"
+ }
+ },
+ "nodejs": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ },
+ "nodejs_host": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ },
+ "nodejs_toolchains": {
+ "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_toolchains_repo.bzl%nodejs_toolchains_repo",
+ "attributes": {
+ "user_node_repository_name": "nodejs"
+ }
+ }
+ },
+ "recordedRepoMappingEntries": []
+ }
+ },
+ "@@rules_python+//python/extensions:pip.bzl%pip": {
+ "general": {
+ "bzlTransitiveDigest": "Jbed6zJUJ6E78XRyOlnG1ryhBDvVeikdntPW1D40S/E=",
+ "usagesDigest": "fztm9ST3ki9E77tct2ZwJe0w38LvfMY8mRYp+YHxXQE=",
+ "recordedFileInputs": {
+ "@@protobuf+//python/requirements.txt": "983be60d3cec4b319dcab6d48aeb3f5b2f7c3350f26b3a9e97486c37967c73c5",
+ "@@rules_fuzzing+//fuzzing/requirements.txt": "ab04664be026b632a0d2a2446c4f65982b7654f5b6851d2f9d399a19b7242a5b",
+ "@@rules_python+//tools/publish/requirements_darwin.txt": "095d4a4f3d639dce831cd493367631cd51b53665292ab20194bac2c0c6458fa8",
+ "@@rules_python+//tools/publish/requirements_linux.txt": "d576e0d8542df61396a9b38deeaa183c24135ed5e8e73bb9622f298f2671811e",
+ "@@rules_python+//tools/publish/requirements_windows.txt": "d18538a3982beab378fd5687f4db33162ee1ece69801f9a451661b1b64286b76"
+ },
+ "recordedDirentsInputs": {},
+ "envVariables": {
+ "RULES_PYTHON_REPO_DEBUG": null,
+ "RULES_PYTHON_REPO_DEBUG_VERBOSITY": null
+ },
+ "generatedRepoSpecs": {
+ "pip_deps_310_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "pip_deps_310",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_310_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "pip_deps_310",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_311_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "pip_deps_311",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_311_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "pip_deps_311",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_312_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "pip_deps_312",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_312_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "pip_deps_312",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_38_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "pip_deps_38",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_38_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "pip_deps_38",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "pip_deps_39_numpy": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "pip_deps_39",
+ "requirement": "numpy<=1.26.1"
+ }
+ },
+ "pip_deps_39_setuptools": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@pip_deps//{name}:{target}",
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "pip_deps_39",
+ "requirement": "setuptools<=70.3.0"
+ }
+ },
+ "rules_fuzzing_py_deps_310_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "rules_fuzzing_py_deps_310",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_310_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python",
+ "repo": "rules_fuzzing_py_deps_310",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_311_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_fuzzing_py_deps_311",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_311_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_fuzzing_py_deps_311",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_312_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "rules_fuzzing_py_deps_312",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_312_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python",
+ "repo": "rules_fuzzing_py_deps_312",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_38_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "rules_fuzzing_py_deps_38",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_38_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python",
+ "repo": "rules_fuzzing_py_deps_38",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_fuzzing_py_deps_39_absl_py": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "rules_fuzzing_py_deps_39",
+ "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"
+ }
+ },
+ "rules_fuzzing_py_deps_39_six": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_fuzzing_py_deps//{name}:{target}",
+ "extra_pip_args": [
+ "--require-hashes"
+ ],
+ "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python",
+ "repo": "rules_fuzzing_py_deps_39",
+ "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ }
+ },
+ "rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "backports.tarfile-1.2.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "backports-tarfile==1.2.0",
+ "sha256": "77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "backports_tarfile-1.2.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "backports-tarfile==1.2.0",
+ "sha256": "d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991",
+ "urls": [
+ "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_certifi_py3_none_any_922820b5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "certifi-2024.8.30-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "certifi==2024.8.30",
+ "sha256": "922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_certifi_sdist_bec941d2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "certifi-2024.8.30.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "certifi==2024.8.30",
+ "sha256": "bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cffi_sdist_1c39c601": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "cffi-1.17.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cffi==1.17.1",
+ "sha256": "1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824",
+ "urls": [
+ "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944",
+ "urls": [
+ "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee",
+ "urls": [
+ "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea",
+ "urls": [
+ "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc",
+ "urls": [
+ "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27",
+ "urls": [
+ "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "charset_normalizer-3.4.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079",
+ "urls": [
+ "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_charset_normalizer_sdist_223217c3": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "charset_normalizer-3.4.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "charset-normalizer==3.4.0",
+ "sha256": "223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7",
+ "urls": [
+ "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16",
+ "urls": [
+ "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_cryptography_sdist_315b9001": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "cryptography-43.0.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "cryptography==43.0.3",
+ "sha256": "315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805",
+ "urls": [
+ "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "docutils-0.21.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "docutils==0.21.2",
+ "sha256": "dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_docutils_sdist_3a6b1873": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "docutils-0.21.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "docutils==0.21.2",
+ "sha256": "3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_idna_py3_none_any_946d195a": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "idna-3.10-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "idna==3.10",
+ "sha256": "946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3",
+ "urls": [
+ "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_idna_sdist_12f65c9b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "idna-3.10.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "idna==3.10",
+ "sha256": "12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "importlib_metadata-8.5.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "importlib-metadata==8.5.0",
+ "sha256": "45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_importlib_metadata_sdist_71522656": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "importlib_metadata-8.5.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "importlib-metadata==8.5.0",
+ "sha256": "71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7",
+ "urls": [
+ "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.classes-3.4.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-classes==3.4.0",
+ "sha256": "f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790",
+ "urls": [
+ "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco.classes-3.4.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-classes==3.4.0",
+ "sha256": "47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd",
+ "urls": [
+ "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.context-6.0.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-context==6.0.1",
+ "sha256": "f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco_context-6.0.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-context==6.0.1",
+ "sha256": "9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3",
+ "urls": [
+ "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "jaraco.functools-4.1.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-functools==4.1.0",
+ "sha256": "ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649",
+ "urls": [
+ "https://files.pythonhosted.org/packages/9f/4f/24b319316142c44283d7540e76c7b5a6dbd5db623abd86bb7b3491c21018/jaraco.functools-4.1.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jaraco_functools-4.1.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jaraco-functools==4.1.0",
+ "sha256": "70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ab/23/9894b3df5d0a6eb44611c36aec777823fc2e07740dabbd0b810e19594013/jaraco_functools-4.1.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "jeepney-0.8.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jeepney==0.8.0",
+ "sha256": "c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ae/72/2a1e2290f1ab1e06f71f3d0f1646c9e4634e70e1d37491535e19266e8dc9/jeepney-0.8.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_jeepney_sdist_5efe48d2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "jeepney-0.8.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "jeepney==0.8.0",
+ "sha256": "5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d6/f4/154cf374c2daf2020e05c3c6a03c91348d59b23c5366e968feb198306fdf/jeepney-0.8.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_keyring_py3_none_any_5426f817": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "keyring-25.4.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "keyring==25.4.1",
+ "sha256": "5426f817cf7f6f007ba5ec722b1bcad95a75b27d780343772ad76b17cb47b0bf",
+ "urls": [
+ "https://files.pythonhosted.org/packages/83/25/e6d59e5f0a0508d0dca8bb98c7f7fd3772fc943ac3f53d5ab18a218d32c0/keyring-25.4.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_keyring_sdist_b07ebc55": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "keyring-25.4.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "keyring==25.4.1",
+ "sha256": "b07ebc55f3e8ed86ac81dd31ef14e81ace9dd9c3d4b5d77a6e9a2016d0d71a1b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a5/1c/2bdbcfd5d59dc6274ffb175bc29aa07ecbfab196830e0cfbde7bd861a2ea/keyring-25.4.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "markdown_it_py-3.0.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "markdown-it-py==3.0.0",
+ "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1",
+ "urls": [
+ "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "markdown-it-py-3.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "markdown-it-py==3.0.0",
+ "sha256": "e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb",
+ "urls": [
+ "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_mdurl_py3_none_any_84008a41": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "mdurl-0.1.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "mdurl==0.1.2",
+ "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_mdurl_sdist_bb413d29": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "mdurl-0.1.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "mdurl==0.1.2",
+ "sha256": "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba",
+ "urls": [
+ "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "more_itertools-10.5.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "more-itertools==10.5.0",
+ "sha256": "037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef",
+ "urls": [
+ "https://files.pythonhosted.org/packages/48/7e/3a64597054a70f7c86eb0a7d4fc315b8c1ab932f64883a297bdffeb5f967/more_itertools-10.5.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_more_itertools_sdist_5482bfef": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "more-itertools-10.5.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "more-itertools==10.5.0",
+ "sha256": "5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/51/78/65922308c4248e0eb08ebcbe67c95d48615cc6f27854b6f2e57143e9178f/more-itertools-10.5.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "14c5a72e9fe82aea5fe3072116ad4661af5cf8e8ff8fc5ad3450f123e4925e86",
+ "urls": [
+ "https://files.pythonhosted.org/packages/b3/89/1daff5d9ba5a95a157c092c7c5f39b8dd2b1ddb4559966f808d31cfb67e0/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "7b7c2a3c9eb1a827d42539aa64091640bd275b81e097cd1d8d82ef91ffa2e811",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2c/b6/42fc3c69cabf86b6b81e4c051a9b6e249c5ba9f8155590222c2622961f58/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "42c64511469005058cd17cc1537578eac40ae9f7200bedcfd1fc1a05f4f8c200",
+ "urls": [
+ "https://files.pythonhosted.org/packages/45/b9/833f385403abaf0023c6547389ec7a7acf141ddd9d1f21573723a6eab39a/nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "0411beb0589eacb6734f28d5497ca2ed379eafab8ad8c84b31bb5c34072b7164",
+ "urls": [
+ "https://files.pythonhosted.org/packages/05/2b/85977d9e11713b5747595ee61f381bc820749daf83f07b90b6c9964cf932/nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "5f36b271dae35c465ef5e9090e1fdaba4a60a56f0bb0ba03e0932a66f28b9189",
+ "urls": [
+ "https://files.pythonhosted.org/packages/72/f2/5c894d5265ab80a97c68ca36f25c8f6f0308abac649aaf152b74e7e854a8/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "19aaba96e0f795bd0a6c56291495ff59364f4300d4a39b29a0abc9cb3774a84b",
+ "urls": [
+ "https://files.pythonhosted.org/packages/c2/a8/3bb02d0c60a03ad3a112b76c46971e9480efa98a8946677b5a59f60130ca/nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "de3ceed6e661954871d6cd78b410213bdcb136f79aafe22aa7182e028b8c7307",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1b/63/6ab90d0e5225ab9780f6c9fb52254fa36b52bb7c188df9201d05b647e5e1/nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "f0eca9ca8628dbb4e916ae2491d72957fdd35f7a5d326b7032a345f111ac07fe",
+ "urls": [
+ "https://files.pythonhosted.org/packages/a3/da/0c4e282bc3cff4a0adf37005fa1fb42257673fbc1bbf7d1ff639ec3d255a/nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "3a157ab149e591bb638a55c8c6bcb8cdb559c8b12c13a8affaba6cedfe51713a",
+ "urls": [
+ "https://files.pythonhosted.org/packages/de/81/c291231463d21da5f8bba82c8167a6d6893cc5419b0639801ee5d3aeb8a9/nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "36c95d4b70530b320b365659bb5034341316e6a9b30f0b25fa9c9eff4c27a204",
+ "urls": [
+ "https://files.pythonhosted.org/packages/eb/61/73a007c74c37895fdf66e0edcd881f5eaa17a348ff02f4bb4bc906d61085/nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "nh3-0.2.18-cp37-abi3-win_amd64.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "8ce0f819d2f1933953fca255db2471ad58184a60508f03e6285e5114b6254844",
+ "urls": [
+ "https://files.pythonhosted.org/packages/26/8d/53c5b19c4999bdc6ba95f246f4ef35ca83d7d7423e5e38be43ad66544e5d/nh3-0.2.18-cp37-abi3-win_amd64.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_nh3_sdist_94a16692": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "nh3-0.2.18.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "nh3==0.2.18",
+ "sha256": "94a166927e53972a9698af9542ace4e38b9de50c34352b962f4d9a7d4c927af4",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/73/10df50b42ddb547a907deeb2f3c9823022580a7a47281e8eae8e003a9639/nh3-0.2.18.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pkginfo-1.10.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pkginfo==1.10.0",
+ "sha256": "889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097",
+ "urls": [
+ "https://files.pythonhosted.org/packages/56/09/054aea9b7534a15ad38a363a2bd974c20646ab1582a387a95b8df1bfea1c/pkginfo-1.10.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pkginfo_sdist_5df73835": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pkginfo-1.10.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pkginfo==1.10.0",
+ "sha256": "5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297",
+ "urls": [
+ "https://files.pythonhosted.org/packages/2f/72/347ec5be4adc85c182ed2823d8d1c7b51e13b9a6b0c1aae59582eca652df/pkginfo-1.10.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "pycparser-2.22-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pycparser==2.22",
+ "sha256": "c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc",
+ "urls": [
+ "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pycparser_sdist_491c8be9": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pycparser-2.22.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pycparser==2.22",
+ "sha256": "491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pygments-2.18.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pygments==2.18.0",
+ "sha256": "b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pygments_sdist_786ff802": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pygments-2.18.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pygments==2.18.0",
+ "sha256": "786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
+ "urls": [
+ "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_windows_x86_64"
+ ],
+ "filename": "pywin32_ctypes-0.2.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pywin32-ctypes==0.2.3",
+ "sha256": "8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8",
+ "urls": [
+ "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "pywin32-ctypes-0.2.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "pywin32-ctypes==0.2.3",
+ "sha256": "d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755",
+ "urls": [
+ "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "readme_renderer-44.0-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "readme-renderer==44.0",
+ "sha256": "2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151",
+ "urls": [
+ "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_readme_renderer_sdist_8712034e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "readme_renderer-44.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "readme-renderer==44.0",
+ "sha256": "8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1",
+ "urls": [
+ "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_py3_none_any_70761cfe": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "requests-2.32.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests==2.32.3",
+ "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_sdist_55365417": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "requests-2.32.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests==2.32.3",
+ "sha256": "55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
+ "urls": [
+ "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "requests_toolbelt-1.0.0-py2.py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests-toolbelt==1.0.0",
+ "sha256": "cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06",
+ "urls": [
+ "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "requests-toolbelt-1.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "requests-toolbelt==1.0.0",
+ "sha256": "7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6",
+ "urls": [
+ "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "rfc3986-2.0.0-py2.py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rfc3986==2.0.0",
+ "sha256": "50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rfc3986_sdist_97aacf9d": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "rfc3986-2.0.0.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rfc3986==2.0.0",
+ "sha256": "97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c",
+ "urls": [
+ "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rich_py3_none_any_6049d5e6": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "rich-13.9.4-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rich==13.9.4",
+ "sha256": "6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90",
+ "urls": [
+ "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_rich_sdist_43959497": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "rich-13.9.4.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "rich==13.9.4",
+ "sha256": "439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "filename": "SecretStorage-3.3.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "secretstorage==3.3.3",
+ "sha256": "f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99",
+ "urls": [
+ "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_secretstorage_sdist_2403533e": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "SecretStorage-3.3.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "secretstorage==3.3.3",
+ "sha256": "2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77",
+ "urls": [
+ "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_twine_py3_none_any_215dbe7b": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "twine-5.1.1-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "twine==5.1.1",
+ "sha256": "215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997",
+ "urls": [
+ "https://files.pythonhosted.org/packages/5d/ec/00f9d5fd040ae29867355e559a94e9a8429225a0284a3f5f091a3878bfc0/twine-5.1.1-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_twine_sdist_9aa08251": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "twine-5.1.1.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "twine==5.1.1",
+ "sha256": "9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db",
+ "urls": [
+ "https://files.pythonhosted.org/packages/77/68/bd982e5e949ef8334e6f7dcf76ae40922a8750aa2e347291ae1477a4782b/twine-5.1.1.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "urllib3-2.2.3-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "urllib3==2.2.3",
+ "sha256": "ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_urllib3_sdist_e7d814a8": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "urllib3-2.2.3.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "urllib3==2.2.3",
+ "sha256": "e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9",
+ "urls": [
+ "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_zipp_py3_none_any_a817ac80": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "filename": "zipp-3.20.2-py3-none-any.whl",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "zipp==3.20.2",
+ "sha256": "a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350",
+ "urls": [
+ "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl"
+ ]
+ }
+ },
+ "rules_python_publish_deps_311_zipp_sdist_bc9eb26f": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library",
+ "attributes": {
+ "dep_template": "@rules_python_publish_deps//{name}:{target}",
+ "experimental_target_platforms": [
+ "cp311_linux_aarch64",
+ "cp311_linux_arm",
+ "cp311_linux_ppc",
+ "cp311_linux_s390x",
+ "cp311_linux_x86_64",
+ "cp311_osx_aarch64",
+ "cp311_osx_x86_64",
+ "cp311_windows_x86_64"
+ ],
+ "extra_pip_args": [
+ "--index-url",
+ "https://pypi.org/simple"
+ ],
+ "filename": "zipp-3.20.2.tar.gz",
+ "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python",
+ "repo": "rules_python_publish_deps_311",
+ "requirement": "zipp==3.20.2",
+ "sha256": "bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29",
+ "urls": [
+ "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz"
+ ]
+ }
+ },
+ "pip_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "pip_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "numpy": "{\"pip_deps_310_numpy\":[{\"version\":\"3.10\"}],\"pip_deps_311_numpy\":[{\"version\":\"3.11\"}],\"pip_deps_312_numpy\":[{\"version\":\"3.12\"}],\"pip_deps_38_numpy\":[{\"version\":\"3.8\"}],\"pip_deps_39_numpy\":[{\"version\":\"3.9\"}]}",
+ "setuptools": "{\"pip_deps_310_setuptools\":[{\"version\":\"3.10\"}],\"pip_deps_311_setuptools\":[{\"version\":\"3.11\"}],\"pip_deps_312_setuptools\":[{\"version\":\"3.12\"}],\"pip_deps_38_setuptools\":[{\"version\":\"3.8\"}],\"pip_deps_39_setuptools\":[{\"version\":\"3.9\"}]}"
+ },
+ "packages": [
+ "numpy",
+ "setuptools"
+ ],
+ "groups": {}
+ }
+ },
+ "rules_fuzzing_py_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "rules_fuzzing_py_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "absl_py": "{\"rules_fuzzing_py_deps_310_absl_py\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_absl_py\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_absl_py\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_absl_py\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_absl_py\":[{\"version\":\"3.9\"}]}",
+ "six": "{\"rules_fuzzing_py_deps_310_six\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_six\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_six\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_six\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_six\":[{\"version\":\"3.9\"}]}"
+ },
+ "packages": [
+ "absl_py",
+ "six"
+ ],
+ "groups": {}
+ }
+ },
+ "rules_python_publish_deps": {
+ "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository",
+ "attributes": {
+ "repo_name": "rules_python_publish_deps",
+ "extra_hub_aliases": {},
+ "whl_map": {
+ "backports_tarfile": "{\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\":[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\":[{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "certifi": "{\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\":[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_certifi_sdist_bec941d2\":[{\"filename\":\"certifi-2024.8.30.tar.gz\",\"version\":\"3.11\"}]}",
+ "cffi": "{\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_sdist_1c39c601\":[{\"filename\":\"cffi-1.17.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "charset_normalizer": "{\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\":[{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\":[{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "cryptography": "{\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_sdist_315b9001\":[{\"filename\":\"cryptography-43.0.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "docutils": "{\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\":[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\":[{\"filename\":\"docutils-0.21.2.tar.gz\",\"version\":\"3.11\"}]}",
+ "idna": "{\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\":[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_idna_sdist_12f65c9b\":[{\"filename\":\"idna-3.10.tar.gz\",\"version\":\"3.11\"}]}",
+ "importlib_metadata": "{\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\":[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\":[{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_classes": "{\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\":[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\":[{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_context": "{\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\":[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\":[{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "jaraco_functools": "{\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\":[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\":[{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "jeepney": "{\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\":[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\":[{\"filename\":\"jeepney-0.8.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "keyring": "{\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\":[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\":[{\"filename\":\"keyring-25.4.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "markdown_it_py": "{\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\":[{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\":[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "mdurl": "{\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\":[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\":[{\"filename\":\"mdurl-0.1.2.tar.gz\",\"version\":\"3.11\"}]}",
+ "more_itertools": "{\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\":[{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\":[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "nh3": "{\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_sdist_94a16692\":[{\"filename\":\"nh3-0.2.18.tar.gz\",\"version\":\"3.11\"}]}",
+ "pkginfo": "{\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\":[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\":[{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "pycparser": "{\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\":[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\":[{\"filename\":\"pycparser-2.22.tar.gz\",\"version\":\"3.11\"}]}",
+ "pygments": "{\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\":[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pygments_sdist_786ff802\":[{\"filename\":\"pygments-2.18.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "pywin32_ctypes": "{\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\":[{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\":[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "readme_renderer": "{\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\":[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\":[{\"filename\":\"readme_renderer-44.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "requests": "{\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\":[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_sdist_55365417\":[{\"filename\":\"requests-2.32.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "requests_toolbelt": "{\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\":[{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\":[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "rfc3986": "{\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\":[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\":[{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"version\":\"3.11\"}]}",
+ "rich": "{\"rules_python_publish_deps_311_rich_py3_none_any_6049d5e6\":[{\"filename\":\"rich-13.9.4-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rich_sdist_43959497\":[{\"filename\":\"rich-13.9.4.tar.gz\",\"version\":\"3.11\"}]}",
+ "secretstorage": "{\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\":[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\":[{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "twine": "{\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\":[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_twine_sdist_9aa08251\":[{\"filename\":\"twine-5.1.1.tar.gz\",\"version\":\"3.11\"}]}",
+ "urllib3": "{\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\":[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\":[{\"filename\":\"urllib3-2.2.3.tar.gz\",\"version\":\"3.11\"}]}",
+ "zipp": "{\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\":[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\":[{\"filename\":\"zipp-3.20.2.tar.gz\",\"version\":\"3.11\"}]}"
+ },
+ "packages": [
+ "backports_tarfile",
+ "certifi",
+ "charset_normalizer",
+ "docutils",
+ "idna",
+ "importlib_metadata",
+ "jaraco_classes",
+ "jaraco_context",
+ "jaraco_functools",
+ "keyring",
+ "markdown_it_py",
+ "mdurl",
+ "more_itertools",
+ "nh3",
+ "pkginfo",
+ "pygments",
+ "readme_renderer",
+ "requests",
+ "requests_toolbelt",
+ "rfc3986",
+ "rich",
+ "twine",
+ "urllib3",
+ "zipp"
+ ],
+ "groups": {}
+ }
+ }
+ },
+ "moduleExtensionMetadata": {
+ "useAllRepos": "NO",
+ "reproducible": false
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "bazel_features+",
+ "bazel_features_globals",
+ "bazel_features++version_extension+bazel_features_globals"
+ ],
+ [
+ "bazel_features+",
+ "bazel_features_version",
+ "bazel_features++version_extension+bazel_features_version"
+ ],
+ [
+ "rules_python+",
+ "bazel_features",
+ "bazel_features+"
+ ],
+ [
+ "rules_python+",
+ "bazel_skylib",
+ "bazel_skylib+"
+ ],
+ [
+ "rules_python+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "rules_python+",
+ "pypi__build",
+ "rules_python++internal_deps+pypi__build"
+ ],
+ [
+ "rules_python+",
+ "pypi__click",
+ "rules_python++internal_deps+pypi__click"
+ ],
+ [
+ "rules_python+",
+ "pypi__colorama",
+ "rules_python++internal_deps+pypi__colorama"
+ ],
+ [
+ "rules_python+",
+ "pypi__importlib_metadata",
+ "rules_python++internal_deps+pypi__importlib_metadata"
+ ],
+ [
+ "rules_python+",
+ "pypi__installer",
+ "rules_python++internal_deps+pypi__installer"
+ ],
+ [
+ "rules_python+",
+ "pypi__more_itertools",
+ "rules_python++internal_deps+pypi__more_itertools"
+ ],
+ [
+ "rules_python+",
+ "pypi__packaging",
+ "rules_python++internal_deps+pypi__packaging"
+ ],
+ [
+ "rules_python+",
+ "pypi__pep517",
+ "rules_python++internal_deps+pypi__pep517"
+ ],
+ [
+ "rules_python+",
+ "pypi__pip",
+ "rules_python++internal_deps+pypi__pip"
+ ],
+ [
+ "rules_python+",
+ "pypi__pip_tools",
+ "rules_python++internal_deps+pypi__pip_tools"
+ ],
+ [
+ "rules_python+",
+ "pypi__pyproject_hooks",
+ "rules_python++internal_deps+pypi__pyproject_hooks"
+ ],
+ [
+ "rules_python+",
+ "pypi__setuptools",
+ "rules_python++internal_deps+pypi__setuptools"
+ ],
+ [
+ "rules_python+",
+ "pypi__tomli",
+ "rules_python++internal_deps+pypi__tomli"
+ ],
+ [
+ "rules_python+",
+ "pypi__wheel",
+ "rules_python++internal_deps+pypi__wheel"
+ ],
+ [
+ "rules_python+",
+ "pypi__zipp",
+ "rules_python++internal_deps+pypi__zipp"
+ ],
+ [
+ "rules_python+",
+ "pythons_hub",
+ "rules_python++python+pythons_hub"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_10_host",
+ "rules_python++python+python_3_10_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_11_host",
+ "rules_python++python+python_3_11_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_12_host",
+ "rules_python++python+python_3_12_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_13_host",
+ "rules_python++python+python_3_13_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_8_host",
+ "rules_python++python+python_3_8_host"
+ ],
+ [
+ "rules_python++python+pythons_hub",
+ "python_3_9_host",
+ "rules_python++python+python_3_9_host"
+ ]
+ ]
+ }
+ },
+ "@@rules_python+//python/uv:uv.bzl%uv": {
+ "general": {
+ "bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=",
+ "usagesDigest": "vJ5RHUxAnV24M5swNGiAnkdxMx3Hp/iOLmNANTC5Xc8=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "uv": {
+ "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
+ "attributes": {
+ "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
+ "toolchain_names": [
+ "none"
+ ],
+ "toolchain_implementations": {
+ "none": "'@@rules_python+//python:none'"
+ },
+ "toolchain_compatible_with": {
+ "none": [
+ "@platforms//:incompatible"
+ ]
+ },
+ "toolchain_target_settings": {}
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_python+",
+ "platforms",
+ "platforms"
+ ]
+ ]
+ }
+ }
+ }
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/hello-world.cc b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/hello-world.cc
new file mode 100644
index 0000000000..ee72c53171
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/bazel/test_secondary_lto_cache/hello-world.cc
@@ -0,0 +1,6 @@
+#include
+
+int main(int argc, char** argv) {
+ std::cout << "hello world!" << std::endl;
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/Makefile b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/Makefile
new file mode 100644
index 0000000000..749ecfe940
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/Makefile
@@ -0,0 +1,31 @@
+# A Makefile to build, test, tag and publish the Emscripten SDK Docker container.
+
+# Emscripten version to build: Should match the version that has been already released.
+# i.e.: 1.39.18
+version =
+alias =
+only_alias =
+
+image_name ?= emscripten/emsdk
+
+.TEST:
+ifndef version
+ $(error argument 'version' is not set. Please call `make version=SOME_VERSION ...`)
+endif
+
+build: Dockerfile .TEST
+ cd .. && docker build --progress=plain --network host --build-arg=EMSCRIPTEN_VERSION=${version} -t ${image_name}:${version} -f docker/$< .
+
+test: test_dockerimage.sh .TEST
+ # test as non-root
+ # test fallback env variables by overriding the entrypoint
+ docker run --rm -u `id -u`:`id -g` -w /emsdk/docker --net=host --entrypoint /bin/bash ${image_name}:${version} $<
+
+push: .TEST
+ifndef only_alias
+ docker push ${image_name}:${version}
+endif
+ifdef alias
+ docker tag ${image_name}:${version} ${image_name}:${alias}
+ docker push ${image_name}:${alias}
+endif
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/entrypoint.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/entrypoint.sh
new file mode 100755
index 0000000000..ceadfc438b
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/entrypoint.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -e
+
+# Set-up PATH and other environment variables
+EMSDK_QUIET=1 source /emsdk/emsdk_env.sh
+
+exec "$@"
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/test_dockerimage.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/test_dockerimage.sh
new file mode 100755
index 0000000000..09648206be
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/docker/test_dockerimage.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+set -ex
+
+if [ $EUID -eq 0 ]; then
+ sudo -u nobody `which emcc` --version
+fi
+
+which emsdk
+node --version
+npm --version
+python3 --version
+pip3 --version
+em++ --version
+emcc --version
+java -version
+cmake --version
+
+exit_code=0
+
+# test emcc compilation
+echo 'int main() { return 0; }' | emcc -o /tmp/main.js -xc -
+node /tmp/main.js || exit_code=$?
+if [ $exit_code -ne 0 ]; then
+ echo "Node exited with non-zero exit code: $exit_code"
+ exit $exit_code
+fi
+
+# test embuilder
+embuilder build zlib --force
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emcmdprompt.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emcmdprompt.bat
new file mode 100644
index 0000000000..89803aef73
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emcmdprompt.bat
@@ -0,0 +1 @@
+@cmd /k call emsdk_env.bat
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emscripten-releases-tags.json b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emscripten-releases-tags.json
new file mode 100644
index 0000000000..012fe41e21
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emscripten-releases-tags.json
@@ -0,0 +1,271 @@
+{
+ "aliases": {
+ "latest": "4.0.9",
+ "latest-sdk": "latest",
+ "latest-arm64-linux": "latest",
+ "latest-64bit": "latest",
+ "sdk-latest-64bit": "latest",
+ "latest-upstream": "latest",
+ "latest-clang-upstream": "latest",
+ "latest-releases-upstream": "latest"
+ },
+ "releases": {
+ "4.0.9": "cb2a69bce627bd2247624c71fc12907cb8785d2f",
+ "4.0.9-asserts": "27f1e0801c6ec5ea4d9a9e1d573eb1fead3525f1",
+ "4.0.8": "56f86607aeb458086e72f23188789be2ee0e971a",
+ "4.0.8-asserts": "ab275365d4057cf92d698ef99744d66cd8c7cba9",
+ "4.0.7": "ef4e9cedeac3332e4738087567552063f4f250d3",
+ "4.0.7-asserts": "4bef8973dc12f5f38022f323d67c16237bbd2962",
+ "4.0.6": "14767574a5c37ff9526a253a65ddbe0811cb3667",
+ "4.0.6-asserts": "4050eaf1fd8e1c191198ec4ba8c346c4f3da0dc8",
+ "4.0.5": "d7f8ff5e2ca3539c33fae81e98f7c56ef9fa1239",
+ "4.0.5-asserts": "71269375282224b2e662bbe009e2e3ebc40db67f",
+ "4.0.4": "ea71afcf5a172125179a07ff1731de6e81c92222",
+ "4.0.4-asserts": "5121692126f7c96d86a13dc8462e758813e30123",
+ "4.0.3": "de2109f0e5e7278d470da11de526aed16c527722",
+ "4.0.3-asserts": "bae6703fb819bd84fb4dfb5e87b41cf93b6d3f2b",
+ "4.0.2": "cc8eba40de8235f9c33d92463018f87b3edaa09e",
+ "4.0.2-asserts": "dc575ac9a214463b2b3503c11a1a31db665b4414",
+ "4.0.1": "5ff495a591978fdf8a16f2d172be3616f3150d1e",
+ "4.0.1-asserts": "c2e46b78d3dde701187d685f8c175f17425bee68",
+ "4.0.0": "3ebc04a3dab24522a5bf8ced3ce3caea816558f6",
+ "4.0.0-asserts": "912ac2d711bb343205f314564ed287d883a7d888",
+ "3.1.74": "c2655005234810c7c42e02a18e4696554abe0352",
+ "3.1.74-asserts": "88e95307accc1f4b247b86b7a0c0e6beaf07f844",
+ "3.1.73": "b363a836e75a245c548b7a6a021822d8c9e4c6df",
+ "3.1.73-asserts": "86f3e54628089634c6b73039955388296e920291",
+ "3.1.72": "7a360458327cd24c2a7aab428bdbcb5bca8810e4",
+ "3.1.72-asserts": "92d39398c0016e73821548a4cd9df3df1358f6d9",
+ "3.1.71": "7ee0f9488f152e9e9cf0d4d243970e03742f1a5c",
+ "3.1.71-asserts": "15b142643065fe241138c6785cb8e384504f76e8",
+ "3.1.70": "6fa6145af41e835f3d13edf7d308c08e4573357a",
+ "3.1.70-asserts": "11444ec05e2cc64ef42c4f33c6e3a2a7534694f2",
+ "3.1.69": "8fe01288bc35668c13316324336ea00195dfb814",
+ "3.1.69-asserts": "cf6f9d1b4026ec7aec33aceb68077c704b52b068",
+ "3.1.68": "b52d8c9150dc7d4c8e4a7a08c7a9b4006c9abe49",
+ "3.1.68-asserts": "1565c9e5a4547215a1b63013607bf7a1cbb3d9d3",
+ "3.1.67": "4ae62984ea36ef0e5bfcbd0ed9b62f04bee6426a",
+ "3.1.67-asserts": "7cfc00962efe07f2e2ff3383f59519dc5bea4f82",
+ "3.1.66": "243eae09cf5c20c4fde51a620b92f483255c8214",
+ "3.1.66-asserts": "c5d25114210455d19cb9232171824292005a5080",
+ "3.1.65": "fdcf56c75a1d27fdff6525a7e03423595485ca19",
+ "3.1.65-asserts": "3231fb47481b2248c31002cdd7324a9155135ce0",
+ "3.1.64": "fd61bacaf40131f74987e649a135f1dd559aff60",
+ "3.1.64-asserts": "42c1d51ceb8e41e70ce1d8dc1bc534c0f609c196",
+ "3.1.63": "aeb36a44b29e8ca9f4c7efbb4735b69003ac2bb9",
+ "3.1.63-asserts": "b0275806047b42f2f88998c5c8159aec90e195ab",
+ "3.1.62": "d52176ac8e07c47c1773bb2776ebd91e3886c3af",
+ "3.1.62-asserts": "9d9e7deac8b91fbdd8804045595e807f9d774a53",
+ "3.1.61": "28e4a74b579b4157bda5fc34f23c7d3905a8bd6c",
+ "3.1.61-asserts": "7fc912687ba2077b3aeae472b51c238b3d201c46",
+ "3.1.60": "87709b5747de5b1993fe314285528bf4b65c23e1",
+ "3.1.60-asserts": "e2388e8a528890b8f3ff7b9ab4f52dbe2aeb38b9",
+ "3.1.59": "e20ee09a8a740544c4bc6de5d4ba5f81f74b74d6",
+ "3.1.59-asserts": "10ae1e83ccce9f4a363bb2e3090ba8fc32d25851",
+ "3.1.58": "a4d4afb626c5010f6ccda4638b8d77579a63782e",
+ "3.1.58-asserts": "5bc1c7108d4d91db316b24a75593a37c1117c266",
+ "3.1.57": "523b29e1b99a61069a2fa9f9d3cc9be1c4c53d4d",
+ "3.1.57-asserts": "10b736eeeac0dae3fd5bc29c6b3e32f7f7adf941",
+ "3.1.56": "9d106be887796484c4aaffc9dc45f48a8810f336",
+ "3.1.56-asserts": "2b9c4b912b611dc51f9019e11371e3cdd36fa64e",
+ "3.1.55": "f5557e3b7166d05bddb5977e363ec48cd06e9d32",
+ "3.1.55-asserts": "eb23cc30563325fd6dc97fcf85ddf26489ab9110",
+ "3.1.54": "aa1588cd28c250a60457b5ed342557c762f416e3",
+ "3.1.54-asserts": "d525f56cb765ed6884a0c443dbb906b63b148915",
+ "3.1.53": "e5523d57a0e0dcf80f3b101bbc23613fcc3101aa",
+ "3.1.53-asserts": "152cef4e00fc17776576bcc57f53badd21b92509",
+ "3.1.52": "ce2097fb81953331e65543c20b437475f218127c",
+ "3.1.52-asserts": "49e9a37dd6d1d65aa92472d8908cb8b88092dfaf",
+ "3.1.51": "4f416d92fbff66ce79901cfc8263768f1b25dd3e",
+ "3.1.51-asserts": "9035c99beb760aa0ea381bdf11abf440d88bb451",
+ "3.1.50": "2ce4170cef5ce46f337f9fd907b614a8db772c7d",
+ "3.1.50-asserts": "0a6fe6ef5880bf5b035d396f3875fda9b7c4bb60",
+ "3.1.49": "bd0a2e230466dadb36efc71aa7271f17c6c35420",
+ "3.1.49-asserts": "4ea035c5bbd6168dae34c970b5f56d7aa4dcf952",
+ "3.1.48": "694434b6d47c5f6eff2c8fbd9eeb016c977ae9dc",
+ "3.1.48-asserts": "6e2b8a97c6db82089c3a405bc88ea9fb125deb16",
+ "3.1.47": "39ade279e75e6d17dd6b7eb9fba2006e61fe966b",
+ "3.1.47-asserts": "dc49d84ed226a5a30a5117cefc07c781f6c0d16e",
+ "3.1.46": "21644188d5c473e92f1d7df2f9f60c758a78a486",
+ "3.1.46-asserts": "3e09b252d0d5a8e045d2ca92c606bfb9874bddf8",
+ "3.1.45": "2b7c5fb8ffeac3315deb1f82ab7bf8da544f84a1",
+ "3.1.45-asserts": "2aec03dfd8ce68c95316116dafbe30e273f32a81",
+ "3.1.44": "b90507fcf011da61bacfca613569d882f7749552",
+ "3.1.44-asserts": "06d00b0c62e435b743aa37c67b4ab76bc8568c79",
+ "3.1.43": "bf3c159888633d232c0507f4c76cc156a43c32dc",
+ "3.1.43-asserts": "3ec53a819a5958665d6bb0ac895c99546921b6ef",
+ "3.1.42": "9d73bf4bd5b5c9ce6e51be0ed5ce6599fcb28e9e",
+ "3.1.42-asserts": "7a622e0b66ee095aea9766375a2774b68c8bd8ef",
+ "3.1.41": "eb71265ef0ab905620015adbfedacf88c5dbf021",
+ "3.1.41-asserts": "064607aeccaffd93175bb40c072271c0393d71a5",
+ "3.1.40": "c3122846bb040798aab975f61008c37eb19476de",
+ "3.1.40-asserts": "5b5daaaabaf7292736454e4f8a73fa79bd455af4",
+ "3.1.39": "1b56b171b627af0841cf8d4d8c0160c6cb6d855f",
+ "3.1.39-asserts": "5e237cc9d9f6020af9ba908692361aa71744af1d",
+ "3.1.38": "03ecb526947f6a3702a0d083083799fe410d3893",
+ "3.1.38-asserts": "f771c7a0b55bc5d89ecceedfe9521c2c04aa43ae",
+ "3.1.37": "7c905cfc1ca6699f6ccb288ae174902cfbdcf0a2",
+ "3.1.37-asserts": "323607efbcdf84886dab55a18d758fe4c7d71d1e",
+ "3.1.36": "adedc0750c4a89b65bee866edab24298cb8d6677",
+ "3.1.36-asserts": "fdd2824226a8b001df5697146b88be98920fc215",
+ "3.1.35": "671550b5bdceee7bdb21493714f9a815aa5149a9",
+ "3.1.35-asserts": "42481a713ae805eda34f6e3e7170384c426b1d73",
+ "3.1.34": "2fdd6b9e5b67d5b62f84d0501a876513ff118ef1",
+ "3.1.34-asserts": "385382932c18a1312fff88000c4f83c2b9d1bb44",
+ "3.1.33": "49b960bd03b3a9da478a08541ce6eafe792a58a8",
+ "3.1.33-asserts": "e3ca2c6756b75cf6c6daa40276de0f25218e04a7",
+ "3.1.32": "29ad1037cd6b99e5d8a1bd75bc188c1e9a6fda8d",
+ "3.1.32-asserts": "2811c849256ec5b62b4ec32fb8369e5f3c9a54b1",
+ "3.1.31": "1eec24930cb2f56f6d9cd10ffcb031e27ea4157a",
+ "3.1.31-asserts": "48488847a38bb9cfb36e7397bea21ab2bb062680",
+ "3.1.30": "dc1fdcfd3f5b9d29cb1ebdf15e6e845bef9b0cc1",
+ "3.1.30-asserts": "21cca44e843267533c3d0b258b46c37bd142a2d7",
+ "3.1.29": "d949f1b99a477d4b0b54d95413df3688afa69d0a",
+ "3.1.29-asserts": "9d1e32e66e4b5921efc1a45cdc68e8c522c42c32",
+ "3.1.28": "30b9e46ddcea66e91530559379089002d8b692cf",
+ "3.1.28-asserts": "19871a9ea4914d63749b8d4d170e27a8854cb565",
+ "3.1.27": "48ce0b44015d0182fc8c27aa9fbc0a4474b55982",
+ "3.1.27-asserts": "630810e5a312f57d17efbe384ed7e4299f796bc1",
+ "3.1.26": "4f68bb2a505c727bcf58195cf4da20592a6e92c8",
+ "3.1.26-asserts": "4e2ffe94b04dbadfbca1687ab458d306b3414d13",
+ "3.1.25": "ff6babb041d0f31575cc16d15ef82c6222ca99b8",
+ "3.1.25-asserts": "6b19d6a8c30d7b83ba2193625fc12cce9ae0206b",
+ "3.1.24": "54217a0950bb1dafe8808cc6207d378e323f9d74",
+ "3.1.24-asserts": "4c20c7393ca208c740c16a97dbf305ba52fea2bb",
+ "3.1.23": "bfd5e63a44ba4c8568cd8ac87c27b35e40732bf4",
+ "3.1.23-asserts": "77d2c744fe37fe0e22a51329fa23bab4b8ffa656",
+ "3.1.22": "990cee04a21caafc75955d736fb45791a7f2aeee",
+ "3.1.22-asserts": "d94fe69a037e93562d0bbe9d0372ce23f4ab1089",
+ "3.1.21": "a16a8bca2466eb144f7c93fa899c0272c8815dc3",
+ "3.1.21-asserts": "c7a387161b029621eb4d3dd57363b1393b4c50b2",
+ "3.1.20": "d92c8639f406582d70a5dde27855f74ecf602f45",
+ "3.1.20-asserts": "db0fd1cb7316675317d527b6ed4f4cc7005df9ec",
+ "3.1.19": "4c3772879a04140298c3abde90962d5567b5e2fc",
+ "3.1.19-asserts": "83c2ba526ec47139d29e1417ac23d15b37ead98a",
+ "3.1.18": "49d45744895c7d7e28acd94a385d7ee361653b4a",
+ "3.1.18-asserts": "cb7fa1dce4b04e35b78ec43499a7759f24c1e64d",
+ "3.1.17": "d27fef2070c86a218965da8b8b5df8b4425aa3bb",
+ "3.1.17-asserts": "19aab28a81be09863e86aba8ee4e20feaee31f6b",
+ "3.1.16": "fb1baf00423818052359cf9126e94bc71c39feb5",
+ "3.1.16-asserts": "61848bee5b330db5ad5f827352d453b5557757fa",
+ "3.1.15": "568a46a9fb7e1f1686a6f7216b3dc976f28d2a79",
+ "3.1.15-asserts": "a8a770a0a23d2279270bd28004c8c60b02d91fbb",
+ "3.1.14": "ade9d780ff17c88d81aa13860361743e3c1e1396",
+ "3.1.14-asserts": "b55548282b553fc0b922b82d97b80f256bf01d20",
+ "3.1.13": "bc44364b561cfde15c243a54e3b96ea12d7ea284",
+ "3.1.13-asserts": "6b8f75967b5d37fa898d217b560d571694eb5b13",
+ "3.1.12": "a8c3b314d61e2bb98581d522f858132b2fc21488",
+ "3.1.12-asserts": "0ec1936aa3cb809d96abfebcc5356cd0cb15f6b8",
+ "3.1.11": "8c3a799341c01148692c52fda73bbba5e89c5727",
+ "3.1.11-asserts": "4d27b98351e021e9b7d2681a84cbab5a0ddc7a88",
+ "3.1.10": "8bd05c7221b4ce34d4bedec40b672d94e681a765",
+ "3.1.10-asserts": "d9b20effb2d660936fb5be525744e941fd900bc6",
+ "3.1.9": "edabe25af34554d19c046078f853999b074259ca",
+ "3.1.9-asserts": "c751721b1dfa47c03ede0f0da89be453c79b34ef",
+ "3.1.8": "8c9e0a76ebed2c5e88a718d43e8b62452def3771",
+ "3.1.8-asserts": "d33ae3c8d16f04b004b76c1d7c1989d637aa36e0",
+ "3.1.7": "d0e637fe48197587d981f79e8114757731d0c2a9",
+ "3.1.7-asserts": "88f0cab4e7db846e171cbbbbf20cc1a51b8c779f",
+ "3.1.6": "8791c3e936141cbc2dd72d76290ea9b2726d39f3",
+ "3.1.6-asserts": "84fa976d87a29ea1734601b042f3c6809ecb89f0",
+ "3.1.5": "2dee36c7163f7394ab9341854ef5281501dd97d0",
+ "3.1.5-asserts": "e9b96739e70faf11bbb2f63addcef59f2b2c7b48",
+ "3.1.4": "39e60dda6945cfcd6487725bdb1361ae7975173f",
+ "3.1.4-asserts": "05edbd634e300fc79ce0f635251bd5bef375328b",
+ "3.1.3": "2ddc66235392b37e5b33477fd86cbe01a14b8aa2",
+ "3.1.3-asserts": "66aaf7da980346898a84e3e1b70477286e225eec",
+ "3.1.2": "6626e25d6d866cf283147ca68d54ac9326fe399f",
+ "3.1.2-asserts": "b5cb3731eeaf127ae73d5e24b56cf5f0cdbf16a6",
+ "3.1.1": "5ee64de9809592480da01372880ea11debd6c740",
+ "3.1.1-asserts": "9455ce6306d97c0b3854e88e1e2f66d4b8565daf",
+ "3.1.0": "562e3a0af169e6dea5e6dbecac2255d67c2c8b94",
+ "3.1.0-asserts": "1de2db691103282dad6b2037018db6ece54f57c6",
+ "3.0.1": "91b7a67a486d2430e73423a38d950d8a550826ed",
+ "3.0.1-asserts": "2a84a08e92ce8748015dfc3eee40ee35a853fed0",
+ "3.0.0": "7fbe748230f2ce99abbf975d9ad997699efb3153",
+ "3.0.0-asserts": "f1d65c26f502220e278d31e7621e99b673e28093",
+ "2.0.34": "d8fc1b92dbc0ce8d740a7adb937c5137ba4755e0",
+ "2.0.33": "cef8850d57278271766fb2163eebcb07354018e7",
+ "2.0.32": "74646397e3c5010824ad60d1de86c6bcbe334dff",
+ "2.0.31": "597724ca3f6cd6e84bea73f1f519a3953b5c273d",
+ "2.0.31-asserts": "c1065389ccf4a81e3c1af080316afd444788bc46",
+ "2.0.30": "c69458f1bbf3ef5b8da4e934de210659cc9bca04",
+ "2.0.30-asserts": "e13a2d74c5fa5f175ae7cffd4197fe7f78bea304",
+ "2.0.29": "c2369dc425725fff86ba90a9007a4603ddf7941b",
+ "2.0.29-lto": "439b7bd7da11e99065c84a60766e427b03be4206",
+ "2.0.28": "866055ea639d64dfedc625d28ec981e47ce37168",
+ "2.0.28-lto": "ac6ac36f7a02cec857bc1e543e55c686c5bd1256",
+ "2.0.27": "1ac46e3b84955231ab4a4f4cbe0c7ac28c86b8cc",
+ "2.0.27-lto": "79509f70be89d66b8441383de94b3e5a91dedc68",
+ "2.0.26": "823d37b15d1ab61bc9ac0665ceef6951d3703842",
+ "2.0.26-lto": "b92ba43f3ac92ab6f1ce6136a8c5969b68ba6968",
+ "2.0.25": "f6f001b08fbb67935379cf13d17fd9bfdbaff791",
+ "2.0.24": "6ab7fc5622a67e6111d07c4ba61c8d3c8fc33ed2",
+ "2.0.23": "77b065ace39e6ab21446e13f92897f956c80476a",
+ "2.0.23-lto": "3f6dbb899f61fab52e4574beb4f7c8382658aa20",
+ "2.0.22": "6465a9acb820207acf7da44661a7de52d0a1ae3c",
+ "2.0.21": "72f4ec97fbc7ec16c15ae68a75b0a257b2835160",
+ "2.0.20": "e0c15cd14170f407a9eb27fcbad22931dc67feb7",
+ "2.0.20-lto": "d1b26cd17e51c5c705eea69b9545975e3705c058",
+ "2.0.19": "9b9ff2dabfb4a7fbacbc004c0bead12a60f9d05c",
+ "2.0.19-lto": "4487f6c5107e7882ae2bad6d26c34ffdceb713f0",
+ "2.0.18": "c2ac7520fad29a7937ed60ab6a95b08eb374c7ba",
+ "2.0.17": "f5c45e60392b82f603e3a8039c62db294fab02d2",
+ "2.0.16": "80d9674f2fafa6b9346d735c42d5c52b8cc8aa8e",
+ "2.0.15": "89202930a98fe7f9ed59b574469a9471b0bda7dd",
+ "2.0.14": "fc5562126762ab26c4757147a3b4c24e85a7289e",
+ "2.0.13": "ce0e4a4d1cab395ee5082a60ebb4f3891a94b256",
+ "2.0.12": "dcf819a7821f8db0c8f15ac336fea8960ec204f5",
+ "2.0.11": "4764c5c323a474f7ba28ae991b0c9024fccca43c",
+ "2.0.10": "37fc7647c754ac9a28ad588c143b82286de0ef71",
+ "2.0.9": "d8e430f9a9b6e87502f826c39e7684852f59624f",
+ "2.0.8": "e4ed6c79f4db8b175d9bbe55869b697aba9bcf2a",
+ "2.0.7": "d7a29d82b320e471203b69d43aaf03b560eedc54",
+ "2.0.6": "4ba921c8c8fe2e8cae071ca9889d5c27f5debd87",
+ "2.0.5": "461f0f118d8d8e6cfd84e077f3eb010c17a39032",
+ "2.0.4": "eefeb3e623af023844ac477d70d1fd8a668f5110",
+ "2.0.3": "7a7f38ca19da152d4cd6da4776921a0f1e3f3e3f",
+ "2.0.2": "ede25d889a0abe63360d4c5d420087c8753b8bbe",
+ "2.0.1": "13e29bd55185e3c12802bc090b4507901856b2ba",
+ "2.0.0": "5974288502aab433d45f53511e961aaca4079d86",
+ "1.40.1": "536568644fd67d53778f6111fdd5f64ad3f4c539",
+ "1.40.0": "edf24e7233e0def312a08cc8dcec63a461155da1",
+ "1.39.20": "e7e39da9c81faecd9ecf44065cee864d76e4e34d",
+ "1.39.19": "665121d026cafc46c29b30d6d4c45ed73eedbb7e",
+ "1.39.18": "1914a1543f08cd8e41f44c2bb05f7a90d1920275",
+ "1.39.17": "9bc968c0e49b1c795ecddb87391b265911e2adcb",
+ "1.39.16": "ae5001fac3849895a873e422a2a80afc90f3b798",
+ "1.39.15": "3880c744c068986d4ee781a61f7b2e820043e11f",
+ "1.39.14": "574ad04affb82cc36a32dd89b2a87bea4fb30eba",
+ "1.39.13": "7b3cd38017f7c582cfa3ac24a9f12aa6a8dca51f",
+ "1.39.12": "e13b86d4dbd9a986525ef27d4ad8157949b9bc3a",
+ "1.39.11": "6584e2d88570ee55914db92a3bad84f99e5bdd82",
+ "1.39.10": "65d33d604d3fa0ebe03548378b898fc6608e9cb8",
+ "1.39.9": "122396dfad60e1b2a83ccefa74a1425a2e05b5cb",
+ "1.39.8": "9e60f34accb4627d7358223862a7e74291886ab6",
+ "1.39.7": "9a89fff28cc6f75e17976fce1904b280e4beb25d",
+ "1.39.6": "967836071d96d9b7894e492382f5fcb96423fc07",
+ "1.39.5": "b3ddcab6efd749d3ed937fb452ace4e39a825842",
+ "1.39.4": "8bb7b0bbbca74cc58741416cc955011f22ff5ccb",
+ "1.39.3": "b024b71038d1291ed7ec23ecd553bf2c0c8d6da6",
+ "1.39.2": "c630da9163a64e08de3dd948be0a0f7a175d285b",
+ "1.39.1": "40f3caabcef7b52bdde63d3883462414d7a25bec",
+ "1.39.0": "d57bfdd6d43181501bbd3fab502d57c9073ceb49",
+ "1.38.48": "1290d9deb93d67c4649999a8f2c8d9167d38dc04",
+ "1.38.47": "bc367c257409d676e71c5511383228b7aabf1689",
+ "1.38.46": "c89919d252f7cea00d944bdf3bd630cd3c7e7388",
+ "1.38.45": "f3030d9fffcc9e1287cb6b8e72982e94ece31d71",
+ "1.38.44": "e5fd171371c3dcb8806a337f2dfa9b70f598f456",
+ "1.38.43": "737d4a07be76c15124adf3c6ef2c218123f7a67f",
+ "1.38.42": "05f8c01394ddd0838d3cb484ba8ca97a3efc1ac9",
+ "1.38.41": "5c6785a63993ae7a4d5362b32b0be9c85138fb96",
+ "1.38.40": "7b4b328af02eafbc857b8ca1e3d9b12dddc56ef7",
+ "1.38.39": "f42b12c45fd3f4c20de1321402fbc28f8fd21df1",
+ "1.38.38": "80bff2784f8500c1305ca69ba1d9fc84df0e401c",
+ "1.38.37": "0ca6c49e30bc09c3ccefc867df4196a4b4183441",
+ "1.38.36": "d46be49c2aab975333423122239892bd46f52bba",
+ "1.38.35": "98f49919f25e06fa557cbcb1321d4c10e60c87ca",
+ "1.38.34": "048cf9424790cc525a7ea6da340820aae226f3b9",
+ "1.38.33": "3b8cff670e9233a6623563add831647e8689a86b"
+ }
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk
new file mode 100755
index 0000000000..78c0288ca0
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Copyright 2019 The Emscripten Authors. All rights reserved.
+# Emscripten is available under two separate licenses, the MIT license and the
+# University of Illinois/NCSA Open Source License. Both these licenses can be
+# found in the LICENSE file.
+
+# Wrapper script that runs emsdk.py
+
+# First look for python bundled in Emsdk
+if [ -z "$EMSDK_PYTHON" ]; then
+ PYTHON3="$(dirname "$0")/python/3.9.2-1_64bit/bin/python3"
+ if [ -f "$PYTHON3" ]; then
+ EMSDK_PYTHON="$PYTHON3"
+
+ # When using our bundled python we never want the users
+ # PYTHONHOME or PYTHONPATH
+ # https://github.com/emscripten-core/emsdk/issues/598
+ unset PYTHONHOME
+ unset PYTHONPATH
+ fi
+fi
+
+# If bundled python is not found, look for `python3` in PATH. This is especially important on macOS (See:
+# https://github.com/emscripten-core/emsdk/pull/273)
+if [ -z "$EMSDK_PYTHON" ]; then
+ if PYTHON3="$(command -v python3 2>/dev/null)"; then
+ EMSDK_PYTHON=$PYTHON3
+ fi
+fi
+
+# Finally fall back to just looking for `python` in PATH
+if [ -z "$EMSDK_PYTHON" ]; then
+ EMSDK_PYTHON=python
+fi
+
+exec "$EMSDK_PYTHON" "$0.py" "$@"
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.bat
new file mode 100644
index 0000000000..df19d67edd
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.bat
@@ -0,0 +1,38 @@
+@echo off
+
+:: Find python from an explicit location relative to the Emscripten SDK.
+
+setlocal
+
+:: When using our bundled python we never want the users
+:: PYTHONHOME or PYTHONPATH
+:: https://github.com/emscripten-core/emsdk/issues/598
+if exist "%~dp0python\3.9.2-1_64bit\python.exe" (
+ set EMSDK_PY="%~dp0python\3.9.2-1_64bit\python.exe"
+ set PYTHONHOME=
+ set PYTHONPATH=
+ goto end
+)
+
+if exist "%~dp0python\3.9.2-nuget_64bit\python.exe" (
+ set EMSDK_PY="%~dp0python\3.9.2-nuget_64bit\python.exe"
+ set PYTHONHOME=
+ set PYTHONPATH=
+ goto end
+)
+
+:: As a last resort, access from PATH.
+set EMSDK_PY=python
+
+:end
+call %EMSDK_PY% "%~dp0\emsdk.py" %*
+
+endlocal
+
+:: python is not able to set environment variables to the parent calling
+:: process, so therefore have it craft a .bat file, which we invoke after
+:: finishing python execution, to set up the environment variables
+if exist "%~dp0\emsdk_set_env.bat" (
+ call "%~dp0\emsdk_set_env.bat" > nul
+ del /F /Q "%~dp0\emsdk_set_env.bat"
+)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.ps1 b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.ps1
new file mode 100644
index 0000000000..e9e6008c32
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.ps1
@@ -0,0 +1,35 @@
+$ScriptDirectory = Split-Path -parent $PSCommandPath
+
+$PythonLocations = $(
+ "python\3.9.2-1_64bit\python.exe",
+ "python\3.9.2-nuget_64bit\python.exe"
+)
+
+# Find python from an explicit location relative to the Emscripten SDK.
+foreach ($Location in $PythonLocations) {
+ $FullLocation = Join-Path $ScriptDirectory $Location
+ if (Test-Path $FullLocation) {
+ $EMSDK_PY = $FullLocation
+ break
+ }
+}
+
+# As a last resort, access from PATH.
+if (-Not $EMSDK_PY) {
+ $EMSDK_PY = "python"
+}
+
+# Tell EMSDK to create environment variable setter as a .ps1 file
+$env:EMSDK_POWERSHELL = 1
+
+& $EMSDK_PY "$ScriptDirectory/emsdk.py" $args
+
+# python is not able to set environment variables to the parent calling process, so
+# therefore have it craft a .ps1 file, which we invoke after finishing python execution,
+# to set up the environment variables
+if (Test-Path $ScriptDirectory/emsdk_set_env.ps1) {
+ & $ScriptDirectory/emsdk_set_env.ps1
+ Remove-Item $ScriptDirectory/emsdk_set_env.ps1
+}
+
+Remove-Item Env:\EMSDK_POWERSHELL
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.py
new file mode 100755
index 0000000000..f01ebf52fd
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk.py
@@ -0,0 +1,3088 @@
+#!/usr/bin/env python
+# Copyright 2019 The Emscripten Authors. All rights reserved.
+# Emscripten is available under two separate licenses, the MIT license and the
+# University of Illinois/NCSA Open Source License. Both these licenses can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import copy
+from collections import OrderedDict
+import errno
+import json
+import multiprocessing
+import os
+import os.path
+import platform
+import re
+import shutil
+import stat
+import subprocess
+import sys
+import sysconfig
+import zipfile
+if os.name == 'nt':
+ try:
+ import winreg
+ except ImportError:
+ # old python 2 name
+ import _winreg as winreg
+ import ctypes.wintypes
+
+if sys.version_info >= (3,):
+ from urllib.parse import urljoin
+ from urllib.request import urlopen
+ import functools
+else:
+ from urlparse import urljoin
+ from urllib2 import urlopen
+
+
+emsdk_packages_url = 'https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/'
+
+emscripten_releases_repo = 'https://chromium.googlesource.com/emscripten-releases'
+
+emscripten_releases_download_url_template = "https://storage.googleapis.com/webassembly/emscripten-releases-builds/%s/%s/wasm-binaries%s.%s"
+
+# This was previously `master.zip` but we are transitioning to `main` and
+# `HEAD.zip` works for both cases. In future we could switch this to
+# `main.zip` perhaps.
+emsdk_zip_download_url = 'https://github.com/emscripten-core/emsdk/archive/HEAD.zip'
+
+download_dir = 'downloads/'
+
+extra_release_tag = None
+
+# Enable this to do very verbose printing about the different steps that are
+# being run. Useful for debugging.
+VERBOSE = int(os.getenv('EMSDK_VERBOSE', '0'))
+QUIET = int(os.getenv('EMSDK_QUIET', '0'))
+TTY_OUTPUT = not os.getenv('EMSDK_NOTTY', not sys.stdout.isatty())
+
+
+def info(msg):
+ if not QUIET:
+ print(msg, file=sys.stderr)
+
+
+def errlog(msg):
+ print(msg, file=sys.stderr)
+
+
+def exit_with_error(msg):
+ errlog('error: %s' % msg)
+ sys.exit(1)
+
+
+WINDOWS = False
+MINGW = False
+MSYS = False
+MACOS = False
+LINUX = False
+
+if 'EMSDK_OS' in os.environ:
+ EMSDK_OS = os.environ['EMSDK_OS']
+ if EMSDK_OS == 'windows':
+ WINDOWS = True
+ elif EMSDK_OS == 'linux':
+ LINUX = True
+ elif EMSDK_OS == 'macos':
+ MACOS = True
+ else:
+ assert False, 'EMSDK_OS must be one of: windows, linux, macos'
+else:
+ if os.name == 'nt' or ('windows' in os.getenv('SYSTEMROOT', '').lower()) or ('windows' in os.getenv('COMSPEC', '').lower()):
+ WINDOWS = True
+
+ if os.getenv('MSYSTEM'):
+ MSYS = True
+ # Some functions like os.path.normpath() exhibit different behavior between
+ # different versions of Python, so we need to distinguish between the MinGW
+ # and MSYS versions of Python
+ if sysconfig.get_platform() == 'mingw':
+ MINGW = True
+ if os.getenv('MSYSTEM') != 'MSYS' and os.getenv('MSYSTEM') != 'MINGW64':
+ # https://stackoverflow.com/questions/37460073/msys-vs-mingw-internal-environment-variables
+ errlog('Warning: MSYSTEM environment variable is present, and is set to "' + os.getenv('MSYSTEM') + '". This shell has not been tested with emsdk and may not work.')
+
+ if platform.mac_ver()[0] != '':
+ MACOS = True
+
+ if not MACOS and (platform.system() == 'Linux'):
+ LINUX = True
+
+UNIX = (MACOS or LINUX)
+
+
+# Pick which shell of 4 shells to use
+POWERSHELL = bool(os.getenv('EMSDK_POWERSHELL'))
+CSH = bool(os.getenv('EMSDK_CSH'))
+CMD = bool(os.getenv('EMSDK_CMD'))
+BASH = bool(os.getenv('EMSDK_BASH'))
+FISH = bool(os.getenv('EMSDK_FISH'))
+
+if WINDOWS and BASH:
+ MSYS = True
+
+if not CSH and not POWERSHELL and not BASH and not CMD and not FISH:
+ # Fall back to default of `cmd` on windows and `bash` otherwise
+ if WINDOWS and not MSYS:
+ CMD = True
+ else:
+ BASH = True
+
+if WINDOWS:
+ ENVPATH_SEPARATOR = ';'
+else:
+ ENVPATH_SEPARATOR = ':'
+
+# platform.machine() may return AMD64 on windows, so standardize the case.
+machine = os.getenv('EMSDK_ARCH', platform.machine().lower())
+if machine.startswith('x64') or machine.startswith('amd64') or machine.startswith('x86_64'):
+ ARCH = 'x86_64'
+elif machine.endswith('86'):
+ ARCH = 'x86'
+elif machine.startswith('aarch64') or machine.lower().startswith('arm64'):
+ if WINDOWS:
+ errlog('No support for Windows on Arm, fallback to x64')
+ ARCH = 'x86_64'
+ else:
+ ARCH = 'arm64'
+elif machine.startswith('arm'):
+ ARCH = 'arm'
+else:
+ exit_with_error('unknown machine architecture: ' + machine)
+
+
+# Don't saturate all cores to not steal the whole system, but be aggressive.
+CPU_CORES = int(os.getenv('EMSDK_NUM_CORES', max(multiprocessing.cpu_count() - 1, 1)))
+
+CMAKE_BUILD_TYPE_OVERRIDE = None
+
+# If true, perform a --shallow clone of git.
+GIT_CLONE_SHALLOW = False
+
+# If true, LLVM backend is built with tests enabled, and Binaryen is built with
+# Visual Studio static analyzer enabled.
+BUILD_FOR_TESTING = False
+
+# If 'auto', assertions are decided by the build type
+# (Release&MinSizeRel=disabled, Debug&RelWithDebInfo=enabled)
+# Other valid values are 'ON' and 'OFF'
+ENABLE_LLVM_ASSERTIONS = 'auto'
+
+# If true, keeps the downloaded archive files.
+KEEP_DOWNLOADS = bool(os.getenv('EMSDK_KEEP_DOWNLOADS'))
+
+
+def os_name():
+ if WINDOWS:
+ return 'win'
+ elif LINUX:
+ return 'linux'
+ elif MACOS:
+ return 'mac'
+ else:
+ raise Exception('unknown OS')
+
+
+def debug_print(msg):
+ if VERBOSE:
+ errlog(msg)
+
+
+def to_unix_path(p):
+ return p.replace('\\', '/')
+
+
+EMSDK_PATH = to_unix_path(os.path.dirname(os.path.realpath(__file__)))
+
+EMSDK_SET_ENV = ""
+if POWERSHELL:
+ EMSDK_SET_ENV = os.path.join(EMSDK_PATH, 'emsdk_set_env.ps1')
+else:
+ EMSDK_SET_ENV = os.path.join(EMSDK_PATH, 'emsdk_set_env.bat')
+
+
+# Parses https://github.com/emscripten-core/emscripten/tree/d6aced8 to a pair (https://github.com/emscripten-core/emscripten, d6aced8)
+def parse_github_url_and_refspec(url):
+ if not url:
+ return ('', '')
+
+ if url.endswith(('/tree/', '/tree', '/commit/', '/commit')):
+ raise Exception('Malformed git URL and refspec ' + url + '!')
+
+ if '/tree/' in url:
+ if url.endswith('/'):
+ raise Exception('Malformed git URL and refspec ' + url + '!')
+ return url.split('/tree/')
+ elif '/commit/' in url:
+ if url.endswith('/'):
+ raise Exception('Malformed git URL and refspec ' + url + '!')
+ return url.split('/commit/')
+ else:
+ return (url, 'main') # Assume the default branch is main in the absence of a refspec
+
+
+ARCHIVE_SUFFIXES = ('zip', '.tar', '.gz', '.xz', '.tbz2', '.bz2')
+
+
+# Finds the given executable 'program' in PATH. Operates like the Unix tool 'which'.
+def which(program):
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and (WINDOWS or os.access(fpath, os.X_OK))
+
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ path = path.strip('"')
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ if WINDOWS and '.' not in fname:
+ if is_exe(exe_file + '.exe'):
+ return exe_file + '.exe'
+ if is_exe(exe_file + '.cmd'):
+ return exe_file + '.cmd'
+ if is_exe(exe_file + '.bat'):
+ return exe_file + '.bat'
+
+ return None
+
+
+def vswhere(version):
+ try:
+ program_files = os.getenv('ProgramFiles(x86)')
+ if not program_files:
+ program_files = os.environ['ProgramFiles']
+ vswhere_path = os.path.join(program_files, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe')
+ # Source: https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022
+ tools_arch = 'ARM64' if ARCH == 'arm64' else 'x86.x64'
+ # The "-products *" allows detection of Build Tools, the "-prerelease" allows detection of Preview version
+ # of Visual Studio and Build Tools.
+ output = json.loads(subprocess.check_output([vswhere_path, '-latest', '-products', '*', '-prerelease', '-version', '[%s.0,%s.0)' % (version, version + 1), '-requires', 'Microsoft.VisualStudio.Component.VC.Tools.' + tools_arch, '-property', 'installationPath', '-format', 'json']))
+ return str(output[0]['installationPath'])
+ except Exception:
+ return ''
+
+
+def vs_filewhere(installation_path, platform, file):
+ try:
+ vcvarsall = os.path.join(installation_path, 'VC\\Auxiliary\\Build\\vcvarsall.bat')
+ env = subprocess.check_output('cmd /c "%s" %s & where %s' % (vcvarsall, platform, file))
+ paths = [path[:-len(file)] for path in env.split('\r\n') if path.endswith(file)]
+ return paths[0]
+ except Exception:
+ return ''
+
+
+CMAKE_GENERATOR = 'Unix Makefiles'
+if WINDOWS:
+ # Detect which CMake generator to use when building on Windows
+ if '--mingw' in sys.argv:
+ CMAKE_GENERATOR = 'MinGW Makefiles'
+ elif '--vs2022' in sys.argv:
+ CMAKE_GENERATOR = 'Visual Studio 17'
+ elif '--vs2019' in sys.argv:
+ CMAKE_GENERATOR = 'Visual Studio 16'
+ elif len(vswhere(17)) > 0:
+ CMAKE_GENERATOR = 'Visual Studio 17'
+ elif len(vswhere(16)) > 0:
+ CMAKE_GENERATOR = 'Visual Studio 16'
+ elif which('mingw32-make') is not None and which('g++') is not None:
+ CMAKE_GENERATOR = 'MinGW Makefiles'
+ else:
+ # No detected generator
+ CMAKE_GENERATOR = ''
+
+
+sys.argv = [a for a in sys.argv if a not in ('--mingw', '--vs2019', '--vs2022')]
+
+
+# Computes a suitable path prefix to use when building with a given generator.
+def cmake_generator_prefix():
+ if CMAKE_GENERATOR == 'Visual Studio 17':
+ return '_vs2022'
+ if CMAKE_GENERATOR == 'Visual Studio 16':
+ return '_vs2019'
+ elif CMAKE_GENERATOR == 'MinGW Makefiles':
+ return '_mingw'
+ # Unix Makefiles do not specify a path prefix for backwards path compatibility
+ return ''
+
+
+# Removes a directory tree even if it was readonly, and doesn't throw exception
+# on failure.
+def remove_tree(d):
+ debug_print('remove_tree(' + str(d) + ')')
+ if not os.path.exists(d):
+ return
+ try:
+ def remove_readonly_and_try_again(func, path, exc_info):
+ if not (os.stat(path).st_mode & stat.S_IWRITE):
+ os.chmod(path, stat.S_IWRITE)
+ func(path)
+ else:
+ raise
+ shutil.rmtree(d, onerror=remove_readonly_and_try_again)
+ except Exception as e:
+ debug_print('remove_tree threw an exception, ignoring: ' + str(e))
+
+
+def win_set_environment_variable_direct(key, value, system=True):
+ folder = None
+ try:
+ if system:
+ # Read globally from ALL USERS section.
+ folder = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment', 0, winreg.KEY_ALL_ACCESS)
+ else:
+ # Register locally from CURRENT USER section.
+ folder = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, 'Environment', 0, winreg.KEY_ALL_ACCESS)
+ winreg.SetValueEx(folder, key, 0, winreg.REG_EXPAND_SZ, value)
+ debug_print('Set key=' + key + ' with value ' + value + ' in registry.')
+ return True
+ except Exception as e:
+ # 'Access is denied.'
+ if e.args[3] == 5:
+ exit_with_error('failed to set the environment variable \'' + key + '\'! Setting environment variables permanently requires administrator access. Please rerun this command with administrative privileges. This can be done for example by holding down the Ctrl and Shift keys while opening a command prompt in start menu.')
+ errlog('Failed to write environment variable ' + key + ':')
+ errlog(str(e))
+ return False
+ finally:
+ if folder is not None:
+ folder.Close()
+
+
+def win_get_environment_variable(key, system=True, user=True, fallback=True):
+ if (not system and not user and fallback):
+ # if no --system or --permanent flag is provided use shell's value
+ return os.environ[key]
+ try:
+ folder = None
+ try:
+ if system:
+ # Read globally from ALL USERS section.
+ folder = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment')
+ else:
+ # Register locally from CURRENT USER section.
+ folder = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Environment')
+ value = str(winreg.QueryValueEx(folder, key)[0])
+ except Exception:
+ # If reading registry fails for some reason - read via os.environ. This has the drawback
+ # that expansion items such as %PROGRAMFILES% will have been expanded, so
+ # need to be precise not to set these back to system registry, or
+ # expansion items would be lost.
+ if fallback:
+ return os.environ[key]
+ return None
+ finally:
+ if folder is not None:
+ folder.Close()
+
+ except Exception as e:
+ # this catch is if both the registry key threw an exception and the key is not in os.environ
+ if e.args[0] != 2:
+ # 'The system cannot find the file specified.'
+ errlog('Failed to read environment variable ' + key + ':')
+ errlog(str(e))
+ return None
+ return value
+
+
+def win_set_environment_variable(key, value, system, user):
+ debug_print('set ' + str(key) + '=' + str(value) + ', in system=' + str(system))
+ previous_value = win_get_environment_variable(key, system=system, user=user)
+ if previous_value == value:
+ debug_print(' no need to set, since same value already exists.')
+ # No need to elevate UAC for nothing to set the same value, skip.
+ return False
+
+ if not value:
+ try:
+ if system:
+ cmd = ['REG', 'DELETE', 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment', '/V', key, '/f']
+ else:
+ cmd = ['REG', 'DELETE', 'HKCU\\Environment', '/V', key, '/f']
+ debug_print(str(cmd))
+ value = subprocess.call(cmd, stdout=subprocess.PIPE)
+ except Exception:
+ return False
+ return True
+
+ try:
+ if win_set_environment_variable_direct(key, value, system):
+ return True
+ # Escape % signs so that we don't expand references to environment variables.
+ value = value.replace('%', '^%')
+ if len(value) >= 1024:
+ exit_with_error('the new environment variable ' + key + ' is more than 1024 characters long! A value this long cannot be set via command line: please add the environment variable specified above to system environment manually via Control Panel.')
+ cmd = ['SETX', key, value]
+ debug_print(str(cmd))
+ retcode = subprocess.call(cmd, stdout=subprocess.PIPE)
+ if retcode != 0:
+ errlog('ERROR! Failed to set environment variable ' + key + '=' + value + '. You may need to set it manually.')
+ else:
+ return True
+ except Exception as e:
+ errlog('ERROR! Failed to set environment variable ' + key + '=' + value + ':')
+ errlog(str(e))
+ errlog('You may need to set it manually.')
+
+ return False
+
+
+def win_set_environment_variables(env_vars_to_add, system, user):
+ if not env_vars_to_add:
+ return
+
+ changed = False
+
+ for key, value in env_vars_to_add:
+ if win_set_environment_variable(key, value, system, user):
+ if not changed:
+ changed = True
+ print('Setting global environment variables:')
+
+ print(key + ' = ' + value)
+
+ if not changed:
+ print('Global environment variables up to date')
+ return
+
+ # if changes were made then we need to notify other processes
+ try:
+ HWND_BROADCAST = ctypes.wintypes.HWND(0xFFFF) # win32con.HWND_BROADCAST == 65535
+ WM_SETTINGCHANGE = 0x001A # win32con.WM_SETTINGCHANGE == 26
+ SMTO_BLOCK = 0x0001 # win32con.SMTO_BLOCK == 1
+ ctypes.windll.user32.SendMessageTimeoutA(
+ HWND_BROADCAST, # hWnd: notify everyone
+ WM_SETTINGCHANGE, # Msg: registry changed
+ 0, # wParam: Must be 0 when setting changed is sent by users
+ 'Environment', # lParam: Specifically environment variables changed
+ SMTO_BLOCK, # fuFlags: Wait for message to be sent or timeout
+ 100) # uTimeout: 100ms
+ except Exception as e:
+ errlog('SendMessageTimeout failed with error: ' + str(e))
+
+
+def win_delete_environment_variable(key, system=True, user=True):
+ debug_print('win_delete_environment_variable(key=' + key + ', system=' + str(system) + ')')
+ return win_set_environment_variable(key, None, system, user)
+
+
+# Returns the absolute pathname to the given path inside the Emscripten SDK.
+def sdk_path(path):
+ if os.path.isabs(path):
+ return path
+
+ return to_unix_path(os.path.join(EMSDK_PATH, path))
+
+
+# Removes a single file, suppressing exceptions on failure.
+def rmfile(filename):
+ debug_print('rmfile(' + filename + ')')
+ if os.path.lexists(filename):
+ os.remove(filename)
+
+
+# http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python
+def mkdir_p(path):
+ debug_print('mkdir_p(' + path + ')')
+ try:
+ os.makedirs(path)
+ except OSError as exc: # Python >2.5
+ if exc.errno != errno.EEXIST or not os.path.isdir(path):
+ raise
+
+
+def is_nonempty_directory(path):
+ if not os.path.isdir(path):
+ return False
+ return len(os.listdir(path)) != 0
+
+
+def run(cmd, cwd=None, quiet=False):
+ debug_print('run(cmd=' + str(cmd) + ', cwd=' + str(cwd) + ')')
+ process = subprocess.Popen(cmd, cwd=cwd, env=os.environ.copy())
+ process.communicate()
+ if process.returncode != 0 and not quiet:
+ errlog(str(cmd) + ' failed with error code ' + str(process.returncode) + '!')
+ return process.returncode
+
+
+# http://pythonicprose.blogspot.fi/2009/10/python-extract-targz-archive.html
+def untargz(source_filename, dest_dir):
+ print("Unpacking '" + source_filename + "' to '" + dest_dir + "'")
+ mkdir_p(dest_dir)
+ returncode = run(['tar', '-xvf' if VERBOSE else '-xf', sdk_path(source_filename), '--strip', '1'], cwd=dest_dir)
+ # tfile = tarfile.open(source_filename, 'r:gz')
+ # tfile.extractall(dest_dir)
+ return returncode == 0
+
+
+# On Windows, it is not possible to reference path names that are longer than
+# ~260 characters, unless the path is referenced via a "\\?\" prefix.
+# See https://msdn.microsoft.com/en-us/library/aa365247.aspx#maxpath and http://stackoverflow.com/questions/3555527/python-win32-filename-length-workaround
+# In that mode, forward slashes cannot be used as delimiters.
+def fix_potentially_long_windows_pathname(pathname):
+ if not WINDOWS or MSYS:
+ return pathname
+ # Test if emsdk calls fix_potentially_long_windows_pathname() with long
+ # relative paths (which is problematic)
+ if not os.path.isabs(pathname) and len(pathname) > 200:
+ errlog('Warning: Seeing a relative path "' + pathname + '" which is dangerously long for being referenced as a short Windows path name. Refactor emsdk to be able to handle this!')
+ if pathname.startswith('\\\\?\\'):
+ return pathname
+ pathname = os.path.normpath(pathname.replace('/', '\\'))
+ if MINGW:
+ # MinGW versions of Python return normalized paths with backslashes
+ # converted to forward slashes, so we must use forward slashes in our
+ # prefix
+ return '//?/' + pathname
+ return '\\\\?\\' + pathname
+
+
+# On windows, rename/move will fail if the destination exists, and there is no
+# race-free way to do it. This method removes the destination if it exists, so
+# the move always works
+def move_with_overwrite(src, dest):
+ if os.path.exists(dest):
+ os.remove(dest)
+ os.rename(src, dest)
+
+
+# http://stackoverflow.com/questions/12886768/simple-way-to-unzip-file-in-python-on-all-oses
+def unzip(source_filename, dest_dir):
+ print("Unpacking '" + source_filename + "' to '" + dest_dir + "'")
+ mkdir_p(dest_dir)
+ common_subdir = None
+ try:
+ with zipfile.ZipFile(source_filename) as zf:
+ # Implement '--strip 1' behavior to unzipping by testing if all the files
+ # in the zip reside in a common subdirectory, and if so, we move the
+ # output tree at the end of uncompression step.
+ for member in zf.infolist():
+ words = member.filename.split('/')
+ if len(words) > 1: # If there is a directory component?
+ if common_subdir is None:
+ common_subdir = words[0]
+ elif common_subdir != words[0]:
+ common_subdir = None
+ break
+ else:
+ common_subdir = None
+ break
+
+ unzip_to_dir = dest_dir
+ if common_subdir:
+ unzip_to_dir = os.path.join(os.path.dirname(dest_dir), 'unzip_temp')
+
+ # Now do the actual decompress.
+ for member in zf.infolist():
+ zf.extract(member, fix_potentially_long_windows_pathname(unzip_to_dir))
+ dst_filename = os.path.join(unzip_to_dir, member.filename)
+
+ # See: https://stackoverflow.com/questions/42326428/zipfile-in-python-file-permission
+ unix_attributes = member.external_attr >> 16
+ if unix_attributes:
+ os.chmod(dst_filename, unix_attributes)
+
+ # Move the extracted file to its final location without the base
+ # directory name, if we are stripping that away.
+ if common_subdir:
+ if not member.filename.startswith(common_subdir):
+ raise Exception('Unexpected filename "' + member.filename + '"!')
+ stripped_filename = '.' + member.filename[len(common_subdir):]
+ final_dst_filename = os.path.join(dest_dir, stripped_filename)
+ # Check if a directory
+ if stripped_filename.endswith('/'):
+ d = fix_potentially_long_windows_pathname(final_dst_filename)
+ if not os.path.isdir(d):
+ os.mkdir(d)
+ else:
+ parent_dir = os.path.dirname(fix_potentially_long_windows_pathname(final_dst_filename))
+ if parent_dir and not os.path.exists(parent_dir):
+ os.makedirs(parent_dir)
+ move_with_overwrite(fix_potentially_long_windows_pathname(dst_filename), fix_potentially_long_windows_pathname(final_dst_filename))
+
+ if common_subdir:
+ remove_tree(unzip_to_dir)
+ except zipfile.BadZipfile as e:
+ errlog("Unzipping file '" + source_filename + "' failed due to reason: " + str(e) + "! Removing the corrupted zip file.")
+ rmfile(source_filename)
+ return False
+ except Exception as e:
+ errlog("Unzipping file '" + source_filename + "' failed due to reason: " + str(e))
+ return False
+
+ return True
+
+
+# This function interprets whether the given string looks like a path to a
+# directory instead of a file, without looking at the actual filesystem.
+# 'a/b/c' points to directory, so does 'a/b/c/', but 'a/b/c.x' is parsed as a
+# filename
+def path_points_to_directory(path):
+ if path == '.':
+ return True
+ last_slash = max(path.rfind('/'), path.rfind('\\'))
+ last_dot = path.rfind('.')
+ no_suffix = last_dot < last_slash or last_dot == -1
+ if no_suffix:
+ return True
+ suffix = path[last_dot:]
+ # Very simple logic for the only file suffixes used by emsdk downloader. Other
+ # suffixes, like 'clang-3.2' are treated as dirs.
+ if suffix in ('.exe', '.zip', '.txt'):
+ return False
+ else:
+ return True
+
+
+def get_content_length(download):
+ try:
+ meta = download.info()
+ if hasattr(meta, "getheaders") and hasattr(meta.getheaders, "Content-Length"):
+ return int(meta.getheaders("Content-Length")[0])
+ elif hasattr(download, "getheader") and download.getheader('Content-Length'):
+ return int(download.getheader('Content-Length'))
+ elif hasattr(meta, "getheader") and meta.getheader('Content-Length'):
+ return int(meta.getheader('Content-Length'))
+ except Exception:
+ pass
+
+ return 0
+
+
+def get_download_target(url, dstpath, filename_prefix=''):
+ file_name = filename_prefix + url.split('/')[-1]
+ if path_points_to_directory(dstpath):
+ file_name = os.path.join(dstpath, file_name)
+ else:
+ file_name = dstpath
+
+ # Treat all relative destination paths as relative to the SDK root directory,
+ # not the current working directory.
+ file_name = sdk_path(file_name)
+
+ return file_name
+
+
+def download_with_curl(url, file_name):
+ print("Downloading: %s from %s" % (file_name, url))
+ if not which('curl'):
+ exit_with_error('curl not found in PATH')
+ # -#: show progress bar
+ # -L: Follow HTTP 3XX redirections
+ # -f: Fail on HTTP errors
+ subprocess.check_call(['curl', '-#', '-f', '-L', '-o', file_name, url])
+
+
+def download_with_urllib(url, file_name):
+ u = urlopen(url)
+ file_size = get_content_length(u)
+ if file_size > 0:
+ print("Downloading: %s from %s, %s Bytes" % (file_name, url, file_size))
+ else:
+ print("Downloading: %s from %s" % (file_name, url))
+
+ file_size_dl = 0
+ # Draw a progress bar 80 chars wide (in non-TTY mode)
+ progress_max = 80 - 4
+ progress_shown = 0
+ block_sz = 256 * 1024
+ if not TTY_OUTPUT:
+ print(' [', end='')
+
+ with open(file_name, 'wb') as f:
+ while True:
+ buffer = u.read(block_sz)
+ if not buffer:
+ break
+
+ file_size_dl += len(buffer)
+ f.write(buffer)
+ if file_size:
+ percent = file_size_dl * 100.0 / file_size
+ if TTY_OUTPUT:
+ status = r" %10d [%3.02f%%]" % (file_size_dl, percent)
+ print(status, end='\r')
+ else:
+ while progress_shown < progress_max * percent / 100:
+ print('-', end='')
+ sys.stdout.flush()
+ progress_shown += 1
+
+ if not TTY_OUTPUT:
+ print(']')
+ sys.stdout.flush()
+
+ debug_print('finished downloading (%d bytes)' % file_size_dl)
+
+
+# On success, returns the filename on the disk pointing to the destination file that was produced
+# On failure, returns None.
+def download_file(url, dstpath, download_even_if_exists=False,
+ filename_prefix='', silent=False):
+ debug_print('download_file(url=' + url + ', dstpath=' + dstpath + ')')
+ file_name = get_download_target(url, dstpath, filename_prefix)
+
+ if os.path.exists(file_name) and not download_even_if_exists:
+ print("File '" + file_name + "' already downloaded, skipping.")
+ return file_name
+
+ mkdir_p(os.path.dirname(file_name))
+
+ try:
+ # Use curl on macOS to avoid CERTIFICATE_VERIFY_FAILED issue with
+ # python's urllib:
+ # https://stackoverflow.com/questions/40684543/how-to-make-python-use-ca-certificates-from-mac-os-truststore
+ # Unlike on linux or windows, curl is always available on macOS systems.
+ if MACOS:
+ download_with_curl(url, file_name)
+ else:
+ download_with_urllib(url, file_name)
+ except Exception as e:
+ errlog("Error: Downloading URL '" + url + "': " + str(e))
+ return None
+ except KeyboardInterrupt:
+ rmfile(file_name)
+ raise
+
+ return file_name
+
+
+def run_get_output(cmd, cwd=None):
+ debug_print('run_get_output(cmd=' + str(cmd) + ', cwd=' + str(cwd) + ')')
+ process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, env=os.environ.copy(), universal_newlines=True)
+ stdout, stderr = process.communicate()
+ return (process.returncode, stdout, stderr)
+
+
+cached_git_executable = None
+
+
+# must_succeed: If false, the search is performed silently without printing out
+# errors if not found. Empty string is returned if git is not found.
+# If true, the search is required to succeed, and the execution
+# will terminate with sys.exit(1) if not found.
+def GIT(must_succeed=True):
+ global cached_git_executable
+ if cached_git_executable is not None:
+ return cached_git_executable
+ # The order in the following is important, and specifies the preferred order
+ # of using the git tools. Primarily use git from emsdk if installed. If not,
+ # use system git.
+ gits = ['git/1.9.4/bin/git.exe', which('git')]
+ for git in gits:
+ try:
+ ret, stdout, stderr = run_get_output([git, '--version'])
+ if ret == 0:
+ cached_git_executable = git
+ return git
+ except Exception:
+ pass
+ if must_succeed:
+ if WINDOWS:
+ msg = "git executable was not found. Please install it by typing 'emsdk install git-1.9.4', or alternatively by installing it manually from http://git-scm.com/downloads . If you install git manually, remember to add it to PATH"
+ elif MACOS:
+ msg = "git executable was not found. Please install git for this operation! This can be done from http://git-scm.com/ , or by installing XCode and then the XCode Command Line Tools (see http://stackoverflow.com/questions/9329243/xcode-4-4-command-line-tools )"
+ elif LINUX:
+ msg = "git executable was not found. Please install git for this operation! This can be probably be done using your package manager, see http://git-scm.com/book/en/Getting-Started-Installing-Git"
+ else:
+ msg = "git executable was not found. Please install git for this operation!"
+ exit_with_error(msg)
+ # Not found
+ return ''
+
+
+def git_repo_version(repo_path):
+ returncode, stdout, stderr = run_get_output([GIT(), 'log', '-n', '1', '--pretty="%aD %H"'], cwd=repo_path)
+ if returncode == 0:
+ return stdout.strip()
+ else:
+ return ""
+
+
+def git_recent_commits(repo_path, n=20):
+ returncode, stdout, stderr = run_get_output([GIT(), 'log', '-n', str(n), '--pretty="%H"'], cwd=repo_path)
+ if returncode == 0:
+ return stdout.strip().replace('\r', '').replace('"', '').split('\n')
+ else:
+ return []
+
+
+def git_clone(url, dstpath, branch):
+ debug_print('git_clone(url=' + url + ', dstpath=' + dstpath + ')')
+ if os.path.isdir(os.path.join(dstpath, '.git')):
+ debug_print("Repository '" + url + "' already cloned to directory '" + dstpath + "', skipping.")
+ return True
+ mkdir_p(dstpath)
+ git_clone_args = ['--recurse-submodules', '--branch', branch] # Do not check out a branch (installer will issue a checkout command right after)
+ if GIT_CLONE_SHALLOW:
+ git_clone_args += ['--depth', '1']
+ print('Cloning from ' + url + '...')
+ return run([GIT(), 'clone'] + git_clone_args + [url, dstpath]) == 0
+
+
+def git_pull(repo_path, branch_or_tag):
+ debug_print('git_pull(repo_path=' + repo_path + ', branch/tag=' + branch_or_tag + ')')
+ ret = run([GIT(), 'fetch', '--quiet', 'origin'], repo_path)
+ if ret != 0:
+ return False
+ try:
+ print("Fetching latest changes to the branch/tag '" + branch_or_tag + "' for '" + repo_path + "'...")
+ ret = run([GIT(), 'fetch', '--quiet', 'origin'], repo_path)
+ if ret != 0:
+ return False
+ # this line assumes that the user has not gone and manually messed with the
+ # repo and added new remotes to ambiguate the checkout.
+ ret = run([GIT(), 'checkout', '--recurse-submodules', '--quiet', branch_or_tag], repo_path)
+ if ret != 0:
+ return False
+ # Test if branch_or_tag is a branch, or if it is a tag that needs to be updated
+ target_is_tag = run([GIT(), 'symbolic-ref', '-q', 'HEAD'], repo_path, quiet=True)
+ if not target_is_tag:
+ # update branch to latest (not needed for tags)
+ # this line assumes that the user has not gone and made local changes to the repo
+ ret = run([GIT(), 'merge', '--ff-only', 'origin/' + branch_or_tag], repo_path)
+ if ret != 0:
+ return False
+ run([GIT(), 'submodule', 'update', '--init'], repo_path, quiet=True)
+ except Exception:
+ errlog('git operation failed!')
+ return False
+ print("Successfully updated and checked out branch/tag '" + branch_or_tag + "' on repository '" + repo_path + "'")
+ print("Current repository version: " + git_repo_version(repo_path))
+ return True
+
+
+def git_clone_checkout_and_pull(url, dstpath, branch):
+ debug_print('git_clone_checkout_and_pull(url=' + url + ', dstpath=' + dstpath + ', branch=' + branch + ')')
+
+ # If the repository has already been cloned before, issue a pull operation. Otherwise do a new clone.
+ if os.path.isdir(os.path.join(dstpath, '.git')):
+ return git_pull(dstpath, branch)
+ else:
+ return git_clone(url, dstpath, branch)
+
+
+# Each tool can have its own build type, or it can be overridden on the command
+# line.
+def decide_cmake_build_type(tool):
+ if CMAKE_BUILD_TYPE_OVERRIDE:
+ return CMAKE_BUILD_TYPE_OVERRIDE
+ else:
+ return tool.cmake_build_type
+
+
+# The root directory of the build.
+def llvm_build_dir(tool):
+ generator_suffix = cmake_generator_prefix()
+ bitness_suffix = '_32' if tool.bitness == 32 else '_64'
+
+ if hasattr(tool, 'git_branch'):
+ build_dir = 'build_' + tool.git_branch.replace(os.sep, '-') + generator_suffix + bitness_suffix
+ else:
+ build_dir = 'build_' + tool.version + generator_suffix + bitness_suffix
+ return build_dir
+
+
+def exe_suffix(filename):
+ if WINDOWS and not filename.endswith('.exe'):
+ filename += '.exe'
+ return filename
+
+
+# The directory where the binaries are produced. (relative to the installation
+# root directory of the tool)
+def llvm_build_bin_dir(tool):
+ build_dir = llvm_build_dir(tool)
+ if WINDOWS and 'Visual Studio' in CMAKE_GENERATOR:
+ old_llvm_bin_dir = os.path.join(build_dir, 'bin', decide_cmake_build_type(tool))
+
+ new_llvm_bin_dir = None
+ default_cmake_build_type = decide_cmake_build_type(tool)
+ cmake_build_types = [default_cmake_build_type, 'Release', 'RelWithDebInfo', 'MinSizeRel', 'Debug']
+ for build_type in cmake_build_types:
+ d = os.path.join(build_dir, build_type, 'bin')
+ if os.path.isfile(os.path.join(tool.installation_path(), d, exe_suffix('clang'))):
+ new_llvm_bin_dir = d
+ break
+
+ if new_llvm_bin_dir and os.path.exists(os.path.join(tool.installation_path(), new_llvm_bin_dir)):
+ return new_llvm_bin_dir
+ elif os.path.exists(os.path.join(tool.installation_path(), old_llvm_bin_dir)):
+ return old_llvm_bin_dir
+ return os.path.join(build_dir, default_cmake_build_type, 'bin')
+ else:
+ return os.path.join(build_dir, 'bin')
+
+
+def build_env(generator):
+ build_env = os.environ.copy()
+
+ # To work around a build issue with older Mac OS X builds, add -stdlib=libc++ to all builds.
+ # See https://groups.google.com/forum/#!topic/emscripten-discuss/5Or6QIzkqf0
+ if MACOS:
+ build_env['CXXFLAGS'] = ((build_env['CXXFLAGS'] + ' ') if hasattr(build_env, 'CXXFLAGS') else '') + '-stdlib=libc++'
+ if WINDOWS:
+ # MSBuild.exe has an internal mechanism to avoid N^2 oversubscription of threads in its two-tier build model, see
+ # https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
+ build_env['UseMultiToolTask'] = 'true'
+ build_env['EnforceProcessCountAcrossBuilds'] = 'true'
+ return build_env
+
+
+def make_build(build_root, build_type):
+ debug_print('make_build(build_root=' + build_root + ', build_type=' + build_type + ')')
+ if CPU_CORES > 1:
+ print('Performing a parallel build with ' + str(CPU_CORES) + ' cores.')
+ else:
+ print('Performing a singlethreaded build.')
+
+ make = ['cmake', '--build', '.', '--config', build_type]
+ if 'Visual Studio' in CMAKE_GENERATOR:
+ # Visual Studio historically has had a two-tier problem in its build system design. A single MSBuild.exe instance only governs
+ # the build of a single project (.exe/.lib/.dll) in a solution. Passing the -j parameter above will only enable multiple MSBuild.exe
+ # instances to be spawned to build multiple projects in parallel, but each MSBuild.exe is still singlethreaded.
+ # To enable each MSBuild.exe instance to also compile several .cpp files in parallel inside a single project, pass the extra
+ # MSBuild.exe specific "Multi-ToolTask" (MTT) setting /p:CL_MPCount. This enables each MSBuild.exe to parallelize builds wide.
+ # This requires CMake 3.12 or newer.
+ make += ['-j', str(CPU_CORES), '--', '/p:CL_MPCount=' + str(CPU_CORES)]
+ else:
+ # Pass -j to native make, CMake might not support -j option.
+ make += ['--', '-j', str(CPU_CORES)]
+
+ # Build
+ try:
+ print('Running build: ' + str(make))
+ ret = subprocess.check_call(make, cwd=build_root, env=build_env(CMAKE_GENERATOR))
+ if ret != 0:
+ errlog('Build failed with exit code ' + ret + '!')
+ errlog('Working directory: ' + build_root)
+ return False
+ except Exception as e:
+ errlog('Build failed due to exception!')
+ errlog('Working directory: ' + build_root)
+ errlog(str(e))
+ return False
+
+ return True
+
+
+def cmake_configure(generator, build_root, src_root, build_type, extra_cmake_args=[]):
+ debug_print('cmake_configure(generator=' + str(generator) + ', build_root=' + str(build_root) + ', src_root=' + str(src_root) + ', build_type=' + str(build_type) + ', extra_cmake_args=' + str(extra_cmake_args) + ')')
+ # Configure
+ if not os.path.isdir(build_root):
+ # Create build output directory if it doesn't yet exist.
+ os.mkdir(build_root)
+ try:
+ if generator:
+ generator = ['-G', generator]
+ else:
+ generator = []
+
+ cmdline = ['cmake'] + generator + ['-DCMAKE_BUILD_TYPE=' + build_type, '-DPYTHON_EXECUTABLE=' + sys.executable]
+ # Target macOS 10.14 at minimum, to support widest range of Mac devices
+ # from "Early 2008" and newer:
+ # https://en.wikipedia.org/wiki/MacBook_(2006-2012)#Supported_operating_systems
+ cmdline += ['-DCMAKE_OSX_DEPLOYMENT_TARGET=10.14']
+ cmdline += extra_cmake_args + [src_root]
+
+ print('Running CMake: ' + str(cmdline))
+
+ # Specify the deployment target also as an env. var, since some Xcode versions
+ # read this instead of the CMake field.
+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.14'
+
+ def quote_parens(x):
+ if ' ' in x:
+ return '"' + x.replace('"', '\\"') + '"'
+ else:
+ return x
+
+ # Create a file 'recmake.bat/sh' in the build root that user can call to
+ # manually recmake the build tree with the previous build params
+ open(os.path.join(build_root, 'recmake.' + ('bat' if WINDOWS else 'sh')), 'w').write(' '.join(map(quote_parens, cmdline)))
+ ret = subprocess.check_call(cmdline, cwd=build_root, env=build_env(CMAKE_GENERATOR))
+ if ret != 0:
+ errlog('CMake invocation failed with exit code ' + ret + '!')
+ errlog('Working directory: ' + build_root)
+ return False
+ except OSError as e:
+ if e.errno == errno.ENOENT:
+ errlog(str(e))
+ errlog('Could not run CMake, perhaps it has not been installed?')
+ if WINDOWS:
+ errlog('Installing this package requires CMake. Get it from http://www.cmake.org/')
+ elif LINUX:
+ errlog('Installing this package requires CMake. Get it via your system package manager (e.g. sudo apt-get install cmake), or from http://www.cmake.org/')
+ elif MACOS:
+ errlog('Installing this package requires CMake. Get it via a macOS package manager (Homebrew: "brew install cmake", or MacPorts: "sudo port install cmake"), or from http://www.cmake.org/')
+ return False
+ raise
+ except Exception as e:
+ errlog('CMake invocation failed due to exception!')
+ errlog('Working directory: ' + build_root)
+ errlog(str(e))
+ return False
+
+ return True
+
+
+def xcode_sdk_version():
+ try:
+ output = subprocess.check_output(['xcrun', '--show-sdk-version'])
+ if sys.version_info >= (3,):
+ output = output.decode('utf8')
+ return output.strip().split('.')
+ except Exception:
+ return subprocess.checkplatform.mac_ver()[0].split('.')
+
+
+def cmake_target_platform(tool):
+ # Source: https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2017%202022.html#platform-selection
+ if hasattr(tool, 'arch'):
+ if tool.arch == 'arm64':
+ return 'ARM64'
+ elif tool.arch == 'x86_64':
+ return 'x64'
+ elif tool.arch == 'x86':
+ return 'Win32'
+ if ARCH == 'arm64':
+ return 'ARM64'
+ else:
+ return 'x64' if tool.bitness == 64 else 'Win32'
+
+
+def cmake_host_platform():
+ # Source: https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2017%202022.html#toolset-selection
+ arch_to_cmake_host_platform = {
+ 'arm64': 'ARM64',
+ 'arm': 'ARM',
+ 'x86_64': 'x64',
+ 'x86': 'x86'
+ }
+ return arch_to_cmake_host_platform[ARCH]
+
+
+def get_generator_and_config_args(tool):
+ args = []
+ cmake_generator = CMAKE_GENERATOR
+ if 'Visual Studio 16' in CMAKE_GENERATOR or 'Visual Studio 17' in CMAKE_GENERATOR: # VS2019 or VS2022
+ # With Visual Studio 16 2019, CMake changed the way they specify target arch.
+ # Instead of appending it into the CMake generator line, it is specified
+ # with a -A arch parameter.
+ args += ['-A', cmake_target_platform(tool)]
+ args += ['-Thost=' + cmake_host_platform()]
+ elif 'Visual Studio' in CMAKE_GENERATOR and tool.bitness == 64:
+ cmake_generator += ' Win64'
+ args += ['-Thost=x64']
+ return (cmake_generator, args)
+
+
+def build_llvm(tool):
+ debug_print('build_llvm(' + str(tool) + ')')
+ llvm_root = tool.installation_path()
+ llvm_src_root = os.path.join(llvm_root, 'src')
+ success = git_clone_checkout_and_pull(tool.download_url(), llvm_src_root, tool.git_branch)
+ if not success:
+ return False
+
+ build_dir = llvm_build_dir(tool)
+ build_root = os.path.join(llvm_root, build_dir)
+
+ build_type = decide_cmake_build_type(tool)
+
+ # Configure
+ tests_arg = 'ON' if BUILD_FOR_TESTING else 'OFF'
+
+ enable_assertions = ENABLE_LLVM_ASSERTIONS.lower() == 'on' or (ENABLE_LLVM_ASSERTIONS == 'auto' and build_type.lower() != 'release' and build_type.lower() != 'minsizerel')
+
+ if ARCH == 'x86' or ARCH == 'x86_64':
+ targets_to_build = 'WebAssembly;X86'
+ elif ARCH == 'arm':
+ targets_to_build = 'WebAssembly;ARM'
+ elif ARCH == 'arm64':
+ targets_to_build = 'WebAssembly;AArch64'
+ else:
+ targets_to_build = 'WebAssembly'
+ cmake_generator, args = get_generator_and_config_args(tool)
+ args += ['-DLLVM_TARGETS_TO_BUILD=' + targets_to_build,
+ '-DLLVM_INCLUDE_EXAMPLES=OFF',
+ '-DLLVM_INCLUDE_TESTS=' + tests_arg,
+ '-DCLANG_INCLUDE_TESTS=' + tests_arg,
+ '-DLLVM_ENABLE_ASSERTIONS=' + ('ON' if enable_assertions else 'OFF'),
+ # Disable optional LLVM dependencies, these can cause unwanted .so dependencies
+ # that prevent distributing the generated compiler for end users.
+ '-DLLVM_ENABLE_LIBXML2=OFF', '-DLLVM_ENABLE_TERMINFO=OFF', '-DLLDB_ENABLE_LIBEDIT=OFF',
+ '-DLLVM_ENABLE_LIBEDIT=OFF', '-DLLVM_ENABLE_LIBPFM=OFF']
+ # LLVM build system bug: compiler-rt does not build on Windows. It insists on performing a CMake install step that writes to C:\Program Files. Attempting
+ # to reroute that to build_root directory then fails on an error
+ # file INSTALL cannot find
+ # "C:/code/emsdk/llvm/git/build_master_vs2017_64/$(Configuration)/lib/clang/10.0.0/lib/windows/clang_rt.ubsan_standalone-x86_64.lib".
+ # (there instead of $(Configuration), one would need ${CMAKE_BUILD_TYPE} ?)
+ # It looks like compiler-rt is not compatible to build on Windows?
+ args += ['-DLLVM_ENABLE_PROJECTS=clang;lld']
+ # To enable widest possible chance of success for building, let the code
+ # compile through with older toolchains that are about to be deprecated by
+ # upstream LLVM.
+ args += ['-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON']
+
+ if os.getenv('LLVM_CMAKE_ARGS'):
+ extra_args = os.environ['LLVM_CMAKE_ARGS'].split(',')
+ print('Passing the following extra arguments to LLVM CMake configuration: ' + str(extra_args))
+ args += extra_args
+
+ cmakelists_dir = os.path.join(llvm_src_root, 'llvm')
+ success = cmake_configure(cmake_generator, build_root, cmakelists_dir, build_type, args)
+ if not success:
+ return False
+
+ # Make
+ success = make_build(build_root, build_type)
+ return success
+
+
+def build_ninja(tool):
+ debug_print('build_ninja(' + str(tool) + ')')
+ root = os.path.normpath(tool.installation_path())
+ src_root = os.path.join(root, 'src')
+ success = git_clone_checkout_and_pull(tool.download_url(), src_root, tool.git_branch)
+ if not success:
+ return False
+
+ build_dir = llvm_build_dir(tool)
+ build_root = os.path.join(root, build_dir)
+
+ build_type = decide_cmake_build_type(tool)
+
+ # Configure
+ cmake_generator, args = get_generator_and_config_args(tool)
+
+ cmakelists_dir = os.path.join(src_root)
+ success = cmake_configure(cmake_generator, build_root, cmakelists_dir, build_type, args)
+ if not success:
+ return False
+
+ # Make
+ success = make_build(build_root, build_type)
+
+ if success:
+ bin_dir = os.path.join(root, 'bin')
+ mkdir_p(bin_dir)
+ exe_paths = [os.path.join(build_root, 'Release', 'ninja'), os.path.join(build_root, 'ninja')]
+ for e in exe_paths:
+ for s in ['.exe', '']:
+ ninja = e + s
+ if os.path.isfile(ninja):
+ dst = os.path.join(bin_dir, 'ninja' + s)
+ shutil.copyfile(ninja, dst)
+ os.chmod(dst, os.stat(dst).st_mode | stat.S_IEXEC)
+
+ return success
+
+
+def build_ccache(tool):
+ debug_print('build_ccache(' + str(tool) + ')')
+ root = os.path.normpath(tool.installation_path())
+ src_root = os.path.join(root, 'src')
+ success = git_clone_checkout_and_pull(tool.download_url(), src_root, tool.git_branch)
+ if not success:
+ return False
+
+ build_dir = llvm_build_dir(tool)
+ build_root = os.path.join(root, build_dir)
+
+ build_type = decide_cmake_build_type(tool)
+
+ # Configure
+ cmake_generator, args = get_generator_and_config_args(tool)
+ args += ['-DZSTD_FROM_INTERNET=ON']
+
+ cmakelists_dir = os.path.join(src_root)
+ success = cmake_configure(cmake_generator, build_root, cmakelists_dir, build_type, args)
+ if not success:
+ return False
+
+ # Make
+ success = make_build(build_root, build_type)
+
+ if success:
+ bin_dir = os.path.join(root, 'bin')
+ mkdir_p(bin_dir)
+ exe_paths = [os.path.join(build_root, 'Release', 'ccache'), os.path.join(build_root, 'ccache')]
+ for e in exe_paths:
+ for s in ['.exe', '']:
+ ccache = e + s
+ if os.path.isfile(ccache):
+ dst = os.path.join(bin_dir, 'ccache' + s)
+ shutil.copyfile(ccache, dst)
+ os.chmod(dst, os.stat(dst).st_mode | stat.S_IEXEC)
+
+ cache_dir = os.path.join(root, 'cache')
+ open(os.path.join(root, 'emcc_ccache.conf'), 'w').write('''# Set maximum cache size to 10 GB:
+max_size = 10G
+cache_dir = %s
+''' % cache_dir)
+ mkdir_p(cache_dir)
+
+ return success
+
+
+# Finds the newest installed version of a given tool
+def find_latest_installed_tool(name):
+ for t in reversed(tools):
+ if t.id == name and t.is_installed():
+ return t
+
+
+# npm install in Emscripten root directory
+def emscripten_npm_install(tool, directory):
+ node_tool = find_latest_installed_tool('node')
+ if not node_tool:
+ npm_fallback = which('npm')
+ if not npm_fallback:
+ errlog('Failed to find npm command!')
+ errlog('Running "npm ci" in installed Emscripten root directory ' + tool.installation_path() + ' is required!')
+ errlog('Please install node.js first!')
+ return False
+ node_path = os.path.dirname(npm_fallback)
+ else:
+ node_path = os.path.join(node_tool.installation_path(), 'bin')
+
+ npm = os.path.join(node_path, 'npm' + ('.cmd' if WINDOWS else ''))
+ env = os.environ.copy()
+ env["PATH"] = node_path + os.pathsep + env["PATH"]
+ print('Running post-install step: npm ci ...')
+ try:
+ subprocess.check_output(
+ [npm, 'ci', '--production'],
+ cwd=directory, stderr=subprocess.STDOUT, env=env,
+ universal_newlines=True)
+ except subprocess.CalledProcessError as e:
+ errlog('Error running %s:\n%s' % (e.cmd, e.output))
+ return False
+
+ print('Done running: npm ci')
+
+ if os.path.isfile(os.path.join(directory, 'bootstrap.py')):
+ try:
+ subprocess.check_output([sys.executable, os.path.join(directory, 'bootstrap.py')],
+ cwd=directory, stderr=subprocess.STDOUT, env=env,
+ universal_newlines=True)
+ except subprocess.CalledProcessError as e:
+ errlog('Error running %s:\n%s' % (e.cmd, e.output))
+ return False
+
+ print('Done running: Emscripten bootstrap')
+ return True
+
+
+# Binaryen build scripts:
+def binaryen_build_root(tool):
+ build_root = tool.installation_path().strip()
+ if build_root.endswith('/') or build_root.endswith('\\'):
+ build_root = build_root[:-1]
+ generator_prefix = cmake_generator_prefix()
+ build_root = build_root + generator_prefix + '_' + str(tool.bitness) + 'bit_binaryen'
+ return build_root
+
+
+def uninstall_binaryen(tool):
+ debug_print('uninstall_binaryen(' + str(tool) + ')')
+ build_root = binaryen_build_root(tool)
+ print("Deleting path '" + build_root + "'")
+ remove_tree(build_root)
+
+
+def is_binaryen_installed(tool):
+ build_root = binaryen_build_root(tool)
+ return os.path.exists(build_root)
+
+
+def build_binaryen_tool(tool):
+ debug_print('build_binaryen_tool(' + str(tool) + ')')
+ src_root = tool.installation_path()
+ build_root = binaryen_build_root(tool)
+ build_type = decide_cmake_build_type(tool)
+
+ # Configure
+ cmake_generator, args = get_generator_and_config_args(tool)
+ args += ['-DENABLE_WERROR=0'] # -Werror is not useful for end users
+ args += ['-DBUILD_TESTS=0'] # We don't want to build or run tests
+
+ if 'Visual Studio' in CMAKE_GENERATOR:
+ if BUILD_FOR_TESTING:
+ args += ['-DRUN_STATIC_ANALYZER=1']
+
+ success = cmake_configure(cmake_generator, build_root, src_root, build_type, args)
+ if not success:
+ return False
+
+ # Make
+ success = make_build(build_root, build_type)
+
+ # Deploy scripts needed from source repository to build directory
+ remove_tree(os.path.join(build_root, 'scripts'))
+ shutil.copytree(os.path.join(src_root, 'scripts'), os.path.join(build_root, 'scripts'))
+ remove_tree(os.path.join(build_root, 'src', 'js'))
+ shutil.copytree(os.path.join(src_root, 'src', 'js'), os.path.join(build_root, 'src', 'js'))
+
+ return success
+
+
+def download_and_extract(archive, dest_dir, filename_prefix='', clobber=True):
+ debug_print('download_and_extract(archive=' + archive + ', dest_dir=' + dest_dir + ')')
+
+ url = urljoin(emsdk_packages_url, archive)
+
+ def try_download(url, silent=False):
+ return download_file(url, download_dir, not KEEP_DOWNLOADS,
+ filename_prefix, silent=silent)
+
+ # Special hack for the wasm-binaries we transitioned from `.bzip2` to
+ # `.xz`, but we can't tell from the version/url which one to use, so
+ # try one and then fall back to the other.
+ success = False
+ if 'wasm-binaries' in archive and os.path.splitext(archive)[1] == '.xz':
+ success = try_download(url, silent=True)
+ if not success:
+ alt_url = url.replace('.tar.xz', '.tbz2')
+ success = try_download(alt_url, silent=True)
+ if success:
+ url = alt_url
+
+ if not success:
+ success = try_download(url)
+
+ if not success:
+ return False
+
+ # Remove the old directory, since we have some SDKs that install into the
+ # same directory. If we didn't do this contents of the previous install
+ # could remain.
+ if clobber:
+ remove_tree(dest_dir)
+
+ download_target = get_download_target(url, download_dir, filename_prefix)
+ if archive.endswith('.zip'):
+ return unzip(download_target, dest_dir)
+ else:
+ return untargz(download_target, dest_dir)
+
+
+def to_native_path(p):
+ if WINDOWS and not MSYS:
+ return to_unix_path(p).replace('/', '\\')
+ else:
+ return to_unix_path(p)
+
+
+# Finds and returns a list of the directories that need to be added to PATH for
+# the given set of tools.
+def get_required_path(active_tools):
+ path_add = [to_native_path(EMSDK_PATH)]
+ for tool in active_tools:
+ if hasattr(tool, 'activated_path'):
+ path = to_native_path(tool.expand_vars(tool.activated_path))
+ # If the tool has an activated_path_skip attribute then we don't add
+ # the tools path to the users path if a program by that name is found
+ # in the existing PATH. This allows us to, for example, add our version
+ # node to the users PATH if, and only if, they don't already have a
+ # another version of node in their PATH.
+ if hasattr(tool, 'activated_path_skip'):
+ current_path = which(tool.activated_path_skip)
+ # We found an executable by this name in the current PATH, but we
+ # ignore our own version for this purpose.
+ if current_path and os.path.dirname(current_path) != path:
+ continue
+ path_add.append(path)
+ return path_add
+
+
+# Returns the absolute path to the file '.emscripten' for the current user on
+# this system.
+EM_CONFIG_PATH = os.path.join(EMSDK_PATH, ".emscripten")
+EM_CONFIG_DICT = {}
+
+
+def parse_key_value(line):
+ if not line:
+ return ('', '')
+ eq = line.find('=')
+ if eq != -1:
+ key = line[0:eq].strip()
+ value = line[eq + 1:].strip()
+ return (key, value)
+ else:
+ return (key, '')
+
+
+def load_em_config():
+ EM_CONFIG_DICT.clear()
+ lines = []
+ try:
+ lines = open(EM_CONFIG_PATH, "r").read().split('\n')
+ except Exception:
+ pass
+ for line in lines:
+ try:
+ key, value = parse_key_value(line)
+ if value != '':
+ EM_CONFIG_DICT[key] = value
+ except Exception:
+ pass
+
+
+def find_emscripten_root(active_tools):
+ """Find the currently active emscripten root.
+
+ If there is more than one tool that defines EMSCRIPTEN_ROOT (this
+ should not happen under normal circumstances), assume the last one takes
+ precedence.
+ """
+ root = None
+ for tool in active_tools:
+ config = tool.activated_config()
+ if 'EMSCRIPTEN_ROOT' in config:
+ root = config['EMSCRIPTEN_ROOT']
+ return root
+
+
+# returns a tuple (string,string) of config files paths that need to used
+# to activate emsdk env depending on $SHELL, defaults to bash.
+def get_emsdk_shell_env_configs():
+ default_emsdk_env = sdk_path('emsdk_env.sh')
+ default_shell_config_file = '$HOME/.bash_profile'
+ shell = os.getenv('SHELL', '')
+ if 'zsh' in shell:
+ return (default_emsdk_env, '$HOME/.zprofile')
+ elif 'csh' in shell:
+ return (sdk_path('emsdk_env.csh'), '$HOME/.cshrc')
+ elif 'fish' in shell:
+ return (sdk_path('emsdk_env.fish'), '$HOME/.config/fish/config.fish')
+ else:
+ return (default_emsdk_env, default_shell_config_file)
+
+
+def generate_em_config(active_tools, permanently_activate, system):
+ cfg = 'import os\n'
+ cfg += "emsdk_path = os.path.dirname(os.getenv('EM_CONFIG')).replace('\\\\', '/')\n"
+
+ # Different tools may provide the same activated configs; the latest to be
+ # activated is the relevant one.
+ activated_config = OrderedDict()
+ for tool in active_tools:
+ for name, value in tool.activated_config().items():
+ activated_config[name] = value
+
+ if 'NODE_JS' not in activated_config:
+ node_fallback = which('nodejs')
+ if not node_fallback:
+ node_fallback = 'node'
+ activated_config['NODE_JS'] = node_fallback
+
+ for name, value in activated_config.items():
+ cfg += name + " = '" + value + "'\n"
+
+ emroot = find_emscripten_root(active_tools)
+ if emroot:
+ version = parse_emscripten_version(emroot)
+ # Older emscripten versions of emscripten depend on certain config
+ # keys that are no longer used.
+ # See https://github.com/emscripten-core/emscripten/pull/9469
+ if version < [1, 38, 46]:
+ cfg += 'COMPILER_ENGINE = NODE_JS\n'
+ # See https://github.com/emscripten-core/emscripten/pull/9542
+ if version < [1, 38, 48]:
+ cfg += 'JS_ENGINES = [NODE_JS]\n'
+
+ cfg = cfg.replace("'" + EMSDK_PATH, "emsdk_path + '")
+
+ if os.path.exists(EM_CONFIG_PATH):
+ backup_path = EM_CONFIG_PATH + ".old"
+ move_with_overwrite(EM_CONFIG_PATH, backup_path)
+
+ with open(EM_CONFIG_PATH, "w") as text_file:
+ text_file.write(cfg)
+
+ # Clear old emscripten content.
+ rmfile(os.path.join(EMSDK_PATH, ".emscripten_sanity"))
+
+ path_add = get_required_path(active_tools)
+
+ # Give some recommended next step, depending on the platform
+ if WINDOWS:
+ if not permanently_activate and not system:
+ print('Next steps:')
+ print('- Consider running `emsdk activate` with --permanent or --system')
+ print(' to have emsdk settings available on startup.')
+ else:
+ print('Next steps:')
+ print('- To conveniently access emsdk tools from the command line,')
+ print(' consider adding the following directories to your PATH:')
+ for p in path_add:
+ print(' ' + p)
+ print('- This can be done for the current shell by running:')
+ emsdk_env, shell_config_file = get_emsdk_shell_env_configs()
+ print(' source "%s"' % emsdk_env)
+ print('- Configure emsdk in your shell startup scripts by running:')
+ print(' echo \'source "%s"\' >> %s' % (emsdk_env, shell_config_file))
+
+
+def find_msbuild_dir():
+ program_files = os.getenv('ProgramFiles', 'C:/Program Files')
+ program_files_x86 = os.getenv('ProgramFiles(x86)', 'C:/Program Files (x86)')
+ MSBUILDX86_DIR = os.path.join(program_files_x86, "MSBuild/Microsoft.Cpp/v4.0/Platforms")
+ MSBUILD_DIR = os.path.join(program_files, "MSBuild/Microsoft.Cpp/v4.0/Platforms")
+ if os.path.exists(MSBUILDX86_DIR):
+ return MSBUILDX86_DIR
+ if os.path.exists(MSBUILD_DIR):
+ return MSBUILD_DIR
+ # No MSbuild installed.
+ return ''
+
+
+class Tool(object):
+ def __init__(self, data):
+ # Convert the dictionary representation of the tool in 'data' to members of
+ # this class for convenience.
+ for key, value in data.items():
+ # Python2 compat, convert unicode to str
+ if sys.version_info < (3,) and isinstance(value, unicode): # noqa
+ value = value.encode('Latin-1')
+ setattr(self, key, value)
+
+ # Cache the name ID of this Tool (these are read very often)
+ self.name = self.id
+ if self.version:
+ self.name += '-' + self.version
+ if hasattr(self, 'bitness'):
+ self.name += '-' + str(self.bitness) + 'bit'
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def expand_vars(self, str):
+ if WINDOWS and '%MSBuildPlatformsDir%' in str:
+ str = str.replace('%MSBuildPlatformsDir%', find_msbuild_dir())
+ if '%cmake_build_type_on_win%' in str:
+ str = str.replace('%cmake_build_type_on_win%', (decide_cmake_build_type(self) + '/') if WINDOWS else '')
+ if '%installation_dir%' in str:
+ str = str.replace('%installation_dir%', sdk_path(self.installation_dir()))
+ if '%generator_prefix%' in str:
+ str = str.replace('%generator_prefix%', cmake_generator_prefix())
+ str = str.replace('%.exe%', '.exe' if WINDOWS else '')
+ if '%llvm_build_bin_dir%' in str:
+ str = str.replace('%llvm_build_bin_dir%', llvm_build_bin_dir(self))
+
+ return str
+
+ # Return true if this tool requires building from source, and false if this is a precompiled tool.
+ def needs_compilation(self):
+ if hasattr(self, 'cmake_build_type'):
+ return True
+
+ if hasattr(self, 'uses'):
+ for tool_name in self.uses:
+ tool = find_tool(tool_name)
+ if not tool:
+ debug_print('Tool ' + str(self) + ' depends on ' + tool_name + ' which does not exist!')
+ continue
+ if tool.needs_compilation():
+ return True
+
+ return False
+
+ # Specifies the target path where this tool will be installed to. This could
+ # either be a directory or a filename (e.g. in case of node.js)
+ def installation_path(self):
+ if hasattr(self, 'install_path'):
+ pth = self.expand_vars(self.install_path)
+ return sdk_path(pth)
+ p = self.version
+ if hasattr(self, 'bitness') and (not hasattr(self, 'append_bitness') or self.append_bitness):
+ p += '_' + str(self.bitness) + 'bit'
+ return sdk_path(os.path.join(self.id, p))
+
+ # Specifies the target directory this tool will be installed to.
+ def installation_dir(self):
+ dir = self.installation_path()
+ if path_points_to_directory(dir):
+ return dir
+ else:
+ return os.path.dirname(dir)
+
+ # Returns the configuration item that needs to be added to .emscripten to make
+ # this Tool active for the current user.
+ def activated_config(self):
+ if not hasattr(self, 'activated_cfg'):
+ return {}
+ config = OrderedDict()
+ expanded = to_unix_path(self.expand_vars(self.activated_cfg))
+ for specific_cfg in expanded.split(';'):
+ name, value = specific_cfg.split('=')
+ config[name] = value.strip("'")
+ return config
+
+ def activated_environment(self):
+ if hasattr(self, 'activated_env'):
+ return self.expand_vars(self.activated_env).split(';')
+ else:
+ return []
+
+ def compatible_with_this_arch(self):
+ if hasattr(self, 'arch'):
+ if self.arch != ARCH:
+ return False
+ return True
+
+ def compatible_with_this_os(self):
+ if hasattr(self, 'os'):
+ if self.os == 'all':
+ return True
+ if self.compatible_with_this_arch() and ((WINDOWS and 'win' in self.os) or (LINUX and ('linux' in self.os or 'unix' in self.os)) or (MACOS and ('macos' in self.os or 'unix' in self.os))):
+ return True
+ else:
+ return False
+ else:
+ if not hasattr(self, 'macos_url') and not hasattr(self, 'windows_url') and not hasattr(self, 'unix_url') and not hasattr(self, 'linux_url'):
+ return True
+
+ if MACOS and hasattr(self, 'macos_url') and self.compatible_with_this_arch():
+ return True
+
+ if LINUX and hasattr(self, 'linux_url') and self.compatible_with_this_arch():
+ return True
+
+ if WINDOWS and hasattr(self, 'windows_url') and self.compatible_with_this_arch():
+ return True
+
+ if UNIX and hasattr(self, 'unix_url'):
+ return True
+
+ return hasattr(self, 'url')
+
+ # the "version file" is a file inside install dirs that indicates the
+ # version installed there. this helps disambiguate when there is more than
+ # one version that may be installed to the same directory (which is used
+ # to avoid accumulating builds over time in some cases, with new builds
+ # overwriting the old)
+ def get_version_file_path(self):
+ return os.path.join(self.installation_path(), '.emsdk_version')
+
+ def is_installed_version(self):
+ version_file_path = self.get_version_file_path()
+ if os.path.isfile(version_file_path):
+ with open(version_file_path, 'r') as version_file:
+ return version_file.read().strip() == self.name
+ return False
+
+ def update_installed_version(self):
+ with open(self.get_version_file_path(), 'w') as version_file:
+ version_file.write(self.name + '\n')
+ return None
+
+ def is_installed(self, skip_version_check=False):
+ # If this tool/sdk depends on other tools, require that all dependencies are
+ # installed for this tool to count as being installed.
+ if hasattr(self, 'uses'):
+ for tool_name in self.uses:
+ tool = find_tool(tool_name)
+ if tool is None:
+ errlog("Manifest error: No tool by name '" + tool_name + "' found! This may indicate an internal SDK error!")
+ return False
+ if not tool.is_installed():
+ return False
+
+ if self.download_url() is None:
+ # This tool does not contain downloadable elements, so it is installed by default.
+ return True
+
+ content_exists = is_nonempty_directory(self.installation_path())
+
+ # For e.g. fastcomp clang from git repo, the activated PATH is the
+ # directory where the compiler is built to, and installation_path is
+ # the directory where the source tree exists. To distinguish between
+ # multiple packages sharing the same source (clang-main-32bit,
+ # clang-main-64bit, clang-main-32bit and clang-main-64bit each
+ # share the same git repo), require that in addition to the installation
+ # directory, each item in the activated PATH must exist.
+ if hasattr(self, 'activated_path') and not os.path.exists(self.expand_vars(self.activated_path)):
+ content_exists = False
+
+ if hasattr(self, 'custom_is_installed_script'):
+ if self.custom_is_installed_script == 'is_binaryen_installed':
+ return is_binaryen_installed(self)
+ else:
+ raise Exception('Unknown custom_is_installed_script directive "' + self.custom_is_installed_script + '"!')
+
+ return content_exists and (skip_version_check or self.is_installed_version())
+
+ def is_active(self):
+ if not self.is_installed():
+ return False
+
+ # All dependencies of this tool must be active as well.
+ deps = self.dependencies()
+ for tool in deps:
+ if not tool.is_active():
+ return False
+
+ activated_cfg = self.activated_config()
+ if not activated_cfg:
+ return len(deps) > 0
+
+ for key, value in activated_cfg.items():
+ if key not in EM_CONFIG_DICT:
+ debug_print(str(self) + ' is not active, because key="' + key + '" does not exist in .emscripten')
+ return False
+
+ # all paths are stored dynamically relative to the emsdk root, so
+ # normalize those first.
+ config_value = EM_CONFIG_DICT[key].replace("emsdk_path + '", "'" + EMSDK_PATH)
+ config_value = config_value.strip("'")
+ if config_value != value:
+ debug_print(str(self) + ' is not active, because key="' + key + '" has value "' + config_value + '" but should have value "' + value + '"')
+ return False
+ return True
+
+ # Returns true if the system environment variables requires by this tool are currently active.
+ def is_env_active(self):
+ envs = self.activated_environment()
+ for env in envs:
+ key, value = parse_key_value(env)
+ if key not in os.environ or to_unix_path(os.environ[key]) != to_unix_path(value):
+ debug_print(str(self) + ' is not active, because environment variable key="' + key + '" has value "' + str(os.getenv(key)) + '" but should have value "' + value + '"')
+ return False
+
+ if hasattr(self, 'activated_path'):
+ path = to_unix_path(self.expand_vars(self.activated_path))
+ for p in path:
+ path_items = os.environ['PATH'].replace('\\', '/').split(ENVPATH_SEPARATOR)
+ if not normalized_contains(path_items, p):
+ debug_print(str(self) + ' is not active, because environment variable PATH item "' + p + '" is not present (PATH=' + os.environ['PATH'] + ')')
+ return False
+ return True
+
+ # If this tool can be installed on this system, this function returns True.
+ # Otherwise, this function returns a string that describes the reason why this
+ # tool is not available.
+ def can_be_installed(self):
+ if hasattr(self, 'bitness'):
+ if self.bitness == 64 and not is_os_64bit():
+ return "this tool is only provided for 64-bit OSes"
+ return True
+
+ def download_url(self):
+ if WINDOWS and hasattr(self, 'windows_url'):
+ return self.windows_url
+ elif MACOS and hasattr(self, 'macos_url'):
+ return self.macos_url
+ elif LINUX and hasattr(self, 'linux_url'):
+ return self.linux_url
+ elif UNIX and hasattr(self, 'unix_url'):
+ return self.unix_url
+ elif hasattr(self, 'url'):
+ return self.url
+ else:
+ return None
+
+ def install(self):
+ """Returns True if the Tool was installed of False if was skipped due to
+ already being installed.
+ """
+ if self.can_be_installed() is not True:
+ exit_with_error("The tool '" + str(self) + "' is not available due to the reason: " + self.can_be_installed())
+
+ if self.id == 'sdk':
+ return self.install_sdk()
+ else:
+ return self.install_tool()
+
+ def install_sdk(self):
+ """Returns True if any SDK component was installed of False all componented
+ were already installed.
+ """
+ print("Installing SDK '" + str(self) + "'..")
+ installed = False
+
+ for tool_name in self.uses:
+ tool = find_tool(tool_name)
+ if tool is None:
+ exit_with_error("manifest error: No tool by name '" + tool_name + "' found! This may indicate an internal SDK error!")
+ installed |= tool.install()
+
+ if not installed:
+ print("All SDK components already installed: '" + str(self) + "'.")
+ return False
+
+ if getattr(self, 'custom_install_script', None) == 'emscripten_npm_install':
+ # upstream tools have hardcoded paths that are not stored in emsdk_manifest.json registry
+ install_path = 'upstream'
+ emscripten_dir = os.path.join(EMSDK_PATH, install_path, 'emscripten')
+ # Older versions of the sdk did not include the node_modules directory
+ # and require `npm ci` to be run post-install
+ if not os.path.exists(os.path.join(emscripten_dir, 'node_modules')):
+ if not emscripten_npm_install(self, emscripten_dir):
+ exit_with_error('post-install step failed: emscripten_npm_install')
+
+ print("Done installing SDK '" + str(self) + "'.")
+ return True
+
+ def install_tool(self):
+ """Returns True if the SDK was installed of False if was skipped due to
+ already being installed.
+ """
+ # Avoid doing a redundant reinstall of the tool, if it has already been installed.
+ # However all tools that are sourced directly from git branches do need to be
+ # installed every time when requested, since the install step is then used to git
+ # pull the tool to a newer version.
+ if self.is_installed() and not hasattr(self, 'git_branch'):
+ print("Skipped installing " + self.name + ", already installed.")
+ return False
+
+ print("Installing tool '" + str(self) + "'..")
+ url = self.download_url()
+
+ if hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_llvm':
+ success = build_llvm(self)
+ elif hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_ninja':
+ success = build_ninja(self)
+ elif hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_ccache':
+ success = build_ccache(self)
+ elif hasattr(self, 'git_branch'):
+ success = git_clone_checkout_and_pull(url, self.installation_path(), self.git_branch)
+ elif url.endswith(ARCHIVE_SUFFIXES):
+ success = download_and_extract(url, self.installation_path(),
+ filename_prefix=getattr(self, 'download_prefix', ''))
+ else:
+ assert False, 'unhandled url type: ' + url
+
+ if not success:
+ exit_with_error("installation failed!")
+
+ if hasattr(self, 'custom_install_script'):
+ if self.custom_install_script == 'emscripten_npm_install':
+ success = emscripten_npm_install(self, self.installation_path())
+ elif self.custom_install_script in ('build_llvm', 'build_ninja', 'build_ccache'):
+ # 'build_llvm' is a special one that does the download on its
+ # own, others do the download manually.
+ pass
+ elif self.custom_install_script == 'build_binaryen':
+ success = build_binaryen_tool(self)
+ else:
+ raise Exception('Unknown custom_install_script command "' + self.custom_install_script + '"!')
+
+ if not success:
+ exit_with_error("installation failed!")
+
+ # Install an emscripten-version.txt file if told to, and if there is one.
+ # (If this is not an actual release, but some other build, then we do not
+ # write anything.)
+ if hasattr(self, 'emscripten_releases_hash'):
+ emscripten_version_file_path = os.path.join(to_native_path(self.expand_vars(self.activated_path)), 'emscripten-version.txt')
+ version = get_emscripten_release_version(self.emscripten_releases_hash)
+ if version:
+ with open(emscripten_version_file_path, 'w') as f:
+ f.write('"%s"\n' % version)
+
+ print("Done installing tool '" + str(self) + "'.")
+
+ # Sanity check that the installation succeeded, and if so, remove unneeded
+ # leftover installation files.
+ if not self.is_installed(skip_version_check=True):
+ exit_with_error("installation of '" + str(self) + "' failed, but no error was detected. Either something went wrong with the installation, or this may indicate an internal emsdk error.")
+
+ self.cleanup_temp_install_files()
+ self.update_installed_version()
+ return True
+
+ def cleanup_temp_install_files(self):
+ if KEEP_DOWNLOADS:
+ return
+ url = self.download_url()
+ if url.endswith(ARCHIVE_SUFFIXES):
+ download_target = get_download_target(url, download_dir, getattr(self, 'download_prefix', ''))
+ debug_print("Deleting temporary download: " + download_target)
+ rmfile(download_target)
+
+ def uninstall(self):
+ if not self.is_installed():
+ print("Tool '" + str(self) + "' was not installed. No need to uninstall.")
+ return
+ print("Uninstalling tool '" + str(self) + "'..")
+ if hasattr(self, 'custom_uninstall_script'):
+ if self.custom_uninstall_script == 'uninstall_binaryen':
+ uninstall_binaryen(self)
+ else:
+ raise Exception('Unknown custom_uninstall_script directive "' + self.custom_uninstall_script + '"!')
+ print("Deleting path '" + self.installation_path() + "'")
+ remove_tree(self.installation_path())
+ print("Done uninstalling '" + str(self) + "'.")
+
+ def dependencies(self):
+ if not hasattr(self, 'uses'):
+ return []
+ deps = []
+
+ for tool_name in self.uses:
+ tool = find_tool(tool_name)
+ if tool:
+ deps += [tool]
+ return deps
+
+ def recursive_dependencies(self):
+ if not hasattr(self, 'uses'):
+ return []
+ deps = []
+ for tool_name in self.uses:
+ tool = find_tool(tool_name)
+ if tool:
+ deps += [tool]
+ deps += tool.recursive_dependencies()
+ return deps
+
+
+# A global registry of all known Emscripten SDK tools available in the SDK manifest.
+tools = []
+tools_map = {}
+
+
+def add_tool(tool):
+ tool.is_sdk = False
+ tools.append(tool)
+ if find_tool(str(tool)):
+ raise Exception('Duplicate tool ' + str(tool) + '! Existing:\n{' + ', '.join("%s: %s" % item for item in vars(find_tool(str(tool))).items()) + '}, New:\n{' + ', '.join("%s: %s" % item for item in vars(tool).items()) + '}')
+ tools_map[str(tool)] = tool
+
+
+# A global registry of all known SDK toolsets.
+sdks = []
+sdks_map = {}
+
+
+def add_sdk(sdk):
+ sdk.is_sdk = True
+ sdks.append(sdk)
+ if find_sdk(str(sdk)):
+ raise Exception('Duplicate sdk ' + str(sdk) + '! Existing:\n{' + ', '.join("%s: %s" % item for item in vars(find_sdk(str(sdk))).items()) + '}, New:\n{' + ', '.join("%s: %s" % item for item in vars(sdk).items()) + '}')
+ sdks_map[str(sdk)] = sdk
+
+
+# N.B. In both tools and sdks list above, we take the convention that the newest
+# items are at the back of the list (ascending chronological order)
+
+def find_tool(name):
+ return tools_map.get(name)
+
+
+def find_sdk(name):
+ return sdks_map.get(name)
+
+
+def is_os_64bit():
+ return ARCH.endswith('64')
+
+
+def find_latest_version():
+ return resolve_sdk_aliases('latest')
+
+
+def find_latest_hash():
+ version = find_latest_version()
+ releases_info = load_releases_info()
+ return releases_info['releases'][version]
+
+
+def resolve_sdk_aliases(name, verbose=False):
+ releases_info = load_releases_info()
+ while name in releases_info['aliases']:
+ if verbose:
+ print("Resolving SDK alias '%s' to '%s'" % (name, releases_info['aliases'][name]))
+ name = releases_info['aliases'][name]
+ return name
+
+
+def find_latest_sdk():
+ return 'sdk-releases-%s-64bit' % (find_latest_hash())
+
+
+def find_tot_sdk():
+ debug_print('Fetching emscripten-releases repository...')
+ global extra_release_tag
+ extra_release_tag = get_emscripten_releases_tot()
+ return 'sdk-releases-%s-64bit' % (extra_release_tag)
+
+
+def parse_emscripten_version(emscripten_root):
+ version_file = os.path.join(emscripten_root, 'emscripten-version.txt')
+ with open(version_file) as f:
+ version = f.read().strip()
+ version = version.strip('"').split('-')[0].split('.')
+ return [int(v) for v in version]
+
+
+# Given a git hash in emscripten-releases, find the emscripten
+# version for it. There may not be one if this is not the hash of
+# a release, in which case we return None.
+def get_emscripten_release_version(emscripten_releases_hash):
+ releases_info = load_releases_info()
+ for key, value in dict(releases_info['releases']).items():
+ if value == emscripten_releases_hash:
+ return key.split('-')[0]
+ return None
+
+
+# Get the tip-of-tree build identifier.
+def get_emscripten_releases_tot():
+ git_clone_checkout_and_pull(emscripten_releases_repo, sdk_path('releases'), 'main')
+ recent_releases = git_recent_commits(sdk_path('releases'))
+ # The recent releases are the latest hashes in the git repo. There
+ # may not be a build for the most recent ones yet; find the last
+ # that does.
+ arch = ''
+ if ARCH == 'arm64':
+ arch = '-arm64'
+
+ def make_url(ext):
+ return emscripten_releases_download_url_template % (
+ os_name(),
+ release,
+ arch,
+ ext,
+ )
+
+ for release in recent_releases:
+ make_url('tar.xz' if not WINDOWS else 'zip')
+ try:
+ urlopen(make_url('tar.xz' if not WINDOWS else 'zip'))
+ except Exception:
+ if not WINDOWS:
+ # Try the old `.tbz2` name
+ # TODO:remove this once tot builds are all using xz
+ try:
+ urlopen(make_url('tbz2'))
+ except Exception:
+ continue
+ else:
+ continue
+ return release
+ exit_with_error('failed to find build of any recent emsdk revision')
+
+
+def get_release_hash(arg, releases_info):
+ return releases_info.get(arg, None) or releases_info.get('sdk-' + arg + '-64bit')
+
+
+def version_key(ver):
+ return tuple(map(int, re.split('[._-]', ver)[:3]))
+
+
+# A sort function that is compatible with both Python 2 and Python 3 using a
+# custom comparison function.
+def python_2_3_sorted(arr, cmp):
+ if sys.version_info >= (3,):
+ return sorted(arr, key=functools.cmp_to_key(cmp))
+ else:
+ return sorted(arr, cmp=cmp)
+
+
+def is_emsdk_sourced_from_github():
+ return os.path.exists(os.path.join(EMSDK_PATH, '.git'))
+
+
+def update_emsdk():
+ if is_emsdk_sourced_from_github():
+ errlog('You seem to have bootstrapped Emscripten SDK by cloning from GitHub. In this case, use "git pull" instead of "emsdk update" to update emsdk. (Not doing that automatically in case you have local changes)')
+ sys.exit(1)
+ if not download_and_extract(emsdk_zip_download_url, EMSDK_PATH, clobber=False):
+ sys.exit(1)
+
+
+# Lists all legacy (pre-emscripten-releases) tagged versions directly in the Git
+# repositories. These we can pull and compile from source.
+def load_legacy_emscripten_tags():
+ return open(sdk_path('legacy-emscripten-tags.txt'), 'r').read().split('\n')
+
+
+def load_legacy_binaryen_tags():
+ return open(sdk_path('legacy-binaryen-tags.txt'), 'r').read().split('\n')
+
+
+def remove_prefix(s, prefix):
+ if s.startswith(prefix):
+ return s[len(prefix):]
+ else:
+ return s
+
+
+def remove_suffix(s, suffix):
+ if s.endswith(suffix):
+ return s[:len(s) - len(suffix)]
+ else:
+ return s
+
+
+# filename should be one of: 'llvm-precompiled-tags-32bit.txt', 'llvm-precompiled-tags-64bit.txt'
+def load_file_index_list(filename):
+ items = open(sdk_path(filename)).read().splitlines()
+ items = [remove_suffix(remove_suffix(remove_prefix(x, 'emscripten-llvm-e'), '.tar.gz'), '.zip').strip() for x in items]
+ items = [x for x in items if 'latest' not in x and len(x) > 0]
+
+ # Sort versions from oldest to newest (the default sort would be
+ # lexicographic, i.e. '1.37.1 < 1.37.10 < 1.37.2')
+ return sorted(items, key=version_key)
+
+
+# Load the json info for emscripten-releases.
+def load_releases_info():
+ if not hasattr(load_releases_info, 'cached_info'):
+ try:
+ text = open(sdk_path('emscripten-releases-tags.json'), 'r').read()
+ load_releases_info.cached_info = json.loads(text)
+ except Exception as e:
+ print('Error parsing emscripten-releases-tags.json!')
+ exit_with_error(str(e))
+
+ return load_releases_info.cached_info
+
+
+def get_installed_sdk_version():
+ version_file = sdk_path(os.path.join('upstream', '.emsdk_version'))
+ if not os.path.exists(version_file):
+ return None
+ with open(version_file) as f:
+ version = f.read()
+ return version.split('-')[1]
+
+
+# Get a list of tags for emscripten-releases.
+def load_releases_tags():
+ tags = []
+ info = load_releases_info()
+
+ for version, sha in sorted(info['releases'].items(), key=lambda x: version_key(x[0])):
+ tags.append(sha)
+
+ if extra_release_tag:
+ tags.append(extra_release_tag)
+
+ # Explicitly add the currently installed SDK version. This could be a custom
+ # version (installed explicitly) so it might not be part of the main list
+ # loaded above.
+ installed = get_installed_sdk_version()
+ if installed and installed not in tags:
+ tags.append(installed)
+
+ return tags
+
+
+def load_releases_versions():
+ info = load_releases_info()
+ versions = list(info['releases'].keys())
+ return versions
+
+
+def is_string(s):
+ if sys.version_info[0] >= 3:
+ return isinstance(s, str)
+ return isinstance(s, basestring) # noqa
+
+
+def load_sdk_manifest():
+ try:
+ manifest = json.loads(open(sdk_path("emsdk_manifest.json"), "r").read())
+ except Exception as e:
+ print('Error parsing emsdk_manifest.json!')
+ print(str(e))
+ return
+
+ emscripten_tags = load_legacy_emscripten_tags()
+ llvm_precompiled_tags_32bit = []
+ llvm_precompiled_tags_64bit = load_file_index_list('llvm-tags-64bit.txt')
+ llvm_precompiled_tags = llvm_precompiled_tags_32bit + llvm_precompiled_tags_64bit
+ binaryen_tags = load_legacy_binaryen_tags()
+ releases_tags = load_releases_tags()
+
+ def dependencies_exist(sdk):
+ for tool_name in sdk.uses:
+ tool = find_tool(tool_name)
+ if not tool:
+ debug_print('missing dependency: ' + tool_name)
+ return False
+ return True
+
+ def cmp_version(ver, cmp_operand, reference):
+ if cmp_operand == '<=':
+ return version_key(ver) <= version_key(reference)
+ if cmp_operand == '<':
+ return version_key(ver) < version_key(reference)
+ if cmp_operand == '>=':
+ return version_key(ver) >= version_key(reference)
+ if cmp_operand == '>':
+ return version_key(ver) > version_key(reference)
+ if cmp_operand == '==':
+ return version_key(ver) == version_key(reference)
+ if cmp_operand == '!=':
+ return version_key(ver) != version_key(reference)
+ raise Exception('Invalid cmp_operand "' + cmp_operand + '"!')
+
+ def passes_filters(param, ver, filters):
+ for v in filters:
+ if v[0] == param and not cmp_version(ver, v[1], v[2]):
+ return False
+ return True
+
+ # A 'category parameter' is a %foo%-encoded identifier that specifies
+ # a class of tools instead of just one tool, e.g. %tag%
+ def expand_category_param(param, category_list, t, is_sdk):
+ for i, ver in enumerate(category_list):
+ if not ver.strip():
+ continue
+ t2 = copy.copy(t)
+ found_param = False
+ for p, v in vars(t2).items():
+ if is_string(v) and param in v:
+ t2.__dict__[p] = v.replace(param, ver)
+ found_param = True
+ if not found_param:
+ continue
+ t2.is_old = i < len(category_list) - 2
+ if hasattr(t2, 'uses'):
+ t2.uses = [x.replace(param, ver) for x in t2.uses]
+
+ # Filter out expanded tools by version requirements, such as ["tag", "<=", "1.37.22"]
+ if hasattr(t2, 'version_filter'):
+ passes = passes_filters(param, ver, t2.version_filter)
+ if not passes:
+ continue
+
+ if is_sdk:
+ if dependencies_exist(t2):
+ if not find_sdk(t2.name):
+ add_sdk(t2)
+ else:
+ debug_print('SDK ' + str(t2) + ' already existed in manifest, not adding twice')
+ else:
+ if not find_tool(t2.name):
+ add_tool(t2)
+ else:
+ debug_print('Tool ' + str(t2) + ' already existed in manifest, not adding twice')
+
+ for tool in manifest['tools']:
+ t = Tool(tool)
+ if t.compatible_with_this_os():
+ if not hasattr(t, 'is_old'):
+ t.is_old = False
+
+ # Expand the metapackages that refer to tags
+ if '%tag%' in t.version:
+ expand_category_param('%tag%', emscripten_tags, t, is_sdk=False)
+ elif '%precompiled_tag%' in t.version:
+ expand_category_param('%precompiled_tag%', llvm_precompiled_tags, t, is_sdk=False)
+ elif '%precompiled_tag32%' in t.version:
+ expand_category_param('%precompiled_tag32%', llvm_precompiled_tags_32bit, t, is_sdk=False)
+ elif '%precompiled_tag64%' in t.version:
+ expand_category_param('%precompiled_tag64%', llvm_precompiled_tags_64bit, t, is_sdk=False)
+ elif '%binaryen_tag%' in t.version:
+ expand_category_param('%binaryen_tag%', binaryen_tags, t, is_sdk=False)
+ elif '%releases-tag%' in t.version:
+ expand_category_param('%releases-tag%', releases_tags, t, is_sdk=False)
+ else:
+ add_tool(t)
+
+ for sdk_str in manifest['sdks']:
+ sdk_str['id'] = 'sdk'
+ sdk = Tool(sdk_str)
+ if sdk.compatible_with_this_os():
+ if not hasattr(sdk, 'is_old'):
+ sdk.is_old = False
+
+ if '%tag%' in sdk.version:
+ expand_category_param('%tag%', emscripten_tags, sdk, is_sdk=True)
+ elif '%precompiled_tag%' in sdk.version:
+ expand_category_param('%precompiled_tag%', llvm_precompiled_tags, sdk, is_sdk=True)
+ elif '%precompiled_tag32%' in sdk.version:
+ expand_category_param('%precompiled_tag32%', llvm_precompiled_tags_32bit, sdk, is_sdk=True)
+ elif '%precompiled_tag64%' in sdk.version:
+ expand_category_param('%precompiled_tag64%', llvm_precompiled_tags_64bit, sdk, is_sdk=True)
+ elif '%releases-tag%' in sdk.version:
+ expand_category_param('%releases-tag%', releases_tags, sdk, is_sdk=True)
+ else:
+ add_sdk(sdk)
+
+
+# Tests if the two given tools can be active at the same time.
+# Currently only a simple check for name for same tool with different versions,
+# possibly adds more logic in the future.
+def can_simultaneously_activate(tool1, tool2):
+ return tool1.id != tool2.id
+
+
+# Expands dependencies for each tool, and removes ones that don't exist.
+def process_tool_list(tools_to_activate):
+ i = 0
+ # Gather dependencies for each tool
+ while i < len(tools_to_activate):
+ tool = tools_to_activate[i]
+ deps = tool.recursive_dependencies()
+ tools_to_activate = tools_to_activate[:i] + deps + tools_to_activate[i:]
+ i += len(deps) + 1
+
+ for tool in tools_to_activate:
+ if not tool.is_installed():
+ exit_with_error("error: tool is not installed and therefore cannot be activated: '%s'" % tool)
+
+ # Remove conflicting tools
+ i = 0
+ while i < len(tools_to_activate):
+ j = 0
+ while j < i:
+ secondary_tool = tools_to_activate[j]
+ primary_tool = tools_to_activate[i]
+ if not can_simultaneously_activate(primary_tool, secondary_tool):
+ tools_to_activate.pop(j)
+ j -= 1
+ i -= 1
+ j += 1
+ i += 1
+ return tools_to_activate
+
+
+def write_set_env_script(env_string):
+ assert CMD or POWERSHELL
+ open(EMSDK_SET_ENV, 'w').write(env_string)
+
+
+# Reconfigure .emscripten to choose the currently activated toolset, set PATH
+# and other environment variables.
+# Returns the full list of deduced tools that are now active.
+def set_active_tools(tools_to_activate, permanently_activate, system):
+ tools_to_activate = process_tool_list(tools_to_activate)
+
+ if tools_to_activate:
+ tools = [x for x in tools_to_activate if not x.is_sdk]
+ print('Setting the following tools as active:\n ' + '\n '.join(map(lambda x: str(x), tools)))
+ print('')
+
+ generate_em_config(tools_to_activate, permanently_activate, system)
+
+ # Construct a .bat or .ps1 script that will be invoked to set env. vars and PATH
+ # We only do this on cmd or powershell since emsdk.bat/ps1 is able to modify the
+ # calling shell environment. On other shell `source emsdk_env.sh` is
+ # required.
+ if CMD or POWERSHELL:
+ # always set local environment variables since permanently activating will only set the registry settings and
+ # will not affect the current session
+ env_vars_to_add = get_env_vars_to_add(tools_to_activate, system, user=permanently_activate)
+ env_string = construct_env_with_vars(env_vars_to_add)
+ write_set_env_script(env_string)
+
+ if WINDOWS and permanently_activate:
+ win_set_environment_variables(env_vars_to_add, system, user=permanently_activate)
+
+ return tools_to_activate
+
+
+def currently_active_sdk():
+ for sdk in reversed(sdks):
+ if sdk.is_active():
+ return sdk
+ return None
+
+
+def currently_active_tools():
+ active_tools = []
+ for tool in tools:
+ if tool.is_active():
+ active_tools += [tool]
+ return active_tools
+
+
+# http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-python-whilst-preserving-order
+def unique_items(seq):
+ seen = set()
+ seen_add = seen.add
+ return [x for x in seq if x not in seen and not seen_add(x)]
+
+
+# Tests if a path is contained in the given list, but with separators normalized.
+def normalized_contains(lst, elem):
+ elem = to_unix_path(elem)
+ for e in lst:
+ if elem == to_unix_path(e):
+ return True
+ return False
+
+
+def to_msys_path(p):
+ p = to_unix_path(p)
+ new_path = re.sub(r'([a-zA-Z]):/(.*)', r'/\1/\2', p)
+ if len(new_path) > 3 and new_path[0] == '/' and new_path[2] == '/':
+ new_path = new_path[0] + new_path[1].lower() + new_path[2:]
+ return new_path
+
+
+# Looks at the current PATH and adds and removes entries so that the PATH reflects
+# the set of given active tools.
+def adjusted_path(tools_to_activate, system=False, user=False):
+ # These directories should be added to PATH
+ path_add = get_required_path(tools_to_activate)
+ # These already exist.
+ if WINDOWS and not MSYS:
+ existing_path = win_get_environment_variable('PATH', system=system, user=user, fallback=True).split(ENVPATH_SEPARATOR)
+ else:
+ existing_path = os.environ['PATH'].split(ENVPATH_SEPARATOR)
+
+ existing_emsdk_tools = []
+ existing_nonemsdk_path = []
+ for entry in existing_path:
+ if to_unix_path(entry).startswith(EMSDK_PATH):
+ existing_emsdk_tools.append(entry)
+ else:
+ existing_nonemsdk_path.append(entry)
+
+ new_emsdk_tools = []
+ kept_emsdk_tools = []
+ for entry in path_add:
+ if not normalized_contains(existing_emsdk_tools, entry):
+ new_emsdk_tools.append(entry)
+ else:
+ kept_emsdk_tools.append(entry)
+
+ whole_path = unique_items(new_emsdk_tools + kept_emsdk_tools + existing_nonemsdk_path)
+
+ if MSYS:
+ # XXX Hack: If running native Windows Python in MSYS prompt where PATH
+ # entries look like "/c/Windows/System32", os.environ['PATH']
+ # in Python will transform to show them as "C:\\Windows\\System32", so need
+ # to reconvert path delimiter back to forward slashes.
+ whole_path = [to_msys_path(p) for p in whole_path]
+ new_emsdk_tools = [to_msys_path(p) for p in new_emsdk_tools]
+
+ separator = ':' if MSYS else ENVPATH_SEPARATOR
+ return (separator.join(whole_path), new_emsdk_tools)
+
+
+def get_env_vars_to_add(tools_to_activate, system, user):
+ env_vars_to_add = []
+
+ newpath, added_path = adjusted_path(tools_to_activate, system, user)
+
+ # Don't bother setting the path if there are no changes.
+ if os.environ['PATH'] != newpath:
+ env_vars_to_add += [('PATH', newpath)]
+
+ if added_path:
+ info('Adding directories to PATH:')
+ for item in added_path:
+ info('PATH += ' + item)
+ info('')
+
+ # A core variable EMSDK points to the root of Emscripten SDK directory.
+ env_vars_to_add += [('EMSDK', EMSDK_PATH)]
+
+ for tool in tools_to_activate:
+ for env in tool.activated_environment():
+ key, value = parse_key_value(env)
+ value = to_native_path(tool.expand_vars(value))
+ env_vars_to_add += [(key, value)]
+
+ emroot = find_emscripten_root(tools_to_activate)
+ if emroot:
+ # For older emscripten versions that don't use an embedded cache by
+ # default we need to export EM_CACHE.
+ #
+ # Sadly, we can't put this in the config file since those older versions
+ # also didn't read the `CACHE` key from the config file:
+ #
+ # History:
+ # - 'CACHE' config started being honored in 1.39.16
+ # https://github.com/emscripten-core/emscripten/pull/11091
+ # - Default to embedded cache also started in 1.39.16
+ # https://github.com/emscripten-core/emscripten/pull/11126
+ # - Emscripten supports automatically locating the embedded
+ # config in 1.39.13:
+ # https://github.com/emscripten-core/emscripten/pull/10935
+ #
+ # Since setting EM_CACHE in the environment effects the entire machine
+ # we want to avoid this except when installing these older emscripten
+ # versions that really need it.
+ version = parse_emscripten_version(emroot)
+ if version < [1, 39, 16]:
+ em_cache_dir = os.path.join(emroot, 'cache')
+ env_vars_to_add += [('EM_CACHE', em_cache_dir)]
+ if version < [1, 39, 13]:
+ env_vars_to_add += [('EM_CONFIG', os.path.normpath(EM_CONFIG_PATH))]
+
+ return env_vars_to_add
+
+
+def construct_env(tools_to_activate, system, user):
+ info('Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1)')
+ return construct_env_with_vars(get_env_vars_to_add(tools_to_activate, system, user))
+
+
+def unset_env(key):
+ if POWERSHELL:
+ return 'Remove-Item env:%s\n' % key
+ if CMD:
+ return 'set %s=\n' % key
+ if CSH:
+ return 'unsetenv %s;\n' % key
+ if FISH:
+ return 'set -e %s;\n' % key
+ if BASH:
+ return 'unset %s;\n' % key
+ assert False
+
+
+def construct_env_with_vars(env_vars_to_add):
+ env_string = ''
+ if env_vars_to_add:
+ info('Setting environment variables:')
+
+ for key, value in env_vars_to_add:
+ # Don't set env vars which are already set to the correct value.
+ if key in os.environ and to_unix_path(os.environ[key]) == to_unix_path(value):
+ continue
+ info(key + ' = ' + value)
+ if POWERSHELL:
+ env_string += '$env:' + key + '="' + value + '"\n'
+ elif CMD:
+ env_string += 'SET ' + key + '=' + value + '\n'
+ elif CSH:
+ env_string += 'setenv ' + key + ' "' + value + '";\n'
+ elif FISH:
+ env_string += 'set -gx ' + key + ' "' + value + '";\n'
+ elif BASH:
+ env_string += 'export ' + key + '="' + value + '";\n'
+ else:
+ assert False
+
+ if 'EMSDK_PYTHON' in env_vars_to_add:
+ # When using our bundled python we never want the user's
+ # PYTHONHOME or PYTHONPATH
+ # See https://github.com/emscripten-core/emsdk/issues/598
+ env_string += unset_env('PYTHONHOME')
+ env_string += unset_env('PYTHONPATH')
+
+ # Remove any environment variables that might have been set by old or
+ # inactive tools/sdks. For example, we set EM_CACHE for older versions
+ # of the SDK but we want to remove that from the current environment
+ # if no such tool is active.
+ # Ignore certain keys that are inputs to emsdk itself.
+ ignore_keys = set(['EMSDK_POWERSHELL', 'EMSDK_CSH', 'EMSDK_CMD', 'EMSDK_BASH', 'EMSDK_FISH',
+ 'EMSDK_NUM_CORES', 'EMSDK_NOTTY', 'EMSDK_KEEP_DOWNLOADS'])
+ env_keys_to_add = set(pair[0] for pair in env_vars_to_add)
+ for key in os.environ:
+ if key.startswith('EMSDK_') or key in ('EM_CACHE', 'EM_CONFIG'):
+ if key not in env_keys_to_add and key not in ignore_keys:
+ info('Clearing existing environment variable: %s' % key)
+ env_string += unset_env(key)
+
+ return env_string
+
+
+def error_on_missing_tool(name):
+ if name.endswith('-64bit') and not is_os_64bit():
+ exit_with_error("'%s' is only provided for 64-bit OSes" % name)
+ else:
+ exit_with_error("tool or SDK not found: '%s'" % name)
+
+
+def expand_sdk_name(name, activating):
+ if 'upstream-master' in name:
+ errlog('upstream-master SDK has been renamed main')
+ name = name.replace('upstream-master', 'main')
+ if 'fastcomp' in name:
+ exit_with_error('the fastcomp backend is no longer supported. Please use an older version of emsdk (for example 3.1.29) if you want to install the old fastcomp-based SDK')
+ if name in ('tot', 'sdk-tot', 'tot-upstream'):
+ if activating:
+ # When we are activating a tot release, assume that the currently
+ # installed SDK, if any, is the tot release we want to activate.
+ # Without this `install tot && activate tot` will race with the builders
+ # that are producing new builds.
+ installed = get_installed_sdk_version()
+ if installed:
+ debug_print('activating currently installed SDK; not updating tot version')
+ return 'sdk-releases-%s-64bit' % installed
+ return find_tot_sdk()
+
+ if '-upstream' in name:
+ name = name.replace('-upstream', '')
+
+ name = resolve_sdk_aliases(name, verbose=True)
+
+ # check if it's a release handled by an emscripten-releases version,
+ # and if so use that by using the right hash. we support a few notations,
+ # x.y.z
+ # sdk-x.y.z-64bit
+ # TODO: support short notation for old builds too?
+ fullname = name
+ version = fullname.replace('sdk-', '').replace('releases-', '').replace('-64bit', '').replace('tag-', '')
+ sdk = 'sdk-' if not name.startswith('releases-') else ''
+ releases_info = load_releases_info()['releases']
+ release_hash = get_release_hash(version, releases_info)
+ if release_hash:
+ # Known release hash
+ full_name = '%sreleases-%s-64bit' % (sdk, release_hash)
+ print("Resolving SDK version '%s' to '%s'" % (version, full_name))
+ return full_name
+
+ if len(version) == 40:
+ global extra_release_tag
+ extra_release_tag = version
+ return '%sreleases-%s-64bit' % (sdk, version)
+
+ return name
+
+
+def main(args):
+ if not args:
+ errlog("Missing command; Type 'emsdk help' to get a list of commands.")
+ return 1
+
+ debug_print('emsdk.py running under `%s`' % sys.executable)
+ cmd = args.pop(0)
+
+ if cmd in ('help', '--help', '-h'):
+ print(' emsdk: Available commands:')
+
+ print('''
+ emsdk list [--old] [--uses] - Lists all available SDKs and tools and their
+ current installation status. With the --old
+ parameter, also historical versions are
+ shown. If --uses is passed, displays the
+ composition of different SDK packages and
+ dependencies.
+
+ emsdk update - Updates emsdk to the newest version. If you have
+ bootstrapped emsdk via cloning directly from
+ GitHub, call "git pull" instead to update emsdk.
+
+ emsdk install [options] ...
+ - Downloads and installs given tools or SDKs.
+ Options can contain:
+
+ -j: Specifies the number of cores to use when
+ building the tool. Default: use one less
+ than the # of detected cores.
+
+ --build=: Controls what kind of build of LLVM to
+ perform. Pass either 'Debug', 'Release',
+ 'MinSizeRel' or 'RelWithDebInfo'. Default:
+ 'Release'.
+
+ --generator=: Specifies the CMake Generator to be used
+ during the build. Possible values are the
+ same as what your CMake supports and whether
+ the generator is valid depends on the tools
+ you have installed. Defaults to 'Unix Makefiles'
+ on *nix systems. If generator name is multiple
+ words, enclose with single or double quotes.
+
+ --shallow: When installing tools from one of the git
+ development branches, this parameter can be
+ passed to perform a shallow git clone instead
+ of a full one. This reduces the amount of
+ network transfer that is needed. This option
+ should only be used when you are interested in
+ downloading one of the development branches,
+ but are not looking to develop Emscripten
+ yourself. Default: disabled, i.e. do a full
+ clone.
+
+ --build-tests: If enabled, LLVM is built with internal tests
+ included. Pass this to enable running test
+ other.test_llvm_lit in the Emscripten test
+ suite. Default: disabled.
+ --enable-assertions: If specified, LLVM is built with assert()
+ checks enabled. Useful for development
+ purposes. Default: Enabled
+ --disable-assertions: Forces assertions off during the build.
+
+ --vs2019/--vs2022: If building from source, overrides to build
+ using the specified compiler. When installing
+ precompiled packages, this has no effect.
+ Note: The same compiler specifier must be
+ passed to the emsdk activate command to
+ activate the desired version.
+
+ Notes on building from source:
+
+ To pass custom CMake directives when configuring
+ LLVM build, specify the environment variable
+ LLVM_CMAKE_ARGS="param1=value1,param2=value2"
+ in the environment where the build is invoked.
+ See README.md for details.
+
+ --override-repository: Specifies the git URL to use for a given Tool. E.g.
+ --override-repository emscripten-main@https://github.com//emscripten/tree/
+
+
+ emsdk uninstall - Removes the given tool or SDK from disk.''')
+
+ if WINDOWS:
+ print('''
+ emsdk activate [--permanent] [--system] [--build=type] [--vs2019/--vs2022]
+
+ - Activates the given tool or SDK in the
+ environment of the current shell.
+
+ - If the `--permanent` option is passed, then the environment
+ variables are set permanently for the current user.
+
+ - If the `--system` option is passed, the registration
+ is done for all users of the system.
+ This needs admin privileges
+ (uses Machine environment variables).
+
+ - If a custom compiler version was used to override
+ the compiler to use, pass the same --vs2019/--vs2022
+ parameter here to choose which version to activate.
+
+ emcmdprompt.bat - Spawns a new command prompt window with the
+ Emscripten environment active.''')
+ else:
+ print(''' emsdk activate [--build=type]
+
+ - Activates the given tool or SDK in the
+ environment of the current shell.''')
+
+ print('''
+ Both commands 'install' and 'activate' accept an optional parameter
+ '--build=type', which can be used to override what kind of installation
+ or activation to perform. Possible values for type are Debug, Release,
+ MinSizeRel or RelWithDebInfo. Note: When overriding a custom build type,
+ be sure to match the same --build= option to both 'install' and
+ 'activate' commands and the invocation of 'emsdk_env', or otherwise
+ these commands will default to operating on the default build type
+ which is RelWithDebInfo.''')
+
+ print('''
+
+ Environment:
+ EMSDK_KEEP_DOWNLOADS=1 - if you want to keep the downloaded archives.
+ EMSDK_NOTTY=1 - override isatty() result (mainly to log progress).
+ EMSDK_NUM_CORES=n - limit parallelism to n cores.
+ EMSDK_VERBOSE=1 - very verbose output, useful for debugging.''')
+ return 0
+
+ # Extracts a boolean command line argument from args and returns True if it was present
+ def extract_bool_arg(name):
+ if name in args:
+ args.remove(name)
+ return True
+ return False
+
+ def extract_string_arg(name):
+ for i in range(len(args)):
+ if args[i] == name:
+ value = args[i + 1]
+ del args[i:i + 2]
+ return value
+
+ arg_old = extract_bool_arg('--old')
+ arg_uses = extract_bool_arg('--uses')
+ arg_permanent = extract_bool_arg('--permanent')
+ arg_global = extract_bool_arg('--global')
+ arg_system = extract_bool_arg('--system')
+ if arg_global:
+ print('--global is deprecated. Use `--system` to set the environment variables for all users')
+ arg_system = True
+ if arg_system:
+ arg_permanent = True
+ if extract_bool_arg('--embedded'):
+ errlog('embedded mode is now the only mode available')
+ if extract_bool_arg('--no-embedded'):
+ errlog('embedded mode is now the only mode available')
+ return 1
+
+ arg_notty = extract_bool_arg('--notty')
+ if arg_notty:
+ global TTY_OUTPUT
+ TTY_OUTPUT = False
+
+ # Replace meta-packages with the real package names.
+ if cmd in ('update', 'install', 'activate'):
+ activating = cmd == 'activate'
+ args = [expand_sdk_name(a, activating=activating) for a in args]
+
+ load_em_config()
+ load_sdk_manifest()
+
+ # Apply any overrides to git branch names to clone from.
+ forked_url = extract_string_arg('--override-repository')
+ while forked_url:
+ tool_name, url_and_refspec = forked_url.split('@')
+ t = find_tool(tool_name)
+ if not t:
+ errlog('Failed to find tool ' + tool_name + '!')
+ return False
+ else:
+ t.url, t.git_branch = parse_github_url_and_refspec(url_and_refspec)
+ debug_print('Reading git repository URL "' + t.url + '" and git branch "' + t.git_branch + '" for Tool "' + tool_name + '".')
+
+ forked_url = extract_string_arg('--override-repository')
+
+ # Process global args
+ for i in range(len(args)):
+ if args[i].startswith('--generator='):
+ build_generator = re.match(r'''^--generator=['"]?([^'"]+)['"]?$''', args[i])
+ if build_generator:
+ global CMAKE_GENERATOR
+ CMAKE_GENERATOR = build_generator.group(1)
+ args[i] = ''
+ else:
+ errlog("Cannot parse CMake generator string: " + args[i] + ". Try wrapping generator string with quotes")
+ return 1
+ elif args[i].startswith('--build='):
+ build_type = re.match(r'^--build=(.+)$', args[i])
+ if build_type:
+ global CMAKE_BUILD_TYPE_OVERRIDE
+ build_type = build_type.group(1)
+ build_types = ['Debug', 'MinSizeRel', 'RelWithDebInfo', 'Release']
+ try:
+ build_type_index = [x.lower() for x in build_types].index(build_type.lower())
+ CMAKE_BUILD_TYPE_OVERRIDE = build_types[build_type_index]
+ args[i] = ''
+ except Exception:
+ errlog('Unknown CMake build type "' + build_type + '" specified! Please specify one of ' + str(build_types))
+ return 1
+ else:
+ errlog("Invalid command line parameter " + args[i] + ' specified!')
+ return 1
+ args = [x for x in args if x]
+
+ if cmd == 'list':
+ print('')
+
+ def installed_sdk_text(name):
+ sdk = find_sdk(name)
+ return 'INSTALLED' if sdk and sdk.is_installed() else ''
+
+ if (LINUX or MACOS or WINDOWS) and (ARCH == 'x86' or ARCH == 'x86_64'):
+ print('The *recommended* precompiled SDK download is %s (%s).' % (find_latest_version(), find_latest_hash()))
+ print()
+ print('To install/activate it use:')
+ print(' latest')
+ print('')
+ print('This is equivalent to installing/activating:')
+ print(' %s %s' % (find_latest_version(), installed_sdk_text(find_latest_sdk())))
+ print('')
+ else:
+ print('Warning: your platform does not have precompiled SDKs available.')
+ print('You may install components from source.')
+ print('')
+
+ print('All recent (non-legacy) installable versions are:')
+ releases_versions = sorted(load_releases_versions(), key=version_key, reverse=True)
+ releases_info = load_releases_info()['releases']
+ for ver in releases_versions:
+ print(' %s %s' % (ver, installed_sdk_text('sdk-releases-%s-64bit' % get_release_hash(ver, releases_info))))
+ print()
+
+ # Use array to work around the lack of being able to mutate from enclosing
+ # function.
+ has_partially_active_tools = [False]
+
+ if sdks:
+ def find_sdks(needs_compilation):
+ s = []
+ for sdk in sdks:
+ if sdk.is_old and not arg_old:
+ continue
+ if sdk.needs_compilation() == needs_compilation:
+ s += [sdk]
+ return s
+
+ def print_sdks(s):
+ for sdk in s:
+ installed = '\tINSTALLED' if sdk.is_installed() else ''
+ active = '*' if sdk.is_active() else ' '
+ print(' ' + active + ' {0: <25}'.format(str(sdk)) + installed)
+ if arg_uses:
+ for dep in sdk.uses:
+ print(' - {0: <25}'.format(dep))
+ print('')
+ print('The additional following precompiled SDKs are also available for download:')
+ print_sdks(find_sdks(False))
+
+ print('The following SDKs can be compiled from source:')
+ print_sdks(find_sdks(True))
+
+ if tools:
+ def find_tools(needs_compilation):
+ t = []
+ for tool in tools:
+ if tool.is_old and not arg_old:
+ continue
+ if tool.needs_compilation() != needs_compilation:
+ continue
+ t += [tool]
+ return t
+
+ def print_tools(t):
+ for tool in t:
+ if tool.is_old and not arg_old:
+ continue
+ if tool.can_be_installed() is True:
+ installed = '\tINSTALLED' if tool.is_installed() else ''
+ else:
+ installed = '\tNot available: ' + tool.can_be_installed()
+ tool_is_active = tool.is_active()
+ tool_is_env_active = tool_is_active and tool.is_env_active()
+ if tool_is_env_active:
+ active = ' * '
+ elif tool_is_active:
+ active = '(*)'
+ has_partially_active_tools[0] = has_partially_active_tools[0] or True
+ else:
+ active = ' '
+ print(' ' + active + ' {0: <25}'.format(str(tool)) + installed)
+ print('')
+
+ print('The following precompiled tool packages are available for download:')
+ print_tools(find_tools(needs_compilation=False))
+ print('The following tools can be compiled from source:')
+ print_tools(find_tools(needs_compilation=True))
+ else:
+ if is_emsdk_sourced_from_github():
+ print("There are no tools available. Run 'git pull' to fetch the latest set of tools.")
+ else:
+ print("There are no tools available. Run 'emsdk update' to fetch the latest set of tools.")
+ print('')
+
+ print('Items marked with * are activated for the current user.')
+ if has_partially_active_tools[0]:
+ env_cmd = 'emsdk_env.bat' if WINDOWS else 'source ./emsdk_env.sh'
+ print('Items marked with (*) are selected for use, but your current shell environment is not configured to use them. Type "' + env_cmd + '" to set up your current shell to use them' + (', or call "emsdk activate --permanent " to permanently activate them.' if WINDOWS else '.'))
+ if not arg_old:
+ print('')
+ print("To access the historical archived versions, type 'emsdk list --old'")
+
+ print('')
+ if is_emsdk_sourced_from_github():
+ print('Run "git pull" to pull in the latest list.')
+ else:
+ print('Run "./emsdk update" to pull in the latest list.')
+
+ return 0
+ elif cmd == 'construct_env':
+ # Clean up old temp file up front, in case of failure later before we get
+ # to write out the new one.
+ tools_to_activate = currently_active_tools()
+ tools_to_activate = process_tool_list(tools_to_activate)
+ env_string = construct_env(tools_to_activate, arg_system, arg_permanent)
+ if CMD or POWERSHELL:
+ write_set_env_script(env_string)
+ else:
+ sys.stdout.write(env_string)
+ return 0
+ elif cmd == 'update':
+ update_emsdk()
+ if WINDOWS:
+ # Clean up litter after old emsdk update which may have left this temp
+ # file around.
+ rmfile(sdk_path(EMSDK_SET_ENV))
+ return 0
+ elif cmd == 'update-tags':
+ errlog('`update-tags` is not longer needed. To install the latest tot release just run `install tot`')
+ return 0
+ elif cmd == 'activate':
+ if arg_permanent:
+ print('Registering active Emscripten environment permanently')
+ print('')
+
+ tools_to_activate = currently_active_tools()
+ for arg in args:
+ tool = find_tool(arg)
+ if tool is None:
+ tool = find_sdk(arg)
+ if tool is None:
+ error_on_missing_tool(arg)
+ tools_to_activate += [tool]
+ if not tools_to_activate:
+ errlog('No tools/SDKs specified to activate! Usage:\n emsdk activate tool/sdk1 [tool/sdk2] [...]')
+ return 1
+ active_tools = set_active_tools(tools_to_activate, permanently_activate=arg_permanent, system=arg_system)
+ if not active_tools:
+ errlog('No tools/SDKs found to activate! Usage:\n emsdk activate tool/sdk1 [tool/sdk2] [...]')
+ return 1
+ if WINDOWS and not arg_permanent:
+ errlog('The changes made to environment variables only apply to the currently running shell instance. Use the \'emsdk_env.bat\' to re-enter this environment later, or if you\'d like to register this environment permanently, rerun this command with the option --permanent.')
+ return 0
+ elif cmd == 'install':
+ global BUILD_FOR_TESTING, ENABLE_LLVM_ASSERTIONS, CPU_CORES, GIT_CLONE_SHALLOW
+
+ # Process args
+ for i in range(len(args)):
+ if args[i].startswith('-j'):
+ multicore = re.match(r'^-j(\d+)$', args[i])
+ if multicore:
+ CPU_CORES = int(multicore.group(1))
+ args[i] = ''
+ else:
+ errlog("Invalid command line parameter " + args[i] + ' specified!')
+ return 1
+ elif args[i] == '--shallow':
+ GIT_CLONE_SHALLOW = True
+ args[i] = ''
+ elif args[i] == '--build-tests':
+ BUILD_FOR_TESTING = True
+ args[i] = ''
+ elif args[i] == '--enable-assertions':
+ ENABLE_LLVM_ASSERTIONS = 'ON'
+ args[i] = ''
+ elif args[i] == '--disable-assertions':
+ ENABLE_LLVM_ASSERTIONS = 'OFF'
+ args[i] = ''
+ args = [x for x in args if x]
+ if not args:
+ errlog("Missing parameter. Type 'emsdk install ' to install a tool or an SDK. Type 'emsdk list' to obtain a list of available tools. Type 'emsdk install latest' to automatically install the newest version of the SDK.")
+ return 1
+
+ if LINUX and ARCH == 'arm64' and args != ['latest']:
+ errlog('WARNING: arm64-linux binaries are not available for all releases.')
+ errlog('See https://github.com/emscripten-core/emsdk/issues/547')
+
+ for t in args:
+ tool = find_tool(t)
+ if tool is None:
+ tool = find_sdk(t)
+ if tool is None:
+ error_on_missing_tool(t)
+ tool.install()
+ return 0
+ elif cmd == 'uninstall':
+ if not args:
+ errlog("Syntax error. Call 'emsdk uninstall '. Call 'emsdk list' to obtain a list of available tools.")
+ return 1
+ tool = find_tool(args[0])
+ if tool is None:
+ errlog("Error: Tool by name '" + args[0] + "' was not found.")
+ return 1
+ tool.uninstall()
+ return 0
+
+ errlog("Unknown command '" + cmd + "' given! Type 'emsdk help' to get a list of commands.")
+ return 1
+
+
+if __name__ == '__main__':
+ try:
+ sys.exit(main(sys.argv[1:]))
+ except KeyboardInterrupt:
+ exit_with_error('aborted by user, exiting')
+ sys.exit(1)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.bat
new file mode 100644
index 0000000000..c793321c98
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.bat
@@ -0,0 +1 @@
+@call "%~dp0emsdk" construct_env
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.csh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.csh
new file mode 100644
index 0000000000..187d4c5438
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.csh
@@ -0,0 +1,30 @@
+# This script is sourced by the user and uses
+# their shell. Try not to use tcshisms.
+
+# Do not execute this script without sourcing,
+# because it won't have any effect then.
+# That is, always run this script with
+#
+# source ./emsdk_env.csh
+#
+# instead of just plainly running with
+#
+# ./emsdk_env.csh
+#
+# which won't have any effect.
+set SRC=($_)
+if ("$SRC" == "") then
+ set SRC="$0"
+else
+ set SRC="$SRC[1]"
+endif
+set CURDIR=`pwd`
+setenv DIR `dirname "$SRC"`
+unset SRC
+
+setenv EMSDK_CSH 1
+
+eval `$DIR/emsdk construct_env`
+unsetenv DIR
+
+unsetenv EMSDK_CSH
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.fish b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.fish
new file mode 100644
index 0000000000..fbd3a0618c
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.fish
@@ -0,0 +1,14 @@
+#In your Fish configuration, add this line:
+#alias emsdk_setup ". /path/to/emsdk/emsdk_env.fish"
+#Now, when you want to use the SDK, run this alias first to set up
+#your environment.
+
+set -gx EMSDK_FISH 1
+
+set -l script (status -f)
+set -l dir (dirname $script)
+
+eval ($dir/emsdk construct_env)
+
+set -e -l script
+set -e -l dir
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.ps1 b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.ps1
new file mode 100644
index 0000000000..ab5fc4dc45
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.ps1
@@ -0,0 +1,2 @@
+$ScriptDirectory = Split-Path -parent $PSCommandPath
+& "$ScriptDirectory/emsdk.ps1" construct_env
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.sh
new file mode 100644
index 0000000000..75229e28a6
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_env.sh
@@ -0,0 +1,73 @@
+# This script is sourced by the user and uses
+# their shell.
+#
+# This script tries to find its location but
+# this does not work in every shell.
+#
+# It is known to work in bash, zsh and ksh
+#
+# Do not execute this script without sourcing,
+# because it won't have any effect then.
+# That is, always run this script with
+#
+# . /path/to/emsdk_env.sh
+#
+# or
+#
+# source /path/to/emsdk_env.sh
+#
+# instead of just plainly running with
+#
+# ./emsdk_env.sh
+#
+# which won't have any effect.
+
+CURRENT_SCRIPT=
+DIR="."
+
+# use shell specific method to get the path
+# to the current file being source'd.
+#
+# To add a shell, add another conditional below,
+# then add tests to scripts/test_source_env.sh
+
+if [ -n "${BASH_SOURCE-}" ]; then
+ CURRENT_SCRIPT="$BASH_SOURCE"
+elif [ -n "${ZSH_VERSION-}" ]; then
+ CURRENT_SCRIPT="${(%):-%x}"
+elif [ -n "${KSH_VERSION-}" ]; then
+ CURRENT_SCRIPT=${.sh.file}
+fi
+
+if [ -n "${CURRENT_SCRIPT-}" ]; then
+ DIR=$(dirname "$CURRENT_SCRIPT")
+ if [ -h "$CURRENT_SCRIPT" ]; then
+ # Now work out actual DIR since this is part of a symlink.
+ # Since we can't be sure that readlink or realpath
+ # are available, use tools more likely to be installed.
+ # (This will still fail if sed is not available.)
+ SYMDIR=$(dirname "$(ls -l "$CURRENT_SCRIPT" | sed -n "s/.*-> //p")")
+ if [ -z "$SYMDIR" ]; then
+ SYMDIR="."
+ fi
+ FULLDIR="$DIR/$SYMDIR"
+ DIR=$(cd "$FULLDIR" > /dev/null 2>&1; /bin/pwd)
+ unset SYMDIR
+ unset FULLDIR
+ fi
+fi
+unset CURRENT_SCRIPT
+
+if [ ! -f "$DIR/emsdk.py" ]; then
+ echo "Error: unable to determine 'emsdk' directory. Perhaps you are using a shell or" 1>&2
+ echo " environment that this script does not support." 1>&2
+ echo 1>&2
+ echo "A possible solution is to source this script while in the 'emsdk' directory." 1>&2
+ echo 1>&2
+ unset DIR
+ return
+fi
+
+# Force emsdk to use bash syntax so that this works in windows + bash too
+eval `EMSDK_BASH=1 "$DIR/emsdk" construct_env`
+unset DIR
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_manifest.json b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_manifest.json
new file mode 100644
index 0000000000..fd43f592ab
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/emsdk_manifest.json
@@ -0,0 +1,405 @@
+{
+ "tools": [
+ {
+ "id": "llvm-git",
+ "version": "main",
+ "bitness": 32,
+ "install_path": "llvm/git",
+ "git_branch": "main",
+ "url": "https://github.com/llvm/llvm-project.git",
+ "custom_install_script": "build_llvm",
+ "only_supports_wasm": true,
+ "activated_path": "%installation_dir%/%llvm_build_bin_dir%",
+ "activated_cfg": "LLVM_ROOT='%installation_dir%/%llvm_build_bin_dir%'",
+ "activated_env": "LLVM_ROOT=%installation_dir%/%llvm_build_bin_dir%;EMCC_WASM_BACKEND=1",
+ "cmake_build_type": "Release"
+ },
+ {
+ "id": "llvm-git",
+ "version": "main",
+ "bitness": 64,
+ "install_path": "llvm/git",
+ "git_branch": "main",
+ "url": "https://github.com/llvm/llvm-project.git",
+ "custom_install_script": "build_llvm",
+ "only_supports_wasm": true,
+ "activated_path": "%installation_dir%/%llvm_build_bin_dir%",
+ "activated_cfg": "LLVM_ROOT='%installation_dir%/%llvm_build_bin_dir%'",
+ "activated_env": "LLVM_ROOT=%installation_dir%/%llvm_build_bin_dir%;EMCC_WASM_BACKEND=1",
+ "cmake_build_type": "Release"
+ },
+
+ {
+ "id": "releases",
+ "version": "%releases-tag%",
+ "bitness": 64,
+ "arch": "x86_64",
+ "linux_url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/%releases-tag%/wasm-binaries.tar.xz",
+ "macos_url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/%releases-tag%/wasm-binaries.tar.xz",
+ "windows_url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/%releases-tag%/wasm-binaries.zip",
+ "download_prefix": "%releases-tag%-",
+ "install_path": "upstream",
+ "activated_path": "%installation_dir%/emscripten",
+ "activated_cfg": "LLVM_ROOT='%installation_dir%/bin';BINARYEN_ROOT='%installation_dir%';EMSCRIPTEN_ROOT='%installation_dir%/emscripten'",
+ "emscripten_releases_hash": "%releases-tag%"
+ },
+ {
+ "id": "releases",
+ "version": "%releases-tag%",
+ "bitness": 64,
+ "arch": "arm64",
+ "macos_url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/%releases-tag%/wasm-binaries-arm64.tar.xz",
+ "linux_url": "https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/%releases-tag%/wasm-binaries-arm64.tar.xz",
+ "download_prefix": "%releases-tag%-",
+ "install_path": "upstream",
+ "activated_path": "%installation_dir%/emscripten",
+ "activated_cfg": "LLVM_ROOT='%installation_dir%/bin';BINARYEN_ROOT='%installation_dir%';EMSCRIPTEN_ROOT='%installation_dir%/emscripten'",
+ "emscripten_releases_hash": "%releases-tag%"
+ },
+
+ {
+ "id": "node",
+ "version": "18.20.3",
+ "bitness": 32,
+ "arch": "x86",
+ "windows_url": "node-v18.20.3-win-x86.zip",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+ {
+ "id": "node",
+ "version": "18.20.3",
+ "arch": "arm",
+ "bitness": 32,
+ "linux_url": "node-v18.20.3-linux-armv7l.tar.xz",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+ {
+ "id": "node",
+ "version": "18.20.3",
+ "bitness": 64,
+ "arch": "x86_64",
+ "macos_url": "node-v18.20.3-darwin-x64.tar.gz",
+ "windows_url": "node-v18.20.3-win-x64.zip",
+ "linux_url": "node-v18.20.3-linux-x64.tar.xz",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+ {
+ "id": "node",
+ "version": "18.20.3",
+ "arch": "arm64",
+ "bitness": 64,
+ "macos_url": "node-v18.20.3-darwin-arm64.tar.gz",
+ "linux_url": "node-v18.20.3-linux-arm64.tar.xz",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+
+
+ {
+ "id": "node",
+ "version": "20.18.0",
+ "bitness": 32,
+ "arch": "x86",
+ "windows_url": "node-v20.18.0-win-x86.zip",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+ {
+ "id": "node",
+ "version": "20.18.0",
+ "arch": "arm",
+ "bitness": 32,
+ "linux_url": "node-v20.18.0-linux-armv7l.tar.xz",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+ {
+ "id": "node",
+ "version": "20.18.0",
+ "bitness": 64,
+ "arch": "x86_64",
+ "macos_url": "node-v20.18.0-darwin-x64.tar.gz",
+ "windows_url": "node-v20.18.0-win-x64.zip",
+ "linux_url": "node-v20.18.0-linux-x64.tar.xz",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+ {
+ "id": "node",
+ "version": "20.18.0",
+ "arch": "arm64",
+ "bitness": 64,
+ "windows_url": "node-v20.18.0-win-arm64.zip",
+ "macos_url": "node-v20.18.0-darwin-arm64.tar.gz",
+ "linux_url": "node-v20.18.0-linux-arm64.tar.xz",
+ "activated_path": "%installation_dir%/bin",
+ "activated_path_skip": "node",
+ "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'",
+ "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%"
+ },
+
+
+ {
+ "id": "python",
+ "version": "3.9.2-nuget",
+ "bitness": 64,
+ "arch": "x86_64",
+ "windows_url": "python-3.9.2-4-amd64+pywin32.zip",
+ "activated_cfg": "PYTHON='%installation_dir%/python.exe'",
+ "activated_env": "EMSDK_PYTHON=%installation_dir%/python.exe"
+ },
+ {
+ "id": "python",
+ "version": "3.9.2",
+ "bitness": 64,
+ "arch": "x86_64",
+ "windows_url": "python-3.9.2-1-embed-amd64+pywin32.zip",
+ "activated_cfg": "PYTHON='%installation_dir%/python.exe'",
+ "activated_env": "EMSDK_PYTHON=%installation_dir%/python.exe"
+ },
+ {
+ "id": "python",
+ "version": "3.9.2",
+ "bitness": 64,
+ "arch": "x86_64",
+ "macos_url": "python-3.9.2-3-macos-x86_64.tar.gz",
+ "activated_cfg": "PYTHON='%installation_dir%/bin/python3'",
+ "activated_env": "EMSDK_PYTHON=%installation_dir%/bin/python3;SSL_CERT_FILE=%installation_dir%/lib/python3.9/site-packages/certifi/cacert.pem"
+ },
+ {
+ "id": "python",
+ "version": "3.9.2",
+ "bitness": 64,
+ "arch": "arm64",
+ "macos_url": "python-3.9.2-1-macos-arm64.tar.gz",
+ "activated_cfg": "PYTHON='%installation_dir%/bin/python3'",
+ "activated_env": "EMSDK_PYTHON=%installation_dir%/bin/python3;SSL_CERT_FILE=%installation_dir%/lib/python3.9/site-packages/certifi/cacert.pem"
+ },
+ {
+ "id": "emscripten",
+ "version": "tag-%tag%",
+ "bitness": 32,
+ "append_bitness": false,
+ "windows_url": "https://github.com/emscripten-core/emscripten/archive/%tag%.zip",
+ "unix_url": "https://github.com/emscripten-core/emscripten/archive/%tag%.tar.gz",
+ "download_prefix": "emscripten-e",
+ "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'",
+ "activated_path": "%installation_dir%",
+ "activated_env": "EMSCRIPTEN=%installation_dir%",
+ "custom_install_script": "emscripten_npm_install"
+ },
+ {
+ "id": "emscripten",
+ "version": "tag-%tag%",
+ "bitness": 64,
+ "append_bitness": false,
+ "windows_url": "https://github.com/emscripten-core/emscripten/archive/%tag%.zip",
+ "unix_url": "https://github.com/emscripten-core/emscripten/archive/%tag%.tar.gz",
+ "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'",
+ "activated_path": "%installation_dir%",
+ "activated_env": "EMSCRIPTEN=%installation_dir%",
+ "custom_install_script": "emscripten_npm_install"
+ },
+ {
+ "id": "emscripten",
+ "version": "%precompiled_tag%",
+ "windows_url": "https://github.com/emscripten-core/emscripten/archive/%precompiled_tag%.zip",
+ "unix_url": "https://github.com/emscripten-core/emscripten/archive/%precompiled_tag%.tar.gz",
+ "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'",
+ "activated_path": "%installation_dir%",
+ "activated_env": "EMSCRIPTEN=%installation_dir%"
+ },
+ {
+ "id": "binaryen",
+ "version": "tag-%binaryen_tag%",
+ "bitness": 32,
+ "append_bitness": false,
+ "windows_url": "https://github.com/WebAssembly/binaryen/archive/%binaryen_tag%.zip",
+ "unix_url": "https://github.com/WebAssembly/binaryen/archive/%binaryen_tag%.tar.gz",
+ "download_prefix": "binaryen-e",
+ "activated_cfg": "BINARYEN_ROOT='%installation_dir%%generator_prefix%_64bit_binaryen'",
+ "activated_path": "%installation_dir%%generator_prefix%_64bit_binaryen/bin",
+ "activated_env": "BINARYEN_ROOT=%installation_dir%%generator_prefix%_64bit_binaryen",
+ "cmake_build_type": "Release",
+ "custom_install_script": "build_binaryen",
+ "custom_is_installed_script": "is_binaryen_installed",
+ "custom_uninstall_script": "uninstall_binaryen"
+ },
+ {
+ "id": "binaryen",
+ "version": "tag-%binaryen_tag%",
+ "bitness": 64,
+ "append_bitness": false,
+ "windows_url": "https://github.com/WebAssembly/binaryen/archive/%binaryen_tag%.zip",
+ "unix_url": "https://github.com/WebAssembly/binaryen/archive/%binaryen_tag%.tar.gz",
+ "download_prefix": "binaryen-e",
+ "activated_cfg": "BINARYEN_ROOT='%installation_dir%%generator_prefix%_64bit_binaryen'",
+ "activated_path": "%installation_dir%%generator_prefix%_64bit_binaryen/bin",
+ "activated_env": "BINARYEN_ROOT=%installation_dir%%generator_prefix%_64bit_binaryen",
+ "cmake_build_type": "Release",
+ "custom_install_script": "build_binaryen",
+ "custom_is_installed_script": "is_binaryen_installed",
+ "custom_uninstall_script": "uninstall_binaryen"
+ },
+ {
+ "id": "emscripten",
+ "version": "main",
+ "bitness": 32,
+ "append_bitness": false,
+ "url": "https://github.com/emscripten-core/emscripten.git",
+ "git_branch": "main",
+ "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'",
+ "activated_path": "%installation_dir%",
+ "activated_env": "EMSCRIPTEN=%installation_dir%",
+ "cmake_build_type": "Release",
+ "custom_install_script": "emscripten_npm_install"
+ },
+ {
+ "id": "emscripten",
+ "version": "main",
+ "bitness": 64,
+ "append_bitness": false,
+ "url": "https://github.com/emscripten-core/emscripten.git",
+ "git_branch": "main",
+ "activated_cfg": "EMSCRIPTEN_ROOT='%installation_dir%'",
+ "activated_path": "%installation_dir%",
+ "activated_env": "EMSCRIPTEN=%installation_dir%",
+ "cmake_build_type": "Release",
+ "custom_install_script": "emscripten_npm_install"
+ },
+ {
+ "id": "binaryen",
+ "version": "main",
+ "bitness": 32,
+ "append_bitness": false,
+ "url": "https://github.com/WebAssembly/binaryen.git",
+ "git_branch": "main",
+ "activated_cfg": "BINARYEN_ROOT='%installation_dir%%generator_prefix%_32bit_binaryen'",
+ "activated_path": "%installation_dir%%generator_prefix%_32bit_binaryen/bin",
+ "activated_env": "BINARYEN_ROOT=%installation_dir%%generator_prefix%_32bit_binaryen",
+ "cmake_build_type": "Release",
+ "custom_install_script": "build_binaryen",
+ "custom_is_installed_script": "is_binaryen_installed",
+ "custom_uninstall_script": "uninstall_binaryen"
+ },
+ {
+ "id": "binaryen",
+ "version": "main",
+ "bitness": 64,
+ "append_bitness": false,
+ "url": "https://github.com/WebAssembly/binaryen.git",
+ "git_branch": "main",
+ "activated_cfg": "BINARYEN_ROOT='%installation_dir%%generator_prefix%_64bit_binaryen'",
+ "activated_path": "%installation_dir%%generator_prefix%_64bit_binaryen/bin",
+ "activated_env": "BINARYEN_ROOT=%installation_dir%%generator_prefix%_64bit_binaryen",
+ "cmake_build_type": "Release",
+ "custom_install_script": "build_binaryen",
+ "custom_is_installed_script": "is_binaryen_installed",
+ "custom_uninstall_script": "uninstall_binaryen"
+ },
+ {
+ "id": "mingw",
+ "version": "7.1.0",
+ "bitness": 64,
+ "windows_url": "mingw_7.1.0_64bit.zip",
+ "activated_cfg": "MINGW_ROOT='%installation_dir%'",
+ "activated_path": "%installation_dir%/bin"
+ },
+ {
+ "id": "ninja",
+ "version": "git-release",
+ "bitness": 64,
+ "url": "https://github.com/ninja-build/ninja.git",
+ "git_branch": "release",
+ "activated_cfg": "NINJA=%installation_dir%/bin",
+ "activated_path": "%installation_dir%/bin",
+ "cmake_build_type": "Release",
+ "custom_install_script": "build_ninja"
+ },
+ {
+ "id": "ccache",
+ "version": "git-emscripten",
+ "bitness": 64,
+ "url": "https://github.com/juj/ccache.git",
+ "git_branch": "emscripten",
+ "activated_path": "%installation_dir%/bin",
+ "activated_env": "_EMCC_CCACHE=1;CCACHE_CONFIGPATH=%installation_dir%/emcc_ccache.conf",
+ "cmake_build_type": "Release",
+ "custom_install_script": "build_ccache"
+ }
+ ],
+
+ "sdks": [
+ {
+ "version": "main",
+ "bitness": 64,
+ "uses": ["python-3.9.2-nuget-64bit", "llvm-git-main-64bit", "node-20.18.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"],
+ "os": "win"
+ },
+ {
+ "version": "main",
+ "bitness": 64,
+ "uses": ["python-3.9.2-64bit", "llvm-git-main-64bit", "node-20.18.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"],
+ "os": "macos"
+ },
+ {
+ "version": "main",
+ "bitness": 64,
+ "uses": ["llvm-git-main-64bit", "node-20.18.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"],
+ "os": "linux"
+ },
+ {
+ "version": "main",
+ "bitness": 32,
+ "uses": ["llvm-git-main-32bit", "emscripten-main-32bit", "binaryen-main-32bit"],
+ "os": "linux"
+ },
+ {
+ "version": "releases-%releases-tag%",
+ "bitness": 64,
+ "uses": ["node-20.18.0-64bit", "releases-%releases-tag%-64bit"],
+ "os": "linux",
+ "custom_install_script": "emscripten_npm_install"
+ },
+ {
+ "version": "releases-%releases-tag%",
+ "bitness": 64,
+ "uses": ["node-20.18.0-64bit", "python-3.9.2-64bit", "releases-%releases-tag%-64bit"],
+ "os": "macos",
+ "arch": "x86_64",
+ "custom_install_script": "emscripten_npm_install"
+ },
+ {
+ "version": "releases-%releases-tag%",
+ "bitness": 64,
+ "uses": ["node-20.18.0-64bit", "python-3.9.2-64bit", "releases-%releases-tag%-64bit"],
+ "os": "macos",
+ "arch": "arm64",
+ "custom_install_script": "emscripten_npm_install"
+ },
+ {
+ "version": "releases-%releases-tag%",
+ "bitness": 64,
+ "uses": ["node-20.18.0-64bit", "python-3.9.2-nuget-64bit", "releases-%releases-tag%-64bit"],
+ "os": "win",
+ "custom_install_script": "emscripten_npm_install"
+ }
+ ]
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/legacy-binaryen-tags.txt b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/legacy-binaryen-tags.txt
new file mode 100644
index 0000000000..06d436c1a8
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/legacy-binaryen-tags.txt
@@ -0,0 +1,86 @@
+1.36.2
+1.36.3
+1.36.4
+1.36.5
+1.36.6
+1.36.7
+1.36.8
+1.36.9
+1.36.10
+1.36.11
+1.36.12
+1.36.13
+1.36.14
+1.37.0
+1.37.1
+1.37.2
+1.37.3
+1.37.4
+1.37.5
+1.37.6
+1.37.7
+1.37.8
+1.37.9
+1.37.10
+1.37.11
+1.37.12
+1.37.13
+1.37.14
+1.37.15
+1.37.16
+1.37.17
+1.37.18
+1.37.19
+1.37.20
+1.37.21
+1.37.22
+1.37.23
+1.37.24
+1.37.25
+1.37.26
+1.37.27
+1.37.28
+1.37.29
+1.37.30
+1.37.31
+1.37.32
+1.37.33
+1.37.34
+1.37.35
+1.37.36
+1.37.37
+1.37.38
+1.37.39
+1.37.40
+1.38.0
+1.38.1
+1.38.2
+1.38.3
+1.38.4
+1.38.5
+1.38.6
+1.38.7
+1.38.8
+1.38.9
+1.38.10
+1.38.11
+1.38.12
+1.38.13
+1.38.14
+1.38.15
+1.38.16
+1.38.17
+1.38.18
+1.38.19
+1.38.20
+1.38.21
+1.38.22
+1.38.23
+1.38.24
+1.38.25
+1.38.26
+1.38.27
+1.38.28
+1.38.29
+1.38.30
+1.38.31
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/legacy-emscripten-tags.txt b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/legacy-emscripten-tags.txt
new file mode 100644
index 0000000000..20069291a4
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/legacy-emscripten-tags.txt
@@ -0,0 +1,159 @@
+1.28.2
+1.28.3
+1.29.0
+1.29.1
+1.29.2
+1.29.3
+1.29.4
+1.29.5
+1.29.6
+1.29.7
+1.29.8
+1.29.9
+1.29.10
+1.29.11
+1.29.12
+1.30.0
+1.30.1
+1.30.2
+1.30.3
+1.30.4
+1.30.5
+1.30.6
+1.31.0
+1.31.1
+1.31.2
+1.31.3
+1.32.0
+1.32.1
+1.32.2
+1.32.3
+1.32.4
+1.33.0
+1.33.1
+1.33.2
+1.34.0
+1.34.1
+1.34.2
+1.34.3
+1.34.4
+1.34.5
+1.34.6
+1.34.7
+1.34.8
+1.34.9
+1.34.10
+1.34.11
+1.34.12
+1.35.0
+1.35.1
+1.35.2
+1.35.3
+1.35.4
+1.35.5
+1.35.6
+1.35.7
+1.35.8
+1.35.9
+1.35.10
+1.35.11
+1.35.12
+1.35.13
+1.35.14
+1.35.15
+1.35.16
+1.35.17
+1.35.18
+1.35.19
+1.35.20
+1.35.21
+1.35.22
+1.35.23
+1.36.0
+1.36.1
+1.36.2
+1.36.3
+1.36.4
+1.36.5
+1.36.6
+1.36.7
+1.36.8
+1.36.9
+1.36.10
+1.36.11
+1.36.12
+1.36.13
+1.36.14
+1.37.0
+1.37.1
+1.37.2
+1.37.3
+1.37.4
+1.37.5
+1.37.6
+1.37.7
+1.37.8
+1.37.9
+1.37.10
+1.37.11
+1.37.12
+1.37.13
+1.37.14
+1.37.15
+1.37.16
+1.37.17
+1.37.18
+1.37.19
+1.37.20
+1.37.21
+1.37.22
+1.37.23
+1.37.24
+1.37.25
+1.37.26
+1.37.27
+1.37.28
+1.37.29
+1.37.30
+1.37.31
+1.37.32
+1.37.33
+1.37.34
+1.37.35
+1.37.36
+1.37.37
+1.37.38
+1.37.39
+1.37.40
+1.38.0
+1.38.1
+1.38.2
+1.38.3
+1.38.4
+1.38.5
+1.38.6
+1.38.7
+1.38.8
+1.38.9
+1.38.10
+1.38.11
+1.38.12
+1.38.13
+1.38.14
+1.38.15
+1.38.16
+1.38.17
+1.38.18
+1.38.19
+1.38.20
+1.38.21
+1.38.22
+1.38.23
+1.38.24
+1.38.25
+1.38.26
+1.38.27
+1.38.28
+1.38.29
+1.38.30
+1.38.31
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/llvm-tags-64bit.txt b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/llvm-tags-64bit.txt
new file mode 100644
index 0000000000..7920f38fdc
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/llvm-tags-64bit.txt
@@ -0,0 +1,75 @@
+emscripten-llvm-e1.38.9.tar.gz
+emscripten-llvm-e1.38.8.tar.gz
+emscripten-llvm-e1.38.7.tar.gz
+emscripten-llvm-e1.38.6.tar.gz
+emscripten-llvm-e1.38.5.tar.gz
+emscripten-llvm-e1.38.4.tar.gz
+emscripten-llvm-e1.38.31.tar.gz
+emscripten-llvm-e1.38.30.tar.gz
+emscripten-llvm-e1.38.3.tar.gz
+emscripten-llvm-e1.38.29.tar.gz
+emscripten-llvm-e1.38.28.tar.gz
+emscripten-llvm-e1.38.27.tar.gz
+emscripten-llvm-e1.38.26.tar.gz
+emscripten-llvm-e1.38.25.tar.gz
+emscripten-llvm-e1.38.24.tar.gz
+emscripten-llvm-e1.38.23.tar.gz
+emscripten-llvm-e1.38.22.tar.gz
+emscripten-llvm-e1.38.21.tar.gz
+emscripten-llvm-e1.38.20.tar.gz
+emscripten-llvm-e1.38.2.tar.gz
+emscripten-llvm-e1.38.19.tar.gz
+emscripten-llvm-e1.38.18.tar.gz
+emscripten-llvm-e1.38.17.tar.gz
+emscripten-llvm-e1.38.16.tar.gz
+emscripten-llvm-e1.38.15.tar.gz
+emscripten-llvm-e1.38.14.tar.gz
+emscripten-llvm-e1.38.13.tar.gz
+emscripten-llvm-e1.38.12.tar.gz
+emscripten-llvm-e1.38.11.tar.gz
+emscripten-llvm-e1.38.10.tar.gz
+emscripten-llvm-e1.38.1.tar.gz
+emscripten-llvm-e1.38.0.tar.gz
+emscripten-llvm-e1.37.9.tar.gz
+emscripten-llvm-e1.37.8.tar.gz
+emscripten-llvm-e1.37.7.tar.gz
+emscripten-llvm-e1.37.6.tar.gz
+emscripten-llvm-e1.37.5.tar.gz
+emscripten-llvm-e1.37.40.tar.gz
+emscripten-llvm-e1.37.4.tar.gz
+emscripten-llvm-e1.37.39.tar.gz
+emscripten-llvm-e1.37.38.tar.gz
+emscripten-llvm-e1.37.37.tar.gz
+emscripten-llvm-e1.37.36.tar.gz
+emscripten-llvm-e1.37.35.tar.gz
+emscripten-llvm-e1.37.34.tar.gz
+emscripten-llvm-e1.37.33.tar.gz
+emscripten-llvm-e1.37.32.tar.gz
+emscripten-llvm-e1.37.31.tar.gz
+emscripten-llvm-e1.37.30.tar.gz
+emscripten-llvm-e1.37.3.tar.gz
+emscripten-llvm-e1.37.29.tar.gz
+emscripten-llvm-e1.37.28.tar.gz
+emscripten-llvm-e1.37.27.tar.gz
+emscripten-llvm-e1.37.26.tar.gz
+emscripten-llvm-e1.37.25.tar.gz
+emscripten-llvm-e1.37.24.tar.gz
+emscripten-llvm-e1.37.23.tar.gz
+emscripten-llvm-e1.37.22.tar.gz
+emscripten-llvm-e1.37.21.tar.gz
+emscripten-llvm-e1.37.20.tar.gz
+emscripten-llvm-e1.37.2.tar.gz
+emscripten-llvm-e1.37.19.tar.gz
+emscripten-llvm-e1.37.18.tar.gz
+emscripten-llvm-e1.37.17.tar.gz
+emscripten-llvm-e1.37.16.tar.gz
+emscripten-llvm-e1.37.15.tar.gz
+emscripten-llvm-e1.37.14.tar.gz
+emscripten-llvm-e1.37.13.tar.gz
+emscripten-llvm-e1.37.12.tar.gz
+emscripten-llvm-e1.37.11.tar.gz
+emscripten-llvm-e1.37.10.tar.gz
+emscripten-llvm-e1.37.1.tar.gz
+emscripten-llvm-e1.37.0.tar.gz
+emscripten-llvm-e1.36.14.tar.gz
+emscripten-llvm-e1.36.13.tar.gz
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/create_release.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/create_release.py
new file mode 100755
index 0000000000..425f7d7238
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/create_release.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+
+import argparse
+import json
+import os
+import re
+import subprocess
+import sys
+from collections import OrderedDict
+
+script_dir = os.path.dirname(os.path.abspath(__file__))
+root_dir = os.path.dirname(script_dir)
+sys.path.append(root_dir)
+
+import emsdk # noqa
+
+
+def version_key(version_string):
+ parts = re.split('[.-]', version_string)
+ key = [[int(part) for part in parts[:3]], -len(parts), parts[3:]]
+ return key
+
+
+def main():
+ if subprocess.check_output(['git', 'status', '--porcelain'], cwd=root_dir).strip():
+ print('tree is not clean')
+ sys.exit(1)
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-r', '--release-hash')
+ parser.add_argument('-a', '--asserts-hash')
+ parser.add_argument('-v', '--new-version')
+ parser.add_argument('--gh-action', action='store_true')
+ options = parser.parse_args()
+
+ release_info = emsdk.load_releases_info()
+ if options.new_version:
+ new_version = options.new_version
+ else:
+ new_version = version_key(release_info['aliases']['latest'])[0]
+ new_version[-1] += 1
+ new_version = '.'.join(str(part) for part in new_version)
+
+ asserts_hash = None
+ if options.release_hash:
+ new_hash = options.release_hash
+ asserts_hash = options.asserts_hash
+ else:
+ new_hash = emsdk.get_emscripten_releases_tot()
+
+ print('Creating new release: %s -> %s' % (new_version, new_hash))
+ release_info['releases'][new_version] = new_hash
+ if asserts_hash:
+ asserts_name = new_version + '-asserts'
+ release_info['releases'][asserts_name] = asserts_hash
+
+ releases = [(k, v) for k, v in release_info['releases'].items()]
+ releases.sort(key=lambda pair: version_key(pair[0]))
+
+ release_info['releases'] = OrderedDict(reversed(releases))
+ release_info['aliases']['latest'] = new_version
+
+ with open(os.path.join(root_dir, 'emscripten-releases-tags.json'), 'w') as f:
+ f.write(json.dumps(release_info, indent=2))
+ f.write('\n')
+
+ subprocess.check_call(
+ [sys.executable, os.path.join(script_dir, 'update_bazel_workspace.py')],
+ cwd=root_dir)
+
+ branch_name = 'version_' + new_version
+
+ if options.gh_action: # For GitHub Actions workflows
+ with open(os.environ['GITHUB_ENV'], 'a') as f:
+ f.write(f'RELEASE_VERSION={new_version}')
+ else: # Local use
+ # Create a new git branch
+ subprocess.check_call(['git', 'checkout', '-b', branch_name, 'origin/main'], cwd=root_dir)
+
+ # Create auto-generated changes to the new git branch
+ subprocess.check_call(['git', 'add', '-u', '.'], cwd=root_dir)
+ subprocess.check_call(['git', 'commit', '-m', new_version], cwd=root_dir)
+ print('New release created in branch: `%s`' % branch_name)
+
+ # Push new branch to origin
+ subprocess.check_call(['git', 'push', 'origin', branch_name], cwd=root_dir)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/get_emscripten_revision_info.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/get_emscripten_revision_info.py
new file mode 100755
index 0000000000..d0ad76eab9
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/get_emscripten_revision_info.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+import json
+import os
+import subprocess
+import sys
+
+EMSCRIPTEN_RELEASES_GIT = 'https://chromium.googlesource.com/emscripten-releases'
+TAGFILE = 'emscripten-releases-tags.json'
+
+
+def get_latest_hash(tagfile):
+ with open(tagfile) as f:
+ versions = json.load(f)
+ latest = versions['aliases']['latest']
+ return versions['releases'][latest]
+
+
+def get_latest_emscripten(tagfile):
+ latest = get_latest_hash(tagfile)
+ if not os.path.isdir('emscripten-releases'):
+ subprocess.run(['git', 'clone', EMSCRIPTEN_RELEASES_GIT, '--depth',
+ '100'], check=True)
+ # This will fail if the 'latest' revision is not within the most recent
+ # 100 commits; but that shouldn't happen because this script is intended
+ # to be run right after a release is added.
+ info = subprocess.run(['emscripten-releases/src/release-info.py',
+ 'emscripten-releases', latest],
+ stdout=subprocess.PIPE, check=True, text=True).stdout
+ for line in info.split('\n'):
+ tokens = line.split()
+ if len(tokens) and tokens[0] == 'emscripten':
+ return tokens[2]
+
+
+if __name__ == '__main__':
+ emscripten_hash = get_latest_emscripten(TAGFILE)
+ print('Emscripten revision ' + emscripten_hash)
+ if 'GITHUB_ENV' in os.environ:
+ with open(os.environ['GITHUB_ENV'], 'a') as f:
+ f.write(f'EMSCRIPTEN_HASH={emscripten_hash}')
+ sys.exit(0)
+ print('Not a GitHub Action')
+ sys.exit(1)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/get_release_info.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/get_release_info.py
new file mode 100755
index 0000000000..016a0aec7c
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/get_release_info.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+import json
+import sys
+
+
+def get_latest(tagfile):
+ with open(tagfile) as f:
+ versions = json.load(f)
+ print(versions['aliases']['latest'])
+ return 0
+
+
+def get_hash(tagfile, version):
+ with open(tagfile) as f:
+ versions = json.load(f)
+ print(versions['releases'][version])
+ return 0
+
+
+if __name__ == '__main__':
+ if sys.argv[2] == 'latest':
+ sys.exit(get_latest(sys.argv[1]))
+ if sys.argv[2] == 'hash':
+ sys.exit(get_hash(sys.argv[1], sys.argv[3]))
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_bazel_workspace.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_bazel_workspace.py
new file mode 100755
index 0000000000..637c355116
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_bazel_workspace.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+# This script will update emsdk/bazel/revisions.bzl to the latest version of
+# emscripten. It reads emsdk/emscripten-releases-tags.json to get the latest
+# version number. Then, it downloads the prebuilts for that version and computes
+# the sha256sum for the archive. It then puts all this information into the
+# emsdk/bazel/revisions.bzl file.
+
+import hashlib
+import json
+import os
+import re
+import requests
+import sys
+
+STORAGE_URL = 'https://storage.googleapis.com/webassembly/emscripten-releases-builds'
+
+EMSDK_ROOT = os.path.dirname(os.path.dirname(__file__))
+RELEASES_TAGS_FILE = EMSDK_ROOT + '/emscripten-releases-tags.json'
+BAZEL_REVISIONS_FILE = EMSDK_ROOT + '/bazel/revisions.bzl'
+BAZEL_MODULE_FILE = EMSDK_ROOT + '/bazel/MODULE.bazel'
+
+
+def get_latest_info():
+ with open(RELEASES_TAGS_FILE) as f:
+ info = json.load(f)
+ latest = info['aliases']['latest']
+ return latest, info['releases'][latest]
+
+
+def get_sha(platform, archive_fmt, latest_hash, arch_suffix=''):
+ r = requests.get(f'{STORAGE_URL}/{platform}/{latest_hash}/wasm-binaries{arch_suffix}.{archive_fmt}')
+ r.raise_for_status()
+ print(f'Fetching {r.url}')
+ h = hashlib.new('sha256')
+ for chunk in r.iter_content(chunk_size=1024):
+ h.update(chunk)
+ return h.hexdigest()
+
+
+def revisions_item(version, latest_hash):
+ return f'''\
+ "{version}": struct(
+ hash = "{latest_hash}",
+ sha_linux = "{get_sha('linux', 'tar.xz', latest_hash)}",
+ sha_linux_arm64 = "{get_sha('linux', 'tar.xz', latest_hash, '-arm64')}",
+ sha_mac = "{get_sha('mac', 'tar.xz', latest_hash)}",
+ sha_mac_arm64 = "{get_sha('mac', 'tar.xz', latest_hash, '-arm64')}",
+ sha_win = "{get_sha('win', 'zip', latest_hash)}",
+ ),
+'''
+
+
+def insert_revision(item):
+ with open(BAZEL_REVISIONS_FILE, 'r') as f:
+ lines = f.readlines()
+
+ lines.insert(lines.index('EMSCRIPTEN_TAGS = {\n') + 1, item)
+
+ with open(BAZEL_REVISIONS_FILE, 'w') as f:
+ f.write(''.join(lines))
+
+
+def update_module_version(version):
+ with open(BAZEL_MODULE_FILE, 'r') as f:
+ content = f.read()
+
+ pattern = r'(module\(\s*name = "emsdk",\s*version = )"\d+.\d+.\d+",\n\)'
+ # Verify that the pattern exists in the input since re.sub will
+ # will succeed either way.
+ assert re.search(pattern, content)
+ content = re.sub(pattern, fr'\1"{version}",\n)', content)
+
+ with open(BAZEL_MODULE_FILE, 'w') as f:
+ f.write(content)
+
+
+def main(argv):
+ version, latest_hash = get_latest_info()
+ update_module_version(version)
+ item = revisions_item(version, latest_hash)
+ print('inserting item:')
+ print(item)
+ insert_revision(item)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_node.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_node.py
new file mode 100755
index 0000000000..774c38ab2f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_node.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Copyright 2020 The Emscripten Authors. All rights reserved.
+# Emscripten is available under two separate licenses, the MIT license and the
+# University of Illinois/NCSA Open Source License. Both these licenses can be
+# found in the LICENSE file.
+
+"""Updates the node binaries that we cache store at
+http://storage.google.com/webassembly.
+
+For the windows version we also alter the directory layout to add the 'bin'
+directory.
+"""
+
+import urllib.request
+import subprocess
+import sys
+import os
+import shutil
+from zip import unzip_cmd, zip_cmd
+
+version = '20.18.0'
+base = 'https://nodejs.org/dist/v20.18.0/'
+upload_base = 'gs://webassembly/emscripten-releases-builds/deps/'
+
+suffixes = [
+ '-win-x86.zip',
+ '-win-x64.zip',
+ '-win-arm64.zip',
+ '-darwin-x64.tar.gz',
+ '-darwin-arm64.tar.gz',
+ '-linux-x64.tar.xz',
+ '-linux-arm64.tar.xz',
+ '-linux-armv7l.tar.xz',
+]
+
+for suffix in suffixes:
+ filename = 'node-v%s%s' % (version, suffix)
+ download_url = base + filename
+ print('Downloading: ' + download_url)
+ urllib.request.urlretrieve(download_url, filename)
+
+ if '-win-' in suffix:
+ subprocess.check_call(unzip_cmd() + [filename])
+ dirname = os.path.splitext(os.path.basename(filename))[0]
+ shutil.move(dirname, 'bin')
+ os.mkdir(dirname)
+ shutil.move('bin', dirname)
+ os.remove(filename)
+ subprocess.check_call(zip_cmd() + [filename, dirname])
+ shutil.rmtree(dirname)
+
+ if '--upload' in sys.argv:
+ upload_url = upload_base + filename
+ print('Uploading: ' + upload_url)
+ cmd = ['gsutil', 'cp', '-n', filename, upload_url]
+ print(' '.join(cmd))
+ subprocess.check_call(cmd)
+ os.remove(filename)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_python.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_python.py
new file mode 100755
index 0000000000..a37b701df9
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/update_python.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python3
+# Copyright 2020 The Emscripten Authors. All rights reserved.
+# Emscripten is available under two separate licenses, the MIT license and the
+# University of Illinois/NCSA Open Source License. Both these licenses can be
+# found in the LICENSE file.
+
+"""Updates the python binaries that we cache store at
+http://storage.google.com/webassembly.
+
+We only supply binaries for windows and macOS, but we do it very different ways for those two OSes.
+
+Windows recipe:
+ 1. Download the "embeddable zip file" version of python from python.org
+ 2. Remove .pth file to work around https://bugs.python.org/issue34841
+ 3. Download and install pywin32 in the `site-packages` directory
+ 4. Re-zip and upload to storage.google.com
+
+macOS recipe:
+ 1. Clone cpython
+ 2. Use homebrew to install and configure openssl (for static linking!)
+ 3. Build cpython from source and use `make install` to create archive.
+"""
+
+import glob
+import multiprocessing
+import os
+import platform
+import urllib.request
+import shutil
+import subprocess
+import sys
+from subprocess import check_call
+from zip import unzip_cmd, zip_cmd
+
+version = '3.9.2'
+major_minor_version = '.'.join(version.split('.')[:2]) # e.g. '3.9.2' -> '3.9'
+download_url = 'https://www.nuget.org/api/v2/package/python/%s' % version
+# This is not part of official Python version, but a repackaging number appended by emsdk
+# when a version of Python needs to be redownloaded.
+revision = '4'
+
+pywin32_version = '227'
+pywin32_base = 'https://github.com/mhammond/pywin32/releases/download/b%s/' % pywin32_version
+
+upload_base = 'gs://webassembly/emscripten-releases-builds/deps/'
+
+
+def make_python_patch():
+ pywin32_filename = 'pywin32-%s.win-amd64-py%s.exe' % (pywin32_version, major_minor_version)
+ filename = 'python-%s-amd64.zip' % (version)
+ out_filename = 'python-%s-%s-amd64+pywin32.zip' % (version, revision)
+ if not os.path.exists(pywin32_filename):
+ url = pywin32_base + pywin32_filename
+ print('Downloading pywin32: ' + url)
+ urllib.request.urlretrieve(url, pywin32_filename)
+
+ if not os.path.exists(filename):
+ print(f'Downloading python: {download_url} to {filename}')
+ urllib.request.urlretrieve(download_url, filename)
+
+ os.mkdir('python-nuget')
+ check_call(unzip_cmd() + [os.path.abspath(filename)], cwd='python-nuget')
+ os.remove(filename)
+
+ os.mkdir('pywin32')
+ rtn = subprocess.call(unzip_cmd() + [os.path.abspath(pywin32_filename)], cwd='pywin32')
+ assert rtn in [0, 1]
+
+ os.mkdir(os.path.join('python-nuget', 'lib'))
+ shutil.move(os.path.join('pywin32', 'PLATLIB'), os.path.join('python-nuget', 'toolss', 'Lib', 'site-packages'))
+
+ check_call(zip_cmd() + [os.path.join('..', '..', out_filename), '.'], cwd='python-nuget/tools')
+ print('Created: %s' % out_filename)
+
+ # cleanup if everything went fine
+ shutil.rmtree('python-nuget')
+ shutil.rmtree('pywin32')
+
+ if '--upload' in sys.argv:
+ upload_url = upload_base + out_filename
+ print('Uploading: ' + upload_url)
+ cmd = ['gsutil', 'cp', '-n', out_filename, upload_url]
+ print(' '.join(cmd))
+ check_call(cmd)
+
+
+def build_python():
+ if sys.platform.startswith('darwin'):
+ # Take some rather drastic steps to link openssl and liblzma statically
+ # and avoid linking libintl completely.
+ osname = 'macos'
+ check_call(['brew', 'install', 'openssl', 'xz', 'pkg-config'])
+ if platform.machine() == 'x86_64':
+ prefix = '/usr/local'
+ min_macos_version = '10.11'
+ elif platform.machine() == 'arm64':
+ prefix = '/opt/homebrew'
+ min_macos_version = '11.0'
+
+ # Append '-x86_64' or '-arm64' depending on current arch. (TODO: Do
+ # this for Linux too, move this below?)
+ osname += '-' + platform.machine()
+
+ for f in [os.path.join(prefix, 'lib', 'libintl.dylib'),
+ os.path.join(prefix, 'include', 'libintl.h'),
+ os.path.join(prefix, 'opt', 'xz', 'lib', 'liblzma.dylib'),
+ os.path.join(prefix, 'opt', 'openssl', 'lib', 'libssl.dylib'),
+ os.path.join(prefix, 'opt', 'openssl', 'lib', 'libcrypto.dylib')]:
+ if os.path.exists(f):
+ os.remove(f)
+ os.environ['PKG_CONFIG_PATH'] = os.path.join(prefix, 'opt', 'openssl', 'lib', 'pkgconfig')
+ else:
+ osname = 'linux'
+
+ src_dir = 'cpython'
+ if not os.path.exists(src_dir):
+ check_call(['git', 'clone', 'https://github.com/python/cpython'])
+ check_call(['git', 'checkout', 'v' + version], cwd=src_dir)
+
+ env = os.environ
+ if sys.platform.startswith('darwin'):
+ # Specify the min OS version we want the build to work on
+ min_macos_version_line = '-mmacosx-version-min=' + min_macos_version
+ build_flags = min_macos_version_line + ' -Werror=partial-availability'
+ # Build against latest SDK, but issue an error if using any API that would not work on the min OS version
+ env = env.copy()
+ env['MACOSX_DEPLOYMENT_TARGET'] = min_macos_version
+ configure_args = ['CFLAGS=' + build_flags, 'CXXFLAGS=' + build_flags, 'LDFLAGS=' + min_macos_version_line]
+ else:
+ configure_args = []
+ check_call(['./configure'] + configure_args, cwd=src_dir, env=env)
+ check_call(['make', '-j', str(multiprocessing.cpu_count())], cwd=src_dir, env=env)
+ check_call(['make', 'install', 'DESTDIR=install'], cwd=src_dir, env=env)
+
+ install_dir = os.path.join(src_dir, 'install')
+
+ # Install requests module. This is needed in particular on macOS to ensure
+ # SSL certificates are available (certifi in installed and used by requests).
+ pybin = os.path.join(src_dir, 'install', 'usr', 'local', 'bin', 'python3')
+ pip = os.path.join(src_dir, 'install', 'usr', 'local', 'bin', 'pip3')
+ check_call([pybin, '-m', 'ensurepip', '--upgrade'])
+ check_call([pybin, pip, 'install', 'requests==2.32.3'])
+
+ # Install psutil module. This is needed by emrun to track when browser
+ # process quits.
+ check_call([pybin, pip, 'install', 'psutil'])
+
+ dirname = 'python-%s-%s' % (version, revision)
+ if os.path.isdir(dirname):
+ print('Erasing old build directory ' + dirname)
+ shutil.rmtree(dirname)
+ os.rename(os.path.join(install_dir, 'usr', 'local'), dirname)
+ tarball = 'python-%s-%s-%s.tar.gz' % (version, revision, osname)
+ shutil.rmtree(os.path.join(dirname, 'lib', 'python' + major_minor_version, 'test'))
+ shutil.rmtree(os.path.join(dirname, 'include'))
+ for lib in glob.glob(os.path.join(dirname, 'lib', 'lib*.a')):
+ os.remove(lib)
+ check_call(['tar', 'zcvf', tarball, dirname])
+
+ print('Created: %s' % tarball)
+ if '--upload' in sys.argv:
+ print('Uploading: ' + upload_base + tarball)
+ check_call(['gsutil', 'cp', '-n', tarball, upload_base + tarball])
+
+
+def main():
+ if sys.platform.startswith('win') or '--win32' in sys.argv:
+ make_python_patch()
+ else:
+ build_python()
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/zip.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/zip.py
new file mode 100644
index 0000000000..1b52a81e50
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/scripts/zip.py
@@ -0,0 +1,19 @@
+import os
+
+
+def unzip_cmd():
+ # Use 7-Zip if available (https://www.7-zip.org/)
+ sevenzip = os.path.join(os.getenv('ProgramFiles', ''), '7-Zip', '7z.exe')
+ if os.path.isfile(sevenzip):
+ return [sevenzip, 'x']
+ # Fall back to 'unzip' tool
+ return ['unzip', '-q']
+
+
+def zip_cmd():
+ # Use 7-Zip if available (https://www.7-zip.org/)
+ sevenzip = os.path.join(os.getenv('ProgramFiles', ''), '7-Zip', '7z.exe')
+ if os.path.isfile(sevenzip):
+ return [sevenzip, 'a', '-mx9']
+ # Fall back to 'zip' tool
+ return ['zip', '-rq']
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.bat b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.bat
new file mode 100644
index 0000000000..c39bb3c19c
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.bat
@@ -0,0 +1,7 @@
+:: equivalent of test.sh as windows bat file
+set PATH=%PATH%;%PYTHON_BIN%
+CALL emsdk install latest
+CALL emsdk activate latest
+CALL emsdk_env.bat
+CALL python -c "import sys; print(sys.executable)"
+CALL emcc.bat -v
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.py b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.py
new file mode 100755
index 0000000000..6d57881690
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python3
+import json
+import os
+import platform
+import shutil
+import subprocess
+import sys
+import tempfile
+import unittest
+
+WINDOWS = sys.platform.startswith('win')
+MACOS = sys.platform == 'darwin'
+MACOS_ARM64 = MACOS and platform.machine() == 'arm64'
+
+emconfig = os.path.abspath('.emscripten')
+assert os.path.exists(emconfig)
+
+upstream_emcc = os.path.join('upstream', 'emscripten', 'emcc')
+emsdk = './emsdk'
+if WINDOWS:
+ upstream_emcc += '.bat'
+ emsdk = 'emsdk.bat'
+else:
+ emsdk = './emsdk'
+
+# Utilities
+
+
+def listify(x):
+ if type(x) in {list, tuple}:
+ return x
+ return [x]
+
+
+def check_call(cmd, **args):
+ if type(cmd) is not list:
+ cmd = cmd.split()
+ print('running: %s' % cmd)
+ args['universal_newlines'] = True
+ subprocess.check_call(cmd, **args)
+
+
+def checked_call_with_output(cmd, expected=None, unexpected=None, stderr=None, env=None):
+ cmd = cmd.split(' ')
+ print('running: %s' % cmd)
+ try:
+ stdout = subprocess.check_output(cmd, stderr=stderr, universal_newlines=True, env=env)
+ except subprocess.CalledProcessError as e:
+ print(e.stderr)
+ print(e.stdout)
+ raise e
+
+ if expected:
+ for x in listify(expected):
+ assert x in stdout, 'expected output missing: ' + stdout + '\n[[[' + x + ']]]'
+ if unexpected:
+ for x in listify(unexpected):
+ assert x not in stdout, 'unexpected output present: ' + stdout + '\n[[[' + x + ']]]'
+
+
+def failing_call_with_output(cmd, expected, env=None):
+ proc = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=env)
+ stdout, stderr = proc.communicate()
+ if WINDOWS:
+ print('warning: skipping part of failing_call_with_output() due to error codes not being propagated (see #592)')
+ else:
+ assert proc.returncode, 'call must have failed: ' + str([stdout, '\n========\n', stderr])
+ assert expected in stdout or expected in stderr, 'call did not have the expected output: %s: %s' % (expected, str([stdout, '\n========\n', stderr]))
+
+
+def hack_emsdk(marker, replacement):
+ with open('emsdk.py') as f:
+ src = f.read()
+ assert marker in src
+ src = src.replace(marker, replacement)
+ name = '__test_emsdk'
+ with open(name, 'w') as f:
+ f.write(src)
+ return name
+
+
+# Set up
+
+TAGS = json.loads(open('emscripten-releases-tags.json').read())
+
+# Tests
+
+
+def do_lib_building(emcc):
+ cache_building_messages = ['generating system library: ']
+
+ def do_build(args, is_expected=None):
+ unexpected = None
+ expected = None
+ if is_expected is True:
+ expected = cache_building_messages
+ elif is_expected is False:
+ unexpected = cache_building_messages
+ checked_call_with_output(emcc + ' hello_world.c' + args,
+ expected=expected,
+ unexpected=unexpected,
+ stderr=subprocess.STDOUT)
+
+ # The emsdk ships all system libraries so we don't expect to see any
+ # cache population unless we explicly --clear-cache.
+ do_build('', is_expected=False)
+ check_call(emcc + ' --clear-cache')
+ do_build(' -O2', is_expected=True)
+ # Do another build at -O0. In nwers SDK versions this generates
+ # different libs, but not in older ones so don't assert here.
+ do_build('')
+ # Now verify that libs are *not* build
+ do_build(' -s WASM=0', is_expected=False)
+ do_build(' -O2 -s WASM=0', is_expected=False)
+
+
+def run_emsdk(cmd):
+ if type(cmd) is not list:
+ cmd = cmd.split()
+ check_call([emsdk] + cmd)
+
+
+class Emsdk(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ with open('hello_world.c', 'w') as f:
+ f.write('''\
+#include
+
+int main() {
+ printf("Hello, world!\\n");
+ return 0;
+}
+''')
+
+ def setUp(self):
+ run_emsdk('install latest')
+ run_emsdk('activate latest')
+
+ def test_unknown_arch(self):
+ env = os.environ.copy()
+ env['EMSDK_ARCH'] = 'mips'
+ failing_call_with_output(emsdk + ' install latest',
+ expected='unknown machine architecture: mips',
+ env=env)
+
+ def test_wrong_bitness(self):
+ env = os.environ.copy()
+ env['EMSDK_ARCH'] = 'x86'
+ failing_call_with_output(emsdk + ' install sdk-latest-64bit',
+ expected='is only provided for 64-bit OSe',
+ env=env)
+
+ def test_already_installed(self):
+ # Test we don't re-download unnecessarily
+ checked_call_with_output(emsdk + ' install latest', expected='already installed', unexpected='Downloading:')
+
+ def test_list(self):
+ # Test we report installed tools properly. The latest version should be
+ # installed, but not some random old one.
+ checked_call_with_output(emsdk + ' list', expected=TAGS['aliases']['latest'] + ' INSTALLED', unexpected='1.39.15 INSTALLED:')
+
+ def test_config_contents(self):
+ print('test .emscripten contents')
+ with open(emconfig) as f:
+ config = f.read()
+ assert 'upstream' in config
+
+ def test_lib_building(self):
+ print('building proper system libraries')
+ do_lib_building(upstream_emcc)
+
+ def test_redownload(self):
+ print('go back to using upstream')
+ run_emsdk('activate latest')
+
+ # Test the normal tools like node don't re-download on re-install
+ print('another install must re-download')
+ checked_call_with_output(emsdk + ' uninstall node-20.18.0-64bit')
+ checked_call_with_output(emsdk + ' install node-20.18.0-64bit', expected='Downloading:', unexpected='already installed')
+ checked_call_with_output(emsdk + ' install node-20.18.0-64bit', unexpected='Downloading:', expected='already installed')
+
+ def test_tot_upstream(self):
+ print('test update-tags')
+ run_emsdk('update-tags')
+ print('test tot-upstream')
+ run_emsdk('install tot-upstream')
+ with open(emconfig) as f:
+ config = f.read()
+ run_emsdk('activate tot-upstream')
+ with open(emconfig + '.old') as f:
+ old_config = f.read()
+ self.assertEqual(config, old_config)
+ # TODO; test on latest as well
+ check_call(upstream_emcc + ' hello_world.c')
+
+ def test_closure(self):
+ # Specifically test with `--closure` so we know that node_modules is working
+ check_call(upstream_emcc + ' hello_world.c --closure=1')
+
+ def test_specific_version(self):
+ if MACOS_ARM64:
+ self.skipTest('Old sdk versions do not have ARM64 binaries')
+ print('test specific release (new, short name)')
+ run_emsdk('install 1.38.33')
+ print('another install, but no need for re-download')
+ checked_call_with_output(emsdk + ' install 1.38.33', expected='Skipped', unexpected='Downloading:')
+ run_emsdk('activate 1.38.33')
+
+ def test_specific_version_full(self):
+ if MACOS_ARM64:
+ self.skipTest('Old sdk versions do not have ARM64 binaries')
+ print('test specific release (new, full name)')
+ run_emsdk('install sdk-1.38.33-64bit')
+ run_emsdk('activate sdk-1.38.33-64bit')
+ print('test specific release (new, tag name)')
+ run_emsdk('install sdk-tag-1.38.33-64bit')
+ run_emsdk('activate sdk-tag-1.38.33-64bit')
+
+ def test_binaryen_from_source(self):
+ if MACOS:
+ self.skipTest("https://github.com/WebAssembly/binaryen/issues/4299")
+ print('test binaryen source build')
+ run_emsdk(['install', '--build=Release', '--generator=Unix Makefiles', 'binaryen-main-64bit'])
+
+ def test_no_32bit(self):
+ print('test 32-bit error')
+ emsdk_hacked = hack_emsdk('not is_os_64bit()', 'True')
+ failing_call_with_output('%s %s install latest' % (sys.executable, emsdk_hacked),
+ 'this tool is only provided for 64-bit OSes')
+ os.remove(emsdk_hacked)
+
+ def test_update_no_git(self):
+ print('test non-git update')
+
+ temp_dir = tempfile.mkdtemp()
+ for filename in os.listdir('.'):
+ if not filename.startswith('.') and not os.path.isdir(filename):
+ shutil.copy2(filename, os.path.join(temp_dir, filename))
+
+ olddir = os.getcwd()
+ try:
+ os.chdir(temp_dir)
+ run_emsdk('update')
+
+ print('second time')
+ run_emsdk('update')
+ finally:
+ os.chdir(olddir)
+
+ def test_install_arbitrary(self):
+ # Test that its possible to install arbrary emscripten-releases SDKs
+ run_emsdk('install 1b7f7bc6002a3ca73647f41fc10e1fac7f06f804')
+
+ # Check that its not re-downloaded
+ checked_call_with_output(emsdk + ' install 1b7f7bc6002a3ca73647f41fc10e1fac7f06f804', expected='Skipped', unexpected='Downloading:')
+
+ def test_install_tool(self):
+ # Test that its possible to install emscripten as tool instead of SDK
+ checked_call_with_output(emsdk + ' install releases-77b065ace39e6ab21446e13f92897f956c80476a', unexpected='Installing SDK')
+
+ def test_activate_missing(self):
+ run_emsdk('install latest')
+ failing_call_with_output(emsdk + ' activate 2.0.1', expected="error: tool is not installed and therefore cannot be activated: 'releases-13e29bd55185e3c12802bc090b4507901856b2ba-64bit'")
+
+ def test_keep_downloads(self):
+ env = os.environ.copy()
+ env['EMSDK_KEEP_DOWNLOADS'] = '1'
+ # With EMSDK_KEEP_DOWNLOADS the downloading should happen on the first
+ # install of 2.0.28, and again when we install 2.0.29, but not on the
+ # second install of 2.0.28 because the zip should already be local.
+ shutil.rmtree('downloads')
+ checked_call_with_output(emsdk + ' install 3.1.54', expected='Downloading:', env=env)
+ checked_call_with_output(emsdk + ' install 3.1.55', expected='Downloading:', env=env)
+ checked_call_with_output(emsdk + ' install 3.1.54', expected='already downloaded, skipping', unexpected='Downloading:', env=env)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.sh
new file mode 100755
index 0000000000..5033fd9613
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+
+echo "test the standard workflow (as close as possible to how a user would do it, in the shell)"
+echo "machine: $(uname -m)"
+echo "kernel: $(uname -s)"
+
+set -x
+set -e
+
+# Test that arbitrary (non-released) versions can be installed and
+# activated.
+# This test cannot run on linux-arm64 because only certain binaries
+# get uploaded for this architecture.
+if [[ !($(uname -s) == "Linux" && $(uname -m) == "aarch64") ]]; then
+ ./emsdk install sdk-upstream-1b7f7bc6002a3ca73647f41fc10e1fac7f06f804
+ ./emsdk activate sdk-upstream-1b7f7bc6002a3ca73647f41fc10e1fac7f06f804
+ source ./emsdk_env.sh
+ which emcc
+ emcc -v
+fi
+
+# Install an older version of the SDK that requires EM_CACHE to be
+# set in the environment, so that we can test it is later removed
+# This test only runs on x64 because we didn't build arm binaries
+# when this older version of the SDK was built.
+if [[ $(uname -m) == "x86_64" ]]; then
+ ./emsdk install sdk-1.39.15
+ ./emsdk activate sdk-1.39.15
+ source ./emsdk_env.sh
+ which emcc
+ emcc -v
+ test -n "$EM_CACHE"
+fi
+
+# Install the latest version of the SDK which is the expected precondition
+# of test.py.
+./emsdk install latest
+./emsdk activate latest
+source ./emsdk_env.sh --build=Release
+# Test that EM_CACHE was unset
+test -z "$EM_CACHE"
+
+# On mac and windows python3 should be in the path and point to the
+# bundled version.
+which python3
+which emcc
+emcc -v
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_activation.ps1 b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_activation.ps1
new file mode 100644
index 0000000000..31a2c8eb8f
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_activation.ps1
@@ -0,0 +1,88 @@
+# This test installs emsdk and activates the latest toolchain using `--system` or `--permanent` flags,
+# and checks if the environment variables and PATH are correctly updated. Set $env:SYSTEM_FLAG and $env:PERMANENT_FLAG to test each.
+# If no flag is provided the process/shell values are tested. See the CI file for an example.
+
+refreshenv
+
+$repo_root = [System.IO.Path]::GetDirectoryName((resolve-path "$PSScriptRoot"))
+
+$PATH_USER_BEFORE = [System.Environment]::GetEnvironmentVariable("PATH", "User")
+$PATH_MACHINE_BEFORE = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
+$PATH_Process_BEFORE = [System.Environment]::GetEnvironmentVariable("PATH", "Process")
+
+
+try {
+
+ & "$repo_root/emsdk.ps1" install latest
+
+ & "$repo_root/emsdk.ps1" activate latest $env:PERMANENT_FLAG $env:SYSTEM_FLAG
+
+ if ($env:SYSTEM_FLAG) {
+ $env_type = "Machine"
+ }
+ elseif ($env:PERMANENT_FLAG) {
+ $env_type = "User"
+ } else {
+ $env_type = "Process"
+ }
+
+ $EMSDK = [System.Environment]::GetEnvironmentVariable("EMSDK", $env_type)
+ $EMSDK_NODE = [System.Environment]::GetEnvironmentVariable("EMSDK_NODE", $env_type)
+ $EMSDK_PYTHON = [System.Environment]::GetEnvironmentVariable("EMSDK_PYTHON", $env_type)
+ $PATH = [System.Environment]::GetEnvironmentVariable("PATH", $env_type)
+
+ if (!$EMSDK) {
+ throw "EMSDK is not set for the user"
+ }
+ if (!$EMSDK_NODE) {
+ throw "EMSDK_NODE is not set for the user"
+ }
+ if (!$EMSDK_PYTHON) {
+ throw "EMSDK_PYTHON is not set for the user"
+ }
+
+
+ $path_split = $PATH.Split(';')
+
+ $EMSDK_Path = $path_split | Where-Object { $_ -like "$repo_root*" }
+ if (!$EMSDK_Path) {
+ throw "No path is added!"
+ }
+
+ $EMSDK_UPSTREAM_Path = $path_split | Where-Object { $_ -like "$repo_root\upstream\emscripten*" }
+ if (!$EMSDK_UPSTREAM_Path) {
+ throw "$repo_root\\upstream\emscripten is not added to path."
+ }
+
+
+}
+finally {
+ # Recover pre-split PATH
+ refreshenv
+
+ [Environment]::SetEnvironmentVariable("Path", $PATH_USER_BEFORE, "User")
+ try {
+ [Environment]::SetEnvironmentVariable("Path", $PATH_MACHINE_BEFORE, "Machine")
+ }
+ catch {}
+
+ [Environment]::SetEnvironmentVariable("Path", $PATH_Process_BEFORE, "Process")
+
+ # Recover pre activation env variables
+ [Environment]::SetEnvironmentVariable("EMSDK", $null, "User")
+ [Environment]::SetEnvironmentVariable("EMSDK_NODE", $null, "User")
+ [Environment]::SetEnvironmentVariable("EMSDK_PYTHON", $null, "User")
+
+ try {
+ [Environment]::SetEnvironmentVariable("EMSDK", $null, "Machine")
+ [Environment]::SetEnvironmentVariable("EMSDK_NODE", $null, "Machine")
+ [Environment]::SetEnvironmentVariable("EMSDK_PYTHON", $null, "Machine")
+ } catch {}
+
+
+ [Environment]::SetEnvironmentVariable("EMSDK", $null, "Process")
+ [Environment]::SetEnvironmentVariable("EMSDK_NODE", $null, "Process")
+ [Environment]::SetEnvironmentVariable("EMSDK_PYTHON", $null, "Process")
+
+ refreshenv
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel.ps1 b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel.ps1
new file mode 100644
index 0000000000..5c20a15251
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel.ps1
@@ -0,0 +1,30 @@
+$ErrorActionPreference = 'Stop'
+
+Set-Location bazel
+
+bazel build //hello-world:hello-world-wasm
+if (-not $?) { Exit $LastExitCode }
+
+bazel build //hello-world:hello-world-wasm-simd
+if (-not $?) { Exit $LastExitCode }
+
+Set-Location test_external
+
+bazel build //:hello-world-wasm
+if (-not $?) { Exit $LastExitCode }
+
+bazel build //long_command_line:long_command_line_wasm
+if (-not $?) { Exit $LastExitCode }
+
+bazel build //:hello-embind-wasm --compilation_mode dbg # debug
+if (-not $?) { Exit $LastExitCode }
+
+# Test use of the closure compiler
+bazel build //:hello-embind-wasm --compilation_mode opt # release
+if (-not $?) { Exit $LastExitCode }
+
+Set-Location ..\test_secondary_lto_cache
+
+bazel build //:hello-world-wasm
+if (-not $?) { Exit $LastExitCode }
+
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel.sh
new file mode 100755
index 0000000000..682866fd53
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+
+echo "test bazel"
+
+set -x
+set -e
+
+# Get the latest version number from emscripten-releases-tag.json.
+VER=$(scripts/get_release_info.py emscripten-releases-tags.json latest)
+
+# Based on the latest version number, get the commit hash for that version.
+HASH=$(scripts/get_release_info.py emscripten-releases-tags.json hash ${VER})
+
+FAILMSG="!!! scripts/update_bazel_workspace.py needs to be run !!!"
+
+# Ensure the WORKSPACE file is up to date with the latest version.
+grep ${VER} bazel/revisions.bzl || (echo ${FAILMSG} && false)
+grep ${HASH} bazel/revisions.bzl || (echo ${FAILMSG} && false)
+grep ${VER} bazel/MODULE.bazel || (echo ${FAILMSG} && false)
+
+cd bazel
+bazel build //hello-world:hello-world-wasm
+bazel build //hello-world:hello-world-wasm-simd
+
+cd test_external
+bazel build //:hello-world-wasm
+bazel build //long_command_line:long_command_line_wasm
+bazel build //:hello-embind-wasm --compilation_mode dbg # debug
+
+# Test use of the closure compiler
+bazel build //:hello-embind-wasm --compilation_mode opt # release
+# This function should not be minified if the externs file is loaded correctly.
+grep "customJSFunctionToTestClosure" bazel-bin/hello-embind-wasm/hello-embind.js
+
+cd ../test_secondary_lto_cache
+bazel build //:hello-world-wasm
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel_mac.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel_mac.sh
new file mode 100755
index 0000000000..e27c657daf
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_bazel_mac.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+echo "test bazel"
+
+set -x
+set -e
+
+# Get the latest version number from emscripten-releases-tag.json.
+VER=$(scripts/get_release_info.py emscripten-releases-tags.json latest)
+
+# Based on the latest version number, get the commit hash for that version.
+HASH=$(scripts/get_release_info.py emscripten-releases-tags.json hash ${VER})
+
+FAILMSG="!!! scripts/update_bazel_workspace.py needs to be run !!!"
+
+# Ensure the WORKSPACE file is up to date with the latest version.
+grep ${VER} bazel/revisions.bzl || (echo ${FAILMSG} && false)
+grep ${HASH} bazel/revisions.bzl || (echo ${FAILMSG} && false)
+grep ${VER} bazel/MODULE.bazel || (echo ${FAILMSG} && false)
+
+cd bazel
+bazel build //hello-world:hello-world-wasm
+bazel build //hello-world:hello-world-wasm-simd
+
+cd test_external
+bazel build //long_command_line:long_command_line_wasm
+bazel build //:hello-world-wasm
+
+cd ../test_secondary_lto_cache
+bazel build //:hello-world-wasm
+
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_node_path.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_node_path.sh
new file mode 100755
index 0000000000..582152b4b1
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_node_path.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+echo "Test that node is added to that PATH if, and only if, it is not one already present".
+
+if [ -n "$EMSDK" ]; then
+ echo "EMSDK is already defined in this shell. Run tests in a shell without sourcing emsdk_env.sh first"
+ exit 1
+fi
+
+DIR=$(dirname "$BASH_SOURCE")
+cd $DIR/..
+
+./emsdk install latest
+./emsdk activate latest
+
+if which node; then
+ echo "Test should be run without node in the path"
+ exit 1
+fi
+
+# Run emsdk_env.sh and confirm that node was added to the PATH
+. emsdk_env.sh
+
+if ! which node; then
+ echo "node not found in path after emsdk_env.sh"
+ exit 1
+fi
+
+# Run emsdk_env.sh again and confirm that node is still in the PATH
+. emsdk_env.sh
+
+if ! which node; then
+ echo "node not found in path after emsdk_env.sh"
+ exit 1
+fi
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_path_preservation.ps1 b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_path_preservation.ps1
new file mode 100644
index 0000000000..0391b63a32
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_path_preservation.ps1
@@ -0,0 +1,142 @@
+# This test installs emsdk and activates the latest toolchain using `--system` or `--permanent` flags,
+# and checks if parts of PATH are lost or overwritten. Set $env:SYSTEM_FLAG and $env:PERMANENT_FLAG to test each.
+# If no flag is provided the process/shell values are tested. See the CI file for an example.
+
+refreshenv
+
+$repo_root = [System.IO.Path]::GetDirectoryName((resolve-path "$PSScriptRoot"))
+
+$PATH_USER_BEFORE = [System.Environment]::GetEnvironmentVariable("PATH", "User")
+$PATH_MACHINE_BEFORE = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
+$PATH_Process_BEFORE = [System.Environment]::GetEnvironmentVariable("PATH", "Process")
+
+try {
+
+
+ & "$repo_root/emsdk.ps1" install latest
+
+ $esc = '--%'
+ & "$repo_root/emsdk.ps1" activate latest $esc $env:PERMANENT_FLAG $env:SYSTEM_FLAG
+
+ $PATH_USER = [System.Environment]::GetEnvironmentVariable("PATH", "User")
+ $PATH_MACHINE = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
+ $PATH_Process = [System.Environment]::GetEnvironmentVariable("PATH", "Process")
+
+ if ($env:SYSTEM_FLAG) {
+ echo "--system test............................."
+ $path_before_arr = $PATH_MACHINE_BEFORE.Split(';')
+ $path_arr = $PATH_MACHINE.Split(';')
+ }
+ elseif ($env:PERMANENT_FLAG) {
+ echo "--permanent test.........................."
+ $path_before_arr = $PATH_USER_BEFORE.Split(';')
+ $path_arr = $PATH_USER.Split(';')
+ } else {
+ echo "no flag test (shell/process).............."
+ $path_before_arr = $PATH_Process_BEFORE.Split(';')
+ $path_arr = $PATH_Process.Split(';')
+ }
+
+
+ $EMSDK_Path = $path_arr | Where-Object { $_ -like "$repo_root*" }
+ $EMSDK_NODE_Path = $path_arr | Where-Object { $_ -like "$repo_root\node*" }
+ $EMSDK_PYTHON_Path = $path_arr | Where-Object { $_ -like "$repo_root\python*" }
+ $EMSDK_JAVA_Path = $path_arr | Where-Object { $_ -like "$repo_root\java*" }
+ $EMSDK_UPSTREAM_Path = $path_arr | Where-Object { $_ -like "$repo_root\upstream\emscripten*" }
+
+ $number_of_items = $path_arr.count
+ [System.Collections.ArrayList]$rest_of_path = @()
+ Foreach ($item in $path_arr) {
+ if (
+ ($item -like "$repo_root*") -or
+ ($item -like "$repo_root\node*") -or
+ ($item -like "$repo_root\python*") -or
+ ($item -like "$repo_root\java*") -or
+ ($item -like "$repo_root\upstream\emscripten*")
+ ) {
+ echo "$item is on the PATH"
+ }
+ else {
+ $rest_of_path.add($item) | Out-Null
+ }
+ }
+
+ # compare the PATHs before activation and after activation
+ if (Compare-Object -ReferenceObject $path_before_arr -DifferenceObject $rest_of_path ) {
+ echo "Old path is ............................."
+ echo $path_before_arr
+ echo "Current rest of path is ................."
+ echo $rest_of_path
+ throw "some parts of PATH are removed"
+ }
+
+ # Compare the other untouched PATH
+ if ($env:SYSTEM_FLAG) {
+ if (Compare-Object -ReferenceObject $PATH_USER_BEFORE.Split(';') -DifferenceObject $PATH_USER.Split(';') ) {
+ echo "Old user path is ...................."
+ echo $PATH_USER_BEFORE
+ echo "Current user path is ................"
+ echo $PATH_USER
+ throw "User PATH are changed while --system had been provided"
+ }
+ }
+ elseif ($env:PERMANENT_FLAG) {
+ if (Compare-Object -ReferenceObject $PATH_MACHINE_BEFORE.Split(';') -DifferenceObject $PATH_MACHINE.Split(';') ) {
+ echo "Old machine path is.................."
+ echo $PATH_MACHINE_BEFORE
+ echo "Current machine path is.............."
+ echo $PATH_MACHINE
+ throw "MACHINE PATH are changed while --system was not provided"
+ }
+ } else {
+ if (
+ (Compare-Object -ReferenceObject $PATH_MACHINE_BEFORE.Split(';') -DifferenceObject $PATH_MACHINE.Split(';')) -or
+ (Compare-Object -ReferenceObject $PATH_MACHINE_BEFORE.Split(';') -DifferenceObject $PATH_MACHINE.Split(';'))
+ ) {
+ echo "Old machine path is.................."
+ echo $PATH_MACHINE_BEFORE
+ echo "Current machine path is.............."
+ echo $PATH_MACHINE
+ echo "Old user path is ...................."
+ echo $PATH_USER_BEFORE
+ echo "Current user path is ................"
+ echo $PATH_USER
+ throw "MACHINE/USER PATH are changed while no flag was provided"
+ }
+ }
+
+
+
+
+}
+finally {
+ # Recover pre-split PATH
+ refreshenv
+
+ [Environment]::SetEnvironmentVariable("Path", $PATH_USER_BEFORE, "User")
+ try {
+ [Environment]::SetEnvironmentVariable("Path", $PATH_MACHINE_BEFORE, "Machine")
+ }
+ catch {}
+
+ [Environment]::SetEnvironmentVariable("Path", $PATH_Process_BEFORE, "Process")
+
+ # Recover pre activation env variables
+ [Environment]::SetEnvironmentVariable("EMSDK", $null, "User")
+ [Environment]::SetEnvironmentVariable("EMSDK_NODE", $null, "User")
+ [Environment]::SetEnvironmentVariable("EMSDK_PYTHON", $null, "User")
+
+ try {
+ [Environment]::SetEnvironmentVariable("EMSDK", $null, "Machine")
+ [Environment]::SetEnvironmentVariable("EMSDK_NODE", $null, "Machine")
+ [Environment]::SetEnvironmentVariable("EMSDK_PYTHON", $null, "Machine")
+ } catch {}
+
+
+ [Environment]::SetEnvironmentVariable("EMSDK", $null, "Process")
+ [Environment]::SetEnvironmentVariable("EMSDK_NODE", $null, "Process")
+ [Environment]::SetEnvironmentVariable("EMSDK_PYTHON", $null, "Process")
+
+ refreshenv
+
+}
diff --git a/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_source_env.sh b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_source_env.sh
new file mode 100755
index 0000000000..71a3e4070a
--- /dev/null
+++ b/zig-pkg/N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ/test/test_source_env.sh
@@ -0,0 +1,132 @@
+#!/usr/bin/env bash
+
+echo "Test ability to source emsdk_env.sh in different shells"
+
+if [ -n "$EMSDK" ]; then
+ echo "EMSDK is already defined in this shell. Run tests in a shell without sourcing emsdk_env.sh first"
+ exit 1
+fi
+
+DIR=$(dirname "$BASH_SOURCE")
+
+# setup a symlink relative to the current dir
+REL_LINK_DIR="$DIR/tmp"
+if [ -d "$REL_LINK_DIR" ]; then
+ rm -rf "$REL_LINK_DIR"
+fi
+echo "Creating links in $REL_LINK_DIR"
+mkdir -p "$REL_LINK_DIR"
+(cd $DIR/.. && ln -s `pwd` "$REL_LINK_DIR/emsdk")
+(cd $DIR/.. && ln -s `pwd`/emsdk_env.sh "$REL_LINK_DIR")
+
+# setup a symlink in an absolute directory
+ABS_LINK_DIR="/tmp/emsdk_env_test"
+if [ -d "$ABS_LINK_DIR" ]; then
+ rm -rf "$ABS_LINK_DIR"
+fi
+echo "Creating links in $ABS_LINK_DIR"
+mkdir -p "$ABS_LINK_DIR"
+(cd $DIR/.. && ln -s `pwd` "$ABS_LINK_DIR/emsdk")
+(cd $DIR/.. && ln -s `pwd`/emsdk_env.sh "$ABS_LINK_DIR")
+
+PATH1="$DIR/../emsdk_env.sh"
+PATH2="$REL_LINK_DIR/emsdk/emsdk_env.sh"
+PATH3="$REL_LINK_DIR/emsdk_env.sh"
+PATH4="$ABS_LINK_DIR/emsdk/emsdk_env.sh"
+PATH5="$ABS_LINK_DIR/emsdk_env.sh"
+
+assert_emcc() {
+ current=$1
+ cmd=$2
+ value=$3
+ if [ -z "$value" ] || [ "$value" == "false" ]; then
+ echo "FAILED: $current"
+ echo " unable to get EMSDK in $current using '$cmd'"
+ else
+ echo "SUCCESS: $current testing $cmd"
+ echo " -> EMSDK = $value"
+ fi
+}
+
+test_bash() {
+ value=$(bash --rcfile <(echo $1))
+ assert_emcc bash "$1" "$value"
+}
+
+test_zsh() {
+ value=$(zsh -d -c "$1")
+ assert_emcc zsh "$1" "$value"
+}
+
+test_ksh() {
+ value=$(ksh -c "$1")
+ assert_emcc ksh "$1" "$value"
+}
+
+it_tests_direct_path() {
+ TEST_SCRIPT=". ${PATH1}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+ TEST_SCRIPT="source ${PATH1}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+}
+
+it_tests_via_relative_dir_symlink() {
+ TEST_SCRIPT=". ${PATH2}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+ TEST_SCRIPT="source ${PATH2}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+}
+
+it_tests_via_relative_file_symlink() {
+ TEST_SCRIPT=". ${PATH3}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+ TEST_SCRIPT="source ${PATH3}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+}
+
+it_tests_via_absolute_dir_symlink() {
+ TEST_SCRIPT=". ${PATH4}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+ TEST_SCRIPT="source ${PATH4}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+}
+
+it_tests_via_absolute_file_symlink() {
+ TEST_SCRIPT=". ${PATH5}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+ TEST_SCRIPT="source ${PATH5}"' >/dev/null 2>&1; if [ -n "$EMSDK" ]; then echo "$EMSDK"; else echo false; fi ; exit'
+ test_bash "$TEST_SCRIPT"
+ test_zsh "$TEST_SCRIPT"
+ test_ksh "$TEST_SCRIPT"
+}
+
+run_bash_tests() {
+ it_tests_direct_path
+ it_tests_via_relative_dir_symlink
+ it_tests_via_relative_file_symlink
+ it_tests_via_absolute_dir_symlink
+ it_tests_via_absolute_file_symlink
+}
+
+run_bash_tests
+
+rm -rf $REL_LINK_DIR
+rm -rf $ABS_LINK_DIR
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.gitattributes b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.gitattributes
new file mode 100644
index 0000000000..15a5c58091
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.gitattributes
@@ -0,0 +1 @@
+*.h linguist-language=C
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.github/FUNDING.yml b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.github/FUNDING.yml
new file mode 100644
index 0000000000..d7775fe838
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: raysan5
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.gitignore b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.gitignore
new file mode 100644
index 0000000000..18c01c5a17
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/.gitignore
@@ -0,0 +1,64 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+
+# VSCode files
+.vscode/
+
+
+# Ignore files build by Visual Studio
+[Dd]ebug
+[Rr]elease
+*.vs
+*.obj
+*.pdb
+*.aps
+*.user
+# *.vcproj
+# *.vcxproj*
+# *.sln
+*.vspscc
+*_i.c
+*.i
+*.icf
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.cache
+*.ilk
+*.log
+
+build
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/LICENSE b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/LICENSE
new file mode 100644
index 0000000000..f5f14b2d9b
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/LICENSE
@@ -0,0 +1,18 @@
+zlib License
+
+Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
+
+This software is provided "as-is", without any express or implied warranty. In no event
+will the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not claim that you
+ wrote the original software. If you use this software in a product, an acknowledgment
+ in the product documentation would be appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+ as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/Makefile b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/Makefile
new file mode 100644
index 0000000000..c282701588
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/Makefile
@@ -0,0 +1,402 @@
+#**************************************************************************************************
+#
+# raylib makefile for Desktop platform and HTML5
+#
+# Copyright (c) 2019 Ramon Santamaria (@raysan5)
+#
+# This software is provided "as-is", without any express or implied warranty. In no event
+# will the authors be held liable for any damages arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose, including commercial
+# applications, and to alter it and redistribute it freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not claim that you
+# wrote the original software. If you use this software in a product, an acknowledgment
+# in the product documentation would be appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+# as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+#
+#**************************************************************************************************
+
+.PHONY: all clean
+
+# Define required raylib variables
+RAYLIB_PATH ?= ../../raylib
+RAYGUI_PATH ?= ../src
+
+# Define default options
+
+# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+PLATFORM ?= PLATFORM_DESKTOP
+
+# Locations of your newly installed library and associated headers. See ../src/Makefile
+# On Linux, if you have installed raylib but cannot compile the examples, check that
+# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations.
+# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED.
+# To enable compile-time linking to a special version of libraylib.so, change these variables here.
+# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below.
+# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime,
+# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH.
+# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths.
+DESTDIR ?= /usr/local
+RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib
+# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files.
+RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include
+
+# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
+RAYLIB_LIBTYPE ?= STATIC
+
+# Build mode for project: DEBUG or RELEASE
+BUILD_MODE ?= RELEASE
+
+# Use external GLFW library instead of rglfw module
+# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3
+USE_EXTERNAL_GLFW ?= FALSE
+
+# Use Wayland display server protocol on Linux desktop
+# by default it uses X11 windowing system
+USE_WAYLAND_DISPLAY ?= FALSE
+
+# Determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
+ # ifeq ($(UNAME),Msys) -> Windows
+ ifeq ($(OS),Windows_NT)
+ PLATFORM_OS=WINDOWS
+ else
+ UNAMEOS=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ endif
+ ifeq ($(UNAMEOS),FreeBSD)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),OpenBSD)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),NetBSD)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),DragonFly)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),Darwin)
+ PLATFORM_OS=OSX
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ UNAMEOS=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ endif
+endif
+
+# RAYLIB_PATH adjustment for different platforms.
+# If using GNU make, we can get the full path to the top of the tree. Windows? BSD?
+# Required for ldconfig or other tools that do not perform path expansion.
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ RAYLIB_PREFIX ?= ..
+ RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX))
+ endif
+endif
+# Default path for raylib on Raspberry Pi, if installed in different path, update it!
+# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki.
+# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX.
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ RAYLIB_PATH ?= /home/pi/raylib
+endif
+
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # Emscripten required variables
+ EMSDK_PATH ?= C:/raylib/emsdk
+ EMSCRIPTEN_VERSION ?= 1.38.32
+ CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit
+ PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64
+ NODE_VERSION = 8.9.1_64bit
+ export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH)
+ EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION)
+endif
+
+# Define raylib release directory for compiled library.
+# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version
+RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src
+
+# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries
+# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH
+# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux
+# without formal installation from ../src/Makefile. It aids portability and is useful if you have
+# multiple versions of raylib, have raylib installed to a non-standard location, or want to
+# bundle libraylib.so with your game. Change it to your liking.
+# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH,
+# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH,
+# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
+# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute.
+# To see which libraries a built example is linking to, ldd core/core_basic_window;
+# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing.
+EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH)
+
+# Define default C compiler: gcc
+# NOTE: define g++ compiler if using C++
+CC = gcc
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),OSX)
+ # OSX default compiler
+ CC = clang
+ endif
+ ifeq ($(PLATFORM_OS),BSD)
+ # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
+ CC = clang
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
+ # Define RPI cross-compiler
+ #CC = armv6j-hardfloat-linux-gnueabi-gcc
+ CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # HTML5 emscripten compiler
+ # WARNING: To compile to HTML5, code must be redesigned
+ # to use emscripten.h and emscripten_set_main_loop()
+ CC = emcc
+endif
+
+# Define default make program: Mingw32-make
+MAKE = mingw32-make
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ MAKE = make
+ endif
+endif
+
+# Define compiler flags:
+# -O1 defines optimization level
+# -g include debug information on compilation
+# -s strip unnecessary data from build
+# -Wall turns on most, but not all, compiler warnings
+# -std=c99 defines C language mode (standard C from 1999 revision)
+# -std=gnu99 defines C language mode (GNU C from 1999 revision)
+# -Wno-missing-braces ignore invalid warning (GCC bug 53119)
+# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
+CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces
+
+ifeq ($(BUILD_MODE),DEBUG)
+ CFLAGS += -g
+endif
+ifeq ($(RAYLIB_BUILD_MODE),RELEASE)
+ CFLAGS += -O1 -s
+endif
+
+# Additional flags for compiler (if desired)
+#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),WINDOWS)
+ # resource file contains windows executable icon and properties
+ # -Wl,--subsystem,windows hides the console window
+ CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ ifeq ($(RAYLIB_LIBTYPE),STATIC)
+ CFLAGS += -D_DEFAULT_SOURCE
+ endif
+ ifeq ($(RAYLIB_LIBTYPE),SHARED)
+ # Explicitly enable runtime link to libraylib.so
+ CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ CFLAGS += -std=gnu99
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # -Os # size optimization
+ # -O2 # optimization level 2, if used, also set --memory-init-file 0
+ # -sUSE_GLFW=3 # Use glfw3 library (context/input management)
+ # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
+ # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB)
+ # -sUSE_PTHREADS=1 # multithreading support
+ # -sWASM=0 # disable Web Assembly, emitted by default
+ # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS
+ # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data
+ # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
+ # -sMINIFY_HTML=0 # minify generated html from shell.html
+ # --profiling # include information for code profiling
+ # --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
+ # --preload-file resources # specify a resources folder for data compilation
+ # --source-map-base # allow debugging in browser with source map
+ # --shell-file shell.html # define a custom shell .html and output extension
+ CFLAGS += -Os -sUSE_GLFW=3 -sFORCE_FILESYSTEM=1 -sASYNCIFY --preload-file $(dir $<)resources@resources -sMINIFY_HTML=0
+ ifeq ($(BUILD_MODE), DEBUG)
+ CFLAGS += -sASSERTIONS=1 --profiling
+ endif
+ # NOTE: Simple raylib examples are compiled to be interpreter by emterpreter, that way,
+ # we can compile same code for ALL platforms with no change required, but, working on bigger
+ # projects, code needs to be refactored to avoid a blocking while() loop, moving Update and Draw
+ # logic to a self contained function: UpdateDrawFrame(), check core_basic_window_web.c for reference.
+
+ # Define a custom shell .html and output extension
+ CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
+ EXT = .html
+endif
+
+# Define include paths for required headers
+# NOTE: Several external required libraries (stb and others)
+INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external -I$(RAYGUI_PATH)
+
+# Define additional directories containing required header files
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # RPI required libraries
+ INCLUDE_PATHS += -I/opt/vc/include
+ INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux
+ INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),BSD)
+ # Consider -L$(RAYLIB_H_INSTALL_PATH)
+ INCLUDE_PATHS += -I/usr/local/include
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ # Reset everything.
+ # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include
+ INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external
+ endif
+endif
+
+# Define library paths containing required libs.
+LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),BSD)
+ # Consider -L$(RAYLIB_INSTALL_PATH)
+ LDFLAGS += -L. -Lsrc -L/usr/local/lib
+ ifeq ($(shell uname),OpenBSD)
+ LDFLAGS += -L/usr/X11R6/lib
+ endif
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ # Reset everything.
+ # Precedence: immediately local, installed version, raysan5 provided libs
+ LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH)
+ endif
+endif
+
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ LDFLAGS += -L/opt/vc/lib
+endif
+
+# Define any libraries required on linking
+# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),WINDOWS)
+ # Libraries for Windows desktop compilation
+ # NOTE: WinMM library required to set high-res timer resolution
+ LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm
+ # Required for physac examples
+ LDLIBS += -static -lpthread
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ # Libraries for Debian GNU/Linux desktop compiling
+ # NOTE: Required packages: libegl1-mesa-dev
+ LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
+
+ # On X11 requires also below libraries
+ LDLIBS += -lX11
+ # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
+ #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+
+ # On Wayland windowing system, additional libraries requires
+ ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
+ LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
+ endif
+ # Explicit link to libc
+ ifeq ($(RAYLIB_LIBTYPE),SHARED)
+ LDLIBS += -lc
+ endif
+ endif
+ ifeq ($(PLATFORM_OS),OSX)
+ # Libraries for OSX 10.9 desktop compiling
+ # NOTE: Required packages: libopenal-dev libegl1-mesa-dev
+ LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
+ endif
+ ifeq ($(PLATFORM_OS),BSD)
+ # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
+ # NOTE: Required packages: mesa-libs
+ LDLIBS = -lraylib -lGL -lpthread -lm
+
+ # On XWindow requires also below libraries
+ LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+ endif
+ ifeq ($(USE_EXTERNAL_GLFW),TRUE)
+ # NOTE: It could require additional packages installed: libglfw3-dev
+ LDLIBS += -lglfw
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # Libraries for Raspberry Pi compiling
+ # NOTE: Required packages: libasound2-dev (ALSA)
+ LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -ldrm -lgbm -ldl
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # Libraries for web (HTML5) compiling
+ LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc
+endif
+
+# Define all source files required
+EXAMPLES = \
+ controls_test_suite/controls_test_suite \
+ custom_file_dialog/custom_file_dialog \
+ custom_input_box/custom_input_box\
+ image_exporter/image_exporter \
+ image_importer_raw/image_importer_raw \
+ property_list/property_list \
+ portable_window/portable_window \
+ scroll_panel/scroll_panel \
+ style_selector/style_selector \
+ custom_sliders/custom_sliders \
+ animation_curve/animation_curve \
+ floating_window/floating_window \
+
+CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST))
+
+# Default target entry
+all: $(EXAMPLES)
+
+# Generic compilation pattern
+# NOTE: Examples must be ready for Android compilation!
+%: %.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
+# Clean everything
+clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),WINDOWS)
+ del *.o *.exe /s
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ rm -f $(EXAMPLES)
+ endif
+ ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -delete
+ rm -f *.o
+ endif
+ ifeq ($(shell uname),OpenBSD)
+ find . -type f -perm 0755 -delete
+ rm -f *.o
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ find . -type f -executable -delete
+ rm -fv *.o
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ del *.o *.html *.js
+endif
+ @echo Cleaning done
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/animation_curve/animation_curve.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/animation_curve/animation_curve.c
new file mode 100644
index 0000000000..2f9b2f04c7
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/animation_curve/animation_curve.c
@@ -0,0 +1,477 @@
+/*******************************************************************************************
+*
+* Animation curves - An example demo for animation curves
+*
+* DEPENDENCIES:
+* raylib 4.0 - Windowing/input management and drawing.
+* raygui 3.0 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2023 Pierre Jaffuer (@smallcluster)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+// raygui embedded styles
+#include "../styles/style_cyber.h" // raygui style: cyber
+#include "../styles/style_jungle.h" // raygui style: jungle
+#include "../styles/style_lavanda.h" // raygui style: lavanda
+#include "../styles/style_dark.h" // raygui style: dark
+#include "../styles/style_bluish.h" // raygui style: bluish
+#include "../styles/style_terminal.h" // raygui style: terminal
+
+#undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again
+
+#define GUI_CURVE_EDITOR_IMPLEMENTATION
+#include "gui_curve_editor.h"
+
+//------------------------------------------------------------------------------------
+// Helper function
+//------------------------------------------------------------------------------------
+void LoadCurveDefaults(GuiCurveEditorState curves[]);
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 540;
+
+ InitWindow(screenWidth, screenHeight, "raygui - animation curves");
+ SetTargetFPS(60);
+
+ // Gui style
+ GuiLoadStyleDefault();
+ int visualStyleActive = 0;
+ int prevVisualStyleActive = 0;
+
+ float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
+ const float margin = 8;
+
+ // Gui states
+ Vector2 scrollOffset = (Vector2){ 0, 0 };
+ Rectangle contentRect = (Rectangle){ 0, 0, 0, 0 };
+ bool moveSlider = false;
+ bool sectionActive[5] = { 0 };
+ sectionActive[0] = true;
+ const char *sectionNames[5] = { "X Position", "Y Position", "Width", "Height", "Rotation" };
+ bool editValueBox[5][4] = { 0 };
+ char *valTextBox[5][4][20] = { 0 };
+ bool playAnimation = true;
+ bool showHelp = true;
+
+ Rectangle settingsRect = (Rectangle){ screenWidth - screenWidth/3, 0, screenWidth/3, screenHeight };
+
+ // Animation curves
+ // 0 -> Ball X position
+ // 1 -> Ball Y position
+ // 2 -> Ball Width
+ // 3 -> Ball Height
+ // 4 -> Ball rotation
+ GuiCurveEditorState curves[5] = { 0 };
+ LoadCurveDefaults(curves);
+
+ // Animation time
+ float time = 0.0f;
+ float animationTime = 4.0f;
+
+ //SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ if (playAnimation) time += GetFrameTime();
+
+ // Reset timer
+ if (time > animationTime) time = 0;
+
+ // Ball animation
+ const float t = time/animationTime;
+ Vector2 ballPos = (Vector2){ GuiCurveEval(&curves[0], t), GuiCurveEval(&curves[1], t) };
+ Vector2 ballSize = (Vector2){ GuiCurveEval(&curves[2], t), GuiCurveEval(&curves[3], t) };
+ float ballRotation = GuiCurveEval(&curves[4], t);
+
+ // Update style
+ if (visualStyleActive != prevVisualStyleActive)
+ {
+ switch (visualStyleActive)
+ {
+ case 0: GuiLoadStyleDefault(); break;
+ case 1: GuiLoadStyleJungle(); break;
+ case 2: GuiLoadStyleLavanda(); break;
+ case 3: GuiLoadStyleDark(); break;
+ case 4: GuiLoadStyleBluish(); break;
+ case 5: GuiLoadStyleCyber(); break;
+ case 6: GuiLoadStyleTerminal(); break;
+ default: break;
+ }
+
+ fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
+ prevVisualStyleActive = visualStyleActive;
+ }
+
+ // Update settings panel rect
+ Rectangle sliderRect = (Rectangle){ settingsRect.x - 4, settingsRect.y, 4, settingsRect.height };
+ if (CheckCollisionPointRec(GetMousePosition(), sliderRect) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) moveSlider = true;
+ if (IsMouseButtonUp(MOUSE_BUTTON_LEFT)) moveSlider = false;
+
+ if (moveSlider)
+ {
+ settingsRect.x = GetMouseX();
+
+ // Minimum-Maximum size
+ if (settingsRect.x > (screenWidth - 4)) settingsRect.x = screenWidth - 4;
+ else if (settingsRect.x < 4) settingsRect.x = 4;
+
+ settingsRect.width = screenWidth - settingsRect.x;
+ }
+
+
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+ ClearBackground(GetColor( GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ // Scene
+ //----------------------------------------------------------------------------------
+ DrawRectangle(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end, BLUE); // Sky
+
+ DrawRectangle(curves[0].start, curves[1].start, curves[0].end-curves[0].start, 32, DARKGREEN); // Ground
+
+ BeginScissorMode(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end+32);
+
+ DrawRectanglePro((Rectangle){ballPos.x, ballPos.y, ballSize.x, ballSize.y}, (Vector2){ballSize.x/2.f,ballSize.y/2.f}, ballRotation, PINK); // Ball
+
+ DrawLine(ballPos.x, ballPos.y, ballPos.x + cosf(ballRotation*DEG2RAD)*ballSize.x, ballPos.y +sinf(ballRotation*DEG2RAD)*ballSize.y, RED);
+ DrawLine(ballPos.x, ballPos.y, ballPos.x + cosf((ballRotation+90)*DEG2RAD)*ballSize.x, ballPos.y +sinf((ballRotation+90)*DEG2RAD)*ballSize.y, GREEN);
+
+ EndScissorMode();
+
+ // Bounds
+ DrawRectangleLines(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end+32, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)));
+ //----------------------------------------------------------------------------------
+
+ // GUI
+ //----------------------------------------------------------------------------------
+ if (showHelp)
+ {
+ if (GuiWindowBox((Rectangle) {margin, margin, settingsRect.x-2*margin, curves[1].end-2*margin}, "help")) showHelp = false;
+
+ Rectangle helpTextRect = (Rectangle) { 2*margin, 2*margin+RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.x - 4 - 4*margin, 0 };
+ GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "Curve widget controls:");
+ helpTextRect.height += fontSize+margin;
+ GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- Left click to move/add point or move tangents");
+ helpTextRect.height += fontSize+margin/2;
+ GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- While moving a tangent, hold SHIFT to disable tangent symetry");
+ helpTextRect.height += fontSize+margin/2;
+ GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- Right click to remove a point");
+ helpTextRect.height += fontSize+margin/2;
+ DrawRectangleGradientV(margin, margin+curves[1].end - 2*margin, settingsRect.x - 2*margin, 12, (Color){ 0,0,0,100 }, BLANK);
+ }
+
+ // Settings panel
+ GuiScrollPanel(settingsRect, "Settings", contentRect, &scrollOffset, NULL);
+
+ BeginScissorMode(settingsRect.x, settingsRect.y+RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.width, settingsRect.height);
+
+ // Rebuild the content Rect
+ contentRect = (Rectangle){ settingsRect.x + margin, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT+margin, settingsRect.width - 2*margin - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), 0 };
+
+ // Help button
+ if (GuiButton((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, 1.5*fontSize }, GuiIconText(showHelp? ICON_EYE_ON : ICON_EYE_OFF, "Curve controls help"))) showHelp = !showHelp;
+
+ contentRect.height += 1.5*fontSize + margin;
+
+ // Animation Time slider
+ GuiSlider((Rectangle){ contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width/2, fontSize }, NULL, TextFormat("Animation Time: %.2fs", animationTime), &animationTime, 1, 8);
+ contentRect.height += fontSize + margin;
+
+ // Load default curves
+ if (GuiButton((Rectangle){ contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width, 1.5*fontSize }, "Load default"))
+ {
+ LoadCurveDefaults(curves);
+ animationTime = 4.0f;
+ time = 0.0f;
+ }
+ contentRect.height += 1.5f*fontSize + margin;
+
+ // Styles
+ GuiLabel((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, fontSize }, "Style:");
+ contentRect.height += fontSize;
+ GuiComboBox((Rectangle){contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width, 1.5*fontSize }, "default;Jungle;Lavanda;Dark;Bluish;Cyber;Terminal", &visualStyleActive);
+ contentRect.height += 1.5f*fontSize + margin;
+
+ // Draw curves with their controls
+ //----------------------------------------------------------------------------------
+ for (int i = 0; i < 5; i++)
+ {
+ // Collapsing section
+ Rectangle headerRect = (Rectangle){ contentRect.x, contentRect.y + contentRect.height+scrollOffset.y, contentRect.width, 1.5f*fontSize };
+ GuiStatusBar(headerRect, NULL);
+
+ if (GuiLabelButton(headerRect, GuiIconText(sectionActive[i] ? ICON_ARROW_DOWN_FILL : ICON_ARROW_RIGHT_FILL, sectionNames[i]))) sectionActive[i] = !sectionActive[i];
+
+ contentRect.height += 1.5f*fontSize + margin;
+
+ // Skip this section
+ if (!sectionActive[i]) continue;
+
+ // Draw curve control
+ Rectangle curveRect = (Rectangle){ contentRect.x, contentRect.y+contentRect.height + scrollOffset.y, contentRect.width, fontSize*12 };
+ EndScissorMode(); // Stop clipping from setting rect
+
+ // Curves can leaks from control boundary... scissor it !
+ BeginScissorMode(curveRect.x, curveRect.y, curveRect.width, curveRect.height);
+ GuiCurveEditor(&curves[i], curveRect);
+ EndScissorMode();
+
+ // Resume clipping from setting rect
+ BeginScissorMode(settingsRect.x, settingsRect.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.width, settingsRect.height);
+ contentRect.height += fontSize*12 + margin;
+
+ // Draw selected point controls
+ GuiCurveEditorPoint *p = &(curves[i].points[curves[i].selectedIndex]);
+ GuiCheckBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Left Linear", &p->leftLinear);
+ GuiCheckBox((Rectangle){ contentRect.x+contentRect.width/2, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Right Linear", &p->rightLinear);
+ contentRect.height += 1.5f*fontSize + margin;
+
+ // Positions
+ GuiLabel((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, fontSize }, "Position");
+ contentRect.height += fontSize;
+
+ if (!editValueBox[i][0]) gcvt(p->position.x, 6, (char *)valTextBox[i][0]); // Transform x position to string
+
+ if (!editValueBox[i][1]) gcvt(curves[i].start + (curves[i].end-curves[i].start)*p->position.y, 6, (char *)valTextBox[i][1]); // Transform y position to string
+
+ // X pos
+ if (GuiTextBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2-margin, 1.5f*fontSize }, (char *)valTextBox[i][0], 20, editValueBox[i][0]))
+ {
+ editValueBox[i][0] = !editValueBox[i][0];
+
+ // Input ended
+ if (!editValueBox[i][0])
+ {
+ // Try to convert text to float and assign it to the point
+ char *endPtr = NULL;
+ double value = strtod((char *)valTextBox[i][0], &endPtr);
+
+ if (endPtr != (char *)valTextBox[i][0]) p->position.x = (value < 0)? 0 : (value > 1)? 1 : value;
+ }
+ }
+
+ // Y pos
+ if (GuiTextBox((Rectangle){ contentRect.x + contentRect.width/2, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2.0f, 1.5f*fontSize }, (char *)valTextBox[i][1], 20, editValueBox[i][1]))
+ {
+ editValueBox[i][1] = !editValueBox[i][1];
+
+ // Input ended
+ if (!editValueBox[i][1])
+ {
+ // Try to convert text to float and assign it to the point
+ char *endPtr = NULL;
+ double value = strtod((char *)valTextBox[i][1], &endPtr);
+
+ if (endPtr != (char *)valTextBox[i][1])
+ {
+ float normalizedVal = (value - curves[i].start)/(curves[i].end - curves[i].start);
+ p->position.y = (normalizedVal < 0)? 0 : (normalizedVal > 1)? 1 : normalizedVal;
+ }
+ }
+
+ }
+
+ contentRect.height += 1.5f*fontSize + margin;
+
+ // Tangents
+ GuiLabel((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, fontSize }, "Tangents");
+ contentRect.height += fontSize;
+
+ if (!editValueBox[i][2]) gcvt(p->tangents.x, 6, (char *)valTextBox[i][2]); // Transform left tangent to string
+
+ if (!editValueBox[i][3]) gcvt(p->tangents.y, 6, (char *)valTextBox[i][3]); // Transform right tangent to string
+
+ // Left tan
+ if (GuiTextBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2 - margin, 1.5f*fontSize }, (char *)valTextBox[i][2], 20, editValueBox[i][2]))
+ {
+ editValueBox[i][2] = !editValueBox[i][2];
+
+ // Input ended
+ if (!editValueBox[i][2])
+ {
+ // Try to convert text to float and assign it to the point
+ char *endPtr = NULL;
+ double value = strtod((char *)valTextBox[i][2], &endPtr);
+ if (endPtr != (char *)valTextBox[i][2]) p->tangents.x = value;
+ }
+ }
+
+ // Right tan
+ if (GuiTextBox((Rectangle){ contentRect.x + contentRect.width/2.0f, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2.0f, 1.5f*fontSize }, (char *)valTextBox[i][3], 20, editValueBox[i][3]))
+ {
+ editValueBox[i][3] = !editValueBox[i][3];
+
+ // Input ended
+ if (!editValueBox[i][3])
+ {
+ // Try to convert text to float and assign it to the point
+ char *endPtr = NULL;
+ double value = strtod((char *)valTextBox[i][3], &endPtr);
+ if (endPtr != (char *)valTextBox[i][3]) p->tangents.y = value;
+ }
+ }
+
+ contentRect.height += 1.5*fontSize + margin;
+ }
+
+ contentRect.height += margin;
+
+ EndScissorMode();
+
+ // Settings panel shadow
+ DrawRectangleGradientH(settingsRect.x - 12, 0, 12, settingsRect.height, BLANK, (Color){ 0, 0, 0, 100 });
+
+ // Slider
+ if (moveSlider) DrawRectangle(sliderRect.x, sliderRect.y, sliderRect.width, sliderRect.height, GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED)));
+ else if(CheckCollisionPointRec(GetMousePosition(), sliderRect)) DrawRectangle(sliderRect.x, sliderRect.y, sliderRect.width, sliderRect.height, GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED)));
+
+ // Draw Time controls
+ //----------------------------------------------------------------------------------
+ Rectangle timeLineRect = (Rectangle){ 0, screenHeight-4*fontSize, settingsRect.x, 4*fontSize };
+ GuiPanel((Rectangle){ timeLineRect.x, timeLineRect.y, timeLineRect.width, 2*fontSize }, NULL);
+ GuiLabel((Rectangle){ timeLineRect.x, timeLineRect.y, timeLineRect.width, 2*fontSize }, TextFormat("Normalized Time: %.3f", time/animationTime));
+ if (GuiButton((Rectangle){ timeLineRect.x+timeLineRect.width/2 - 2*fontSize - margin/4, timeLineRect.y, 2*fontSize, 2*fontSize }, GuiIconText((playAnimation? ICON_PLAYER_PAUSE : ICON_PLAYER_PLAY), ""))) playAnimation = !playAnimation;
+
+ if (GuiButton((Rectangle){ timeLineRect.x+timeLineRect.width/2 + margin/4, timeLineRect.y, 2*fontSize, 2*fontSize }, GuiIconText(ICON_PLAYER_STOP, "")))
+ {
+ playAnimation = false;
+ time = 0;
+ }
+
+ float animTime = time/animationTime;
+ GuiSlider((Rectangle){timeLineRect.x, timeLineRect.y + 2*fontSize, timeLineRect.width, timeLineRect.height - 2*fontSize }, NULL, NULL, &animTime, 0, 1);
+ time = animationTime*animTime;
+
+ // Time panel shadow
+ DrawRectangleGradientV(timeLineRect.x, timeLineRect.y - 12, timeLineRect.width, 12, BLANK, (Color){ 0, 0, 0, 100 });
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+void LoadCurveDefaults(GuiCurveEditorState curves[])
+{
+ // X pos
+ curves[0].start = 28;
+ curves[0].end = 506;
+ curves[0].numPoints = 4;
+ curves[0].selectedIndex = 0;
+ curves[0].editLeftTangent = false;
+ curves[0].editRightTangent = false;
+ curves[0].points[0].position =(Vector2) {0.000000, 0.000000}; curves[0].points[0].tangents = (Vector2) {0.000000, 1.515101}; curves[0].points[0].leftLinear = 1;curves[0].points[0].rightLinear = 1;
+ curves[0].points[1].position =(Vector2) {0.422414, 0.640000}; curves[0].points[1].tangents = (Vector2) {-2.824348, -4.494999};curves[0].points[1].leftLinear = 0;curves[0].points[1].rightLinear = 0;
+ curves[0].points[2].position =(Vector2) {0.732759, 0.210000}; curves[0].points[2].tangents = (Vector2) {0.000000, 2.956133}; curves[0].points[2].leftLinear = 0;curves[0].points[2].rightLinear = 1;
+ curves[0].points[3].position =(Vector2) {1.000000, 1.000000}; curves[0].points[3].tangents = (Vector2) {2.956133, 0.000000}; curves[0].points[3].leftLinear = 1;curves[0].points[3].rightLinear = 1;
+
+ // Y pos
+ curves[1].start = 405;
+ curves[1].end = 135;
+ curves[1].numPoints = 7;
+ curves[1].selectedIndex = 0;
+ curves[1].editLeftTangent = false;
+ curves[1].editRightTangent = false;
+ curves[1].points[0].position = (Vector2) {0.000000, 1.000000};curves[1].points[0].tangents = (Vector2) { 0.000000 , 0.000000};curves[1].points[0].leftLinear = 0;curves[1].points[0].rightLinear = 0;
+ curves[1].points[1].position = (Vector2) {0.140000, 0.000000};curves[1].points[1].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[1].leftLinear = 0;curves[1].points[1].rightLinear = 0;
+ curves[1].points[2].position = (Vector2) {0.450000, 0.000000};curves[1].points[2].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[2].leftLinear = 0;curves[1].points[2].rightLinear = 0;
+ curves[1].points[3].position = (Vector2) {0.670000, 0.000000};curves[1].points[3].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[3].leftLinear = 0;curves[1].points[3].rightLinear = 0;
+ curves[1].points[4].position = (Vector2) {0.830000, 0.000000};curves[1].points[4].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[4].leftLinear = 0;curves[1].points[4].rightLinear = 0;
+ curves[1].points[5].position = (Vector2) {0.940000, 0.000000};curves[1].points[5].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[5].leftLinear = 0;curves[1].points[5].rightLinear = 0;
+ curves[1].points[6].position = (Vector2) {1.000000, 0.000000};curves[1].points[6].tangents = (Vector2) {-10.000000 , 0.000000};curves[1].points[6].leftLinear = 0;curves[1].points[6].rightLinear = 0;
+
+ // X size
+ curves[2].start = 1;
+ curves[2].end = 64;
+ curves[2].numPoints = 16;
+ curves[2].selectedIndex = 0;
+ curves[2].editLeftTangent = false;
+ curves[2].editRightTangent = false;
+ curves[2].points[0].position = (Vector2) {0.000000, 0.492063}; curves[2].points[0].tangents = (Vector2) {0,0}; curves[2].points[0].leftLinear = 0; curves[2].points[0].rightLinear = 0;
+ curves[2].points[1].position = (Vector2) {0.130000, 0.492063}; curves[2].points[1].tangents = (Vector2) {0,0}; curves[2].points[1].leftLinear = 0; curves[2].points[1].rightLinear = 0;
+ curves[2].points[2].position = (Vector2) {0.140000, 0.746032}; curves[2].points[2].tangents = (Vector2) {0,0}; curves[2].points[2].leftLinear = 0; curves[2].points[2].rightLinear = 0;
+ curves[2].points[3].position = (Vector2) {0.150000, 0.492063}; curves[2].points[3].tangents = (Vector2) {0,0}; curves[2].points[3].leftLinear = 0; curves[2].points[3].rightLinear = 0;
+ curves[2].points[4].position = (Vector2) {0.440000, 0.490000}; curves[2].points[4].tangents = (Vector2) {0,0}; curves[2].points[4].leftLinear = 0; curves[2].points[4].rightLinear = 0;
+ curves[2].points[5].position = (Vector2) {0.450000, 0.682540}; curves[2].points[5].tangents = (Vector2) {0,0}; curves[2].points[5].leftLinear = 0; curves[2].points[5].rightLinear = 0;
+ curves[2].points[6].position = (Vector2) {0.460000, 0.480000}; curves[2].points[6].tangents = (Vector2) {0,0}; curves[2].points[6].leftLinear = 0; curves[2].points[6].rightLinear = 0;
+ curves[2].points[7].position = (Vector2) {0.660000, 0.492063}; curves[2].points[7].tangents = (Vector2) {0,0}; curves[2].points[7].leftLinear = 0; curves[2].points[7].rightLinear = 0;
+ curves[2].points[8].position = (Vector2) {0.670000, 0.619048}; curves[2].points[8].tangents = (Vector2) {0,0}; curves[2].points[8].leftLinear = 0; curves[2].points[8].rightLinear = 0;
+ curves[2].points[9].position = (Vector2) {0.680000, 0.492063}; curves[2].points[9].tangents = (Vector2) {0,0}; curves[2].points[9].leftLinear = 0; curves[2].points[9].rightLinear = 0;
+ curves[2].points[10].position = (Vector2) {0.820000, 0.492063}; curves[2].points[10].tangents = (Vector2) {0,0}; curves[2].points[10].leftLinear = 0; curves[2].points[10].rightLinear = 0;
+ curves[2].points[11].position = (Vector2) {0.830000, 0.619048}; curves[2].points[11].tangents = (Vector2) {0,0}; curves[2].points[11].leftLinear = 0; curves[2].points[11].rightLinear = 0;
+ curves[2].points[12].position = (Vector2) {0.840000, 0.492063}; curves[2].points[12].tangents = (Vector2) {0,0}; curves[2].points[12].leftLinear = 0; curves[2].points[12].rightLinear = 0;
+ curves[2].points[13].position = (Vector2) {0.930000, 0.492063}; curves[2].points[13].tangents = (Vector2) {0,0}; curves[2].points[13].leftLinear = 0; curves[2].points[13].rightLinear = 0;
+ curves[2].points[14].position = (Vector2) {0.940000, 0.619048}; curves[2].points[14].tangents = (Vector2) {0,0}; curves[2].points[14].leftLinear = 0; curves[2].points[14].rightLinear = 0;
+ curves[2].points[15].position = (Vector2) {0.950000, 0.492063}; curves[2].points[15].tangents = (Vector2) {0,0}; curves[2].points[15].leftLinear = 0; curves[2].points[15].rightLinear = 0;
+
+ // Y Size
+ curves[3].start = 1;
+ curves[3].end = 64;
+ curves[3].numPoints = 16;
+ curves[3].selectedIndex = 0;
+ curves[3].editLeftTangent = false;
+ curves[3].editRightTangent = false;
+ curves[3].points[0].position = (Vector2) {0.000000, 0.492063};curves[3].points[0].tangents = (Vector2) {0,0};curves[3].points[0].leftLinear = 0;curves[3].points[0].rightLinear = 0;
+ curves[3].points[1].position = (Vector2) {0.130000, 0.492063};curves[3].points[1].tangents = (Vector2) {0,0};curves[3].points[1].leftLinear = 0;curves[3].points[1].rightLinear = 0;
+ curves[3].points[2].position = (Vector2) {0.140000, 0.238095};curves[3].points[2].tangents = (Vector2) {0,0};curves[3].points[2].leftLinear = 0;curves[3].points[2].rightLinear = 0;
+ curves[3].points[3].position = (Vector2) {0.150000, 0.492063};curves[3].points[3].tangents = (Vector2) {0,0};curves[3].points[3].leftLinear = 0;curves[3].points[3].rightLinear = 0;
+ curves[3].points[4].position = (Vector2) {0.440000, 0.492063};curves[3].points[4].tangents = (Vector2) {0,0};curves[3].points[4].leftLinear = 0;curves[3].points[4].rightLinear = 0;
+ curves[3].points[5].position = (Vector2) {0.450000, 0.301587};curves[3].points[5].tangents = (Vector2) {0,0};curves[3].points[5].leftLinear = 0;curves[3].points[5].rightLinear = 0;
+ curves[3].points[6].position = (Vector2) {0.460000, 0.492063};curves[3].points[6].tangents = (Vector2) {0,0};curves[3].points[6].leftLinear = 0;curves[3].points[6].rightLinear = 0;
+ curves[3].points[7].position = (Vector2) {0.660000, 0.492063};curves[3].points[7].tangents = (Vector2) {0,0};curves[3].points[7].leftLinear = 0;curves[3].points[7].rightLinear = 0;
+ curves[3].points[8].position = (Vector2) {0.670000, 0.365079};curves[3].points[8].tangents = (Vector2) {0,0};curves[3].points[8].leftLinear = 0;curves[3].points[8].rightLinear = 0;
+ curves[3].points[9].position = (Vector2) {0.680000, 0.492063};curves[3].points[9].tangents = (Vector2) {0,0};curves[3].points[9].leftLinear = 0;curves[3].points[9].rightLinear = 0;
+ curves[3].points[10].position = (Vector2) {0.820000, 0.492063};curves[3].points[10].tangents = (Vector2) {0,0};curves[3].points[10].leftLinear = 0;curves[3].points[10].rightLinear = 0;
+ curves[3].points[11].position = (Vector2) {0.830000, 0.365079};curves[3].points[11].tangents = (Vector2) {0,0};curves[3].points[11].leftLinear = 0;curves[3].points[11].rightLinear = 0;
+ curves[3].points[12].position = (Vector2) {0.840000, 0.492063};curves[3].points[12].tangents = (Vector2) {0,0};curves[3].points[12].leftLinear = 0;curves[3].points[12].rightLinear = 0;
+ curves[3].points[13].position = (Vector2) {0.930000, 0.492063};curves[3].points[13].tangents = (Vector2) {0,0};curves[3].points[13].leftLinear = 0;curves[3].points[13].rightLinear = 0;
+ curves[3].points[14].position = (Vector2) {0.940000, 0.365079};curves[3].points[14].tangents = (Vector2) {0,0};curves[3].points[14].leftLinear = 0;curves[3].points[14].rightLinear = 0;
+ curves[3].points[15].position = (Vector2) {0.950000, 0.507937};curves[3].points[15].tangents = (Vector2) {0,0};curves[3].points[15].leftLinear = 0;curves[3].points[15].rightLinear = 0;
+
+ // Rotation
+ curves[4].start = -360;
+ curves[4].end = 360;
+ curves[4].numPoints = 9;
+ curves[4].selectedIndex = 0;
+ curves[4].editLeftTangent = false;
+ curves[4].editRightTangent = false;
+ curves[4].points[0].position = (Vector2) {0.140000, 0.500000};curves[4].points[0].tangents = (Vector2) {0,0};curves[4].points[0].leftLinear = 0;curves[4].points[0].rightLinear = 0;
+ curves[4].points[1].position = (Vector2) {0.450000, 0.500000};curves[4].points[1].tangents = (Vector2) {0,0};curves[4].points[1].leftLinear = 0;curves[4].points[1].rightLinear = 0;
+ curves[4].points[2].position = (Vector2) {0.670000, 0.500000};curves[4].points[2].tangents = (Vector2) {0,0};curves[4].points[2].leftLinear = 0;curves[4].points[2].rightLinear = 0;
+ curves[4].points[3].position = (Vector2) {0.830000, 0.500000};curves[4].points[3].tangents = (Vector2) {0,0};curves[4].points[3].leftLinear = 0;curves[4].points[3].rightLinear = 0;
+ curves[4].points[4].position = (Vector2) {0.940000, 0.500000};curves[4].points[4].tangents = (Vector2) {0,0};curves[4].points[4].leftLinear = 0;curves[4].points[4].rightLinear = 0;
+ curves[4].points[5].position = (Vector2) {1.000000, 0.500000};curves[4].points[5].tangents = (Vector2) {0,0};curves[4].points[5].leftLinear = 0;curves[4].points[5].rightLinear = 0;
+ curves[4].points[6].position = (Vector2) {0.000000, 0.472222};curves[4].points[6].tangents = (Vector2) {0,0};curves[4].points[6].leftLinear = 0;curves[4].points[6].rightLinear = 0;
+ curves[4].points[7].position = (Vector2) {0.302752, 0.527778};curves[4].points[7].tangents = (Vector2) {0,0};curves[4].points[7].leftLinear = 0;curves[4].points[7].rightLinear = 0;
+ curves[4].points[8].position = (Vector2) {0.577982, 0.472222};curves[4].points[8].tangents = (Vector2) {0,0};curves[4].points[8].leftLinear = 0;curves[4].points[8].rightLinear = 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/animation_curve/gui_curve_editor.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/animation_curve/gui_curve_editor.h
new file mode 100644
index 0000000000..8cf9c0c901
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/animation_curve/gui_curve_editor.h
@@ -0,0 +1,543 @@
+/*******************************************************************************************
+*
+* CurveEdit v1.0 - A cubic Hermite editor for making animation curves
+*
+* MODULE USAGE:
+* #define GUI_CURVE_EDITOR_IMPLEMENTATION
+* #include "gui_curve_edit.h"
+*
+* INIT: GuiCurveEditState state = InitCurveEdit();
+* EVALUATE: float y = EvalGuiCurve(&state, t); // 0 <= t <= 1
+* DRAW: BeginScissorMode(bounds.x,bounds.y,bounds.width,bounds.height);
+* GuiCurveEdit(&state, bounds, pointSize);
+* EndScissorMode();
+*
+* NOTE: See 'Module Structures Declaration' section for more informations.
+*
+* NOTE: This module uses functions of the stdlib:
+* - qsort
+*
+* NOTE: Built-in interactions:
+* - Left click to move/add point or move tangents
+* - While moving a tangent, hold (left/right) SHIFT to disable tangent symetry
+* - Right click to remove a point
+*
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2023 Pierre Jaffuer (@smallcluster)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#ifndef GUI_CURVE_EDITOR_H
+#define GUI_CURVE_EDITOR_H
+
+
+#ifndef GUI_CURVE_EDITOR_MAX_POINTS
+ #define GUI_CURVE_EDITOR_MAX_POINTS 30
+#endif
+
+//----------------------------------------------------------------------------------
+// Module Structures Declaration
+//----------------------------------------------------------------------------------
+
+typedef struct {
+ Vector2 position; // In normalized space [0.0f, 1.0f]
+ Vector2 tangents; // The derivatives (left/right) of the 1D curve
+
+ // Let the curve editor calculate tangents to linearize part of the curve
+ bool leftLinear;
+ bool rightLinear;
+} GuiCurveEditorPoint;
+
+typedef struct {
+ float start; // Value at y = 0
+ float end; // Value at y = 1
+
+ // Always valid (unless you manualy change state's point array). Make sure to set it to -1 before init
+ int selectedIndex;
+
+ // Unsorted array with at least one point (constant curve)
+ GuiCurveEditorPoint points[GUI_CURVE_EDITOR_MAX_POINTS];
+ int numPoints;
+
+ // Private variables
+ bool editLeftTangent;
+ bool editRightTangent;
+ Vector2 mouseOffset;
+} GuiCurveEditorState;
+
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+GuiCurveEditorState InitGuiCurveEditor(); // Initialize curve editor state
+void GuiCurveEditor(GuiCurveEditorState *state, Rectangle bounds); // Draw and update curve control
+
+// 1D Interpolation
+// Returns the y value (in [start, end]) of the curve at x = t
+// t must be normalized [0.f, 1.f]
+float GuiCurveEval(GuiCurveEditorState *state, float t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GUI_CURVE_EDITOR_H
+
+/***********************************************************************************
+*
+* GUI_CURVE_EDITOR IMPLEMENTATION
+*
+************************************************************************************/
+#if defined(GUI_CURVE_EDITOR_IMPLEMENTATION)
+
+#include "../../src/raygui.h" // Change this to fit your project
+
+#include "stdlib.h" // Required for qsort
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+GuiCurveEditorState InitGuiCurveEditor()
+{
+ GuiCurveEditorState state = { 0 };
+
+ state.start = 0;
+ state.end = 1;
+ state.selectedIndex = 0;
+ state.editLeftTangent = false;
+ state.editRightTangent = false;
+ state.mouseOffset = (Vector2){ 0.0f, 0.0f };
+
+ // At least one point (AVG by default)
+ state.numPoints = 1;
+ state.points[0].position = (Vector2){ 0.5f, 0.5f };
+ state.points[0].tangents = (Vector2){ 0.0f, 0.0f };
+ state.points[0].leftLinear = false;
+ state.points[0].rightLinear = false;
+
+ return state;
+}
+
+static int CompareGuiCurveEditPointPtr(const void *a, const void *b)
+{
+ float fa = (*(GuiCurveEditorPoint**)a)->position.x;
+ float fb = (*(GuiCurveEditorPoint**)b)->position.x;
+
+ return ((fa > fb) - (fa < fb));
+}
+
+float GuiCurveEval(GuiCurveEditorState *state, float t)
+{
+ // Sort points
+ GuiCurveEditorPoint* sortedPoints[GUI_CURVE_EDITOR_MAX_POINTS];
+
+ for (int i=0; i < state->numPoints; i++) sortedPoints[i] = &state->points[i];
+
+ qsort(sortedPoints, state->numPoints, sizeof(GuiCurveEditorPoint*), CompareGuiCurveEditPointPtr);
+
+ if (state->numPoints == 0) return state->start;
+
+ // Constants part on edges
+ if (t <= sortedPoints[0]->position.x) return state->start + (state->end-state->start)*sortedPoints[0]->position.y;
+ if (t >= sortedPoints[state->numPoints-1]->position.x) return state->start + (state->end-state->start)*sortedPoints[state->numPoints-1]->position.y;
+
+ // Find curve portion
+ for (int i=0; i < state->numPoints-1; i++)
+ {
+ const GuiCurveEditorPoint *p1 = sortedPoints[i];
+ const GuiCurveEditorPoint *p2 = sortedPoints[i+1];
+
+ // Skip this range
+ if (!((t >= p1->position.x) && (t < p2->position.x)) || (p1->position.x == p2->position.x)) continue;
+
+ float scale = (p2->position.x-p1->position.x);
+ float T = (t-p1->position.x)/scale;
+ float startTangent = scale*p1->tangents.y;
+ float endTangent = scale*p2->tangents.x;
+ float T2 = T*T;
+ float T3 = T*T*T;
+
+ return (state->start + (state->end-state->start)*((2*T3 - 3*T2 + 1)*p1->position.y + (T3 - 2*T2 + T)*startTangent + (3*T2 - 2*T3)*p2->position.y + (T3 - T2)*endTangent));
+ }
+
+ return state->start;
+}
+
+void GuiCurveEditor(GuiCurveEditorState *state, Rectangle bounds)
+{
+ // CONST
+ //----------------------------------------------------------------------------------
+ const float pointSize = 10.0f;
+ const float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
+ const float handleLength = pointSize*2.5f;
+ const float handleSize = pointSize/1.5f;
+
+ const Rectangle innerBounds = (Rectangle){ bounds.x + fontSize, bounds.y + fontSize, bounds.width - 2*fontSize, bounds.height - 2*fontSize };
+ const Vector2 mouse = GetMousePosition();
+ const Vector2 mouseLocal = (Vector2){ (mouse.x - innerBounds.x)/innerBounds.width, (innerBounds.y + innerBounds.height-mouse.y)/innerBounds.height};
+ //----------------------------------------------------------------------------------
+
+ // UPDATE STATE
+ //----------------------------------------------------------------------------------
+ // Find first point under mouse (-1 if not found)
+ int hoveredPointIndex = -1;
+ for (int i = 0; i < state->numPoints; i++)
+ {
+ const GuiCurveEditorPoint *p = &state->points[i];
+ const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height-p->position.y*innerBounds.height };
+ const Rectangle pointRect = (Rectangle){ screenPos.x - pointSize/2.0f, screenPos.y - pointSize/2.0f, pointSize, pointSize };
+
+ if (CheckCollisionPointRec(mouse, pointRect))
+ {
+ hoveredPointIndex = i;
+ break;
+ }
+ }
+
+ // Unselect tangents
+ if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
+ {
+ state->editLeftTangent = false;
+ state->editRightTangent = false;
+ }
+
+ // Select a tangent if possible
+ if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (state->selectedIndex != -1) && CheckCollisionPointRec(mouse, bounds))
+ {
+ const GuiCurveEditorPoint* p = &state->points[state->selectedIndex];
+ const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height };
+
+ // Left control
+ Vector2 target = (Vector2){ (p->position.x-1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y-p->tangents.x)*innerBounds.height };
+ Vector2 dir = (Vector2){ target.x-screenPos.x, target.y-screenPos.y };
+ float d = sqrt(dir.x*dir.x + dir.y*dir.y);
+ Vector2 control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
+ Rectangle controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
+
+ // Edit left tangent
+ if (CheckCollisionPointRec(mouse, controlRect)) state->editLeftTangent = true;
+
+ // Right control
+ target = (Vector2){ (p->position.x + 1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y + p->tangents.y)*innerBounds.height };
+ dir = (Vector2){ target.x-screenPos.x, target.y-screenPos.y };
+ d = sqrt(dir.x*dir.x + dir.y*dir.y);
+ control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
+ controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
+
+ // Edit right tangent
+ if (CheckCollisionPointRec(mouse, controlRect)) state->editRightTangent = true;
+ }
+
+ // Move tangents
+ if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && state->editRightTangent)
+ {
+ // editRightTangent == true implies selectedIndex != -1
+ GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
+ const Vector2 dir = (Vector2){ mouseLocal.x - p->position.x, mouseLocal.y - p->position.y};
+
+ // Calculate right tangent slope
+ p->tangents.y = (dir.x < 0.001f)? dir.y/0.001f : dir.y/dir.x;
+ p->rightLinear = false; // Stop right linearization update
+
+ // Tangents are symetric by default unless SHIFT is pressed
+ if (!(IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT)))
+ {
+ p->tangents.x = p->tangents.y;
+ p->leftLinear = false; // Stop left linearization update
+ }
+
+ }
+ else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && state->editLeftTangent)
+ {
+ // editLeftTangent == true implies selectedIndex != -1
+ GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
+ const Vector2 dir = (Vector2){ mouseLocal.x - p->position.x, mouseLocal.y - p->position.y };
+
+ // Calculate left tangent slope
+ p->tangents.x = (dir.x > -0.001f)? dir.y/(-0.001f) : dir.y/dir.x;
+ p->leftLinear = false; // Stop left linearization update
+
+ // Tangents are symetric by default unless SHIFT is pressed
+ if (!(IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT)))
+ {
+ p->tangents.y = p->tangents.x;
+ p->rightLinear = false; // Stop right linearization update
+ }
+ }
+ // Select a point
+ else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (hoveredPointIndex != -1) && CheckCollisionPointRec(mouse, bounds))
+ {
+ state->selectedIndex = hoveredPointIndex;
+ const GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
+ state->mouseOffset = (Vector2){ p->position.x - mouseLocal.x, p->position.y - mouseLocal.y };
+ }
+ // Remove a point (check against bounds)
+ else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT) && (hoveredPointIndex != -1) && CheckCollisionPointRec(mouse, bounds) && (state->numPoints > 1))
+ {
+ // Deselect everything
+ state->selectedIndex = 0; // select first point by default
+ state->editLeftTangent = false;
+ state->editRightTangent = false;
+
+ // Remove point
+ state->numPoints -= 1;
+ for (int i = hoveredPointIndex; i < state->numPoints; i++) state->points[i] = state->points[i+1];
+ }
+ // Add a point (check against innerBounds)
+ else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mouse, innerBounds) && (state->numPoints < GUI_CURVE_EDITOR_MAX_POINTS))
+ {
+ state->editLeftTangent = false;
+ state->editRightTangent = false;
+
+ // Create new point
+ GuiCurveEditorPoint p;
+ p.tangents = (Vector2){ 0.0f, 0.0f };
+ p.position = mouseLocal;
+ p.leftLinear = false;
+ p.rightLinear = false;
+
+ // Append point
+ state->points[state->numPoints] = p;
+ state->selectedIndex = state->numPoints; // select new point
+ state->numPoints += 1;
+
+ // Point is add on mouse pos
+ state->mouseOffset = (Vector2){ 0, 0 };
+ }
+ // Move selected point
+ else if ((state->selectedIndex != -1) && IsMouseButtonDown(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mouse, bounds))
+ {
+ GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
+
+ // use mouse offset on click to prevent point teleporting to mouse
+ const Vector2 newLocalPos = (Vector2){ mouseLocal.x + state->mouseOffset.x, mouseLocal.y + state->mouseOffset.y };
+
+ // Clamp to innerbounds
+ p->position.x = (newLocalPos.x < 0)? 0 : ((newLocalPos.x > 1)? 1 : newLocalPos.x);
+ p->position.y = (newLocalPos.y < 0)? 0 : ((newLocalPos.y > 1)? 1 : newLocalPos.y);
+ }
+
+ // Sort points
+ GuiCurveEditorPoint *sortedPoints[GUI_CURVE_EDITOR_MAX_POINTS] = { 0 };
+ for (int i = 0; i < state->numPoints; i++) sortedPoints[i] = &state->points[i];
+ qsort(sortedPoints, state->numPoints, sizeof(GuiCurveEditorPoint*), CompareGuiCurveEditPointPtr);
+
+ // Update linear tangents
+ for (int i = 0; i < state->numPoints; i++)
+ {
+ GuiCurveEditorPoint *p = sortedPoints[i];
+
+ // Left tangent
+ if ((i > 0) && p->leftLinear)
+ {
+ const GuiCurveEditorPoint *p2 = sortedPoints[i - 1];
+ Vector2 dir = (Vector2){ p2->position.x - p->position.x, p2->position.y - p->position.y };
+ p->tangents.x = (dir.x == 0)? 0 : dir.y/dir.x;
+ }
+
+ // Right tangent
+ if ((i < state->numPoints - 1) && p->rightLinear)
+ {
+ const GuiCurveEditorPoint *p2 = sortedPoints[i + 1];
+ Vector2 dir = (Vector2){ p2->position.x - p->position.x, p2->position.y - p->position.y };
+ p->tangents.y = (dir.x == 0)? 0 : dir.y/dir.x;
+ }
+ }
+ //----------------------------------------------------------------------------------
+
+ // DRAWING
+ //----------------------------------------------------------------------------------
+ DrawRectangle(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ // Draw grid
+ // H lines
+ const Color lineColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
+ DrawLine(bounds.x, innerBounds.y, bounds.x+bounds.width, innerBounds.y, lineColor); // end
+ DrawLine(bounds.x, innerBounds.y+innerBounds.height/2, bounds.x+bounds.width, innerBounds.y+innerBounds.height/2, lineColor); // avg
+ DrawLine(bounds.x, innerBounds.y+innerBounds.height, bounds.x+bounds.width, innerBounds.y+innerBounds.height, lineColor); // start
+
+ // V lines
+ DrawLine(innerBounds.x, bounds.y, innerBounds.x, bounds.y+bounds.height, lineColor); // 0
+ DrawLine(innerBounds.x + innerBounds.width/4, bounds.y, innerBounds.x + innerBounds.width/4, bounds.y + bounds.height, lineColor); // 0.25
+ DrawLine(innerBounds.x + innerBounds.width/2, bounds.y, innerBounds.x + innerBounds.width/2, bounds.y + bounds.height, lineColor); // 0.5
+ DrawLine(innerBounds.x + 3*innerBounds.width/4, bounds.y, innerBounds.x + 3*innerBounds.width/4, bounds.y + bounds.height, lineColor); // 0.75
+ DrawLine(innerBounds.x + innerBounds.width, bounds.y, innerBounds.x + innerBounds.width, bounds.y + bounds.height, lineColor); // 1
+
+ Font font = GuiGetFont();
+ // V labels
+ DrawTextEx(font, "0", (Vector2){ innerBounds.x, bounds.y + bounds.height-fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+ DrawTextEx(font, "0.25", (Vector2){ innerBounds.x + innerBounds.width/4.0f, bounds.y + bounds.height - fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+ DrawTextEx(font, "0.5", (Vector2){ innerBounds.x + innerBounds.width/2.0f, bounds.y + bounds.height - fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+ DrawTextEx(font, "0.75", (Vector2){ innerBounds.x + 3.0f*innerBounds.width/4.0f, bounds.y + bounds.height-fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+ DrawTextEx(font, "1", (Vector2){ innerBounds.x + innerBounds.width, bounds.y+bounds.height - fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+
+ // H labels
+ DrawTextEx(font, TextFormat("%.2f", state->start), (Vector2){ innerBounds.x, innerBounds.y - fontSize+innerBounds.height }, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+ DrawTextEx(font, TextFormat("%.2f", state->start + (state->end-state->start)/2.f), (Vector2){ innerBounds.x, innerBounds.y - fontSize + innerBounds.height/2.0f }, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+ DrawTextEx(font, TextFormat("%.2f", state->end), (Vector2){ innerBounds.x, innerBounds.y }, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
+
+ // Draw contours
+ if (CheckCollisionPointRec(mouse, bounds)) DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_FOCUSED)));
+ else DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)));
+
+ // Draw points
+ for (int i = 0; i < state->numPoints; i++)
+ {
+ const GuiCurveEditorPoint *p = sortedPoints[i];
+
+ const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p->position.y*innerBounds.height };
+ const Rectangle pointRect = (Rectangle){ screenPos.x - pointSize/2.0f, screenPos.y - pointSize/2.0f, pointSize, pointSize };
+
+ Color pointColor = { 0 };
+ Color pointBorderColor = { 0 };
+
+ // Draw point
+ if (&state->points[state->selectedIndex] == p)
+ {
+ // Draw left handle
+ if (i > 0)
+ {
+ const Vector2 target = (Vector2){ (p->position.x - 1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y - p->tangents.x)*innerBounds.height };
+ const Vector2 dir = (Vector2){ target.x - screenPos.x, target.y - screenPos.y };
+ const float d = sqrt(dir.x*dir.x + dir.y*dir.y);
+ const Vector2 control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
+ const Rectangle controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
+
+ Color controlColor = { 0 };
+
+ if (state->editLeftTangent)
+ {
+ controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED));
+ }
+ else if (CheckCollisionPointRec(mouse, controlRect))
+ {
+ controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED));
+ }
+ else
+ {
+ controlColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL));
+ }
+
+ DrawLine(screenPos.x,screenPos.y, control.x, control.y, controlColor);
+ DrawRectangle(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
+ DrawRectangleLines(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
+ }
+
+ // Draw right handle
+ if (i < state->numPoints - 1)
+ {
+ const Vector2 target = (Vector2){ (p->position.x + 1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y + p->tangents.y)*innerBounds.height };
+ const Vector2 dir = (Vector2){ target.x - screenPos.x, target.y - screenPos.y };
+ const float d = sqrt(dir.x*dir.x + dir.y*dir.y);
+ const Vector2 control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
+ const Rectangle controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
+
+ Color controlColor = { 0 };
+
+ if (state->editRightTangent)
+ {
+ controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED));
+ }
+ else if (CheckCollisionPointRec(mouse, controlRect))
+ {
+ controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED));
+ }
+ else
+ {
+ controlColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL));
+ }
+
+ DrawLine(screenPos.x,screenPos.y, control.x, control.y, controlColor);
+ DrawRectangle(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
+ DrawRectangleLines(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
+ }
+
+ pointColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED));
+ pointBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
+
+ }
+ else if (&state->points[hoveredPointIndex] == p)
+ {
+ pointColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED));
+ pointBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
+ }
+ else
+ {
+ pointColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL));
+ pointBorderColor = GetColor(GuiGetStyle(BUTTON, BORDER_COLOR_NORMAL));
+ }
+
+ DrawRectangle(pointRect.x, pointRect.y, pointRect.width, pointRect.height, pointColor);
+ DrawRectangleLines(pointRect.x, pointRect.y, pointRect.width, pointRect.height, pointBorderColor);
+ }
+
+ // Draw curve
+ Color curveColor = GetColor(GuiGetStyle(LABEL, TEXT_COLOR_FOCUSED));
+
+ if (state->numPoints == 1)
+ {
+ const GuiCurveEditorPoint *p = sortedPoints[0];
+ const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p->position.y*innerBounds.height };
+ DrawLine(innerBounds.x, screenPos.y, innerBounds.x+innerBounds.width, screenPos.y, curveColor);
+ }
+ else
+ {
+ for (int i = 0; i < state->numPoints - 1; i++)
+ {
+ const GuiCurveEditorPoint *p1 = sortedPoints[i];
+ const GuiCurveEditorPoint *p2 = sortedPoints[i + 1];
+ const Vector2 screenPos1 = (Vector2){ p1->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p1->position.y*innerBounds.height };
+ const Vector2 screenPos2 = (Vector2){ p2->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p2->position.y*innerBounds.height };
+
+ // Constant on edge
+ if ((screenPos1.x > innerBounds.x) && (i == 0))
+ {
+ DrawLine(innerBounds.x, screenPos1.y, screenPos1.x, screenPos1.y, curveColor);
+ }
+ if ((screenPos2.x < innerBounds.x + innerBounds.width) && (i == (state->numPoints - 2)))
+ {
+ DrawLine(screenPos2.x, screenPos2.y, innerBounds.x+innerBounds.width, screenPos2.y, curveColor);
+ }
+
+ // Draw cubic Hermite curve
+ const float scale = (p2->position.x - p1->position.x)/3.0f;
+ const Vector2 offset1 = (Vector2){ scale, scale*p1->tangents.y };
+ // negative endTangent => top part => need to invert value to calculate offset
+ const Vector2 offset2 = (Vector2){ -scale, -scale*p2->tangents.x };
+
+ const Vector2 c1 = (Vector2){ p1->position.x + offset1.x, p1->position.y + offset1.y };
+ const Vector2 c2 = (Vector2){ p2->position.x + offset2.x, p2->position.y + offset2.y };
+
+ const Vector2 screenC1 = (Vector2){ c1.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - c1.y*innerBounds.height };
+ const Vector2 screenC2 = (Vector2){ c2.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - c2.y*innerBounds.height };
+
+ DrawSplineSegmentBezierCubic(screenPos1, screenC1, screenC2, screenPos2, 1, curveColor);
+ }
+ }
+}
+
+#endif // GUI_CURVE_EDITOR_IMPLEMENTATION
+
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/controls_test_suite.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/controls_test_suite.c
new file mode 100644
index 0000000000..9bf057af7a
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/controls_test_suite.c
@@ -0,0 +1,331 @@
+/*******************************************************************************************
+*
+* raygui - controls test suite
+*
+* TEST CONTROLS:
+* - GuiDropdownBox()
+* - GuiCheckBox()
+* - GuiSpinner()
+* - GuiValueBox()
+* - GuiTextBox()
+* - GuiButton()
+* - GuiComboBox()
+* - GuiListView()
+* - GuiToggleGroup()
+* - GuiColorPicker()
+* - GuiSlider()
+* - GuiSliderBar()
+* - GuiProgressBar()
+* - GuiColorBarAlpha()
+* - GuiScrollPanel()
+*
+*
+* DEPENDENCIES:
+* raylib 4.5 - Windowing/input management and drawing
+* raygui 3.5 - Immediate-mode GUI controls with custom styling and icons
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+//#define RAYGUI_DEBUG_RECS_BOUNDS
+//#define RAYGUI_DEBUG_TEXT_BOUNDS
+
+#define RAYGUI_IMPLEMENTATION
+//#define RAYGUI_CUSTOM_ICONS // It requires providing gui_icons.h in the same directory
+//#include "gui_icons.h" // External icons data provided, it can be generated with rGuiIcons tool
+#include "../../src/raygui.h"
+
+// raygui embedded styles
+#include "../styles/style_cyber.h" // raygui style: cyber
+#include "../styles/style_jungle.h" // raygui style: jungle
+#include "../styles/style_lavanda.h" // raygui style: lavanda
+#include "../styles/style_dark.h" // raygui style: dark
+#include "../styles/style_bluish.h" // raygui style: bluish
+#include "../styles/style_terminal.h" // raygui style: terminal
+#include "../styles/style_candy.h"
+#include "../styles/style_cherry.h"
+#include "../styles/style_ashes.h"
+#include "../styles/style_enefete.h"
+#include "../styles/style_sunny.h"
+#include "../styles/style_amber.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ const int screenWidth = 960;
+ const int screenHeight = 560;
+
+ InitWindow(screenWidth, screenHeight, "raygui - controls test suite");
+ SetExitKey(0);
+
+ // GUI controls initialization
+ //----------------------------------------------------------------------------------
+ int dropdownBox000Active = 0;
+ bool dropDown000EditMode = false;
+
+ int dropdownBox001Active = 0;
+ bool dropDown001EditMode = false;
+
+ int spinner001Value = 0;
+ bool spinnerEditMode = false;
+
+ int valueBox002Value = 0;
+ bool valueBoxEditMode = false;
+
+ char textBoxText[64] = "Text box";
+ bool textBoxEditMode = false;
+
+ char textBoxMultiText[1024] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n\nThisisastringlongerthanexpectedwithoutspacestotestcharbreaksforthosecases,checkingifworkingasexpected.\n\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
+ bool textBoxMultiEditMode = false;
+
+ int listViewScrollIndex = 0;
+ int listViewActive = -1;
+
+ int listViewExScrollIndex = 0;
+ int listViewExActive = 2;
+ int listViewExFocus = -1;
+ const char *listViewExList[8] = { "This", "is", "a", "list view", "with", "disable", "elements", "amazing!" };
+
+ Color colorPickerValue = RED;
+
+ float sliderValue = 50.0f;
+ float sliderBarValue = 60;
+ float progressValue = 0.1f;
+
+ bool forceSquaredChecked = false;
+
+ float alphaValue = 0.5f;
+
+ //int comboBoxActive = 1;
+ int visualStyleActive = 0;
+ int prevVisualStyleActive = 0;
+
+ int toggleGroupActive = 0;
+ int toggleSliderActive = 0;
+
+ Vector2 viewScroll = { 0, 0 };
+ //----------------------------------------------------------------------------------
+
+ // Custom GUI font loading
+ //Font font = LoadFontEx("fonts/rainyhearts16.ttf", 12, 0, 0);
+ //GuiSetFont(font);
+
+ bool exitWindow = false;
+ bool showMessageBox = false;
+
+ char textInput[256] = { 0 };
+ char textInputFileName[256] = { 0 };
+ bool showTextInputBox = false;
+
+ float alpha = 1.0f;
+
+ // DEBUG: Testing how those two properties affect all controls!
+ //GuiSetStyle(DEFAULT, TEXT_PADDING, 0);
+ //GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!exitWindow) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ exitWindow = WindowShouldClose();
+
+ if (IsKeyPressed(KEY_ESCAPE)) showMessageBox = !showMessageBox;
+
+ if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_S)) showTextInputBox = true;
+
+ if (IsFileDropped())
+ {
+ FilePathList droppedFiles = LoadDroppedFiles();
+
+ if ((droppedFiles.count > 0) && IsFileExtension(droppedFiles.paths[0], ".rgs")) GuiLoadStyle(droppedFiles.paths[0]);
+
+ UnloadDroppedFiles(droppedFiles); // Clear internal buffers
+ }
+
+ //alpha -= 0.002f;
+ if (alpha < 0.0f) alpha = 0.0f;
+ if (IsKeyPressed(KEY_SPACE)) alpha = 1.0f;
+
+ GuiSetAlpha(alpha);
+
+ //progressValue += 0.002f;
+ if (IsKeyPressed(KEY_LEFT)) progressValue -= 0.1f;
+ else if (IsKeyPressed(KEY_RIGHT)) progressValue += 0.1f;
+ if (progressValue > 1.0f) progressValue = 1.0f;
+ else if (progressValue < 0.0f) progressValue = 0.0f;
+
+ if (visualStyleActive != prevVisualStyleActive)
+ {
+ GuiLoadStyleDefault();
+
+ switch (visualStyleActive)
+ {
+ case 0: break; // Default style
+ case 1: GuiLoadStyleJungle(); break;
+ case 2: GuiLoadStyleLavanda(); break;
+ case 3: GuiLoadStyleDark(); break;
+ case 4: GuiLoadStyleBluish(); break;
+ case 5: GuiLoadStyleCyber(); break;
+ case 6: GuiLoadStyleTerminal(); break;
+ case 7: GuiLoadStyleCandy(); break;
+ case 8: GuiLoadStyleCherry(); break;
+ case 9: GuiLoadStyleAshes(); break;
+ case 10: GuiLoadStyleEnefete(); break;
+ case 11: GuiLoadStyleSunny(); break;
+ case 12: GuiLoadStyleAmber(); break;
+ default: break;
+ }
+
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+
+ prevVisualStyleActive = visualStyleActive;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ // raygui: controls drawing
+ //----------------------------------------------------------------------------------
+ // Check all possible events that require GuiLock
+ if (dropDown000EditMode || dropDown001EditMode) GuiLock();
+
+ // First GUI column
+ //GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ GuiCheckBox((Rectangle){ 25, 108, 15, 15 }, "FORCE CHECK!", &forceSquaredChecked);
+
+ GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ //GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ if (GuiSpinner((Rectangle){ 25, 135, 125, 30 }, NULL, &spinner001Value, 0, 100, spinnerEditMode)) spinnerEditMode = !spinnerEditMode;
+ if (GuiValueBox((Rectangle){ 25, 175, 125, 30 }, NULL, &valueBox002Value, 0, 100, valueBoxEditMode)) valueBoxEditMode = !valueBoxEditMode;
+ GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ if (GuiTextBox((Rectangle){ 25, 215, 125, 30 }, textBoxText, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
+
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ if (GuiButton((Rectangle){ 25, 255, 125, 30 }, GuiIconText(ICON_FILE_SAVE, "Save File"))) showTextInputBox = true;
+
+ GuiGroupBox((Rectangle){ 25, 310, 125, 150 }, "STATES");
+ //GuiLock();
+ GuiSetState(STATE_NORMAL); if (GuiButton((Rectangle){ 30, 320, 115, 30 }, "NORMAL")) { }
+ GuiSetState(STATE_FOCUSED); if (GuiButton((Rectangle){ 30, 355, 115, 30 }, "FOCUSED")) { }
+ GuiSetState(STATE_PRESSED); if (GuiButton((Rectangle){ 30, 390, 115, 30 }, "#15#PRESSED")) { }
+ GuiSetState(STATE_DISABLED); if (GuiButton((Rectangle){ 30, 425, 115, 30 }, "DISABLED")) { }
+ GuiSetState(STATE_NORMAL);
+ //GuiUnlock();
+
+ GuiComboBox((Rectangle){ 25, 480, 125, 30 }, "default;Jungle;Lavanda;Dark;Bluish;Cyber;Terminal;Candy;Cherry;Ashes;Enefete;Sunny;Amber", &visualStyleActive);
+
+ // NOTE: GuiDropdownBox must draw after any other control that can be covered on unfolding
+ GuiUnlock();
+ GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 4);
+ GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ if (GuiDropdownBox((Rectangle){ 25, 65, 125, 30 }, "#01#ONE;#02#TWO;#03#THREE;#04#FOUR", &dropdownBox001Active, dropDown001EditMode)) dropDown001EditMode = !dropDown001EditMode;
+ GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0);
+
+ if (GuiDropdownBox((Rectangle){ 25, 25, 125, 30 }, "ONE;TWO;THREE", &dropdownBox000Active, dropDown000EditMode)) dropDown000EditMode = !dropDown000EditMode;
+
+ // Second GUI column
+ //GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL, 1);
+ GuiListView((Rectangle){ 165, 25, 140, 124 }, "Charmander;Bulbasaur;#18#Squirtel;Pikachu;Eevee;Pidgey", &listViewScrollIndex, &listViewActive);
+ GuiListViewEx((Rectangle){ 165, 162, 140, 184 }, listViewExList, 8, &listViewExScrollIndex, &listViewExActive, &listViewExFocus);
+ GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL, 0);
+
+ //GuiToggle((Rectangle){ 165, 400, 140, 25 }, "#1#ONE", &toggleGroupActive);
+ GuiToggleGroup((Rectangle){ 165, 360, 140, 24 }, "#1#ONE\n#3#TWO\n#8#THREE\n#23#", &toggleGroupActive);
+ //GuiDisable();
+ GuiSetStyle(SLIDER, SLIDER_PADDING, 2);
+ GuiToggleSlider((Rectangle){ 165, 480, 140, 30 }, "ON;OFF", &toggleSliderActive);
+ GuiSetStyle(SLIDER, SLIDER_PADDING, 0);
+
+ // Third GUI column
+ GuiPanel((Rectangle){ 320, 25, 225, 140 }, "Panel Info");
+ GuiColorPicker((Rectangle){ 320, 185, 196, 192 }, NULL, &colorPickerValue);
+
+ //GuiDisable();
+ GuiSlider((Rectangle){ 355, 400, 165, 20 }, "TEST", TextFormat("%2.2f", sliderValue), &sliderValue, -50, 100);
+ GuiSliderBar((Rectangle){ 320, 430, 200, 20 }, NULL, TextFormat("%i", (int)sliderBarValue), &sliderBarValue, 0, 100);
+
+ GuiProgressBar((Rectangle){ 320, 460, 200, 20 }, NULL, TextFormat("%i%%", (int)(progressValue*100)), &progressValue, 0.0f, 1.0f);
+ GuiEnable();
+
+ // NOTE: View rectangle could be used to perform some scissor test
+ Rectangle view = { 0 };
+ GuiScrollPanel((Rectangle){ 560, 25, 102, 354 }, NULL, (Rectangle){ 560, 25, 300, 1200 }, &viewScroll, &view);
+
+ Vector2 mouseCell = { 0 };
+ GuiGrid((Rectangle) { 560, 25 + 180 + 195, 100, 120 }, NULL, 20, 3, &mouseCell);
+
+ GuiColorBarAlpha((Rectangle){ 320, 490, 200, 30 }, NULL, &alphaValue);
+
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); // WARNING: Word-wrap does not work as expected in case of no-top alignment
+ GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported
+ if (GuiTextBox((Rectangle){ 678, 25, 258, 492 }, textBoxMultiText, 1024, textBoxMultiEditMode)) textBoxMultiEditMode = !textBoxMultiEditMode;
+ GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE);
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE);
+
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ GuiStatusBar((Rectangle){ 0, (float)GetScreenHeight() - 20, (float)GetScreenWidth(), 20 }, "This is a status bar");
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ //GuiSetStyle(STATUSBAR, TEXT_INDENTATION, 20);
+
+ if (showMessageBox)
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, 0.8f));
+ int result = GuiMessageBox((Rectangle){ (float)GetScreenWidth()/2 - 125, (float)GetScreenHeight()/2 - 50, 250, 100 }, GuiIconText(ICON_EXIT, "Close Window"), "Do you really want to exit?", "Yes;No");
+
+ if ((result == 0) || (result == 2)) showMessageBox = false;
+ else if (result == 1) exitWindow = true;
+ }
+
+ if (showTextInputBox)
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, 0.8f));
+ int result = GuiTextInputBox((Rectangle){ (float)GetScreenWidth()/2 - 120, (float)GetScreenHeight()/2 - 60, 240, 140 }, GuiIconText(ICON_FILE_SAVE, "Save file as..."), "Introduce output file name:", "Ok;Cancel", textInput, 255, NULL);
+
+ if (result == 1)
+ {
+ // TODO: Validate textInput value and save
+
+ TextCopy(textInputFileName, textInput);
+ }
+
+ if ((result == 0) || (result == 1) || (result == 2))
+ {
+ showTextInputBox = false;
+ TextCopy(textInput, "\0");
+ }
+ }
+ //----------------------------------------------------------------------------------
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/controls_test_suite.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/controls_test_suite.png
new file mode 100644
index 0000000000..895696cf17
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/controls_test_suite.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/gui_value_box_float.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/gui_value_box_float.c
new file mode 100644
index 0000000000..871937599f
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/controls_test_suite/gui_value_box_float.c
@@ -0,0 +1,71 @@
+/*******************************************************************************************
+*
+* raygui - controls test suite
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+#include
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raygui - controls test suite");
+
+ float valueBoxValue = 0.0f;
+ bool valueBoxEditMode = false;
+ char valueBoxTextValue[32] = { 0 };
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ if (GuiValueBoxFloat((Rectangle){ 25, 175, 125, 30 }, NULL, valueBoxTextValue, &valueBoxValue, valueBoxEditMode))
+ {
+ valueBoxEditMode = !valueBoxEditMode;
+
+ printf("Value: %2.2f\n", valueBoxValue);
+ }
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/cat.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/cat.png
new file mode 100644
index 0000000000..d023aa2185
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/cat.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/custom_file_dialog.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/custom_file_dialog.c
new file mode 100644
index 0000000000..dea4f2315a
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/custom_file_dialog.c
@@ -0,0 +1,112 @@
+/*******************************************************************************************
+*
+* raygui - custom file dialog to load image
+*
+* DEPENDENCIES:
+* raylib 4.0 - Windowing/input management and drawing.
+* raygui 3.0 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+#undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again
+
+#define GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION
+#include "gui_window_file_dialog.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ int screenWidth = 800;
+ int screenHeight = 560;
+
+ InitWindow(screenWidth, screenHeight, "raygui - custom modal dialog");
+ SetExitKey(0);
+
+ // Custom file dialog
+ GuiWindowFileDialogState fileDialogState = InitGuiWindowFileDialog(GetWorkingDirectory());
+
+ bool exitWindow = false;
+
+ char fileNameToLoad[512] = { 0 };
+
+ Texture texture = { 0 };
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!exitWindow) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ exitWindow = WindowShouldClose();
+
+ if (fileDialogState.SelectFilePressed)
+ {
+ // Load image file (if supported extension)
+ if (IsFileExtension(fileDialogState.fileNameText, ".png"))
+ {
+ strcpy(fileNameToLoad, TextFormat("%s" PATH_SEPERATOR "%s", fileDialogState.dirPathText, fileDialogState.fileNameText));
+ UnloadTexture(texture);
+ texture = LoadTexture(fileNameToLoad);
+ }
+
+ fileDialogState.SelectFilePressed = false;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ DrawTexture(texture, GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, WHITE);
+ DrawRectangleLines(GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, texture.width, texture.height, BLACK);
+
+ DrawText(fileNameToLoad, 208, GetScreenHeight() - 20, 10, GRAY);
+
+ // raygui: controls drawing
+ //----------------------------------------------------------------------------------
+ if (fileDialogState.windowActive) GuiLock();
+
+ if (GuiButton((Rectangle){ 20, 20, 140, 30 }, GuiIconText(ICON_FILE_OPEN, "Open Image"))) fileDialogState.windowActive = true;
+
+ GuiUnlock();
+
+ // GUI: Dialog Window
+ //--------------------------------------------------------------------------------
+ GuiWindowFileDialog(&fileDialogState);
+ //--------------------------------------------------------------------------------
+
+ //----------------------------------------------------------------------------------
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadTexture(texture); // Unload texture
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/gui_window_file_dialog.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/gui_window_file_dialog.h
new file mode 100644
index 0000000000..dc9f3a9367
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_file_dialog/gui_window_file_dialog.h
@@ -0,0 +1,625 @@
+/*******************************************************************************************
+*
+* Window File Dialog v1.2 - Modal file dialog to open/save files
+*
+* MODULE USAGE:
+* #define GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION
+* #include "gui_window_file_dialog.h"
+*
+* INIT: GuiWindowFileDialogState state = GuiInitWindowFileDialog();
+* DRAW: GuiWindowFileDialog(&state);
+*
+* NOTE: This module depends on some raylib file system functions:
+* - LoadDirectoryFiles()
+* - UnloadDirectoryFiles()
+* - GetWorkingDirectory()
+* - DirectoryExists()
+* - FileExists()
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2019-2024 Ramon Santamaria (@raysan5)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#ifndef GUI_WINDOW_FILE_DIALOG_H
+#define GUI_WINDOW_FILE_DIALOG_H
+
+// Gui file dialog context data
+typedef struct {
+
+ // Window management variables
+ bool windowActive;
+ Rectangle windowBounds;
+ Vector2 panOffset;
+ bool dragMode;
+ bool supportDrag;
+
+ // UI variables
+ bool dirPathEditMode;
+ char dirPathText[1024];
+
+ int filesListScrollIndex;
+ bool filesListEditMode;
+ int filesListActive;
+
+ bool fileNameEditMode;
+ char fileNameText[1024];
+ bool SelectFilePressed;
+ bool CancelFilePressed;
+ int fileTypeActive;
+ int itemFocused;
+
+ // Custom state variables
+ FilePathList dirFiles;
+ char filterExt[256];
+ char dirPathTextCopy[1024];
+ char fileNameTextCopy[1024];
+
+ int prevFilesListActive;
+
+ bool saveFileMode;
+
+} GuiWindowFileDialogState;
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+GuiWindowFileDialogState InitGuiWindowFileDialog(const char *initPath);
+void GuiWindowFileDialog(GuiWindowFileDialogState *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GUI_WINDOW_FILE_DIALOG_H
+
+/***********************************************************************************
+*
+* GUI_WINDOW_FILE_DIALOG IMPLEMENTATION
+*
+************************************************************************************/
+#if defined(GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION)
+
+#include "../../src/raygui.h"
+
+#include // Required for: strcpy()
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define MAX_DIRECTORY_FILES 2048
+#define MAX_ICON_PATH_LENGTH 512
+#ifdef _WIN32
+#define PATH_SEPERATOR "\\"
+#else
+#define PATH_SEPERATOR "/"
+#endif
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
+// Detailed file info type
+typedef struct FileInfo {
+ const char *name;
+ int size;
+ int modTime;
+ int type;
+ int icon;
+} FileInfo;
+#else
+// Filename only
+typedef char *FileInfo; // Files are just a path string
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+FileInfo *dirFilesIcon = NULL; // Path string + icon (for fancy drawing)
+
+//----------------------------------------------------------------------------------
+// Internal Module Functions Definition
+//----------------------------------------------------------------------------------
+// Read files in new path
+static void ReloadDirectoryFiles(GuiWindowFileDialogState *state);
+
+#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
+// List View control for files info with extended parameters
+static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active);
+#endif
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+GuiWindowFileDialogState InitGuiWindowFileDialog(const char *initPath)
+{
+ GuiWindowFileDialogState state = { 0 };
+
+ // Init window data
+ state.windowBounds = (Rectangle){ GetScreenWidth()/2 - 440/2, GetScreenHeight()/2 - 310/2, 440, 310 };
+ state.windowActive = false;
+ state.supportDrag = true;
+ state.dragMode = false;
+ state.panOffset = (Vector2){ 0, 0 };
+
+ // Init path data
+ state.dirPathEditMode = false;
+ state.filesListActive = -1;
+ state.prevFilesListActive = state.filesListActive;
+ state.filesListScrollIndex = 0;
+
+ state.fileNameEditMode = false;
+
+ state.SelectFilePressed = false;
+ state.CancelFilePressed = false;
+
+ state.fileTypeActive = 0;
+
+ strcpy(state.fileNameText, "\0");
+
+ // Custom variables initialization
+ if (initPath && DirectoryExists(initPath))
+ {
+ strcpy(state.dirPathText, initPath);
+ }
+ else if (initPath && FileExists(initPath))
+ {
+ strcpy(state.dirPathText, GetDirectoryPath(initPath));
+ strcpy(state.fileNameText, GetFileName(initPath));
+ }
+ else strcpy(state.dirPathText, GetWorkingDirectory());
+
+ // TODO: Why we keep a copy?
+ strcpy(state.dirPathTextCopy, state.dirPathText);
+ strcpy(state.fileNameTextCopy, state.fileNameText);
+
+ state.filterExt[0] = '\0';
+ //strcpy(state.filterExt, "all");
+
+ state.dirFiles.count = 0;
+
+ return state;
+}
+
+// Update and draw file dialog
+void GuiWindowFileDialog(GuiWindowFileDialogState *state)
+{
+ if (state->windowActive)
+ {
+ // Update window dragging
+ //----------------------------------------------------------------------------------------
+ if (state->supportDrag)
+ {
+ Vector2 mousePosition = GetMousePosition();
+
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ // Window can be dragged from the top window bar
+ if (CheckCollisionPointRec(mousePosition, (Rectangle){ state->windowBounds.x, state->windowBounds.y, (float)state->windowBounds.width, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }))
+ {
+ state->dragMode = true;
+ state->panOffset.x = mousePosition.x - state->windowBounds.x;
+ state->panOffset.y = mousePosition.y - state->windowBounds.y;
+ }
+ }
+
+ if (state->dragMode)
+ {
+ state->windowBounds.x = (mousePosition.x - state->panOffset.x);
+ state->windowBounds.y = (mousePosition.y - state->panOffset.y);
+
+ // Check screen limits to avoid moving out of screen
+ if (state->windowBounds.x < 0) state->windowBounds.x = 0;
+ else if (state->windowBounds.x > (GetScreenWidth() - state->windowBounds.width)) state->windowBounds.x = GetScreenWidth() - state->windowBounds.width;
+
+ if (state->windowBounds.y < 0) state->windowBounds.y = 0;
+ else if (state->windowBounds.y > (GetScreenHeight() - state->windowBounds.height)) state->windowBounds.y = GetScreenHeight() - state->windowBounds.height;
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) state->dragMode = false;
+ }
+ }
+ //----------------------------------------------------------------------------------------
+
+ // Load dirFilesIcon and state->dirFiles lazily on windows open
+ // NOTE: They are automatically unloaded at fileDialog closing
+ //----------------------------------------------------------------------------------------
+ if (dirFilesIcon == NULL)
+ {
+ dirFilesIcon = (FileInfo *)RL_CALLOC(MAX_DIRECTORY_FILES, sizeof(FileInfo)); // Max files to read
+ for (int i = 0; i < MAX_DIRECTORY_FILES; i++) dirFilesIcon[i] = (char *)RL_CALLOC(MAX_ICON_PATH_LENGTH, 1); // Max file name length
+ }
+
+ // Load current directory files
+ if (state->dirFiles.paths == NULL) ReloadDirectoryFiles(state);
+ //----------------------------------------------------------------------------------------
+
+ // Draw window and controls
+ //----------------------------------------------------------------------------------------
+ state->windowActive = !GuiWindowBox(state->windowBounds, "#198# Select File Dialog");
+
+ // Draw previous directory button + logic
+ if (GuiButton((Rectangle){ state->windowBounds.x + state->windowBounds.width - 48, state->windowBounds.y + 24 + 12, 40, 24 }, "< .."))
+ {
+ // Move dir path one level up
+ strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
+
+ // Reload directory files (frees previous list)
+ ReloadDirectoryFiles(state);
+
+ state->filesListActive = -1;
+ memset(state->fileNameText, 0, 1024);
+ memset(state->fileNameTextCopy, 0, 1024);
+ }
+
+ // Draw current directory text box info + path editing logic
+ if (GuiTextBox((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + 24 + 12, state->windowBounds.width - 48 - 16, 24 }, state->dirPathText, 1024, state->dirPathEditMode))
+ {
+ if (state->dirPathEditMode)
+ {
+ // Verify if a valid path has been introduced
+ if (DirectoryExists(state->dirPathText))
+ {
+ // Reload directory files (frees previous list)
+ ReloadDirectoryFiles(state);
+
+ strcpy(state->dirPathTextCopy, state->dirPathText);
+ }
+ else strcpy(state->dirPathText, state->dirPathTextCopy);
+ }
+
+ state->dirPathEditMode = !state->dirPathEditMode;
+ }
+
+ // List view elements are aligned left
+ int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT);
+ int prevElementsHeight = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
+# if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
+ state->filesListActive = GuiListViewFiles((Rectangle){ state->position.x + 8, state->position.y + 48 + 20, state->windowBounds.width - 16, state->windowBounds.height - 60 - 16 - 68 }, fileInfo, state->dirFiles.count, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive);
+# else
+ GuiListViewEx((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + 48 + 20, state->windowBounds.width - 16, state->windowBounds.height - 60 - 16 - 68 },
+ (const char**)dirFilesIcon, state->dirFiles.count, &state->filesListScrollIndex, &state->filesListActive, &state->itemFocused);
+# endif
+ GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment);
+ GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight);
+
+ // Check if a path has been selected, if it is a directory, move to that directory (and reload paths)
+ if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive))
+ //&& (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_DPAD_A)))
+ {
+ strcpy(state->fileNameText, GetFileName(state->dirFiles.paths[state->filesListActive]));
+
+ if (DirectoryExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
+ {
+ if (TextIsEqual(state->fileNameText, "..")) strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
+ else strcpy(state->dirPathText, TextFormat("%s/%s", (strcmp(state->dirPathText, "/") == 0)? "" : state->dirPathText, state->fileNameText));
+
+ strcpy(state->dirPathTextCopy, state->dirPathText);
+
+ // Reload directory files (frees previous list)
+ ReloadDirectoryFiles(state);
+
+ strcpy(state->dirPathTextCopy, state->dirPathText);
+
+ state->filesListActive = -1;
+ strcpy(state->fileNameText, "\0");
+ strcpy(state->fileNameTextCopy, state->fileNameText);
+ }
+
+ state->prevFilesListActive = state->filesListActive;
+ }
+
+ // Draw bottom controls
+ //--------------------------------------------------------------------------------------
+ GuiLabel((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + state->windowBounds.height - 68, 60, 24 }, "File name:");
+ if (GuiTextBox((Rectangle){ state->windowBounds.x + 72, state->windowBounds.y + state->windowBounds.height - 68, state->windowBounds.width - 184, 24 }, state->fileNameText, 128, state->fileNameEditMode))
+ {
+ if (*state->fileNameText)
+ {
+ // Verify if a valid filename has been introduced
+ if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
+ {
+ // Select filename from list view
+ for (unsigned int i = 0; i < state->dirFiles.count; i++)
+ {
+ if (TextIsEqual(state->fileNameText, state->dirFiles.paths[i]))
+ {
+ state->filesListActive = i;
+ strcpy(state->fileNameTextCopy, state->fileNameText);
+ break;
+ }
+ }
+ }
+ else if (!state->saveFileMode)
+ {
+ strcpy(state->fileNameText, state->fileNameTextCopy);
+ }
+ }
+
+ state->fileNameEditMode = !state->fileNameEditMode;
+ }
+
+ GuiLabel((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + state->windowBounds.height - 24 - 12, 68, 24 }, "File filter:");
+ GuiComboBox((Rectangle){ state->windowBounds.x + 72, state->windowBounds.y + state->windowBounds.height - 24 - 12, state->windowBounds.width - 184, 24 }, "All files", &state->fileTypeActive);
+
+ state->SelectFilePressed = GuiButton((Rectangle){ state->windowBounds.x + state->windowBounds.width - 96 - 8, state->windowBounds.y + state->windowBounds.height - 68, 96, 24 }, "Select");
+
+ if (GuiButton((Rectangle){ state->windowBounds.x + state->windowBounds.width - 96 - 8, state->windowBounds.y + state->windowBounds.height - 24 - 12, 96, 24 }, "Cancel")) state->windowActive = false;
+ //--------------------------------------------------------------------------------------
+
+ // Exit on file selected
+ if (state->SelectFilePressed) state->windowActive = false;
+
+ // File dialog has been closed, free all memory before exit
+ if (!state->windowActive)
+ {
+ // Free dirFilesIcon memory
+ for (int i = 0; i < MAX_DIRECTORY_FILES; i++) RL_FREE(dirFilesIcon[i]);
+
+ RL_FREE(dirFilesIcon);
+ dirFilesIcon = NULL;
+
+ // Unload directory file paths
+ UnloadDirectoryFiles(state->dirFiles);
+
+ // Reset state variables
+ state->dirFiles.count = 0;
+ state->dirFiles.capacity = 0;
+ state->dirFiles.paths = NULL;
+ }
+ }
+}
+
+// Compare two files from a directory
+static inline int FileCompare(const char *d1, const char *d2, const char *dir)
+{
+ const bool b1 = DirectoryExists(TextFormat("%s/%s", dir, d1));
+ const bool b2 = DirectoryExists(TextFormat("%s/%s", dir, d2));
+
+ if (b1 && !b2) return -1;
+ if (!b1 && b2) return 1;
+
+ if (!FileExists(TextFormat("%s/%s", dir, d1))) return 1;
+ if (!FileExists(TextFormat("%s/%s", dir, d2))) return -1;
+
+ return strcmp(d1, d2);
+}
+
+// Read files in new path
+static void ReloadDirectoryFiles(GuiWindowFileDialogState *state)
+{
+ UnloadDirectoryFiles(state->dirFiles);
+
+ state->dirFiles = LoadDirectoryFilesEx(state->dirPathText, (state->filterExt[0] == '\0')? NULL : state->filterExt, false);
+ state->itemFocused = 0;
+
+ // Reset dirFilesIcon memory
+ for (int i = 0; i < MAX_DIRECTORY_FILES; i++) memset(dirFilesIcon[i], 0, MAX_ICON_PATH_LENGTH);
+
+ // Copy paths as icon + fileNames into dirFilesIcon
+ for (unsigned int i = 0; i < state->dirFiles.count; i++)
+ {
+ if (IsPathFile(state->dirFiles.paths[i]))
+ {
+ // Path is a file, a file icon for convenience (for some recognized extensions)
+ if (IsFileExtension(state->dirFiles.paths[i], ".png;.bmp;.tga;.gif;.jpg;.jpeg;.psd;.hdr;.qoi;.dds;.pkm;.ktx;.pvr;.astc"))
+ {
+ strcpy(dirFilesIcon[i], TextFormat("#12#%s", GetFileName(state->dirFiles.paths[i])));
+ }
+ else if (IsFileExtension(state->dirFiles.paths[i], ".wav;.mp3;.ogg;.flac;.xm;.mod;.it;.wma;.aiff"))
+ {
+ strcpy(dirFilesIcon[i], TextFormat("#11#%s", GetFileName(state->dirFiles.paths[i])));
+ }
+ else if (IsFileExtension(state->dirFiles.paths[i], ".txt;.info;.md;.nfo;.xml;.json;.c;.cpp;.cs;.lua;.py;.glsl;.vs;.fs"))
+ {
+ strcpy(dirFilesIcon[i], TextFormat("#10#%s", GetFileName(state->dirFiles.paths[i])));
+ }
+ else if (IsFileExtension(state->dirFiles.paths[i], ".exe;.bin;.raw;.msi"))
+ {
+ strcpy(dirFilesIcon[i], TextFormat("#200#%s", GetFileName(state->dirFiles.paths[i])));
+ }
+ else strcpy(dirFilesIcon[i], TextFormat("#218#%s", GetFileName(state->dirFiles.paths[i])));
+ }
+ else
+ {
+ // Path is a directory, add a directory icon
+ strcpy(dirFilesIcon[i], TextFormat("#1#%s", GetFileName(state->dirFiles.paths[i])));
+ }
+ }
+}
+
+#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
+// List View control for files info with extended parameters
+static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int *active)
+{
+ int result = 0;
+ GuiState state = guiState;
+ int itemFocused = (focus == NULL)? -1 : *focus;
+ int itemSelected = *active;
+
+ // Check if we need a scroll bar
+ bool useScrollBar = false;
+ if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING))*count > bounds.height) useScrollBar = true;
+
+ // Define base item rectangle [0]
+ Rectangle itemBounds = { 0 };
+ itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING);
+ itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ itemBounds.height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
+
+ // Get items on the list
+ int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
+ if (visibleItems > count) visibleItems = count;
+
+ int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
+ if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
+ int endIndex = startIndex + visibleItems;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != GUI_STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check mouse inside list view
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = GUI_STATE_FOCUSED;
+
+ // Check focused and selected item
+ for (int i = 0; i < visibleItems; i++)
+ {
+ if (CheckCollisionPointRec(mousePoint, itemBounds))
+ {
+ itemFocused = startIndex + i;
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i;
+ break;
+ }
+
+ // Update item rectangle y position for next item
+ itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
+ }
+
+ if (useScrollBar)
+ {
+ int wheelMove = GetMouseWheelMove();
+ startIndex -= wheelMove;
+
+ if (startIndex < 0) startIndex = 0;
+ else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
+
+ endIndex = startIndex + visibleItems;
+ if (endIndex > count) endIndex = count;
+ }
+ }
+ else itemFocused = -1;
+
+ // Reset item rectangle y to [0]
+ itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
+ DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha));
+
+ // TODO: Draw list view header with file sections: icon+name | size | type | modTime
+
+ // Draw visible items
+ for (int i = 0; i < visibleItems; i++)
+ {
+ if (state == GUI_STATE_DISABLED)
+ {
+ if ((startIndex + i) == itemSelected)
+ {
+ DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
+ DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), guiAlpha));
+ }
+
+ // TODO: Draw full file info line: icon+name | size | type | modTime
+
+ GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
+ }
+ else
+ {
+ if ((startIndex + i) == itemSelected)
+ {
+ // Draw item selected
+ DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
+ DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha));
+
+ GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha));
+ }
+ else if ((startIndex + i) == itemFocused)
+ {
+ // Draw item focused
+ DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
+ DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha));
+
+ GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha));
+ }
+ else
+ {
+ // Draw item normal
+ GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha));
+ }
+ }
+
+ // Update item rectangle y position for next item
+ itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
+ }
+
+ if (useScrollBar)
+ {
+ Rectangle scrollBarBounds = {
+ bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
+ bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
+ bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
+ };
+
+ // Calculate percentage of visible items and apply same percentage to scrollbar
+ float percentVisible = (float)(endIndex - startIndex)/count;
+ float sliderSize = bounds.height*percentVisible;
+
+ int prevSliderSize = GuiGetStyle(SCROLLBAR, SLIDER_WIDTH); // Save default slider size
+ int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
+ GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, sliderSize); // Change slider size
+ GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
+
+ startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
+
+ GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
+ GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, prevSliderSize); // Reset slider size to default
+ }
+ //--------------------------------------------------------------------
+
+ if (focus != NULL) *focus = itemFocused;
+ if (scrollIndex != NULL) *scrollIndex = startIndex;
+
+ *active = itemSelected;
+ return result;
+}
+#endif // USE_CUSTOM_LISTVIEW_FILEINFO
+
+#endif // GUI_FILE_DIALOG_IMPLEMENTATION
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_input_box/custom_input_box.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_input_box/custom_input_box.c
new file mode 100644
index 0000000000..18b7ffcf93
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_input_box/custom_input_box.c
@@ -0,0 +1,223 @@
+/*******************************************************************************************
+*
+* raygui - basic calculator app with custom input box for float values
+*
+* DEPENDENCIES:
+* raylib 4.5 - Windowing/input management and drawing.
+* raygui 3.5 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+int guiFloatingPointIndex = 0; // Global variable shared by all GuiFloatBox()
+
+int GuiFloatBox(Rectangle bounds, const char* text, float* value, int minValue, int maxValue, bool editMode); // Custom input box that works with float values. Basicly GuiValueBox(), but with some changes
+
+int main()
+{
+ InitWindow(250, 100, "Basic calculator");
+
+ // General variables
+ SetTargetFPS(60);
+
+ float variableA = 0.0f;
+ float variableB = 0.0f;
+ float result = 0.0f;
+ char operation[2];
+ operation[0] = '+';
+ operation[1] = '\0';
+
+ bool variableAMode = false;
+ bool variableBMode = false;
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose())
+ {
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (GuiFloatBox((Rectangle){ 10, 10, 100, 20 }, NULL, &variableA, -1000000.0, 1000000.0, variableAMode)) variableAMode = !variableAMode;
+ if (GuiFloatBox((Rectangle){ 140, 10, 100, 20 }, NULL, &variableB, -1000000.0, 1000000.0, variableBMode)) variableBMode = !variableBMode;
+
+ if (GuiButton((Rectangle){ 10, 70, 50, 20 }, "+"))
+ {
+ result = variableA + variableB;
+ operation[0] = '+';
+ }
+ if (GuiButton((Rectangle){ 70, 70, 50, 20 }, "-"))
+ {
+ result = variableA - variableB;
+ operation[0] = '-';
+ }
+ if (GuiButton((Rectangle){ 130, 70, 50, 20 }, "*"))
+ {
+ result = variableA * variableB;
+ operation[0] = '*';
+ }
+ if (GuiButton((Rectangle){ 190, 70, 50, 20 }, "/"))
+ {
+ result = variableA / variableB;
+ operation[0] = '/';
+ }
+
+ DrawText(operation, 123, 15, 10, DARKGRAY);
+
+ GuiFloatBox((Rectangle){ 55, 40, 135, 20 }, "= ", &result, -2000000.0, 2000000.0, false);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ CloseWindow();
+}
+
+// Float Box control, updates input text with numbers
+int GuiFloatBox(Rectangle bounds, const char* text, float* value, int minValue, int maxValue, bool editMode)
+{
+#if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
+#define RAYGUI_VALUEBOX_MAX_CHARS 32
+#endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
+
+ Rectangle textBounds = { 0 };
+ if (text != NULL)
+ {
+ textBounds.width = (float)GuiGetTextWidth(text) + 2;
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height / 2.0f - GuiGetStyle(DEFAULT, TEXT_SIZE) / 2.0f;
+ if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (*value >= 0) sprintf(textValue, "+%.3f", *value);
+ else sprintf(textValue, "%.3f", *value);
+
+ bool valueHasChanged = false;
+
+ int keyCount = (int)strlen(textValue) - guiFloatingPointIndex;
+
+ if (editMode)
+ {
+ state = STATE_PRESSED;
+
+ // Only allow keys in range [48..57]
+ if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
+ {
+ if (GuiGetTextWidth(textValue) < bounds.width)
+ {
+ int key = GetCharPressed();
+ if ((key >= 48) && (key <= 57) && guiFloatingPointIndex)
+ {
+ if (guiFloatingPointIndex && guiFloatingPointIndex != 4) guiFloatingPointIndex--;
+
+ textValue[keyCount] = (char)key;
+ textValue[++keyCount] = '\0';
+ valueHasChanged = true;
+ }
+ }
+ }
+
+ // Delete text
+ if (keyCount > 0)
+ {
+ if (IsKeyPressed(KEY_BACKSPACE))
+ {
+ if (guiFloatingPointIndex < 4) guiFloatingPointIndex++;
+
+ keyCount--;
+ textValue[keyCount] = '\0';
+ valueHasChanged = true;
+ }
+ }
+
+ // Change sign
+ if (IsKeyPressed(KEY_MINUS))
+ {
+ if (textValue[0] == '+') textValue[0] = '-';
+ else if (textValue[0] == '-') textValue[0] = '+';
+ valueHasChanged = true;
+ }
+
+ // Add decimal separator
+ if ((IsKeyPressed(KEY_COMMA) || IsKeyPressed(KEY_PERIOD)) && guiFloatingPointIndex == 4)
+ {
+ guiFloatingPointIndex--;
+ valueHasChanged = true;
+ }
+
+ if (valueHasChanged)
+ {
+ *value = atof(textValue);
+ }
+
+ if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ guiFloatingPointIndex = 0;
+ result = 1;
+ }
+ }
+ else
+ {
+ if (*value > maxValue) *value = maxValue;
+ else if (*value < minValue) *value = minValue;
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ Color baseColor = BLANK;
+ sprintf(textValue, "%.3f", *value);
+
+ if (state == STATE_PRESSED)
+ {
+ baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
+ textValue[(int)strlen(textValue) - guiFloatingPointIndex] = '\0';
+ }
+ else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
+
+ // WARNING: BLANK color does not work properly with Fade()
+ GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state * 3))), guiAlpha), baseColor);
+ GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state * 3))), guiAlpha));
+
+ // Draw cursor
+ if (editMode)
+ {
+ // NOTE: ValueBox internal text is always centered
+ Rectangle cursor = { bounds.x + GuiGetTextWidth(textValue) / 2.0f + bounds.width / 2.0f + 1, bounds.y + 2.0f * GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, bounds.height - 4 * GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
+ GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+ }
+
+ // Draw text label if provided
+ GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state * 3))), guiAlpha));
+ //--------------------------------------------------------------------
+
+ return result;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_sliders/custom_sliders.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_sliders/custom_sliders.c
new file mode 100644
index 0000000000..ecd7e27b54
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/custom_sliders/custom_sliders.c
@@ -0,0 +1,470 @@
+/*******************************************************************************************
+*
+* raygui - custom sliders
+*
+* DEPENDENCIES:
+* raylib 4.0 - Windowing/input management and drawing.
+* raygui 3.0 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+//----------------------------------------------------------------------------------
+// Controls Functions Declaration
+//----------------------------------------------------------------------------------
+float GuiVerticalSlider(Rectangle bounds, const char *textTop, const char *textBottom, float value, float minValue, float maxValue);
+float GuiVerticalSliderBar(Rectangle bounds, const char *textTop, const char *textBottom, float value, float minValue, float maxValue);
+float GuiVerticalSliderPro(Rectangle bounds, const char *textTop, const char *textBottom, float value, float minValue, float maxValue, int sliderHeight);
+
+bool GuiSliderOwning(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, bool editMode);
+bool GuiSliderBarOwning(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, bool editMode);
+bool GuiSliderProOwning(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth, bool editMode);
+
+bool GuiVerticalSliderOwning(Rectangle bounds, const char *textTop, const char *textBottom, float *value, float minValue, float maxValue, bool editMode);
+bool GuiVerticalSliderBarOwning(Rectangle bounds, const char *textTop, const char *textBottom, float *value, float minValue, float maxValue, bool editMode);
+bool GuiVerticalSliderProOwning(Rectangle bounds, const char *textTop, const char *textBottom, float *value, float minValue, float maxValue, int sliderHeight, bool editMode);
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ int screenWidth = 800;
+ int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raygui - custom sliders");
+
+ float value = 0.5f;
+ bool sliderEditMode = false;
+ bool vSliderEditMode = false;
+ bool vSliderBarEditMode = false;
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ // TODO: Implement required update logic
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ if (vSliderEditMode || vSliderBarEditMode) GuiLock();
+ else GuiUnlock();
+
+ // raygui: controls drawing
+ //----------------------------------------------------------------------------------
+ GuiGroupBox((Rectangle){ 66, 24, 276, 312 }, "STANDARD");
+ GuiSlider((Rectangle){ 96, 48, 216, 16 }, TextFormat("%0.2f", value), NULL, &value, 0.0f, 1.0f);
+ value = GuiVerticalSlider((Rectangle){ 120, 120, 24, 192 }, TextFormat("%0.2f", value), NULL, value, 0.0f, 1.0f);
+ value = GuiVerticalSliderBar((Rectangle){ 264, 120, 24, 192 }, TextFormat("%0.2f", value), NULL, value, 0.0f, 1.0f);
+
+ GuiGroupBox((Rectangle){ 378, 24, 276, 312 }, "OWNING");
+ if (GuiSliderOwning((Rectangle){ 408, 48, 216, 16 }, NULL, TextFormat("%0.2f", value), &value, 0.0f, 1.0f, sliderEditMode)) sliderEditMode = !sliderEditMode;
+ if (GuiVerticalSliderOwning((Rectangle){ 432, 120, 24, 192 }, NULL, TextFormat("%0.2f", value), &value, 0.0f, 1.0f, vSliderEditMode)) vSliderEditMode = !vSliderEditMode;
+ if (GuiVerticalSliderBarOwning((Rectangle){ 576, 120, 24, 192 }, NULL, TextFormat("%0.2f", value), &value, 0.0f, 1.0f, vSliderBarEditMode)) vSliderBarEditMode = !vSliderBarEditMode;
+ //----------------------------------------------------------------------------------
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Controls Functions Definitions (local)
+//------------------------------------------------------------------------------------
+float GuiVerticalSliderPro(Rectangle bounds, const char *textTop, const char *textBottom, float value, float minValue, float maxValue, int sliderHeight)
+{
+ GuiState state = (GuiState)GuiGetState();
+
+ int sliderValue = (int)(((value - minValue)/(maxValue - minValue)) * (bounds.height - 2 * GuiGetStyle(SLIDER, BORDER_WIDTH)));
+
+ Rectangle slider = {
+ bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
+ bounds.y + bounds.height - sliderValue,
+ bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING),
+ 0.0f,
+ };
+
+ if (sliderHeight > 0) // Slider
+ {
+ slider.y -= sliderHeight/2;
+ slider.height = (float)sliderHeight;
+ }
+ else if (sliderHeight == 0) // SliderBar
+ {
+ slider.y -= GuiGetStyle(SLIDER, BORDER_WIDTH);
+ slider.height = (float)sliderValue;
+ }
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+
+ // Get equivalent value and slider position from mousePoint.x
+ float normalizedValue = (bounds.y + bounds.height - mousePoint.y - (float)(sliderHeight / 2)) / (bounds.height - (float)sliderHeight);
+ value = (maxValue - minValue) * normalizedValue + minValue;
+
+ if (sliderHeight > 0) slider.y = mousePoint.y - slider.height / 2; // Slider
+ else if (sliderHeight == 0) // SliderBar
+ {
+ slider.y = mousePoint.y;
+ slider.height = bounds.y + bounds.height - slider.y - GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ }
+ else state = STATE_FOCUSED;
+ }
+
+ if (value > maxValue) value = maxValue;
+ else if (value < minValue) value = minValue;
+ }
+
+
+ // Bar limits check
+ if (sliderHeight > 0) // Slider
+ {
+ if (slider.y < (bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.y = bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH);
+ else if ((slider.y + slider.height) >= (bounds.y + bounds.height)) slider.y = bounds.y + bounds.height - slider.height - GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ else if (sliderHeight == 0) // SliderBar
+ {
+ if (slider.y < (bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH)))
+ {
+ slider.y = bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH);
+ slider.height = bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
+
+ // Draw slider internal bar (depends on state)
+ if ((state == STATE_NORMAL) || (state == STATE_PRESSED)) GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)), guiAlpha));
+ else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)), guiAlpha));
+
+ // Draw top/bottom text if provided
+ if (textTop != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textTop);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width/2 - textBounds.width/2;
+ textBounds.y = bounds.y - textBounds.height - GuiGetStyle(SLIDER, TEXT_PADDING);
+
+ GuiDrawText(textTop, textBounds, TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ }
+
+ if (textBottom != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textBottom);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width/2 - textBounds.width/2;
+ textBounds.y = bounds.y + bounds.height + GuiGetStyle(SLIDER, TEXT_PADDING);
+
+ GuiDrawText(textBottom, textBounds, TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ }
+ //--------------------------------------------------------------------
+
+ return value;
+}
+
+float GuiVerticalSlider(Rectangle bounds, const char *textTop, const char *textBottom, float value, float minValue, float maxValue)
+{
+ return GuiVerticalSliderPro(bounds, textTop, textBottom, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH));
+}
+
+float GuiVerticalSliderBar(Rectangle bounds, const char *textTop, const char *textBottom, float value, float minValue, float maxValue)
+{
+ return GuiVerticalSliderPro(bounds, textTop, textBottom, value, minValue, maxValue, 0);
+}
+
+bool GuiSliderProOwning(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth, bool editMode)
+{
+ GuiState state = (GuiState)GuiGetState();
+
+ float tempValue = *value;
+ bool pressed = false;
+
+ int sliderValue = (int)(((tempValue - minValue)/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));
+
+ Rectangle slider = {
+ bounds.x,
+ bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
+ 0,
+ bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING)
+ };
+
+ if (sliderWidth > 0) // Slider
+ {
+ slider.x += (sliderValue - sliderWidth/2);
+ slider.width = (float)sliderWidth;
+ }
+ else if (sliderWidth == 0) // SliderBar
+ {
+ slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);
+ slider.width = (float)sliderValue;
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && (editMode || !guiLocked))
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ pressed = true;
+ }
+ }
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON) && editMode)
+ {
+ pressed = true;
+ }
+ if (editMode)
+ {
+ state = STATE_PRESSED;
+ tempValue = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
+
+ if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2; // Slider
+ else if (sliderWidth == 0) slider.width = (float)sliderValue; // SliderBar
+
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+ }
+
+ if (tempValue > maxValue) tempValue = maxValue;
+ else if (tempValue < minValue) tempValue = minValue;
+ }
+
+
+ // Bar limits check
+ if (sliderWidth > 0) // Slider
+ {
+ if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH);
+ else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ else if (sliderWidth == 0) // SliderBar
+ {
+ if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+
+ //--------------------------------------------------------------------
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
+
+ // Draw slider internal bar (depends on state)
+ if ((state == STATE_NORMAL) || (state == STATE_PRESSED))
+ GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)), guiAlpha));
+ else if (state == STATE_FOCUSED)
+ GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)), guiAlpha));
+
+ // Draw left/right text if provided
+ if (textLeft != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textLeft);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ }
+
+ if (textRight != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textRight);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ }
+ //--------------------------------------------------------------------
+
+ *value = tempValue;
+ return pressed;
+}
+
+bool GuiSliderOwning(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, bool editMode)
+{
+ return GuiSliderProOwning(bounds, textLeft, textRight, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH), editMode);
+}
+
+bool GuiSliderBarOwning(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, bool editMode)
+{
+ return GuiSliderProOwning(bounds, textLeft, textRight, value, minValue, maxValue, 0, editMode);
+}
+
+bool GuiVerticalSliderProOwning(Rectangle bounds, const char *textTop, const char *textBottom, float *value, float minValue, float maxValue, int sliderHeight, bool editMode)
+{
+ GuiState state = (GuiState)GuiGetState();
+
+ float tempValue = *value;
+ bool pressed = false;
+
+ int sliderValue = (int)(((tempValue - minValue)/(maxValue - minValue)) * (bounds.height - 2 * GuiGetStyle(SLIDER, BORDER_WIDTH)));
+
+ Rectangle slider = {
+ bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
+ bounds.y + bounds.height - sliderValue,
+ bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING),
+ 0.0f,
+ };
+
+ if (sliderHeight > 0) // Slider
+ {
+ slider.y -= sliderHeight/2;
+ slider.height = (float)sliderHeight;
+ }
+ else if (sliderHeight == 0) // SliderBar
+ {
+ slider.y -= GuiGetStyle(SLIDER, BORDER_WIDTH);
+ slider.height = (float)sliderValue;
+ }
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && (editMode || !guiLocked))
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ pressed = true;
+ }
+ }
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON) && editMode)
+ {
+ pressed = true;
+ }
+ if (editMode)
+ {
+ state = STATE_PRESSED;
+
+ float normalizedValue = (bounds.y + bounds.height - mousePoint.y - (float)(sliderHeight / 2)) / (bounds.height - (float)sliderHeight);
+ tempValue = (maxValue - minValue) * normalizedValue + minValue;
+
+ if (sliderHeight > 0) slider.y = mousePoint.y - slider.height / 2; // Slider
+ else if (sliderHeight == 0) // SliderBar
+ {
+ slider.y = mousePoint.y;
+ slider.height = bounds.y + bounds.height - slider.y - GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+ }
+
+ if (tempValue > maxValue) tempValue = maxValue;
+ else if (tempValue < minValue) tempValue = minValue;
+ }
+
+
+ // Bar limits check
+ if (sliderHeight > 0) // Slider
+ {
+ if (slider.y < (bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.y = bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH);
+ else if ((slider.y + slider.height) >= (bounds.y + bounds.height)) slider.y = bounds.y + bounds.height - slider.height - GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ else if (sliderHeight == 0) // SliderBar
+ {
+ if (slider.y < (bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH)))
+ {
+ slider.y = bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH);
+ slider.height = bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
+
+ // Draw slider internal bar (depends on state)
+ if ((state == STATE_NORMAL) || (state == STATE_PRESSED))
+ GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)), guiAlpha));
+ else if (state == STATE_FOCUSED)
+ GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)), guiAlpha));
+
+ // Draw top/bottom text if provided
+ if (textTop != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textTop);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width/2 - textBounds.width/2;
+ textBounds.y = bounds.y - textBounds.height - GuiGetStyle(SLIDER, TEXT_PADDING);
+
+ GuiDrawText(textTop, textBounds, TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ }
+
+ if (textBottom != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textBottom);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width/2 - textBounds.width/2;
+ textBounds.y = bounds.y + bounds.height + GuiGetStyle(SLIDER, TEXT_PADDING);
+
+ GuiDrawText(textBottom, textBounds, TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ }
+ //--------------------------------------------------------------------
+
+ *value = tempValue;
+ return pressed;
+}
+
+bool GuiVerticalSliderOwning(Rectangle bounds, const char *textTop, const char *textBottom, float *value, float minValue, float maxValue, bool editMode)
+{
+ return GuiVerticalSliderProOwning(bounds, textTop, textBottom, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH), editMode);
+}
+
+bool GuiVerticalSliderBarOwning(Rectangle bounds, const char *textTop, const char *textBottom, float *value, float minValue, float maxValue, bool editMode)
+{
+ return GuiVerticalSliderProOwning(bounds, textTop, textBottom, value, minValue, maxValue, 0, editMode);
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/floating_window/floating_window.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/floating_window/floating_window.c
new file mode 100644
index 0000000000..df6bc311a1
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/floating_window/floating_window.c
@@ -0,0 +1,148 @@
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+#include "../../styles/dark/style_dark.h"
+
+static Vector2 window_position = { 10, 10 };
+static Vector2 window_size = { 200, 400 };
+static bool minimized = false;
+static bool moving = false;
+static bool resizing = false;
+static Vector2 scroll;
+
+static Vector2 window2_position = { 250, 10 };
+static Vector2 window2_size = { 200, 400 };
+static bool minimized2 = false;
+static bool moving2 = false;
+static bool resizing2 = false;
+static Vector2 scroll2;
+
+void GuiWindowFloating(Vector2 *position, Vector2 *size, bool *minimized, bool *moving, bool *resizing, void (*draw_content)(Vector2, Vector2), Vector2 content_size, Vector2 *scroll, const char* title) {
+ #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)
+ #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
+ #endif
+
+ #if !defined(RAYGUI_WINDOW_CLOSEBUTTON_SIZE)
+ #define RAYGUI_WINDOW_CLOSEBUTTON_SIZE 18
+ #endif
+
+ int close_title_size_delta_half = (RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_WINDOW_CLOSEBUTTON_SIZE) / 2;
+
+ // window movement and resize input and collision check
+ if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && !*moving && !*resizing) {
+ Vector2 mouse_position = GetMousePosition();
+
+ Rectangle title_collision_rect = { position->x, position->y, size->x - (RAYGUI_WINDOW_CLOSEBUTTON_SIZE + close_title_size_delta_half), RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
+ Rectangle resize_collision_rect = { position->x + size->x - 20, position->y + size->y - 20, 20, 20 };
+
+ if(CheckCollisionPointRec(mouse_position, title_collision_rect)) {
+ *moving = true;
+ } else if(!*minimized && CheckCollisionPointRec(mouse_position, resize_collision_rect)) {
+ *resizing = true;
+ }
+ }
+
+ // window movement and resize update
+ if(*moving) {
+ Vector2 mouse_delta = GetMouseDelta();
+ position->x += mouse_delta.x;
+ position->y += mouse_delta.y;
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
+ *moving = false;
+
+ // clamp window position keep it inside the application area
+ if(position->x < 0) position->x = 0;
+ else if(position->x > GetScreenWidth() - size->x) position->x = GetScreenWidth() - size->x;
+ if(position->y < 0) position->y = 0;
+ else if(position->y > GetScreenHeight()) position->y = GetScreenHeight() - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT;
+ }
+
+ } else if(*resizing) {
+ Vector2 mouse = GetMousePosition();
+ if (mouse.x > position->x)
+ size->x = mouse.x - position->x;
+ if (mouse.y > position->y)
+ size->y = mouse.y - position->y;
+
+ // clamp window size to an arbitrary minimum value and the window size as the maximum
+ if(size->x < 100) size->x = 100;
+ else if(size->x > GetScreenWidth()) size->x = GetScreenWidth();
+ if(size->y < 100) size->y = 100;
+ else if(size->y > GetScreenHeight()) size->y = GetScreenHeight();
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
+ *resizing = false;
+ }
+ }
+
+ // window and content drawing with scissor and scroll area
+ if(*minimized) {
+ GuiStatusBar((Rectangle){ position->x, position->y, size->x, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }, title);
+
+ if (GuiButton((Rectangle){ position->x + size->x - RAYGUI_WINDOW_CLOSEBUTTON_SIZE - close_title_size_delta_half,
+ position->y + close_title_size_delta_half,
+ RAYGUI_WINDOW_CLOSEBUTTON_SIZE,
+ RAYGUI_WINDOW_CLOSEBUTTON_SIZE },
+ "#120#")) {
+ *minimized = false;
+ }
+
+ } else {
+ *minimized = GuiWindowBox((Rectangle) { position->x, position->y, size->x, size->y }, title);
+
+ // scissor and draw content within a scroll panel
+ if(draw_content != NULL) {
+ Rectangle scissor = { 0 };
+ GuiScrollPanel((Rectangle) { position->x, position->y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, size->x, size->y - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT },
+ NULL,
+ (Rectangle) { position->x, position->y, content_size.x, content_size.y },
+ scroll,
+ &scissor);
+
+ bool require_scissor = size->x < content_size.x || size->y < content_size.y;
+
+ if(require_scissor) {
+ BeginScissorMode(scissor.x, scissor.y, scissor.width, scissor.height);
+ }
+
+ draw_content(*position, *scroll);
+
+ if(require_scissor) {
+ EndScissorMode();
+ }
+ }
+
+ // draw the resize button/icon
+ GuiDrawIcon(71, position->x + size->x - 20, position->y + size->y - 20, 1, WHITE);
+ }
+}
+
+static void DrawContent(Vector2 position, Vector2 scroll) {
+ GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 50 + scroll.y, 100, 25 }, "Button 1");
+ GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 100 + scroll.y, 100, 25 }, "Button 2");
+ GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 150 + scroll.y, 100, 25 }, "Button 3");
+ GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 200 + scroll.y, 250, 25 }, "A Label");
+ GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 250 + scroll.y, 250, 25 }, "Another Label");
+ GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 300 + scroll.y, 250, 25 }, "Yet Another Label");
+}
+
+int main(void) {
+ InitWindow(960, 560, "raygui - floating window example");
+ SetTargetFPS(60);
+ GuiLoadStyleDark();
+
+ while(!WindowShouldClose()) {
+ BeginDrawing();
+ ClearBackground(DARKGREEN);
+ GuiWindowFloating(&window_position, &window_size, &minimized, &moving, &resizing, &DrawContent, (Vector2) { 140, 320 }, &scroll, "Movable & Scalable Window");
+ GuiWindowFloating(&window2_position, &window2_size, &minimized2, &moving2, &resizing2, &DrawContent, (Vector2) { 140, 320 }, &scroll2, "Another window");
+ EndDrawing();
+ }
+
+ CloseWindow();
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/image_exporter.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/image_exporter.c
new file mode 100644
index 0000000000..cf5cd580f8
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/image_exporter.c
@@ -0,0 +1,192 @@
+/*******************************************************************************************
+*
+* raygui - image exporter
+*
+* DEPENDENCIES:
+* raylib 4.0 - Windowing/input management and drawing.
+* raygui 3.0 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raygui - image exporter");
+
+ // GUI controls initialization
+ //----------------------------------------------------------------------------------
+ Rectangle windowBoxRec = { screenWidth/2 - 110, screenHeight/2 - 100, 220, 190 };
+ bool windowBoxActive = false;
+
+ int fileFormatActive = 0;
+ const char *fileFormatTextList[3] = { "IMAGE (.png)", "DATA (.raw)", "CODE (.h)" };
+
+ int pixelFormatActive = 0;
+ const char *pixelFormatTextList[7] = { "GRAYSCALE", "GRAY ALPHA", "R5G6B5", "R8G8B8", "R5G5B5A1", "R4G4B4A4", "R8G8B8A8" };
+
+ bool textBoxEditMode = false;
+ char fileName[64] = "untitled";
+ //--------------------------------------------------------------------------------------
+
+ Image image = { 0 };
+ Texture2D texture = { 0 };
+
+ bool imageLoaded = false;
+ float imageScale = 1.0f;
+ Rectangle imageRec = { 0 };
+
+ bool btnExportPressed = false;
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ if (IsFileDropped())
+ {
+ FilePathList droppedFiles = LoadDroppedFiles();
+
+ if (droppedFiles.count == 1)
+ {
+ Image imTemp = LoadImage(droppedFiles.paths[0]);
+
+ if (imTemp.data != NULL)
+ {
+ UnloadImage(image);
+ image = imTemp;
+
+ UnloadTexture(texture);
+ texture = LoadTextureFromImage(image);
+
+ imageLoaded = true;
+ pixelFormatActive = image.format - 1;
+
+ if (texture.height > texture.width) imageScale = (float)(screenHeight - 100)/(float)texture.height;
+ else imageScale = (float)(screenWidth - 100)/(float)texture.width;
+ }
+ }
+
+ UnloadDroppedFiles(droppedFiles);
+ }
+
+ if (btnExportPressed)
+ {
+ if (imageLoaded)
+ {
+ ImageFormat(&image, pixelFormatActive + 1);
+
+ if (fileFormatActive == 0) // PNG
+ {
+ if ((GetFileExtension(fileName) == NULL) || (!IsFileExtension(fileName, ".png"))) strcat(fileName, ".png\0"); // No extension provided
+ ExportImage(image, fileName);
+ }
+ else if (fileFormatActive == 1) // RAW
+ {
+ if ((GetFileExtension(fileName) == NULL) || (!IsFileExtension(fileName, ".raw"))) strcat(fileName, ".raw\0"); // No extension provided
+
+ int dataSize = GetPixelDataSize(image.width, image.height, image.format);
+
+ FILE *rawFile = fopen(fileName, "wb");
+ fwrite(image.data, 1, dataSize, rawFile);
+ fclose(rawFile);
+ }
+ else if (fileFormatActive == 2) // CODE
+ {
+ ExportImageAsCode(image, fileName);
+ }
+ }
+
+ windowBoxActive = false;
+ }
+
+ if (imageLoaded)
+ {
+ imageScale += (float)GetMouseWheelMove()*0.05f; // Image scale control
+ if (imageScale <= 0.1f) imageScale = 0.1f;
+ else if (imageScale >= 5) imageScale = 5;
+
+ imageRec = (Rectangle){ screenWidth/2 - (float)image.width*imageScale/2,
+ screenHeight/2 - (float)image.height*imageScale/2,
+ (float)image.width*imageScale, (float)image.height*imageScale };
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (texture.id > 0)
+ {
+ DrawTextureEx(texture, (Vector2){ screenWidth/2 - (float)texture.width*imageScale/2, screenHeight/2 - (float)texture.height*imageScale/2 }, 0.0f, imageScale, WHITE);
+
+ DrawRectangleLinesEx(imageRec, 1, CheckCollisionPointRec(GetMousePosition(), imageRec) ? RED : DARKGRAY);
+ DrawText(TextFormat("SCALE: %.2f%%", imageScale*100.0f), 20, screenHeight - 40, 20, GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)));
+ }
+ else
+ {
+ DrawText("DRAG & DROP YOUR IMAGE!", 350, 200, 10, DARKGRAY);
+ GuiDisable();
+ }
+
+ if (GuiButton((Rectangle){ screenWidth - 170, screenHeight - 50, 150, 30 }, "Image Export")) windowBoxActive = true;
+ GuiEnable();
+
+ // Draw window box: windowBoxName
+ //-----------------------------------------------------------------------------
+ if (windowBoxActive)
+ {
+ DrawRectangle(0, 0, screenWidth, screenHeight, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), 0.7f));
+ windowBoxActive = !GuiWindowBox((Rectangle){ windowBoxRec.x, windowBoxRec.y, 220, 190 }, "Image Export Options");
+
+ GuiLabel((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 35, 60, 25 }, "File format:");
+ GuiComboBox((Rectangle){ windowBoxRec.x + 80, windowBoxRec.y + 35, 130, 25 }, TextJoin(fileFormatTextList, 3, ";"), &fileFormatActive);
+ GuiLabel((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 70, 63, 25 }, "Pixel format:");
+ GuiComboBox((Rectangle){ windowBoxRec.x + 80, windowBoxRec.y + 70, 130, 25 }, TextJoin(pixelFormatTextList, 7, ";"), &pixelFormatActive);
+ GuiLabel((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 105, 50, 25 }, "File name:");
+ if (GuiTextBox((Rectangle){ windowBoxRec.x + 80, windowBoxRec.y + 105, 130, 25 }, fileName, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
+
+ btnExportPressed = GuiButton((Rectangle){ windowBoxRec.x + 10, windowBoxRec.y + 145, 200, 30 }, "Export Image");
+ }
+ else btnExportPressed = false;
+
+ if (btnExportPressed) DrawText("Image exported!", 20, screenHeight - 20, 20, RED);
+ //-----------------------------------------------------------------------------
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadImage(image);
+ UnloadTexture(texture);
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/cat.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/cat.png
new file mode 100644
index 0000000000..d023aa2185
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/cat.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/fudesumi.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/fudesumi.png
new file mode 100644
index 0000000000..9d9038fa22
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/fudesumi.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/parrots.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/parrots.png
new file mode 100644
index 0000000000..d6ec60ba36
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/parrots.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/scarfy.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/scarfy.png
new file mode 100644
index 0000000000..4803ef7778
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_exporter/resources/scarfy.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REF.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REF.png
new file mode 100644
index 0000000000..6f16441cd7
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REF.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV0.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV0.png
new file mode 100644
index 0000000000..884b09689e
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV0.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV1.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV1.png
new file mode 100644
index 0000000000..39b1b7211f
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV1.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV2.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV2.png
new file mode 100644
index 0000000000..0797528fa0
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV2.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV3.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV3.png
new file mode 100644
index 0000000000..f396f6cce6
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV3.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV4.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV4.png
new file mode 100644
index 0000000000..b128a62538
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV4.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV5.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV5.png
new file mode 100644
index 0000000000..3f5e012987
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/design/raw_importer_REV5.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/image_2x2_RGBA.raw b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/image_2x2_RGBA.raw
new file mode 100644
index 0000000000..1aa92cd865
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/image_2x2_RGBA.raw differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/image_importer_raw.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/image_importer_raw.c
new file mode 100644
index 0000000000..4f860820e5
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/image_importer_raw/image_importer_raw.c
@@ -0,0 +1,228 @@
+/*******************************************************************************************
+*
+* raygui - image raw importer
+*
+* DEPENDENCIES:
+* raylib 4.0 - Windowing/input management and drawing.
+* raygui 3.0 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+#include // Required for: strcpy()
+#include // Required for: atoi()
+#include // Required for: round()
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 600;
+
+ InitWindow(screenWidth, screenHeight, "raygui - image raw importer");
+
+ Texture2D texture = { 0 };
+
+ // GUI controls initialization
+ //----------------------------------------------------------------------------------
+ Vector2 windowOffset = { screenWidth/2 - 200/2, screenHeight/2 - 465/2 };
+
+ bool importWindowActive = false;
+
+ int widthValue = 0;
+ bool widthEditMode = false;
+ int heightValue = 0;
+ bool heightEditMode = false;
+
+ int pixelFormatActive = 0;
+ const char *pixelFormatTextList[8] = { "CUSTOM", "GRAYSCALE", "GRAY ALPHA", "R5G6B5", "R8G8B8", "R5G5B5A1", "R4G4B4A4", "R8G8B8A8" };
+
+ int channelsActive = 3;
+ const char *channelsTextList[4] = { "1", "2", "3", "4" };
+ int bitDepthActive = 0;
+ const char *bitDepthTextList[3] = { "8", "16", "32" };
+
+ int headerSizeValue = 0;
+ bool headerSizeEditMode = false;
+ //----------------------------------------------------------------------------------
+
+ // Image file info
+ int dataSize = 0;
+ char fileNamePath[256] = "\0";
+ char fileName[64] = "\0";
+
+ bool btnLoadPressed = false;
+
+ bool imageLoaded = false;
+ float imageScale = 1.0f;
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ // Check if a file is dropped
+ if (IsFileDropped())
+ {
+ FilePathList droppedFiles = LoadDroppedFiles();
+
+ // Check file extensions for drag-and-drop
+ if ((droppedFiles.count == 1) && IsFileExtension(droppedFiles.paths[0], ".raw"))
+ {
+ FILE *imageFile = fopen(droppedFiles.paths[0], "rb");
+ fseek(imageFile, 0L, SEEK_END);
+ dataSize = ftell(imageFile);
+ fclose(imageFile);
+
+ // NOTE: Returned string is just a pointer to droppedFiles[0],
+ // we need to make a copy of that data somewhere else: fileName
+ strcpy(fileNamePath, droppedFiles.paths[0]);
+ strcpy(fileName, GetFileName(droppedFiles.paths[0]));
+
+ // Try to guess possible raw values
+ // Let's assume image is square, RGBA, 8 bit per channel
+ widthValue = round(sqrt(dataSize/4));
+ heightValue = widthValue;
+ headerSizeValue = dataSize - widthValue*heightValue*4;
+ if (headerSizeValue < 0) headerSizeValue = 0;
+
+ importWindowActive = true;
+ }
+
+ UnloadDroppedFiles(droppedFiles);
+ }
+
+ // Check if load button has been pressed
+ if (btnLoadPressed)
+ {
+ // Depending on channels and bit depth, select correct pixel format
+ if ((widthValue != 0) && (heightValue != 0))
+ {
+ int format = -1;
+
+ if (pixelFormatActive == 0)
+ {
+ int channels = atoi(channelsTextList[channelsActive]);
+ int bpp = atoi(bitDepthTextList[bitDepthActive]);
+
+ // Select correct format depending on channels and bpp
+ if (bpp == 8)
+ {
+ if (channels == 1) format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
+ else if (channels == 2) format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
+ else if (channels == 3) format = PIXELFORMAT_UNCOMPRESSED_R8G8B8;
+ else if (channels == 4) format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
+ }
+ else if (bpp == 32)
+ {
+ if (channels == 1) format = PIXELFORMAT_UNCOMPRESSED_R32;
+ else if (channels == 2) TraceLog(LOG_WARNING, "Channel bit-depth not supported!");
+ else if (channels == 3) format = PIXELFORMAT_UNCOMPRESSED_R32G32B32;
+ else if (channels == 4) format = PIXELFORMAT_UNCOMPRESSED_R32G32B32A32;
+ }
+ else if (bpp == 16) TraceLog(LOG_WARNING, "Channel bit-depth not supported!");
+ }
+ else format = pixelFormatActive;
+
+ if (format != -1)
+ {
+ Image image = LoadImageRaw(fileNamePath, widthValue, heightValue, format, headerSizeValue);
+ texture = LoadTextureFromImage(image);
+ UnloadImage(image);
+
+ importWindowActive = false;
+ btnLoadPressed = false;
+
+ if (texture.id > 0)
+ {
+ imageLoaded = true;
+ imageScale = (float)(screenHeight - 100)/texture.height;
+ }
+ }
+ }
+ }
+
+ if (imageLoaded) imageScale += (float)GetMouseWheelMove(); // Image scale control
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ if (texture.id != 0)
+ {
+ DrawTextureEx(texture, (Vector2){ screenWidth/2 - texture.width*imageScale/2, screenHeight/2 - texture.height*imageScale/2 }, 0, imageScale, WHITE);
+ DrawText(TextFormat("SCALE x%.0f", imageScale), 20, screenHeight - 40, 20, GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)));
+ }
+ else DrawText("drag & drop RAW image file", 320, 180, 10, GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)));
+
+ // raygui: controls drawing
+ //----------------------------------------------------------------------------------
+ if (importWindowActive)
+ {
+ importWindowActive = !GuiWindowBox((Rectangle){ windowOffset.x + 0, windowOffset.y + 0, 200, 465 }, "Image RAW Import Options");
+
+ GuiLabel((Rectangle){ windowOffset.x + 10, windowOffset.y + 30, 65, 20 }, "Import file:");
+ GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 30, 75, 20 }, fileName);
+ GuiLabel((Rectangle){ windowOffset.x + 10, windowOffset.y + 50, 65, 20 }, "File size:");
+ GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 50, 75, 20 }, TextFormat("%i bytes", dataSize));
+ GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 85, 180, 80 }, "Resolution");
+ GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 100, 33, 25 }, "Width:");
+ if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 100, 80, 25 }, NULL, &widthValue, 0, 8192, widthEditMode)) widthEditMode = !widthEditMode;
+ GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 100, 30, 25 }, "pixels");
+ GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 130, 33, 25 }, "Height:");
+ if (GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 130, 80, 25 }, NULL, &heightValue, 0, 8192, heightEditMode)) heightEditMode = !heightEditMode;
+ GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 130, 30, 25 }, "pixels");
+ GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 180, 180, 160 }, "Pixel Format");
+ GuiComboBox((Rectangle){ windowOffset.x + 20, windowOffset.y + 195, 160, 25 }, TextJoin(pixelFormatTextList, 8, ";"), &pixelFormatActive);
+ GuiLine((Rectangle){ windowOffset.x + 20, windowOffset.y + 220, 160, 20 }, NULL);
+
+ if (pixelFormatActive != 0) GuiDisable();
+ GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 235, 50, 20 }, "Channels:");
+ GuiToggleGroup((Rectangle){ windowOffset.x + 20, windowOffset.y + 255, 156/4, 25 }, TextJoin(channelsTextList, 4, ";"), &channelsActive);
+ GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 285, 50, 20 }, "Bit Depth:");
+ GuiToggleGroup((Rectangle){ windowOffset.x + 20, windowOffset.y + 305, 160/3, 25 }, TextJoin(bitDepthTextList, 3, ";"), &bitDepthActive);
+ GuiEnable();
+
+ GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 355, 180, 50 }, "Header");
+ GuiLabel((Rectangle){ windowOffset.x + 25, windowOffset.y + 370, 27, 25 }, "Size:");
+ if (GuiValueBox((Rectangle){ windowOffset.x + 55, windowOffset.y + 370, 85, 25 }, NULL, &headerSizeValue, 0, 10000, headerSizeEditMode)) headerSizeEditMode = !headerSizeEditMode;
+ GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 370, 30, 25 }, "bytes");
+
+ btnLoadPressed = GuiButton((Rectangle){ windowOffset.x + 10, windowOffset.y + 420, 180, 30 }, "Import RAW");
+ }
+ //----------------------------------------------------------------------------------
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ if (texture.id != 0) UnloadTexture(texture);
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/portable_window/portable_window.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/portable_window/portable_window.c
new file mode 100644
index 0000000000..a7d3c9aa94
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/portable_window/portable_window.c
@@ -0,0 +1,98 @@
+/*******************************************************************************************
+*
+* raygui - portable window
+*
+* DEPENDENCIES:
+* raylib 4.0 - Windowing/input management and drawing.
+* raygui 3.0 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 600;
+
+ SetConfigFlags(FLAG_WINDOW_UNDECORATED);
+ InitWindow(screenWidth, screenHeight, "raygui - portable window");
+
+ // General variables
+ Vector2 mousePosition = { 0 };
+ Vector2 windowPosition = { 500, 200 };
+ Vector2 panOffset = mousePosition;
+ bool dragWindow = false;
+
+ SetWindowPosition(windowPosition.x, windowPosition.y);
+
+ bool exitWindow = false;
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!exitWindow && !WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ mousePosition = GetMousePosition();
+
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && !dragWindow)
+ {
+ if (CheckCollisionPointRec(mousePosition, (Rectangle){ 0, 0, screenWidth, 20 }))
+ {
+ windowPosition = GetWindowPosition();
+ dragWindow = true;
+ panOffset = mousePosition;
+ }
+ }
+
+ if (dragWindow)
+ {
+ windowPosition.x += (mousePosition.x - panOffset.x);
+ windowPosition.y += (mousePosition.y - panOffset.y);
+
+ SetWindowPosition((int)windowPosition.x, (int)windowPosition.y);
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) dragWindow = false;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ exitWindow = GuiWindowBox((Rectangle){ 0, 0, screenWidth, screenHeight }, "#198# PORTABLE WINDOW");
+
+ DrawText(TextFormat("Mouse Position: [ %.0f, %.0f ]", mousePosition.x, mousePosition.y), 10, 40, 10, DARKGRAY);
+ DrawText(TextFormat("Window Position: [ %.0f, %.0f ]", windowPosition.x, windowPosition.y), 10, 60, 10, DARKGRAY);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/property_list/dm_property_list.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/property_list/dm_property_list.h
new file mode 100644
index 0000000000..838a1610f9
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/property_list/dm_property_list.h
@@ -0,0 +1,868 @@
+/*******************************************************************************************
+*
+* PropertyListControl v1.0.1 - A custom control that displays a set of properties as a list
+*
+* UPDATES: last updated - 10 march 2020 (v1.0.1)
+* v1.0.1 - Made it work with latest raygui version
+* - Added `GuiDMSaveProperties()` for saving properties to a text file
+* - A `GuiDMLoadProperties()` is planed but not implemented yet
+* - Added a section property that can work as a way to group multiple properties
+* - Fixed issue with section not having the correct height
+* v1.0.0 - Initial release
+*
+*
+* MODULE USAGE:
+* #define GUI_PROPERTY_LIST_IMPLEMENTATION
+* #include "dm_property_list.h"
+*
+* INIT: GuiDMProperty props[] = { // initialize a set of properties first
+ PCOLOR(),
+ PINT(),
+ PFLOAT(),
+ ...
+ };
+* DRAW: GuiDMPropertyList(bounds, props, sizeof(props)/sizeof(props[0]), ...);
+*
+*
+* NOTE: This module also contains 2 extra controls used internally by the property list
+* - GuiDMValueBox() - a value box that supports displaying float values
+* - GuiDMSpinner() - a `better` GuiSpinner()
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2020 Vlad Adrian (@Demizdor - https://github.com/Demizdor).
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+// WARNING: raygui implementation is expected to be defined before including this header
+#undef RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+
+#ifndef GUI_PROPERTY_LIST_H
+#define GUI_PROPERTY_LIST_H
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+
+// A bunch of usefull macros for modifying the flags of each property
+
+// Set flag `F` of property `P`. `P` must be a pointer!
+#define PROP_SET_FLAG(P, F) ((P)->flags |= (F))
+// Clear flag `F` of property `P`. `P` must be a pointer!
+#define PROP_CLEAR_FLAG(P, F) ((P)->flags &= ~(F))
+// Toggles flag `F` of property `P`. `P` must be a pointer!
+#define PROP_TOGGLE_FLAG(P, F) ((P)->flags ^= (F))
+// Checks if flag `F` of property `P` is set . `P` must be a pointer!
+#define PROP_CHECK_FLAG(P, F) ((P)->flags & (F))
+
+// Some usefull macros for creating properties
+
+// Create a bool property with name `N`, flags `F` and value `V`
+#define PBOOL(N, F, V) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_BOOL, F, .value.vbool = V}
+// Create a int property with name `N`, flags `F` and value `V`
+#define PINT(N, F, V) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_INT, F, .value.vint = {V,0,0,1}}
+// Create a ranged int property within `MIN` and `MAX` with name `N`, flags `F` value `V`.
+// Pressing the spinner buttons will increase/decrease the value by `S`.
+#define PINT_RANGE(N, F, V, S, MIN, MAX) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_INT, F, .value.vint = {V,MIN,MAX,S}}
+// Create a float property with name `N`, flags `F` and value `V`
+#define PFLOAT(N, F, V) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_FLOAT, F, .value.vfloat = {V,0.f,0.f,1.0f,3}}
+// Create a ranged float property within `MIN` and `MAX` with name `N`, flags `F` value `V` with `P` decimal digits to show.
+// Pressing the spinner buttons will increase/decrease the value by `S`.
+#define PFLOAT_RANGE(N, F, V, S, P, MIN, MAX) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_FLOAT, F, .value.vfloat = {V,MIN,MAX,S,P}}
+// Create a text property with name `N`, flags `F` value `V` and max text size `S`
+#define PTEXT(N, F, V, S) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_TEXT, F, .value.vtext = {V, S} }
+// Create a text property with name `N`, flags `F` value `V` and max text size `S`
+#define PSELECT(N, F, V, A) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_SELECT, F, .value.vselect = {V, A} }
+// Create a 2D vector property with name `N`, flags `F` and the `X`, `Y` coordinates
+#define PVEC2(N, F, X, Y) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_VECTOR2, F, .value.v2 = {X, Y} }
+// Create a 3D vector property with name `N`, flags `F` and the `X`, `Y`, `Z` coordinates
+#define PVEC3(N, F, X, Y, Z) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_VECTOR3, F, .value.v3 = {X, Y, Z} }
+// Create a 4D vector property with name `N`, flags `F` and the `X`, `Y`, `Z`, `W` coordinates
+#define PVEC4(N, F, X, Y, Z, W) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_VECTOR4, F, .value.v4 = {X, Y, Z, W} }
+// Create a rectangle property with name `N`, flags `F`, `X`, `Y` coordinates and `W` and `H` size
+#define PRECT(N, F, X, Y, W, H) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_RECT, F, .value.vrect = {X, Y, W, H} }
+// Create a 3D vector property with name `N`, flags `F` and the `R`, `G`, `B`, `A` channel values
+#define PCOLOR(N, F, R, G, B, A) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_COLOR, F, .value.vcolor = {R, G, B, A} }
+// Create a collapsable section named `N` with `F` flags and the next `C` properties as children.
+// !! A section cannot hold another section as a child !!
+#define PSECTION(N, F, C) RAYGUI_CLITERAL(GuiDMProperty){N, GUI_PROP_SECTION, F, .value.vsection = (C)}
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+enum GuiDMPropertyTypes {
+ GUI_PROP_BOOL = 0,
+ GUI_PROP_INT,
+ GUI_PROP_FLOAT,
+ GUI_PROP_TEXT,
+ GUI_PROP_SELECT,
+ GUI_PROP_VECTOR2,
+ GUI_PROP_VECTOR3,
+ GUI_PROP_VECTOR4,
+ GUI_PROP_RECT,
+ GUI_PROP_COLOR,
+ GUI_PROP_SECTION,
+};
+
+enum GuiDMPropertyFlags {
+ GUI_PFLAG_COLLAPSED = 1 << 0, // is the property expanded or collapsed?
+ GUI_PFLAG_DISABLED = 1 << 1, // is this property disabled or enabled?
+};
+
+// Data structure for each property
+typedef struct {
+ char* name;
+ short type;
+ short flags;
+ union {
+ bool vbool;
+ struct { int val; int min; int max; int step; } vint;
+ struct { float val; float min; float max; float step; int precision; } vfloat;
+ struct { char* val; int size; } vtext;
+ struct { char* val; int active; } vselect;
+ int vsection;
+ Vector2 v2;
+ Vector3 v3;
+ Vector4 v4;
+ Rectangle vrect;
+ Color vcolor;
+ } value;
+} GuiDMProperty;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+
+// A more advanced `GuiValueBox()` supporting float/int values with specified `precision`, cursor movements, cut/copy/paste and
+// other keybord shortcuts. Needed by `GuiDMSpinner()` !!
+// `precision` should be between 1-7 for float values and 0 for int values (maybe 15 for doubles but that was not tested)
+// WARNING: The bounds should be set big enough else the text will overflow and things will break
+// WARNING: Sometimes the last decimal value could differ, this is probably due to rounding
+double GuiDMValueBox(Rectangle bounds, double value, double minValue, double maxValue, int precision, bool editMode);
+
+// A more advanced `GuiSpinner()` using `GuiDMValueBox()` for displaying the values.
+// This was needed because `GuiSpinner()` can't display float values and editing values is somewhat hard.
+// This is by no means perfect but should be more user friendly than the default control provided by raygui.
+double GuiDMSpinner(Rectangle bounds, double value, double minValue, double maxValue, double step, int precision, bool editMode);
+
+// Works just like `GuiListViewEx()` but with an array of properties instead of text.
+void GuiDMPropertyList(Rectangle bounds, GuiDMProperty* props, int count, int* focus, int* scrollIndex);
+
+// Handy function to save properties to a file. Returns false on failure or true otherwise.
+bool GuiDMSaveProperties(const char* file, GuiDMProperty* props, int count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GUI_PROPERTY_LIST_H
+
+
+
+/***********************************************************************************
+*
+* GUI_PROPERTY_LIST_IMPLEMENTATION
+*
+************************************************************************************/
+#if defined(GUI_PROPERTY_LIST_IMPLEMENTATION)
+
+#include "../../src/raygui.h"
+
+#include // for calloc()
+#include // for memmove(), strlen()
+#include // for sscanf(), snprintf()
+
+#ifndef __cplusplus
+#if __STDC_VERSION__ >= 199901L
+#include // for bool if >= C99
+#endif
+#endif
+
+double GuiDMValueBox(Rectangle bounds, double value, double minValue, double maxValue, int precision, bool editMode) {
+ // FIXME: Hope all those `memmove()` functions are correctly used so we won't leak memory or overflow the buffer !!!
+ static int framesCounter = 0; // Required for blinking cursor
+ static int cursor = 0; // Required for tracking the cursor position (only for a single active valuebox)
+
+ enum {cursorTimer = 6, maxChars = 31, textPadding = 2};
+
+ GuiState state = GuiGetState();
+
+ // Make sure value is in range
+ if(maxValue != minValue){
+ if(value < minValue) value = minValue;
+ if(value > maxValue) value = maxValue;
+ }
+
+ char textValue[maxChars + 1] = "\0";
+ snprintf(textValue, maxChars, "%.*f", precision, value); // NOTE: use `snprintf` here so we don't overflow the buffer
+ int len = strlen(textValue);
+
+ bool valueHasChanged = false;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ if (editMode)
+ {
+ // Make sure cursor position is correct
+ if(cursor > len) cursor = len;
+ if(cursor < 0) cursor = 0;
+
+ state = STATE_PRESSED;
+ framesCounter++;
+
+ if(IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && (framesCounter%cursorTimer == 0))) {
+ // MOVE CURSOR TO RIGHT
+ ++cursor;
+ framesCounter = 0;
+ } else if(IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (framesCounter%cursorTimer == 0))) {
+ // MOVE CURSOR TO LEFT
+ --cursor;
+ framesCounter = 0;
+ } else if (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (framesCounter%cursorTimer) == 0)) {
+ // HANDLE BACKSPACE
+ if(cursor > 0) {
+ if(textValue[cursor-1] != '.') {
+ if(cursor < len )
+ memmove(&textValue[cursor-1], &textValue[cursor], len-cursor);
+ textValue[len - 1] = '\0';
+ valueHasChanged = true;
+ }
+ --cursor;
+ }
+ framesCounter = 0;
+ } else if (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (framesCounter%cursorTimer) == 0)) {
+ // HANDLE DEL
+ if(len > 0 && cursor < len && textValue[cursor] != '.') {
+ memmove(&textValue[cursor], &textValue[cursor+1], len-cursor);
+ textValue[len] = '\0';
+ len -= 1;
+ valueHasChanged = true;
+ }
+ } else if (IsKeyPressed(KEY_HOME)) {
+ // MOVE CURSOR TO START
+ cursor = 0;
+ } else if (IsKeyPressed(KEY_END)) {
+ // MOVE CURSOR TO END
+ cursor = len;
+ } else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) {
+ // COPY
+ SetClipboardText(textValue);
+ } else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_X)) {
+ // CUT
+ SetClipboardText(textValue);
+ textValue[0] = '\0';
+ cursor = len = 0;
+ value = 0.0; // set it to 0 and pretend the value didn't change
+ } else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) {
+ // PASTE
+ const char* clip = GetClipboardText();
+ int clipLen = strlen(clip);
+ clipLen = clipLen > maxChars ? maxChars : clipLen;
+ memcpy(textValue, clip, clipLen);
+ len = clipLen;
+ textValue[len] = '\0';
+ valueHasChanged = true;
+ }
+ else {
+ // HANDLE KEY PRESS
+ int key = GetKeyPressed();
+ if( ((len < maxChars) && (key >= 48) && (key <= 57)) || (key == 46) || (key == 45) ) // only allow 0..9, minus(-) and dot(.)
+ {
+ if(precision != 0 && cursor < len) { // when we have decimals we can't insert at the end
+ memmove(&textValue[cursor], &textValue[cursor-1], len+1-cursor);
+ textValue[len+1] = '\0';
+ textValue[cursor] = (char)key;
+ cursor++;
+ valueHasChanged = true;
+ }
+ else if(precision == 0) {
+ if(cursor < len) memmove(&textValue[cursor], &textValue[cursor-1], len+1-cursor);
+ len += 1;
+ textValue[len+1] = '\0';
+ textValue[cursor] = (char)key;
+ cursor++;
+ valueHasChanged = true;
+ }
+ }
+ }
+
+ // Make sure cursor position is correct
+ if(cursor > len) cursor = len;
+ if(cursor < 0) cursor = 0;
+ }
+ else
+ {
+ if (CheckCollisionPointRec(GetMousePosition(), bounds))
+ {
+ state = STATE_FOCUSED;
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) framesCounter = 0;
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleLinesEx(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha));
+
+ Rectangle textBounds = {bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH) + textPadding, bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH),
+ bounds.width - 2*(GuiGetStyle(VALUEBOX, BORDER_WIDTH) + textPadding), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH)};
+
+ int textWidth = GuiGetTextWidth(textValue);
+ if(textWidth > textBounds.width) textBounds.width = textWidth;
+
+ if (state == STATE_PRESSED)
+ {
+ DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)), guiAlpha));
+
+ // Draw blinking cursor
+ // NOTE: ValueBox internal text is always centered
+ if (editMode && ((framesCounter/20)%2 == 0)) {
+ // Measure text until the cursor
+ int textWidthCursor = -2;
+ if(cursor > 0) {
+ char c = textValue[cursor];
+ textValue[cursor] = '\0';
+ textWidthCursor = GuiGetTextWidth(textValue);
+ textValue[cursor] = c;
+ }
+ //DrawRectangle(bounds.x + textWidthCursor + textPadding + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+ DrawRectangle(bounds.x + textWidthCursor + (int)((bounds.width - textWidth - textPadding)/2.0f) + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+ }
+ }
+ else if (state == STATE_DISABLED)
+ {
+ DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)), guiAlpha));
+ }
+
+ GuiDrawText(textValue, textBounds, TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
+
+ value = valueHasChanged ? strtod(textValue, NULL) : value;
+
+ // Make sure value is in range
+ if(maxValue != minValue){
+ if(value < minValue) value = minValue;
+ if(value > maxValue) value = maxValue;
+ }
+
+ return value;
+}
+
+
+
+double GuiDMSpinner(Rectangle bounds, double value, double minValue, double maxValue, double step, int precision, bool editMode) {
+ GuiState state = GuiGetState();
+
+ Rectangle spinner = { bounds.x + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING), bounds.y,
+ bounds.width - 2*(GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING)), bounds.height };
+ Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height };
+ Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH),
+ (float)bounds.y, (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check spinner state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+ }
+ }
+ //--------------------------------------------------------------------
+
+
+ // Draw control
+ //--------------------------------------------------------------------
+ // Draw value selector custom buttons
+ // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
+ int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+ int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(VALUEBOX, BORDER_WIDTH));
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+#if defined(RAYGUI_SUPPORT_RICONS)
+ if (GuiButton(leftButtonBound, GuiIconText(RICON_ARROW_LEFT_FILL, NULL))) value -= step;
+ if (GuiButton(rightButtonBound, GuiIconText(RICON_ARROW_RIGHT_FILL, NULL))) value += step;
+#else
+ if (GuiButton(leftButtonBound, "<")) value -= step;
+ if (GuiButton(rightButtonBound, ">")) value += step;
+#endif
+
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+
+ value = GuiDMValueBox(spinner, value, minValue, maxValue, precision, editMode);
+
+ return value;
+}
+
+
+
+void GuiDMPropertyList(Rectangle bounds, GuiDMProperty* props, int count, int* focus, int* scrollIndex) {
+ #ifdef RAYGUI_SUPPORT_RICONS
+ #define PROPERTY_COLLAPSED_ICON "#120#"
+ #define PROPERTY_EXPANDED_ICON "#121#"
+ #else
+ #define PROPERTY_COLLAPSED_ICON "+"
+ #define PROPERTY_EXPANDED_ICON "-"
+ #endif
+
+ #define PROPERTY_PADDING 6
+ #define PROPERTY_ICON_SIZE 16
+ #define PROPERTY_DECIMAL_DIGITS 3 //how many digits to show (used only for the vector properties)
+
+ // NOTE: Using ListView style for everything !!
+ GuiState state = GuiGetState();
+ int propFocused = (focus == NULL)? -1 : *focus;
+ int scroll = *scrollIndex > 0 ? 0 : *scrollIndex; // NOTE: scroll should always be negative or 0
+
+ // Each property occupies a certain number of slots, highly synchronized with the properties enum (GUI_PROP_BOOL ... GUI_PROP_SECTION)
+ // NOTE: If you add a custom property type make sure to add the number of slots it occupies here !!
+ const int propSlots[] = {1,1,1,2,1,3,4,5,5,5,1};
+
+ Rectangle absoluteBounds = {0}; // total bounds for all of the properties (unclipped)
+ // We need to loop over all the properties to get total height so we can see if we need a scrollbar or not
+ for(int p=0; p bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) ? true : false;
+ if(!useScrollBar && scroll != 0) scroll = 0; // make sure scroll is 0 when there's no scrollbar
+
+ Rectangle scrollBarBounds = {bounds.x + GuiGetStyle(LISTVIEW, BORDER_WIDTH), bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH),
+ GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)};
+
+ absoluteBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ absoluteBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + scroll;
+ absoluteBounds.width = bounds.width - 2*(GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH));
+
+ if(useScrollBar) {
+ if(GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)
+ absoluteBounds.x += GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); // scrollbar is on the LEFT, adjust bounds
+ else
+ scrollBarBounds.x = bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); // scrollbar is on the RIGHT
+ absoluteBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); // adjust width to fit the scrollbar
+ }
+
+ int maxScroll = absoluteBounds.height + 2*(GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH))-bounds.height;
+
+ // Update control
+ //--------------------------------------------------------------------
+ Vector2 mousePos = GetMousePosition();
+ // NOTE: most of the update code is actually done in the draw control section
+ if ((state != STATE_DISABLED) && !guiLocked) {
+ if(!CheckCollisionPointRec(mousePos, bounds)) {
+ propFocused = -1;
+ }
+
+ if (useScrollBar)
+ {
+ int wheelMove = GetMouseWheelMove();
+ scroll += wheelMove*count;
+ if(-scroll > maxScroll) scroll = -maxScroll;
+ }
+ }
+ //--------------------------------------------------------------------
+
+
+ // Draw control
+ //--------------------------------------------------------------------
+ DrawRectangleRec(bounds, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), guiAlpha) ); // Draw background
+ DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha)); // Draw border
+
+ BeginScissorMode(absoluteBounds.x, bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), absoluteBounds.width, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH));
+ int currentHeight = 0;
+ for(int p=0; p= bounds.y && absoluteBounds.y + currentHeight <= bounds.y + bounds.height)
+ {
+ Rectangle propBounds = {absoluteBounds.x, absoluteBounds.y + currentHeight, absoluteBounds.width, height};
+ Color textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha);
+ int propState = STATE_NORMAL;
+
+ // Get the state of this property and do some initial drawing
+ if(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_DISABLED)) {
+ propState = STATE_DISABLED;
+ propBounds.height += 1;
+ DrawRectangleRec(propBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
+ propBounds.height -= 1;
+ textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha);
+ } else {
+ if(CheckCollisionPointRec(mousePos, propBounds) && !guiLocked) {
+ if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
+ propState = STATE_PRESSED;
+ //DrawRectangleRec(propRect, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
+ textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha);
+ } else {
+ propState = STATE_FOCUSED;
+ propFocused = p;
+ //DrawRectangleRec(propRect, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
+ textColor = Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha);
+ }
+ } else propState = STATE_NORMAL;
+ }
+
+ if(propState == STATE_DISABLED) GuiSetState(propState);
+ switch(props[p].type)
+ {
+ case GUI_PROP_BOOL: {
+ // draw property name
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ if(propState == STATE_PRESSED) props[p].value.vbool = !props[p].value.vbool; // toggle the property value when clicked
+
+ // draw property value
+ const bool locked = guiLocked;
+ GuiLock(); // lock the checkbox since we changed the value manually
+ GuiCheckBox((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + height/4, height/2, height/2}, props[p].value.vbool? "Yes" : "No", &props[p].value.vbool);
+ if(!locked) GuiUnlock(); // only unlock when needed
+ } break;
+
+ case GUI_PROP_INT:
+ // draw property name
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ // draw property value
+ props[p].value.vint.val = GuiDMSpinner((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2},
+ props[p].value.vint.val, props[p].value.vint.min, props[p].value.vint.max, props[p].value.vint.step, 0, (propState == STATE_FOCUSED) );
+ break;
+
+ case GUI_PROP_FLOAT:
+ // draw property name
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ // draw property value
+ props[p].value.vfloat.val = GuiDMSpinner((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2},
+ props[p].value.vfloat.val, props[p].value.vfloat.min, props[p].value.vfloat.max, props[p].value.vfloat.step, props[p].value.vfloat.precision, (propState == STATE_FOCUSED) );
+ break;
+
+ case GUI_PROP_TEXT: {
+ Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
+ // Collapse/Expand property on click
+ if((propState == STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
+ PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
+
+ // draw property name
+ GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(TextFormat("%i/%i", strlen(props[p].value.vtext.val), props[p].value.vtext.size), (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, TEXT_ALIGN_LEFT, textColor);
+
+ // draw property value
+ if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED))
+ GuiTextBox((Rectangle){propBounds.x, propBounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2}, props[p].value.vtext.val, props[p].value.vtext.size, (propState == STATE_FOCUSED));
+ } break;
+
+ case GUI_PROP_SELECT: {
+ // TODO: Create a custom dropdownbox control instead of using the raygui combobox
+ // draw property name
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ // draw property value
+ GuiComboBox((Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2},
+ props[p].value.vselect.val, &props[p].value.vselect.active);
+ } break;
+
+ case GUI_PROP_VECTOR2: case GUI_PROP_VECTOR3: case GUI_PROP_VECTOR4: {
+ Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
+ // Collapse/Expand property on click
+ if((propState == STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
+ PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
+
+ const char* fmt = "";
+ if(props[p].type == GUI_PROP_VECTOR2) fmt = TextFormat("[%.0f, %.0f]", props[p].value.v2.x, props[p].value.v2.y);
+ else if(props[p].type == GUI_PROP_VECTOR3) fmt = TextFormat("[%.0f, %.0f, %.0f]", props[p].value.v3.x, props[p].value.v3.y, props[p].value.v3.z);
+ else fmt = TextFormat("[%.0f, %.0f, %.0f, %.0f]", props[p].value.v4.x, props[p].value.v4.y, props[p].value.v4.z, props[p].value.v4.w);
+
+ // draw property name
+ GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(fmt, (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, TEXT_ALIGN_LEFT, textColor);
+
+ // draw X, Y, Z, W values (only when expanded)
+ if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
+ Rectangle slotBounds = { propBounds.x, propBounds.y+GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2};
+ Rectangle lblBounds = { propBounds.x+PROPERTY_PADDING, slotBounds.y, GuiGetTextWidth("A"), slotBounds.height};
+ Rectangle valBounds = { lblBounds.x+lblBounds.width+PROPERTY_PADDING, slotBounds.y, propBounds.width-lblBounds.width-2*PROPERTY_PADDING, slotBounds.height};
+ GuiDrawText("X", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.v2.x = GuiDMSpinner(valBounds, props[p].value.v2.x, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = slotBounds.y;
+ GuiDrawText("Y", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.v2.y = GuiDMSpinner(valBounds, props[p].value.v2.y, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = slotBounds.y;
+ if(props[p].type >= GUI_PROP_VECTOR3) {
+ GuiDrawText("Z", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.v3.z = GuiDMSpinner(valBounds, props[p].value.v3.z, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = slotBounds.y;
+ }
+
+ if(props[p].type >= GUI_PROP_VECTOR4) {
+ GuiDrawText("W", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.v4.w = GuiDMSpinner(valBounds, props[p].value.v4.w, 0.0, 0.0, 1.0, PROPERTY_DECIMAL_DIGITS, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ }
+ }
+ } break;
+
+ case GUI_PROP_RECT:{
+ Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
+ // Collapse/Expand property on click
+ if((propState == STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
+ PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
+
+ // draw property name
+ GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(TextFormat("[%.0f, %.0f, %.0f, %.0f]", props[p].value.vrect.x, props[p].value.vrect.y, props[p].value.vrect.width, props[p].value.vrect.height),
+ (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, TEXT_ALIGN_LEFT, textColor);
+
+ // draw X, Y, Width, Height values (only when expanded)
+ if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
+ Rectangle slotBounds = { propBounds.x, propBounds.y+GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2};
+ Rectangle lblBounds = { propBounds.x+PROPERTY_PADDING, slotBounds.y, GuiGetTextWidth("Height"), slotBounds.height};
+ Rectangle valBounds = { lblBounds.x+lblBounds.width+PROPERTY_PADDING, slotBounds.y, propBounds.width-lblBounds.width-2*PROPERTY_PADDING, slotBounds.height};
+ GuiDrawText("X", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vrect.x = GuiDMSpinner(valBounds, props[p].value.vrect.x, 0.0, 0.0, 1.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = slotBounds.y;
+ GuiDrawText("Y", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vrect.y = GuiDMSpinner(valBounds, props[p].value.vrect.y, 0.0, 0.0, 1.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = slotBounds.y;
+ GuiDrawText("Width", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vrect.width = GuiDMSpinner(valBounds, props[p].value.vrect.width, 0.0, 0.0, 1.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = slotBounds.y;
+ GuiDrawText("Height", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vrect.height = GuiDMSpinner(valBounds, props[p].value.vrect.height, 0.0, 0.0, 1.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ }
+ } break;
+
+
+ case GUI_PROP_COLOR: {
+ Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
+ // Collapse/Expand property on click
+ if((propState == STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds))
+ PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
+
+ // draw property name
+ GuiDrawText(PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED) ? PROPERTY_COLLAPSED_ICON : PROPERTY_EXPANDED_ICON, titleBounds, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y+1, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2}, TEXT_ALIGN_LEFT, textColor);
+ DrawLineEx( (Vector2){propBounds.x+propBounds.width/2, propBounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 5}, (Vector2){propBounds.x+propBounds.width, propBounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 5}, 6.0f, props[p].value.vcolor);
+ const char* fmt = TextFormat("#%02X%02X%02X%02X", props[p].value.vcolor.r, props[p].value.vcolor.g, props[p].value.vcolor.b, props[p].value.vcolor.a);
+ char clip[10] = "\0";
+ memcpy(clip, fmt, 10*sizeof(char)); // copy to temporary buffer since we can't be sure when TextFormat() will be called again and our text will be overwritten
+ GuiDrawText(fmt, (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, TEXT_ALIGN_LEFT, textColor);
+
+ // draw R, G, B, A values (only when expanded)
+ if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
+ Rectangle slotBounds = { propBounds.x, propBounds.y+GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)+1, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2};
+ Rectangle lblBounds = { propBounds.x+PROPERTY_PADDING, slotBounds.y, GuiGetTextWidth("A"), slotBounds.height};
+ Rectangle valBounds = { lblBounds.x+lblBounds.width+PROPERTY_PADDING, slotBounds.y, GuiGetTextWidth("000000"), slotBounds.height};
+ Rectangle sbarBounds = { valBounds.x + valBounds.width + PROPERTY_PADDING, slotBounds.y, slotBounds.width - 3*PROPERTY_PADDING - lblBounds.width - valBounds.width, slotBounds.height };
+
+ if(sbarBounds.width <= GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2) valBounds.width = propBounds.width-lblBounds.width-2*PROPERTY_PADDING; // hide slider when no space
+ // save current scrollbar style
+ int tmpSliderPadding = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING);
+ int tmpPadding = GuiGetStyle(SCROLLBAR, SCROLL_PADDING);
+ int tmpBorder = GuiGetStyle(SCROLLBAR, BORDER_WIDTH);
+ int tmpSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
+ int tmpArrows = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE);
+ Color tmpBG1 = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED));
+ // set a custom scrollbar style
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 3);
+ GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 10);
+ GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 6);
+ GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0);
+ GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, GuiGetStyle(DEFAULT, BACKGROUND_COLOR)); // disable scrollbar background
+
+ GuiDrawText("R", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vcolor.r = GuiDMValueBox(valBounds, props[p].value.vcolor.r, 0.0, 255.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
+ props[p].value.vcolor.r = GuiScrollBar(sbarBounds, props[p].value.vcolor.r, 0, 255);
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = sbarBounds.y = slotBounds.y;
+
+ GuiDrawText("G", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vcolor.g = GuiDMValueBox(valBounds, props[p].value.vcolor.g, 0.0, 255.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
+ props[p].value.vcolor.g = GuiScrollBar(sbarBounds, props[p].value.vcolor.g, 0, 255);
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = sbarBounds.y = slotBounds.y;
+
+ GuiDrawText("B", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vcolor.b = GuiDMValueBox(valBounds, props[p].value.vcolor.b, 0.0, 255.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
+ props[p].value.vcolor.b = GuiScrollBar(sbarBounds, props[p].value.vcolor.b, 0, 255);
+ slotBounds.y += GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ lblBounds.y = valBounds.y = sbarBounds.y = slotBounds.y;
+
+ GuiDrawText("A", lblBounds, TEXT_ALIGN_LEFT, textColor);
+ props[p].value.vcolor.a = GuiDMValueBox(valBounds, props[p].value.vcolor.a, 0.0, 255.0, 0, (propState == STATE_FOCUSED) && CheckCollisionPointRec(mousePos, slotBounds) );
+ if(sbarBounds.width > GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)-2)
+ props[p].value.vcolor.a = GuiScrollBar(sbarBounds, props[p].value.vcolor.a, 0, 255);
+
+ // load saved scrollbar style
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, tmpSliderPadding);
+ GuiSetStyle(SCROLLBAR, SCROLL_PADDING, tmpPadding);
+ GuiSetStyle(SCROLLBAR, BORDER_WIDTH, tmpBorder);
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, tmpSliderSize);
+ GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, tmpArrows);
+ GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, ColorToInt(tmpBG1));
+ }
+
+ // support COPY/PASTE (need to do this here since GuiDMValueBox() also has COPY/PASTE so we need to overwrite it)
+ if((propState == STATE_FOCUSED)) {
+ if(IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C))
+ SetClipboardText(clip);
+ else if(IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)){
+ unsigned int a = props[p].value.vcolor.a, r = props[p].value.vcolor.r, g=props[p].value.vcolor.g, b=props[p].value.vcolor.b;
+ sscanf(GetClipboardText(), "#%02X%02X%02X%02X", &r, &g, &b, &a);
+ props[p].value.vcolor.r=r; props[p].value.vcolor.g=g; props[p].value.vcolor.b=b; props[p].value.vcolor.a=a;
+ }
+ }
+ } break;
+
+ case GUI_PROP_SECTION: {
+ Rectangle titleBounds = { propBounds.x, propBounds.y, propBounds.width, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) };
+ // Collapse/Expand section on click
+ if( (propState == STATE_PRESSED) && CheckCollisionPointRec(mousePos, titleBounds) )
+ PROP_TOGGLE_FLAG(&props[p], GUI_PFLAG_COLLAPSED);
+
+ if(!PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED)) {
+ GuiDrawText(PROPERTY_EXPANDED_ICON, titleBounds, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_CENTER, textColor);
+ } else {
+ GuiDrawText(PROPERTY_COLLAPSED_ICON, titleBounds, TEXT_ALIGN_LEFT, textColor);
+ GuiDrawText(TextFormat("%s [%i]", props[p].name, props[p].value.vsection), (Rectangle){propBounds.x+PROPERTY_ICON_SIZE+PROPERTY_PADDING, propBounds.y, propBounds.width-PROPERTY_ICON_SIZE-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_CENTER, textColor);
+ }
+ } break;
+
+
+ // NOTE: Add your custom property here !!
+ default: {
+ // draw property name
+ GuiDrawText(props[p].name, (Rectangle){propBounds.x + PROPERTY_PADDING, propBounds.y, propBounds.width/2-PROPERTY_PADDING, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT)}, TEXT_ALIGN_LEFT, textColor);
+ // draw property type
+ GuiDrawText(TextFormat("TYPE %i", props[p].type), (Rectangle){propBounds.x+propBounds.width/2, propBounds.y + 1, propBounds.width/2, GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) - 2}, TEXT_ALIGN_LEFT, textColor);
+ } break;
+
+ } // end of switch()
+
+ GuiSetState(state);
+ }
+
+ currentHeight += height + 1;
+
+ // Skip collapsed section. Don't put this code inside the switch !!
+ if(props[p].type == GUI_PROP_SECTION && (PROP_CHECK_FLAG(&props[p], GUI_PFLAG_COLLAPSED))) p += props[p].value.vsection;
+ } // end for
+ EndScissorMode();
+
+ if(useScrollBar) {
+ scroll = -GuiScrollBar(scrollBarBounds, -scroll, 0, maxScroll);
+ *scrollIndex = scroll;
+ }
+ //--------------------------------------------------------------------
+
+ if(focus != NULL) *focus = propFocused;
+}
+
+bool GuiDMSaveProperties(const char* file, GuiDMProperty* props, int count) {
+ if(file == NULL || props == NULL) return false;
+ if(count == 0) return true;
+
+ FILE* f = fopen(file, "w");
+ if(f == NULL) return false;
+
+ // write header
+ fprintf(f, "#\n# Property types:\n"
+ "# b // Bool\n"
+ "# i // Int\n"
+ "# f // Float\n"
+ "# t // Text\n"
+ "# l // Select\n"
+ "# g // Section (Group)\n"
+ "# v2 // Vector 2D\n"
+ "# v3 // Vector 3D\n"
+ "# v4 // Vector 4D\n"
+ "# r // Rectangle\n"
+ "# c // Color\n"
+ "#\n\n");
+ for(int p=0; p= 1)
+ {
+ DrawText(TextFormat("FOCUS:%i | SCROLL:%i | FPS:%i", focus, scroll, GetFPS()), prop[8].value.v2.x, prop[8].value.v2.y, 20, prop[11].value.vcolor);
+ }
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ GuiDMSaveProperties("test.props", prop, SIZEOF(prop)); // Save properties to `test.props` file at exit
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/property_list/test.props b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/property_list/test.props
new file mode 100644
index 0000000000..3208dd08a8
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/property_list/test.props
@@ -0,0 +1,27 @@
+#
+# Property types:
+# b // Bool
+# i // Int
+# f // Float
+# t // Text
+# l // Select
+# g // Section (Group)
+# v2 // Vector 2D
+# v3 // Vector 3D
+# v4 // Vector 4D
+# r // Rectangle
+# c // Color
+#
+
+b Bool 0 1
+g #102#SECTION 0 2
+i Int 0 123 0 0 1
+f Float 0 0.990000 0.000000 0.000000 1.000000 3
+t Text 1 Hello! 30
+l Select 0 ONE;TWO;THREE;FOUR 3
+i Int Range 0 32 0 100 1
+r Rect 1 0 0 100 200
+v2 Vec2 1 20.000000 20.000000
+v3 Vec3 1 12.000000 13.000000 14.000000
+v4 Vec4 1 12.000000 13.000000 14.000000 15.000000
+c Color 1 94 68 197 160
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/raygui.ico b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/raygui.ico
new file mode 100644
index 0000000000..cc8498b123
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/raygui.ico differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/raygui.rc b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/raygui.rc
new file mode 100644
index 0000000000..8dc1e71823
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/raygui.rc
@@ -0,0 +1,27 @@
+GLFW_ICON ICON "raygui.ico"
+
+1 VERSIONINFO
+FILEVERSION 4,0,0,0
+PRODUCTVERSION 4,0,0,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ //BLOCK "080904E4" // English UK
+ BLOCK "040904E4" // English US
+ BEGIN
+ //VALUE "CompanyName", "raylib technologies"
+ VALUE "FileDescription", "raygui application (www.raylib.com)"
+ VALUE "FileVersion", "4.0.0"
+ VALUE "InternalName", "raygui app"
+ VALUE "LegalCopyright", "(c) 2023 Ramon Santamaria (@raysan5)"
+ //VALUE "OriginalFilename", "raygui_app.exe"
+ VALUE "ProductName", "raygui app"
+ VALUE "ProductVersion", "4.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ //VALUE "Translation", 0x809, 1252 // English UK
+ VALUE "Translation", 0x409, 1252 // English US
+ END
+END
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/scroll_panel/scroll_panel.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/scroll_panel/scroll_panel.c
new file mode 100644
index 0000000000..9c2ae1f325
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/scroll_panel/scroll_panel.c
@@ -0,0 +1,153 @@
+/*******************************************************************************************
+*
+* raygui - Controls test
+*
+* TEST CONTROLS:
+* - GuiScrollPanel()
+*
+* DEPENDENCIES:
+* raylib 4.0 - Windowing/input management and drawing.
+* raygui 3.0 - Immediate-mode GUI controls.
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* COMPILATION (Linux - gcc):
+* gcc -o $(NAME_PART) $(FILE_NAME) -I../../src -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2019-2024 Vlad Adrian (@Demizdor) and Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+#include "../../src/raygui.h"
+
+
+static void DrawStyleEditControls(void); // Draw and process scroll bar style edition controls
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raygui - GuiScrollPanel()");
+
+ Rectangle panelRec = { 20, 40, 200, 150 };
+ Rectangle panelContentRec = {0, 0, 340, 340 };
+ Rectangle panelView = { 0 };
+ Vector2 panelScroll = { 99, -20 };
+
+ bool showContentArea = true;
+
+ SetTargetFPS(60);
+ //---------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ // TODO: Implement required update logic
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ DrawText(TextFormat("[%f, %f]", panelScroll.x, panelScroll.y), 4, 4, 20, RED);
+
+ GuiScrollPanel(panelRec, NULL, panelContentRec, &panelScroll, &panelView);
+
+ BeginScissorMode(panelView.x, panelView.y, panelView.width, panelView.height);
+ GuiGrid((Rectangle){panelRec.x + panelScroll.x, panelRec.y + panelScroll.y, panelContentRec.width, panelContentRec.height}, NULL, 16, 3, NULL);
+ EndScissorMode();
+
+ if (showContentArea) DrawRectangle(panelRec.x + panelScroll.x, panelRec.y + panelScroll.y, panelContentRec.width, panelContentRec.height, Fade(RED, 0.1));
+
+ DrawStyleEditControls();
+
+ GuiCheckBox((Rectangle){ 565, 80, 20, 20 }, "SHOW CONTENT AREA", &showContentArea);
+
+ GuiSliderBar((Rectangle){ 590, 385, 145, 15}, "WIDTH", TextFormat("%i", (int)panelContentRec.width), &panelContentRec.width, 1, 600);
+ GuiSliderBar((Rectangle){ 590, 410, 145, 15 }, "HEIGHT", TextFormat("%i", (int)panelContentRec.height), &panelContentRec.height, 1, 400);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+// Draw and process scroll bar style edition controls
+static void DrawStyleEditControls(void)
+{
+ // ScrollPanel style controls
+ //----------------------------------------------------------
+ GuiGroupBox((Rectangle){ 550, 170, 220, 205 }, "SCROLLBAR STYLE");
+
+ int style = GuiGetStyle(SCROLLBAR, BORDER_WIDTH);
+ GuiLabel((Rectangle){ 555, 195, 110, 10 }, "BORDER_WIDTH");
+ GuiSpinner((Rectangle){ 670, 190, 90, 20 }, NULL, &style, 0, 6, false);
+ GuiSetStyle(SCROLLBAR, BORDER_WIDTH, style);
+
+ style = GuiGetStyle(SCROLLBAR, ARROWS_SIZE);
+ GuiLabel((Rectangle){ 555, 220, 110, 10 }, "ARROWS_SIZE");
+ GuiSpinner((Rectangle){ 670, 215, 90, 20 }, NULL, &style, 4, 14, false);
+ GuiSetStyle(SCROLLBAR, ARROWS_SIZE, style);
+
+ style = GuiGetStyle(SCROLLBAR, SLIDER_PADDING);
+ GuiLabel((Rectangle){ 555, 245, 110, 10 }, "SLIDER_PADDING");
+ GuiSpinner((Rectangle){ 670, 240, 90, 20 }, NULL, &style, 0, 14, false);
+ GuiSetStyle(SCROLLBAR, SLIDER_PADDING, style);
+
+ bool scrollBarArrows = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE);
+ GuiCheckBox((Rectangle){ 565, 280, 20, 20 }, "ARROWS_VISIBLE", &scrollBarArrows);
+ GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, scrollBarArrows);
+
+ style = GuiGetStyle(SCROLLBAR, SLIDER_PADDING);
+ GuiLabel((Rectangle){ 555, 325, 110, 10 }, "SLIDER_PADDING");
+ GuiSpinner((Rectangle){ 670, 320, 90, 20 }, NULL, &style, 0, 14, false);
+ GuiSetStyle(SCROLLBAR, SLIDER_PADDING, style);
+
+ style = GuiGetStyle(SCROLLBAR, SLIDER_WIDTH);
+ GuiLabel((Rectangle){ 555, 350, 110, 10 }, "SLIDER_WIDTH");
+ GuiSpinner((Rectangle){ 670, 345, 90, 20 }, NULL, &style, 2, 100, false);
+ GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, style);
+
+ const char *text = GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE? "SCROLLBAR: LEFT" : "SCROLLBAR: RIGHT";
+ bool toggleScrollBarSide = GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE);
+ GuiToggle((Rectangle){ 560, 110, 200, 35 }, text, &toggleScrollBarSide);
+ GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, toggleScrollBarSide);
+ //----------------------------------------------------------
+
+ // ScrollBar style controls
+ //----------------------------------------------------------
+ GuiGroupBox((Rectangle){ 550, 20, 220, 135 }, "SCROLLPANEL STYLE");
+
+ style = GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
+ GuiLabel((Rectangle){ 555, 35, 110, 10 }, "SCROLLBAR_WIDTH");
+ GuiSpinner((Rectangle){ 670, 30, 90, 20 }, NULL, &style, 6, 30, false);
+ GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, style);
+
+ style = GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ GuiLabel((Rectangle){ 555, 60, 110, 10 }, "BORDER_WIDTH");
+ GuiSpinner((Rectangle){ 670, 55, 90, 20 }, NULL, &style, 0, 20, false);
+ GuiSetStyle(DEFAULT, BORDER_WIDTH, style);
+ //----------------------------------------------------------
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/standalone/raygui_custom_backend.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/standalone/raygui_custom_backend.h
new file mode 100644
index 0000000000..e430d153fa
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/standalone/raygui_custom_backend.h
@@ -0,0 +1,181 @@
+/*******************************************************************************************
+*
+* raygui - Standalone mode custom backend
+*
+* Just edit this file to include your custom implementation to your graphic API
+*
+* LICENSE:
+*
+* Copyright (c)
+*
+**********************************************************************************************/
+
+//#include "my_cool_graphic_api.h"
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+// TODO: Define input keys required by raygui
+//----------------------------------------------------------------------------------
+#define KEY_RIGHT 262
+#define KEY_LEFT 263
+#define KEY_DOWN 264
+#define KEY_UP 265
+#define KEY_BACKSPACE 259
+#define KEY_ENTER 257
+#define MOUSE_LEFT_BUTTON 0
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+// TODO: Define required structures, maybe Font/Texture2D should be defined here?
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+// TODO: Define all raygui required functions (previously provided by raylib)
+//----------------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------
+// Input required functions
+//-------------------------------------------------------------------------------
+static Vector2 GetMousePosition(void)
+{
+ Vector2 position = { 0 };
+
+ // TODO: Mouse position
+
+ return position;
+}
+
+static int GetMouseWheelMove(void)
+{
+ // TODO: Mouse wheel movement variation, reseted every frame
+
+ return 0;
+}
+
+static bool IsMouseButtonDown(int button)
+{
+ // TODO: Return true while mouse button [0..2] is being down
+
+ return false;
+}
+
+static bool IsMouseButtonPressed(int button)
+{
+ // TODO: Return true when mouse button [0..2] has been pressed: up->down
+
+ return false;
+}
+
+static bool IsMouseButtonReleased(int button)
+{
+ // TODO: Return true when mouse button [0..2] has been released: down->up
+
+ return false;
+}
+
+static bool IsKeyDown(int key)
+{
+ // TODO: Return true while key is being down
+
+ return false;
+}
+
+static bool IsKeyPressed(int key)
+{
+ // TODO: Return true when key has been pressed: up->down
+
+ return false;
+}
+
+// USED IN: GuiTextBox(), GuiValueBox()
+static int GetKeyPressed(void)
+{
+ // TODO: Return last key pressed (up->down) in the frame
+
+ return 0;
+}
+
+//-------------------------------------------------------------------------------
+// Drawing required functions
+//-------------------------------------------------------------------------------
+static void DrawRectangle(int x, int y, int width, int height, Color color)
+{
+ // TODO: Draw rectangle on the screen
+}
+
+// USED IN: GuiColorPicker()
+static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
+{
+ // TODO: Draw rectangle with gradients (4 vertex colors) on the screen
+}
+
+// USED IN: GuiDropdownBox(), GuiScrollBar()
+static void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
+{
+ // TODO: Draw triangle on the screen, required for arrows
+}
+
+//-------------------------------------------------------------------------------
+// Text required functions
+//-------------------------------------------------------------------------------
+// USED IN: GuiLoadStyleDefault()
+static Font GetFontDefault(void)
+{
+ Font font = { 0 };
+
+ // TODO: Return default rendering Font for the UI
+
+ return font;
+}
+
+// USED IN: GetTextWidth()
+static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
+{
+ Vector2 size = { 0 };
+
+ // TODO: Return text size (width, height) on screen depending on the Font, text, fontSize and spacing
+
+ return size;
+}
+
+// USED IN: GuiDrawText()
+static void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint)
+{
+ // TODO: Draw text on the screen
+}
+
+//-------------------------------------------------------------------------------
+// GuiLoadStyle() required functions
+//-------------------------------------------------------------------------------
+static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount)
+{
+ Font font = { 0 };
+
+ // TODO: Load a new font from a file
+
+ return font;
+}
+
+static char *LoadText(const char *fileName)
+{
+ // TODO: Load text file data, used by GuiLoadStyle() to load characters list required on Font generation,
+ // this is a .rgs feature, probably this function is not required in most cases
+
+ return NULL;
+}
+
+static const char *GetDirectoryPath(const char *filePath)
+{
+ // TODO: Get directory path for .rgs file, required to look for a possible .ttf/.otf font file referenced,
+ // this is a .rgs feature, probably this function is not required in most cases
+
+ return NULL;
+}
+
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/standalone/raygui_standalone.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/standalone/raygui_standalone.c
new file mode 100644
index 0000000000..2fbc8a2dbb
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/standalone/raygui_standalone.c
@@ -0,0 +1,36 @@
+/*******************************************************************************************
+*
+* raygui - Standalone mode usage template
+*
+* DEPENDENCIES:
+* raygui 2.6 - Immediate-mode GUI controls.
+*
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2020 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#define RAYGUI_IMPLEMENTATION
+#define RAYGUI_STANDALONE
+#include "../../src/raygui.h"
+
+#include "custom_backend.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // TODO: Initialize your systems (window, graphics, inputs)
+
+ // TODO: Create your game loop
+ {
+ // TODO: Use raygui API
+ }
+
+ // TODO: De-initialize all resources
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/style_selector/style_selector.c b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/style_selector/style_selector.c
new file mode 100644
index 0000000000..b4afe66950
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/style_selector/style_selector.c
@@ -0,0 +1,145 @@
+/*******************************************************************************************
+*
+* raygui - style selector
+*
+* DEPENDENCIES:
+* raylib 4.5 - Windowing/input management and drawing
+* raygui 3.5 - Immediate-mode GUI controls with custom styling and icons
+*
+* COMPILATION (Windows - MinGW):
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5)
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#define RAYGUI_IMPLEMENTATION
+//#define RAYGUI_CUSTOM_ICONS // It requires providing gui_icons.h in the same directory
+//#include "gui_icons.h" // External icons data provided, it can be generated with rGuiIcons tool
+#include "../../src/raygui.h"
+
+// raygui embedded styles
+// NOTE: Included in the same order as selector
+#define MAX_GUI_STYLES_AVAILABLE 12 // NOTE: Included light style
+#include "../styles/style_jungle.h" // raygui style: jungle
+#include "../styles/style_candy.h" // raygui style: candy
+#include "../styles/style_lavanda.h" // raygui style: lavanda
+#include "../styles/style_cyber.h" // raygui style: cyber
+#include "../styles/style_terminal.h" // raygui style: terminal
+#include "../styles/style_ashes.h" // raygui style: ashes
+#include "../styles/style_bluish.h" // raygui style: bluish
+#include "../styles/style_dark.h" // raygui style: dark
+#include "../styles/style_cherry.h" // raygui style: cherry
+#include "../styles/style_sunny.h" // raygui style: sunny
+#include "../styles/style_enefete.h" // raygui style: enefete
+
+#include // Required for: strcpy()
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //---------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 480;
+
+ InitWindow(screenWidth, screenHeight, "raygui - styles selector");
+ SetExitKey(0);
+
+ // Custom GUI font loading
+ //Font font = LoadFontEx("fonts/custom_font.ttf", 12, 0, 0);
+ //GuiSetFont(font);
+
+ bool exitWindow = false;
+ bool showMessageBox = false;
+
+ // Load default style
+ GuiLoadStyleBluish();
+ int visualStyleActive = 4;
+ int prevVisualStyleActive = 4;
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!exitWindow) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ exitWindow = WindowShouldClose();
+
+ if (IsKeyPressed(KEY_ESCAPE)) showMessageBox = !showMessageBox;
+
+ if (IsFileDropped())
+ {
+ FilePathList droppedFiles = LoadDroppedFiles();
+
+ if ((droppedFiles.count > 0) && IsFileExtension(droppedFiles.paths[0], ".rgs")) GuiLoadStyle(droppedFiles.paths[0]);
+
+ UnloadDroppedFiles(droppedFiles); // Clear internal buffers
+ }
+
+ if (visualStyleActive != prevVisualStyleActive)
+ {
+ // Reset to default internal style
+ // NOTE: Required to unload any previously loaded font texture
+ GuiLoadStyleDefault();
+
+ switch (visualStyleActive)
+ {
+ case 1: GuiLoadStyleJungle(); break;
+ case 2: GuiLoadStyleCandy(); break;
+ case 3: GuiLoadStyleLavanda(); break;
+ case 4: GuiLoadStyleCyber(); break;
+ case 5: GuiLoadStyleTerminal(); break;
+ case 6: GuiLoadStyleAshes(); break;
+ case 7: GuiLoadStyleBluish(); break;
+ case 8: GuiLoadStyleDark(); break;
+ case 9: GuiLoadStyleCherry(); break;
+ case 10: GuiLoadStyleSunny(); break;
+ case 11: GuiLoadStyleEnefete(); break;
+ default: break;
+ }
+
+ prevVisualStyleActive = visualStyleActive;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
+
+ // Visuals options
+ GuiLabel((Rectangle){ 10, 10, 60, 24 }, "Style:");
+ GuiComboBox((Rectangle){ 60,10, 120, 24 }, "default;Jungle;Candy;Lavanda;Cyber;Terminal;Ashes;Bluish;Dark;Cherry;Sunny;Enefete", &visualStyleActive);
+
+ DrawRectangle(10, 44, GuiGetFont().texture.width, GuiGetFont().texture.height, BLACK);
+ DrawTexture(GuiGetFont().texture, 10, 44, WHITE);
+ DrawRectangleLines(10, 44, GuiGetFont().texture.width, GuiGetFont().texture.height,
+ GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)));
+
+ //GuiSetIconScale(2);
+ //GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT);
+ //GuiButton((Rectangle){ 25, 255, 300, 30 }, GuiIconText(ICON_FILE_SAVE, "Save File"));
+ //GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ //----------------------------------------------------------------------------------
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_amber.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_amber.h
new file mode 100644
index 0000000000..dee6e87088
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_amber.h
@@ -0,0 +1,606 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleAmber(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define AMBER_STYLE_PROPS_COUNT 16
+
+// Custom style name: Amber
+static const GuiStyleProp amberStyleProps[AMBER_STYLE_PROPS_COUNT] = {
+ { 0, 0, (int)0x898988ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, (int)0x292929ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, (int)0xd4d4d4ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, (int)0xeb891dff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, (int)0x292929ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, (int)0xffffffff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, (int)0xf1cf9dff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, (int)0xf39333ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, (int)0x282020ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, (int)0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, (int)0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, (int)0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, (int)0x00000010 }, // DEFAULT_TEXT_SIZE
+ { 0, 18, (int)0xef922aff }, // DEFAULT_LINE_COLOR
+ { 0, 19, (int)0x333333ff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, (int)0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "hello-world.ttf" (size: 16, spacing: 1)
+
+#define AMBER_STYLE_FONT_ATLAS_COMP_SIZE 2605
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char amberFontData[AMBER_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0x8b, 0x8e, 0x9c, 0xb8, 0x12, 0x00, 0x50, 0xf8, 0xff, 0x7f, 0x76, 0x5d, 0xe9, 0x66, 0xb3, 0xd2, 0xee, 0x8e, 0x6d,
+ 0xaa, 0x30, 0x8f, 0xee, 0x9c, 0x1c, 0x45, 0x91, 0x9a, 0x34, 0x18, 0xdb, 0x85, 0x0d, 0x33, 0x94, 0x63, 0x03, 0x00, 0x00,
+ 0x00, 0x88, 0x2d, 0x5a, 0xe7, 0xb3, 0xcc, 0xe7, 0x5b, 0xf7, 0xf3, 0xf6, 0xd7, 0xe7, 0x6d, 0xb0, 0xed, 0xe8, 0xbe, 0xfa,
+ 0x65, 0xda, 0x92, 0xfb, 0x89, 0xee, 0x37, 0xe2, 0x87, 0x4f, 0x7e, 0xff, 0xc9, 0xec, 0xa7, 0x77, 0xbe, 0xf9, 0xda, 0xcb,
+ 0x6e, 0x19, 0x1f, 0xbd, 0x25, 0x4b, 0x56, 0xff, 0xce, 0xd1, 0x7a, 0xcf, 0xd4, 0xe1, 0xef, 0x3f, 0x2d, 0xb1, 0x97, 0x71,
+ 0x79, 0x7e, 0xde, 0xdb, 0x36, 0x39, 0xeb, 0xdc, 0x79, 0xb7, 0xe9, 0x96, 0xda, 0xb7, 0xd6, 0xc4, 0x7f, 0xaf, 0x4d, 0x32,
+ 0x9f, 0x6f, 0xdd, 0x7a, 0xfc, 0x15, 0x37, 0xbd, 0xb8, 0xdd, 0x13, 0xfd, 0xa4, 0x17, 0x23, 0xfb, 0x20, 0xca, 0x23, 0xb5,
+ 0xff, 0x71, 0x2f, 0x5a, 0x71, 0x4d, 0xed, 0x95, 0xf6, 0xe7, 0xab, 0x4b, 0xff, 0x1b, 0x6d, 0x78, 0xe6, 0xb5, 0x6b, 0x55,
+ 0xbf, 0x1e, 0xf7, 0x1f, 0xbe, 0x5b, 0x2b, 0xdb, 0xf1, 0x72, 0x45, 0xba, 0x2d, 0x62, 0xd8, 0x6b, 0xf6, 0xee, 0x35, 0x23,
+ 0x77, 0x76, 0x51, 0x38, 0xef, 0x98, 0x6c, 0xd9, 0x52, 0xa3, 0x5a, 0x5b, 0x3c, 0xfe, 0xaf, 0x88, 0xff, 0xf8, 0x7f, 0x2d,
+ 0xee, 0xa9, 0xf1, 0x36, 0x92, 0x65, 0xca, 0x47, 0xed, 0xde, 0x39, 0x6e, 0x7f, 0x3c, 0xbf, 0xba, 0x4e, 0x7b, 0xdb, 0xf6,
+ 0x42, 0x6d, 0xf4, 0xb6, 0xb4, 0xee, 0x79, 0x6f, 0xe5, 0xab, 0x5e, 0x24, 0xce, 0x26, 0x4e, 0x5f, 0x4b, 0x63, 0xd0, 0xd2,
+ 0xe3, 0xb6, 0x8b, 0x74, 0x49, 0xa3, 0xf0, 0x9d, 0xf1, 0x96, 0x6d, 0xe9, 0x77, 0xae, 0x1b, 0xa3, 0xf2, 0xfb, 0x1b, 0xcf,
+ 0xbe, 0xa2, 0x18, 0x0f, 0xe7, 0xcb, 0xb9, 0xa7, 0xaf, 0x89, 0x71, 0xf1, 0x3d, 0x55, 0x36, 0xfe, 0xb7, 0x85, 0xf1, 0x1f,
+ 0xe9, 0xfa, 0xbe, 0x2f, 0xfe, 0x9f, 0x18, 0xff, 0xb7, 0x49, 0xfc, 0x6f, 0xe2, 0x3f, 0xf5, 0x7f, 0x73, 0xf7, 0x05, 0xe3,
+ 0x71, 0x3b, 0x12, 0xf3, 0x99, 0x58, 0x18, 0xcf, 0x71, 0x7b, 0xf4, 0x8f, 0x7a, 0x5b, 0x65, 0x26, 0xd8, 0xbf, 0xdf, 0xea,
+ 0xc7, 0xd9, 0xe8, 0x1e, 0x2d, 0xd2, 0x33, 0xce, 0xd1, 0xdd, 0x55, 0xe6, 0x79, 0x49, 0x2c, 0xeb, 0x99, 0x5b, 0x29, 0xfe,
+ 0x23, 0xf5, 0xcc, 0x27, 0x26, 0x35, 0x9f, 0x8d, 0xff, 0x18, 0x5c, 0xff, 0x46, 0xfd, 0x28, 0x2e, 0xbd, 0xff, 0xcf, 0xc6,
+ 0xff, 0x36, 0x99, 0x95, 0x6d, 0xa9, 0x9e, 0x5a, 0x29, 0x65, 0x7b, 0xd1, 0x13, 0xd5, 0x95, 0xf1, 0x1f, 0xc9, 0xb3, 0x8e,
+ 0x03, 0x4f, 0xc3, 0x7a, 0xc7, 0xa8, 0xdc, 0xbd, 0xb5, 0x93, 0xfd, 0x2a, 0x1e, 0x6c, 0x93, 0x33, 0x23, 0x76, 0x7b, 0x7c,
+ 0xfc, 0x8f, 0xc7, 0xe6, 0xff, 0x91, 0x9e, 0x1b, 0x5c, 0x1f, 0xff, 0xf1, 0xf2, 0xe8, 0xaf, 0xcd, 0xff, 0xa3, 0x38, 0x2f,
+ 0x8f, 0x45, 0x73, 0xf9, 0xea, 0xdd, 0xcc, 0xbb, 0x5a, 0x64, 0x9b, 0x3e, 0x4f, 0xf8, 0xc4, 0xf9, 0x7f, 0x3c, 0x54, 0x8f,
+ 0x51, 0xb8, 0x37, 0x10, 0xff, 0x95, 0xf8, 0xaf, 0xcd, 0x69, 0x67, 0x4f, 0x37, 0x63, 0xe9, 0x95, 0xe9, 0xb3, 0xe3, 0xbf,
+ 0x1e, 0xb1, 0xe2, 0xff, 0xe8, 0xdc, 0x36, 0x86, 0xcf, 0x65, 0x63, 0x49, 0x1b, 0x7e, 0xc6, 0x58, 0xb3, 0x2e, 0xfe, 0xe3,
+ 0xc4, 0x5d, 0xc3, 0x9f, 0x18, 0xff, 0xdb, 0x8d, 0xf1, 0x1f, 0x5f, 0x3b, 0xff, 0xaf, 0xdc, 0xff, 0xc7, 0xf0, 0x27, 0xd2,
+ 0xb1, 0x68, 0x06, 0xf0, 0xfe, 0xd1, 0xbf, 0xf2, 0xb4, 0x67, 0xfc, 0x9b, 0x47, 0x91, 0xfe, 0xb9, 0x40, 0xe5, 0x69, 0xd3,
+ 0x6c, 0xee, 0xbc, 0xa5, 0xcb, 0xf6, 0xe9, 0xe3, 0x7f, 0xfe, 0xbc, 0x63, 0xba, 0x25, 0x0a, 0xfd, 0xe8, 0x6d, 0xd7, 0xd7,
+ 0x78, 0x7c, 0x64, 0x05, 0xbe, 0x97, 0xf8, 0x07, 0x57, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x77, 0x6a, 0xff, 0xfa, 0xf7, 0x9f, 0xdb, 0xda, 0x8f, 0xd9, 0x8c, 0x5b, 0x77, 0x4b, 0x6f, 0x5f, 0xad,
+ 0x70, 0xfc, 0x7c, 0xc9, 0x56, 0xe7, 0x60, 0xdf, 0x06, 0x67, 0x5a, 0xaf, 0x83, 0xeb, 0xb7, 0x8c, 0x4b, 0x9d, 0x69, 0x9b,
+ 0x7e, 0xbd, 0x6c, 0xa9, 0x77, 0x92, 0x73, 0x79, 0x02, 0xdb, 0xe4, 0x0d, 0xd7, 0xec, 0xba, 0x0e, 0xb3, 0x1c, 0x86, 0x99,
+ 0xcc, 0x87, 0xed, 0x50, 0x34, 0xcd, 0x3f, 0xcf, 0x96, 0x67, 0x1b, 0x66, 0xc5, 0x8c, 0x72, 0xde, 0xbf, 0x5a, 0xee, 0xe9,
+ 0x3d, 0x99, 0xf9, 0x69, 0xf4, 0x3e, 0x7a, 0x4b, 0x67, 0x67, 0xbe, 0x2b, 0x07, 0xfb, 0xa8, 0x3e, 0xf7, 0x74, 0xf6, 0x8b,
+ 0xca, 0x96, 0xbd, 0xbb, 0xae, 0xca, 0x2c, 0xd7, 0xc3, 0x7e, 0xb8, 0x15, 0x46, 0x39, 0x92, 0xf7, 0x6e, 0x1e, 0xf1, 0x5c,
+ 0x5f, 0x5b, 0x95, 0xfb, 0x3e, 0xa6, 0x25, 0x8e, 0xe4, 0x77, 0xda, 0xf0, 0x38, 0x71, 0xd9, 0x3b, 0x65, 0x91, 0xac, 0xad,
+ 0xed, 0xef, 0x1c, 0x1b, 0xb9, 0xba, 0x3c, 0x13, 0xff, 0x95, 0xfc, 0xd2, 0x5b, 0x3a, 0x03, 0xea, 0xde, 0xc9, 0x4b, 0xff,
+ 0xfb, 0x7a, 0x76, 0x57, 0xa6, 0x95, 0x6c, 0x5b, 0xdf, 0x11, 0xff, 0xf3, 0xdc, 0x69, 0x91, 0x1a, 0x07, 0xf3, 0x7d, 0xf1,
+ 0x89, 0xdc, 0x0d, 0x77, 0xe5, 0x23, 0x3f, 0xd3, 0x8a, 0x57, 0xc6, 0x7f, 0x3e, 0x4f, 0x6c, 0x3d, 0xf3, 0xcf, 0xfa, 0xf8,
+ 0xcf, 0xe7, 0xab, 0x8a, 0x6e, 0x3e, 0x15, 0xf1, 0x5f, 0x8d, 0xff, 0xf8, 0x80, 0xf8, 0x5f, 0x99, 0x49, 0x7b, 0xb6, 0xb7,
+ 0x48, 0x65, 0x3e, 0x9f, 0x65, 0xf9, 0x69, 0x83, 0xb9, 0xec, 0xb1, 0xbb, 0x8f, 0x38, 0x30, 0xff, 0xb8, 0x27, 0xfe, 0x67,
+ 0x99, 0x7b, 0x73, 0xfd, 0xab, 0xba, 0x9f, 0x55, 0x6b, 0x30, 0xcc, 0x7a, 0x4e, 0xb6, 0x45, 0x23, 0xb9, 0x52, 0xe0, 0xea,
+ 0xf8, 0x1f, 0x47, 0x6d, 0xad, 0x6c, 0xdb, 0xd2, 0x11, 0xf7, 0xec, 0x08, 0x18, 0x4b, 0xef, 0x0c, 0xee, 0xb9, 0x8a, 0xef,
+ 0xa7, 0x57, 0x8f, 0x8b, 0xe1, 0x1d, 0xe6, 0xba, 0xbe, 0x75, 0xef, 0xf8, 0x1f, 0x8b, 0xf3, 0xa9, 0xc7, 0x8d, 0x99, 0x56,
+ 0xf3, 0xab, 0x5c, 0x64, 0xeb, 0xb3, 0x92, 0x23, 0x35, 0x9f, 0x55, 0xf9, 0x5b, 0xe2, 0xff, 0xfa, 0x2d, 0xeb, 0x23, 0x2d,
+ 0x17, 0xff, 0x71, 0xc3, 0xdc, 0xf2, 0x13, 0xe6, 0xff, 0xdb, 0x30, 0x5f, 0xfd, 0x5d, 0xf1, 0x5f, 0x6d, 0x8d, 0x6b, 0xe3,
+ 0x3f, 0x0a, 0xf3, 0xf6, 0x95, 0xf3, 0xfc, 0x67, 0xe6, 0xff, 0xe3, 0x31, 0x26, 0xd2, 0xf5, 0x5e, 0xcd, 0x61, 0x7a, 0x65,
+ 0xfc, 0xc7, 0x2d, 0xf7, 0x96, 0xf7, 0xc7, 0xff, 0xda, 0xb8, 0x5c, 0x1b, 0xff, 0x2b, 0xd7, 0xab, 0x10, 0xff, 0xf7, 0xcf,
+ 0x0c, 0xd6, 0x7e, 0xa7, 0x72, 0x77, 0xf0, 0xe4, 0xf8, 0x7f, 0x7f, 0x5d, 0x3f, 0x1f, 0xff, 0x2b, 0xe7, 0xff, 0xf1, 0x70,
+ 0xfc, 0x57, 0xd6, 0xff, 0xba, 0x67, 0x96, 0x2f, 0xfe, 0x9f, 0x88, 0xff, 0x37, 0xd4, 0x7a, 0x7e, 0xde, 0x34, 0x7f, 0x5a,
+ 0x98, 0x5b, 0x35, 0xb1, 0xf6, 0x54, 0x3c, 0x8a, 0x2b, 0x87, 0x47, 0xa1, 0xd4, 0x95, 0x99, 0xe3, 0xb6, 0xe4, 0x5e, 0xbe,
+ 0x76, 0x35, 0xa9, 0x64, 0x8e, 0xaf, 0xae, 0x33, 0x76, 0xe7, 0x7d, 0xc1, 0x35, 0xdf, 0xca, 0xb5, 0x62, 0x4c, 0xeb, 0x7e,
+ 0xc5, 0x75, 0x64, 0x7b, 0x61, 0x16, 0x7f, 0x3e, 0x5d, 0xdc, 0xf4, 0x1d, 0xd4, 0x22, 0xe2, 0x1f, 0xb5, 0xc8, 0x9b, 0x7a,
+ 0x61, 0x24, 0xef, 0xa9, 0xcd, 0x42, 0xd7, 0xd4, 0xba, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x56, 0xfd, 0x7e, 0x72, 0x36, 0xa7, 0xf8, 0x28, 0x6f, 0x62, 0x7e, 0x7f, 0xb3, 0x2c, 0x68, 0xed, 0xc1, 0x2d, 0xa3,
+ 0x5a, 0x68, 0x07, 0xcf, 0xa6, 0x25, 0xf3, 0xbc, 0xf5, 0xeb, 0xa4, 0x9f, 0x5f, 0xbe, 0x25, 0xb7, 0xb5, 0xc9, 0x1e, 0x8f,
+ 0xee, 0xfd, 0x78, 0x1b, 0xf7, 0xb3, 0xa8, 0xe5, 0xea, 0xbd, 0x9f, 0x99, 0xbf, 0x25, 0x57, 0x2c, 0x98, 0xd5, 0xe8, 0x96,
+ 0x68, 0xc9, 0x23, 0xbd, 0x69, 0xb4, 0xd6, 0xc4, 0xd1, 0x76, 0x38, 0x7a, 0x0e, 0x71, 0xf0, 0xad, 0xa3, 0x59, 0xae, 0xc5,
+ 0xd1, 0x96, 0x4c, 0x56, 0xa3, 0x33, 0xb9, 0x27, 0x56, 0xe6, 0xd2, 0x5d, 0x95, 0x4b, 0x3f, 0x97, 0xbb, 0x71, 0x1f, 0xb6,
+ 0x51, 0x9c, 0xbc, 0x52, 0xb7, 0xc1, 0x31, 0x5a, 0x21, 0xef, 0xc3, 0xf1, 0xbd, 0x1f, 0x6f, 0xe3, 0x3d, 0x9d, 0xdd, 0x64,
+ 0x65, 0xfe, 0xfd, 0x96, 0xce, 0xd8, 0xb9, 0x27, 0x57, 0xc4, 0x38, 0x9e, 0x4f, 0x62, 0x4f, 0x67, 0xae, 0x98, 0xf5, 0xc3,
+ 0xfd, 0xc4, 0x15, 0xe0, 0xce, 0xfc, 0x3b, 0x6f, 0x88, 0xff, 0x55, 0xb9, 0xb4, 0xaf, 0xce, 0xca, 0xd3, 0xba, 0xa5, 0x6f,
+ 0x17, 0xd7, 0x6d, 0x3d, 0xe2, 0x62, 0x98, 0x01, 0x23, 0xca, 0x63, 0xd4, 0xd1, 0x63, 0x8c, 0x22, 0x67, 0xb4, 0x62, 0xd1,
+ 0xf1, 0xeb, 0x66, 0x2c, 0x88, 0xff, 0x33, 0x6f, 0x03, 0x1f, 0x1f, 0x5b, 0x8e, 0xd6, 0xef, 0x7d, 0x19, 0xf3, 0xc7, 0x39,
+ 0xd8, 0x73, 0x59, 0xd8, 0x57, 0x67, 0xcc, 0x59, 0x17, 0xe7, 0xab, 0xf2, 0xe8, 0xe4, 0xa2, 0x25, 0xd2, 0xf3, 0xf1, 0x4c,
+ 0xfc, 0xc7, 0xe1, 0xd9, 0x7f, 0x36, 0x9f, 0x4d, 0x3e, 0x1a, 0x62, 0xf1, 0x1b, 0xb5, 0xfd, 0xf2, 0xb6, 0x8b, 0xc6, 0xff,
+ 0xd5, 0xf1, 0xbf, 0x9d, 0x88, 0xfe, 0x7b, 0x57, 0xcc, 0xd8, 0x8a, 0xeb, 0x52, 0x5c, 0x9d, 0x4b, 0x33, 0x0a, 0x65, 0x7b,
+ 0x2e, 0xfe, 0xb3, 0x2b, 0x18, 0x8c, 0x8e, 0xd0, 0x0e, 0x97, 0xa4, 0x5d, 0x14, 0x9b, 0x51, 0xec, 0xd5, 0xf1, 0x48, 0x66,
+ 0x8e, 0x73, 0xe3, 0xff, 0x76, 0x3a, 0xfe, 0xd7, 0xd7, 0xab, 0xf8, 0xaf, 0xcf, 0x67, 0xee, 0x8d, 0xff, 0xad, 0xb0, 0x4e,
+ 0x4b, 0x14, 0x66, 0x5d, 0xf5, 0x2b, 0xc0, 0x5d, 0xfd, 0xfa, 0xed, 0xcf, 0xd3, 0x67, 0xfd, 0xe0, 0x5d, 0xe7, 0x30, 0xeb,
+ 0x21, 0x99, 0x7e, 0x15, 0x93, 0xa3, 0xe4, 0xef, 0x8d, 0x2b, 0x7d, 0x7e, 0x2b, 0x66, 0x88, 0xaf, 0xe4, 0x2d, 0x3d, 0x7f,
+ 0xbf, 0x70, 0xfe, 0x2a, 0x52, 0x5d, 0xbf, 0x2b, 0x4e, 0xf7, 0x91, 0x4c, 0x7b, 0xad, 0xed, 0xaf, 0xef, 0xbd, 0x0e, 0xcc,
+ 0xb3, 0xc6, 0x7e, 0x46, 0x3e, 0xa0, 0xb8, 0xed, 0x5a, 0xfc, 0x96, 0xfa, 0x88, 0x45, 0x77, 0x8e, 0x57, 0x8d, 0xff, 0x6b,
+ 0x9f, 0xad, 0x66, 0xe3, 0xe8, 0xfb, 0xb2, 0x58, 0xc5, 0x25, 0xd7, 0x92, 0x58, 0x7a, 0xbf, 0x23, 0xfe, 0xc5, 0xff, 0x15,
+ 0xf1, 0x7f, 0xfc, 0x18, 0xf1, 0xb5, 0xf1, 0xff, 0x44, 0x2f, 0x12, 0xff, 0x67, 0xe6, 0x97, 0x6f, 0x9a, 0x51, 0x5e, 0x1b,
+ 0xff, 0xeb, 0xc6, 0xb1, 0xca, 0x7d, 0xd7, 0x9b, 0x5a, 0x47, 0xfc, 0xf3, 0x49, 0xed, 0xfc, 0x9e, 0x75, 0x34, 0x00, 0xf1,
+ 0x0f, 0x5c, 0x33, 0xef, 0x3e, 0xf6, 0x93, 0x7b, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x59, 0xad, 0x9b, 0x59, 0x3c, 0xba, 0x59, 0xcc, 0xff, 0xf9, 0xef, 0xcf, 0x5b, 0x9f, 0x3d, 0x9f, 0x2d, 0x55, 0xb6,
+ 0x36, 0xcc, 0xf8, 0xde, 0x1e, 0x2e, 0xf5, 0x95, 0x47, 0x68, 0xb7, 0x9d, 0xe1, 0xda, 0x5a, 0xe9, 0xbd, 0x47, 0xdb, 0x6e,
+ 0xa8, 0xc9, 0x5a, 0x7b, 0xb5, 0xe1, 0xb6, 0x96, 0xee, 0xb3, 0xb5, 0x2d, 0xff, 0xfd, 0x9f, 0xfb, 0xb0, 0x86, 0xf7, 0x64,
+ 0x5e, 0xde, 0xda, 0x9b, 0xd1, 0xb5, 0x6c, 0x5a, 0x3f, 0x6f, 0xdb, 0xff, 0xfa, 0xdb, 0xdb, 0x96, 0xa9, 0x83, 0x71, 0xee,
+ 0xfb, 0x95, 0xe7, 0x33, 0x2a, 0xf5, 0x9a, 0x0c, 0xc4, 0x3f, 0x1f, 0x21, 0x06, 0x67, 0x18, 0xa5, 0x6c, 0x66, 0x77, 0xb5,
+ 0x65, 0x6f, 0x4d, 0x86, 0xbd, 0xb0, 0xda, 0xca, 0x1d, 0xed, 0x15, 0xa5, 0xf5, 0x1b, 0xb6, 0x49, 0xdf, 0xcc, 0xf5, 0xe7,
+ 0x4c, 0xdd, 0x8f, 0xf2, 0xcd, 0x8e, 0xce, 0xb3, 0x7f, 0xe4, 0xfe, 0x99, 0xec, 0xc9, 0x33, 0xf9, 0xf5, 0xf9, 0x9e, 0xbc,
+ 0x96, 0xb6, 0xc1, 0x3c, 0xa7, 0xf2, 0xd6, 0xee, 0xca, 0xf3, 0x19, 0x8d, 0xc3, 0xfd, 0x3a, 0xc8, 0x1f, 0xe3, 0x78, 0x5b,
+ 0x8e, 0xea, 0xf8, 0xf9, 0xb6, 0x1c, 0xf5, 0xcc, 0x48, 0x47, 0x52, 0xbe, 0xcc, 0xfd, 0xbe, 0xde, 0xdb, 0xdb, 0x6c, 0x3d,
+ 0x9d, 0x67, 0xde, 0x11, 0x9f, 0xc5, 0x7f, 0xa4, 0xe3, 0x7f, 0xbc, 0x0a, 0xcc, 0xf1, 0x4f, 0x47, 0x57, 0xd9, 0x7d, 0x30,
+ 0x96, 0xf7, 0x6a, 0xb9, 0x0d, 0xeb, 0xbf, 0xf6, 0xd6, 0xfe, 0xaa, 0xf3, 0xa9, 0x1c, 0x67, 0x4f, 0xd7, 0x59, 0x2e, 0x2b,
+ 0xea, 0x3e, 0x3c, 0x93, 0x67, 0xdb, 0x72, 0xd4, 0x9b, 0xdb, 0x20, 0x4b, 0xff, 0xea, 0xf6, 0x8a, 0xc4, 0xde, 0xaa, 0x6b,
+ 0xd6, 0x8c, 0xd6, 0xe0, 0xcb, 0x6e, 0xe9, 0x45, 0x79, 0x65, 0xf6, 0x97, 0x9d, 0x13, 0xe7, 0xc7, 0xe5, 0xea, 0x58, 0xbe,
+ 0xa5, 0xb3, 0x96, 0xcf, 0x56, 0xc9, 0xc8, 0x8c, 0xd8, 0x95, 0x2d, 0x51, 0xb8, 0x37, 0x6c, 0xe9, 0x27, 0x16, 0xa3, 0x9c,
+ 0xe2, 0x91, 0x1c, 0xe3, 0x9e, 0x6d, 0xcb, 0xd9, 0x68, 0x96, 0x39, 0x9b, 0xca, 0x96, 0xd1, 0xac, 0xa9, 0xff, 0x9d, 0xfc,
+ 0xca, 0x98, 0x67, 0x56, 0xe7, 0x6b, 0x97, 0xcd, 0xff, 0xe7, 0x39, 0xb6, 0xd7, 0x8c, 0xcb, 0xd5, 0xb1, 0x7c, 0x2b, 0xac,
+ 0x5a, 0x10, 0x97, 0xdf, 0x31, 0x56, 0x57, 0x47, 0xdb, 0xbb, 0xf7, 0xc6, 0xb9, 0xcf, 0xab, 0x6b, 0x1f, 0xc4, 0x0b, 0xdb,
+ 0x32, 0x1f, 0xff, 0xd7, 0xac, 0x73, 0xb1, 0x76, 0x6d, 0xbc, 0x76, 0x5b, 0x9f, 0x3a, 0x3e, 0xca, 0xaf, 0x5e, 0xe5, 0xee,
+ 0xfa, 0x5a, 0xae, 0xe5, 0xf2, 0x7f, 0x3a, 0xfe, 0x63, 0xe1, 0x8a, 0x02, 0xab, 0xe2, 0xbf, 0xbd, 0x24, 0x62, 0xfe, 0x94,
+ 0xf8, 0xcf, 0xad, 0xc2, 0x11, 0xa5, 0x95, 0x3b, 0x32, 0x31, 0x9e, 0x7f, 0x96, 0xff, 0x9e, 0x5a, 0xfe, 0x9e, 0xf1, 0xff,
+ 0xb9, 0xf8, 0x8f, 0x0f, 0x8c, 0xff, 0xf7, 0x96, 0xf9, 0xf9, 0xb1, 0xf1, 0xd9, 0xf8, 0xaf, 0x8c, 0xcb, 0xf5, 0x75, 0x79,
+ 0xd6, 0xc6, 0x7f, 0x24, 0x46, 0xec, 0xf5, 0x99, 0xb8, 0x9f, 0x8a, 0xff, 0xf7, 0x8e, 0xa5, 0xb3, 0xba, 0x7a, 0xb2, 0x64,
+ 0xb3, 0x55, 0xe6, 0xdf, 0x15, 0xff, 0xd5, 0x15, 0x55, 0x23, 0x39, 0x93, 0x7d, 0xff, 0xf8, 0x1f, 0xa9, 0x35, 0xf7, 0xbe,
+ 0x67, 0xfc, 0x8f, 0xc9, 0xda, 0xbc, 0x9f, 0x37, 0xff, 0x8f, 0x47, 0x63, 0x2c, 0x4a, 0x2b, 0xc9, 0x66, 0x57, 0xda, 0x5b,
+ 0x35, 0xff, 0xbf, 0xf3, 0xe7, 0x8c, 0x9f, 0x36, 0x9b, 0x3c, 0xf7, 0xa4, 0xe3, 0x33, 0xe2, 0x7f, 0x3e, 0x92, 0x7e, 0x5e,
+ 0x8b, 0x3d, 0x3d, 0xc6, 0xca, 0xf6, 0xfc, 0x4d, 0xf1, 0xbf, 0xdd, 0x32, 0xfe, 0x57, 0x57, 0x3a, 0xcd, 0xfe, 0xfe, 0xd9,
+ 0x27, 0xc5, 0xff, 0xca, 0x95, 0x87, 0xee, 0x2c, 0x99, 0xf8, 0x7f, 0xdb, 0x3d, 0xce, 0x8a, 0x92, 0xdf, 0xf5, 0x13, 0x99,
+ 0xbb, 0xc7, 0xf9, 0xf7, 0x5e, 0xb1, 0xdf, 0xdb, 0xff, 0xaa, 0xbf, 0xe7, 0x2e, 0xfe, 0x3f, 0x2f, 0xfe, 0xb3, 0x23, 0x76,
+ 0x65, 0xcb, 0xfc, 0x48, 0xe7, 0x3f, 0x5f, 0xd7, 0x62, 0xeb, 0x9f, 0x7e, 0xde, 0x71, 0xb7, 0x7a, 0x5f, 0xc9, 0xc4, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xad, 0x36, 0xcc, 0xe4, 0x9f, 0xcd, 0x4a, 0x3e, 0xca, 0x0c,
+ 0x18, 0xb7, 0xe4, 0x38, 0xaf, 0xe6, 0xff, 0x3f, 0xfe, 0x79, 0xbe, 0xc6, 0x2a, 0x65, 0x5a, 0x7b, 0xee, 0x6d, 0xd2, 0x66,
+ 0x3f, 0x7f, 0xde, 0x0a, 0xab, 0x3c, 0xdc, 0xd1, 0x62, 0xad, 0xd4, 0x9f, 0xf9, 0xa9, 0xb6, 0xf6, 0x85, 0xb5, 0x35, 0x5b,
+ 0x33, 0xe0, 0x99, 0x1c, 0xe7, 0xb3, 0xe3, 0xb4, 0x45, 0xc7, 0x18, 0x67, 0xb8, 0xce, 0x95, 0xa9, 0x72, 0xee, 0xeb, 0xdb,
+ 0xb2, 0x5f, 0x8a, 0x7b, 0x5a, 0xac, 0xf9, 0x0d, 0xfb, 0x47, 0xdf, 0xd9, 0xa9, 0x64, 0x18, 0x8e, 0x64, 0xf6, 0xa3, 0xfb,
+ 0x4a, 0xbd, 0xee, 0x08, 0xfd, 0xab, 0xd8, 0xfe, 0xd2, 0xb1, 0x67, 0x9c, 0x7b, 0x76, 0x94, 0x15, 0xb1, 0xdd, 0xf4, 0x66,
+ 0x58, 0x4b, 0xbf, 0xcb, 0xd3, 0x16, 0xed, 0x4d, 0x94, 0xaf, 0xca, 0x3d, 0xbc, 0x4d, 0xf3, 0x72, 0xad, 0xba, 0xce, 0xe4,
+ 0x4b, 0xbd, 0x0d, 0xf6, 0x95, 0xfb, 0x7c, 0x4b, 0xe6, 0x6a, 0x89, 0xc5, 0x59, 0xdc, 0xd7, 0xd6, 0xca, 0x36, 0xb9, 0x8e,
+ 0x47, 0x22, 0xc6, 0xce, 0x6c, 0xc9, 0x1f, 0xe7, 0x6d, 0x6b, 0x69, 0x7c, 0xee, 0x7b, 0xb9, 0xfb, 0xa2, 0xdc, 0xc3, 0xf5,
+ 0x4c, 0x9a, 0xab, 0x72, 0x9c, 0xd7, 0x32, 0xb3, 0xac, 0xcb, 0xa4, 0xb7, 0x77, 0xfb, 0xf1, 0xda, 0x33, 0xbc, 0xbe, 0x56,
+ 0x3e, 0x21, 0x97, 0xee, 0x1b, 0xdf, 0x0c, 0xff, 0xec, 0xf7, 0xf3, 0x8f, 0x8c, 0x67, 0xdb, 0x74, 0xce, 0xf8, 0x64, 0xfb,
+ 0x5f, 0x9f, 0x49, 0x67, 0xfb, 0xc8, 0x0c, 0x87, 0x5b, 0x39, 0x03, 0x98, 0xf8, 0xff, 0xf6, 0xf9, 0x7f, 0xdc, 0x90, 0x17,
+ 0x69, 0x76, 0x2d, 0x59, 0x9b, 0xff, 0x77, 0x13, 0xff, 0x27, 0xa3, 0xe2, 0xf9, 0x5c, 0x9a, 0xf3, 0xab, 0xfc, 0x26, 0xfe,
+ 0x17, 0x8d, 0xfb, 0xdf, 0x96, 0x49, 0xd3, 0xf8, 0x7f, 0x5d, 0x54, 0x7c, 0xea, 0x5a, 0x1a, 0x6c, 0x85, 0xb1, 0x7c, 0x65,
+ 0x86, 0xe1, 0xb8, 0xe1, 0x0a, 0x54, 0xc9, 0xcc, 0x98, 0xff, 0xfc, 0xd3, 0xa2, 0x7c, 0x65, 0x8e, 0xad, 0x6b, 0xca, 0xb6,
+ 0x26, 0xfe, 0xdf, 0x99, 0xfd, 0xfa, 0x13, 0xe7, 0xff, 0xf7, 0x3c, 0x63, 0xd8, 0x6e, 0xce, 0xcc, 0x16, 0x4b, 0x3e, 0xdf,
+ 0x92, 0x77, 0x38, 0x2b, 0xef, 0x97, 0x9e, 0xcf, 0xa4, 0x77, 0x5f, 0x56, 0xfa, 0xda, 0x5d, 0x9e, 0xf1, 0x1f, 0xbe, 0xfb,
+ 0xd9, 0xb4, 0xf8, 0x07, 0xf1, 0x6f, 0xf6, 0x0f, 0xee, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xc7, 0xaf, 0x3f, 0xea, 0x01, 0xc4, 0x3f, 0xf0, 0xc7,
+ 0xc5, 0xff, 0xff, 0x00 };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle amberFontRecs[189] = {
+ { 4, 4, 5 , 16 },
+ { 17, 4, 2 , 10 },
+ { 27, 4, 4 , 4 },
+ { 39, 4, 5 , 10 },
+ { 52, 4, 5 , 11 },
+ { 65, 4, 5 , 10 },
+ { 78, 4, 5 , 10 },
+ { 91, 4, 2 , 4 },
+ { 101, 4, 4 , 13 },
+ { 113, 4, 5 , 13 },
+ { 126, 4, 4 , 4 },
+ { 138, 4, 5 , 6 },
+ { 151, 4, 3 , 2 },
+ { 162, 4, 5 , 2 },
+ { 175, 4, 2 , 1 },
+ { 185, 4, 5 , 10 },
+ { 198, 4, 5 , 10 },
+ { 211, 4, 4 , 10 },
+ { 223, 4, 5 , 10 },
+ { 236, 4, 5 , 10 },
+ { 249, 4, 5 , 10 },
+ { 262, 4, 5 , 10 },
+ { 275, 4, 5 , 10 },
+ { 288, 4, 5 , 10 },
+ { 301, 4, 5 , 10 },
+ { 314, 4, 5 , 10 },
+ { 327, 4, 2 , 6 },
+ { 337, 4, 2 , 6 },
+ { 347, 4, 5 , 6 },
+ { 360, 4, 5 , 4 },
+ { 373, 4, 5 , 6 },
+ { 386, 4, 5 , 10 },
+ { 399, 4, 5 , 7 },
+ { 412, 4, 5 , 10 },
+ { 425, 4, 5 , 10 },
+ { 438, 4, 5 , 10 },
+ { 451, 4, 5 , 10 },
+ { 464, 4, 5 , 10 },
+ { 477, 4, 5 , 10 },
+ { 490, 4, 5 , 10 },
+ { 4, 28, 5 , 10 },
+ { 17, 28, 4 , 10 },
+ { 29, 28, 5 , 10 },
+ { 42, 28, 5 , 10 },
+ { 55, 28, 5 , 10 },
+ { 68, 28, 5 , 10 },
+ { 81, 28, 5 , 10 },
+ { 94, 28, 5 , 10 },
+ { 107, 28, 5 , 10 },
+ { 120, 28, 5 , 10 },
+ { 133, 28, 5 , 10 },
+ { 146, 28, 5 , 10 },
+ { 159, 28, 5 , 10 },
+ { 172, 28, 5 , 10 },
+ { 185, 28, 5 , 10 },
+ { 198, 28, 5 , 10 },
+ { 211, 28, 5 , 10 },
+ { 224, 28, 5 , 10 },
+ { 237, 28, 5 , 10 },
+ { 250, 28, 3 , 13 },
+ { 261, 28, 5 , 10 },
+ { 274, 28, 3 , 13 },
+ { 285, 28, 4 , 3 },
+ { 297, 28, 5 , 1 },
+ { 310, 28, 3 , 3 },
+ { 321, 28, 5 , 7 },
+ { 334, 28, 5 , 10 },
+ { 347, 28, 5 , 7 },
+ { 360, 28, 5 , 10 },
+ { 373, 28, 5 , 7 },
+ { 386, 28, 5 , 10 },
+ { 399, 28, 5 , 10 },
+ { 412, 28, 5 , 10 },
+ { 425, 28, 4 , 10 },
+ { 437, 28, 3 , 13 },
+ { 448, 28, 5 , 10 },
+ { 461, 28, 5 , 10 },
+ { 474, 28, 5 , 7 },
+ { 487, 28, 5 , 7 },
+ { 4, 52, 5 , 7 },
+ { 17, 52, 5 , 10 },
+ { 30, 52, 5 , 10 },
+ { 43, 52, 5 , 7 },
+ { 56, 52, 5 , 7 },
+ { 69, 52, 5 , 10 },
+ { 82, 52, 5 , 7 },
+ { 95, 52, 5 , 7 },
+ { 108, 52, 5 , 7 },
+ { 121, 52, 5 , 7 },
+ { 134, 52, 5 , 10 },
+ { 147, 52, 5 , 7 },
+ { 160, 52, 4 , 13 },
+ { 172, 52, 2 , 13 },
+ { 182, 52, 4 , 13 },
+ { 194, 52, 5 , 4 },
+ { 207, 52, 2 , 9 },
+ { 217, 52, 5 , 7 },
+ { 230, 52, 5 , 10 },
+ { 243, 52, 5 , 10 },
+ { 256, 52, 5 , 10 },
+ { 269, 52, 0 , 0 },
+ { 277, 52, 5 , 10 },
+ { 290, 52, 0 , 0 },
+ { 298, 52, 5 , 7 },
+ { 311, 52, 3 , 5 },
+ { 322, 52, 5 , 5 },
+ { 335, 52, 5 , 3 },
+ { 348, 52, 5 , 7 },
+ { 361, 52, 5 , 2 },
+ { 374, 52, 4 , 4 },
+ { 386, 52, 5 , 8 },
+ { 399, 52, 3 , 5 },
+ { 410, 52, 3 , 6 },
+ { 421, 52, 0 , 0 },
+ { 429, 52, 5 , 10 },
+ { 442, 52, 5 , 10 },
+ { 455, 52, 2 , 3 },
+ { 465, 52, 0 , 0 },
+ { 473, 52, 3 , 5 },
+ { 484, 52, 4 , 4 },
+ { 496, 52, 5 , 5 },
+ { 4, 76, 5 , 10 },
+ { 17, 76, 5 , 7 },
+ { 30, 76, 5 , 10 },
+ { 43, 76, 5 , 10 },
+ { 56, 76, 5 , 14 },
+ { 69, 76, 5 , 14 },
+ { 82, 76, 5 , 14 },
+ { 95, 76, 5 , 14 },
+ { 108, 76, 5 , 12 },
+ { 121, 76, 5 , 12 },
+ { 134, 76, 5 , 10 },
+ { 147, 76, 5 , 13 },
+ { 160, 76, 5 , 14 },
+ { 173, 76, 5 , 14 },
+ { 186, 76, 5 , 14 },
+ { 199, 76, 5 , 12 },
+ { 212, 76, 4 , 14 },
+ { 224, 76, 4 , 14 },
+ { 236, 76, 4 , 14 },
+ { 248, 76, 4 , 12 },
+ { 260, 76, 5 , 10 },
+ { 273, 76, 5 , 14 },
+ { 286, 76, 5 , 14 },
+ { 299, 76, 5 , 14 },
+ { 312, 76, 5 , 14 },
+ { 325, 76, 5 , 14 },
+ { 338, 76, 5 , 12 },
+ { 351, 76, 4 , 3 },
+ { 363, 76, 5 , 10 },
+ { 376, 76, 5 , 14 },
+ { 389, 76, 5 , 14 },
+ { 402, 76, 5 , 14 },
+ { 415, 76, 5 , 12 },
+ { 428, 76, 5 , 14 },
+ { 441, 76, 5 , 10 },
+ { 454, 76, 5 , 10 },
+ { 467, 76, 5 , 10 },
+ { 480, 76, 5 , 10 },
+ { 493, 76, 5 , 10 },
+ { 4, 100, 5 , 10 },
+ { 17, 100, 5 , 9 },
+ { 30, 100, 5 , 9 },
+ { 43, 100, 5 , 7 },
+ { 56, 100, 5 , 10 },
+ { 69, 100, 5 , 10 },
+ { 82, 100, 5 , 10 },
+ { 95, 100, 5 , 10 },
+ { 108, 100, 5 , 9 },
+ { 121, 100, 4 , 10 },
+ { 133, 100, 4 , 10 },
+ { 145, 100, 4 , 10 },
+ { 157, 100, 4 , 9 },
+ { 169, 100, 5 , 10 },
+ { 182, 100, 5 , 10 },
+ { 195, 100, 5 , 10 },
+ { 208, 100, 5 , 10 },
+ { 221, 100, 5 , 10 },
+ { 234, 100, 5 , 10 },
+ { 247, 100, 5 , 9 },
+ { 260, 100, 5 , 6 },
+ { 273, 100, 5 , 7 },
+ { 286, 100, 5 , 10 },
+ { 299, 100, 5 , 10 },
+ { 312, 100, 5 , 10 },
+ { 325, 100, 5 , 9 },
+ { 338, 100, 5 , 13 },
+ { 351, 100, 5 , 10 },
+ { 364, 100, 5 , 12 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo amberFontGlyphs[189] = {
+ { 32, 0, 0, 5, { 0 }},
+ { 33, 1, 3, 5, { 0 }},
+ { 34, 0, 3, 5, { 0 }},
+ { 35, 0, 3, 5, { 0 }},
+ { 36, 0, 3, 5, { 0 }},
+ { 37, 0, 3, 5, { 0 }},
+ { 38, 0, 3, 5, { 0 }},
+ { 39, 1, 4, 5, { 0 }},
+ { 40, 0, 3, 5, { 0 }},
+ { 41, 0, 3, 5, { 0 }},
+ { 42, 0, 3, 5, { 0 }},
+ { 43, 0, 7, 5, { 0 }},
+ { 44, 0, 12, 5, { 0 }},
+ { 45, 0, 9, 5, { 0 }},
+ { 46, 1, 12, 5, { 0 }},
+ { 47, 0, 3, 5, { 0 }},
+ { 48, 0, 3, 5, { 0 }},
+ { 49, 0, 3, 5, { 0 }},
+ { 50, 0, 3, 5, { 0 }},
+ { 51, 0, 3, 5, { 0 }},
+ { 52, 0, 3, 5, { 0 }},
+ { 53, 0, 3, 5, { 0 }},
+ { 54, 0, 3, 5, { 0 }},
+ { 55, 0, 3, 5, { 0 }},
+ { 56, 0, 3, 5, { 0 }},
+ { 57, 0, 3, 5, { 0 }},
+ { 58, 0, 7, 5, { 0 }},
+ { 59, 0, 7, 5, { 0 }},
+ { 60, 0, 7, 5, { 0 }},
+ { 61, 0, 8, 5, { 0 }},
+ { 62, 0, 7, 5, { 0 }},
+ { 63, 0, 3, 5, { 0 }},
+ { 64, 0, 6, 5, { 0 }},
+ { 65, 0, 3, 5, { 0 }},
+ { 66, 0, 3, 5, { 0 }},
+ { 67, 0, 3, 5, { 0 }},
+ { 68, 0, 3, 5, { 0 }},
+ { 69, 0, 3, 5, { 0 }},
+ { 70, 0, 3, 5, { 0 }},
+ { 71, 0, 3, 5, { 0 }},
+ { 72, 0, 3, 5, { 0 }},
+ { 73, 0, 3, 5, { 0 }},
+ { 74, 0, 3, 5, { 0 }},
+ { 75, 0, 3, 5, { 0 }},
+ { 76, 0, 3, 5, { 0 }},
+ { 77, 0, 3, 5, { 0 }},
+ { 78, 0, 3, 5, { 0 }},
+ { 79, 0, 3, 5, { 0 }},
+ { 80, 0, 3, 5, { 0 }},
+ { 81, 0, 3, 5, { 0 }},
+ { 82, 0, 3, 5, { 0 }},
+ { 83, 0, 3, 5, { 0 }},
+ { 84, 0, 3, 5, { 0 }},
+ { 85, 0, 3, 5, { 0 }},
+ { 86, 0, 3, 5, { 0 }},
+ { 87, 0, 3, 5, { 0 }},
+ { 88, 0, 3, 5, { 0 }},
+ { 89, 0, 3, 5, { 0 }},
+ { 90, 0, 3, 5, { 0 }},
+ { 91, 0, 3, 5, { 0 }},
+ { 92, 0, 3, 5, { 0 }},
+ { 93, 0, 3, 5, { 0 }},
+ { 94, 0, 3, 5, { 0 }},
+ { 95, 0, 12, 5, { 0 }},
+ { 96, 1, 4, 5, { 0 }},
+ { 97, 0, 6, 5, { 0 }},
+ { 98, 0, 3, 5, { 0 }},
+ { 99, 0, 6, 5, { 0 }},
+ { 100, 0, 3, 5, { 0 }},
+ { 101, 0, 6, 5, { 0 }},
+ { 102, 0, 3, 5, { 0 }},
+ { 103, 0, 6, 5, { 0 }},
+ { 104, 0, 3, 5, { 0 }},
+ { 105, 0, 3, 5, { 0 }},
+ { 106, 0, 3, 5, { 0 }},
+ { 107, 0, 3, 5, { 0 }},
+ { 108, 0, 3, 5, { 0 }},
+ { 109, 0, 6, 5, { 0 }},
+ { 110, 0, 6, 5, { 0 }},
+ { 111, 0, 6, 5, { 0 }},
+ { 112, 0, 6, 5, { 0 }},
+ { 113, 0, 6, 5, { 0 }},
+ { 114, 0, 6, 5, { 0 }},
+ { 115, 0, 6, 5, { 0 }},
+ { 116, 0, 3, 5, { 0 }},
+ { 117, 0, 6, 5, { 0 }},
+ { 118, 0, 6, 5, { 0 }},
+ { 119, 0, 6, 5, { 0 }},
+ { 120, 0, 6, 5, { 0 }},
+ { 121, 0, 6, 5, { 0 }},
+ { 122, 0, 6, 5, { 0 }},
+ { 123, 0, 3, 5, { 0 }},
+ { 124, 1, 3, 5, { 0 }},
+ { 125, 0, 3, 5, { 0 }},
+ { 126, 0, 8, 5, { 0 }},
+ { 161, 1, 4, 5, { 0 }},
+ { 162, 0, 6, 5, { 0 }},
+ { 163, 0, 3, 5, { 0 }},
+ { 8364, 0, 3, 5, { 0 }},
+ { 165, 0, 3, 5, { 0 }},
+ { 352, 0, 0, 0, { 0 }},
+ { 167, 0, 3, 5, { 0 }},
+ { 353, 0, 0, 0, { 0 }},
+ { 169, 0, 6, 5, { 0 }},
+ { 170, 2, 3, 5, { 0 }},
+ { 171, 0, 8, 5, { 0 }},
+ { 172, 0, 6, 5, { 0 }},
+ { 174, 0, 6, 5, { 0 }},
+ { 175, 0, 3, 5, { 0 }},
+ { 176, 1, 3, 5, { 0 }},
+ { 177, 0, 5, 5, { 0 }},
+ { 178, 2, 3, 5, { 0 }},
+ { 179, 2, 3, 5, { 0 }},
+ { 381, 0, 0, 0, { 0 }},
+ { 181, 0, 6, 5, { 0 }},
+ { 182, 0, 3, 5, { 0 }},
+ { 183, 1, 6, 5, { 0 }},
+ { 382, 0, 0, 0, { 0 }},
+ { 185, 0, 3, 5, { 0 }},
+ { 186, 0, 3, 5, { 0 }},
+ { 187, 0, 8, 5, { 0 }},
+ { 338, 0, 3, 5, { 0 }},
+ { 339, 0, 6, 5, { 0 }},
+ { 376, 0, 3, 5, { 0 }},
+ { 191, 0, 3, 5, { 0 }},
+ { 192, 0, -1, 5, { 0 }},
+ { 193, 0, -1, 5, { 0 }},
+ { 194, 0, -1, 5, { 0 }},
+ { 195, 0, -1, 5, { 0 }},
+ { 196, 0, 1, 5, { 0 }},
+ { 197, 0, 1, 5, { 0 }},
+ { 198, 0, 3, 5, { 0 }},
+ { 199, 0, 3, 5, { 0 }},
+ { 200, 0, -1, 5, { 0 }},
+ { 201, 0, -1, 5, { 0 }},
+ { 202, 0, -1, 5, { 0 }},
+ { 203, 0, 1, 5, { 0 }},
+ { 204, 0, -1, 5, { 0 }},
+ { 205, 0, -1, 5, { 0 }},
+ { 206, 0, -1, 5, { 0 }},
+ { 207, 0, 1, 5, { 0 }},
+ { 208, 0, 3, 5, { 0 }},
+ { 209, 0, -1, 5, { 0 }},
+ { 210, 0, -1, 5, { 0 }},
+ { 211, 0, -1, 5, { 0 }},
+ { 212, 0, -1, 5, { 0 }},
+ { 213, 0, -1, 5, { 0 }},
+ { 214, 0, 1, 5, { 0 }},
+ { 215, 0, 10, 5, { 0 }},
+ { 216, 0, 3, 5, { 0 }},
+ { 217, 0, -1, 5, { 0 }},
+ { 218, 0, -1, 5, { 0 }},
+ { 219, 0, -1, 5, { 0 }},
+ { 220, 0, 1, 5, { 0 }},
+ { 221, 0, -1, 5, { 0 }},
+ { 222, 0, 3, 5, { 0 }},
+ { 223, 0, 3, 5, { 0 }},
+ { 224, 0, 3, 5, { 0 }},
+ { 225, 0, 3, 5, { 0 }},
+ { 226, 0, 3, 5, { 0 }},
+ { 227, 0, 3, 5, { 0 }},
+ { 228, 0, 4, 5, { 0 }},
+ { 229, 0, 4, 5, { 0 }},
+ { 230, 0, 6, 5, { 0 }},
+ { 231, 0, 6, 5, { 0 }},
+ { 232, 0, 3, 5, { 0 }},
+ { 233, 0, 3, 5, { 0 }},
+ { 234, 0, 3, 5, { 0 }},
+ { 235, 0, 4, 5, { 0 }},
+ { 236, 0, 3, 5, { 0 }},
+ { 237, 0, 3, 5, { 0 }},
+ { 238, 0, 3, 5, { 0 }},
+ { 239, 0, 4, 5, { 0 }},
+ { 240, 0, 3, 5, { 0 }},
+ { 241, 0, 3, 5, { 0 }},
+ { 242, 0, 3, 5, { 0 }},
+ { 243, 0, 3, 5, { 0 }},
+ { 244, 0, 3, 5, { 0 }},
+ { 245, 0, 3, 5, { 0 }},
+ { 246, 0, 4, 5, { 0 }},
+ { 247, 0, 7, 5, { 0 }},
+ { 248, 0, 6, 5, { 0 }},
+ { 249, 0, 3, 5, { 0 }},
+ { 250, 0, 3, 5, { 0 }},
+ { 251, 0, 3, 5, { 0 }},
+ { 252, 0, 4, 5, { 0 }},
+ { 253, 0, 3, 5, { 0 }},
+ { 254, 0, 3, 5, { 0 }},
+ { 255, 0, 4, 5, { 0 }},
+};
+
+// Style loading function: Amber
+static void GuiLoadStyleAmber(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < AMBER_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(amberStyleProps[i].controlId, amberStyleProps[i].propertyId, amberStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int amberFontDataSize = 0;
+ unsigned char *data = DecompressData(amberFontData, AMBER_STYLE_FONT_ATLAS_COMP_SIZE, &amberFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 16;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, amberFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, amberFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_ashes.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_ashes.h
new file mode 100644
index 0000000000..ea1e6aab99
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_ashes.h
@@ -0,0 +1,578 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleAshes(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define ASHES_STYLE_PROPS_COUNT 16
+
+// Custom style name: Ashes
+static const GuiStyleProp ashesStyleProps[ASHES_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0xf0f0f0ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x868686ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0xe6e6e6ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0x929999ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0xeaeaeaff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0x98a1a8ff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0x3f3f3fff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0xf6f6f6ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0x414141ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x8b8b8bff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x777777ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x959595ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE
+ { 0, 18, 0x9dadb1ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x6b6b6bff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "v5loxical.ttf" (size: 16, spacing: 1)
+
+#define ASHES_STYLE_FONT_ATLAS_COMP_SIZE 2042
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char ashesFontData[ASHES_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0xd1, 0xb2, 0xab, 0x36, 0x0c, 0x05, 0x50, 0xff, 0xff, 0x4f, 0xab, 0x0f, 0x9d, 0x4e, 0xdb, 0x69, 0x13, 0x90, 0x2c,
+ 0x83, 0x21, 0xeb, 0xae, 0xb7, 0x9c, 0xdc, 0x40, 0x0c, 0x1b, 0x63, 0x88, 0x45, 0x0c, 0x00, 0x00, 0x00, 0xe0, 0xe7, 0xc5,
+ 0xff, 0xbe, 0x12, 0x1f, 0xdf, 0x19, 0xa7, 0x3f, 0xe7, 0xdf, 0xaf, 0xc7, 0x87, 0xbf, 0xe6, 0x3e, 0x2f, 0x4e, 0x2f, 0xb7,
+ 0xf2, 0x97, 0xf8, 0xdf, 0xf5, 0x8b, 0xe9, 0xa5, 0xc6, 0xe9, 0x6f, 0xf3, 0xed, 0xbd, 0xdf, 0x96, 0xf9, 0xe9, 0x93, 0x22,
+ 0xb1, 0x8c, 0xec, 0xfb, 0x3f, 0x7f, 0xce, 0xd5, 0x2d, 0x1e, 0x5f, 0xfe, 0xf2, 0xfd, 0xaf, 0xd9, 0xd7, 0xe3, 0xe4, 0xab,
+ 0xdf, 0xfe, 0x12, 0x07, 0x7f, 0x39, 0x9b, 0xbb, 0x78, 0x40, 0xfe, 0xe3, 0xcb, 0xe7, 0x7d, 0xff, 0xc4, 0x98, 0x38, 0x26,
+ 0x9c, 0x5b, 0xee, 0x95, 0xed, 0xf9, 0x69, 0x4f, 0xcf, 0x6d, 0xeb, 0xef, 0x6d, 0x9c, 0xcb, 0x5c, 0x34, 0xac, 0xff, 0x6c,
+ 0xab, 0x45, 0xc3, 0xbb, 0xe3, 0xc4, 0xde, 0x92, 0xd9, 0x9b, 0xb3, 0x69, 0xab, 0xbd, 0x7f, 0x34, 0x6c, 0xaf, 0x6b, 0xf3,
+ 0xff, 0xcf, 0x7f, 0x23, 0x75, 0x14, 0x1c, 0x4d, 0xf9, 0xcf, 0xf7, 0xb9, 0xdf, 0x8e, 0xbe, 0x71, 0xd1, 0xd9, 0xd4, 0xb9,
+ 0x3d, 0xb4, 0xfe, 0x7a, 0xdf, 0xa7, 0x5f, 0x9d, 0xff, 0x68, 0xfc, 0x1f, 0x47, 0x6b, 0x17, 0xf2, 0x3f, 0xbd, 0x15, 0xa2,
+ 0xd8, 0xdb, 0x56, 0x7b, 0xa2, 0xd9, 0xad, 0x1f, 0x8b, 0x7b, 0xfa, 0x55, 0x09, 0xad, 0x1d, 0xcd, 0x22, 0xf9, 0x7f, 0x72,
+ 0x7d, 0x6c, 0x4c, 0x6f, 0xbd, 0xf3, 0xfb, 0x44, 0x7e, 0xfd, 0x8e, 0xf7, 0x00, 0xf9, 0xbf, 0x22, 0xff, 0x95, 0xe4, 0xc6,
+ 0x92, 0xa3, 0x7f, 0xf5, 0xca, 0xc0, 0x8a, 0xb6, 0xcc, 0xe5, 0x3f, 0x1a, 0x5b, 0x20, 0xdb, 0x6f, 0xe7, 0xd7, 0xff, 0xec,
+ 0x48, 0x3d, 0x6e, 0xec, 0xff, 0xbf, 0x1d, 0x1d, 0x33, 0x47, 0xcd, 0x6c, 0x3a, 0x73, 0xcb, 0xfd, 0x7b, 0x5d, 0xe7, 0xaf,
+ 0x88, 0xac, 0xc8, 0x7f, 0xf5, 0xfc, 0xbf, 0x72, 0x86, 0x3a, 0x36, 0xc9, 0xf3, 0xf5, 0xf9, 0x8f, 0xf6, 0x16, 0x58, 0x99,
+ 0xff, 0xb3, 0x6d, 0x1f, 0x0b, 0xc7, 0xff, 0xb9, 0xab, 0xab, 0xfb, 0xf7, 0xff, 0xf7, 0x5f, 0xff, 0x1b, 0xe5, 0xeb, 0x46,
+ 0xd9, 0x6b, 0x80, 0x71, 0xea, 0xec, 0xe1, 0x29, 0xf9, 0xef, 0x38, 0xfe, 0x55, 0x47, 0x4a, 0x1d, 0x57, 0xb8, 0xb2, 0xf9,
+ 0x8f, 0x86, 0xb6, 0x8f, 0xa5, 0x47, 0xff, 0x4a, 0xaf, 0x24, 0xff, 0xbd, 0xe3, 0xff, 0x38, 0x71, 0x06, 0x18, 0xaf, 0xe8,
+ 0xff, 0xf3, 0xa3, 0x9c, 0x68, 0xb8, 0x07, 0x57, 0xb9, 0xbb, 0x9a, 0xed, 0x31, 0x2b, 0xf7, 0x24, 0x77, 0x68, 0x77, 0xfd,
+ 0xff, 0x75, 0xdb, 0xa0, 0xb6, 0x2f, 0xfc, 0xf5, 0xff, 0x9e, 0xdf, 0xff, 0xef, 0xb4, 0x35, 0x90, 0xff, 0xab, 0xf7, 0xdb,
+ 0xb8, 0xb5, 0x7f, 0x95, 0x7f, 0xbf, 0x60, 0xeb, 0xca, 0xff, 0xda, 0xdf, 0xff, 0xc4, 0x41, 0x6f, 0x38, 0x1e, 0xd9, 0xff,
+ 0x5f, 0xb3, 0x36, 0x21, 0x79, 0xe0, 0x58, 0x2f, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0xd0, 0xec, 0x99, 0xcc, 0xec, 0xe5, 0x6a, 0x15, 0xe0, 0x8e, 0xf7, 0x57, 0x97, 0x10, 0x6d, 0xf5, 0x1f, 0xfb,
+ 0xaa, 0x49, 0x7e, 0x9e, 0x4d, 0x9a, 0x99, 0xf7, 0x9c, 0xab, 0x6f, 0x9e, 0xab, 0x24, 0x17, 0xc9, 0x9a, 0x6d, 0x91, 0xac,
+ 0x5b, 0x9c, 0xdd, 0x8e, 0xf3, 0xb3, 0xec, 0xe7, 0xfe, 0xff, 0xdf, 0xb5, 0x2a, 0xfa, 0xf6, 0xe5, 0xd1, 0xd4, 0x32, 0xd7,
+ 0xe5, 0x7f, 0xb4, 0xd7, 0x54, 0xcd, 0x57, 0xa8, 0xca, 0xd7, 0xc7, 0x1f, 0x9b, 0xe5, 0x3f, 0xb3, 0x3f, 0x66, 0xeb, 0xfe,
+ 0x44, 0x61, 0x56, 0x64, 0x4c, 0xcf, 0xb7, 0x8c, 0x85, 0xfb, 0x5d, 0x57, 0x05, 0xc9, 0x31, 0x99, 0xff, 0x3b, 0xf7, 0xfd,
+ 0x4a, 0x6d, 0x46, 0xf9, 0x7f, 0x43, 0xfe, 0x2b, 0xd5, 0x3d, 0x3b, 0xe6, 0x45, 0x77, 0xd5, 0xc7, 0x8d, 0xf4, 0x79, 0x51,
+ 0x66, 0x7f, 0x88, 0xa9, 0xca, 0xea, 0x91, 0x3e, 0x0e, 0xef, 0x98, 0x7f, 0xfd, 0x7f, 0xa5, 0x36, 0xde, 0xdd, 0xf9, 0x9f,
+ 0x7b, 0x22, 0xc0, 0xea, 0xea, 0x07, 0x6b, 0xfb, 0xa7, 0xde, 0xfe, 0x3f, 0x26, 0xf2, 0x9f, 0x7d, 0x86, 0xd9, 0x5e, 0xf9,
+ 0x9f, 0x3f, 0xff, 0xaf, 0x57, 0x3b, 0xef, 0x1a, 0x05, 0x8f, 0x86, 0xe3, 0x7d, 0xf5, 0x49, 0x82, 0x5d, 0xf9, 0x1f, 0x85,
+ 0xa7, 0xc0, 0xcd, 0x9e, 0x8f, 0x3e, 0x3b, 0xff, 0xb9, 0x2b, 0x11, 0xeb, 0xf2, 0xff, 0xec, 0xfe, 0x7f, 0xbc, 0xe0, 0xfc,
+ 0xbf, 0x63, 0x7b, 0x8f, 0x4d, 0xcf, 0xff, 0xbb, 0x46, 0xd1, 0xef, 0xcb, 0x7f, 0xf6, 0x7b, 0x76, 0x7c, 0xfe, 0x5b, 0xcf,
+ 0xff, 0xe5, 0xff, 0xed, 0xf9, 0xbf, 0xeb, 0x49, 0x66, 0x7b, 0xe4, 0x3f, 0x9a, 0xaa, 0xef, 0xca, 0xff, 0x5b, 0xf3, 0xbf,
+ 0xeb, 0xf5, 0xbf, 0xe7, 0xe6, 0x7f, 0x94, 0xc6, 0x66, 0x73, 0xef, 0x7e, 0x42, 0xff, 0x3f, 0x0a, 0xd7, 0xac, 0xf2, 0x23,
+ 0xd9, 0xeb, 0xc6, 0xff, 0xf2, 0x7f, 0xee, 0xee, 0xd9, 0xdd, 0xf9, 0x5f, 0x73, 0xff, 0xab, 0xef, 0xbc, 0xa0, 0xe3, 0xdd,
+ 0x7b, 0x8f, 0xff, 0x57, 0xff, 0x16, 0x67, 0xed, 0xf2, 0x7b, 0xae, 0xb4, 0x45, 0xf9, 0xba, 0x7d, 0xcf, 0x6f, 0x49, 0xf2,
+ 0xd7, 0xdf, 0xb2, 0x47, 0xce, 0x38, 0x78, 0x7f, 0x34, 0xf5, 0x73, 0x95, 0xea, 0xf0, 0x3b, 0xe4, 0x3f, 0xfb, 0xd4, 0x9f,
+ 0xec, 0xbb, 0xf7, 0xc8, 0xff, 0xfa, 0x96, 0xbd, 0x3a, 0xff, 0x4f, 0xfc, 0xb5, 0xe2, 0xef, 0xb5, 0x42, 0x2c, 0x7e, 0xff,
+ 0x6f, 0xef, 0x0b, 0x7b, 0x3d, 0x31, 0xcb, 0x76, 0xe5, 0xca, 0xbe, 0x15, 0xad, 0x05, 0x8e, 0xac, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x9b, 0xfb, 0x70, 0x34, 0x7f, 0x32, 0x9a, 0xaa, 0x20, 0x64, 0xeb, 0xc0,
+ 0x8d, 0xd3, 0xb5, 0xf0, 0xa3, 0x54, 0x79, 0x76, 0xbe, 0xba, 0xc2, 0xf7, 0x19, 0xcd, 0x9f, 0xbf, 0x69, 0x14, 0x66, 0x09,
+ 0x67, 0x9f, 0x6d, 0x50, 0xa9, 0xad, 0x50, 0x5f, 0x56, 0x14, 0xab, 0x48, 0xce, 0xb7, 0x41, 0x14, 0x9e, 0xef, 0x70, 0xf4,
+ 0x5d, 0xf2, 0x5b, 0x21, 0xf3, 0x5a, 0x65, 0x6e, 0xf9, 0x38, 0xf1, 0xdc, 0x81, 0x38, 0x9c, 0xdf, 0xd0, 0x9b, 0xff, 0xd5,
+ 0x75, 0xb0, 0x2b, 0xb5, 0x3c, 0xfe, 0xfb, 0xda, 0x7d, 0x75, 0x27, 0xbe, 0x1d, 0x77, 0x2a, 0x55, 0x28, 0xb2, 0xc7, 0xe1,
+ 0xfc, 0x5e, 0x38, 0xb7, 0xac, 0x91, 0xda, 0x02, 0x95, 0x7a, 0xe6, 0x9d, 0x6d, 0x1a, 0x85, 0x9a, 0x17, 0xe7, 0x7b, 0x9f,
+ 0x28, 0xb6, 0xfd, 0x4c, 0xcd, 0x9d, 0x33, 0x33, 0x8a, 0xa3, 0xb0, 0xe7, 0x75, 0xd5, 0xc1, 0x8d, 0x96, 0x4c, 0x77, 0x54,
+ 0xc1, 0xca, 0xd5, 0xee, 0xcd, 0xce, 0x24, 0x8d, 0xc9, 0xfd, 0x38, 0xbf, 0x7f, 0x47, 0x4b, 0x35, 0xae, 0xe3, 0x65, 0xc5,
+ 0x97, 0x65, 0x65, 0xf2, 0x5f, 0xef, 0x4b, 0xd7, 0xe7, 0x3f, 0xbf, 0x06, 0x99, 0x0a, 0x52, 0x73, 0xbd, 0xe3, 0x7c, 0xfe,
+ 0x77, 0xed, 0xff, 0xef, 0xce, 0x7f, 0xbe, 0x06, 0xcc, 0xd1, 0x79, 0x77, 0x65, 0x2f, 0x8a, 0x52, 0x26, 0xb3, 0xfb, 0x60,
+ 0xbd, 0xff, 0x8f, 0xd2, 0x39, 0x55, 0xe7, 0xb6, 0xbd, 0x22, 0xff, 0x63, 0x61, 0xfe, 0xef, 0xee, 0xff, 0xf7, 0xcc, 0x7f,
+ 0x5f, 0x2d, 0xdf, 0xb9, 0xfc, 0xe7, 0x53, 0x3e, 0x8a, 0x6b, 0xde, 0x77, 0xfe, 0x1f, 0xe9, 0xf1, 0xd3, 0xcc, 0xb2, 0xa2,
+ 0xe5, 0x5c, 0x6b, 0x1c, 0x3c, 0x9f, 0xf0, 0xf9, 0xf9, 0x1f, 0xc5, 0x33, 0xe0, 0xa3, 0xa7, 0x61, 0xe4, 0xdb, 0x67, 0x76,
+ 0x84, 0xbb, 0xbe, 0x0a, 0xf2, 0xf5, 0xcf, 0xc1, 0x88, 0x86, 0xb3, 0xfc, 0xa3, 0xca, 0x85, 0xb1, 0x41, 0xfe, 0xeb, 0xd7,
+ 0x87, 0xbb, 0xfa, 0xff, 0xee, 0xeb, 0xd6, 0x3d, 0xf9, 0x1f, 0xa5, 0x71, 0x4c, 0x5f, 0x3b, 0x8f, 0xa9, 0xfe, 0x7f, 0xbc,
+ 0x2c, 0xff, 0xd7, 0x3f, 0x07, 0x23, 0x5a, 0x46, 0xf9, 0x51, 0x7c, 0xde, 0x50, 0xef, 0xf9, 0xff, 0xb7, 0xe7, 0xe2, 0x46,
+ 0xf9, 0xd9, 0x70, 0x6b, 0xf3, 0x7f, 0xee, 0x6a, 0xf5, 0xca, 0xfc, 0x0f, 0xf9, 0x3f, 0x79, 0x87, 0xeb, 0xe8, 0x5e, 0xc5,
+ 0x48, 0xdf, 0x75, 0x99, 0xbd, 0x77, 0x74, 0xe5, 0xf9, 0xff, 0x75, 0xfd, 0xff, 0x58, 0x72, 0xfd, 0x7f, 0x45, 0x3f, 0xfb,
+ 0xa4, 0xfe, 0xff, 0xfb, 0x9e, 0xfd, 0x9c, 0xfc, 0x9f, 0x49, 0xdc, 0x78, 0x44, 0x45, 0xd1, 0xae, 0x4a, 0xd0, 0xd7, 0x5e,
+ 0xff, 0xeb, 0xbe, 0x9f, 0xd1, 0x73, 0xfe, 0x9f, 0xef, 0x49, 0xe7, 0x46, 0xb9, 0x9d, 0xcb, 0xba, 0xee, 0xfc, 0xff, 0x1d,
+ 0xf9, 0xef, 0x59, 0xbb, 0xfb, 0x2b, 0x20, 0xee, 0x99, 0xff, 0x51, 0xfc, 0x7d, 0xcd, 0xbd, 0xe7, 0xff, 0x57, 0xe6, 0x6c,
+ 0x8f, 0x7d, 0xe6, 0xbd, 0xf9, 0x3f, 0xfa, 0xfd, 0xcf, 0x13, 0xb7, 0xdb, 0xec, 0xd1, 0x27, 0x16, 0xbd, 0xf7, 0xae, 0xb3,
+ 0xa3, 0x98, 0xba, 0x56, 0x21, 0xff, 0x9d, 0xf9, 0x7f, 0x53, 0xc2, 0x9e, 0x92, 0xff, 0x55, 0x47, 0x8c, 0xa7, 0x3c, 0x19,
+ 0x42, 0xfe, 0xaf, 0xcd, 0xff, 0xaf, 0x24, 0xec, 0xbd, 0xf9, 0x7f, 0xdf, 0xd1, 0x2c, 0x3b, 0x86, 0x8e, 0x0b, 0xc7, 0xdd,
+ 0x71, 0xe3, 0x18, 0xbf, 0xba, 0x5e, 0xd7, 0xac, 0xf3, 0xae, 0x2d, 0xf3, 0x84, 0xb5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x67, 0xb9, 0x44, 0xcb, 0x6c, 0xd9, 0x51, 0xaa, 0xc3, 0x9e, 0x9f, 0x0b, 0x99, 0xad,
+ 0x35, 0x3f, 0x5a, 0xea, 0x14, 0x57, 0xaa, 0xc5, 0x1e, 0xcf, 0x37, 0x8d, 0x64, 0x5b, 0xde, 0xb5, 0xad, 0xa2, 0xbc, 0xf4,
+ 0x95, 0xdb, 0xe4, 0xf3, 0xac, 0xa0, 0xfc, 0x93, 0x16, 0x2a, 0xd5, 0x33, 0xae, 0xcb, 0xc1, 0xea, 0xd9, 0xfc, 0xf9, 0xba,
+ 0xfc, 0xf3, 0x55, 0x4f, 0xfb, 0x9e, 0x14, 0xd0, 0xfd, 0x2d, 0x32, 0x75, 0x5e, 0xcf, 0xb5, 0x42, 0x34, 0xb5, 0xe5, 0x5d,
+ 0xdb, 0xea, 0x68, 0x8d, 0x62, 0xf9, 0xda, 0x76, 0xd5, 0xeb, 0x8e, 0x52, 0x3f, 0x78, 0x47, 0x0e, 0x2a, 0xfd, 0xd1, 0xfd,
+ 0xb3, 0x5c, 0xe7, 0xe7, 0xf7, 0xd6, 0xf3, 0xff, 0xd4, 0xf3, 0xb1, 0x67, 0x7c, 0xa7, 0xef, 0xb5, 0xb4, 0x76, 0xfa, 0x0e,
+ 0xd5, 0xfc, 0x77, 0x54, 0x97, 0xe9, 0x9c, 0xe7, 0x1e, 0x5f, 0x6a, 0x2e, 0x47, 0xeb, 0xf9, 0xff, 0x4e, 0xaf, 0x57, 0xf3,
+ 0x9f, 0x1f, 0x2f, 0xcc, 0x8e, 0x2f, 0xe6, 0x9f, 0x50, 0x94, 0xaf, 0xde, 0x79, 0xdf, 0xeb, 0xdd, 0xcf, 0x48, 0x5a, 0xfd,
+ 0x7a, 0x25, 0xff, 0xbb, 0xf6, 0x0d, 0x3d, 0xf9, 0x8f, 0x0d, 0xb7, 0x52, 0x7e, 0xf4, 0x36, 0x7f, 0x9e, 0x59, 0x3d, 0xbe,
+ 0x74, 0xe7, 0x7f, 0xc7, 0xb6, 0xcf, 0x8f, 0xff, 0x9f, 0x97, 0xff, 0x28, 0xf4, 0xc3, 0xf7, 0xf5, 0x83, 0x99, 0xa7, 0x58,
+ 0xd6, 0xc7, 0xf8, 0xfb, 0xef, 0x83, 0xf2, 0x7f, 0x77, 0xdb, 0x8f, 0x1f, 0xe8, 0xff, 0xf7, 0xd9, 0xef, 0xba, 0xc7, 0xc1,
+ 0xf2, 0x2f, 0xff, 0xf2, 0x1f, 0x27, 0xc6, 0x63, 0x7b, 0xbc, 0x7e, 0x5d, 0xfe, 0x73, 0x95, 0xf9, 0xd7, 0xbf, 0x5e, 0xcb,
+ 0xed, 0xda, 0x6d, 0x24, 0xff, 0xfb, 0xe5, 0x7f, 0xe6, 0x89, 0x61, 0x4f, 0x68, 0xf3, 0xde, 0xfb, 0x7f, 0xcf, 0x1a, 0x6b,
+ 0xea, 0xff, 0xe5, 0xbf, 0x7e, 0xff, 0xff, 0x1d, 0xf9, 0xef, 0xbe, 0x97, 0xf7, 0x94, 0xeb, 0x7f, 0xe3, 0xe0, 0xb9, 0x40,
+ 0x71, 0xcb, 0x73, 0xc4, 0xd6, 0xe4, 0xff, 0x19, 0xdb, 0xe4, 0x78, 0xaf, 0x7a, 0x52, 0xfe, 0x9f, 0xdf, 0xe6, 0x9d, 0xf7,
+ 0x25, 0xdf, 0xf1, 0xbd, 0x9f, 0x99, 0xff, 0x37, 0x6c, 0x93, 0xa3, 0x11, 0xd3, 0x9e, 0xfd, 0xff, 0xf3, 0x73, 0x10, 0x8b,
+ 0x7f, 0x83, 0xb2, 0x6f, 0xfe, 0xc7, 0x6b, 0xfa, 0xff, 0xe7, 0x6f, 0x93, 0xb8, 0xf1, 0x5b, 0xf4, 0xe6, 0x7f, 0xb7, 0xfb,
+ 0x7f, 0x77, 0xff, 0x06, 0xed, 0x69, 0xe7, 0x3d, 0xcf, 0xfb, 0xfd, 0x4f, 0x6d, 0x4c, 0xfd, 0xa4, 0x7d, 0xf1, 0xae, 0x3b,
+ 0xe7, 0x2a, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0xd6, 0x55, 0xdf, 0x3c, 0x8a,
+ 0x33, 0xab, 0xce, 0xbd, 0x56, 0xa9, 0xe6, 0x1e, 0xcb, 0xbe, 0x6b, 0xa5, 0x36, 0x4b, 0xb4, 0xcd, 0x5d, 0xea, 0xda, 0x32,
+ 0x9f, 0x97, 0x1b, 0xc5, 0x2a, 0x2c, 0xbc, 0xeb, 0x08, 0xb0, 0xaa, 0x42, 0xfe, 0x68, 0xa8, 0x92, 0x5f, 0xab, 0xe6, 0x78,
+ 0x4f, 0x2d, 0xf7, 0xb9, 0x99, 0xb2, 0xeb, 0xb6, 0x4c, 0x6f, 0x9d, 0x7c, 0xde, 0x75, 0x04, 0x58, 0xf9, 0x1c, 0x91, 0x68,
+ 0xfc, 0xcc, 0xd8, 0xea, 0xbb, 0x8e, 0xaf, 0x33, 0xcf, 0x46, 0xa2, 0xf2, 0xc4, 0xfa, 0xb5, 0x8d, 0xd6, 0x96, 0x85, 0x3b,
+ 0x8e, 0x59, 0xcf, 0xde, 0x4b, 0xf7, 0xeb, 0x51, 0xe5, 0xff, 0xd7, 0x92, 0xb4, 0x7a, 0x8e, 0xf8, 0x6c, 0x5d, 0x8e, 0xfc,
+ 0x59, 0xea, 0x7e, 0x35, 0x1b, 0xa2, 0x30, 0xa7, 0x7f, 0x78, 0x4e, 0x06, 0x37, 0xf5, 0x3f, 0x9d, 0x75, 0x3b, 0xae, 0xcf,
+ 0xff, 0x5e, 0xaf, 0xd7, 0xfa, 0x7f, 0xf9, 0x47, 0xfe, 0xe5, 0x5f, 0xfe, 0x91, 0xff, 0xf7, 0xe6, 0x3f, 0xe4, 0x9f, 0x5b,
+ 0x47, 0xff, 0x2b, 0x9f, 0xdb, 0x21, 0xff, 0x73, 0x77, 0xff, 0xe4, 0x9f, 0x3b, 0xee, 0xfe, 0xf7, 0x55, 0xc8, 0x95, 0xff,
+ 0xda, 0xaf, 0xaf, 0xe4, 0x1f, 0xf9, 0x7f, 0x7b, 0xff, 0x2f, 0xff, 0xb8, 0xff, 0x77, 0x4d, 0xfe, 0xd5, 0xc9, 0xce, 0xfd,
+ 0x4a, 0x3a, 0xf7, 0x24, 0x44, 0xb8, 0xfe, 0xba, 0x85, 0xbd, 0xb1, 0xff, 0xb7, 0x99, 0x47, 0x2d, 0xab, 0xc5, 0xe1, 0x17,
+ 0xe6, 0x7f, 0xc9, 0x3f, 0xfc, 0xda, 0xc8, 0xaf, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe3, 0xcf, 0x7f, 0xda, 0x01, 0xe4, 0x1f, 0xf8, 0xb9, 0xfc, 0xff,
+ 0x01 };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle ashesFontRecs[189] = {
+ { 4, 4, 4 , 16 },
+ { 16, 4, 1 , 10 },
+ { 25, 4, 3 , 3 },
+ { 36, 4, 6 , 8 },
+ { 50, 4, 5 , 11 },
+ { 63, 4, 7 , 8 },
+ { 78, 4, 6 , 9 },
+ { 92, 4, 1 , 3 },
+ { 101, 4, 3 , 12 },
+ { 112, 4, 3 , 12 },
+ { 123, 4, 5 , 5 },
+ { 136, 4, 5 , 5 },
+ { 149, 4, 2 , 2 },
+ { 159, 4, 4 , 1 },
+ { 171, 4, 1 , 1 },
+ { 180, 4, 5 , 10 },
+ { 193, 4, 4 , 8 },
+ { 205, 4, 2 , 8 },
+ { 215, 4, 4 , 8 },
+ { 227, 4, 4 , 8 },
+ { 239, 4, 6 , 8 },
+ { 253, 4, 4 , 8 },
+ { 265, 4, 4 , 8 },
+ { 277, 4, 4 , 8 },
+ { 289, 4, 4 , 8 },
+ { 301, 4, 4 , 8 },
+ { 313, 4, 1 , 5 },
+ { 322, 4, 2 , 6 },
+ { 332, 4, 4 , 7 },
+ { 344, 4, 4 , 4 },
+ { 356, 4, 4 , 7 },
+ { 368, 4, 4 , 10 },
+ { 380, 4, 8 , 7 },
+ { 396, 4, 4 , 10 },
+ { 408, 4, 4 , 10 },
+ { 420, 4, 4 , 10 },
+ { 432, 4, 4 , 10 },
+ { 444, 4, 4 , 10 },
+ { 456, 4, 5 , 10 },
+ { 469, 4, 4 , 10 },
+ { 481, 4, 4 , 10 },
+ { 493, 4, 1 , 10 },
+ { 4, 28, 3 , 10 },
+ { 15, 28, 4 , 10 },
+ { 27, 28, 4 , 10 },
+ { 39, 28, 7 , 10 },
+ { 54, 28, 4 , 10 },
+ { 66, 28, 4 , 10 },
+ { 78, 28, 4 , 10 },
+ { 90, 28, 5 , 11 },
+ { 103, 28, 4 , 10 },
+ { 115, 28, 4 , 10 },
+ { 127, 28, 5 , 10 },
+ { 140, 28, 4 , 10 },
+ { 152, 28, 4 , 10 },
+ { 164, 28, 7 , 10 },
+ { 179, 28, 4 , 10 },
+ { 191, 28, 4 , 10 },
+ { 203, 28, 4 , 10 },
+ { 215, 28, 2 , 12 },
+ { 225, 28, 5 , 10 },
+ { 238, 28, 2 , 12 },
+ { 248, 28, 5 , 3 },
+ { 261, 28, 5 , 1 },
+ { 274, 28, 2 , 2 },
+ { 284, 28, 4 , 8 },
+ { 296, 28, 4 , 10 },
+ { 308, 28, 3 , 8 },
+ { 319, 28, 4 , 10 },
+ { 331, 28, 4 , 8 },
+ { 343, 28, 3 , 10 },
+ { 354, 28, 5 , 11 },
+ { 367, 28, 4 , 10 },
+ { 379, 28, 1 , 10 },
+ { 388, 28, 3 , 13 },
+ { 399, 28, 4 , 10 },
+ { 411, 28, 2 , 10 },
+ { 421, 28, 7 , 8 },
+ { 436, 28, 4 , 8 },
+ { 448, 28, 4 , 8 },
+ { 460, 28, 4 , 11 },
+ { 472, 28, 4 , 11 },
+ { 484, 28, 3 , 8 },
+ { 495, 28, 4 , 8 },
+ { 4, 52, 3 , 10 },
+ { 15, 52, 4 , 8 },
+ { 27, 52, 5 , 8 },
+ { 40, 52, 7 , 8 },
+ { 55, 52, 4 , 8 },
+ { 67, 52, 4 , 11 },
+ { 79, 52, 4 , 8 },
+ { 91, 52, 4 , 12 },
+ { 103, 52, 1 , 10 },
+ { 112, 52, 4 , 12 },
+ { 124, 52, 4 , 2 },
+ { 136, 52, 1 , 10 },
+ { 145, 52, 4 , 12 },
+ { 157, 52, 5 , 10 },
+ { 170, 52, 5 , 10 },
+ { 183, 52, 5 , 10 },
+ { 196, 52, 6 , 13 },
+ { 210, 52, 4 , 10 },
+ { 222, 52, 6 , 13 },
+ { 236, 52, 7 , 9 },
+ { 251, 52, 3 , 7 },
+ { 262, 52, 6 , 5 },
+ { 276, 52, 6 , 13 },
+ { 290, 52, 7 , 9 },
+ { 305, 52, 4 , 1 },
+ { 317, 52, 3 , 5 },
+ { 328, 52, 5 , 7 },
+ { 341, 52, 3 , 5 },
+ { 352, 52, 6 , 13 },
+ { 366, 52, 6 , 13 },
+ { 380, 52, 4 , 11 },
+ { 392, 52, 6 , 10 },
+ { 406, 52, 3 , 3 },
+ { 417, 52, 6 , 13 },
+ { 431, 52, 2 , 5 },
+ { 441, 52, 3 , 5 },
+ { 452, 52, 6 , 5 },
+ { 466, 52, 7 , 10 },
+ { 481, 52, 7 , 8 },
+ { 496, 52, 6 , 13 },
+ { 4, 76, 4 , 10 },
+ { 16, 76, 4 , 13 },
+ { 28, 76, 4 , 13 },
+ { 40, 76, 4 , 13 },
+ { 52, 76, 4 , 13 },
+ { 64, 76, 4 , 13 },
+ { 76, 76, 4 , 13 },
+ { 88, 76, 7 , 10 },
+ { 103, 76, 4 , 13 },
+ { 115, 76, 4 , 13 },
+ { 127, 76, 4 , 13 },
+ { 139, 76, 4 , 13 },
+ { 151, 76, 4 , 13 },
+ { 163, 76, 2 , 13 },
+ { 173, 76, 2 , 13 },
+ { 183, 76, 3 , 13 },
+ { 194, 76, 3 , 13 },
+ { 205, 76, 5 , 10 },
+ { 218, 76, 4 , 13 },
+ { 230, 76, 4 , 13 },
+ { 242, 76, 4 , 13 },
+ { 254, 76, 4 , 13 },
+ { 266, 76, 4 , 13 },
+ { 278, 76, 4 , 13 },
+ { 290, 76, 5 , 5 },
+ { 303, 76, 6 , 12 },
+ { 317, 76, 4 , 13 },
+ { 329, 76, 4 , 13 },
+ { 341, 76, 4 , 13 },
+ { 353, 76, 4 , 13 },
+ { 365, 76, 4 , 13 },
+ { 377, 76, 6 , 13 },
+ { 391, 76, 5 , 12 },
+ { 404, 76, 4 , 12 },
+ { 416, 76, 4 , 12 },
+ { 428, 76, 4 , 12 },
+ { 440, 76, 4 , 12 },
+ { 452, 76, 4 , 12 },
+ { 464, 76, 4 , 12 },
+ { 476, 76, 7 , 8 },
+ { 491, 76, 3 , 11 },
+ { 4, 100, 4 , 12 },
+ { 16, 100, 4 , 12 },
+ { 28, 100, 4 , 12 },
+ { 40, 100, 4 , 12 },
+ { 52, 100, 3 , 12 },
+ { 63, 100, 3 , 12 },
+ { 74, 100, 3 , 12 },
+ { 85, 100, 3 , 12 },
+ { 96, 100, 6 , 13 },
+ { 110, 100, 4 , 12 },
+ { 122, 100, 4 , 12 },
+ { 134, 100, 4 , 12 },
+ { 146, 100, 4 , 12 },
+ { 158, 100, 4 , 12 },
+ { 170, 100, 4 , 12 },
+ { 182, 100, 5 , 5 },
+ { 195, 100, 6 , 10 },
+ { 209, 100, 4 , 12 },
+ { 221, 100, 4 , 12 },
+ { 233, 100, 4 , 12 },
+ { 245, 100, 4 , 12 },
+ { 257, 100, 4 , 15 },
+ { 269, 100, 6 , 13 },
+ { 283, 100, 4 , 15 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo ashesFontGlyphs[189] = {
+ { 32, 0, 13, 4, { 0 }},
+ { 33, 0, 3, 4, { 0 }},
+ { 34, 0, 1, 5, { 0 }},
+ { 35, 0, 4, 8, { 0 }},
+ { 36, 0, 2, 7, { 0 }},
+ { 37, 0, 5, 9, { 0 }},
+ { 38, 0, 4, 8, { 0 }},
+ { 39, 0, 1, 3, { 0 }},
+ { 40, 0, 2, 5, { 0 }},
+ { 41, 0, 2, 5, { 0 }},
+ { 42, 0, 3, 7, { 0 }},
+ { 43, 0, 6, 7, { 0 }},
+ { 44, 0, 12, 4, { 0 }},
+ { 45, 0, 9, 5, { 0 }},
+ { 46, 0, 12, 3, { 0 }},
+ { 47, 0, 3, 7, { 0 }},
+ { 48, 0, 5, 6, { 0 }},
+ { 49, 0, 5, 4, { 0 }},
+ { 50, 0, 5, 6, { 0 }},
+ { 51, 0, 5, 6, { 0 }},
+ { 52, 0, 5, 8, { 0 }},
+ { 53, 0, 5, 6, { 0 }},
+ { 54, 0, 5, 6, { 0 }},
+ { 55, 0, 5, 6, { 0 }},
+ { 56, 0, 5, 6, { 0 }},
+ { 57, 0, 5, 6, { 0 }},
+ { 58, 0, 8, 3, { 0 }},
+ { 59, 0, 8, 4, { 0 }},
+ { 60, 0, 5, 6, { 0 }},
+ { 61, 0, 7, 7, { 0 }},
+ { 62, 0, 5, 6, { 0 }},
+ { 63, 1, 3, 7, { 0 }},
+ { 64, 0, 5, 10, { 0 }},
+ { 65, 0, 3, 6, { 0 }},
+ { 66, 0, 3, 6, { 0 }},
+ { 67, 0, 3, 6, { 0 }},
+ { 68, 0, 3, 6, { 0 }},
+ { 69, 0, 3, 6, { 0 }},
+ { 70, 0, 3, 6, { 0 }},
+ { 71, 0, 3, 6, { 0 }},
+ { 72, 0, 3, 6, { 0 }},
+ { 73, 0, 3, 3, { 0 }},
+ { 74, 0, 3, 5, { 0 }},
+ { 75, 0, 3, 6, { 0 }},
+ { 76, 0, 3, 6, { 0 }},
+ { 77, 0, 3, 9, { 0 }},
+ { 78, 0, 3, 6, { 0 }},
+ { 79, 0, 3, 6, { 0 }},
+ { 80, 0, 3, 6, { 0 }},
+ { 81, 0, 3, 7, { 0 }},
+ { 82, 0, 3, 6, { 0 }},
+ { 83, 0, 3, 6, { 0 }},
+ { 84, 0, 3, 6, { 0 }},
+ { 85, 0, 3, 6, { 0 }},
+ { 86, 0, 3, 6, { 0 }},
+ { 87, 0, 3, 9, { 0 }},
+ { 88, 0, 3, 6, { 0 }},
+ { 89, 0, 3, 6, { 0 }},
+ { 90, 0, 3, 6, { 0 }},
+ { 91, 0, 2, 4, { 0 }},
+ { 92, 0, 3, 7, { 0 }},
+ { 93, 0, 2, 4, { 0 }},
+ { 94, 0, 3, 7, { 0 }},
+ { 95, 0, 12, 7, { 0 }},
+ { 96, 0, 1, 4, { 0 }},
+ { 97, 0, 5, 6, { 0 }},
+ { 98, 0, 3, 6, { 0 }},
+ { 99, 0, 5, 5, { 0 }},
+ { 100, 0, 3, 6, { 0 }},
+ { 101, 0, 5, 6, { 0 }},
+ { 102, 0, 3, 5, { 0 }},
+ { 103, 0, 5, 6, { 0 }},
+ { 104, 0, 3, 6, { 0 }},
+ { 105, 0, 3, 3, { 0 }},
+ { 106, 0, 3, 5, { 0 }},
+ { 107, 0, 3, 6, { 0 }},
+ { 108, 0, 3, 4, { 0 }},
+ { 109, 0, 5, 9, { 0 }},
+ { 110, 0, 5, 6, { 0 }},
+ { 111, 0, 5, 6, { 0 }},
+ { 112, 0, 5, 6, { 0 }},
+ { 113, 0, 5, 6, { 0 }},
+ { 114, 0, 5, 5, { 0 }},
+ { 115, 0, 5, 6, { 0 }},
+ { 116, 0, 3, 5, { 0 }},
+ { 117, 0, 5, 6, { 0 }},
+ { 118, 0, 5, 7, { 0 }},
+ { 119, 0, 5, 9, { 0 }},
+ { 120, 0, 5, 6, { 0 }},
+ { 121, 0, 5, 6, { 0 }},
+ { 122, 0, 5, 6, { 0 }},
+ { 123, 0, 2, 6, { 0 }},
+ { 124, 0, 3, 3, { 0 }},
+ { 125, 0, 2, 6, { 0 }},
+ { 126, 0, 1, 6, { 0 }},
+ { 161, 0, 4, 4, { 0 }},
+ { 162, 0, 3, 6, { 0 }},
+ { 163, 0, 3, 7, { 0 }},
+ { 8364, 0, 3, 7, { 0 }},
+ { 165, 0, 3, 7, { 0 }},
+ { 352, 1, 0, 8, { 0 }},
+ { 167, 0, 3, 6, { 0 }},
+ { 353, 1, 0, 8, { 0 }},
+ { 169, 0, 1, 9, { 0 }},
+ { 170, 0, 1, 5, { 0 }},
+ { 171, 0, 6, 8, { 0 }},
+ { 172, 1, 0, 8, { 0 }},
+ { 174, 0, 1, 9, { 0 }},
+ { 175, 0, 0, 6, { 0 }},
+ { 176, 0, 1, 5, { 0 }},
+ { 177, 0, 5, 7, { 0 }},
+ { 178, 0, 1, 5, { 0 }},
+ { 179, 1, 0, 8, { 0 }},
+ { 381, 1, 0, 8, { 0 }},
+ { 181, 0, 5, 6, { 0 }},
+ { 182, 0, 3, 8, { 0 }},
+ { 183, 0, 7, 5, { 0 }},
+ { 382, 1, 0, 8, { 0 }},
+ { 185, 0, 1, 4, { 0 }},
+ { 186, 0, 1, 5, { 0 }},
+ { 187, 0, 6, 8, { 0 }},
+ { 338, 0, 3, 9, { 0 }},
+ { 339, 0, 5, 9, { 0 }},
+ { 376, 1, 0, 8, { 0 }},
+ { 191, 0, 4, 6, { 0 }},
+ { 192, 0, 0, 6, { 0 }},
+ { 193, 0, 0, 6, { 0 }},
+ { 194, 0, 0, 6, { 0 }},
+ { 195, 0, 0, 6, { 0 }},
+ { 196, 0, 0, 6, { 0 }},
+ { 197, 0, 0, 6, { 0 }},
+ { 198, 0, 3, 9, { 0 }},
+ { 199, 0, 3, 6, { 0 }},
+ { 200, 0, 0, 6, { 0 }},
+ { 201, 0, 0, 6, { 0 }},
+ { 202, 0, 0, 6, { 0 }},
+ { 203, 0, 0, 6, { 0 }},
+ { 204, 0, 0, 4, { 0 }},
+ { 205, 0, 0, 4, { 0 }},
+ { 206, 0, 0, 5, { 0 }},
+ { 207, 0, 0, 5, { 0 }},
+ { 208, 0, 3, 7, { 0 }},
+ { 209, 0, 0, 6, { 0 }},
+ { 210, 0, 0, 6, { 0 }},
+ { 211, 0, 0, 6, { 0 }},
+ { 212, 0, 0, 6, { 0 }},
+ { 213, 0, 0, 6, { 0 }},
+ { 214, 0, 0, 6, { 0 }},
+ { 215, 0, 7, 7, { 0 }},
+ { 216, 0, 2, 8, { 0 }},
+ { 217, 0, 0, 6, { 0 }},
+ { 218, 0, 0, 6, { 0 }},
+ { 219, 0, 0, 6, { 0 }},
+ { 220, 0, 0, 6, { 0 }},
+ { 221, 0, 0, 6, { 0 }},
+ { 222, 1, 0, 8, { 0 }},
+ { 223, 0, 3, 7, { 0 }},
+ { 224, 0, 1, 6, { 0 }},
+ { 225, 0, 1, 6, { 0 }},
+ { 226, 0, 1, 6, { 0 }},
+ { 227, 0, 1, 6, { 0 }},
+ { 228, 0, 1, 6, { 0 }},
+ { 229, 0, 1, 6, { 0 }},
+ { 230, 0, 5, 9, { 0 }},
+ { 231, 0, 5, 5, { 0 }},
+ { 232, 0, 1, 6, { 0 }},
+ { 233, 0, 1, 6, { 0 }},
+ { 234, 0, 1, 6, { 0 }},
+ { 235, 0, 1, 6, { 0 }},
+ { 236, 0, 1, 5, { 0 }},
+ { 237, 0, 1, 5, { 0 }},
+ { 238, 0, 1, 5, { 0 }},
+ { 239, 0, 1, 5, { 0 }},
+ { 240, 1, 0, 8, { 0 }},
+ { 241, 0, 1, 6, { 0 }},
+ { 242, 0, 1, 6, { 0 }},
+ { 243, 0, 1, 6, { 0 }},
+ { 244, 0, 1, 6, { 0 }},
+ { 245, 0, 1, 6, { 0 }},
+ { 246, 0, 1, 6, { 0 }},
+ { 247, 0, 7, 7, { 0 }},
+ { 248, 0, 4, 8, { 0 }},
+ { 249, 0, 1, 6, { 0 }},
+ { 250, 0, 1, 6, { 0 }},
+ { 251, 0, 1, 6, { 0 }},
+ { 252, 0, 1, 6, { 0 }},
+ { 253, 0, 1, 6, { 0 }},
+ { 254, 1, 0, 8, { 0 }},
+ { 255, 0, 1, 6, { 0 }},
+};
+
+// Style loading function: Ashes
+static void GuiLoadStyleAshes(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < ASHES_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(ashesStyleProps[i].controlId, ashesStyleProps[i].propertyId, ashesStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int ashesFontDataSize = 0;
+ unsigned char *data = DecompressData(ashesFontData, ASHES_STYLE_FONT_ATLAS_COMP_SIZE, &ashesFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 16;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, ashesFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, ashesFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_bluish.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_bluish.h
new file mode 100644
index 0000000000..9025e5dfac
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_bluish.h
@@ -0,0 +1,619 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleBluish(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define BLUISH_STYLE_PROPS_COUNT 14
+
+// Custom style name: Bluish
+static const GuiStyleProp bluishStyleProps[BLUISH_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0x5ca6a6ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0xb4e8f3ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0x447e77ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0x5f8792ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0xcdeff7ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0x4c6c74ff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0x3b5b5fff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0xeaffffff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0x275057ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x96aaacff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0xc8d7d9ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x8c9c9eff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 18, 0x84adb7ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0xe8eef1ff }, // DEFAULT_BACKGROUND_COLOR
+};
+
+// WARNING: This style uses a custom font: "homespun.ttf" (size: 10, spacing: 1)
+
+#define BLUISH_STYLE_FONT_ATLAS_COMP_SIZE 2914
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char bluishFontData[BLUISH_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0x9d, 0xb1, 0x8e, 0x24, 0x49, 0x11, 0x86, 0x2b, 0xf3, 0x00, 0x09, 0x13, 0x01, 0x12, 0xe0, 0x20, 0x81, 0x90, 0xf0, 0x10,
+ 0x12, 0x2e, 0x16, 0x3c, 0x02, 0x2f, 0x02, 0x0e, 0xef, 0x81, 0x07, 0x12, 0x06, 0x12, 0xce, 0x99, 0x38, 0x48, 0x20, 0xe1,
+ 0x81, 0x83, 0xc0, 0xc3, 0xc5, 0xe5, 0x2c, 0x8c, 0xc3, 0x81, 0x93, 0x26, 0x33, 0xd0, 0x4e, 0xcf, 0x2e, 0xe2, 0xae, 0xfe,
+ 0xc8, 0x8a, 0xac, 0xa8, 0xea, 0xea, 0x9b, 0x6f, 0x3f, 0xed, 0x1a, 0x95, 0x5d, 0xd5, 0x99, 0x19, 0x59, 0x35, 0xb3, 0x9d,
+ 0x5f, 0x47, 0xd8, 0x02, 0x00, 0x00, 0x00, 0xf0, 0x09, 0xaa, 0x38, 0x56, 0xe5, 0xab, 0x6b, 0xe0, 0x4a, 0xb7, 0xe3, 0xd5,
+ 0x69, 0x8f, 0x5d, 0xad, 0x06, 0xae, 0xe0, 0xb5, 0xf8, 0x6d, 0x1f, 0xa7, 0xbc, 0x90, 0x31, 0xb3, 0xf5, 0xdd, 0x7c, 0xac,
+ 0xcf, 0x52, 0xe4, 0xf5, 0x35, 0x34, 0x8a, 0x75, 0x4c, 0x1c, 0xeb, 0xab, 0xe3, 0x35, 0x2b, 0xa2, 0xa5, 0x9a, 0x89, 0xfe,
+ 0xd8, 0xf3, 0x59, 0xeb, 0x57, 0xf4, 0xce, 0x5a, 0x7b, 0x8f, 0xb6, 0x72, 0x8d, 0x26, 0x57, 0xc5, 0x9b, 0x77, 0x54, 0x33,
+ 0xd4, 0x45, 0x3c, 0x6d, 0xf5, 0xb5, 0x37, 0xca, 0xa6, 0x57, 0x7b, 0xef, 0x60, 0xd6, 0xac, 0xbd, 0xcc, 0xc7, 0xc7, 0x47,
+ 0x61, 0xa1, 0xd7, 0xeb, 0x96, 0xfd, 0xf1, 0xef, 0xcf, 0xfd, 0x29, 0x2b, 0xf7, 0xc1, 0x9b, 0x68, 0x75, 0x11, 0x2f, 0xd5,
+ 0x9f, 0xdb, 0xcc, 0x95, 0xd5, 0x2b, 0x7a, 0x67, 0x2d, 0x9b, 0x67, 0x7b, 0xfd, 0xfc, 0x5b, 0x4f, 0xd7, 0xc7, 0x51, 0x9e,
+ 0xdb, 0xd6, 0xe6, 0xae, 0x25, 0x3d, 0x57, 0xd5, 0x78, 0x17, 0xf7, 0xde, 0x5a, 0x9f, 0x85, 0x1e, 0x6a, 0xd9, 0x1f, 0x7f,
+ 0xbd, 0xa2, 0xed, 0xe5, 0xaf, 0x1a, 0x59, 0x13, 0xfd, 0x29, 0xa2, 0xc5, 0x3f, 0x6b, 0x4f, 0xfc, 0xcb, 0x4b, 0x4f, 0xab,
+ 0xb8, 0x9f, 0x4d, 0xdc, 0xd1, 0x47, 0x46, 0x3f, 0x1e, 0xff, 0xf2, 0xb2, 0x56, 0x8b, 0xf8, 0xa9, 0x74, 0x6e, 0xfc, 0xcb,
+ 0xcb, 0xf3, 0xbf, 0x8a, 0xde, 0x17, 0x19, 0x7d, 0xfd, 0xb4, 0x8d, 0xfc, 0x5c, 0x8d, 0xdd, 0xff, 0xb7, 0x79, 0x56, 0x6b,
+ 0xeb, 0xb8, 0xd8, 0xfb, 0xe3, 0x8d, 0xc5, 0xdf, 0xe4, 0x4f, 0x9e, 0xb7, 0xab, 0x78, 0xef, 0x28, 0x7a, 0xd2, 0xfd, 0xdf,
+ 0x65, 0x7f, 0xca, 0xcb, 0xf3, 0x7f, 0x7d, 0xcc, 0x91, 0xbb, 0x30, 0x12, 0xff, 0x51, 0x8c, 0x8f, 0xbc, 0xf7, 0xf5, 0xb5,
+ 0xe3, 0xf1, 0xbf, 0x5d, 0x71, 0xed, 0x5d, 0x8e, 0x5e, 0xc5, 0x4b, 0xe8, 0xf7, 0xbf, 0xe2, 0xfc, 0xce, 0xf3, 0x76, 0xed,
+ 0x44, 0xc6, 0x97, 0x15, 0xe7, 0xf3, 0xb1, 0xe1, 0x08, 0x22, 0xf1, 0x2f, 0x72, 0x56, 0xcb, 0xe9, 0x3f, 0xff, 0xbd, 0xf8,
+ 0x7b, 0x3d, 0xf5, 0xe2, 0x1f, 0x1b, 0x85, 0x05, 0x7f, 0x07, 0xbf, 0x5e, 0xfc, 0xed, 0xdd, 0xff, 0x87, 0xb6, 0x8d, 0x4d,
+ 0xbd, 0xde, 0xbb, 0xd2, 0x7d, 0x46, 0x3d, 0xd3, 0x9f, 0xab, 0x8d, 0x02, 0xf6, 0xf0, 0x34, 0x11, 0xc7, 0x27, 0x62, 0x0f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x66, 0xf9, 0x64, 0x19, 0x26, 0xd9, 0x2d, 0xfb, 0xac, 0x20, 0x6d, 0xe7,
+ 0x78, 0x46, 0x92, 0xdf, 0xcb, 0xb3, 0xe6, 0x63, 0x39, 0xc9, 0xf9, 0xb1, 0x09, 0x23, 0xe5, 0xac, 0x96, 0xb6, 0xd9, 0xc2,
+ 0x58, 0xdf, 0xcd, 0xd5, 0x76, 0x4e, 0x17, 0x73, 0x35, 0xea, 0xe5, 0x79, 0xf3, 0x51, 0x27, 0x7a, 0x37, 0xf3, 0x69, 0xb9,
+ 0x0d, 0x76, 0xe7, 0x5a, 0xa8, 0xa5, 0x0f, 0xf7, 0xfa, 0x62, 0xe6, 0xcb, 0xbe, 0x7d, 0x55, 0xcf, 0xce, 0x53, 0xfe, 0x87,
+ 0xd7, 0x4b, 0xe5, 0x55, 0xd8, 0xf4, 0xa8, 0x5b, 0xea, 0x39, 0x6d, 0x2a, 0xfe, 0x7a, 0x54, 0x7a, 0x6f, 0xde, 0xb7, 0x1e,
+ 0xf5, 0xd5, 0x62, 0x2d, 0xdb, 0xed, 0x03, 0x15, 0x63, 0xed, 0x48, 0x44, 0xdd, 0x19, 0x73, 0xbc, 0x8a, 0xd1, 0xd8, 0x5a,
+ 0x68, 0x6f, 0xd2, 0x06, 0x73, 0xb8, 0xdf, 0x96, 0xd9, 0x66, 0x67, 0x74, 0x67, 0xbc, 0xbe, 0x61, 0xd2, 0x43, 0xe7, 0xf4,
+ 0x04, 0x5f, 0x25, 0xba, 0x7a, 0x3c, 0x0f, 0xa7, 0x3b, 0xf1, 0xaf, 0xc1, 0xb1, 0xdd, 0x5a, 0x6a, 0x68, 0x2f, 0xd8, 0x06,
+ 0x73, 0xb8, 0xdf, 0x96, 0xd9, 0x36, 0x7f, 0x65, 0xfa, 0x89, 0x9d, 0x75, 0xce, 0x71, 0x2b, 0xc0, 0xc2, 0xd7, 0xb1, 0x77,
+ 0x2b, 0x35, 0xf3, 0xf9, 0x5f, 0x26, 0x7e, 0x22, 0x97, 0xdd, 0xae, 0xc6, 0xf6, 0x27, 0xf6, 0x9c, 0x61, 0x92, 0x75, 0xce,
+ 0xb5, 0xdc, 0x8d, 0x32, 0xf9, 0xc4, 0x3e, 0xa7, 0xe5, 0x88, 0xf8, 0xcf, 0x1a, 0x26, 0x3d, 0xed, 0x9c, 0xe5, 0x74, 0xa7,
+ 0xc7, 0xe4, 0xfd, 0xef, 0xcd, 0x47, 0xe6, 0x1c, 0x7a, 0x1e, 0x90, 0xdf, 0x83, 0xd7, 0x40, 0xe3, 0x33, 0x1b, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0xe3, 0xdb, 0x37, 0x31, 0x43, 0xc5, 0xb7, 0x76, 0xa2, 0x39, 0x7a,
+ 0xea, 0xe9, 0xd6, 0x4d, 0x76, 0xcb, 0xcc, 0x5c, 0x8c, 0x5a, 0x62, 0x67, 0x8e, 0x3f, 0xef, 0xd6, 0x4e, 0x89, 0xfa, 0x54,
+ 0xbb, 0x3d, 0x9f, 0x95, 0xb3, 0xfb, 0x67, 0xc3, 0x9e, 0xdd, 0xfe, 0xad, 0x17, 0xf4, 0x93, 0x3c, 0x73, 0xe9, 0x6d, 0xcf,
+ 0x33, 0x77, 0x0b, 0x6f, 0x2d, 0x6d, 0x75, 0x2e, 0x66, 0xf7, 0xd0, 0x66, 0x3c, 0x14, 0x7f, 0x37, 0x2c, 0x2f, 0xfe, 0xb3,
+ 0x63, 0x3e, 0xb7, 0x25, 0x9a, 0x47, 0xe4, 0x7a, 0xf1, 0xf7, 0x2c, 0x9f, 0xac, 0xf8, 0xef, 0xf3, 0x60, 0xf2, 0xe2, 0x3f,
+ 0xe3, 0x70, 0xe9, 0xbe, 0x7b, 0x1e, 0xd4, 0x99, 0xf1, 0xd7, 0x79, 0xb4, 0xb6, 0xc4, 0x3f, 0x6e, 0xf9, 0xc4, 0xe3, 0xbf,
+ 0xcf, 0x83, 0xc9, 0x8b, 0xff, 0x8c, 0xc3, 0xd1, 0x9d, 0x6c, 0x51, 0x3d, 0x9c, 0x7b, 0xc4, 0x06, 0x8e, 0x61, 0x9b, 0x88,
+ 0x7f, 0x91, 0x7d, 0xdc, 0xeb, 0x7f, 0x46, 0xee, 0xff, 0x72, 0x98, 0x07, 0x93, 0xfb, 0xfc, 0xcf, 0x9a, 0x87, 0x32, 0xb0,
+ 0x0f, 0xcb, 0x84, 0x2d, 0xd2, 0x93, 0xe7, 0x62, 0x9b, 0xef, 0x90, 0x13, 0xff, 0x99, 0x6b, 0x6d, 0x3b, 0x27, 0x1a, 0xff,
+ 0x32, 0x11, 0xff, 0xcc, 0xbe, 0xfb, 0xf1, 0x2f, 0x8e, 0x2d, 0x32, 0x3e, 0x27, 0x3b, 0xfe, 0xb3, 0x56, 0x4b, 0x49, 0xbc,
+ 0x96, 0x25, 0xc7, 0x3f, 0xee, 0xc9, 0xe4, 0xf6, 0xdd, 0x8f, 0xff, 0x7c, 0xef, 0x6e, 0x7f, 0xea, 0x01, 0x0e, 0x3d, 0x90,
+ 0x71, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0xb3, 0x38, 0x15, 0xa9, 0x7c, 0xcb, 0x68, 0xbb,
+ 0x2d, 0xf4, 0xd6, 0xa0, 0x58, 0xf7, 0x27, 0x72, 0x32, 0xfd, 0x8c, 0x6b, 0x77, 0x45, 0xdf, 0x47, 0xcd, 0xd6, 0x4c, 0xdf,
+ 0x8e, 0xae, 0x71, 0xb6, 0xcd, 0xf2, 0xf1, 0xbc, 0x97, 0xd8, 0x77, 0x50, 0x55, 0x6e, 0x9a, 0x2a, 0x32, 0xdd, 0x44, 0xbf,
+ 0xbb, 0xef, 0xe5, 0xaa, 0xd0, 0xd7, 0xc9, 0xcc, 0x62, 0x61, 0x72, 0xbd, 0xda, 0x44, 0xdf, 0x9a, 0x38, 0xaa, 0xae, 0x51,
+ 0xa7, 0xbf, 0x29, 0x3d, 0x9f, 0xcb, 0x61, 0x6b, 0x4e, 0x25, 0xbd, 0x63, 0x78, 0xdb, 0xeb, 0x8e, 0xae, 0x80, 0x2e, 0xef,
+ 0xb1, 0xf5, 0xbe, 0x56, 0xe9, 0xb7, 0x2c, 0xb2, 0x9a, 0x59, 0x3c, 0x57, 0x8d, 0x89, 0xaa, 0x61, 0xfe, 0xfe, 0x91, 0xea,
+ 0x9b, 0xaa, 0x96, 0xb4, 0x88, 0x6b, 0xb4, 0xe9, 0xef, 0x84, 0xdb, 0xa0, 0x8e, 0x54, 0xe4, 0xca, 0xde, 0x0a, 0xf0, 0x2a,
+ 0xb9, 0xb5, 0x84, 0x5a, 0x25, 0xf1, 0x5c, 0x35, 0x9e, 0x79, 0xe0, 0x5f, 0x2d, 0x9a, 0x9b, 0x45, 0xaf, 0x99, 0xd8, 0x93,
+ 0x21, 0x2b, 0xc3, 0xcc, 0xb6, 0x27, 0x67, 0x71, 0x46, 0xb4, 0x84, 0x57, 0xc0, 0xb1, 0x95, 0x3c, 0x8e, 0x33, 0x0f, 0xb6,
+ 0x8e, 0x22, 0x7b, 0x67, 0x79, 0x7b, 0xfc, 0x97, 0x5d, 0x39, 0x41, 0xca, 0xb4, 0x2b, 0x13, 0x5b, 0x01, 0x47, 0xc7, 0xff,
+ 0x28, 0xf3, 0x20, 0x2b, 0x03, 0x47, 0xbf, 0x68, 0xfc, 0x47, 0xd9, 0x66, 0xe2, 0xb1, 0x8c, 0x1b, 0xa3, 0xcb, 0x5d, 0x9e,
+ 0x0c, 0xd9, 0xe7, 0x2c, 0xe1, 0xff, 0xc9, 0x5c, 0x23, 0xfe, 0x73, 0x19, 0x6a, 0x4a, 0x38, 0x97, 0xd0, 0xbd, 0xe2, 0x1f,
+ 0xaf, 0x23, 0x35, 0x77, 0x4e, 0xbe, 0x7b, 0x79, 0x46, 0xfc, 0xe1, 0x71, 0x32, 0x1f, 0x35, 0xfc, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x52, 0xfe, 0x8f, 0x88, 0xbd, 0x72, 0xff, 0x96, 0x3a, 0xd8, 0xd5, 0x2a, 0xd3, 0x2d,
+ 0x25, 0xed, 0x9a, 0x9e, 0x63, 0xb4, 0xb7, 0xe6, 0xd9, 0xdb, 0x6b, 0x97, 0x69, 0xfb, 0xe7, 0x7f, 0x7b, 0xd0, 0xb7, 0x7f,
+ 0x6b, 0xd2, 0xce, 0x7a, 0x7e, 0xcb, 0xf1, 0xdf, 0xe6, 0x3f, 0x22, 0xdf, 0x80, 0x97, 0x21, 0xa2, 0x6e, 0x76, 0x2b, 0x9a,
+ 0xdc, 0x53, 0xed, 0x32, 0x67, 0x40, 0x9b, 0xd8, 0x83, 0xb8, 0x7f, 0x96, 0x9d, 0x16, 0xac, 0x43, 0x55, 0x4f, 0xcc, 0xb1,
+ 0xd1, 0x07, 0x3e, 0x4c, 0xcc, 0xa1, 0xd1, 0x39, 0x14, 0x96, 0xd0, 0x6b, 0x55, 0x4d, 0xa2, 0xf2, 0x90, 0xf1, 0x5f, 0x82,
+ 0x6e, 0x5f, 0xdf, 0x90, 0x2f, 0x23, 0x2b, 0xc7, 0x46, 0x99, 0x30, 0x7c, 0x8a, 0x53, 0x7f, 0x2c, 0x16, 0x7f, 0x55, 0xad,
+ 0x2e, 0xfe, 0x6c, 0x3c, 0x23, 0xcb, 0x46, 0x7e, 0x05, 0x9b, 0xbc, 0x6c, 0x1e, 0xf9, 0x39, 0x36, 0xbc, 0x9d, 0x72, 0xed,
+ 0x55, 0xc6, 0xe2, 0x1f, 0xcd, 0xed, 0x70, 0x46, 0xfc, 0x67, 0x6b, 0xdb, 0xe4, 0x66, 0xe6, 0x28, 0x17, 0xc9, 0xb1, 0x11,
+ 0xcd, 0x10, 0xb2, 0xff, 0xf9, 0x9f, 0xed, 0x23, 0xe4, 0xed, 0x54, 0x9f, 0x93, 0x67, 0x63, 0xc6, 0xd3, 0x39, 0x6a, 0x67,
+ 0x3e, 0xbe, 0x3b, 0x1f, 0x71, 0x2b, 0xfb, 0x43, 0xc5, 0xff, 0xca, 0x6e, 0xcf, 0x95, 0x38, 0xb2, 0xe6, 0x19, 0xf6, 0xcf,
+ 0xa3, 0xae, 0x69, 0xe6, 0xe0, 0x75, 0x5b, 0x5e, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x93, 0x01,
+ 0x68, 0x91, 0x39, 0x6d, 0x3e, 0x79, 0xfc, 0x8b, 0x56, 0xed, 0x5b, 0xf6, 0x35, 0xfb, 0x8e, 0x7d, 0xd7, 0xbe, 0xe2, 0x5c,
+ 0xb1, 0xa6, 0xe5, 0x1b, 0x1a, 0x9d, 0x53, 0x83, 0x75, 0xca, 0x4a, 0xd8, 0xd7, 0xd9, 0x57, 0x8b, 0x2c, 0x36, 0xf3, 0xd1,
+ 0x6b, 0x8d, 0xe2, 0xe1, 0xfb, 0x5f, 0x9e, 0x45, 0xb1, 0x9e, 0xb7, 0xe7, 0xe7, 0xf6, 0x64, 0x1f, 0xda, 0x3f, 0xed, 0x1f,
+ 0xf6, 0x37, 0xfb, 0xd0, 0x3e, 0x2b, 0x3f, 0xc3, 0x5c, 0xf7, 0x52, 0xde, 0x8c, 0xe1, 0x29, 0x58, 0x4d, 0xcb, 0x3f, 0x47,
+ 0x55, 0x08, 0x53, 0xd7, 0x2b, 0xcf, 0xd6, 0x44, 0x0b, 0xf9, 0x3a, 0xe3, 0x77, 0x52, 0xdf, 0xf1, 0x6e, 0xe1, 0x0a, 0x01,
+ 0x7e, 0x55, 0xb1, 0x78, 0x3c, 0xe6, 0x32, 0xa7, 0xdc, 0xf6, 0xd7, 0xd6, 0xc6, 0xf4, 0x7b, 0xfb, 0x8f, 0xfd, 0xc0, 0xaa,
+ 0xfd, 0xd0, 0xbe, 0x6a, 0x7f, 0xb5, 0xcf, 0xc9, 0xbc, 0x36, 0xeb, 0xe3, 0x6b, 0xd2, 0x87, 0xd1, 0xb9, 0x60, 0xbc, 0x73,
+ 0xca, 0xcb, 0x2e, 0x60, 0x5d, 0xbd, 0x5f, 0xd6, 0xad, 0xac, 0xe2, 0xe6, 0xaa, 0xd1, 0xde, 0x50, 0x19, 0xe6, 0x39, 0x5a,
+ 0x9b, 0x8b, 0x2e, 0x72, 0x0c, 0x75, 0x71, 0xe7, 0xa9, 0x7e, 0xab, 0xe3, 0xa3, 0x78, 0x8c, 0xf7, 0x1b, 0xd6, 0xb3, 0x20,
+ 0x99, 0x18, 0xe9, 0xaf, 0xed, 0xcf, 0xf6, 0x0d, 0xfb, 0xb6, 0xfd, 0xcb, 0xfe, 0x6d, 0x1f, 0xd9, 0x67, 0x56, 0xef, 0x22,
+ 0xe5, 0xe6, 0xe8, 0x27, 0xa5, 0x97, 0x0d, 0xa9, 0x38, 0x39, 0x9c, 0xba, 0x8c, 0xa7, 0xbe, 0xf7, 0xba, 0x5c, 0x9d, 0xde,
+ 0x3c, 0xf5, 0xe1, 0xca, 0x51, 0x7b, 0xc3, 0x25, 0x34, 0x47, 0xaa, 0x72, 0xa0, 0xba, 0xff, 0x47, 0xf1, 0x18, 0xc7, 0xbf,
+ 0x08, 0x43, 0x65, 0x7d, 0x8e, 0x7e, 0x61, 0x7f, 0xb7, 0xaf, 0xdb, 0x97, 0xec, 0x0b, 0xf6, 0x79, 0x7b, 0x5f, 0xc4, 0x4b,
+ 0xad, 0xed, 0x51, 0x06, 0xa5, 0xb8, 0x01, 0x7a, 0x8b, 0xc7, 0x7a, 0xfc, 0x6b, 0x9a, 0x1d, 0x60, 0xef, 0x9e, 0x0b, 0x73,
+ 0x75, 0xb6, 0x22, 0xcf, 0x7f, 0xf5, 0x13, 0x59, 0x3d, 0x53, 0x47, 0xf1, 0x98, 0x75, 0x28, 0x4c, 0xdc, 0x75, 0x7f, 0xb0,
+ 0x9f, 0xd9, 0x4f, 0xed, 0x7b, 0xf6, 0x2b, 0xfb, 0xc8, 0x9a, 0x7d, 0x33, 0xb8, 0xb6, 0x4b, 0xb8, 0xde, 0xa0, 0x4d, 0xde,
+ 0xff, 0x5d, 0xda, 0x77, 0xd7, 0x8e, 0xbf, 0xea, 0xb7, 0x3a, 0x3e, 0x8a, 0xc7, 0xac, 0x43, 0xa1, 0x5c, 0xc9, 0xf7, 0xed,
+ 0xc7, 0xf6, 0x81, 0xfd, 0xd2, 0x7e, 0x64, 0xdf, 0xb7, 0xdf, 0xd8, 0x97, 0x27, 0xc6, 0x66, 0xa1, 0xdf, 0xbd, 0xbc, 0xdf,
+ 0xca, 0xca, 0x20, 0xef, 0x54, 0x6e, 0x1e, 0xa1, 0x33, 0xde, 0x29, 0xce, 0x96, 0x78, 0xc4, 0x6d, 0x2c, 0xbd, 0x32, 0x7e,
+ 0x62, 0xbf, 0xb5, 0x3f, 0xd9, 0x07, 0xf6, 0x3b, 0xfb, 0xa3, 0xfd, 0xc5, 0xde, 0x73, 0x4c, 0xba, 0x68, 0xcd, 0xbc, 0x59,
+ 0xbf, 0xce, 0xe4, 0xef, 0x2a, 0xd9, 0xae, 0x51, 0xd6, 0x3b, 0x59, 0xa2, 0xbd, 0x34, 0x8a, 0xc7, 0xb5, 0xfc, 0x96, 0x99,
+ 0xac, 0x7b, 0x8f, 0xed, 0x79, 0xc1, 0x96, 0x58, 0xce, 0x59, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
+ 0xc5, 0xfe, 0xf1, 0xdd, 0x9a, 0x65, 0x53, 0x76, 0x89, 0xb1, 0x15, 0x14, 0x71, 0x5a, 0x8a, 0xcc, 0x61, 0x51, 0x37, 0xd4,
+ 0xda, 0x2a, 0xa1, 0x91, 0xce, 0x1c, 0x1f, 0xf9, 0x3b, 0xfa, 0x78, 0x9e, 0x15, 0x35, 0xe3, 0x23, 0x45, 0x3f, 0x75, 0x6d,
+ 0x6e, 0xe5, 0x9e, 0x88, 0x85, 0xa2, 0x6b, 0x89, 0x99, 0x70, 0x34, 0x9a, 0xf0, 0x04, 0x9a, 0x3c, 0xcb, 0x5e, 0x76, 0x1e,
+ 0x4d, 0x66, 0xc4, 0x79, 0x92, 0xce, 0x8d, 0x3a, 0xfe, 0x9e, 0x8c, 0xf2, 0x93, 0xcc, 0xeb, 0xb3, 0x7e, 0x96, 0x3d, 0x1f,
+ 0xef, 0xa1, 0xbe, 0x99, 0x5b, 0x85, 0xcd, 0x9c, 0xb6, 0xb6, 0xe9, 0x13, 0xf3, 0x51, 0xfc, 0xb7, 0x7b, 0x12, 0x63, 0x0b,
+ 0xc5, 0xe4, 0x0e, 0xfe, 0xba, 0xa3, 0xa5, 0xb3, 0xed, 0xf8, 0x6d, 0xca, 0x9e, 0xf1, 0x73, 0x69, 0x69, 0x83, 0x23, 0xba,
+ 0x62, 0x54, 0x2c, 0x9b, 0x34, 0x99, 0x7c, 0x2b, 0xa6, 0x3a, 0xee, 0x83, 0x97, 0x91, 0xa8, 0x9d, 0x1a, 0xff, 0xb1, 0x85,
+ 0x12, 0x89, 0x7f, 0x77, 0x33, 0x24, 0x68, 0xbb, 0x64, 0x94, 0x11, 0x47, 0xbb, 0x58, 0x65, 0xea, 0xe9, 0x9b, 0xd3, 0xe2,
+ 0xdf, 0xe5, 0x4d, 0xee, 0x7d, 0x7b, 0xf3, 0x10, 0xcf, 0xff, 0xb2, 0x66, 0x71, 0x6c, 0x8f, 0xff, 0xd8, 0x42, 0x31, 0x51,
+ 0x03, 0x6f, 0xce, 0xc4, 0x8a, 0x65, 0x77, 0xf2, 0x57, 0xba, 0xce, 0xec, 0x74, 0x56, 0x8e, 0xbb, 0x99, 0x8c, 0x59, 0x9e,
+ 0x65, 0xb3, 0x6c, 0xcc, 0x01, 0x66, 0x03, 0x5b, 0x63, 0x7b, 0xfc, 0xc7, 0x16, 0x4a, 0xc4, 0x69, 0x19, 0x9b, 0x38, 0x25,
+ 0xb8, 0xab, 0xee, 0xf9, 0x45, 0x3a, 0x8f, 0xd0, 0x4c, 0x25, 0xc8, 0xb3, 0x5a, 0xbc, 0x79, 0x28, 0x1b, 0x23, 0xe7, 0xe7,
+ 0xd0, 0x89, 0xc4, 0x7f, 0x9f, 0x85, 0x12, 0x33, 0x08, 0xe2, 0xfe, 0xe6, 0xd8, 0x22, 0xea, 0x77, 0xcf, 0x71, 0x19, 0x7f,
+ 0x66, 0x74, 0xb9, 0x36, 0xb6, 0x1a, 0x13, 0xfe, 0x2b, 0x23, 0xf3, 0x7c, 0x96, 0x85, 0x32, 0x6b, 0xce, 0x94, 0x09, 0xbf,
+ 0xe4, 0xdc, 0xec, 0x87, 0xf1, 0x96, 0x3e, 0x88, 0x1d, 0xf9, 0x46, 0xb6, 0x3e, 0xe9, 0xe2, 0xbf, 0x1d, 0xdf, 0xbb, 0x65,
+ 0x64, 0xf5, 0x61, 0xd2, 0xec, 0xb7, 0xc8, 0x1e, 0x37, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19,
+ 0x2e, 0x4b, 0xb0, 0x86, 0x95, 0x6e, 0xd3, 0x47, 0x6b, 0x28, 0x6b, 0x8e, 0xe7, 0xdd, 0xdc, 0xdf, 0xef, 0x29, 0xee, 0x3e,
+ 0x5d, 0x5e, 0x9f, 0xbd, 0x4f, 0x80, 0xf3, 0x0c, 0x17, 0xcf, 0x7d, 0xa8, 0xa1, 0x77, 0xa9, 0xce, 0x3b, 0x3c, 0x89, 0x3d,
+ 0xaf, 0xb8, 0x77, 0x73, 0x7f, 0xbf, 0x47, 0x19, 0x1c, 0x55, 0x7a, 0x1f, 0x33, 0x7d, 0x1e, 0xad, 0x80, 0x2c, 0xc3, 0xc5,
+ 0xf3, 0xce, 0x62, 0xef, 0xd2, 0x44, 0x8b, 0xbe, 0xbe, 0xfe, 0x7c, 0xbf, 0x39, 0x19, 0x84, 0xee, 0xed, 0xf7, 0xe8, 0x6a,
+ 0x54, 0xca, 0xfb, 0xa8, 0x72, 0x05, 0xdc, 0x72, 0x5a, 0xd5, 0xe0, 0xd3, 0xff, 0x1c, 0x8f, 0x25, 0x9a, 0xd3, 0x4c, 0x1d,
+ 0xbf, 0x39, 0x6f, 0x3a, 0x5b, 0x51, 0x2c, 0xe7, 0xd0, 0xfd, 0xfd, 0x9e, 0xee, 0xe6, 0x9b, 0x3a, 0x7e, 0xaf, 0x60, 0x94,
+ 0x8f, 0xa7, 0x4f, 0x54, 0x64, 0x5c, 0xcf, 0x77, 0x64, 0xc2, 0xff, 0x88, 0x1d, 0x5f, 0x64, 0x46, 0x27, 0x73, 0x76, 0xc3,
+ 0xaf, 0xb0, 0x57, 0x1f, 0x8b, 0xcc, 0xcd, 0x72, 0xb0, 0x13, 0xe2, 0x5f, 0x9c, 0x7a, 0x68, 0x79, 0x2d, 0xcb, 0xa0, 0xee,
+ 0x5a, 0xd6, 0xf1, 0xeb, 0xee, 0xd5, 0x47, 0xe3, 0x6f, 0x27, 0xc5, 0xdf, 0x77, 0xdf, 0xb2, 0x5a, 0x88, 0x7f, 0x34, 0xfe,
+ 0xfd, 0xa4, 0xe7, 0xbf, 0x76, 0xdf, 0x32, 0x5b, 0xce, 0x88, 0xbf, 0xb9, 0x35, 0xf5, 0x1e, 0x2d, 0xfe, 0xe5, 0x14, 0x57,
+ 0x20, 0xbb, 0x8a, 0xa7, 0x9f, 0x4d, 0xee, 0xc8, 0xf8, 0xcf, 0x59, 0x1c, 0xe5, 0xce, 0x2d, 0x71, 0x5b, 0x25, 0xf3, 0x5d,
+ 0xf2, 0xab, 0x78, 0xfa, 0x2d, 0xc7, 0x1d, 0xdf, 0xf3, 0x1d, 0x07, 0xbb, 0x63, 0x4b, 0xdc, 0xcb, 0xcb, 0x7c, 0x17, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2d, 0xfe, 0x4f, 0xd4, 0xe5, 0x99, 0x31, 0x53, 0xaa, 0xeb, 0xe7, 0x5c, 0x35,
+ 0xc7, 0x8e, 0x97, 0x4f, 0x48, 0xb7, 0xdc, 0xdb, 0xa9, 0xaa, 0xa1, 0xe8, 0xc7, 0x5d, 0x1e, 0xed, 0x99, 0xd8, 0xc4, 0x0e,
+ 0xb8, 0xef, 0x06, 0xb5, 0x09, 0x07, 0xa7, 0x3a, 0x0e, 0x4e, 0x0b, 0xe5, 0xd8, 0xe8, 0x4e, 0x3e, 0x21, 0x73, 0x72, 0x17,
+ 0x64, 0x8e, 0x48, 0xf7, 0xbb, 0x89, 0x55, 0xd1, 0xc2, 0x9f, 0x33, 0x3e, 0x85, 0xf2, 0xe5, 0x68, 0xcf, 0x64, 0x76, 0x07,
+ 0x7c, 0xce, 0xc1, 0x69, 0x21, 0x07, 0xc7, 0xab, 0x22, 0x55, 0x07, 0x55, 0xba, 0xf4, 0x6e, 0x4b, 0xae, 0x53, 0x15, 0xeb,
+ 0xb7, 0x9e, 0x81, 0x8c, 0xfc, 0x6f, 0xd9, 0x3b, 0x60, 0x45, 0x98, 0x6e, 0x33, 0x4f, 0xd8, 0x99, 0x16, 0x9d, 0xff, 0xc1,
+ 0xab, 0xde, 0x37, 0x53, 0xc9, 0x28, 0xb7, 0xdf, 0x5e, 0x85, 0xbe, 0x12, 0xca, 0x64, 0x75, 0xdf, 0x6f, 0x38, 0x77, 0x51,
+ 0x39, 0x27, 0xb7, 0x22, 0x90, 0x6e, 0x29, 0x32, 0x27, 0x4a, 0x71, 0x6b, 0x52, 0xf5, 0x70, 0x7d, 0x9c, 0x6c, 0x77, 0xa8,
+ 0x38, 0x96, 0x60, 0xd9, 0x91, 0xfb, 0x69, 0xdf, 0xbd, 0xdc, 0x27, 0x72, 0xec, 0xf4, 0x89, 0xb8, 0x64, 0xb5, 0xd8, 0x54,
+ 0x7d, 0xa9, 0x71, 0x7e, 0x94, 0xe3, 0xb3, 0x06, 0x75, 0xc7, 0xb7, 0xb9, 0x47, 0xfc, 0xc7, 0xf3, 0x15, 0x7f, 0x32, 0x9c,
+ 0x73, 0x1f, 0x45, 0x57, 0xe0, 0x5c, 0x8e, 0x8d, 0x6c, 0xa7, 0xb2, 0x0c, 0xec, 0x8d, 0xb3, 0xe3, 0x5f, 0x06, 0xe7, 0xe8,
+ 0xac, 0x5d, 0x76, 0x57, 0x07, 0x23, 0xfe, 0xbc, 0xde, 0x93, 0x69, 0x26, 0xaf, 0xc5, 0xaf, 0xd0, 0xb7, 0x37, 0xfe, 0x67,
+ 0xd8, 0x2c, 0x57, 0x30, 0x50, 0x72, 0x33, 0x03, 0x9d, 0x37, 0xa2, 0xe8, 0x4a, 0xb3, 0x8b, 0xf6, 0xf5, 0xd3, 0x95, 0x19,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xd1, 0xf3, 0xff, 0xd4, 0x70, 0xcb, 0x95, 0xb3, 0xec, 0xe4, 0xe5,
+ 0x1f, 0xca, 0x76, 0x78, 0xe6, 0x5c, 0xaa, 0xb9, 0x4c, 0x3f, 0xca, 0x47, 0xa9, 0x81, 0xfc, 0x2b, 0x37, 0xeb, 0x44, 0x55,
+ 0xaa, 0xaa, 0x27, 0xf8, 0x30, 0x33, 0x86, 0x8f, 0x3a, 0xea, 0xed, 0xfc, 0x9c, 0xe3, 0xf0, 0xe8, 0xab, 0xd9, 0xc0, 0xd9,
+ 0xc9, 0xc9, 0xef, 0xde, 0x9c, 0xb9, 0x99, 0x59, 0x31, 0xed, 0x92, 0x86, 0xcf, 0x8c, 0x5b, 0x91, 0xeb, 0xf0, 0xe8, 0x19,
+ 0x6d, 0xd2, 0x2f, 0xf0, 0xab, 0x2f, 0x66, 0x7d, 0x5a, 0x1d, 0xdd, 0x91, 0x6a, 0x61, 0x8b, 0xa2, 0xdc, 0xdd, 0x94, 0xe9,
+ 0xae, 0xc3, 0xd3, 0x43, 0x11, 0x9b, 0x69, 0x19, 0xed, 0xa5, 0x96, 0x44, 0x97, 0x2e, 0x6b, 0xb7, 0xd2, 0x82, 0x4f, 0xcc,
+ 0x6b, 0x67, 0xd9, 0x29, 0x4e, 0xf6, 0x93, 0x47, 0xac, 0xfc, 0x72, 0xaf, 0xf8, 0x3f, 0xe6, 0x8c, 0xf9, 0x39, 0x29, 0x1e,
+ 0x2d, 0xca, 0x36, 0xe9, 0xab, 0xe4, 0xc4, 0xff, 0xda, 0xf3, 0x92, 0x97, 0x65, 0xe3, 0x9c, 0x9e, 0xcd, 0x19, 0x61, 0x99,
+ 0xfb, 0xd5, 0xd1, 0xf8, 0x97, 0xe4, 0xd1, 0x9f, 0x61, 0xf8, 0xcc, 0x64, 0xd9, 0x38, 0xcb, 0x3d, 0x9a, 0xb5, 0x2c, 0x8e,
+ 0xbe, 0xff, 0x33, 0xef, 0x98, 0x7b, 0x1b, 0x3e, 0x57, 0x76, 0x78, 0xe2, 0x2e, 0x9d, 0xf6, 0xd5, 0xe1, 0xd1, 0xd0, 0xb1,
+ 0x7c, 0x3d, 0x95, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe6, 0xb9, 0xfd, 0x61, 0x1e, 0x88, 0x3f, 0xbc, 0xda, 0xf8, 0xff, 0x17 };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle bluishFontRecs[189] = {
+ { 4, 4, 5 , 10 },
+ { 17, 4, 2 , 8 },
+ { 27, 4, 4 , 3 },
+ { 39, 4, 6 , 8 },
+ { 53, 4, 5 , 10 },
+ { 66, 4, 6 , 8 },
+ { 80, 4, 5 , 10 },
+ { 93, 4, 2 , 3 },
+ { 103, 4, 3 , 8 },
+ { 114, 4, 3 , 8 },
+ { 125, 4, 6 , 6 },
+ { 139, 4, 6 , 6 },
+ { 153, 4, 2 , 3 },
+ { 163, 4, 5 , 2 },
+ { 176, 4, 2 , 2 },
+ { 186, 4, 6 , 8 },
+ { 200, 4, 5 , 8 },
+ { 213, 4, 3 , 8 },
+ { 224, 4, 5 , 8 },
+ { 237, 4, 5 , 8 },
+ { 4, 22, 5 , 8 },
+ { 17, 22, 5 , 8 },
+ { 30, 22, 5 , 8 },
+ { 43, 22, 5 , 8 },
+ { 56, 22, 5 , 8 },
+ { 69, 22, 5 , 8 },
+ { 82, 22, 2 , 8 },
+ { 92, 22, 2 , 9 },
+ { 102, 22, 4 , 6 },
+ { 114, 22, 5 , 4 },
+ { 127, 22, 4 , 6 },
+ { 139, 22, 5 , 8 },
+ { 152, 22, 6 , 8 },
+ { 166, 22, 5 , 8 },
+ { 179, 22, 5 , 8 },
+ { 192, 22, 5 , 8 },
+ { 205, 22, 5 , 8 },
+ { 218, 22, 5 , 8 },
+ { 231, 22, 5 , 8 },
+ { 4, 40, 5 , 8 },
+ { 17, 40, 5 , 8 },
+ { 30, 40, 4 , 8 },
+ { 42, 40, 5 , 8 },
+ { 55, 40, 5 , 8 },
+ { 68, 40, 5 , 8 },
+ { 81, 40, 8 , 8 },
+ { 97, 40, 5 , 8 },
+ { 110, 40, 5 , 8 },
+ { 123, 40, 5 , 8 },
+ { 136, 40, 5 , 9 },
+ { 149, 40, 5 , 8 },
+ { 162, 40, 5 , 8 },
+ { 175, 40, 6 , 8 },
+ { 189, 40, 5 , 8 },
+ { 202, 40, 5 , 8 },
+ { 215, 40, 8 , 8 },
+ { 231, 40, 5 , 8 },
+ { 4, 58, 5 , 8 },
+ { 17, 58, 5 , 8 },
+ { 30, 58, 3 , 8 },
+ { 41, 58, 6 , 8 },
+ { 55, 58, 3 , 8 },
+ { 66, 58, 6 , 4 },
+ { 80, 58, 5 , 1 },
+ { 93, 58, 2 , 3 },
+ { 103, 58, 5 , 6 },
+ { 116, 58, 5 , 8 },
+ { 129, 58, 5 , 6 },
+ { 142, 58, 5 , 8 },
+ { 155, 58, 5 , 6 },
+ { 168, 58, 5 , 8 },
+ { 181, 58, 5 , 7 },
+ { 194, 58, 5 , 8 },
+ { 207, 58, 2 , 8 },
+ { 217, 58, 3 , 9 },
+ { 228, 58, 5 , 8 },
+ { 241, 58, 2 , 8 },
+ { 4, 76, 8 , 6 },
+ { 20, 76, 5 , 6 },
+ { 33, 76, 5 , 6 },
+ { 46, 76, 5 , 7 },
+ { 59, 76, 5 , 7 },
+ { 72, 76, 5 , 6 },
+ { 85, 76, 5 , 6 },
+ { 98, 76, 5 , 8 },
+ { 111, 76, 5 , 6 },
+ { 124, 76, 5 , 6 },
+ { 137, 76, 8 , 6 },
+ { 153, 76, 5 , 6 },
+ { 166, 76, 5 , 7 },
+ { 179, 76, 5 , 6 },
+ { 192, 76, 4 , 8 },
+ { 204, 76, 2 , 10 },
+ { 214, 76, 4 , 8 },
+ { 226, 76, 6 , 4 },
+ { 240, 76, 2 , 8 },
+ { 4, 94, 5 , 8 },
+ { 17, 94, 5 , 8 },
+ { 30, 94, 8 , 8 },
+ { 46, 94, 6 , 8 },
+ { 60, 94, 5 , 10 },
+ { 73, 94, 5 , 10 },
+ { 86, 94, 5 , 9 },
+ { 99, 94, 7 , 8 },
+ { 114, 94, 4 , 6 },
+ { 126, 94, 5 , 4 },
+ { 139, 94, 5 , 3 },
+ { 152, 94, 7 , 8 },
+ { 167, 94, 5 , 2 },
+ { 180, 94, 4 , 4 },
+ { 192, 94, 6 , 8 },
+ { 206, 94, 4 , 6 },
+ { 218, 94, 4 , 6 },
+ { 230, 94, 8 , 8 },
+ { 4, 112, 5 , 9 },
+ { 17, 112, 6 , 8 },
+ { 31, 112, 2 , 2 },
+ { 41, 112, 8 , 8 },
+ { 57, 112, 3 , 6 },
+ { 68, 112, 4 , 6 },
+ { 80, 112, 5 , 4 },
+ { 93, 112, 6 , 8 },
+ { 107, 112, 6 , 6 },
+ { 121, 112, 5 , 10 },
+ { 134, 112, 5 , 8 },
+ { 147, 112, 5 , 10 },
+ { 160, 112, 5 , 10 },
+ { 173, 112, 5 , 10 },
+ { 186, 112, 5 , 10 },
+ { 199, 112, 5 , 10 },
+ { 212, 112, 5 , 10 },
+ { 225, 112, 6 , 8 },
+ { 239, 112, 5 , 9 },
+ { 4, 130, 5 , 10 },
+ { 17, 130, 5 , 10 },
+ { 30, 130, 5 , 10 },
+ { 43, 130, 5 , 10 },
+ { 56, 130, 4 , 10 },
+ { 68, 130, 4 , 10 },
+ { 80, 130, 4 , 10 },
+ { 92, 130, 4 , 10 },
+ { 104, 130, 6 , 8 },
+ { 118, 130, 5 , 10 },
+ { 131, 130, 5 , 10 },
+ { 144, 130, 5 , 10 },
+ { 157, 130, 5 , 10 },
+ { 170, 130, 5 , 10 },
+ { 183, 130, 5 , 10 },
+ { 196, 130, 4 , 4 },
+ { 208, 130, 5 , 10 },
+ { 221, 130, 5 , 10 },
+ { 234, 130, 5 , 10 },
+ { 4, 148, 5 , 10 },
+ { 17, 148, 5 , 10 },
+ { 30, 148, 5 , 10 },
+ { 43, 148, 5 , 8 },
+ { 56, 148, 5 , 8 },
+ { 69, 148, 5 , 9 },
+ { 82, 148, 5 , 9 },
+ { 95, 148, 5 , 9 },
+ { 108, 148, 5 , 9 },
+ { 121, 148, 5 , 8 },
+ { 134, 148, 5 , 10 },
+ { 147, 148, 6 , 6 },
+ { 161, 148, 5 , 7 },
+ { 174, 148, 5 , 9 },
+ { 187, 148, 5 , 9 },
+ { 200, 148, 5 , 9 },
+ { 213, 148, 5 , 8 },
+ { 226, 148, 3 , 9 },
+ { 237, 148, 3 , 9 },
+ { 4, 166, 4 , 9 },
+ { 16, 166, 4 , 8 },
+ { 28, 166, 5 , 9 },
+ { 41, 166, 5 , 9 },
+ { 54, 166, 5 , 9 },
+ { 67, 166, 5 , 9 },
+ { 80, 166, 5 , 9 },
+ { 93, 166, 5 , 9 },
+ { 106, 166, 5 , 8 },
+ { 119, 166, 4 , 6 },
+ { 131, 166, 5 , 8 },
+ { 144, 166, 5 , 9 },
+ { 157, 166, 5 , 9 },
+ { 170, 166, 5 , 9 },
+ { 183, 166, 5 , 8 },
+ { 196, 166, 5 , 10 },
+ { 209, 166, 5 , 10 },
+ { 222, 166, 5 , 9 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo bluishFontGlyphs[189] = {
+ { 32, 0, 9, 5, { 0 }},
+ { 33, 0, 1, 2, { 0 }},
+ { 34, 0, 1, 4, { 0 }},
+ { 35, 0, 1, 6, { 0 }},
+ { 36, 0, 0, 5, { 0 }},
+ { 37, 0, 1, 6, { 0 }},
+ { 38, 0, 0, 5, { 0 }},
+ { 39, 0, 1, 2, { 0 }},
+ { 40, 0, 1, 3, { 0 }},
+ { 41, 0, 1, 3, { 0 }},
+ { 42, 0, 1, 6, { 0 }},
+ { 43, 0, 2, 6, { 0 }},
+ { 44, 0, 7, 2, { 0 }},
+ { 45, 0, 4, 5, { 0 }},
+ { 46, 0, 7, 2, { 0 }},
+ { 47, 0, 1, 6, { 0 }},
+ { 48, 0, 1, 5, { 0 }},
+ { 49, 0, 1, 3, { 0 }},
+ { 50, 0, 1, 5, { 0 }},
+ { 51, 0, 1, 5, { 0 }},
+ { 52, 0, 1, 5, { 0 }},
+ { 53, 0, 1, 5, { 0 }},
+ { 54, 0, 1, 5, { 0 }},
+ { 55, 0, 1, 5, { 0 }},
+ { 56, 0, 1, 5, { 0 }},
+ { 57, 0, 1, 5, { 0 }},
+ { 58, 0, 1, 2, { 0 }},
+ { 59, 0, 1, 2, { 0 }},
+ { 60, 0, 2, 4, { 0 }},
+ { 61, 0, 3, 5, { 0 }},
+ { 62, 0, 2, 4, { 0 }},
+ { 63, 0, 1, 5, { 0 }},
+ { 64, 0, 1, 6, { 0 }},
+ { 65, 0, 1, 5, { 0 }},
+ { 66, 0, 1, 5, { 0 }},
+ { 67, 0, 1, 5, { 0 }},
+ { 68, 0, 1, 5, { 0 }},
+ { 69, 0, 1, 5, { 0 }},
+ { 70, 0, 1, 5, { 0 }},
+ { 71, 0, 1, 5, { 0 }},
+ { 72, 0, 1, 5, { 0 }},
+ { 73, 0, 1, 4, { 0 }},
+ { 74, 0, 1, 5, { 0 }},
+ { 75, 0, 1, 5, { 0 }},
+ { 76, 0, 1, 5, { 0 }},
+ { 77, 0, 1, 8, { 0 }},
+ { 78, 0, 1, 5, { 0 }},
+ { 79, 0, 1, 5, { 0 }},
+ { 80, 0, 1, 5, { 0 }},
+ { 81, 0, 1, 5, { 0 }},
+ { 82, 0, 1, 5, { 0 }},
+ { 83, 0, 1, 5, { 0 }},
+ { 84, 0, 1, 6, { 0 }},
+ { 85, 0, 1, 5, { 0 }},
+ { 86, 0, 1, 5, { 0 }},
+ { 87, 0, 1, 8, { 0 }},
+ { 88, 0, 1, 5, { 0 }},
+ { 89, 0, 1, 5, { 0 }},
+ { 90, 0, 1, 5, { 0 }},
+ { 91, 0, 1, 3, { 0 }},
+ { 92, 0, 1, 6, { 0 }},
+ { 93, 0, 1, 3, { 0 }},
+ { 94, 0, 1, 6, { 0 }},
+ { 95, 0, 9, 5, { 0 }},
+ { 96, 0, 1, 2, { 0 }},
+ { 97, 0, 3, 5, { 0 }},
+ { 98, 0, 1, 5, { 0 }},
+ { 99, 0, 3, 5, { 0 }},
+ { 100, 0, 1, 5, { 0 }},
+ { 101, 0, 3, 5, { 0 }},
+ { 102, 0, 1, 5, { 0 }},
+ { 103, 0, 3, 5, { 0 }},
+ { 104, 0, 1, 5, { 0 }},
+ { 105, 0, 1, 2, { 0 }},
+ { 106, 0, 1, 3, { 0 }},
+ { 107, 0, 1, 5, { 0 }},
+ { 108, 0, 1, 2, { 0 }},
+ { 109, 0, 3, 8, { 0 }},
+ { 110, 0, 3, 5, { 0 }},
+ { 111, 0, 3, 5, { 0 }},
+ { 112, 0, 3, 5, { 0 }},
+ { 113, 0, 3, 5, { 0 }},
+ { 114, 0, 3, 5, { 0 }},
+ { 115, 0, 3, 5, { 0 }},
+ { 116, 0, 1, 5, { 0 }},
+ { 117, 0, 3, 5, { 0 }},
+ { 118, 0, 3, 5, { 0 }},
+ { 119, 0, 3, 8, { 0 }},
+ { 120, 0, 3, 5, { 0 }},
+ { 121, 0, 3, 5, { 0 }},
+ { 122, 0, 3, 5, { 0 }},
+ { 123, 0, 1, 4, { 0 }},
+ { 124, 0, 0, 2, { 0 }},
+ { 125, 0, 1, 4, { 0 }},
+ { 126, 0, 3, 6, { 0 }},
+ { 161, 0, 1, 2, { 0 }},
+ { 162, 0, 2, 5, { 0 }},
+ { 163, 0, 1, 5, { 0 }},
+ { 8364, 0, 1, 7, { 0 }},
+ { 165, 0, 1, 6, { 0 }},
+ { 352, 0, -1, 5, { 0 }},
+ { 167, 0, 0, 5, { 0 }},
+ { 353, 0, 0, 5, { 0 }},
+ { 169, 0, 1, 7, { 0 }},
+ { 170, 0, -1, 4, { 0 }},
+ { 171, 0, 3, 5, { 0 }},
+ { 172, 0, 4, 5, { 0 }},
+ { 174, 0, 1, 7, { 0 }},
+ { 175, 0, -1, 5, { 0 }},
+ { 176, 0, -1, 4, { 0 }},
+ { 177, 0, 1, 6, { 0 }},
+ { 178, 0, -1, 4, { 0 }},
+ { 179, 0, -1, 4, { 0 }},
+ { 381, 0, 1, 7, { 0 }},
+ { 181, 0, 1, 5, { 0 }},
+ { 182, 0, 1, 6, { 0 }},
+ { 183, 0, 4, 2, { 0 }},
+ { 382, 0, 1, 7, { 0 }},
+ { 185, 0, -1, 3, { 0 }},
+ { 186, 0, -1, 4, { 0 }},
+ { 187, 0, 3, 5, { 0 }},
+ { 338, 0, 1, 6, { 0 }},
+ { 339, 0, 3, 6, { 0 }},
+ { 376, 0, -1, 5, { 0 }},
+ { 191, 0, 1, 5, { 0 }},
+ { 192, 0, -1, 5, { 0 }},
+ { 193, 0, -1, 5, { 0 }},
+ { 194, 0, -1, 5, { 0 }},
+ { 195, 0, -1, 5, { 0 }},
+ { 196, 0, -1, 5, { 0 }},
+ { 197, 0, -1, 5, { 0 }},
+ { 198, 0, 1, 6, { 0 }},
+ { 199, 0, 1, 5, { 0 }},
+ { 200, 0, -1, 5, { 0 }},
+ { 201, 0, -1, 5, { 0 }},
+ { 202, 0, -1, 5, { 0 }},
+ { 203, 0, -1, 5, { 0 }},
+ { 204, 0, -1, 4, { 0 }},
+ { 205, 0, -1, 4, { 0 }},
+ { 206, 0, -1, 4, { 0 }},
+ { 207, 0, -1, 4, { 0 }},
+ { 208, 0, 1, 6, { 0 }},
+ { 209, 0, -1, 5, { 0 }},
+ { 210, 0, -1, 5, { 0 }},
+ { 211, 0, -1, 5, { 0 }},
+ { 212, 0, -1, 5, { 0 }},
+ { 213, 0, -1, 5, { 0 }},
+ { 214, 0, -1, 5, { 0 }},
+ { 215, 0, 3, 4, { 0 }},
+ { 216, 0, 0, 5, { 0 }},
+ { 217, 0, -1, 5, { 0 }},
+ { 218, 0, -1, 5, { 0 }},
+ { 219, 0, -1, 5, { 0 }},
+ { 220, 0, -1, 5, { 0 }},
+ { 221, 0, -1, 5, { 0 }},
+ { 222, 0, 1, 5, { 0 }},
+ { 223, 0, 1, 5, { 0 }},
+ { 224, 0, 0, 5, { 0 }},
+ { 225, 0, 0, 5, { 0 }},
+ { 226, 0, 0, 5, { 0 }},
+ { 227, 0, 0, 5, { 0 }},
+ { 228, 0, 1, 5, { 0 }},
+ { 229, 0, -1, 5, { 0 }},
+ { 230, 0, 3, 6, { 0 }},
+ { 231, 0, 3, 5, { 0 }},
+ { 232, 0, 0, 5, { 0 }},
+ { 233, 0, 0, 5, { 0 }},
+ { 234, 0, 0, 5, { 0 }},
+ { 235, 0, 1, 5, { 0 }},
+ { 236, 0, 0, 3, { 0 }},
+ { 237, 0, 0, 2, { 0 }},
+ { 238, 0, 0, 3, { 0 }},
+ { 239, 0, 1, 3, { 0 }},
+ { 240, 0, 0, 5, { 0 }},
+ { 241, 0, 0, 5, { 0 }},
+ { 242, 0, 0, 5, { 0 }},
+ { 243, 0, 0, 5, { 0 }},
+ { 244, 0, 0, 5, { 0 }},
+ { 245, 0, 0, 5, { 0 }},
+ { 246, 0, 1, 5, { 0 }},
+ { 247, 0, 2, 4, { 0 }},
+ { 248, 0, 2, 5, { 0 }},
+ { 249, 0, 0, 5, { 0 }},
+ { 250, 0, 0, 5, { 0 }},
+ { 251, 0, 0, 5, { 0 }},
+ { 252, 0, 1, 5, { 0 }},
+ { 253, 0, 0, 5, { 0 }},
+ { 254, 0, 0, 5, { 0 }},
+ { 255, 0, 1, 5, { 0 }},
+};
+
+// Style loading function: Bluish
+static void GuiLoadStyleBluish(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < BLUISH_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(bluishStyleProps[i].controlId, bluishStyleProps[i].propertyId, bluishStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int bluishFontDataSize = 0;
+ unsigned char *data = DecompressData(bluishFontData, BLUISH_STYLE_FONT_ATLAS_COMP_SIZE, &bluishFontDataSize);
+ Image imFont = { data, 256, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 10;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, bluishFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, bluishFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 254, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_candy.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_candy.h
new file mode 100644
index 0000000000..39c818c67c
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_candy.h
@@ -0,0 +1,589 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleCandy(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define CANDY_STYLE_PROPS_COUNT 17
+
+// Custom style name: Candy
+static const GuiStyleProp candyStyleProps[CANDY_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0xe58b68ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0xfeda96ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0xe59b5fff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0xee813fff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0xfcd85bff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0xfc6955ff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0xb34848ff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0xeb7272ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0xbd4a4aff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x94795dff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0xc2a37aff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x9c8369ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x0000000f }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0xd77575ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0xfff5e1ff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000016 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "v5easter.ttf" (size: 15, spacing: 0)
+
+#define CANDY_STYLE_FONT_ATLAS_COMP_SIZE 2260
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char candyFontData[CANDY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0x4d, 0x92, 0xd4, 0x38, 0x10, 0x06, 0x50, 0xdd, 0x80, 0xfb, 0xcc, 0x61, 0xe6, 0x4a, 0x73, 0x45, 0x8e, 0xc0, 0x86,
+ 0x25, 0xa1, 0x89, 0x61, 0x88, 0x20, 0x80, 0x2e, 0x4b, 0x4a, 0xa5, 0x6c, 0xd9, 0xf5, 0x78, 0x1b, 0xa2, 0xdd, 0x5d, 0x55,
+ 0xfe, 0xf9, 0x2c, 0xc9, 0x2e, 0xa5, 0x6b, 0x01, 0x00, 0x00, 0x00, 0xde, 0xdc, 0x7f, 0xff, 0xfe, 0xfc, 0x59, 0xf9, 0xe0,
+ 0xa7, 0x3f, 0x7f, 0xb7, 0x7e, 0xb8, 0xf4, 0x68, 0x49, 0xfc, 0x2f, 0x8f, 0x3f, 0x49, 0xdf, 0x2b, 0x94, 0x83, 0x25, 0xed,
+ 0xcf, 0xfc, 0xfb, 0xcf, 0x6a, 0xca, 0xbb, 0xbf, 0x7a, 0x9d, 0xd6, 0x27, 0x8a, 0x2c, 0x3b, 0x7a, 0xd5, 0x7a, 0xb0, 0x4e,
+ 0xa5, 0x63, 0x49, 0x0d, 0xad, 0x5d, 0x9d, 0xde, 0xab, 0x63, 0x7b, 0xa7, 0xbd, 0xfe, 0x65, 0x78, 0x1d, 0xcb, 0x82, 0x65,
+ 0x75, 0x72, 0x1f, 0xaf, 0xcc, 0xff, 0xef, 0xff, 0x32, 0xf3, 0x7f, 0xfc, 0x9a, 0x33, 0xc7, 0xc4, 0xcf, 0xb5, 0xa9, 0x09,
+ 0xf9, 0x1f, 0x3f, 0x8b, 0x1c, 0xaf, 0xc1, 0xeb, 0xa3, 0xb8, 0x0c, 0xff, 0x4d, 0xfb, 0xfc, 0x9a, 0xf9, 0xaa, 0x2b, 0x97,
+ 0xf5, 0xa5, 0x76, 0xfe, 0x38, 0x6f, 0x7d, 0x9a, 0xb9, 0x7d, 0x78, 0xe6, 0xb2, 0xdc, 0xfc, 0xb7, 0x7e, 0x37, 0x7a, 0x66,
+ 0x8f, 0xf7, 0x0e, 0x7a, 0x5b, 0xf3, 0x3a, 0x74, 0xec, 0xb7, 0x5b, 0xb1, 0x9c, 0x2d, 0x3c, 0xba, 0xc6, 0xc7, 0xe7, 0x92,
+ 0xd6, 0xd2, 0xf9, 0x36, 0x77, 0xe4, 0xd8, 0xb8, 0xe2, 0x28, 0x6e, 0xef, 0xcd, 0x8c, 0x76, 0xa9, 0xfe, 0xb2, 0xb5, 0xe5,
+ 0xbf, 0xf7, 0xa8, 0xad, 0x8b, 0x5b, 0xda, 0x32, 0xdc, 0xd2, 0xc6, 0xfa, 0x2c, 0x79, 0x5b, 0x38, 0x2b, 0xff, 0x75, 0x22,
+ 0xfd, 0x25, 0xd0, 0xe3, 0x3c, 0x3e, 0x6b, 0xb7, 0x3e, 0x7f, 0xf4, 0x28, 0xc9, 0x3d, 0x66, 0x67, 0xf3, 0x7f, 0xdc, 0x1f,
+ 0x2e, 0x87, 0xe7, 0x9b, 0xf3, 0x7a, 0x5c, 0x3b, 0xe5, 0x3f, 0xda, 0x43, 0xee, 0x1f, 0xdd, 0xe4, 0xb5, 0xff, 0xeb, 0xf3,
+ 0xdf, 0x4a, 0x64, 0x1d, 0x1c, 0xa9, 0xe6, 0xb6, 0xc6, 0x3d, 0xe3, 0xe9, 0xe8, 0x19, 0x7d, 0x7c, 0x8c, 0x7b, 0x7e, 0xff,
+ 0xbf, 0x3d, 0x6e, 0xac, 0xcb, 0x46, 0x4e, 0xf9, 0x09, 0xdb, 0xb7, 0xff, 0xdf, 0xd7, 0x2f, 0x58, 0xd3, 0xff, 0x6f, 0x8d,
+ 0xff, 0xcb, 0xe9, 0xad, 0x7f, 0x2b, 0x59, 0xf1, 0xbd, 0x5f, 0x43, 0x3d, 0xa0, 0xb9, 0xab, 0x0a, 0xb1, 0xfd, 0x39, 0x97,
+ 0xff, 0x15, 0x7d, 0x80, 0xd1, 0xd1, 0xdf, 0x33, 0xfa, 0xff, 0x91, 0x2d, 0x18, 0xbd, 0xce, 0x9c, 0xb5, 0x66, 0xe3, 0xd7,
+ 0xf9, 0xaf, 0xdb, 0x62, 0x79, 0xe7, 0xf9, 0xd9, 0x2d, 0x98, 0xff, 0xaa, 0xb1, 0x5e, 0xf5, 0xe8, 0x51, 0x5c, 0x2f, 0xbd,
+ 0x37, 0x56, 0x6f, 0x71, 0xe5, 0xf4, 0x8c, 0xf6, 0xbf, 0x75, 0xfd, 0x7f, 0xe6, 0xea, 0xc0, 0xd8, 0x9d, 0x8d, 0xba, 0xe1,
+ 0xb1, 0x22, 0xff, 0x77, 0x69, 0xc5, 0xb2, 0x7a, 0xd5, 0xae, 0xff, 0x45, 0xee, 0x69, 0x67, 0xf4, 0xe7, 0xee, 0x92, 0xff,
+ 0xda, 0x71, 0x36, 0xed, 0x5f, 0x12, 0xbf, 0xe3, 0xbe, 0xea, 0x5b, 0x05, 0xad, 0xbb, 0x8d, 0xe7, 0xdd, 0xc5, 0xde, 0x31,
+ 0xff, 0xf7, 0xb8, 0xff, 0xbf, 0xc7, 0xb6, 0x5c, 0x3b, 0x92, 0xdb, 0x31, 0xff, 0xf0, 0x1e, 0xdf, 0x26, 0x3c, 0xef, 0x5b,
+ 0x8b, 0xf2, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdd, 0x67, 0xe7, 0xc4, 0x2b,
+ 0x44, 0x8e, 0xcd, 0xb9, 0xa9, 0x4b, 0xea, 0x22, 0xc5, 0xe6, 0x46, 0x9f, 0x5b, 0xc3, 0x39, 0x5a, 0x35, 0x7b, 0x6e, 0x5e,
+ 0xf8, 0xeb, 0x7a, 0x42, 0x33, 0xaf, 0x7b, 0x3c, 0x17, 0x79, 0x64, 0x5e, 0x76, 0xb4, 0xd6, 0xf9, 0x68, 0x4d, 0xa0, 0x48,
+ 0xed, 0xa4, 0xd9, 0xda, 0xe9, 0xe3, 0x6b, 0x1c, 0x99, 0xc1, 0x3a, 0x3b, 0xe7, 0xed, 0xac, 0x8a, 0xcd, 0xd1, 0x9c, 0xf6,
+ 0x55, 0xbd, 0xad, 0xc3, 0x95, 0xea, 0x76, 0xab, 0xd3, 0x90, 0x5d, 0x35, 0x63, 0x65, 0xfe, 0x4b, 0x57, 0x6d, 0xec, 0xbe,
+ 0xf9, 0xce, 0x35, 0x71, 0x46, 0xfb, 0x79, 0x35, 0xf7, 0xca, 0xf4, 0x3e, 0x19, 0x6d, 0xa9, 0x9e, 0x9f, 0xff, 0xe8, 0xba,
+ 0xb7, 0xb6, 0x6a, 0xdd, 0xb6, 0x8a, 0xfd, 0x95, 0xf9, 0x8f, 0xf6, 0xed, 0x8e, 0x5b, 0xbe, 0xf1, 0x8a, 0x07, 0xe7, 0x54,
+ 0xb4, 0xa9, 0x1b, 0xe5, 0x7f, 0xfc, 0xdd, 0x56, 0xce, 0x61, 0x9f, 0x6b, 0x7b, 0x6b, 0x5a, 0xfe, 0xe3, 0x7d, 0x9f, 0xdd,
+ 0xda, 0xf8, 0xdc, 0xaa, 0x39, 0xeb, 0xf2, 0x5f, 0xd2, 0xab, 0x32, 0xed, 0x99, 0xff, 0x9e, 0xf6, 0x21, 0x32, 0x36, 0x18,
+ 0xff, 0xcb, 0xe8, 0x19, 0x77, 0xf4, 0xdd, 0x22, 0xed, 0xff, 0xf1, 0x5a, 0xde, 0xb9, 0xfd, 0xdf, 0x25, 0xff, 0x65, 0xab,
+ 0xfe, 0xff, 0xec, 0xd1, 0x38, 0x96, 0xf3, 0xeb, 0x6a, 0xb3, 0xed, 0xfe, 0x24, 0xa3, 0x91, 0x2d, 0x3e, 0x5b, 0x1d, 0x39,
+ 0x7a, 0xdd, 0x21, 0xf3, 0x89, 0x4d, 0xf7, 0xba, 0xc6, 0x55, 0xde, 0x72, 0xfc, 0x1f, 0xbf, 0xee, 0x2b, 0xff, 0xb3, 0xfd,
+ 0xe9, 0x72, 0x41, 0xfe, 0x57, 0x6d, 0xbb, 0x3b, 0xe7, 0x7f, 0xa6, 0xe7, 0x77, 0x56, 0xfe, 0xcb, 0xcb, 0xa7, 0x50, 0xcd,
+ 0xe6, 0x3f, 0xfe, 0x6c, 0x9c, 0xd1, 0x9c, 0xd7, 0x0b, 0xef, 0x6f, 0xad, 0x38, 0x07, 0xc6, 0xef, 0x37, 0x14, 0xf9, 0xbf,
+ 0x55, 0xfe, 0xaf, 0x6f, 0xff, 0x7b, 0x9f, 0xad, 0xf8, 0xde, 0xf9, 0x2f, 0x53, 0xd7, 0xf8, 0x56, 0xfc, 0xdd, 0x6e, 0xfd,
+ 0xff, 0xec, 0x73, 0xe7, 0xb9, 0xe7, 0xd3, 0x75, 0x7d, 0xdc, 0xd8, 0xf5, 0xa4, 0xd8, 0xd3, 0x0c, 0x62, 0x55, 0xb3, 0xd7,
+ 0x1c, 0x53, 0x25, 0xfc, 0x0c, 0xaf, 0x32, 0x7c, 0x06, 0x90, 0xff, 0x5f, 0x97, 0xac, 0x7b, 0x3a, 0x32, 0xac, 0xce, 0xd3,
+ 0xbd, 0xf2, 0x3f, 0xf7, 0x4d, 0x83, 0xfc, 0xa7, 0x0d, 0xd6, 0x0b, 0xda, 0x7f, 0x58, 0x7b, 0x97, 0x3d, 0xef, 0xf7, 0xc9,
+ 0xe8, 0xd3, 0x03, 0xef, 0xdb, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x38, 0x57,
+ 0xe0, 0xf5, 0x2c, 0xcf, 0xe3, 0x2a, 0x18, 0x25, 0x58, 0x05, 0xbb, 0x74, 0x54, 0x4e, 0xae, 0xc1, 0xf7, 0x1b, 0x99, 0xa5,
+ 0xbc, 0x5b, 0x2d, 0x82, 0xd1, 0xfa, 0x88, 0x23, 0xb5, 0xb1, 0xcb, 0x70, 0x9d, 0xaf, 0x68, 0x15, 0x9b, 0x32, 0x59, 0x73,
+ 0x34, 0x3e, 0xff, 0x2e, 0x3a, 0x83, 0xfa, 0x68, 0x7f, 0x7e, 0xaa, 0xdf, 0xea, 0x97, 0xef, 0xbe, 0xd6, 0x7f, 0x86, 0xdf,
+ 0xb5, 0x76, 0xcd, 0xf7, 0x9b, 0xdd, 0x27, 0x3d, 0x5b, 0x28, 0x92, 0xff, 0x1d, 0xab, 0xee, 0x65, 0x55, 0xf9, 0xb8, 0x53,
+ 0xbd, 0xed, 0x91, 0x3a, 0xbc, 0xed, 0x7a, 0x1e, 0xf3, 0xf9, 0xef, 0xad, 0x29, 0x50, 0x27, 0xab, 0x7e, 0x8e, 0x9e, 0x2b,
+ 0x8e, 0xb7, 0xcb, 0xd1, 0xdc, 0xe4, 0xd7, 0xad, 0xdc, 0xa7, 0xfa, 0xf9, 0xc7, 0xff, 0xfe, 0xfe, 0x30, 0xff, 0x35, 0x3c,
+ 0x1b, 0xa7, 0xfd, 0x89, 0x32, 0xe7, 0x57, 0xbf, 0x47, 0xfe, 0xc7, 0xcf, 0x99, 0x77, 0xa8, 0xb7, 0x5d, 0x12, 0x7e, 0x9a,
+ 0x39, 0xf3, 0x3d, 0x5a, 0x53, 0x24, 0x9a, 0xff, 0x91, 0x34, 0xbd, 0x3e, 0xcb, 0x95, 0x8e, 0x0a, 0x6a, 0xa3, 0xf9, 0x6f,
+ 0xbd, 0x6b, 0x24, 0xff, 0x75, 0xb8, 0xf6, 0x4a, 0xff, 0xb6, 0x1c, 0x6b, 0x5d, 0xf6, 0xcc, 0x7f, 0xa4, 0xc7, 0x59, 0x4f,
+ 0xcc, 0xff, 0x5c, 0x8d, 0xaf, 0x72, 0x7a, 0xfe, 0x73, 0x9f, 0x53, 0xd1, 0x37, 0x92, 0xe9, 0x4d, 0x76, 0xff, 0xef, 0xd6,
+ 0x46, 0x5b, 0xbc, 0x2e, 0xff, 0xf5, 0x83, 0xf7, 0x5f, 0xd5, 0xfe, 0xc7, 0xeb, 0xab, 0xd6, 0x83, 0x4f, 0xf8, 0x84, 0xfc,
+ 0x97, 0x4d, 0xfa, 0xff, 0xf9, 0xcf, 0x52, 0xdb, 0x33, 0xff, 0xe3, 0x3d, 0xae, 0xf1, 0x76, 0x7d, 0xac, 0xaf, 0xd0, 0x1e,
+ 0x01, 0xd4, 0xc0, 0x19, 0xa0, 0x27, 0xff, 0xb1, 0xf6, 0x3f, 0x3a, 0xfe, 0x8f, 0x27, 0xa3, 0x3e, 0xb6, 0xfd, 0xcf, 0x1d,
+ 0xff, 0xaf, 0xaa, 0x45, 0x98, 0xfb, 0xbc, 0xad, 0xac, 0x5a, 0x9b, 0xb1, 0xbe, 0x56, 0xb4, 0xfd, 0x6f, 0xf5, 0x0e, 0x66,
+ 0xf2, 0x5f, 0x26, 0x93, 0xf8, 0xf1, 0xf5, 0xbf, 0x55, 0xed, 0xff, 0xf9, 0xd7, 0xff, 0x6b, 0x20, 0x21, 0xab, 0xaa, 0x6e,
+ 0xd6, 0xe1, 0x6b, 0x31, 0xb3, 0x55, 0xd5, 0xfa, 0xef, 0x34, 0xf4, 0x9c, 0x9b, 0x5f, 0xdf, 0xa5, 0xe8, 0xd9, 0x2a, 0x19,
+ 0xa3, 0xbe, 0x5d, 0xfb, 0xff, 0xd7, 0xb4, 0xff, 0x3d, 0xad, 0x7f, 0xa4, 0x0e, 0xd9, 0xba, 0xeb, 0x7f, 0xd1, 0xf1, 0xd3,
+ 0xdc, 0xfd, 0xbf, 0xeb, 0xeb, 0x08, 0x66, 0x5f, 0xf9, 0x39, 0xf3, 0xb5, 0xae, 0xfa, 0x44, 0x3b, 0xf6, 0xff, 0xe3, 0x63,
+ 0xab, 0x91, 0x51, 0x7d, 0xde, 0xfd, 0xbf, 0x98, 0x56, 0xfe, 0xd7, 0xbc, 0xeb, 0xba, 0x63, 0x4e, 0xfe, 0xf7, 0xdc, 0x07,
+ 0x7b, 0xe5, 0xbf, 0xf7, 0x29, 0xe6, 0x35, 0xfd, 0x4e, 0xfc, 0x6e, 0x7b, 0xb0, 0x9d, 0xff, 0x7b, 0x7d, 0xff, 0xe7, 0xfc,
+ 0x27, 0x8f, 0x5e, 0x9d, 0xff, 0xdd, 0xce, 0x00, 0x59, 0x4f, 0xbc, 0x2e, 0x49, 0x7b, 0x32, 0x72, 0x17, 0x6f, 0xf7, 0xf3,
+ 0xa5, 0xfc, 0xf3, 0xfc, 0xef, 0x6f, 0xd6, 0xc7, 0xf7, 0x9b, 0xae, 0xef, 0x5b, 0xcb, 0x3f, 0xbc, 0xaf, 0xf6, 0xf7, 0x7f,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x9e, 0x0f, 0x58, 0x27, 0xe7, 0x0a, 0xc6, 0x2a,
+ 0x0d, 0x95, 0xe6, 0x8c, 0xd3, 0x1a, 0xfe, 0x9d, 0x91, 0x75, 0x89, 0xd7, 0xb0, 0x88, 0xd4, 0xe0, 0x2e, 0x8d, 0xba, 0x35,
+ 0x39, 0xdb, 0xe6, 0x9c, 0xf5, 0x6c, 0xd7, 0xda, 0x1b, 0x3b, 0x2e, 0x46, 0xb6, 0x54, 0xbb, 0x86, 0xca, 0x79, 0xdb, 0x21,
+ 0xba, 0xbf, 0x6b, 0x63, 0x76, 0x77, 0x6d, 0x54, 0xae, 0xc9, 0xa9, 0x07, 0x50, 0x1b, 0x75, 0x54, 0xe2, 0xf3, 0xd5, 0x46,
+ 0xcf, 0x00, 0xf5, 0x8f, 0xda, 0x4e, 0x35, 0xf4, 0x3b, 0xa3, 0x7b, 0x3d, 0xb6, 0xac, 0xa7, 0xaa, 0x63, 0x5e, 0xa5, 0xe8,
+ 0xc8, 0xb6, 0x59, 0xbf, 0x9e, 0xe3, 0xc7, 0x45, 0x4d, 0x7a, 0x87, 0xde, 0xba, 0x24, 0xfb, 0xef, 0xef, 0x76, 0x05, 0xd9,
+ 0xba, 0xac, 0xfd, 0xcf, 0xc8, 0xff, 0x58, 0x0d, 0xd6, 0x91, 0x3a, 0x63, 0x99, 0xf9, 0xdf, 0xab, 0x3f, 0x16, 0x7f, 0x1e,
+ 0x44, 0x56, 0xc5, 0xfd, 0x7b, 0xcc, 0xda, 0x8d, 0x3f, 0x99, 0xe0, 0x3e, 0xfb, 0x7b, 0xf5, 0xfa, 0xf5, 0x9c, 0x29, 0xe7,
+ 0xea, 0x42, 0x5c, 0x95, 0xff, 0xbc, 0xfe, 0x7f, 0xb4, 0x3f, 0x1d, 0x79, 0x26, 0xd2, 0x6c, 0x2d, 0xc5, 0x99, 0x27, 0x8b,
+ 0x9c, 0xbd, 0x2e, 0x73, 0xa3, 0x82, 0x9e, 0x31, 0xeb, 0x0e, 0xdb, 0x61, 0x66, 0x1b, 0x95, 0xe0, 0x93, 0x17, 0xb2, 0xf2,
+ 0x9f, 0x51, 0xcf, 0x74, 0x7c, 0xfc, 0xd7, 0xde, 0x56, 0xb9, 0xe7, 0xc5, 0xd8, 0xeb, 0xed, 0xba, 0xac, 0x4e, 0x8c, 0x63,
+ 0xae, 0x7d, 0x92, 0x51, 0x4e, 0xfe, 0xfb, 0x7b, 0xb5, 0xbb, 0xef, 0xd3, 0xd2, 0x31, 0x4e, 0xde, 0x3f, 0xff, 0xa3, 0x9f,
+ 0x25, 0xb3, 0x8f, 0x3b, 0x5b, 0x5d, 0xfa, 0x9a, 0x65, 0xf3, 0x4f, 0x2a, 0xd9, 0xfd, 0xd8, 0xbe, 0x3a, 0xff, 0x6b, 0x9e,
+ 0x06, 0x93, 0xbd, 0x8d, 0x5a, 0xa3, 0x86, 0xac, 0xf6, 0xbf, 0x35, 0x02, 0xa9, 0x5b, 0x8c, 0x0b, 0xfb, 0xb2, 0x3d, 0x7e,
+ 0xfd, 0x7f, 0xee, 0x58, 0x59, 0xb1, 0x6c, 0xfe, 0xb8, 0xdd, 0x37, 0xe3, 0xbb, 0xe4, 0xff, 0x0e, 0xe7, 0xc8, 0x78, 0xab,
+ 0x9d, 0xd1, 0xf7, 0x3d, 0xbf, 0xfd, 0xcf, 0xc8, 0x7f, 0xfe, 0x15, 0xd0, 0x3b, 0x2e, 0x5b, 0x9f, 0xd5, 0xd9, 0x6b, 0x70,
+ 0xf2, 0x2f, 0xff, 0xf1, 0xbe, 0x4a, 0x4d, 0xaf, 0x70, 0xb9, 0xe2, 0xe9, 0x60, 0x57, 0x8d, 0xff, 0x73, 0xaf, 0x43, 0xdd,
+ 0xb5, 0xff, 0x7f, 0xf7, 0x7d, 0x3a, 0xd3, 0x6b, 0xa7, 0xbc, 0x55, 0xdf, 0x60, 0xf6, 0x6c, 0xff, 0xb4, 0xfc, 0x3f, 0x7b,
+ 0x9f, 0x4a, 0xbd, 0xfc, 0xe7, 0x9e, 0x01, 0xd6, 0x65, 0x7c, 0x24, 0xbb, 0xef, 0x97, 0xff, 0xbb, 0x3c, 0x35, 0x48, 0xfe,
+ 0x9f, 0x31, 0xe6, 0x3b, 0xf7, 0x7b, 0x0e, 0x39, 0xdf, 0xff, 0x2b, 0x27, 0x3e, 0x01, 0xef, 0xec, 0xfb, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x33, 0x7e, 0x33, 0x2b, 0x3d, 0x1f, 0xfd, 0xe5, 0xa7, 0xfa,
+ 0xad, 0x7e, 0xf9, 0xee, 0x6b, 0xfd, 0xe7, 0xb0, 0xce, 0xc9, 0x19, 0x6b, 0xa1, 0x2e, 0xf7, 0xda, 0xba, 0xdc, 0xc7, 0x7b,
+ 0xfb, 0x2e, 0x55, 0xb9, 0x7b, 0x8f, 0xd9, 0x3a, 0xb8, 0x85, 0x57, 0xa6, 0x2f, 0xab, 0x9e, 0x43, 0x74, 0xee, 0xe1, 0xab,
+ 0xd7, 0xfc, 0x54, 0x3f, 0xff, 0xf8, 0xdf, 0xdf, 0x1f, 0x6e, 0xcb, 0xbe, 0x7a, 0x60, 0x79, 0x6b, 0xa1, 0x2e, 0xf7, 0xca,
+ 0xba, 0xdc, 0x7d, 0x7b, 0x7b, 0xf7, 0xaa, 0xdc, 0xfd, 0x6b, 0x51, 0x37, 0x49, 0xdf, 0xb5, 0xb3, 0xe4, 0xe2, 0xdb, 0x72,
+ 0xaf, 0x1a, 0xce, 0x35, 0x5c, 0x5b, 0x73, 0xae, 0x2e, 0xef, 0xf9, 0xeb, 0xb2, 0xaa, 0x87, 0xd9, 0x4a, 0xce, 0x6e, 0x47,
+ 0x74, 0x6c, 0x2d, 0xae, 0xd9, 0x9b, 0xfd, 0xef, 0xb8, 0xd3, 0xec, 0xe7, 0x99, 0xfc, 0xef, 0x54, 0xa7, 0xb9, 0xbd, 0xbd,
+ 0xe3, 0xcf, 0x51, 0x7a, 0x4e, 0x5d, 0xee, 0xd6, 0xde, 0x2e, 0x27, 0xcf, 0xbc, 0x8d, 0x6d, 0xa1, 0xfe, 0x3e, 0xeb, 0x1e,
+ 0x75, 0x96, 0xee, 0x9e, 0xff, 0x9d, 0xb6, 0x63, 0x0d, 0xd6, 0xe5, 0xdf, 0xab, 0xf6, 0xf6, 0xae, 0xf9, 0xbf, 0x47, 0xa5,
+ 0x95, 0x9e, 0xfc, 0xef, 0x76, 0xdc, 0x3e, 0xb1, 0xfd, 0x2f, 0x1d, 0xd5, 0xee, 0x33, 0x97, 0xe5, 0xd4, 0x8c, 0x7f, 0xe7,
+ 0xba, 0xbc, 0xef, 0x93, 0xff, 0x22, 0xff, 0xa7, 0xf4, 0xff, 0xcf, 0x5b, 0x36, 0xdf, 0x37, 0x58, 0x71, 0xfd, 0xff, 0x5e,
+ 0x75, 0x79, 0xdf, 0xa9, 0xfd, 0xdf, 0xa7, 0xce, 0xe2, 0x33, 0xf3, 0xbf, 0x63, 0x7b, 0xaa, 0x2e, 0xa7, 0xfc, 0xd7, 0xcd,
+ 0xd2, 0xb7, 0xcb, 0x11, 0x15, 0x3f, 0x22, 0x76, 0xaa, 0x57, 0x9d, 0x7d, 0x6d, 0xb0, 0xff, 0x0e, 0xfb, 0x13, 0xea, 0x72,
+ 0xde, 0x27, 0xff, 0x33, 0xd7, 0xff, 0xcf, 0x4f, 0x5f, 0x19, 0x7a, 0x0e, 0xf8, 0x15, 0x67, 0xa0, 0xd8, 0xfd, 0xff, 0xb3,
+ 0xaf, 0x8b, 0x67, 0x3d, 0x97, 0x28, 0xf7, 0x3b, 0x59, 0xcf, 0xa9, 0xcb, 0x79, 0x9f, 0xbb, 0x3d, 0x33, 0xf7, 0xff, 0xfb,
+ 0xee, 0x2c, 0x96, 0xe1, 0x1c, 0x67, 0x3c, 0xeb, 0xbf, 0x5c, 0x54, 0xc5, 0x38, 0xfa, 0xfd, 0x9f, 0x3b, 0x7d, 0xa3, 0x52,
+ 0x7d, 0xd7, 0xd5, 0xc9, 0xb1, 0x16, 0xeb, 0x8f, 0xd6, 0x35, 0x55, 0x8c, 0x5f, 0xe7, 0xbf, 0xf5, 0x5d, 0x4a, 0x9e, 0x94,
+ 0xff, 0x27, 0xec, 0x6d, 0xc7, 0x2c, 0xac, 0xf4, 0x97, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xd0, 0x3d, 0x43, 0xf3, 0xf8, 0xbb, 0xcd, 0x3b, 0xd7, 0x20, 0x05, 0x66, 0xe7, 0xe3, 0x3c, 0x63, 0x3e, 0x1e, 0x90, 0x3d,
+ 0xb7, 0x71, 0xaf, 0x7a, 0xdc, 0x40, 0xee, 0xfc, 0x7f, 0xf9, 0x07, 0xf9, 0x97, 0x7f, 0x90, 0x7f, 0xf9, 0x07, 0xf9, 0xff,
+ 0xf9, 0x97, 0x55, 0xfe, 0xe1, 0xe6, 0xf9, 0xaf, 0x4b, 0x6a, 0x9b, 0x03, 0x77, 0x39, 0x03, 0x44, 0xf2, 0x5f, 0xf4, 0xff,
+ 0xe1, 0xb1, 0xdf, 0x01, 0x30, 0xfe, 0x07, 0xe3, 0x7f, 0xf9, 0x87, 0x77, 0xcc, 0x7f, 0xeb, 0xfb, 0xbf, 0x46, 0xff, 0xf0,
+ 0x8c, 0xf1, 0xbf, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xf2, 0xff, 0x3f, 0xdb, 0x01, 0xe4, 0x1f, 0x78, 0xbb, 0xfc, 0xff, 0x0b };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle candyFontRecs[189] = {
+ { 4, 4, 3 , 15 },
+ { 15, 4, 2 , 9 },
+ { 25, 4, 3 , 2 },
+ { 36, 4, 8 , 9 },
+ { 52, 4, 6 , 11 },
+ { 66, 4, 7 , 9 },
+ { 81, 4, 7 , 9 },
+ { 96, 4, 1 , 2 },
+ { 105, 4, 3 , 11 },
+ { 116, 4, 3 , 11 },
+ { 127, 4, 7 , 7 },
+ { 142, 4, 6 , 5 },
+ { 156, 4, 2 , 3 },
+ { 166, 4, 5 , 1 },
+ { 179, 4, 2 , 2 },
+ { 189, 4, 5 , 10 },
+ { 202, 4, 6 , 9 },
+ { 216, 4, 4 , 9 },
+ { 228, 4, 6 , 9 },
+ { 242, 4, 6 , 9 },
+ { 256, 4, 7 , 9 },
+ { 271, 4, 6 , 9 },
+ { 285, 4, 6 , 9 },
+ { 299, 4, 6 , 9 },
+ { 313, 4, 6 , 9 },
+ { 327, 4, 6 , 9 },
+ { 341, 4, 2 , 6 },
+ { 351, 4, 2 , 7 },
+ { 361, 4, 4 , 6 },
+ { 373, 4, 5 , 3 },
+ { 386, 4, 4 , 6 },
+ { 398, 4, 6 , 9 },
+ { 412, 4, 8 , 7 },
+ { 428, 4, 6 , 9 },
+ { 442, 4, 6 , 9 },
+ { 456, 4, 6 , 9 },
+ { 470, 4, 6 , 9 },
+ { 484, 4, 6 , 9 },
+ { 4, 27, 6 , 9 },
+ { 18, 27, 6 , 9 },
+ { 32, 27, 6 , 9 },
+ { 46, 27, 2 , 9 },
+ { 56, 27, 6 , 9 },
+ { 70, 27, 6 , 9 },
+ { 84, 27, 6 , 9 },
+ { 98, 27, 8 , 9 },
+ { 114, 27, 6 , 9 },
+ { 128, 27, 6 , 9 },
+ { 142, 27, 6 , 9 },
+ { 156, 27, 6 , 9 },
+ { 170, 27, 6 , 9 },
+ { 184, 27, 6 , 9 },
+ { 198, 27, 6 , 9 },
+ { 212, 27, 6 , 9 },
+ { 226, 27, 6 , 9 },
+ { 240, 27, 8 , 9 },
+ { 256, 27, 6 , 9 },
+ { 270, 27, 6 , 9 },
+ { 284, 27, 6 , 9 },
+ { 298, 27, 3 , 11 },
+ { 309, 27, 5 , 10 },
+ { 322, 27, 3 , 11 },
+ { 333, 27, 6 , 4 },
+ { 347, 27, 6 , 1 },
+ { 361, 27, 3 , 2 },
+ { 372, 27, 6 , 7 },
+ { 386, 27, 6 , 10 },
+ { 400, 27, 6 , 7 },
+ { 414, 27, 6 , 10 },
+ { 428, 27, 6 , 7 },
+ { 442, 27, 5 , 10 },
+ { 455, 27, 7 , 10 },
+ { 470, 27, 6 , 10 },
+ { 484, 27, 2 , 10 },
+ { 494, 27, 2 , 12 },
+ { 4, 50, 6 , 10 },
+ { 18, 50, 3 , 10 },
+ { 29, 50, 8 , 7 },
+ { 45, 50, 6 , 7 },
+ { 59, 50, 6 , 7 },
+ { 73, 50, 6 , 10 },
+ { 87, 50, 6 , 10 },
+ { 101, 50, 6 , 7 },
+ { 115, 50, 6 , 7 },
+ { 129, 50, 3 , 10 },
+ { 140, 50, 6 , 7 },
+ { 154, 50, 6 , 7 },
+ { 168, 50, 8 , 7 },
+ { 184, 50, 6 , 7 },
+ { 198, 50, 6 , 10 },
+ { 212, 50, 6 , 7 },
+ { 226, 50, 4 , 11 },
+ { 238, 50, 1 , 11 },
+ { 247, 50, 4 , 11 },
+ { 259, 50, 6 , 2 },
+ { 273, 50, 2 , 10 },
+ { 283, 50, 6 , 11 },
+ { 297, 50, 8 , 9 },
+ { 313, 50, 7 , 9 },
+ { 328, 50, 6 , 9 },
+ { 342, 50, 0 , 0 },
+ { 350, 50, 6 , 11 },
+ { 364, 50, 0 , 0 },
+ { 372, 50, 8 , 8 },
+ { 388, 50, 5 , 7 },
+ { 401, 50, 7 , 6 },
+ { 416, 50, 7 , 12 },
+ { 431, 50, 8 , 8 },
+ { 447, 50, 6 , 1 },
+ { 461, 50, 4 , 5 },
+ { 473, 50, 6 , 7 },
+ { 487, 50, 3 , 5 },
+ { 498, 50, 3 , 5 },
+ { 4, 73, 0 , 0 },
+ { 12, 73, 6 , 9 },
+ { 26, 73, 6 , 9 },
+ { 40, 73, 4 , 4 },
+ { 52, 73, 0 , 0 },
+ { 60, 73, 2 , 5 },
+ { 70, 73, 4 , 7 },
+ { 82, 73, 7 , 6 },
+ { 97, 73, 10 , 9 },
+ { 115, 73, 10 , 7 },
+ { 133, 73, 0 , 0 },
+ { 141, 73, 6 , 9 },
+ { 155, 73, 6 , 12 },
+ { 169, 73, 6 , 12 },
+ { 183, 73, 6 , 12 },
+ { 197, 73, 6 , 12 },
+ { 211, 73, 6 , 11 },
+ { 225, 73, 6 , 12 },
+ { 239, 73, 10 , 9 },
+ { 257, 73, 6 , 12 },
+ { 271, 73, 6 , 12 },
+ { 285, 73, 6 , 12 },
+ { 299, 73, 6 , 12 },
+ { 313, 73, 6 , 11 },
+ { 327, 73, 3 , 12 },
+ { 338, 73, 3 , 12 },
+ { 349, 73, 4 , 12 },
+ { 361, 73, 4 , 11 },
+ { 373, 73, 8 , 9 },
+ { 389, 73, 6 , 12 },
+ { 403, 73, 6 , 12 },
+ { 417, 73, 6 , 12 },
+ { 431, 73, 6 , 12 },
+ { 445, 73, 6 , 12 },
+ { 459, 73, 6 , 11 },
+ { 473, 73, 5 , 5 },
+ { 486, 73, 9 , 10 },
+ { 4, 96, 6 , 12 },
+ { 18, 96, 6 , 12 },
+ { 32, 96, 6 , 12 },
+ { 46, 96, 6 , 11 },
+ { 60, 96, 6 , 12 },
+ { 74, 96, 7 , 12 },
+ { 89, 96, 6 , 10 },
+ { 103, 96, 6 , 10 },
+ { 117, 96, 6 , 10 },
+ { 131, 96, 6 , 10 },
+ { 145, 96, 6 , 10 },
+ { 159, 96, 6 , 9 },
+ { 173, 96, 6 , 11 },
+ { 187, 96, 10 , 7 },
+ { 205, 96, 6 , 10 },
+ { 219, 96, 6 , 10 },
+ { 233, 96, 6 , 10 },
+ { 247, 96, 6 , 10 },
+ { 261, 96, 6 , 9 },
+ { 275, 96, 3 , 10 },
+ { 286, 96, 3 , 10 },
+ { 297, 96, 4 , 10 },
+ { 309, 96, 4 , 9 },
+ { 321, 96, 7 , 12 },
+ { 336, 96, 6 , 13 },
+ { 350, 96, 6 , 10 },
+ { 364, 96, 6 , 10 },
+ { 378, 96, 6 , 10 },
+ { 392, 96, 6 , 10 },
+ { 406, 96, 6 , 9 },
+ { 420, 96, 7 , 12 },
+ { 435, 96, 8 , 8 },
+ { 451, 96, 6 , 10 },
+ { 465, 96, 6 , 10 },
+ { 479, 96, 6 , 10 },
+ { 493, 96, 6 , 9 },
+ { 4, 119, 6 , 13 },
+ { 18, 119, 7 , 12 },
+ { 33, 119, 6 , 12 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo candyFontGlyphs[189] = {
+ { 32, 0, 12, 3, { 0 }},
+ { 33, 0, 3, 3, { 0 }},
+ { 34, 0, 2, 4, { 0 }},
+ { 35, 0, 3, 9, { 0 }},
+ { 36, 0, 2, 7, { 0 }},
+ { 37, 0, 3, 8, { 0 }},
+ { 38, 0, 3, 8, { 0 }},
+ { 39, 0, 2, 2, { 0 }},
+ { 40, 1, 2, 5, { 0 }},
+ { 41, 1, 2, 5, { 0 }},
+ { 42, 0, 4, 8, { 0 }},
+ { 43, 0, 6, 7, { 0 }},
+ { 44, 0, 10, 3, { 0 }},
+ { 45, 0, 7, 6, { 0 }},
+ { 46, 0, 10, 3, { 0 }},
+ { 47, 1, 3, 7, { 0 }},
+ { 48, 0, 3, 7, { 0 }},
+ { 49, 0, 3, 5, { 0 }},
+ { 50, 0, 3, 7, { 0 }},
+ { 51, 0, 3, 7, { 0 }},
+ { 52, 0, 3, 8, { 0 }},
+ { 53, 0, 3, 7, { 0 }},
+ { 54, 0, 3, 7, { 0 }},
+ { 55, 0, 3, 7, { 0 }},
+ { 56, 0, 3, 7, { 0 }},
+ { 57, 0, 3, 7, { 0 }},
+ { 58, 0, 6, 3, { 0 }},
+ { 59, 0, 6, 3, { 0 }},
+ { 60, 1, 5, 6, { 0 }},
+ { 61, 1, 7, 7, { 0 }},
+ { 62, 1, 5, 6, { 0 }},
+ { 63, 0, 3, 7, { 0 }},
+ { 64, 0, 4, 9, { 0 }},
+ { 65, 0, 3, 7, { 0 }},
+ { 66, 0, 3, 7, { 0 }},
+ { 67, 0, 3, 7, { 0 }},
+ { 68, 0, 3, 7, { 0 }},
+ { 69, 0, 3, 7, { 0 }},
+ { 70, 0, 3, 7, { 0 }},
+ { 71, 0, 3, 7, { 0 }},
+ { 72, 0, 3, 7, { 0 }},
+ { 73, 0, 3, 3, { 0 }},
+ { 74, 0, 3, 7, { 0 }},
+ { 75, 0, 3, 7, { 0 }},
+ { 76, 0, 3, 7, { 0 }},
+ { 77, 0, 3, 9, { 0 }},
+ { 78, 0, 3, 7, { 0 }},
+ { 79, 0, 3, 7, { 0 }},
+ { 80, 0, 3, 7, { 0 }},
+ { 81, 0, 3, 7, { 0 }},
+ { 82, 0, 3, 7, { 0 }},
+ { 83, 0, 3, 7, { 0 }},
+ { 84, 0, 3, 7, { 0 }},
+ { 85, 0, 3, 7, { 0 }},
+ { 86, 0, 3, 7, { 0 }},
+ { 87, 0, 3, 9, { 0 }},
+ { 88, 0, 3, 7, { 0 }},
+ { 89, 0, 3, 7, { 0 }},
+ { 90, 0, 3, 7, { 0 }},
+ { 91, 1, 2, 5, { 0 }},
+ { 92, 1, 3, 7, { 0 }},
+ { 93, 1, 2, 5, { 0 }},
+ { 94, 0, 3, 7, { 0 }},
+ { 95, 0, 11, 7, { 0 }},
+ { 96, 0, 0, 4, { 0 }},
+ { 97, 0, 5, 7, { 0 }},
+ { 98, 0, 2, 7, { 0 }},
+ { 99, 0, 5, 7, { 0 }},
+ { 100, 0, 2, 7, { 0 }},
+ { 101, 0, 5, 7, { 0 }},
+ { 102, 0, 2, 6, { 0 }},
+ { 103, 0, 5, 7, { 0 }},
+ { 104, 0, 2, 7, { 0 }},
+ { 105, 0, 2, 3, { 0 }},
+ { 106, 0, 2, 3, { 0 }},
+ { 107, 0, 2, 7, { 0 }},
+ { 108, 0, 2, 4, { 0 }},
+ { 109, 0, 5, 9, { 0 }},
+ { 110, 0, 5, 7, { 0 }},
+ { 111, 0, 5, 7, { 0 }},
+ { 112, 0, 5, 7, { 0 }},
+ { 113, 0, 5, 7, { 0 }},
+ { 114, 0, 5, 7, { 0 }},
+ { 115, 0, 5, 7, { 0 }},
+ { 116, 0, 2, 4, { 0 }},
+ { 117, 0, 5, 7, { 0 }},
+ { 118, 0, 5, 7, { 0 }},
+ { 119, 0, 5, 9, { 0 }},
+ { 120, 0, 5, 7, { 0 }},
+ { 121, 0, 5, 7, { 0 }},
+ { 122, 0, 5, 7, { 0 }},
+ { 123, 1, 2, 6, { 0 }},
+ { 124, 1, 2, 3, { 0 }},
+ { 125, 1, 2, 6, { 0 }},
+ { 126, 0, 0, 7, { 0 }},
+ { 161, 0, 3, 3, { 0 }},
+ { 162, 0, 2, 7, { 0 }},
+ { 163, 0, 3, 9, { 0 }},
+ { 8364, 0, 3, 8, { 0 }},
+ { 165, 0, 3, 7, { 0 }},
+ { 352, 0, 12, 1, { 0 }},
+ { 167, 0, 2, 7, { 0 }},
+ { 353, 0, 12, 1, { 0 }},
+ { 169, 0, 0, 9, { 0 }},
+ { 170, 0, 0, 6, { 0 }},
+ { 171, 1, 5, 9, { 0 }},
+ { 172, 0, 0, 7, { 0 }},
+ { 174, 0, 0, 9, { 0 }},
+ { 175, 0, 0, 7, { 0 }},
+ { 176, 0, 0, 5, { 0 }},
+ { 177, 0, 4, 7, { 0 }},
+ { 178, 0, 0, 4, { 0 }},
+ { 179, 0, 0, 4, { 0 }},
+ { 381, 0, 12, 1, { 0 }},
+ { 181, 0, 5, 7, { 0 }},
+ { 182, 0, 3, 7, { 0 }},
+ { 183, 0, 6, 5, { 0 }},
+ { 382, 0, 12, 1, { 0 }},
+ { 185, 0, 0, 3, { 0 }},
+ { 186, 0, 0, 5, { 0 }},
+ { 187, 1, 5, 9, { 0 }},
+ { 338, 0, 3, 11, { 0 }},
+ { 339, 0, 5, 11, { 0 }},
+ { 376, 0, 12, 1, { 0 }},
+ { 191, 0, 4, 7, { 0 }},
+ { 192, 0, 0, 7, { 0 }},
+ { 193, 0, 0, 7, { 0 }},
+ { 194, 0, 0, 7, { 0 }},
+ { 195, 0, 0, 7, { 0 }},
+ { 196, 0, 1, 7, { 0 }},
+ { 197, 0, 0, 7, { 0 }},
+ { 198, 0, 3, 11, { 0 }},
+ { 199, 0, 3, 7, { 0 }},
+ { 200, 0, 0, 7, { 0 }},
+ { 201, 0, 0, 7, { 0 }},
+ { 202, 0, 0, 7, { 0 }},
+ { 203, 0, 1, 7, { 0 }},
+ { 204, -1, 0, 3, { 0 }},
+ { 205, 0, 0, 3, { 0 }},
+ { 206, -1, 0, 3, { 0 }},
+ { 207, -1, 1, 3, { 0 }},
+ { 208, 0, 3, 9, { 0 }},
+ { 209, 0, 0, 7, { 0 }},
+ { 210, 0, 0, 7, { 0 }},
+ { 211, 0, 0, 7, { 0 }},
+ { 212, 0, 0, 7, { 0 }},
+ { 213, 0, 0, 7, { 0 }},
+ { 214, 0, 1, 7, { 0 }},
+ { 215, 0, 7, 6, { 0 }},
+ { 216, 0, 3, 10, { 0 }},
+ { 217, 0, 0, 7, { 0 }},
+ { 218, 0, 0, 7, { 0 }},
+ { 219, 0, 0, 7, { 0 }},
+ { 220, 0, 1, 7, { 0 }},
+ { 221, 0, 0, 7, { 0 }},
+ { 222, 0, 0, 7, { 0 }},
+ { 223, 0, 3, 7, { 0 }},
+ { 224, 0, 2, 7, { 0 }},
+ { 225, 0, 2, 7, { 0 }},
+ { 226, 0, 2, 7, { 0 }},
+ { 227, 0, 2, 7, { 0 }},
+ { 228, 0, 3, 7, { 0 }},
+ { 229, 0, 1, 7, { 0 }},
+ { 230, 0, 5, 11, { 0 }},
+ { 231, 0, 5, 7, { 0 }},
+ { 232, 0, 2, 7, { 0 }},
+ { 233, 0, 2, 7, { 0 }},
+ { 234, 0, 2, 7, { 0 }},
+ { 235, 0, 3, 7, { 0 }},
+ { 236, 0, 2, 4, { 0 }},
+ { 237, 0, 2, 4, { 0 }},
+ { 238, 0, 2, 4, { 0 }},
+ { 239, 0, 3, 4, { 0 }},
+ { 240, 0, 0, 7, { 0 }},
+ { 241, 0, 2, 7, { 0 }},
+ { 242, 0, 2, 7, { 0 }},
+ { 243, 0, 2, 7, { 0 }},
+ { 244, 0, 2, 7, { 0 }},
+ { 245, 0, 2, 7, { 0 }},
+ { 246, 0, 3, 7, { 0 }},
+ { 247, 0, 0, 7, { 0 }},
+ { 248, 0, 5, 9, { 0 }},
+ { 249, 0, 2, 7, { 0 }},
+ { 250, 0, 2, 7, { 0 }},
+ { 251, 0, 2, 7, { 0 }},
+ { 252, 0, 3, 7, { 0 }},
+ { 253, 0, 2, 7, { 0 }},
+ { 254, 0, 0, 7, { 0 }},
+ { 255, 0, 3, 7, { 0 }},
+};
+
+// Style loading function: Candy
+static void GuiLoadStyleCandy(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < CANDY_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(candyStyleProps[i].controlId, candyStyleProps[i].propertyId, candyStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int candyFontDataSize = 0;
+ unsigned char *data = DecompressData(candyFontData, CANDY_STYLE_FONT_ATLAS_COMP_SIZE, &candyFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 15;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, candyFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, candyFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_cherry.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_cherry.h
new file mode 100644
index 0000000000..c736396cf7
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_cherry.h
@@ -0,0 +1,617 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleCherry(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define CHERRY_STYLE_PROPS_COUNT 17
+
+// Custom style name: Cherry
+static const GuiStyleProp cherryStyleProps[CHERRY_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0xda5757ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x753233ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0xe17373ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0xfaaa97ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0xe06262ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0xfdb4aaff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0xe03c46ff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0x5b1e20ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0xc2474fff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0xa19292ff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x706060ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x9e8585ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x0000000f }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0xfb8170ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x3a1720ff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000016 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "Westington.ttf" (size: 15, spacing: 0)
+
+#define CHERRY_STYLE_FONT_ATLAS_COMP_SIZE 2821
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char cherryFontData[CHERRY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0x59, 0x92, 0xdc, 0xba, 0x11, 0x05, 0x50, 0xee, 0x7f, 0xd3, 0xd7, 0xe1, 0x70, 0x84, 0xed, 0x27, 0xa9, 0x09, 0x20,
+ 0x91, 0x20, 0xab, 0x5b, 0x47, 0xe7, 0xaf, 0xa1, 0x1a, 0x38, 0x24, 0x26, 0x16, 0x12, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0xef, 0x7f, 0x5f, 0xfd, 0xf5, 0xcf, 0x65, 0xff, 0xff, 0xaa, 0xdc, 0xbe, 0x73, 0xfd, 0xb3, 0xb3, 0xf8, 0xae, 0x59, 0xf8,
+ 0x7f, 0xf9, 0xf2, 0xbb, 0x64, 0xfa, 0x33, 0xd7, 0x8f, 0x7b, 0xfd, 0x58, 0xef, 0xce, 0xfd, 0xfa, 0x31, 0x5c, 0x37, 0x9f,
+ 0xbf, 0xf6, 0xdd, 0x2a, 0xaf, 0xb9, 0x2f, 0x59, 0xbf, 0x7b, 0x3a, 0xae, 0xc8, 0xdc, 0x35, 0xb8, 0x3f, 0xa7, 0xd7, 0xf0,
+ 0x95, 0xeb, 0xef, 0x9c, 0xe1, 0x59, 0x1c, 0x7f, 0xab, 0xb5, 0x1a, 0xe0, 0xeb, 0xbf, 0x8e, 0xee, 0xa6, 0x14, 0xee, 0xab,
+ 0xff, 0xbd, 0x22, 0x8b, 0x65, 0xa3, 0xd7, 0xec, 0xdd, 0x57, 0x59, 0xa8, 0xa5, 0x2a, 0x57, 0x21, 0x8b, 0xe7, 0x61, 0xf5,
+ 0xdc, 0xa5, 0x54, 0xff, 0x8c, 0xbe, 0x6d, 0x5a, 0x8e, 0xe7, 0xae, 0x24, 0xd3, 0x7f, 0x1d, 0xbf, 0xa2, 0xf2, 0x6e, 0x33,
+ 0xf7, 0xd5, 0xdd, 0xab, 0xfb, 0xdf, 0x39, 0x53, 0xf7, 0xef, 0xd9, 0xf8, 0x1f, 0xd5, 0x97, 0xf7, 0xe7, 0xfb, 0xee, 0x28,
+ 0xf2, 0xdf, 0xde, 0x45, 0xed, 0xbe, 0xdb, 0x89, 0xf4, 0xdc, 0xdc, 0x9d, 0x29, 0x9e, 0x8d, 0xfa, 0xff, 0xbb, 0x8f, 0x97,
+ 0x14, 0x7b, 0x5e, 0x59, 0xb8, 0x4f, 0xb3, 0x54, 0xeb, 0xcd, 0xf4, 0x26, 0x2a, 0x35, 0xdd, 0x6e, 0x2f, 0x6a, 0xbf, 0xa7,
+ 0xfb, 0xf5, 0x35, 0xb8, 0x3b, 0xdf, 0x99, 0x3c, 0x82, 0x94, 0xe2, 0xff, 0x5a, 0xac, 0xb1, 0x9f, 0x8a, 0xff, 0x71, 0xac,
+ 0x8c, 0xe2, 0x29, 0xc3, 0x2b, 0x9c, 0x96, 0xef, 0x9f, 0x52, 0x8d, 0x76, 0x6a, 0x9c, 0x55, 0xbf, 0x7f, 0x66, 0xcf, 0x5e,
+ 0x06, 0xa3, 0xb9, 0xee, 0x5e, 0xe8, 0x7c, 0xaf, 0x2f, 0xc5, 0xda, 0x75, 0xa5, 0x8f, 0x9f, 0xad, 0xde, 0xfa, 0x28, 0x7e,
+ 0xb3, 0x5c, 0x17, 0x67, 0xa2, 0x3f, 0x74, 0xa2, 0x4f, 0xf2, 0x09, 0xf1, 0x9f, 0xc2, 0x08, 0xae, 0x5a, 0xc7, 0xa7, 0xa9,
+ 0x6d, 0xce, 0xa1, 0xfa, 0xb5, 0x3b, 0xfe, 0xd7, 0xcb, 0xc6, 0x91, 0x91, 0xd6, 0x71, 0x58, 0x4a, 0x23, 0xe9, 0x7a, 0x1b,
+ 0xbe, 0xfb, 0xda, 0xbb, 0xb9, 0xa2, 0x4c, 0xd4, 0x9e, 0x59, 0x9e, 0x01, 0xd8, 0x89, 0xff, 0xfe, 0xf1, 0x7f, 0x4a, 0xaf,
+ 0x98, 0xab, 0x8d, 0x6b, 0x35, 0x71, 0x16, 0xbe, 0x59, 0x9a, 0x6a, 0xb6, 0x1c, 0x9d, 0x65, 0xbd, 0x1a, 0xe3, 0xbf, 0x36,
+ 0x72, 0x4a, 0xdb, 0xdc, 0x44, 0x7d, 0xec, 0x96, 0xa6, 0xfb, 0x35, 0xad, 0xaf, 0xb8, 0x8f, 0xff, 0xbb, 0xf6, 0x7f, 0xbf,
+ 0xff, 0xff, 0x7e, 0xfb, 0xdf, 0x3d, 0xfa, 0x9f, 0x9f, 0xc5, 0x18, 0x9f, 0xd3, 0xe7, 0xe2, 0xff, 0x64, 0xdf, 0xbf, 0x36,
+ 0x96, 0x4f, 0x71, 0x9e, 0x32, 0x4d, 0x23, 0xf6, 0x94, 0x47, 0xe7, 0x69, 0x99, 0xd5, 0xe9, 0xab, 0xab, 0x53, 0xfe, 0x8c,
+ 0xfa, 0x3c, 0xf6, 0x4f, 0x1d, 0xff, 0x67, 0xe9, 0xd9, 0xc0, 0xb8, 0x6f, 0x75, 0x77, 0x66, 0xd2, 0x3e, 0xff, 0xf7, 0xde,
+ 0x53, 0xd6, 0xb5, 0x5a, 0x27, 0x85, 0x31, 0x76, 0x65, 0xd6, 0xbc, 0xfa, 0x34, 0xb1, 0xf3, 0xd9, 0xe4, 0xfb, 0xd7, 0xa9,
+ 0x3a, 0xd7, 0x98, 0x72, 0xed, 0x9e, 0x89, 0x67, 0x3f, 0xeb, 0xb3, 0x0a, 0x4f, 0xf5, 0xa6, 0x66, 0xe6, 0x62, 0xae, 0xe2,
+ 0xbc, 0x69, 0x0a, 0x3d, 0x9c, 0x4f, 0x8f, 0xff, 0x4f, 0xaa, 0x89, 0x3e, 0xf1, 0xf7, 0x27, 0x69, 0x1e, 0xe9, 0x77, 0x45,
+ 0x40, 0x26, 0x46, 0xe2, 0x57, 0xa1, 0x9e, 0xfe, 0x0e, 0xcf, 0xff, 0xc7, 0xf1, 0x5f, 0x1d, 0xff, 0x67, 0xea, 0xf7, 0x18,
+ 0x6b, 0xcf, 0x01, 0xf2, 0xe1, 0xad, 0xbf, 0x1a, 0xa0, 0x67, 0x4e, 0xfe, 0xe9, 0xfa, 0x39, 0x87, 0xc7, 0x85, 0x7f, 0xe3,
+ 0x75, 0x05, 0xf7, 0x0f, 0x20, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x5e, 0x37,
+ 0xb8, 0xbe, 0x16, 0xb1, 0x3b, 0x4b, 0x6b, 0xe5, 0xfd, 0x7e, 0x2f, 0x1d, 0xbd, 0x47, 0xf5, 0x68, 0x2b, 0xb9, 0xa0, 0x33,
+ 0xf5, 0xdd, 0xb3, 0xbc, 0xa2, 0x73, 0x74, 0x34, 0xf9, 0xc7, 0x1a, 0xd5, 0x99, 0x73, 0xba, 0x73, 0x5d, 0xc6, 0x99, 0x77,
+ 0x57, 0xf2, 0xfb, 0xae, 0xad, 0x06, 0x5e, 0x5d, 0x21, 0xd0, 0x99, 0xed, 0x60, 0xf6, 0xfa, 0x56, 0xee, 0xa8, 0x95, 0x4f,
+ 0xdb, 0x59, 0x8b, 0x78, 0x9f, 0x81, 0xf9, 0x1a, 0x66, 0x88, 0xee, 0xca, 0x51, 0x97, 0x8d, 0x35, 0xfb, 0xbf, 0xdf, 0xc9,
+ 0x95, 0x55, 0xdb, 0xe3, 0x7b, 0xaa, 0x92, 0x77, 0xa9, 0x9a, 0xb3, 0x39, 0x2d, 0x9f, 0x3b, 0xf3, 0xcd, 0xe6, 0x32, 0xfa,
+ 0xd4, 0x33, 0xb6, 0x5f, 0x8b, 0xfb, 0x30, 0xac, 0xad, 0xe5, 0xce, 0xf2, 0x5a, 0xf8, 0xb4, 0xe5, 0x8b, 0x48, 0xf1, 0x3d,
+ 0x6b, 0xf7, 0xda, 0x99, 0xec, 0x3f, 0xd5, 0x2c, 0x59, 0x67, 0xe2, 0x3f, 0xe5, 0xef, 0x92, 0xdb, 0x7b, 0xe2, 0x1a, 0x66,
+ 0x28, 0xaa, 0x66, 0x5e, 0xca, 0x46, 0xbd, 0x96, 0x8d, 0xb5, 0xee, 0x5d, 0xf1, 0xbf, 0x13, 0xe1, 0xb3, 0xf9, 0x7b, 0xd3,
+ 0xb2, 0xba, 0x7f, 0x25, 0x1b, 0x7a, 0xb5, 0x1f, 0xdc, 0x19, 0x21, 0x77, 0xc7, 0x9e, 0x8d, 0x33, 0x73, 0x26, 0xfe, 0xf3,
+ 0x01, 0xf1, 0xbf, 0x53, 0x17, 0x7d, 0xcf, 0xf8, 0x4f, 0x43, 0xed, 0x9c, 0xd2, 0x15, 0xfa, 0x3d, 0x76, 0x2b, 0x7b, 0x59,
+ 0x5c, 0xe5, 0x8c, 0xce, 0x69, 0x6e, 0x8f, 0x3a, 0xd6, 0x14, 0x3f, 0x19, 0xff, 0xeb, 0xf5, 0xcd, 0xa9, 0xf8, 0xbf, 0xdb,
+ 0xad, 0x23, 0xa5, 0xdd, 0x9e, 0xfa, 0xf6, 0xc1, 0x5a, 0xa9, 0x8b, 0x32, 0x9d, 0x5b, 0xb4, 0x12, 0xff, 0x19, 0xee, 0xa0,
+ 0x51, 0xd9, 0xb7, 0xa0, 0x9a, 0x0d, 0xb9, 0x23, 0xfe, 0xe7, 0xf3, 0x9b, 0x67, 0xb2, 0xee, 0xed, 0x88, 0xf3, 0x77, 0xe2,
+ 0x7f, 0x74, 0x05, 0x53, 0xcc, 0xd6, 0xb7, 0x9e, 0xe5, 0x7b, 0xfc, 0x69, 0xbd, 0x59, 0xd4, 0x67, 0xf6, 0x9a, 0xc9, 0x37,
+ 0x68, 0xff, 0xcf, 0xc7, 0x7f, 0xe5, 0x5d, 0x67, 0xe7, 0x66, 0xf2, 0x5a, 0xfc, 0x67, 0xbb, 0x85, 0x4f, 0xf3, 0xe8, 0xf2,
+ 0x8d, 0xbc, 0x5f, 0x33, 0xf3, 0x05, 0xb5, 0x18, 0x4f, 0xeb, 0x78, 0xa3, 0xf6, 0x69, 0x27, 0x7a, 0x98, 0xeb, 0xf1, 0x9f,
+ 0xa3, 0xe3, 0xff, 0x95, 0x4f, 0xa8, 0xf7, 0xff, 0xef, 0x3e, 0xbb, 0x77, 0xfe, 0xaf, 0x6b, 0xee, 0x69, 0xa6, 0xed, 0x4e,
+ 0x43, 0x2f, 0xe2, 0x7c, 0xcd, 0x90, 0xd7, 0x9e, 0x91, 0x55, 0x3e, 0xff, 0x44, 0x44, 0x56, 0x63, 0xab, 0x1a, 0xff, 0xbd,
+ 0xf3, 0xff, 0x1d, 0xf3, 0xcc, 0x73, 0x47, 0x9f, 0x42, 0xa4, 0xa6, 0x38, 0xbe, 0xca, 0xd6, 0x0c, 0x79, 0x36, 0xe2, 0x3f,
+ 0x0d, 0xf1, 0x7f, 0xf7, 0xfc, 0x6e, 0x37, 0xfe, 0x33, 0x78, 0xbe, 0x91, 0x6f, 0x13, 0xff, 0x29, 0xc5, 0x7f, 0x9a, 0x23,
+ 0x32, 0xe5, 0xd8, 0xba, 0x96, 0x9f, 0x4f, 0x9e, 0x79, 0xfe, 0x3f, 0x7e, 0xca, 0xba, 0xf3, 0x24, 0x79, 0xf6, 0x3b, 0xd5,
+ 0x7f, 0xed, 0x30, 0x3a, 0x4b, 0x59, 0x8e, 0xb0, 0x94, 0x72, 0xf3, 0xcf, 0x8f, 0xf9, 0xb2, 0xd9, 0x4a, 0x8d, 0x6b, 0x88,
+ 0x6a, 0x4e, 0xea, 0xd5, 0x7d, 0xd5, 0xf3, 0xfa, 0xbe, 0x36, 0xcf, 0xbc, 0x72, 0x67, 0xaf, 0x06, 0x39, 0x89, 0xf9, 0x19,
+ 0xbf, 0x49, 0x73, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0x60,
+ 0xa6, 0x94, 0xd5, 0x6b, 0xf6, 0x7f, 0x55, 0x73, 0x90, 0xe5, 0x36, 0xcb, 0xf4, 0xda, 0x5a, 0xdf, 0x0c, 0x8f, 0xb1, 0x63,
+ 0xa5, 0xf4, 0xd9, 0x2c, 0xdc, 0xf3, 0xe7, 0xb6, 0x76, 0xf5, 0xb3, 0x98, 0xcf, 0x32, 0xed, 0x2b, 0xd3, 0xc7, 0xeb, 0xad,
+ 0xef, 0xd7, 0xd0, 0xd7, 0x5f, 0x77, 0x15, 0x56, 0x38, 0xaf, 0x5e, 0xad, 0x99, 0x5c, 0xf1, 0x6f, 0xd4, 0x15, 0xd7, 0x44,
+ 0x86, 0xbb, 0x9d, 0x1c, 0xfa, 0x77, 0xe7, 0xfe, 0xeb, 0xfb, 0xf5, 0xee, 0x7b, 0xf5, 0xe5, 0x2d, 0xbc, 0xb6, 0x33, 0xe8,
+ 0x5e, 0x8f, 0x64, 0xe1, 0xce, 0xe2, 0x7d, 0x38, 0xfb, 0x3f, 0x47, 0x59, 0x04, 0x53, 0xc8, 0xf4, 0x71, 0xee, 0x78, 0x67,
+ 0xf2, 0x3f, 0x8d, 0xf2, 0x3c, 0xfe, 0xf9, 0xef, 0x2b, 0xf7, 0x53, 0x2d, 0x67, 0x72, 0x06, 0xb9, 0x24, 0x7b, 0xd7, 0x5a,
+ 0xe7, 0xf6, 0x5e, 0x5d, 0xef, 0x47, 0x9c, 0xb9, 0xa2, 0xf5, 0xf8, 0x5f, 0x6f, 0x77, 0x4e, 0xc5, 0xff, 0x7e, 0x16, 0xde,
+ 0x9d, 0x1c, 0x3d, 0xfb, 0x7f, 0xbf, 0x6f, 0xfd, 0xaf, 0xe5, 0xde, 0xd9, 0xb5, 0x95, 0xeb, 0x76, 0x9c, 0x09, 0x67, 0x9c,
+ 0x61, 0x6a, 0xf5, 0x38, 0xae, 0xc5, 0xfc, 0xce, 0x9f, 0x13, 0xff, 0x57, 0x29, 0xfe, 0xaf, 0x0f, 0x8a, 0xff, 0xbb, 0x76,
+ 0xe7, 0x2a, 0xee, 0x27, 0x72, 0xd7, 0x33, 0xbb, 0x1a, 0xdb, 0x9c, 0xdf, 0x6b, 0xd5, 0x94, 0xfa, 0xc3, 0x29, 0x67, 0x4f,
+ 0x7c, 0x2b, 0x07, 0xd7, 0x78, 0x77, 0x93, 0x71, 0xdf, 0xbf, 0x56, 0x53, 0xd6, 0x32, 0x31, 0xdd, 0x8f, 0x28, 0xb2, 0xb4,
+ 0x3b, 0x41, 0x3d, 0x2f, 0x58, 0x0e, 0x64, 0x47, 0x59, 0xad, 0xe9, 0x53, 0xe8, 0xff, 0x5f, 0x5b, 0xfb, 0x48, 0x54, 0xf3,
+ 0x1e, 0xd7, 0x72, 0xac, 0xa7, 0xd0, 0xee, 0xcc, 0xc4, 0xdf, 0x5e, 0x16, 0xde, 0x4c, 0x8e, 0xb2, 0xae, 0xc5, 0x3a, 0xf2,
+ 0x6a, 0xab, 0x31, 0xd6, 0x7a, 0x98, 0xd9, 0x1a, 0x6d, 0xcd, 0xd4, 0x0d, 0x59, 0xdc, 0xab, 0xa1, 0xde, 0x5e, 0x54, 0xf2,
+ 0xc9, 0xd5, 0x6b, 0x80, 0xbc, 0x36, 0xff, 0x77, 0x15, 0x32, 0xd5, 0xaf, 0xe5, 0xe6, 0xab, 0xcc, 0xbd, 0x55, 0x8e, 0xaf,
+ 0x96, 0x73, 0x6f, 0x26, 0x6b, 0x7b, 0x4f, 0xfe, 0xe2, 0xd5, 0xf3, 0x73, 0x4d, 0xcd, 0x6a, 0xe5, 0xa5, 0xf6, 0x7f, 0x3d,
+ 0x02, 0xe6, 0x76, 0xa5, 0xdc, 0xe9, 0xd5, 0x54, 0x33, 0x76, 0xf7, 0xf7, 0x7e, 0xde, 0x9f, 0xff, 0x5f, 0xcb, 0xe0, 0xfd,
+ 0x59, 0xd9, 0x59, 0xd3, 0xf0, 0x3f, 0xfa, 0x3e, 0xeb, 0xed, 0x67, 0x38, 0x39, 0x5a, 0xfb, 0xf7, 0xc6, 0x7f, 0x8a, 0xe3,
+ 0xc9, 0xd9, 0x7a, 0x38, 0x4b, 0x39, 0x87, 0xc7, 0xf3, 0x5b, 0xe7, 0xc6, 0x3f, 0x9f, 0x78, 0x3f, 0xed, 0xe4, 0xb2, 0x7f,
+ 0xf6, 0x7b, 0xe6, 0xb1, 0x1e, 0xd3, 0x89, 0xd9, 0x97, 0xe7, 0xce, 0xc4, 0xda, 0x31, 0xa5, 0xf1, 0x8e, 0xad, 0xcd, 0xff,
+ 0x65, 0x63, 0x8e, 0x6f, 0x77, 0xbf, 0xde, 0x14, 0x66, 0x15, 0xff, 0x86, 0x5f, 0x0a, 0x7c, 0x3d, 0x03, 0x91, 0xbf, 0x22,
+ 0xf7, 0xf0, 0x4f, 0x3c, 0xc6, 0x8e, 0xe7, 0xff, 0xd5, 0x7e, 0x53, 0x6d, 0xe7, 0x80, 0xb9, 0x79, 0x9f, 0xca, 0xfc, 0x6e,
+ 0x75, 0xcc, 0x08, 0x54, 0x9e, 0x31, 0x57, 0x76, 0x0e, 0xe8, 0x18, 0xc1, 0x65, 0xf9, 0xf9, 0x3f, 0xf0, 0x53, 0x6a, 0xa2,
+ 0xda, 0xbc, 0x22, 0xf0, 0xfd, 0x47, 0x3b, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x9e, 0xbf, 0x88, 0x5e, 0x5f, 0xeb, 0xba, 0x9e, 0xeb, 0xb0, 0x9e, 0x71, 0x65, 0x76, 0x7d, 0xea, 0x55, 0xca, 0x1a, 0xb9,
+ 0x97, 0x9b, 0x66, 0x2e, 0x5b, 0x73, 0x3d, 0x5b, 0x5d, 0x35, 0x43, 0xd6, 0x5e, 0xe9, 0xf8, 0x95, 0xf5, 0x57, 0x5f, 0xd3,
+ 0xe7, 0x2d, 0xaf, 0x1c, 0x77, 0x16, 0x73, 0x18, 0xac, 0xdc, 0x53, 0xfd, 0xc7, 0xba, 0x77, 0x2e, 0xae, 0x62, 0x46, 0x9f,
+ 0x4a, 0xb6, 0xe3, 0x4a, 0xbc, 0xde, 0xe5, 0x3b, 0xcd, 0xe2, 0x67, 0x65, 0x39, 0xa7, 0xf3, 0xa8, 0x16, 0xc9, 0x60, 0xc5,
+ 0x68, 0x26, 0xd6, 0x9c, 0xee, 0xe5, 0x1b, 0xa8, 0x96, 0x8d, 0xaf, 0x7a, 0x3d, 0xcf, 0x49, 0x16, 0xeb, 0x8f, 0xb5, 0x1c,
+ 0x7d, 0x27, 0x8f, 0x7b, 0x7d, 0x0d, 0x73, 0x96, 0x73, 0x64, 0x5d, 0x8b, 0xad, 0x4d, 0x26, 0xda, 0x87, 0xea, 0xb9, 0x98,
+ 0x6d, 0x01, 0x57, 0xdb, 0xcd, 0xd5, 0x9a, 0xa4, 0x1a, 0xff, 0xd5, 0xcf, 0x3a, 0x13, 0xff, 0x77, 0xc7, 0x96, 0xdb, 0x9c,
+ 0x13, 0xd9, 0xcc, 0x6f, 0xf8, 0x6c, 0xaf, 0xb0, 0xa7, 0xfd, 0x4d, 0x71, 0x8d, 0xfe, 0xf9, 0x75, 0x81, 0xa7, 0x56, 0x07,
+ 0xd6, 0x73, 0x47, 0xbf, 0x71, 0x0f, 0xa4, 0x2d, 0x6b, 0xe4, 0x5c, 0x3e, 0xd6, 0xf5, 0xf8, 0x5f, 0x1d, 0x2f, 0xac, 0xe6,
+ 0x33, 0xcc, 0x44, 0xeb, 0x34, 0xdb, 0xfe, 0x67, 0xeb, 0xea, 0x3f, 0xdf, 0xff, 0xbf, 0x36, 0xda, 0xd0, 0xb9, 0xd1, 0xc1,
+ 0x6c, 0x1e, 0x8e, 0xd5, 0xbb, 0xa9, 0x5e, 0x3a, 0xce, 0x0d, 0xbc, 0xf7, 0xd7, 0xf1, 0xfd, 0x77, 0xf7, 0x4e, 0x95, 0x91,
+ 0x52, 0xb6, 0x33, 0x36, 0x65, 0xf9, 0x6c, 0xdc, 0x1f, 0xf5, 0x7a, 0xce, 0xe5, 0xd5, 0xf8, 0x1f, 0xd5, 0x26, 0x6b, 0x23,
+ 0xb8, 0x71, 0xfb, 0x3f, 0x93, 0x6b, 0x72, 0x6f, 0xb7, 0x8a, 0x1c, 0x89, 0xc3, 0x7a, 0xe9, 0xce, 0x4e, 0x27, 0x7f, 0xaa,
+ 0x13, 0x53, 0xae, 0x99, 0x72, 0xac, 0xf4, 0xc4, 0xf8, 0x7f, 0x9c, 0x71, 0x24, 0x85, 0x7c, 0x25, 0x3b, 0xa3, 0xa8, 0xdd,
+ 0xf6, 0xa5, 0xe3, 0xdd, 0xb2, 0xb5, 0x97, 0xc3, 0xb9, 0x6f, 0xdd, 0x31, 0xfe, 0x3f, 0x3b, 0xff, 0xb7, 0xbf, 0xe3, 0x58,
+ 0xcf, 0x6e, 0x45, 0xab, 0xb5, 0xd9, 0xaf, 0xe7, 0x22, 0x1f, 0xd2, 0xab, 0xa9, 0xd5, 0x0e, 0xfb, 0x7f, 0x1d, 0xcf, 0x59,
+ 0xe7, 0xa5, 0xf8, 0xef, 0x1d, 0x09, 0xe5, 0xc0, 0xfc, 0xe4, 0xf3, 0xd1, 0xbf, 0x32, 0xfe, 0xef, 0x98, 0x31, 0xab, 0xee,
+ 0x38, 0x72, 0xb6, 0xb4, 0xb2, 0xe3, 0xea, 0xfc, 0x3d, 0xf9, 0x44, 0x0b, 0xdf, 0xb5, 0x4f, 0xc2, 0x4f, 0x8d, 0xff, 0x37,
+ 0xf7, 0x18, 0xd9, 0x89, 0xff, 0xf3, 0x59, 0x9a, 0xf3, 0x87, 0x79, 0xbd, 0xdd, 0x4f, 0x1c, 0xed, 0x11, 0x9b, 0xf6, 0x38,
+ 0xdc, 0x8f, 0xe1, 0x9d, 0xd2, 0xb9, 0x7d, 0x78, 0x6a, 0x51, 0xba, 0x53, 0xfa, 0x56, 0xfb, 0x3f, 0x33, 0x0b, 0xf5, 0x74,
+ 0xfc, 0x77, 0xce, 0x86, 0xe6, 0x50, 0xeb, 0xb8, 0x3e, 0x9a, 0xe8, 0x9f, 0x1b, 0xed, 0xf8, 0xc4, 0x6a, 0xcb, 0xf0, 0x4e,
+ 0xff, 0xbf, 0xfe, 0xfb, 0x8b, 0x7f, 0xce, 0x66, 0xa5, 0x38, 0xab, 0xf5, 0x93, 0xc6, 0xff, 0xd7, 0xd4, 0xae, 0x51, 0x79,
+ 0x69, 0xfc, 0xff, 0x19, 0xaf, 0xff, 0x7b, 0x7f, 0x81, 0x75, 0x1d, 0x6e, 0x87, 0x9f, 0x2e, 0x3d, 0xdf, 0x63, 0xdc, 0x2b,
+ 0xcd, 0x2b, 0xed, 0xff, 0xdc, 0x48, 0xf4, 0xbd, 0xf8, 0xef, 0xea, 0x2f, 0xab, 0x09, 0x3a, 0xe7, 0x59, 0xde, 0x6d, 0xc3,
+ 0x6b, 0xbb, 0x38, 0xee, 0xfd, 0xda, 0x66, 0x76, 0x74, 0x50, 0x2b, 0xcd, 0xe1, 0xf1, 0xff, 0xee, 0x55, 0xae, 0x1c, 0xcf,
+ 0xa7, 0xc4, 0xbf, 0xbc, 0xea, 0xa7, 0xea, 0x8c, 0x4a, 0x1c, 0x3e, 0x15, 0xc3, 0xcf, 0xdf, 0x4d, 0x7b, 0xcf, 0xff, 0xd7,
+ 0xeb, 0xe8, 0xb5, 0xe7, 0xff, 0x3b, 0x2d, 0xc3, 0xd3, 0xcf, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xef, 0xb7, 0xfe, 0x6c, 0x9c, 0x99, 0xa6, 0x9e, 0xd5, 0x7b, 0x37, 0x2b, 0xc0, 0xde, 0x11, 0xa5, 0xb4, 0xf6,
+ 0x6c, 0x36, 0xb7, 0x75, 0xf7, 0xfa, 0xb4, 0x7a, 0x7e, 0xf0, 0x6c, 0xac, 0x3a, 0xac, 0xff, 0xba, 0xfc, 0xd4, 0x71, 0x9e,
+ 0xca, 0xc2, 0x55, 0xb9, 0x1f, 0x9e, 0xbb, 0x96, 0x69, 0xbf, 0xc2, 0xb3, 0xef, 0x51, 0xcd, 0x05, 0x9d, 0xa5, 0x1c, 0x10,
+ 0xab, 0x71, 0x96, 0xcd, 0x0c, 0xf5, 0xf5, 0xb5, 0x67, 0xb3, 0xb5, 0x4e, 0x6f, 0xe6, 0xea, 0x6c, 0xe4, 0x87, 0xae, 0x9f,
+ 0xa3, 0x9d, 0xd5, 0xa5, 0xdd, 0xc7, 0xb9, 0x7e, 0xc5, 0x3a, 0x72, 0x73, 0x67, 0xe3, 0xcc, 0x67, 0xf9, 0xcc, 0x64, 0x50,
+ 0x3b, 0xe5, 0x91, 0x75, 0xa5, 0xbd, 0x99, 0x0b, 0x56, 0x57, 0x34, 0x3e, 0xb7, 0xd6, 0xb6, 0xbe, 0x0a, 0x6c, 0x37, 0xbf,
+ 0xd5, 0x73, 0xfd, 0xb7, 0x6a, 0x5f, 0xe4, 0xd7, 0xa3, 0xcc, 0x07, 0xe4, 0x74, 0x38, 0xbb, 0x9a, 0xed, 0xcc, 0x5e, 0x23,
+ 0xe7, 0xbf, 0xe1, 0xde, 0xde, 0x21, 0x3b, 0x6b, 0x08, 0x53, 0xec, 0x51, 0x8d, 0x32, 0x1a, 0xdc, 0xc7, 0xe7, 0x6e, 0xf9,
+ 0x5c, 0x0e, 0xb8, 0x6b, 0x22, 0x33, 0x6d, 0x0a, 0xd9, 0x2f, 0x32, 0x58, 0xd7, 0xde, 0x5d, 0x56, 0xbb, 0x47, 0x67, 0xf2,
+ 0x96, 0xe7, 0xc0, 0x1d, 0x75, 0xbd, 0x98, 0x9b, 0xeb, 0x5a, 0x6e, 0x93, 0x53, 0x6c, 0x7b, 0x3b, 0x4b, 0x3a, 0xea, 0xe7,
+ 0x6a, 0x2f, 0x6f, 0xa6, 0x6c, 0x3d, 0xa3, 0xe1, 0x4c, 0xcf, 0xf2, 0x99, 0xf2, 0xf5, 0x5c, 0xe6, 0xb3, 0xd9, 0x6f, 0xf2,
+ 0x58, 0x59, 0xca, 0x77, 0xdb, 0x35, 0x91, 0x87, 0xff, 0xd4, 0x5d, 0xf3, 0x7c, 0x36, 0x8b, 0x4a, 0x0d, 0x5a, 0xcb, 0x91,
+ 0xf8, 0x5c, 0xc9, 0x6c, 0xae, 0x83, 0x13, 0x57, 0xeb, 0x2a, 0xde, 0x39, 0x9f, 0x11, 0xff, 0xb9, 0xbd, 0xe6, 0xd7, 0x56,
+ 0xdd, 0xd6, 0xdd, 0x2e, 0xce, 0xb4, 0x99, 0xf5, 0x7a, 0xa3, 0xfa, 0xb9, 0xb5, 0xac, 0x34, 0x73, 0xd9, 0x79, 0xae, 0xe9,
+ 0x91, 0x7e, 0x65, 0x8f, 0xca, 0x95, 0x4f, 0xad, 0xb4, 0x03, 0x4f, 0x95, 0x54, 0x46, 0x30, 0x4f, 0xc5, 0xff, 0x67, 0xb4,
+ 0xef, 0xb5, 0xdd, 0x0d, 0xc7, 0xe3, 0xff, 0x94, 0x7b, 0x45, 0xfd, 0x65, 0x29, 0xcf, 0xde, 0x74, 0xcc, 0x0b, 0xa5, 0xb5,
+ 0xec, 0x6a, 0x9a, 0x9f, 0xaf, 0xec, 0x66, 0xf7, 0xb9, 0xf1, 0x5f, 0xdd, 0x3b, 0xe6, 0xad, 0xf8, 0xcf, 0xc7, 0xb7, 0xff,
+ 0xeb, 0xbb, 0x9b, 0xfe, 0xf9, 0x19, 0x55, 0x4a, 0x3d, 0x8b, 0xce, 0xb2, 0xab, 0xb8, 0xef, 0xda, 0x6e, 0xaf, 0xf9, 0xc4,
+ 0xf8, 0x66, 0x36, 0x27, 0xf0, 0x93, 0xf1, 0x5f, 0xb9, 0x2a, 0xbd, 0x25, 0xbb, 0x33, 0x43, 0x6f, 0xb4, 0xff, 0xf3, 0xcf,
+ 0x0d, 0xde, 0x8a, 0xff, 0xea, 0xf3, 0xff, 0x99, 0xbd, 0x3c, 0x4f, 0xb4, 0x8c, 0x95, 0x96, 0xfc, 0xec, 0x3e, 0x09, 0x27,
+ 0xc6, 0x39, 0xa7, 0xdb, 0xff, 0xca, 0x78, 0xe4, 0x1a, 0xee, 0xfc, 0x7e, 0xba, 0xe4, 0xda, 0x9e, 0xf9, 0xfd, 0xb4, 0x19,
+ 0x99, 0xa7, 0xc6, 0xf7, 0x9f, 0xb5, 0xdf, 0xea, 0xf5, 0xda, 0xf3, 0xb4, 0x9f, 0x70, 0xac, 0x1d, 0x33, 0x00, 0xcf, 0x3f,
+ 0x73, 0xfc, 0xb4, 0x73, 0x57, 0xdd, 0x89, 0xe5, 0xb9, 0xef, 0xd3, 0x51, 0x3e, 0xf3, 0xbd, 0xe5, 0x4c, 0xe5, 0x6f, 0xfa,
+ 0xf5, 0xef, 0x67, 0xe5, 0x10, 0x1e, 0xff, 0x86, 0x76, 0xaf, 0xfc, 0xb9, 0xdf, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa9, 0xdf, 0xde, 0xd7, 0xd7, 0xbd, 0x57, 0xd7, 0x7c, 0xf7, 0x67, 0xe2, 0x8e, 0x35,
+ 0x3c, 0xd0, 0xb6, 0x16, 0x34, 0x93, 0xb9, 0xe0, 0xba, 0x63, 0x31, 0x5b, 0x99, 0x4d, 0x80, 0xf9, 0x36, 0xff, 0x8d, 0x75,
+ 0x7e, 0xd5, 0xcf, 0xcd, 0x30, 0xf3, 0x82, 0x55, 0x7c, 0x30, 0x1f, 0xff, 0x19, 0xe6, 0x32, 0xea, 0x2e, 0xbd, 0x26, 0xb2,
+ 0x0b, 0x5c, 0x85, 0xfc, 0x55, 0xd1, 0x47, 0x80, 0xa5, 0xf8, 0x9f, 0xc9, 0xc8, 0xfd, 0x49, 0xa5, 0x29, 0xef, 0x3e, 0x06,
+ 0xfc, 0x79, 0x94, 0xfd, 0xbd, 0xe2, 0x7f, 0x27, 0x7f, 0x3d, 0xf0, 0x7e, 0xfc, 0xa7, 0x58, 0x5a, 0xcf, 0x15, 0x0b, 0xfc,
+ 0xda, 0xfb, 0x9f, 0x99, 0xfd, 0x4f, 0x7b, 0xe9, 0xd5, 0xb0, 0xc7, 0x44, 0xf5, 0xa9, 0x24, 0xd0, 0xf1, 0x7c, 0x70, 0xa7,
+ 0xb4, 0xfe, 0x9b, 0x84, 0x99, 0xe7, 0x19, 0xae, 0x1c, 0x7c, 0xff, 0xe7, 0x92, 0xb5, 0xfa, 0xca, 0x19, 0x84, 0xef, 0xdf,
+ 0xef, 0x70, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x79, 0xff, 0xf9, 0xe7, 0x3c, 0x80, 0xf8, 0x07, 0xfe, 0xba, 0xf8, 0xff, 0x17 };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle cherryFontRecs[189] = {
+ { 4, 4, 5 , 15 },
+ { 17, 4, 3 , 10 },
+ { 28, 4, 5 , 2 },
+ { 41, 4, 10 , 10 },
+ { 59, 4, 7 , 11 },
+ { 74, 4, 7 , 10 },
+ { 89, 4, 8 , 10 },
+ { 105, 4, 1 , 2 },
+ { 114, 4, 3 , 10 },
+ { 125, 4, 3 , 10 },
+ { 136, 4, 3 , 3 },
+ { 147, 4, 7 , 7 },
+ { 162, 4, 2 , 2 },
+ { 172, 4, 6 , 3 },
+ { 186, 4, 1 , 1 },
+ { 195, 4, 4 , 10 },
+ { 207, 4, 5 , 8 },
+ { 220, 4, 5 , 8 },
+ { 233, 4, 5 , 8 },
+ { 246, 4, 5 , 8 },
+ { 259, 4, 5 , 8 },
+ { 272, 4, 5 , 8 },
+ { 285, 4, 5 , 8 },
+ { 298, 4, 5 , 8 },
+ { 311, 4, 5 , 8 },
+ { 324, 4, 5 , 8 },
+ { 337, 4, 3 , 10 },
+ { 348, 4, 3 , 12 },
+ { 359, 4, 6 , 7 },
+ { 373, 4, 6 , 4 },
+ { 387, 4, 6 , 7 },
+ { 401, 4, 5 , 10 },
+ { 414, 4, 8 , 10 },
+ { 430, 4, 7 , 9 },
+ { 445, 4, 7 , 9 },
+ { 460, 4, 6 , 9 },
+ { 474, 4, 6 , 9 },
+ { 488, 4, 7 , 9 },
+ { 4, 27, 6 , 9 },
+ { 18, 27, 6 , 9 },
+ { 32, 27, 7 , 9 },
+ { 47, 27, 3 , 9 },
+ { 58, 27, 6 , 9 },
+ { 72, 27, 7 , 9 },
+ { 87, 27, 7 , 9 },
+ { 102, 27, 11 , 9 },
+ { 121, 27, 8 , 9 },
+ { 137, 27, 6 , 9 },
+ { 151, 27, 6 , 9 },
+ { 165, 27, 7 , 9 },
+ { 180, 27, 7 , 9 },
+ { 195, 27, 6 , 9 },
+ { 209, 27, 7 , 9 },
+ { 224, 27, 8 , 9 },
+ { 240, 27, 9 , 9 },
+ { 257, 27, 11 , 9 },
+ { 276, 27, 7 , 9 },
+ { 291, 27, 7 , 9 },
+ { 306, 27, 7 , 9 },
+ { 321, 27, 3 , 9 },
+ { 332, 27, 4 , 10 },
+ { 344, 27, 3 , 9 },
+ { 355, 27, 3 , 3 },
+ { 366, 27, 7 , 2 },
+ { 381, 27, 2 , 2 },
+ { 391, 27, 6 , 6 },
+ { 405, 27, 6 , 9 },
+ { 419, 27, 6 , 6 },
+ { 433, 27, 6 , 9 },
+ { 447, 27, 6 , 6 },
+ { 461, 27, 5 , 9 },
+ { 474, 27, 5 , 9 },
+ { 487, 27, 7 , 9 },
+ { 4, 50, 3 , 7 },
+ { 15, 50, 3 , 8 },
+ { 26, 50, 6 , 9 },
+ { 40, 50, 4 , 9 },
+ { 52, 50, 11 , 6 },
+ { 71, 50, 7 , 6 },
+ { 86, 50, 5 , 6 },
+ { 99, 50, 6 , 8 },
+ { 113, 50, 6 , 8 },
+ { 127, 50, 5 , 6 },
+ { 140, 50, 5 , 6 },
+ { 153, 50, 5 , 9 },
+ { 166, 50, 7 , 6 },
+ { 181, 50, 7 , 6 },
+ { 196, 50, 11 , 6 },
+ { 215, 50, 7 , 6 },
+ { 230, 50, 7 , 8 },
+ { 245, 50, 6 , 6 },
+ { 259, 50, 5 , 9 },
+ { 272, 50, 1 , 9 },
+ { 281, 50, 5 , 9 },
+ { 294, 50, 7 , 3 },
+ { 309, 50, 3 , 10 },
+ { 320, 50, 7 , 10 },
+ { 335, 50, 7 , 10 },
+ { 350, 50, 6 , 9 },
+ { 364, 50, 7 , 9 },
+ { 379, 50, 6 , 12 },
+ { 393, 50, 7 , 11 },
+ { 408, 50, 5 , 9 },
+ { 421, 50, 5 , 5 },
+ { 434, 50, 4 , 5 },
+ { 446, 50, 6 , 7 },
+ { 460, 50, 6 , 3 },
+ { 474, 50, 5 , 5 },
+ { 487, 50, 6 , 1 },
+ { 4, 73, 3 , 3 },
+ { 15, 73, 7 , 10 },
+ { 30, 73, 3 , 5 },
+ { 41, 73, 3 , 5 },
+ { 52, 73, 7 , 12 },
+ { 67, 73, 6 , 8 },
+ { 81, 73, 7 , 9 },
+ { 96, 73, 2 , 3 },
+ { 106, 73, 6 , 9 },
+ { 120, 73, 3 , 5 },
+ { 131, 73, 3 , 5 },
+ { 142, 73, 6 , 7 },
+ { 156, 73, 13 , 9 },
+ { 177, 73, 10 , 6 },
+ { 195, 73, 7 , 11 },
+ { 210, 73, 5 , 10 },
+ { 223, 73, 7 , 12 },
+ { 238, 73, 7 , 12 },
+ { 253, 73, 7 , 12 },
+ { 268, 73, 7 , 12 },
+ { 283, 73, 7 , 11 },
+ { 298, 73, 7 , 11 },
+ { 313, 73, 12 , 9 },
+ { 333, 73, 6 , 11 },
+ { 347, 73, 7 , 12 },
+ { 362, 73, 7 , 12 },
+ { 377, 73, 7 , 12 },
+ { 392, 73, 7 , 11 },
+ { 407, 73, 3 , 12 },
+ { 418, 73, 3 , 12 },
+ { 429, 73, 3 , 12 },
+ { 440, 73, 3 , 11 },
+ { 451, 73, 7 , 9 },
+ { 466, 73, 8 , 12 },
+ { 482, 73, 6 , 12 },
+ { 496, 73, 6 , 12 },
+ { 4, 96, 6 , 12 },
+ { 18, 96, 6 , 12 },
+ { 32, 96, 6 , 11 },
+ { 46, 96, 5 , 5 },
+ { 59, 96, 8 , 9 },
+ { 75, 96, 8 , 12 },
+ { 91, 96, 8 , 12 },
+ { 107, 96, 8 , 12 },
+ { 123, 96, 8 , 11 },
+ { 139, 96, 7 , 12 },
+ { 154, 96, 7 , 9 },
+ { 169, 96, 8 , 9 },
+ { 185, 96, 6 , 9 },
+ { 199, 96, 6 , 9 },
+ { 213, 96, 6 , 9 },
+ { 227, 96, 6 , 9 },
+ { 241, 96, 6 , 8 },
+ { 255, 96, 6 , 10 },
+ { 269, 96, 10 , 6 },
+ { 287, 96, 6 , 8 },
+ { 301, 96, 6 , 9 },
+ { 315, 96, 6 , 9 },
+ { 329, 96, 6 , 9 },
+ { 343, 96, 6 , 8 },
+ { 357, 96, 3 , 10 },
+ { 368, 96, 3 , 10 },
+ { 379, 96, 3 , 10 },
+ { 390, 96, 3 , 9 },
+ { 401, 96, 6 , 10 },
+ { 415, 96, 7 , 9 },
+ { 430, 96, 5 , 9 },
+ { 443, 96, 5 , 9 },
+ { 456, 96, 5 , 9 },
+ { 469, 96, 5 , 9 },
+ { 482, 96, 5 , 8 },
+ { 495, 96, 7 , 9 },
+ { 4, 119, 8 , 8 },
+ { 20, 119, 7 , 9 },
+ { 35, 119, 7 , 9 },
+ { 50, 119, 7 , 9 },
+ { 65, 119, 7 , 8 },
+ { 80, 119, 7 , 11 },
+ { 95, 119, 5 , 8 },
+ { 108, 119, 7 , 10 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo cherryFontGlyphs[189] = {
+ { 32, 0, 12, 5, { 0 }},
+ { 33, 0, 2, 4, { 0 }},
+ { 34, 0, 2, 6, { 0 }},
+ { 35, 0, 2, 11, { 0 }},
+ { 36, 0, 2, 8, { 0 }},
+ { 37, 0, 2, 8, { 0 }},
+ { 38, 0, 2, 9, { 0 }},
+ { 39, 0, 2, 2, { 0 }},
+ { 40, 0, 2, 4, { 0 }},
+ { 41, 0, 2, 4, { 0 }},
+ { 42, 0, 2, 4, { 0 }},
+ { 43, 0, 4, 8, { 0 }},
+ { 44, 0, 11, 3, { 0 }},
+ { 45, 0, 6, 7, { 0 }},
+ { 46, 0, 11, 2, { 0 }},
+ { 47, 0, 2, 5, { 0 }},
+ { 48, 0, 4, 6, { 0 }},
+ { 49, 0, 4, 6, { 0 }},
+ { 50, 0, 4, 6, { 0 }},
+ { 51, 0, 4, 6, { 0 }},
+ { 52, 0, 4, 6, { 0 }},
+ { 53, 0, 4, 6, { 0 }},
+ { 54, 0, 4, 6, { 0 }},
+ { 55, 0, 4, 6, { 0 }},
+ { 56, 0, 4, 6, { 0 }},
+ { 57, 0, 4, 6, { 0 }},
+ { 58, 0, 2, 4, { 0 }},
+ { 59, 0, 2, 4, { 0 }},
+ { 60, 0, 4, 7, { 0 }},
+ { 61, 0, 5, 7, { 0 }},
+ { 62, 0, 4, 7, { 0 }},
+ { 63, 0, 2, 6, { 0 }},
+ { 64, 0, 2, 9, { 0 }},
+ { 65, 0, 3, 8, { 0 }},
+ { 66, 0, 3, 8, { 0 }},
+ { 67, 0, 3, 7, { 0 }},
+ { 68, 0, 3, 7, { 0 }},
+ { 69, 0, 3, 8, { 0 }},
+ { 70, 0, 3, 7, { 0 }},
+ { 71, 0, 3, 7, { 0 }},
+ { 72, 0, 3, 8, { 0 }},
+ { 73, 0, 3, 4, { 0 }},
+ { 74, 0, 3, 7, { 0 }},
+ { 75, 0, 3, 8, { 0 }},
+ { 76, 0, 3, 8, { 0 }},
+ { 77, 0, 3, 12, { 0 }},
+ { 78, 0, 3, 9, { 0 }},
+ { 79, 0, 3, 7, { 0 }},
+ { 80, 0, 3, 7, { 0 }},
+ { 81, 0, 3, 8, { 0 }},
+ { 82, 0, 3, 8, { 0 }},
+ { 83, 0, 3, 7, { 0 }},
+ { 84, 0, 3, 8, { 0 }},
+ { 85, 0, 3, 9, { 0 }},
+ { 86, 0, 3, 10, { 0 }},
+ { 87, 0, 3, 12, { 0 }},
+ { 88, 0, 3, 8, { 0 }},
+ { 89, 0, 3, 8, { 0 }},
+ { 90, 0, 3, 8, { 0 }},
+ { 91, 0, 3, 4, { 0 }},
+ { 92, 0, 2, 5, { 0 }},
+ { 93, 0, 3, 4, { 0 }},
+ { 94, 0, 3, 4, { 0 }},
+ { 95, 0, 10, 8, { 0 }},
+ { 96, 0, 2, 3, { 0 }},
+ { 97, 0, 6, 7, { 0 }},
+ { 98, 0, 3, 7, { 0 }},
+ { 99, 0, 6, 7, { 0 }},
+ { 100, 0, 3, 7, { 0 }},
+ { 101, 0, 6, 7, { 0 }},
+ { 102, 0, 3, 6, { 0 }},
+ { 103, 0, 5, 6, { 0 }},
+ { 104, 0, 3, 8, { 0 }},
+ { 105, 0, 5, 4, { 0 }},
+ { 106, 0, 5, 4, { 0 }},
+ { 107, 0, 3, 7, { 0 }},
+ { 108, 0, 3, 5, { 0 }},
+ { 109, 0, 6, 12, { 0 }},
+ { 110, 0, 6, 8, { 0 }},
+ { 111, 0, 6, 6, { 0 }},
+ { 112, 0, 6, 7, { 0 }},
+ { 113, 0, 6, 7, { 0 }},
+ { 114, 0, 6, 6, { 0 }},
+ { 115, 0, 6, 6, { 0 }},
+ { 116, 0, 3, 6, { 0 }},
+ { 117, 0, 6, 8, { 0 }},
+ { 118, 0, 6, 8, { 0 }},
+ { 119, 0, 6, 12, { 0 }},
+ { 120, 0, 6, 8, { 0 }},
+ { 121, 0, 6, 8, { 0 }},
+ { 122, 0, 6, 7, { 0 }},
+ { 123, 0, 3, 6, { 0 }},
+ { 124, 0, 3, 2, { 0 }},
+ { 125, 0, 3, 6, { 0 }},
+ { 126, 0, 6, 8, { 0 }},
+ { 161, 0, 4, 4, { 0 }},
+ { 162, 0, 4, 8, { 0 }},
+ { 163, 0, 2, 8, { 0 }},
+ { 8364, 0, 3, 7, { 0 }},
+ { 165, 0, 3, 8, { 0 }},
+ { 352, 0, 0, 7, { 0 }},
+ { 167, 0, 2, 8, { 0 }},
+ { 353, 0, 3, 6, { 0 }},
+ { 169, 0, 1, 6, { 0 }},
+ { 170, 0, 2, 5, { 0 }},
+ { 171, 0, 5, 7, { 0 }},
+ { 172, 0, 6, 7, { 0 }},
+ { 174, 0, 1, 6, { 0 }},
+ { 175, 0, 2, 7, { 0 }},
+ { 176, 0, 2, 4, { 0 }},
+ { 177, 0, 3, 8, { 0 }},
+ { 178, 0, 2, 4, { 0 }},
+ { 179, 0, 2, 4, { 0 }},
+ { 381, 0, 0, 8, { 0 }},
+ { 181, 0, 6, 7, { 0 }},
+ { 182, 0, 3, 8, { 0 }},
+ { 183, 0, 6, 3, { 0 }},
+ { 382, 0, 3, 7, { 0 }},
+ { 185, 0, 2, 4, { 0 }},
+ { 186, 0, 2, 4, { 0 }},
+ { 187, 0, 5, 7, { 0 }},
+ { 338, 0, 3, 14, { 0 }},
+ { 339, 0, 6, 11, { 0 }},
+ { 376, 0, 1, 8, { 0 }},
+ { 191, 0, 4, 6, { 0 }},
+ { 192, 0, 0, 8, { 0 }},
+ { 193, 0, 0, 8, { 0 }},
+ { 194, 0, 0, 8, { 0 }},
+ { 195, 0, 0, 8, { 0 }},
+ { 196, 0, 1, 8, { 0 }},
+ { 197, 0, 1, 8, { 0 }},
+ { 198, 0, 3, 13, { 0 }},
+ { 199, 0, 3, 7, { 0 }},
+ { 200, 0, 0, 8, { 0 }},
+ { 201, 0, 0, 8, { 0 }},
+ { 202, 0, 0, 8, { 0 }},
+ { 203, 0, 1, 8, { 0 }},
+ { 204, 0, 0, 4, { 0 }},
+ { 205, 0, 0, 4, { 0 }},
+ { 206, 0, 0, 4, { 0 }},
+ { 207, 0, 1, 4, { 0 }},
+ { 208, 0, 3, 8, { 0 }},
+ { 209, 0, 0, 9, { 0 }},
+ { 210, 0, 0, 7, { 0 }},
+ { 211, 0, 0, 7, { 0 }},
+ { 212, 0, 0, 7, { 0 }},
+ { 213, 0, 0, 7, { 0 }},
+ { 214, 0, 1, 7, { 0 }},
+ { 215, 1, 5, 7, { 0 }},
+ { 216, 0, 3, 9, { 0 }},
+ { 217, 0, 0, 9, { 0 }},
+ { 218, 0, 0, 9, { 0 }},
+ { 219, 0, 0, 9, { 0 }},
+ { 220, 0, 1, 9, { 0 }},
+ { 221, 0, 0, 8, { 0 }},
+ { 222, 0, 2, 8, { 0 }},
+ { 223, 0, 3, 9, { 0 }},
+ { 224, 0, 3, 7, { 0 }},
+ { 225, 0, 3, 7, { 0 }},
+ { 226, 0, 3, 7, { 0 }},
+ { 227, 0, 3, 7, { 0 }},
+ { 228, 0, 4, 7, { 0 }},
+ { 229, 0, 2, 7, { 0 }},
+ { 230, 0, 6, 11, { 0 }},
+ { 231, 0, 6, 7, { 0 }},
+ { 232, 0, 3, 7, { 0 }},
+ { 233, 0, 3, 7, { 0 }},
+ { 234, 0, 3, 7, { 0 }},
+ { 235, 0, 4, 7, { 0 }},
+ { 236, 0, 2, 4, { 0 }},
+ { 237, 0, 2, 4, { 0 }},
+ { 238, 0, 2, 4, { 0 }},
+ { 239, 0, 3, 4, { 0 }},
+ { 240, 0, 2, 7, { 0 }},
+ { 241, 0, 3, 8, { 0 }},
+ { 242, 0, 3, 6, { 0 }},
+ { 243, 0, 3, 6, { 0 }},
+ { 244, 0, 3, 6, { 0 }},
+ { 245, 0, 3, 6, { 0 }},
+ { 246, 0, 4, 6, { 0 }},
+ { 247, 0, 3, 8, { 0 }},
+ { 248, 0, 4, 9, { 0 }},
+ { 249, 0, 3, 8, { 0 }},
+ { 250, 0, 3, 8, { 0 }},
+ { 251, 0, 3, 8, { 0 }},
+ { 252, 0, 4, 8, { 0 }},
+ { 253, 0, 3, 8, { 0 }},
+ { 254, 0, 4, 6, { 0 }},
+ { 255, 0, 4, 8, { 0 }},
+};
+
+// Style loading function: Cherry
+static void GuiLoadStyleCherry(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < CHERRY_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(cherryStyleProps[i].controlId, cherryStyleProps[i].propertyId, cherryStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int cherryFontDataSize = 0;
+ unsigned char *data = DecompressData(cherryFontData, CHERRY_STYLE_FONT_ATLAS_COMP_SIZE, &cherryFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 15;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, cherryFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, cherryFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_cyber.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_cyber.h
new file mode 100644
index 0000000000..e224e4d920
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_cyber.h
@@ -0,0 +1,591 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleCyber(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define CYBER_STYLE_PROPS_COUNT 17
+
+// Custom style name: Cyber
+static const GuiStyleProp cyberStyleProps[CYBER_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0x2f7486ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x024658ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0x51bfd3ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0x82cde0ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0x3299b4ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0xb6e1eaff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0xeb7630ff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0xffbc51ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0xd86f36ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x134b5aff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x02313dff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x17505fff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x0000000e }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0x81c0d0ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x00222bff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000015 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "Kyrou 7 Wide.ttf" (size: 14, spacing: 0)
+
+#define CYBER_STYLE_FONT_ATLAS_COMP_SIZE 2286
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char cyberFontData[CYBER_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0x81, 0x6e, 0xdb, 0x36, 0x10, 0x06, 0x60, 0x21, 0xef, 0xff, 0xc6, 0x99, 0xf6, 0x0f, 0xe8, 0xd0, 0x2d, 0x45, 0x6b,
+ 0x89, 0x3c, 0x92, 0xb2, 0xec, 0x7c, 0xfd, 0x80, 0x61, 0x88, 0x62, 0x5b, 0xa2, 0x78, 0xe4, 0x49, 0x0a, 0xcf, 0xd9, 0x00,
+ 0x00, 0x00, 0x00, 0x26, 0xcb, 0xc5, 0x9f, 0x96, 0xe6, 0x9f, 0xce, 0x3b, 0xa2, 0x9f, 0xff, 0x9e, 0x7b, 0xec, 0xfa, 0x57,
+ 0x7f, 0xbb, 0xe7, 0xe1, 0xb9, 0xd3, 0x9e, 0x5f, 0x7f, 0x92, 0xc3, 0xdf, 0x4d, 0xa9, 0x75, 0x73, 0x7a, 0xc6, 0x8e, 0xcf,
+ 0x4c, 0x5f, 0xbc, 0x3d, 0xde, 0x87, 0x74, 0xbf, 0x62, 0xe5, 0xc8, 0xf8, 0xf3, 0xdf, 0xde, 0xd5, 0xdf, 0x8f, 0x7b, 0x71,
+ 0x5b, 0x2f, 0xcf, 0xc9, 0x1e, 0xa5, 0xe1, 0x37, 0xce, 0x5e, 0xbf, 0x0d, 0xec, 0xfd, 0x7e, 0xe9, 0x5c, 0x94, 0xd3, 0x31,
+ 0x63, 0x5b, 0x70, 0x34, 0x19, 0x3c, 0x97, 0x19, 0x1e, 0xd1, 0xda, 0xe3, 0xff, 0xac, 0x5f, 0xe4, 0xb7, 0xff, 0x6e, 0xa5,
+ 0x48, 0xcb, 0xc2, 0xf8, 0xdf, 0xba, 0xc6, 0x97, 0xf5, 0x79, 0x51, 0x1a, 0x22, 0xbd, 0xff, 0x35, 0xad, 0x47, 0x5b, 0x1b,
+ 0xf1, 0xd2, 0xfc, 0xbb, 0x29, 0x1d, 0xf1, 0xac, 0x33, 0xd2, 0x3b, 0x72, 0x9e, 0xb5, 0xc6, 0x8a, 0xa3, 0xf9, 0xfa, 0xb3,
+ 0xcf, 0xc1, 0xd7, 0xef, 0xcb, 0xc7, 0xc8, 0xbd, 0xa1, 0xa5, 0xf6, 0xf2, 0x27, 0xa6, 0x90, 0xcd, 0xcd, 0x3a, 0xfb, 0xab,
+ 0xf3, 0xc2, 0x94, 0x63, 0x29, 0x43, 0x67, 0xef, 0xf8, 0x73, 0xab, 0xf3, 0xf7, 0xda, 0x11, 0xaf, 0x3f, 0xd7, 0xcf, 0xa4,
+ 0xd1, 0xbc, 0x36, 0x9a, 0xfd, 0x6c, 0xa9, 0x2c, 0x88, 0xdf, 0x79, 0x63, 0xf1, 0xcc, 0x1c, 0x69, 0x24, 0xef, 0x3c, 0xda,
+ 0xf6, 0xf9, 0x43, 0xfb, 0x5e, 0xbd, 0xca, 0xfc, 0x9f, 0x81, 0xf3, 0x97, 0x52, 0x3b, 0x9f, 0xe5, 0x94, 0xad, 0x47, 0x7c,
+ 0xfc, 0xe9, 0x7b, 0xe1, 0x98, 0x3f, 0xb2, 0xff, 0x67, 0x9b, 0x92, 0xd3, 0x66, 0xe2, 0xb9, 0x4c, 0xf7, 0xb5, 0xd2, 0xbf,
+ 0x71, 0x5b, 0xcf, 0x99, 0x93, 0xbf, 0x7f, 0xd8, 0x17, 0xe7, 0x62, 0x57, 0xc4, 0xff, 0xff, 0xa3, 0x58, 0x06, 0x22, 0x36,
+ 0x83, 0x33, 0xcc, 0xdc, 0xeb, 0xff, 0x71, 0xfb, 0xd0, 0xf9, 0xcb, 0xf4, 0xab, 0xda, 0xff, 0xa3, 0x37, 0xa5, 0xfc, 0x21,
+ 0xd3, 0x46, 0xd9, 0x7d, 0xe1, 0xbd, 0xe4, 0x2c, 0xca, 0xd2, 0x1e, 0xcd, 0xff, 0xd7, 0x65, 0x3b, 0x6b, 0xae, 0x96, 0x7a,
+ 0xee, 0x9d, 0x56, 0xaf, 0xff, 0xd3, 0x38, 0xba, 0xac, 0x8b, 0xff, 0xeb, 0xfd, 0x35, 0x78, 0xfe, 0x72, 0xf1, 0xf5, 0xf9,
+ 0x9c, 0x2b, 0xf4, 0x7a, 0xc6, 0xb3, 0xf6, 0xfa, 0xff, 0xaa, 0x11, 0x63, 0x45, 0xfe, 0x9f, 0x17, 0xcf, 0xff, 0x7b, 0xee,
+ 0xff, 0xe7, 0x4d, 0xe2, 0x3f, 0xc3, 0x4f, 0xa4, 0x32, 0xfd, 0xfe, 0x7c, 0x5b, 0xb6, 0x3b, 0xf6, 0x7c, 0x21, 0x43, 0x47,
+ 0x3c, 0xeb, 0x5e, 0x4c, 0x26, 0xfd, 0x6e, 0x1a, 0x67, 0xc5, 0xda, 0xfd, 0xdd, 0xe7, 0xde, 0xff, 0xf7, 0xfc, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9e, 0xd5, 0x9d, 0xb9, 0xe0, 0x75, 0x95,
+ 0x55, 0xb4, 0x23, 0xab, 0x6e, 0x47, 0xd6, 0xec, 0x56, 0x5f, 0x79, 0x5e, 0x87, 0xa8, 0xbe, 0xce, 0xb8, 0x7d, 0x95, 0x73,
+ 0xdf, 0xba, 0xe1, 0xb1, 0xea, 0x28, 0x39, 0x5d, 0x47, 0xdf, 0x56, 0x8f, 0xe0, 0xbc, 0x76, 0xeb, 0x59, 0x25, 0xab, 0xf5,
+ 0xb5, 0x5f, 0x57, 0xd6, 0xa6, 0x4c, 0xb9, 0x05, 0x7b, 0x56, 0xbf, 0xa7, 0xab, 0x3e, 0x41, 0x75, 0x1d, 0xfa, 0x75, 0x55,
+ 0x01, 0xc7, 0x57, 0xc8, 0x1f, 0xbf, 0xf3, 0xbe, 0xfc, 0x28, 0xda, 0xf7, 0x38, 0x13, 0xce, 0xd9, 0x8a, 0xf8, 0xcf, 0x61,
+ 0x45, 0x80, 0x5c, 0x58, 0xdb, 0x75, 0x5d, 0x25, 0xdc, 0x75, 0x95, 0x76, 0xce, 0xe3, 0xbf, 0xbd, 0x66, 0x73, 0x26, 0x47,
+ 0x6b, 0xca, 0xd1, 0x33, 0x6b, 0x04, 0xa8, 0x8c, 0x5b, 0x33, 0xe2, 0xbf, 0x9a, 0x3b, 0xbc, 0x76, 0xfc, 0x57, 0xeb, 0x89,
+ 0xe5, 0xe0, 0xbc, 0xa7, 0xb1, 0x6f, 0xdf, 0x61, 0xfb, 0x76, 0xd3, 0xf8, 0x3f, 0x8f, 0xa9, 0x0c, 0x57, 0x29, 0x9e, 0xd7,
+ 0x9f, 0xe6, 0xd9, 0x9b, 0xa2, 0xb4, 0x56, 0xd3, 0x73, 0x2f, 0x8f, 0x2c, 0xab, 0xf2, 0xff, 0x9c, 0x5c, 0x79, 0xa4, 0x29,
+ 0x97, 0x9d, 0x3b, 0xc6, 0xb6, 0x8e, 0x5a, 0x8f, 0x2b, 0x8a, 0x9d, 0xd5, 0x2b, 0x7c, 0xfe, 0xfc, 0x3e, 0x56, 0x4f, 0xf9,
+ 0x9a, 0xf8, 0x1f, 0x8f, 0xc4, 0x3c, 0x65, 0xce, 0x9a, 0x73, 0x6f, 0x22, 0xc5, 0x79, 0x6b, 0xcd, 0x6b, 0xaf, 0x98, 0xff,
+ 0xf3, 0x52, 0xf3, 0x7f, 0xcb, 0xf5, 0x7f, 0x26, 0x5c, 0xbd, 0xd6, 0x5a, 0x6d, 0x6f, 0x3e, 0x97, 0x2b, 0xf2, 0xff, 0x96,
+ 0x99, 0x7d, 0x7c, 0xfe, 0x1f, 0xd9, 0x9a, 0xe6, 0x59, 0xf8, 0xfa, 0xf8, 0x6f, 0x3b, 0xa6, 0x5c, 0xfa, 0xda, 0xd7, 0x8b,
+ 0xff, 0xdc, 0xe2, 0xfe, 0x5f, 0x16, 0xd6, 0x66, 0xce, 0x94, 0xd1, 0x6d, 0x4d, 0xfc, 0xb7, 0xd5, 0x43, 0x1f, 0xb9, 0xfe,
+ 0x1f, 0x8b, 0xf0, 0xf3, 0x08, 0xf8, 0x4b, 0xfc, 0x4f, 0xca, 0xff, 0x67, 0xbd, 0xba, 0xff, 0x5e, 0xc9, 0xc8, 0x0c, 0xda,
+ 0x7e, 0x4c, 0x99, 0x9e, 0x7f, 0x8f, 0xd6, 0xf6, 0x5d, 0x9d, 0xff, 0xcf, 0x7a, 0xfd, 0x56, 0x3e, 0xef, 0xe7, 0x5b, 0xc6,
+ 0x7a, 0xe5, 0xf6, 0x84, 0x6f, 0x73, 0x58, 0xfd, 0x7c, 0xcf, 0x77, 0x94, 0xbe, 0xdf, 0x53, 0x6c, 0x6d, 0x70, 0xef, 0xe7,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x5e, 0x65, 0x75, 0xbf, 0x15,
+ 0x53, 0x69, 0x58, 0x1f, 0xda, 0x52, 0x3f, 0xf3, 0xb8, 0xfa, 0xe6, 0xa3, 0x1a, 0x12, 0x7b, 0x53, 0xed, 0xcd, 0x59, 0xad,
+ 0xd9, 0x5a, 0x07, 0x61, 0xb4, 0x4e, 0x67, 0xe5, 0xdd, 0x5b, 0x5a, 0xf9, 0x7c, 0xcd, 0x63, 0x4e, 0xd6, 0x01, 0x6f, 0x13,
+ 0x7b, 0xe0, 0xf9, 0x9a, 0xe7, 0x0c, 0xd4, 0x5c, 0x18, 0xa9, 0x22, 0x98, 0x85, 0x2b, 0x4c, 0x53, 0x6a, 0x95, 0xf6, 0x0a,
+ 0x1c, 0xad, 0x5b, 0x33, 0xa9, 0xca, 0xc3, 0xea, 0x7e, 0x3d, 0x63, 0x6b, 0x7f, 0x1d, 0x85, 0x67, 0xc4, 0xff, 0x71, 0x0f,
+ 0xc9, 0xe4, 0xb3, 0xdd, 0xf7, 0xd3, 0xb3, 0xd8, 0x7f, 0x5c, 0x5b, 0xf9, 0xa3, 0xb1, 0xdf, 0xf4, 0x6c, 0xcf, 0xf0, 0x59,
+ 0xce, 0x60, 0x25, 0x84, 0xbd, 0x73, 0xbe, 0x69, 0x8f, 0xfe, 0xb1, 0x9e, 0xb7, 0x6e, 0x05, 0xfc, 0x3b, 0xc5, 0xff, 0x56,
+ 0xac, 0x58, 0xb8, 0x3a, 0xfe, 0xb7, 0xa6, 0x7d, 0xca, 0xb4, 0x23, 0x9a, 0x57, 0x7d, 0xfb, 0xa3, 0x3b, 0xc7, 0x9a, 0x53,
+ 0xcb, 0x2a, 0x17, 0xd6, 0x7a, 0x48, 0x47, 0xef, 0xaa, 0x8e, 0x00, 0x29, 0xce, 0xff, 0xfd, 0x2d, 0x3d, 0x2b, 0xc7, 0x78,
+ 0xcd, 0xf8, 0xaf, 0xb5, 0x66, 0x06, 0xce, 0xf0, 0xda, 0xf9, 0x7f, 0x66, 0xe5, 0xee, 0x4a, 0x74, 0xec, 0x0f, 0xde, 0x65,
+ 0x2f, 0xcf, 0xce, 0xf5, 0xab, 0x83, 0xad, 0xe9, 0x3b, 0x19, 0xf6, 0xee, 0xd7, 0xe5, 0x97, 0xf8, 0xcc, 0x92, 0x6b, 0xf4,
+ 0x1c, 0xb4, 0x70, 0xb5, 0x1a, 0x69, 0x6f, 0xfc, 0xe7, 0xd2, 0xf9, 0x7f, 0x6b, 0xfc, 0xf6, 0x8c, 0xad, 0x74, 0xbe, 0xb6,
+ 0xe2, 0xbb, 0xd6, 0x5f, 0x99, 0xd3, 0x1e, 0xbb, 0xa6, 0x1e, 0xed, 0xcc, 0x6f, 0xe8, 0xc8, 0x84, 0x7e, 0x9b, 0x93, 0x4f,
+ 0x48, 0x31, 0x07, 0xef, 0xcd, 0xfc, 0x7b, 0xc6, 0xd9, 0x74, 0xdc, 0x19, 0xc8, 0xc1, 0x18, 0x98, 0x45, 0x39, 0xf8, 0xcc,
+ 0x79, 0x30, 0x53, 0xf3, 0xb5, 0x75, 0x77, 0x17, 0x57, 0x66, 0x74, 0xd7, 0xbc, 0xdb, 0xb3, 0xda, 0xe4, 0xca, 0xf9, 0x3f,
+ 0xdd, 0xd9, 0xee, 0xc8, 0xfc, 0x9f, 0xe1, 0x3a, 0x99, 0x67, 0xb9, 0xdf, 0x76, 0xbb, 0xf9, 0xbf, 0x2d, 0x36, 0x73, 0x79,
+ 0xfe, 0x2f, 0xfe, 0xaf, 0x7e, 0xd2, 0xb2, 0xbd, 0x44, 0xfc, 0xaf, 0xbd, 0xfe, 0x9f, 0x33, 0x82, 0x54, 0x67, 0xd9, 0x6d,
+ 0xf1, 0x33, 0x82, 0xfa, 0xab, 0xd6, 0xc5, 0xff, 0xf6, 0xad, 0xaa, 0x35, 0xbe, 0x5b, 0x6d, 0xca, 0x67, 0xc4, 0x7f, 0x4b,
+ 0xfe, 0x9f, 0xe2, 0xfd, 0xff, 0xf6, 0x6f, 0xd8, 0x4a, 0x57, 0xce, 0xd2, 0x9e, 0x77, 0xbc, 0x67, 0x8f, 0xe0, 0x9d, 0x47,
+ 0xb4, 0xb1, 0xe7, 0xff, 0x77, 0x1b, 0x83, 0xc7, 0xbe, 0x53, 0xe5, 0x3b, 0xf7, 0x7f, 0x75, 0x97, 0xf1, 0xd7, 0x72, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x5e, 0xb7, 0x90, 0x4b, 0xd7, 0xcb, 0x57, 0xeb,
+ 0xd6, 0xf5, 0xaf, 0x58, 0xcd, 0xa4, 0x96, 0xc9, 0xa4, 0xb3, 0xb5, 0x37, 0xac, 0xce, 0xcf, 0x60, 0xbb, 0x67, 0xf8, 0x77,
+ 0xd2, 0xb0, 0x22, 0x2c, 0xa5, 0x33, 0x7c, 0xbf, 0x75, 0xab, 0x23, 0xab, 0x06, 0x33, 0xb5, 0x75, 0x67, 0x9e, 0xef, 0x9c,
+ 0x56, 0xc3, 0xfe, 0x6a, 0x2f, 0x56, 0x5f, 0x49, 0x69, 0xc5, 0x64, 0xca, 0xb5, 0x09, 0x7a, 0xc7, 0xbb, 0x74, 0xb6, 0x59,
+ 0xef, 0xb9, 0xfe, 0xda, 0xc6, 0xad, 0x55, 0x66, 0xbe, 0x6e, 0xdf, 0xcb, 0x3d, 0xfb, 0x73, 0xa8, 0xdf, 0xa7, 0x3c, 0x42,
+ 0x6f, 0x53, 0xea, 0x7a, 0xb7, 0x54, 0xe3, 0xd8, 0x1b, 0xd6, 0xd0, 0x67, 0xb8, 0x36, 0x58, 0xca, 0xed, 0x30, 0xb3, 0xe7,
+ 0x8d, 0x7d, 0xda, 0xd9, 0x5a, 0xed, 0x0c, 0xcc, 0xa0, 0x29, 0xd6, 0xbf, 0xcb, 0x60, 0x65, 0x88, 0x1c, 0xac, 0xf1, 0xce,
+ 0xb2, 0xf5, 0xed, 0xe9, 0x8c, 0xfe, 0xf6, 0xe3, 0x4d, 0x73, 0x9b, 0xb6, 0xd5, 0xab, 0xfe, 0xb8, 0x7d, 0x56, 0xba, 0x97,
+ 0x66, 0x9b, 0x5a, 0x9b, 0x5e, 0x9d, 0x6f, 0xdc, 0xbd, 0xb6, 0xc7, 0x79, 0xf5, 0xb1, 0xf5, 0xd7, 0x06, 0x95, 0x5a, 0x2c,
+ 0xf3, 0xe2, 0x3f, 0xdd, 0x15, 0xa5, 0xf6, 0xa1, 0xab, 0x8e, 0xbe, 0xf8, 0x6f, 0x7b, 0xdf, 0x94, 0xe6, 0xff, 0xb3, 0xf8,
+ 0x5b, 0xbb, 0x7d, 0xb4, 0xda, 0x7e, 0x35, 0xfe, 0xfb, 0xfb, 0x40, 0x16, 0xd4, 0x48, 0x3d, 0xcb, 0x4a, 0x2a, 0x5b, 0xc6,
+ 0xaf, 0xb1, 0xd7, 0xc5, 0xff, 0x51, 0xeb, 0x8d, 0xe6, 0x1b, 0xb3, 0xe6, 0xff, 0x0c, 0xe7, 0xff, 0xad, 0x7d, 0x35, 0xcd,
+ 0xdf, 0x2f, 0xd4, 0x92, 0x53, 0x1d, 0x55, 0x77, 0xde, 0x4f, 0xbf, 0x29, 0x63, 0x2b, 0x7e, 0x1b, 0xc6, 0xea, 0xed, 0x3d,
+ 0xe3, 0xf6, 0x9c, 0xca, 0x9d, 0xd7, 0x6f, 0x9d, 0x31, 0xf6, 0xdd, 0x23, 0xfe, 0xb3, 0x28, 0xd3, 0xc9, 0x50, 0xbb, 0xa6,
+ 0x6b, 0xdf, 0xaf, 0xb9, 0xbb, 0x94, 0xcb, 0xaa, 0x8a, 0xce, 0xf9, 0x2e, 0x8c, 0x75, 0xdb, 0x5b, 0xc7, 0xc1, 0xfd, 0x82,
+ 0xf9, 0x7f, 0xe5, 0x1d, 0xd0, 0x7a, 0x55, 0xf8, 0x6b, 0xe2, 0xff, 0x59, 0xd7, 0x46, 0xeb, 0xfa, 0x76, 0x4f, 0xfc, 0xe7,
+ 0xe2, 0xe3, 0xb8, 0x3e, 0xfe, 0x3f, 0xfe, 0x18, 0x41, 0xe9, 0xc8, 0x6b, 0xd7, 0x6c, 0x9f, 0x39, 0xbe, 0x8c, 0x8e, 0x75,
+ 0xcf, 0xc9, 0xff, 0x9f, 0x1f, 0xff, 0x77, 0xbe, 0x43, 0x91, 0x37, 0xba, 0x43, 0x93, 0x5f, 0xee, 0xb2, 0x5c, 0xf7, 0x3c,
+ 0xb6, 0x7e, 0xfd, 0xfd, 0x5a, 0xdb, 0xc7, 0xee, 0xff, 0x7f, 0xdf, 0xfc, 0xff, 0xce, 0x7f, 0xb3, 0xe0, 0xef, 0x36, 0x56,
+ 0xb6, 0xd3, 0xfd, 0xe3, 0x7b, 0xfe, 0xc8, 0xfc, 0xe8, 0x6e, 0xc8, 0xf7, 0xcd, 0xff, 0xef, 0xff, 0x17, 0x4b, 0xaa, 0xad,
+ 0x5e, 0x71, 0x4d, 0x72, 0xc7, 0xfb, 0x7b, 0xb3, 0xfb, 0xfb, 0xd1, 0xbd, 0xd0, 0x55, 0xf9, 0xff, 0x76, 0xf3, 0xfb, 0xff,
+ 0xf0, 0x9a, 0xe3, 0x13, 0x20, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0xaf, 0x29,
+ 0x53, 0x5e, 0x37, 0x91, 0x1f, 0x6b, 0xc8, 0x3f, 0x06, 0x56, 0x23, 0xad, 0xab, 0x22, 0x7b, 0x5c, 0x03, 0xeb, 0x73, 0xe0,
+ 0xef, 0x47, 0xd7, 0x1e, 0x57, 0x26, 0xad, 0x1f, 0x7d, 0xc6, 0x91, 0xa5, 0x78, 0xae, 0xc6, 0xd7, 0x32, 0xe7, 0xb7, 0xff,
+ 0x9f, 0xbb, 0xd6, 0xf7, 0x71, 0xbd, 0x84, 0xb1, 0x33, 0xd2, 0xb3, 0xf2, 0xf0, 0x5e, 0x15, 0x0a, 0xf7, 0x1f, 0xed, 0x91,
+ 0xc3, 0x3a, 0x92, 0x77, 0xae, 0x22, 0xbb, 0x97, 0xaa, 0xcb, 0xac, 0x3f, 0xae, 0xb1, 0x78, 0xc8, 0x49, 0x5d, 0xcf, 0xe7,
+ 0x54, 0xbb, 0x3d, 0x3b, 0x57, 0xc7, 0xb5, 0xb0, 0xf7, 0xc6, 0xf5, 0xf2, 0xc7, 0x55, 0x91, 0x33, 0x38, 0xfa, 0x9d, 0x47,
+ 0x7f, 0x4a, 0x47, 0xf7, 0xa7, 0x33, 0x96, 0xe6, 0x4f, 0xc8, 0xa4, 0xea, 0x5c, 0xc7, 0xad, 0xb1, 0xbf, 0xf0, 0x4a, 0xe1,
+ 0xbd, 0x2b, 0xfe, 0xf3, 0x25, 0x43, 0xc8, 0x0b, 0xae, 0x6e, 0x69, 0x1d, 0x8f, 0x5f, 0x6b, 0xe5, 0x4c, 0x9a, 0x57, 0x84,
+ 0x8f, 0x54, 0xdc, 0xb1, 0x9e, 0xaa, 0xbd, 0x27, 0x9e, 0xf7, 0xd3, 0x7b, 0x57, 0x91, 0xfd, 0x3c, 0x39, 0xae, 0xbc, 0x6c,
+ 0xf5, 0x9b, 0xb6, 0x56, 0x49, 0x21, 0x3b, 0x78, 0xd6, 0xd6, 0xe3, 0x2c, 0xee, 0x4f, 0xf3, 0x7f, 0x2d, 0xb3, 0x79, 0xd6,
+ 0xb1, 0xb7, 0xee, 0x6b, 0x96, 0x5c, 0x09, 0xb6, 0xf4, 0x84, 0x1c, 0x66, 0x5b, 0xaf, 0x18, 0x27, 0x2d, 0x99, 0xe8, 0x3d,
+ 0xf7, 0x3b, 0x8d, 0xbd, 0x21, 0x07, 0x79, 0xf8, 0x5d, 0xeb, 0xde, 0x8e, 0x8c, 0x4a, 0x69, 0xb8, 0xc2, 0x6f, 0xc9, 0x0e,
+ 0xf6, 0x4b, 0xb7, 0xde, 0x35, 0xfe, 0x5b, 0xe6, 0xff, 0xbc, 0x69, 0xfc, 0xef, 0x37, 0xdf, 0xef, 0xfa, 0xf7, 0x9f, 0xb5,
+ 0xce, 0xff, 0xf7, 0xda, 0x3a, 0x33, 0x83, 0x7f, 0x7c, 0xbf, 0x6d, 0x5d, 0xa5, 0xcf, 0xfe, 0xfb, 0x8e, 0xaf, 0x11, 0xff,
+ 0x77, 0x9e, 0x27, 0xeb, 0xf1, 0xff, 0xf9, 0x02, 0xfb, 0x9d, 0xd2, 0x1d, 0x9d, 0xb3, 0xf8, 0xdf, 0x6f, 0xb9, 0x75, 0x66,
+ 0x65, 0xab, 0xea, 0xb3, 0xaa, 0x95, 0x95, 0x3e, 0xef, 0x1b, 0xff, 0x2d, 0xf9, 0xd2, 0xab, 0x5e, 0x27, 0x6f, 0xc3, 0x11,
+ 0x74, 0xd7, 0xf8, 0x3f, 0x7f, 0xf2, 0x50, 0x7f, 0x42, 0xf6, 0x8c, 0xad, 0xfb, 0x45, 0x77, 0xf0, 0x9e, 0x77, 0xec, 0xcf,
+ 0x8b, 0xff, 0x91, 0x0a, 0x85, 0xc7, 0xf7, 0x5d, 0xee, 0x70, 0x9d, 0xbc, 0xa2, 0x1e, 0xe2, 0x3d, 0xf6, 0x3b, 0x8b, 0xe6,
+ 0xa2, 0x7b, 0x3f, 0xc9, 0x71, 0x07, 0xff, 0x9e, 0x4f, 0x0d, 0x6a, 0xfd, 0x78, 0xf5, 0xf6, 0x67, 0xf5, 0xc6, 0x2b, 0xf6,
+ 0x5b, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xa7, 0x95, 0x3c, 0x39, 0x59,
+ 0x05, 0xbc, 0x75, 0xd5, 0x2e, 0xfa, 0x55, 0xb5, 0x66, 0x6a, 0x26, 0x54, 0xc9, 0x7c, 0xb4, 0xf6, 0x66, 0xbf, 0xfc, 0x68,
+ 0xb6, 0xc1, 0x77, 0x86, 0xab, 0x56, 0xf3, 0xfd, 0x69, 0xbd, 0x78, 0xb5, 0xcf, 0x57, 0x6b, 0xa6, 0x8e, 0xd5, 0x8b, 0x3d,
+ 0x5b, 0x29, 0xfd, 0x59, 0x1c, 0xcf, 0x56, 0x55, 0x80, 0x3d, 0x7a, 0xe7, 0xf3, 0x7a, 0xbe, 0xd6, 0x03, 0x32, 0x1e, 0xfd,
+ 0xdf, 0xa1, 0x07, 0x65, 0x59, 0x5e, 0xb1, 0x72, 0x9f, 0x3f, 0xf4, 0x50, 0x9e, 0x94, 0x03, 0xb4, 0xad, 0x65, 0xdf, 0x6f,
+ 0xb5, 0xf5, 0xf1, 0x3e, 0xa7, 0xb1, 0xb2, 0xdf, 0xbd, 0xb6, 0x8e, 0xd4, 0xf3, 0x85, 0x96, 0x2b, 0xe2, 0xf3, 0xaa, 0xa8,
+ 0xaf, 0xb3, 0xb5, 0xe5, 0x68, 0xb7, 0x37, 0x39, 0x56, 0xf1, 0xcf, 0xac, 0x39, 0xff, 0x9d, 0x7a, 0x7d, 0x86, 0xda, 0x42,
+ 0xfc, 0x23, 0xfe, 0xbf, 0x5b, 0xaf, 0x17, 0xff, 0x7c, 0xdf, 0xfc, 0x7f, 0x1f, 0xaa, 0x17, 0xbf, 0xdd, 0x6a, 0xeb, 0xf8,
+ 0xb5, 0xd0, 0x7d, 0xb6, 0xde, 0xb5, 0x0a, 0x22, 0x70, 0xc5, 0x1d, 0xd8, 0xb1, 0x27, 0xb8, 0xc0, 0x6b, 0xe4, 0x60, 0x95,
+ 0xb8, 0x36, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xe2, 0xdf, 0x7f, 0xda, 0x01, 0xc4, 0x3f,
+ 0xf0, 0xed, 0xe2, 0xff, 0x1f };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle cyberFontRecs[189] = {
+ { 4, 4, 4 , 14 },
+ { 16, 4, 1 , 8 },
+ { 25, 4, 4 , 3 },
+ { 37, 4, 8 , 8 },
+ { 53, 4, 8 , 9 },
+ { 69, 4, 8 , 8 },
+ { 85, 4, 8 , 8 },
+ { 101, 4, 1 , 3 },
+ { 110, 4, 4 , 9 },
+ { 122, 4, 4 , 9 },
+ { 134, 4, 5 , 6 },
+ { 147, 4, 5 , 6 },
+ { 160, 4, 2 , 2 },
+ { 170, 4, 4 , 1 },
+ { 182, 4, 1 , 1 },
+ { 191, 4, 8 , 8 },
+ { 207, 4, 8 , 8 },
+ { 223, 4, 2 , 8 },
+ { 233, 4, 8 , 8 },
+ { 249, 4, 8 , 8 },
+ { 265, 4, 8 , 8 },
+ { 281, 4, 8 , 8 },
+ { 297, 4, 8 , 8 },
+ { 313, 4, 7 , 8 },
+ { 328, 4, 8 , 8 },
+ { 344, 4, 8 , 8 },
+ { 360, 4, 1 , 4 },
+ { 369, 4, 2 , 5 },
+ { 379, 4, 4 , 8 },
+ { 391, 4, 5 , 3 },
+ { 404, 4, 4 , 8 },
+ { 416, 4, 7 , 8 },
+ { 431, 4, 8 , 8 },
+ { 447, 4, 8 , 8 },
+ { 463, 4, 8 , 8 },
+ { 479, 4, 8 , 8 },
+ { 495, 4, 8 , 8 },
+ { 4, 26, 7 , 8 },
+ { 19, 26, 7 , 8 },
+ { 34, 26, 8 , 8 },
+ { 50, 26, 8 , 8 },
+ { 66, 26, 5 , 8 },
+ { 79, 26, 7 , 8 },
+ { 94, 26, 8 , 8 },
+ { 110, 26, 7 , 8 },
+ { 125, 26, 8 , 8 },
+ { 141, 26, 8 , 8 },
+ { 157, 26, 8 , 8 },
+ { 173, 26, 8 , 8 },
+ { 189, 26, 8 , 9 },
+ { 205, 26, 8 , 8 },
+ { 221, 26, 8 , 8 },
+ { 237, 26, 8 , 8 },
+ { 253, 26, 8 , 8 },
+ { 269, 26, 8 , 8 },
+ { 285, 26, 9 , 8 },
+ { 302, 26, 8 , 8 },
+ { 318, 26, 8 , 8 },
+ { 334, 26, 8 , 8 },
+ { 350, 26, 4 , 9 },
+ { 362, 26, 8 , 8 },
+ { 378, 26, 4 , 9 },
+ { 390, 26, 4 , 3 },
+ { 402, 26, 7 , 1 },
+ { 417, 26, 2 , 3 },
+ { 427, 26, 7 , 5 },
+ { 442, 26, 7 , 8 },
+ { 457, 26, 7 , 5 },
+ { 472, 26, 7 , 8 },
+ { 487, 26, 7 , 5 },
+ { 4, 48, 4 , 8 },
+ { 16, 48, 7 , 7 },
+ { 31, 48, 7 , 8 },
+ { 46, 48, 1 , 8 },
+ { 55, 48, 3 , 10 },
+ { 66, 48, 7 , 8 },
+ { 81, 48, 4 , 8 },
+ { 93, 48, 9 , 5 },
+ { 110, 48, 7 , 5 },
+ { 125, 48, 7 , 5 },
+ { 140, 48, 7 , 7 },
+ { 155, 48, 7 , 7 },
+ { 170, 48, 5 , 5 },
+ { 183, 48, 7 , 5 },
+ { 198, 48, 5 , 8 },
+ { 211, 48, 7 , 5 },
+ { 226, 48, 7 , 5 },
+ { 241, 48, 9 , 5 },
+ { 258, 48, 7 , 5 },
+ { 273, 48, 7 , 7 },
+ { 288, 48, 7 , 5 },
+ { 303, 48, 4 , 9 },
+ { 315, 48, 1 , 9 },
+ { 324, 48, 4 , 9 },
+ { 336, 48, 8 , 2 },
+ { 352, 48, 1 , 8 },
+ { 361, 48, 7 , 8 },
+ { 376, 48, 7 , 8 },
+ { 391, 48, 8 , 9 },
+ { 407, 48, 8 , 9 },
+ { 423, 48, 8 , 10 },
+ { 439, 48, 4 , 9 },
+ { 451, 48, 7 , 8 },
+ { 466, 48, 8 , 8 },
+ { 482, 48, 7 , 6 },
+ { 497, 48, 5 , 3 },
+ { 4, 70, 5 , 3 },
+ { 17, 70, 8 , 8 },
+ { 33, 70, 0 , 0 },
+ { 41, 70, 4 , 3 },
+ { 53, 70, 8 , 6 },
+ { 69, 70, 4 , 5 },
+ { 81, 70, 4 , 5 },
+ { 93, 70, 8 , 10 },
+ { 109, 70, 7 , 7 },
+ { 124, 70, 5 , 7 },
+ { 137, 70, 1 , 1 },
+ { 146, 70, 7 , 8 },
+ { 161, 70, 2 , 5 },
+ { 171, 70, 4 , 5 },
+ { 183, 70, 5 , 3 },
+ { 196, 70, 14 , 8 },
+ { 218, 70, 13 , 5 },
+ { 239, 70, 8 , 9 },
+ { 255, 70, 7 , 8 },
+ { 270, 70, 8 , 10 },
+ { 286, 70, 8 , 10 },
+ { 302, 70, 8 , 10 },
+ { 318, 70, 8 , 10 },
+ { 334, 70, 8 , 9 },
+ { 350, 70, 8 , 12 },
+ { 366, 70, 14 , 8 },
+ { 388, 70, 8 , 10 },
+ { 404, 70, 7 , 10 },
+ { 419, 70, 7 , 10 },
+ { 434, 70, 7 , 10 },
+ { 449, 70, 7 , 9 },
+ { 464, 70, 5 , 10 },
+ { 477, 70, 5 , 10 },
+ { 490, 70, 5 , 10 },
+ { 4, 92, 5 , 9 },
+ { 17, 92, 8 , 8 },
+ { 33, 92, 8 , 10 },
+ { 49, 92, 8 , 10 },
+ { 65, 92, 8 , 10 },
+ { 81, 92, 8 , 10 },
+ { 97, 92, 8 , 10 },
+ { 113, 92, 8 , 9 },
+ { 129, 92, 4 , 4 },
+ { 141, 92, 8 , 8 },
+ { 157, 92, 8 , 10 },
+ { 173, 92, 8 , 10 },
+ { 189, 92, 8 , 10 },
+ { 205, 92, 8 , 9 },
+ { 221, 92, 8 , 10 },
+ { 237, 92, 7 , 9 },
+ { 252, 92, 7 , 9 },
+ { 267, 92, 7 , 8 },
+ { 282, 92, 7 , 8 },
+ { 297, 92, 7 , 8 },
+ { 312, 92, 7 , 8 },
+ { 327, 92, 7 , 8 },
+ { 342, 92, 7 , 9 },
+ { 357, 92, 13 , 5 },
+ { 378, 92, 7 , 7 },
+ { 393, 92, 7 , 8 },
+ { 408, 92, 7 , 8 },
+ { 423, 92, 7 , 8 },
+ { 438, 92, 7 , 8 },
+ { 453, 92, 3 , 8 },
+ { 464, 92, 2 , 8 },
+ { 474, 92, 3 , 8 },
+ { 485, 92, 3 , 8 },
+ { 4, 114, 8 , 8 },
+ { 20, 114, 7 , 8 },
+ { 35, 114, 7 , 8 },
+ { 50, 114, 7 , 8 },
+ { 65, 114, 7 , 8 },
+ { 80, 114, 7 , 8 },
+ { 95, 114, 7 , 8 },
+ { 110, 114, 5 , 6 },
+ { 123, 114, 7 , 5 },
+ { 138, 114, 7 , 8 },
+ { 153, 114, 7 , 8 },
+ { 168, 114, 7 , 8 },
+ { 183, 114, 7 , 8 },
+ { 198, 114, 7 , 10 },
+ { 213, 114, 7 , 10 },
+ { 228, 114, 7 , 10 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo cyberFontGlyphs[189] = {
+ { 32, 0, 11, 4, { 0 }},
+ { 33, 0, 3, 2, { 0 }},
+ { 34, 0, 3, 4, { 0 }},
+ { 35, 0, 3, 8, { 0 }},
+ { 36, 0, 3, 8, { 0 }},
+ { 37, 0, 3, 8, { 0 }},
+ { 38, 0, 3, 8, { 0 }},
+ { 39, 0, 3, 2, { 0 }},
+ { 40, 0, 3, 4, { 0 }},
+ { 41, 0, 3, 4, { 0 }},
+ { 42, 0, 4, 6, { 0 }},
+ { 43, 0, 4, 6, { 0 }},
+ { 44, 0, 10, 3, { 0 }},
+ { 45, 0, 7, 5, { 0 }},
+ { 46, 0, 10, 2, { 0 }},
+ { 47, 0, 3, 8, { 0 }},
+ { 48, 0, 3, 8, { 0 }},
+ { 49, 0, 3, 3, { 0 }},
+ { 50, 0, 3, 8, { 0 }},
+ { 51, 0, 3, 8, { 0 }},
+ { 52, 0, 3, 8, { 0 }},
+ { 53, 0, 3, 8, { 0 }},
+ { 54, 0, 3, 8, { 0 }},
+ { 55, 0, 3, 7, { 0 }},
+ { 56, 0, 3, 8, { 0 }},
+ { 57, 0, 3, 8, { 0 }},
+ { 58, 0, 6, 2, { 0 }},
+ { 59, 0, 6, 3, { 0 }},
+ { 60, 0, 3, 5, { 0 }},
+ { 61, 0, 6, 6, { 0 }},
+ { 62, 0, 3, 5, { 0 }},
+ { 63, 0, 3, 7, { 0 }},
+ { 64, 0, 3, 8, { 0 }},
+ { 65, 0, 3, 8, { 0 }},
+ { 66, 0, 3, 8, { 0 }},
+ { 67, 0, 3, 8, { 0 }},
+ { 68, 0, 3, 8, { 0 }},
+ { 69, 0, 3, 7, { 0 }},
+ { 70, 0, 3, 7, { 0 }},
+ { 71, 0, 3, 8, { 0 }},
+ { 72, 0, 3, 8, { 0 }},
+ { 73, 0, 3, 6, { 0 }},
+ { 74, 0, 3, 7, { 0 }},
+ { 75, 0, 3, 8, { 0 }},
+ { 76, 0, 3, 7, { 0 }},
+ { 77, 0, 3, 9, { 0 }},
+ { 78, 0, 3, 8, { 0 }},
+ { 79, 0, 3, 8, { 0 }},
+ { 80, 0, 3, 8, { 0 }},
+ { 81, 0, 3, 8, { 0 }},
+ { 82, 0, 3, 8, { 0 }},
+ { 83, 0, 3, 8, { 0 }},
+ { 84, 0, 3, 8, { 0 }},
+ { 85, 0, 3, 8, { 0 }},
+ { 86, 0, 3, 8, { 0 }},
+ { 87, 0, 3, 10, { 0 }},
+ { 88, 0, 3, 8, { 0 }},
+ { 89, 0, 3, 8, { 0 }},
+ { 90, 0, 3, 8, { 0 }},
+ { 91, 0, 3, 4, { 0 }},
+ { 92, 0, 3, 8, { 0 }},
+ { 93, 0, 3, 4, { 0 }},
+ { 94, 0, 3, 4, { 0 }},
+ { 95, 0, 11, 7, { 0 }},
+ { 96, 0, 3, 3, { 0 }},
+ { 97, 0, 6, 7, { 0 }},
+ { 98, 0, 3, 7, { 0 }},
+ { 99, 0, 6, 7, { 0 }},
+ { 100, 0, 3, 7, { 0 }},
+ { 101, 0, 6, 7, { 0 }},
+ { 102, 0, 3, 5, { 0 }},
+ { 103, 0, 6, 7, { 0 }},
+ { 104, 0, 3, 7, { 0 }},
+ { 105, 0, 3, 2, { 0 }},
+ { 106, -2, 3, 2, { 0 }},
+ { 107, 0, 3, 7, { 0 }},
+ { 108, 0, 3, 4, { 0 }},
+ { 109, 0, 6, 10, { 0 }},
+ { 110, 0, 6, 7, { 0 }},
+ { 111, 0, 6, 7, { 0 }},
+ { 112, 0, 6, 7, { 0 }},
+ { 113, 0, 6, 7, { 0 }},
+ { 114, 0, 6, 6, { 0 }},
+ { 115, 0, 6, 7, { 0 }},
+ { 116, 0, 3, 6, { 0 }},
+ { 117, 0, 6, 7, { 0 }},
+ { 118, 0, 6, 7, { 0 }},
+ { 119, 0, 6, 10, { 0 }},
+ { 120, 0, 6, 7, { 0 }},
+ { 121, 0, 6, 7, { 0 }},
+ { 122, 0, 6, 7, { 0 }},
+ { 123, 0, 3, 5, { 0 }},
+ { 124, 0, 3, 2, { 0 }},
+ { 125, 0, 3, 5, { 0 }},
+ { 126, 0, 6, 8, { 0 }},
+ { 161, 0, 3, 2, { 0 }},
+ { 162, 0, 4, 7, { 0 }},
+ { 163, 0, 3, 7, { 0 }},
+ { 8364, 0, 3, 9, { 0 }},
+ { 165, 0, 3, 8, { 0 }},
+ { 352, 0, 1, 8, { 0 }},
+ { 167, 0, 4, 5, { 0 }},
+ { 353, 0, 3, 7, { 0 }},
+ { 169, 0, 3, 9, { 0 }},
+ { 170, 0, 3, 7, { 0 }},
+ { 171, 0, 6, 6, { 0 }},
+ { 172, 0, 7, 6, { 0 }},
+ { 174, 0, 3, 9, { 0 }},
+ { 175, 0, 11, 3, { 0 }},
+ { 176, 0, 3, 4, { 0 }},
+ { 177, 0, 6, 8, { 0 }},
+ { 178, 0, 3, 4, { 0 }},
+ { 179, 0, 3, 4, { 0 }},
+ { 381, 0, 1, 8, { 0 }},
+ { 181, 0, 6, 7, { 0 }},
+ { 182, 0, 4, 6, { 0 }},
+ { 183, 0, 7, 2, { 0 }},
+ { 382, 0, 3, 7, { 0 }},
+ { 185, 0, 3, 4, { 0 }},
+ { 186, 0, 3, 5, { 0 }},
+ { 187, 0, 6, 6, { 0 }},
+ { 338, 0, 3, 14, { 0 }},
+ { 339, 0, 6, 13, { 0 }},
+ { 376, 0, 2, 8, { 0 }},
+ { 191, 0, 3, 7, { 0 }},
+ { 192, 0, 1, 8, { 0 }},
+ { 193, 0, 1, 8, { 0 }},
+ { 194, 0, 1, 8, { 0 }},
+ { 195, 0, 1, 8, { 0 }},
+ { 196, 0, 2, 8, { 0 }},
+ { 197, 0, -1, 8, { 0 }},
+ { 198, 0, 3, 14, { 0 }},
+ { 199, 0, 3, 8, { 0 }},
+ { 200, 0, 1, 7, { 0 }},
+ { 201, 0, 1, 7, { 0 }},
+ { 202, 0, 1, 7, { 0 }},
+ { 203, 0, 2, 7, { 0 }},
+ { 204, 0, 1, 6, { 0 }},
+ { 205, 0, 1, 6, { 0 }},
+ { 206, 0, 1, 6, { 0 }},
+ { 207, 0, 2, 6, { 0 }},
+ { 208, 0, 3, 9, { 0 }},
+ { 209, 0, 1, 8, { 0 }},
+ { 210, 0, 1, 8, { 0 }},
+ { 211, 0, 1, 8, { 0 }},
+ { 212, 0, 1, 8, { 0 }},
+ { 213, 0, 1, 8, { 0 }},
+ { 214, 0, 2, 8, { 0 }},
+ { 215, 1, 6, 6, { 0 }},
+ { 216, 0, 3, 8, { 0 }},
+ { 217, 0, 1, 8, { 0 }},
+ { 218, 0, 1, 8, { 0 }},
+ { 219, 0, 1, 8, { 0 }},
+ { 220, 0, 2, 8, { 0 }},
+ { 221, 0, 1, 8, { 0 }},
+ { 222, 0, 3, 7, { 0 }},
+ { 223, 0, 3, 7, { 0 }},
+ { 224, 0, 3, 7, { 0 }},
+ { 225, 0, 3, 7, { 0 }},
+ { 226, 0, 3, 7, { 0 }},
+ { 227, 0, 3, 7, { 0 }},
+ { 228, 0, 3, 7, { 0 }},
+ { 229, 0, 2, 7, { 0 }},
+ { 230, 0, 6, 13, { 0 }},
+ { 231, 0, 6, 7, { 0 }},
+ { 232, 0, 3, 7, { 0 }},
+ { 233, 0, 3, 7, { 0 }},
+ { 234, 0, 3, 7, { 0 }},
+ { 235, 0, 3, 7, { 0 }},
+ { 236, -1, 3, 2, { 0 }},
+ { 237, 0, 3, 2, { 0 }},
+ { 238, -1, 3, 2, { 0 }},
+ { 239, -1, 3, 2, { 0 }},
+ { 240, 0, 3, 8, { 0 }},
+ { 241, 0, 3, 7, { 0 }},
+ { 242, 0, 3, 7, { 0 }},
+ { 243, 0, 3, 7, { 0 }},
+ { 244, 0, 3, 7, { 0 }},
+ { 245, 0, 3, 7, { 0 }},
+ { 246, 0, 3, 7, { 0 }},
+ { 247, 0, 4, 6, { 0 }},
+ { 248, 0, 6, 7, { 0 }},
+ { 249, 0, 3, 7, { 0 }},
+ { 250, 0, 3, 7, { 0 }},
+ { 251, 0, 3, 7, { 0 }},
+ { 252, 0, 3, 7, { 0 }},
+ { 253, 0, 3, 7, { 0 }},
+ { 254, 0, 3, 7, { 0 }},
+ { 255, 0, 3, 7, { 0 }},
+};
+
+// Style loading function: Cyber
+static void GuiLoadStyleCyber(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < CYBER_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(cyberStyleProps[i].controlId, cyberStyleProps[i].propertyId, cyberStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int cyberFontDataSize = 0;
+ unsigned char *data = DecompressData(cyberFontData, CYBER_STYLE_FONT_ATLAS_COMP_SIZE, &cyberFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 14;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, cyberFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, cyberFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_dark.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_dark.h
new file mode 100644
index 0000000000..674b125b5c
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_dark.h
@@ -0,0 +1,589 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleDark(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define DARK_STYLE_PROPS_COUNT 23
+
+// Custom style name: Dark
+static const GuiStyleProp darkStyleProps[DARK_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0x878787ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x2c2c2cff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0xc3c3c3ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0xe1e1e1ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0x848484ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0x181818ff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0x000000ff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0xefefefff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0x202020ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0x9d9d9dff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x3c3c3cff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
+ { 1, 5, 0xf7f7f7ff }, // LABEL_TEXT_COLOR_FOCUSED
+ { 1, 8, 0x898989ff }, // LABEL_TEXT_COLOR_PRESSED
+ { 4, 5, 0xb0b0b0ff }, // SLIDER_TEXT_COLOR_FOCUSED
+ { 5, 5, 0x848484ff }, // PROGRESSBAR_TEXT_COLOR_FOCUSED
+ { 9, 5, 0xf5f5f5ff }, // TEXTBOX_TEXT_COLOR_FOCUSED
+ { 10, 5, 0xf6f6f6ff }, // VALUEBOX_TEXT_COLOR_FOCUSED
+};
+
+// WARNING: This style uses a custom font: "PixelOperator.ttf" (size: 16, spacing: 0)
+
+#define DARK_STYLE_FONT_ATLAS_COMP_SIZE 2126
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char darkFontData[DARK_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0xdb, 0x72, 0xa4, 0x3a, 0x12, 0x05, 0x50, 0xfd, 0xff, 0x4f, 0xe7, 0x3c, 0x4c, 0x4c, 0x4c, 0x74, 0x9c, 0xd3, 0x20,
+ 0xa5, 0x52, 0x17, 0xec, 0xd5, 0xeb, 0xcd, 0xe5, 0x76, 0x51, 0xa0, 0x94, 0x84, 0x28, 0x36, 0xd1, 0x00, 0x00, 0x00, 0x80,
+ 0x5f, 0x2f, 0xfe, 0xf5, 0x27, 0xf1, 0xd7, 0xdf, 0x8c, 0xee, 0xbf, 0xf3, 0xfc, 0xf3, 0xff, 0xbd, 0x1a, 0x0f, 0xef, 0xd5,
+ 0xb7, 0xad, 0xa3, 0xef, 0x1b, 0x03, 0x7b, 0xe2, 0xdf, 0xb7, 0x2f, 0xba, 0xff, 0xee, 0xdf, 0x3e, 0xdf, 0xf8, 0xef, 0x3f,
+ 0xfd, 0xa5, 0xe7, 0xad, 0x8f, 0xa1, 0xfd, 0x3e, 0xfe, 0x7f, 0xc6, 0x8e, 0x62, 0x2c, 0xd9, 0xf7, 0xef, 0x5b, 0x37, 0xbe,
+ 0xed, 0x95, 0xff, 0x27, 0x1e, 0x3e, 0x4f, 0xe6, 0x28, 0xf5, 0xd4, 0xd6, 0x0d, 0xf5, 0x1f, 0x5d, 0x95, 0x18, 0xa5, 0x2d,
+ 0xe7, 0xff, 0xef, 0x1a, 0x85, 0x3d, 0x55, 0x76, 0x4f, 0x3e, 0x55, 0xfa, 0xf8, 0xfe, 0x78, 0x6a, 0xfd, 0xe3, 0x3d, 0x60,
+ 0x94, 0x7c, 0x96, 0xf9, 0xd6, 0x18, 0xd3, 0xbf, 0xdd, 0xd7, 0x92, 0x6a, 0x3e, 0xd5, 0xcc, 0x2b, 0xad, 0xe4, 0x28, 0x9d,
+ 0xa8, 0xff, 0x48, 0xf7, 0x54, 0x31, 0x58, 0xd1, 0x15, 0x7b, 0x30, 0xd3, 0x0f, 0xb7, 0x8d, 0xf5, 0x1f, 0xa5, 0x73, 0x97,
+ 0x28, 0x6b, 0x73, 0x27, 0xea, 0xff, 0x79, 0xd4, 0x6e, 0x25, 0xed, 0x26, 0x5e, 0xf6, 0x51, 0x6d, 0x2d, 0xaf, 0x9d, 0xa7,
+ 0xae, 0xae, 0xff, 0xe7, 0xdf, 0x1c, 0x1d, 0x6f, 0x63, 0x70, 0xec, 0xae, 0xd8, 0x4f, 0xb9, 0xf1, 0xbf, 0x7e, 0x3f, 0xc6,
+ 0x5f, 0xc7, 0xe6, 0xec, 0x3c, 0x64, 0x64, 0x0f, 0xc7, 0xe0, 0xd9, 0xd5, 0xec, 0x08, 0x7b, 0x72, 0xfc, 0xef, 0x9b, 0x0b,
+ 0xaa, 0xff, 0xb5, 0xf5, 0x9f, 0xf9, 0x24, 0xd1, 0xb9, 0x05, 0x99, 0x31, 0xb1, 0x5d, 0x50, 0xff, 0xa3, 0xfd, 0xd0, 0xf3,
+ 0xbe, 0xaa, 0x9a, 0xcb, 0x8f, 0xae, 0x4b, 0xf4, 0x9d, 0x61, 0xef, 0x6b, 0x85, 0xe3, 0x73, 0xa3, 0xf1, 0xfa, 0x1f, 0xef,
+ 0x3d, 0xdf, 0xfe, 0xda, 0xe8, 0x5e, 0xfd, 0xfb, 0x99, 0xdd, 0xfc, 0x1e, 0xdf, 0x57, 0xff, 0x91, 0x18, 0x53, 0xce, 0xd7,
+ 0x73, 0x4d, 0xfd, 0x47, 0x62, 0xe5, 0xa2, 0x95, 0xad, 0xf2, 0xe5, 0xd6, 0x25, 0xea, 0xd6, 0x0c, 0xce, 0x1f, 0x81, 0xf7,
+ 0xfa, 0x7f, 0x3b, 0x1f, 0x3c, 0x3f, 0xfe, 0xc7, 0x15, 0xe3, 0x7f, 0xa4, 0xd7, 0x86, 0x5b, 0xa2, 0xf7, 0xfd, 0x5a, 0xfd,
+ 0x47, 0xa2, 0x66, 0xa2, 0xe4, 0xbc, 0xbc, 0x2d, 0x59, 0xcb, 0xab, 0x5d, 0x33, 0xdc, 0x73, 0xb4, 0xde, 0x46, 0xd1, 0xaa,
+ 0xb3, 0x9a, 0x9f, 0x55, 0xff, 0xad, 0x60, 0xfc, 0xef, 0x9b, 0x03, 0xcc, 0x7e, 0x8e, 0xf8, 0xd8, 0xe8, 0x5f, 0x59, 0xff,
+ 0xbb, 0x56, 0xec, 0xd7, 0xb7, 0xc6, 0xb8, 0xe2, 0xc8, 0x58, 0xff, 0xaf, 0x9c, 0xff, 0xe7, 0xd7, 0x00, 0xc6, 0xce, 0x63,
+ 0xe2, 0xd2, 0xea, 0xcf, 0x9c, 0x33, 0x57, 0x5d, 0xb1, 0xaf, 0xfd, 0x36, 0x41, 0x24, 0xbe, 0xab, 0x51, 0xb3, 0x8a, 0xb3,
+ 0xfa, 0x18, 0x8c, 0x8f, 0xff, 0xbb, 0xae, 0xff, 0xbf, 0xcf, 0xb9, 0xef, 0x18, 0xff, 0xdb, 0xeb, 0xe8, 0x7e, 0xcb, 0xf6,
+ 0x00, 0x7b, 0x7b, 0x80, 0x50, 0xfd, 0xe0, 0x7b, 0xc4, 0x80, 0xfa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0xbf, 0x9f, 0x5f, 0x9f, 0x63, 0x30, 0x9e, 0x84, 0xbd, 0x3e, 0x81, 0x7d, 0x26, 0x13, 0x38, 0xbb,
+ 0x87, 0xaa, 0xfe, 0xe2, 0x73, 0x76, 0xfc, 0x48, 0xd2, 0x42, 0x7f, 0xcb, 0x88, 0xe1, 0xa7, 0x1f, 0x54, 0x26, 0x0a, 0x64,
+ 0x32, 0x0d, 0xda, 0x60, 0x9b, 0xa8, 0xcd, 0x52, 0x1a, 0xdb, 0xfa, 0x3d, 0x2d, 0xfe, 0x0b, 0xf5, 0x7f, 0xfe, 0x95, 0x96,
+ 0xc8, 0xef, 0xd9, 0x59, 0xff, 0xa3, 0x6d, 0x2f, 0x97, 0x8f, 0x3b, 0x37, 0x96, 0xec, 0x4e, 0x14, 0x8b, 0xc2, 0x63, 0xb8,
+ 0x6f, 0x5c, 0xfd, 0x33, 0x43, 0x67, 0x47, 0xbb, 0x9e, 0xa9, 0xff, 0xd1, 0xec, 0xd3, 0x78, 0xe8, 0x85, 0xef, 0xa9, 0xff,
+ 0xb6, 0xa5, 0xfe, 0xe3, 0x23, 0xf5, 0x5f, 0x9d, 0x24, 0x53, 0x95, 0x42, 0x9e, 0x49, 0xbe, 0x19, 0x3f, 0x86, 0xf9, 0x84,
+ 0xdf, 0x6c, 0x8b, 0xfb, 0x4e, 0xfd, 0x67, 0xda, 0xd6, 0x73, 0xce, 0xaa, 0xfa, 0x7f, 0xdf, 0xb7, 0x99, 0xd1, 0x64, 0xfe,
+ 0xe7, 0x35, 0x95, 0xbf, 0x27, 0x47, 0xf7, 0xed, 0x39, 0x5a, 0x6b, 0xdb, 0xca, 0xec, 0x58, 0xf9, 0x95, 0xfa, 0x8f, 0xe4,
+ 0x5f, 0x89, 0x97, 0x1e, 0xa5, 0x36, 0x81, 0xbd, 0x26, 0xb5, 0x6d, 0x6f, 0xfd, 0x57, 0x3f, 0xf7, 0xe7, 0x8e, 0xfa, 0x3f,
+ 0x9f, 0xa3, 0xbb, 0xea, 0x1c, 0xae, 0x76, 0xac, 0xfc, 0xd9, 0xe3, 0xff, 0x7b, 0x2f, 0xb9, 0xa3, 0x7d, 0xcc, 0x8c, 0xf4,
+ 0x27, 0xc7, 0xff, 0x73, 0x3f, 0x3f, 0x5b, 0xff, 0x55, 0xad, 0x3d, 0x36, 0xce, 0x4c, 0xb2, 0x63, 0xe5, 0xce, 0x55, 0xb2,
+ 0xdd, 0xe7, 0xff, 0xab, 0x3e, 0x59, 0x1b, 0x9e, 0x4d, 0xc4, 0xb5, 0xf5, 0x3f, 0xb3, 0x0a, 0xb9, 0x6e, 0xbe, 0x70, 0x66,
+ 0xfe, 0x9f, 0x7b, 0xbe, 0x6d, 0xe6, 0xa9, 0x80, 0xb7, 0x8d, 0xff, 0xbb, 0xae, 0x92, 0xb5, 0xcd, 0x35, 0xb9, 0xf7, 0xbd,
+ 0x2a, 0x9f, 0x52, 0x37, 0x9e, 0xdf, 0x1f, 0xc5, 0x33, 0xbc, 0xaf, 0xd7, 0x7f, 0x7e, 0x95, 0xbf, 0x15, 0xad, 0x4a, 0x9e,
+ 0x9b, 0xff, 0xef, 0x7e, 0xd2, 0x49, 0xe6, 0x5d, 0x6a, 0xfa, 0xdf, 0xbe, 0xab, 0xc2, 0xb5, 0xa3, 0xc0, 0xdf, 0xaf, 0x36,
+ 0x44, 0xd1, 0xc8, 0x51, 0x95, 0xdf, 0xff, 0xe7, 0xb6, 0x8d, 0x3f, 0xf1, 0x6c, 0xfc, 0x4a, 0x7c, 0x0c, 0x3e, 0x4f, 0xff,
+ 0x44, 0xfd, 0x67, 0xde, 0x39, 0xf3, 0xbf, 0x46, 0x8f, 0x61, 0x65, 0xfd, 0x9f, 0xeb, 0x01, 0xe4, 0x6e, 0xc2, 0x8d, 0xb3,
+ 0x18, 0xe0, 0xe7, 0xf4, 0x00, 0x9e, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xec, 0xbe, 0x13, 0xfb, 0xef, 0xd9, 0x5c, 0x99, 0xd4, 0xf8, 0xf1, 0xfb, 0xa4, 0x77, 0x26, 0xe6, 0xb7, 0x97, 0x14, 0xb2,
+ 0xe7, 0xdf, 0xfa, 0xf3, 0x95, 0x8a, 0x3c, 0xde, 0x28, 0xbc, 0x6b, 0xfd, 0x29, 0x93, 0xe4, 0x39, 0x4b, 0x71, 0x34, 0x77,
+ 0xe0, 0x7d, 0x0f, 0x8f, 0x1f, 0x97, 0x99, 0xd7, 0x5a, 0x61, 0x9a, 0x42, 0x24, 0xd2, 0x5e, 0xde, 0xf6, 0x7a, 0x7f, 0x36,
+ 0x70, 0x94, 0x6d, 0xf1, 0x58, 0x1d, 0x55, 0x65, 0x27, 0xdf, 0x9e, 0x98, 0x3f, 0x9f, 0xbc, 0x13, 0x2f, 0xad, 0xae, 0xbf,
+ 0xfe, 0x7b, 0x92, 0x23, 0xd6, 0xe7, 0x18, 0xf5, 0xfc, 0x34, 0x93, 0x7a, 0x31, 0x96, 0xc1, 0x36, 0xd7, 0x06, 0x56, 0x8f,
+ 0x50, 0x6d, 0xb2, 0x42, 0x62, 0xaa, 0xa5, 0xcc, 0x67, 0xff, 0xbd, 0x6f, 0x69, 0x1b, 0x1c, 0xb9, 0x6e, 0x48, 0xcc, 0x8c,
+ 0xce, 0xfa, 0xaa, 0xfe, 0x69, 0x1b, 0xec, 0x6f, 0x32, 0x79, 0x75, 0x51, 0x9a, 0x44, 0x91, 0xff, 0x3f, 0x91, 0x48, 0x6d,
+ 0x6e, 0xc9, 0x2c, 0xbe, 0x7c, 0x46, 0x7c, 0x26, 0xa7, 0x2a, 0x16, 0xef, 0xd9, 0x4c, 0xfd, 0xb7, 0x43, 0xf5, 0x9f, 0x49,
+ 0x3d, 0x38, 0x9f, 0x98, 0x1d, 0xa9, 0xda, 0xdd, 0x5b, 0xff, 0xd1, 0xd1, 0x7f, 0x65, 0x66, 0xd7, 0x51, 0x78, 0xce, 0xf0,
+ 0x3e, 0xe3, 0xad, 0x1e, 0xff, 0xdb, 0xe3, 0x7e, 0x1a, 0x4f, 0x75, 0x5b, 0x3f, 0x42, 0x65, 0x7a, 0x93, 0xb1, 0xfa, 0x5f,
+ 0xdd, 0x63, 0xcd, 0x3c, 0x07, 0x29, 0x3e, 0x37, 0xfe, 0x9f, 0x49, 0xcc, 0x8e, 0xc4, 0xd9, 0x75, 0xe6, 0x7d, 0xeb, 0xd7,
+ 0x5e, 0xa2, 0xb0, 0xfe, 0x33, 0x3d, 0x40, 0xbe, 0xfe, 0x77, 0xce, 0xa6, 0xb3, 0x79, 0x93, 0x31, 0xdd, 0x86, 0xce, 0xd4,
+ 0x7f, 0xe5, 0xd3, 0x96, 0x56, 0x24, 0xe6, 0x8e, 0x3f, 0xd9, 0xf1, 0xd4, 0xf8, 0xdf, 0x52, 0xe3, 0x7f, 0x6e, 0x9c, 0xa8,
+ 0x3b, 0xf6, 0xb5, 0x73, 0xe5, 0xf7, 0xfa, 0x8f, 0x0d, 0xef, 0xb6, 0xaf, 0xfe, 0x33, 0x3d, 0x61, 0x2c, 0x9b, 0xff, 0x67,
+ 0xab, 0x25, 0x86, 0xe7, 0xd7, 0x3b, 0x13, 0x73, 0x33, 0xeb, 0xcc, 0xf7, 0xd7, 0x7f, 0xe5, 0x33, 0x4c, 0xda, 0x54, 0xfa,
+ 0x72, 0x94, 0x8e, 0xc8, 0xfb, 0xc6, 0xff, 0x15, 0xb3, 0xe9, 0x4c, 0xfa, 0xfe, 0x3d, 0xeb, 0x7f, 0xad, 0xf8, 0x88, 0xb5,
+ 0xe3, 0x79, 0x88, 0x2b, 0x66, 0x85, 0x27, 0xce, 0xff, 0xab, 0x12, 0xd8, 0x73, 0xe7, 0xff, 0xd5, 0x2b, 0xf2, 0x73, 0xc7,
+ 0xf2, 0xde, 0xf1, 0x3f, 0xd7, 0x42, 0x62, 0x68, 0x7c, 0x6e, 0x9f, 0xaa, 0xff, 0x5b, 0xbe, 0xd1, 0x50, 0xd1, 0x6f, 0x45,
+ 0x49, 0xef, 0x96, 0x79, 0x6e, 0x4b, 0xe5, 0x3c, 0xaa, 0x72, 0xfd, 0x6a, 0xe6, 0xfa, 0xff, 0xcc, 0xb7, 0x53, 0x56, 0xbf,
+ 0x5b, 0xfe, 0xfa, 0xff, 0xda, 0xfa, 0x8f, 0xe2, 0x2d, 0xe6, 0x9e, 0x5e, 0xea, 0xe6, 0xf7, 0xd3, 0x7e, 0xee, 0x38, 0x82,
+ 0x6a, 0x59, 0xeb, 0x39, 0x71, 0x3e, 0xc4, 0xef, 0x9a, 0x33, 0xf3, 0xd3, 0xbf, 0xe1, 0x6d, 0x3f, 0x18, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xde, 0xc3, 0x14, 0xaf, 0x77, 0x38, 0xbc, 0x65, 0x4b,
+ 0x64, 0x72, 0x29, 0x5b, 0x69, 0xce, 0x5d, 0x4b, 0x24, 0xf3, 0x67, 0xb7, 0xae, 0x77, 0xaf, 0xac, 0xff, 0x64, 0xb3, 0x69,
+ 0xe6, 0x99, 0xc4, 0xf9, 0xcc, 0x3e, 0x3e, 0x7b, 0x34, 0xdf, 0x32, 0x3c, 0x22, 0x91, 0xc6, 0x5a, 0x79, 0xbc, 0x5a, 0x6a,
+ 0xdf, 0x65, 0x5b, 0x59, 0x6f, 0x0f, 0xd0, 0x9f, 0x0f, 0x53, 0x7f, 0x8f, 0x69, 0xa4, 0xf6, 0x79, 0x4d, 0x32, 0xff, 0x4c,
+ 0x5b, 0x6a, 0xe9, 0x04, 0xe2, 0x6c, 0xab, 0xe9, 0xfd, 0x5b, 0x31, 0xfd, 0x97, 0xdf, 0xb3, 0x5a, 0xe3, 0x73, 0x47, 0x33,
+ 0x9b, 0x17, 0x5f, 0x7d, 0xbc, 0x6a, 0xd3, 0xdb, 0x6a, 0x7a, 0x80, 0x8a, 0xfa, 0xaf, 0xdb, 0xca, 0xfd, 0xf7, 0xc6, 0x46,
+ 0xf2, 0x7e, 0xfa, 0xf8, 0xfc, 0xfd, 0xa7, 0xf1, 0xd1, 0x24, 0x81, 0x5c, 0xca, 0xe4, 0xae, 0x4f, 0x95, 0xcb, 0xe5, 0xca,
+ 0xa7, 0xb7, 0xed, 0x1c, 0xff, 0x33, 0x49, 0x52, 0x99, 0xb4, 0xd0, 0xea, 0x57, 0xb2, 0xbd, 0x65, 0xae, 0xfe, 0x33, 0x99,
+ 0x4d, 0x51, 0x94, 0x67, 0x5c, 0xf7, 0xdc, 0x93, 0x48, 0xce, 0xaf, 0x4f, 0x1e, 0xcd, 0x78, 0x4d, 0x25, 0xaf, 0xca, 0xd8,
+ 0xdd, 0xfb, 0x4a, 0x4c, 0x26, 0x3e, 0x44, 0xd7, 0xf1, 0x8e, 0xe9, 0xb1, 0x70, 0xd7, 0xd3, 0x02, 0x33, 0xcf, 0xa4, 0x68,
+ 0xc9, 0xd4, 0xcc, 0x28, 0x9b, 0xe1, 0x57, 0xbf, 0xb2, 0xa2, 0xfe, 0xe3, 0xe1, 0x3c, 0xb9, 0xfa, 0x99, 0x65, 0xd5, 0x47,
+ 0xb3, 0xa7, 0x67, 0xf8, 0x62, 0xfd, 0xaf, 0x9d, 0xa7, 0xd5, 0x9c, 0xff, 0x47, 0xfa, 0x59, 0x3c, 0x77, 0xb6, 0x98, 0xe8,
+ 0x4c, 0x77, 0xfe, 0x69, 0xf5, 0xbf, 0x77, 0x1f, 0x57, 0xf7, 0xe6, 0xcf, 0x33, 0xec, 0xf6, 0xd1, 0xfa, 0x9f, 0x49, 0x8b,
+ 0xaf, 0x39, 0x5f, 0x79, 0x5f, 0xff, 0xaf, 0x5c, 0xd9, 0xb8, 0xa3, 0xfe, 0x6f, 0xa9, 0xf2, 0xb1, 0x7d, 0xbe, 0xb6, 0xfe,
+ 0xcf, 0xd7, 0xd0, 0x6c, 0xf2, 0xfb, 0xf9, 0x6d, 0x8f, 0xb2, 0xf3, 0xff, 0x9a, 0x75, 0xa1, 0xea, 0x79, 0xc4, 0x6d, 0x3d,
+ 0xe8, 0xaa, 0xa7, 0xab, 0xbd, 0xcd, 0x1d, 0xaa, 0xcf, 0x77, 0xef, 0x18, 0xff, 0x43, 0xfd, 0x2f, 0x58, 0x0b, 0xaf, 0x1d,
+ 0x25, 0xf3, 0x2b, 0xcc, 0x33, 0xfd, 0xc9, 0xf8, 0xb3, 0xec, 0x6b, 0x57, 0xc9, 0x32, 0x7d, 0x68, 0xcf, 0x2b, 0xf9, 0x27,
+ 0x6e, 0x7c, 0x75, 0xfe, 0xdf, 0xf3, 0x54, 0xa0, 0x6f, 0xd5, 0x7f, 0x24, 0xd7, 0xb7, 0xee, 0xa8, 0xff, 0xb5, 0x57, 0x06,
+ 0xd6, 0x5f, 0xcb, 0xbf, 0x79, 0xfe, 0xbf, 0xa2, 0xcf, 0xfb, 0x76, 0xfd, 0x7f, 0x61, 0x0e, 0xbd, 0xe6, 0x5b, 0x28, 0xe7,
+ 0xea, 0x7f, 0x6e, 0xdc, 0x56, 0xff, 0x2b, 0x56, 0x8c, 0xf3, 0x9f, 0x7a, 0xc5, 0xf9, 0x7f, 0xef, 0x4c, 0xe3, 0xe7, 0xd7,
+ 0x7f, 0x7d, 0xd2, 0xf9, 0x9a, 0xf3, 0xcd, 0x76, 0xe9, 0x77, 0x61, 0xee, 0xfa, 0x4e, 0xf2, 0x9e, 0x16, 0xb3, 0x66, 0xed,
+ 0x23, 0xf3, 0x94, 0xde, 0xda, 0xa7, 0x39, 0xc5, 0xa2, 0x4a, 0xcf, 0x5d, 0xe5, 0xdd, 0x73, 0xfd, 0x7f, 0xef, 0x37, 0x8a,
+ 0xaa, 0xb7, 0x50, 0xfd, 0x7f, 0xa3, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdb,
+ 0xee, 0xd0, 0xdb, 0x9b, 0xa8, 0x5f, 0x9f, 0x82, 0x71, 0x7b, 0xa2, 0xfe, 0xdb, 0x5d, 0x33, 0xed, 0xda, 0x44, 0xfd, 0xd6,
+ 0x95, 0x4c, 0xf4, 0xbd, 0x44, 0xfd, 0xdf, 0x78, 0xc7, 0xc7, 0x6d, 0x89, 0xfa, 0x75, 0x77, 0x4e, 0xdf, 0x9e, 0xa8, 0xdf,
+ 0x5e, 0xf2, 0x87, 0x6e, 0x4e, 0xd4, 0xcf, 0xdf, 0x3b, 0x75, 0x6b, 0xa2, 0x3e, 0x6b, 0xef, 0x98, 0xec, 0xed, 0xfb, 0xe3,
+ 0xe0, 0x31, 0x5b, 0x75, 0x77, 0x69, 0x7c, 0xf4, 0xce, 0xcf, 0xf1, 0x8c, 0xa6, 0x15, 0x3d, 0x4a, 0xe5, 0x5d, 0x9a, 0xeb,
+ 0x13, 0xf5, 0x7f, 0x4a, 0xbd, 0xee, 0x4a, 0xd4, 0x7f, 0xcf, 0x19, 0x8b, 0x4d, 0xdb, 0x1f, 0x43, 0xf3, 0xc6, 0xb5, 0x89,
+ 0x5a, 0xcf, 0xfd, 0xe8, 0xbd, 0xcf, 0x47, 0xf8, 0x76, 0xa2, 0xf6, 0x6f, 0xab, 0xff, 0x55, 0xfb, 0x29, 0x8a, 0xaa, 0xae,
+ 0xf7, 0x95, 0x7d, 0x59, 0x41, 0x75, 0xf5, 0x1f, 0xe5, 0xaf, 0xed, 0x4d, 0xd4, 0xca, 0xae, 0x27, 0xa8, 0xff, 0xef, 0xac,
+ 0x01, 0xe4, 0xd6, 0xad, 0xe6, 0x12, 0x75, 0x4f, 0xb6, 0x80, 0x9d, 0x89, 0x5a, 0x5f, 0xaf, 0xff, 0xcc, 0xac, 0x5c, 0xfd,
+ 0xdf, 0x39, 0xff, 0x8f, 0xb2, 0x57, 0x32, 0xbd, 0x46, 0x7e, 0xfd, 0xff, 0xcb, 0x4f, 0xd4, 0xfa, 0x99, 0xf5, 0x7f, 0x47,
+ 0xa2, 0xae, 0xfa, 0x3f, 0x33, 0xff, 0x5f, 0xf7, 0x54, 0x82, 0x9d, 0x89, 0xba, 0xc6, 0xff, 0x55, 0x15, 0x71, 0x77, 0x95,
+ 0xdf, 0x95, 0x9b, 0xfb, 0xcd, 0xf3, 0xff, 0xdc, 0x93, 0x40, 0xb3, 0x3d, 0xc0, 0xbe, 0x84, 0xd6, 0x13, 0x89, 0xfa, 0x12,
+ 0x75, 0x67, 0x8e, 0xd7, 0xf3, 0xec, 0xef, 0x9b, 0xd7, 0x63, 0x6e, 0x9f, 0xff, 0xd7, 0x5e, 0xab, 0xf9, 0xe7, 0x9a, 0xd2,
+ 0xea, 0x15, 0xef, 0x55, 0xf3, 0xff, 0xda, 0x2b, 0x5b, 0x12, 0x75, 0xab, 0x8f, 0xda, 0x6f, 0x5f, 0xff, 0x3b, 0xdb, 0xd3,
+ 0xc0, 0xee, 0x79, 0xed, 0xf9, 0x9e, 0x10, 0xf8, 0xda, 0x37, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf9, 0xef, 0x3f, 0xfb, 0x01, 0xd4, 0x3f,
+ 0xf0, 0xeb, 0xea, 0xff, 0x3f };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle darkFontRecs[189] = {
+ { 4, 4, 4 , 16 },
+ { 16, 4, 1 , 9 },
+ { 25, 4, 3 , 3 },
+ { 36, 4, 6 , 9 },
+ { 50, 4, 5 , 13 },
+ { 63, 4, 7 , 9 },
+ { 78, 4, 5 , 9 },
+ { 91, 4, 1 , 3 },
+ { 100, 4, 3 , 9 },
+ { 111, 4, 3 , 9 },
+ { 122, 4, 5 , 5 },
+ { 135, 4, 5 , 5 },
+ { 148, 4, 2 , 3 },
+ { 158, 4, 4 , 1 },
+ { 170, 4, 1 , 1 },
+ { 179, 4, 3 , 9 },
+ { 190, 4, 5 , 9 },
+ { 203, 4, 3 , 9 },
+ { 214, 4, 5 , 9 },
+ { 227, 4, 5 , 9 },
+ { 240, 4, 5 , 9 },
+ { 253, 4, 5 , 9 },
+ { 266, 4, 5 , 9 },
+ { 279, 4, 5 , 9 },
+ { 292, 4, 5 , 9 },
+ { 305, 4, 5 , 9 },
+ { 318, 4, 1 , 7 },
+ { 327, 4, 2 , 9 },
+ { 337, 4, 3 , 5 },
+ { 348, 4, 4 , 3 },
+ { 360, 4, 3 , 5 },
+ { 371, 4, 5 , 9 },
+ { 384, 4, 7 , 9 },
+ { 399, 4, 5 , 9 },
+ { 412, 4, 5 , 9 },
+ { 425, 4, 5 , 9 },
+ { 438, 4, 5 , 9 },
+ { 451, 4, 5 , 9 },
+ { 464, 4, 5 , 9 },
+ { 477, 4, 5 , 9 },
+ { 490, 4, 5 , 9 },
+ { 4, 28, 1 , 9 },
+ { 13, 28, 5 , 9 },
+ { 26, 28, 5 , 9 },
+ { 39, 28, 5 , 9 },
+ { 52, 28, 7 , 9 },
+ { 67, 28, 5 , 9 },
+ { 80, 28, 5 , 9 },
+ { 93, 28, 5 , 9 },
+ { 106, 28, 5 , 9 },
+ { 119, 28, 5 , 9 },
+ { 132, 28, 5 , 9 },
+ { 145, 28, 5 , 9 },
+ { 158, 28, 5 , 9 },
+ { 171, 28, 5 , 9 },
+ { 184, 28, 7 , 9 },
+ { 199, 28, 5 , 9 },
+ { 212, 28, 5 , 9 },
+ { 225, 28, 5 , 9 },
+ { 238, 28, 3 , 9 },
+ { 249, 28, 3 , 9 },
+ { 260, 28, 3 , 9 },
+ { 271, 28, 5 , 3 },
+ { 284, 28, 5 , 1 },
+ { 297, 28, 2 , 2 },
+ { 307, 28, 5 , 7 },
+ { 320, 28, 5 , 9 },
+ { 333, 28, 5 , 7 },
+ { 346, 28, 5 , 9 },
+ { 359, 28, 5 , 7 },
+ { 372, 28, 4 , 9 },
+ { 384, 28, 5 , 9 },
+ { 397, 28, 5 , 9 },
+ { 410, 28, 1 , 9 },
+ { 419, 28, 5 , 11 },
+ { 432, 28, 5 , 9 },
+ { 445, 28, 2 , 9 },
+ { 455, 28, 7 , 7 },
+ { 470, 28, 5 , 7 },
+ { 483, 28, 5 , 7 },
+ { 496, 28, 5 , 9 },
+ { 4, 52, 5 , 9 },
+ { 17, 52, 5 , 7 },
+ { 30, 52, 5 , 7 },
+ { 43, 52, 4 , 8 },
+ { 55, 52, 5 , 7 },
+ { 68, 52, 5 , 7 },
+ { 81, 52, 7 , 7 },
+ { 96, 52, 5 , 7 },
+ { 109, 52, 5 , 9 },
+ { 122, 52, 5 , 7 },
+ { 135, 52, 4 , 9 },
+ { 147, 52, 1 , 9 },
+ { 156, 52, 4 , 9 },
+ { 168, 52, 6 , 2 },
+ { 182, 52, 1 , 9 },
+ { 191, 52, 5 , 11 },
+ { 204, 52, 6 , 9 },
+ { 218, 52, 6 , 9 },
+ { 232, 52, 5 , 9 },
+ { 245, 52, 5 , 12 },
+ { 258, 52, 5 , 9 },
+ { 271, 52, 5 , 10 },
+ { 284, 52, 7 , 9 },
+ { 299, 52, 5 , 9 },
+ { 312, 52, 6 , 5 },
+ { 326, 52, 5 , 3 },
+ { 339, 52, 7 , 9 },
+ { 354, 52, 5 , 9 },
+ { 367, 52, 4 , 4 },
+ { 379, 52, 5 , 7 },
+ { 392, 52, 5 , 9 },
+ { 405, 52, 5 , 9 },
+ { 418, 52, 5 , 12 },
+ { 431, 52, 5 , 9 },
+ { 444, 52, 7 , 9 },
+ { 459, 52, 1 , 1 },
+ { 468, 52, 5 , 10 },
+ { 481, 52, 5 , 9 },
+ { 494, 52, 5 , 9 },
+ { 4, 76, 6 , 5 },
+ { 18, 76, 9 , 9 },
+ { 35, 76, 9 , 7 },
+ { 52, 76, 5 , 11 },
+ { 65, 76, 5 , 9 },
+ { 78, 76, 5 , 12 },
+ { 91, 76, 5 , 12 },
+ { 104, 76, 5 , 12 },
+ { 117, 76, 6 , 12 },
+ { 131, 76, 5 , 11 },
+ { 144, 76, 5 , 13 },
+ { 157, 76, 9 , 9 },
+ { 174, 76, 5 , 12 },
+ { 187, 76, 5 , 12 },
+ { 200, 76, 5 , 12 },
+ { 213, 76, 5 , 12 },
+ { 226, 76, 5 , 11 },
+ { 239, 76, 2 , 12 },
+ { 249, 76, 2 , 12 },
+ { 259, 76, 3 , 12 },
+ { 270, 76, 3 , 11 },
+ { 281, 76, 6 , 9 },
+ { 295, 76, 6 , 12 },
+ { 309, 76, 5 , 12 },
+ { 322, 76, 5 , 12 },
+ { 335, 76, 5 , 12 },
+ { 348, 76, 6 , 12 },
+ { 362, 76, 5 , 11 },
+ { 375, 76, 5 , 5 },
+ { 388, 76, 7 , 9 },
+ { 403, 76, 5 , 12 },
+ { 416, 76, 5 , 12 },
+ { 429, 76, 5 , 12 },
+ { 442, 76, 5 , 11 },
+ { 455, 76, 5 , 12 },
+ { 468, 76, 5 , 9 },
+ { 481, 76, 5 , 9 },
+ { 494, 76, 5 , 10 },
+ { 4, 100, 5 , 10 },
+ { 17, 100, 5 , 10 },
+ { 30, 100, 6 , 10 },
+ { 44, 100, 5 , 9 },
+ { 57, 100, 5 , 11 },
+ { 70, 100, 9 , 7 },
+ { 87, 100, 5 , 10 },
+ { 100, 100, 5 , 10 },
+ { 113, 100, 5 , 10 },
+ { 126, 100, 5 , 10 },
+ { 139, 100, 5 , 9 },
+ { 152, 100, 2 , 10 },
+ { 162, 100, 2 , 10 },
+ { 172, 100, 3 , 10 },
+ { 183, 100, 3 , 9 },
+ { 194, 100, 6 , 9 },
+ { 208, 100, 6 , 10 },
+ { 222, 100, 5 , 10 },
+ { 235, 100, 5 , 10 },
+ { 248, 100, 5 , 10 },
+ { 261, 100, 6 , 10 },
+ { 275, 100, 5 , 9 },
+ { 288, 100, 5 , 5 },
+ { 301, 100, 7 , 7 },
+ { 316, 100, 5 , 10 },
+ { 329, 100, 5 , 10 },
+ { 342, 100, 5 , 10 },
+ { 355, 100, 5 , 9 },
+ { 368, 100, 5 , 12 },
+ { 381, 100, 5 , 11 },
+ { 394, 100, 5 , 11 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo darkFontGlyphs[189] = {
+ { 32, 0, 13, 4, { 0 }},
+ { 33, 2, 4, 5, { 0 }},
+ { 34, 2, 4, 7, { 0 }},
+ { 35, 1, 4, 8, { 0 }},
+ { 36, 1, 2, 7, { 0 }},
+ { 37, 1, 4, 9, { 0 }},
+ { 38, 1, 4, 7, { 0 }},
+ { 39, 2, 4, 5, { 0 }},
+ { 40, 3, 4, 7, { 0 }},
+ { 41, 1, 4, 7, { 0 }},
+ { 42, 1, 4, 7, { 0 }},
+ { 43, 1, 6, 7, { 0 }},
+ { 44, 1, 12, 5, { 0 }},
+ { 45, 1, 8, 6, { 0 }},
+ { 46, 2, 12, 5, { 0 }},
+ { 47, 1, 4, 5, { 0 }},
+ { 48, 1, 4, 7, { 0 }},
+ { 49, 2, 4, 7, { 0 }},
+ { 50, 1, 4, 7, { 0 }},
+ { 51, 1, 4, 7, { 0 }},
+ { 52, 1, 4, 7, { 0 }},
+ { 53, 1, 4, 7, { 0 }},
+ { 54, 1, 4, 7, { 0 }},
+ { 55, 1, 4, 7, { 0 }},
+ { 56, 1, 4, 7, { 0 }},
+ { 57, 1, 4, 7, { 0 }},
+ { 58, 2, 6, 5, { 0 }},
+ { 59, 1, 6, 5, { 0 }},
+ { 60, 1, 6, 5, { 0 }},
+ { 61, 1, 7, 6, { 0 }},
+ { 62, 1, 6, 5, { 0 }},
+ { 63, 1, 4, 7, { 0 }},
+ { 64, 1, 4, 9, { 0 }},
+ { 65, 1, 4, 7, { 0 }},
+ { 66, 1, 4, 7, { 0 }},
+ { 67, 1, 4, 7, { 0 }},
+ { 68, 1, 4, 7, { 0 }},
+ { 69, 1, 4, 7, { 0 }},
+ { 70, 1, 4, 7, { 0 }},
+ { 71, 1, 4, 7, { 0 }},
+ { 72, 1, 4, 7, { 0 }},
+ { 73, 2, 4, 5, { 0 }},
+ { 74, 1, 4, 7, { 0 }},
+ { 75, 1, 4, 7, { 0 }},
+ { 76, 1, 4, 7, { 0 }},
+ { 77, 1, 4, 9, { 0 }},
+ { 78, 1, 4, 7, { 0 }},
+ { 79, 1, 4, 7, { 0 }},
+ { 80, 1, 4, 7, { 0 }},
+ { 81, 1, 4, 7, { 0 }},
+ { 82, 1, 4, 7, { 0 }},
+ { 83, 1, 4, 7, { 0 }},
+ { 84, 1, 4, 7, { 0 }},
+ { 85, 1, 4, 7, { 0 }},
+ { 86, 1, 4, 7, { 0 }},
+ { 87, 1, 4, 9, { 0 }},
+ { 88, 1, 4, 7, { 0 }},
+ { 89, 1, 4, 7, { 0 }},
+ { 90, 1, 4, 7, { 0 }},
+ { 91, 3, 4, 7, { 0 }},
+ { 92, 1, 4, 5, { 0 }},
+ { 93, 1, 4, 7, { 0 }},
+ { 94, 1, 4, 7, { 0 }},
+ { 95, 0, 14, 5, { 0 }},
+ { 96, 1, 4, 5, { 0 }},
+ { 97, 1, 6, 7, { 0 }},
+ { 98, 1, 4, 7, { 0 }},
+ { 99, 1, 6, 7, { 0 }},
+ { 100, 1, 4, 7, { 0 }},
+ { 101, 1, 6, 7, { 0 }},
+ { 102, 1, 4, 6, { 0 }},
+ { 103, 1, 6, 7, { 0 }},
+ { 104, 1, 4, 7, { 0 }},
+ { 105, 2, 4, 5, { 0 }},
+ { 106, 1, 4, 7, { 0 }},
+ { 107, 1, 4, 7, { 0 }},
+ { 108, 2, 4, 5, { 0 }},
+ { 109, 1, 6, 9, { 0 }},
+ { 110, 1, 6, 7, { 0 }},
+ { 111, 1, 6, 7, { 0 }},
+ { 112, 1, 6, 7, { 0 }},
+ { 113, 1, 6, 7, { 0 }},
+ { 114, 1, 6, 7, { 0 }},
+ { 115, 1, 6, 7, { 0 }},
+ { 116, 1, 5, 6, { 0 }},
+ { 117, 1, 6, 7, { 0 }},
+ { 118, 1, 6, 7, { 0 }},
+ { 119, 1, 6, 9, { 0 }},
+ { 120, 1, 6, 7, { 0 }},
+ { 121, 1, 6, 7, { 0 }},
+ { 122, 1, 6, 7, { 0 }},
+ { 123, 2, 4, 7, { 0 }},
+ { 124, 2, 4, 5, { 0 }},
+ { 125, 1, 4, 7, { 0 }},
+ { 126, 1, 4, 8, { 0 }},
+ { 161, 2, 6, 5, { 0 }},
+ { 162, 1, 4, 7, { 0 }},
+ { 163, 1, 4, 8, { 0 }},
+ { 8364, 1, 4, 8, { 0 }},
+ { 165, 1, 4, 7, { 0 }},
+ { 352, 1, 1, 7, { 0 }},
+ { 167, 2, 4, 9, { 0 }},
+ { 353, 1, 3, 7, { 0 }},
+ { 169, 1, 4, 9, { 0 }},
+ { 170, 2, 4, 9, { 0 }},
+ { 171, 1, 6, 8, { 0 }},
+ { 172, 1, 8, 7, { 0 }},
+ { 174, 1, 4, 9, { 0 }},
+ { 175, 2, 4, 9, { 0 }},
+ { 176, 1, 4, 6, { 0 }},
+ { 177, 1, 6, 7, { 0 }},
+ { 178, 2, 4, 9, { 0 }},
+ { 179, 2, 4, 9, { 0 }},
+ { 381, 1, 1, 7, { 0 }},
+ { 181, 1, 6, 7, { 0 }},
+ { 182, 1, 4, 9, { 0 }},
+ { 183, 2, 8, 5, { 0 }},
+ { 382, 1, 3, 7, { 0 }},
+ { 185, 2, 4, 9, { 0 }},
+ { 186, 2, 4, 9, { 0 }},
+ { 187, 1, 6, 8, { 0 }},
+ { 338, 1, 4, 11, { 0 }},
+ { 339, 1, 6, 11, { 0 }},
+ { 376, 1, 2, 7, { 0 }},
+ { 191, 1, 6, 7, { 0 }},
+ { 192, 1, 1, 7, { 0 }},
+ { 193, 1, 1, 7, { 0 }},
+ { 194, 1, 1, 7, { 0 }},
+ { 195, 1, 1, 7, { 0 }},
+ { 196, 1, 2, 7, { 0 }},
+ { 197, 1, 0, 7, { 0 }},
+ { 198, 1, 4, 11, { 0 }},
+ { 199, 1, 4, 7, { 0 }},
+ { 200, 1, 1, 7, { 0 }},
+ { 201, 1, 1, 7, { 0 }},
+ { 202, 1, 1, 7, { 0 }},
+ { 203, 1, 2, 7, { 0 }},
+ { 204, 1, 1, 5, { 0 }},
+ { 205, 2, 1, 5, { 0 }},
+ { 206, 1, 1, 5, { 0 }},
+ { 207, 1, 2, 5, { 0 }},
+ { 208, 0, 4, 7, { 0 }},
+ { 209, 1, 1, 7, { 0 }},
+ { 210, 1, 1, 7, { 0 }},
+ { 211, 1, 1, 7, { 0 }},
+ { 212, 1, 1, 7, { 0 }},
+ { 213, 1, 1, 7, { 0 }},
+ { 214, 1, 2, 7, { 0 }},
+ { 215, 1, 6, 7, { 0 }},
+ { 216, 0, 4, 7, { 0 }},
+ { 217, 1, 1, 7, { 0 }},
+ { 218, 1, 1, 7, { 0 }},
+ { 219, 1, 1, 7, { 0 }},
+ { 220, 1, 2, 7, { 0 }},
+ { 221, 1, 1, 7, { 0 }},
+ { 222, 1, 4, 7, { 0 }},
+ { 223, 1, 4, 7, { 0 }},
+ { 224, 1, 3, 7, { 0 }},
+ { 225, 1, 3, 7, { 0 }},
+ { 226, 1, 3, 7, { 0 }},
+ { 227, 1, 3, 7, { 0 }},
+ { 228, 1, 4, 7, { 0 }},
+ { 229, 1, 2, 7, { 0 }},
+ { 230, 1, 6, 11, { 0 }},
+ { 231, 1, 6, 7, { 0 }},
+ { 232, 1, 3, 7, { 0 }},
+ { 233, 1, 3, 7, { 0 }},
+ { 234, 1, 3, 7, { 0 }},
+ { 235, 1, 4, 7, { 0 }},
+ { 236, 1, 3, 5, { 0 }},
+ { 237, 2, 3, 5, { 0 }},
+ { 238, 1, 3, 5, { 0 }},
+ { 239, 1, 4, 5, { 0 }},
+ { 240, 1, 4, 7, { 0 }},
+ { 241, 1, 3, 7, { 0 }},
+ { 242, 1, 3, 7, { 0 }},
+ { 243, 1, 3, 7, { 0 }},
+ { 244, 1, 3, 7, { 0 }},
+ { 245, 1, 3, 7, { 0 }},
+ { 246, 1, 4, 7, { 0 }},
+ { 247, 1, 6, 7, { 0 }},
+ { 248, 0, 6, 7, { 0 }},
+ { 249, 1, 3, 7, { 0 }},
+ { 250, 1, 3, 7, { 0 }},
+ { 251, 1, 3, 7, { 0 }},
+ { 252, 1, 4, 7, { 0 }},
+ { 253, 1, 3, 7, { 0 }},
+ { 254, 1, 4, 7, { 0 }},
+ { 255, 1, 4, 7, { 0 }},
+};
+
+// Style loading function: Dark
+static void GuiLoadStyleDark(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < DARK_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(darkStyleProps[i].controlId, darkStyleProps[i].propertyId, darkStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int darkFontDataSize = 0;
+ unsigned char *data = DecompressData(darkFontData, DARK_STYLE_FONT_ATLAS_COMP_SIZE, &darkFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 16;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, darkFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, darkFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_enefete.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_enefete.h
new file mode 100644
index 0000000000..04290fbf67
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_enefete.h
@@ -0,0 +1,600 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleEnefete(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define ENEFETE_STYLE_PROPS_COUNT 17
+
+// Custom style name: Enefete
+static const GuiStyleProp enefeteStyleProps[ENEFETE_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0x1980d5ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x4df3ebff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0x103e60ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0xe7e2f7ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0x23d4ddff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0xf1f1f1ff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0x6413a6ff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0xea66d9ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0x9f00bbff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x4b909eff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x73c7d0ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x448894ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0x1d3f6cff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x29c9e5ff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "GenericMobileSystemNuevo.ttf" (size: 16, spacing: 0)
+
+#define ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE 2462
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char enefeteFontData[ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0x59, 0xb2, 0xeb, 0x34, 0x10, 0x00, 0x50, 0x6d, 0x83, 0xfd, 0xef, 0x8d, 0x6d, 0x88, 0xa2, 0x28, 0x0a, 0xb8, 0x8f,
+ 0x58, 0x52, 0x77, 0xcb, 0x53, 0x0e, 0xa7, 0xf8, 0xb9, 0x7e, 0x49, 0x6c, 0xd9, 0x6d, 0x0d, 0xb6, 0x5a, 0xbd, 0x01, 0x00,
+ 0x00, 0x00, 0x5f, 0xef, 0xcf, 0xff, 0xfe, 0xff, 0x6f, 0xff, 0xb7, 0xe5, 0x78, 0xdb, 0xdf, 0xff, 0x62, 0xb4, 0xa5, 0x7f,
+ 0xdc, 0x93, 0x7e, 0xb0, 0x6d, 0xee, 0xb7, 0x62, 0xfb, 0xd5, 0x97, 0xca, 0xa6, 0x1f, 0x94, 0x5a, 0x4b, 0xff, 0xbd, 0x1d,
+ 0x96, 0x7d, 0x0f, 0x94, 0x5e, 0x3b, 0xdc, 0xe7, 0xcf, 0x9f, 0x1c, 0x6f, 0xa9, 0xdc, 0xcf, 0x95, 0x32, 0xad, 0x3c, 0x3f,
+ 0x2b, 0x25, 0xd8, 0x96, 0xb7, 0x1e, 0x97, 0x54, 0x9b, 0x2a, 0xc7, 0xf1, 0x37, 0xf7, 0x9b, 0xc4, 0xff, 0xf1, 0xd1, 0xfc,
+ 0x1d, 0x83, 0x47, 0x67, 0x7f, 0xfe, 0xda, 0x68, 0xd3, 0xf7, 0x84, 0x7f, 0x7e, 0xbb, 0x2e, 0x42, 0xb3, 0xdf, 0xd2, 0x87,
+ 0x77, 0xc2, 0x95, 0x12, 0x3a, 0x2e, 0xbd, 0x16, 0x8a, 0x89, 0xd1, 0x77, 0x46, 0xf6, 0x65, 0x66, 0xdb, 0xdc, 0xfe, 0xc5,
+ 0xae, 0xf9, 0xf1, 0xf7, 0x1d, 0x5f, 0x69, 0x47, 0x67, 0x78, 0x74, 0xe5, 0x1e, 0x1f, 0xdf, 0xfa, 0x59, 0xcd, 0x44, 0xfd,
+ 0x9e, 0xf8, 0xef, 0xff, 0x8a, 0xb3, 0x1e, 0x8c, 0xc1, 0x7c, 0xdd, 0xb0, 0x5e, 0x2b, 0x1c, 0xdf, 0xb3, 0xf6, 0x95, 0xf0,
+ 0x51, 0x39, 0xf5, 0xc0, 0x35, 0xbc, 0x7e, 0xce, 0xa2, 0xbf, 0xb3, 0x23, 0xfe, 0x2b, 0xa2, 0xb8, 0x4d, 0xd4, 0x88, 0x91,
+ 0x36, 0xc5, 0x71, 0x8b, 0x33, 0x1f, 0xe1, 0xa3, 0x7d, 0x89, 0xb4, 0x67, 0xf2, 0x65, 0xb9, 0xda, 0xe6, 0xd8, 0x17, 0xff,
+ 0x15, 0xf5, 0xed, 0x7a, 0x5d, 0xb2, 0xaf, 0x7c, 0x67, 0xea, 0xeb, 0xfb, 0xc7, 0xff, 0xfa, 0xb1, 0x55, 0xc4, 0x7f, 0xcd,
+ 0x59, 0x59, 0x8f, 0xff, 0x2e, 0xfe, 0xa7, 0xeb, 0xff, 0xcf, 0xa5, 0xde, 0x83, 0xfd, 0xaf, 0x7c, 0xaf, 0xbd, 0xaa, 0x9d,
+ 0x7f, 0x6d, 0xfc, 0x8f, 0xfa, 0x83, 0x6d, 0x39, 0xfe, 0x63, 0xbd, 0xcf, 0x48, 0x6f, 0xa3, 0xaa, 0xfd, 0xbf, 0xb7, 0xf5,
+ 0x70, 0xdc, 0x7b, 0x8c, 0x44, 0xf8, 0xda, 0x98, 0x47, 0xcd, 0x37, 0x5f, 0x11, 0xff, 0x6d, 0x62, 0x6f, 0xfa, 0xb0, 0xff,
+ 0x3f, 0x7b, 0x87, 0x5f, 0x8b, 0xff, 0xba, 0xba, 0xe3, 0xca, 0xf8, 0xef, 0xc1, 0x11, 0xb1, 0xea, 0x7e, 0x7c, 0xfc, 0xd8,
+ 0xd6, 0xc6, 0xe7, 0xce, 0xeb, 0xff, 0x8f, 0xda, 0x81, 0x99, 0xf8, 0xff, 0x96, 0xf6, 0xff, 0x4c, 0x4b, 0x7b, 0x54, 0x8a,
+ 0xf3, 0xf7, 0xb3, 0x2b, 0x6a, 0xf3, 0x6b, 0xe3, 0xbf, 0x4f, 0x8d, 0x61, 0xdf, 0x3b, 0xfe, 0xdb, 0x72, 0x2f, 0xaf, 0xf2,
+ 0xda, 0x8d, 0x5e, 0x51, 0xa3, 0x2b, 0x77, 0xe6, 0xae, 0x76, 0xcf, 0xf8, 0x8f, 0x5d, 0xcf, 0x7d, 0xd8, 0xca, 0xef, 0x89,
+ 0xf8, 0x6f, 0xaf, 0x89, 0xff, 0x1e, 0x1c, 0xed, 0xf8, 0xdc, 0xde, 0x8b, 0x8d, 0xc7, 0x45, 0x5a, 0xf2, 0x99, 0x36, 0x4a,
+ 0x55, 0xfc, 0xdf, 0xe3, 0x4c, 0xaa, 0xff, 0x2b, 0xc6, 0xff, 0xdb, 0x61, 0x0b, 0xff, 0xbb, 0xe2, 0xff, 0xf8, 0xf9, 0x5f,
+ 0xbb, 0xfd, 0xb3, 0xba, 0x68, 0xfc, 0xd7, 0x8c, 0xff, 0x9f, 0x7f, 0xb7, 0x9e, 0xe9, 0xb9, 0xe6, 0xe2, 0xff, 0x4e, 0xcf,
+ 0xff, 0xf6, 0xc6, 0xff, 0xe8, 0xa9, 0xf7, 0x9b, 0xda, 0xff, 0x95, 0xe3, 0xf8, 0xf1, 0x77, 0x6e, 0xf6, 0xbd, 0x53, 0xd4,
+ 0x42, 0x6f, 0x72, 0xdd, 0x33, 0xfa, 0xa3, 0xcf, 0x81, 0x72, 0xa3, 0x74, 0x57, 0xbf, 0xff, 0x53, 0x5f, 0x82, 0xe7, 0xed,
+ 0x4f, 0xbf, 0x71, 0x9b, 0x91, 0x77, 0xbd, 0x25, 0xeb, 0xea, 0x3a, 0xf3, 0xf9, 0x6c, 0xfc, 0xb7, 0x9c, 0x1f, 0x76, 0xd6,
+ 0x6c, 0x4a, 0xe2, 0x19, 0x63, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xe4, 0xf9,
+ 0x0b, 0x91, 0xb9, 0x86, 0xd1, 0x3c, 0x04, 0xb5, 0xf9, 0x10, 0xfa, 0x8f, 0x3c, 0xac, 0xab, 0xdf, 0x3d, 0x3b, 0xd7, 0x32,
+ 0x33, 0x4f, 0xb3, 0xf6, 0xb3, 0x55, 0x99, 0x25, 0x6a, 0x67, 0x9e, 0x8f, 0xf3, 0xdd, 0xac, 0x66, 0x6b, 0x8e, 0x65, 0x41,
+ 0x5b, 0xcf, 0x69, 0x9e, 0xc9, 0xc3, 0x57, 0x3d, 0xb7, 0xba, 0x26, 0x3f, 0xda, 0xfc, 0x9c, 0xf7, 0x9a, 0x4c, 0x23, 0x75,
+ 0xf1, 0xbf, 0x7e, 0x1e, 0xfa, 0x8f, 0xfd, 0xe8, 0x17, 0x64, 0x62, 0xa8, 0xdf, 0x3a, 0xf7, 0xf7, 0x3b, 0xc5, 0xff, 0xec,
+ 0x3d, 0x38, 0x7b, 0xf5, 0xc6, 0x67, 0xdc, 0x8d, 0xb2, 0x4f, 0x5c, 0x9f, 0x5b, 0xa5, 0x15, 0xe5, 0x47, 0xad, 0x8f, 0xff,
+ 0x76, 0x52, 0xfd, 0x1f, 0x8d, 0xff, 0x3e, 0x5c, 0xcd, 0xe6, 0xbe, 0xf1, 0xbf, 0x9e, 0x77, 0x22, 0xfb, 0xab, 0xb9, 0x95,
+ 0x1c, 0xe2, 0xb9, 0xc6, 0xf3, 0xf1, 0x9f, 0xcb, 0x14, 0x74, 0x6e, 0xdd, 0x7a, 0x7d, 0xfc, 0x47, 0x4b, 0xe4, 0xaa, 0xf8,
+ 0x8f, 0x5f, 0x25, 0x7d, 0x98, 0xcd, 0xfa, 0x8e, 0xf1, 0xdf, 0xbf, 0x3e, 0xfe, 0xeb, 0x73, 0xf9, 0x46, 0x23, 0x20, 0x92,
+ 0x07, 0x7d, 0xa6, 0x5f, 0xbd, 0xda, 0xb3, 0x8b, 0xf7, 0xbb, 0xa2, 0xf5, 0xff, 0xe8, 0xf3, 0x33, 0x47, 0x72, 0x75, 0xfc,
+ 0xb7, 0x61, 0x84, 0xf7, 0x44, 0x94, 0xc6, 0x47, 0x40, 0x32, 0x39, 0xaf, 0xae, 0x89, 0xff, 0x16, 0x5a, 0x31, 0x30, 0x5e,
+ 0xcf, 0xdf, 0x3d, 0xfe, 0xab, 0xfb, 0x06, 0xd1, 0x11, 0x83, 0xea, 0x7d, 0xbc, 0x5f, 0xff, 0xbf, 0x17, 0xb4, 0x12, 0x77,
+ 0xc4, 0x7f, 0xb6, 0x7c, 0xa2, 0xd1, 0x14, 0x8b, 0xff, 0xf9, 0xda, 0x3d, 0xb6, 0x9a, 0x40, 0x6c, 0xdb, 0x7b, 0xe3, 0xbf,
+ 0x36, 0x7f, 0xea, 0xfa, 0x58, 0xf1, 0x9b, 0xe2, 0x3f, 0xda, 0xff, 0x9f, 0xef, 0x71, 0xdd, 0x2b, 0xfe, 0xdb, 0xc4, 0xfa,
+ 0x3c, 0x67, 0xc7, 0xff, 0x28, 0xdb, 0xea, 0xdb, 0xe2, 0x3f, 0x1a, 0x5b, 0xd1, 0xf5, 0x8c, 0x5a, 0xb8, 0xa6, 0x7b, 0x7b,
+ 0xfd, 0xdf, 0x5e, 0x1a, 0xff, 0xf1, 0xf5, 0x65, 0x9e, 0x15, 0xff, 0xd5, 0xad, 0x86, 0xeb, 0xf3, 0xea, 0x45, 0x47, 0x1b,
+ 0xe3, 0xa3, 0x94, 0xef, 0x6e, 0xff, 0xf7, 0x0d, 0xad, 0xf0, 0xec, 0xf3, 0xff, 0xab, 0xe2, 0x7f, 0xd7, 0xf3, 0xbf, 0x36,
+ 0xbd, 0xe6, 0xdf, 0xae, 0xbd, 0x12, 0xff, 0xd5, 0xf1, 0x5f, 0xb9, 0x76, 0xe2, 0xda, 0xbf, 0xa8, 0x7e, 0xff, 0xa7, 0x7e,
+ 0x24, 0x6d, 0xff, 0xfb, 0x3f, 0x7b, 0xca, 0xa7, 0x4d, 0xad, 0x98, 0xb6, 0xfe, 0xab, 0x6d, 0x72, 0x55, 0xe3, 0xd8, 0x3e,
+ 0xd7, 0xbf, 0x7d, 0x73, 0xf7, 0xf8, 0x8f, 0xbd, 0x6d, 0x10, 0xfd, 0x64, 0xfc, 0x13, 0xf7, 0x59, 0x0b, 0xec, 0x3b, 0xdf,
+ 0xa2, 0x54, 0x0a, 0xd5, 0x25, 0xa4, 0x54, 0x71, 0x07, 0x78, 0xd7, 0x7b, 0xe6, 0xbb, 0xfe, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0xcd, 0x5e, 0x99, 0xcd, 0xb9, 0xfd, 0xeb, 0x5f, 0x7b, 0x68, 0xbe,
+ 0x6b, 0x4f, 0x7e, 0xae, 0x2f, 0xe7, 0xc1, 0x58, 0x9b, 0x77, 0x5a, 0x91, 0x83, 0xa1, 0x3a, 0x8f, 0xd4, 0xb8, 0x5c, 0x66,
+ 0xcf, 0xf4, 0x78, 0x26, 0xf1, 0xea, 0x15, 0x12, 0x99, 0xd7, 0x93, 0xc9, 0xa8, 0x93, 0x59, 0x4b, 0x20, 0x9e, 0x09, 0xb1,
+ 0x2d, 0x7e, 0x6b, 0xec, 0xac, 0xfd, 0x3a, 0xbf, 0x3a, 0x9a, 0xef, 0xb3, 0x26, 0xfe, 0x63, 0xb9, 0x25, 0xaf, 0xc8, 0xb4,
+ 0x16, 0xbf, 0x9a, 0x6a, 0xf7, 0xb0, 0xbe, 0x54, 0xe6, 0xf6, 0x36, 0xf7, 0xf7, 0xcc, 0x9c, 0xfe, 0x5c, 0xee, 0x81, 0xd5,
+ 0x92, 0xe8, 0x53, 0xd9, 0x52, 0x56, 0x3f, 0xf9, 0xf9, 0x73, 0xc7, 0xdb, 0xfa, 0x54, 0xe6, 0x88, 0xd5, 0x6f, 0xfd, 0x6d,
+ 0xf0, 0xf9, 0x7e, 0x78, 0xe7, 0xad, 0x9d, 0xd1, 0xfa, 0x94, 0xf8, 0x5f, 0xbf, 0x77, 0x9f, 0x1d, 0xff, 0xf1, 0xfb, 0x54,
+ 0x2b, 0xcc, 0xd2, 0xb3, 0xbe, 0x36, 0x46, 0x64, 0xe6, 0x6e, 0x3e, 0x47, 0xd0, 0x19, 0x19, 0x35, 0x7e, 0x8d, 0xa6, 0x95,
+ 0xb3, 0x36, 0x17, 0xfd, 0x9f, 0xe2, 0xf7, 0xa8, 0xb5, 0xb5, 0x2f, 0xfe, 0x6b, 0x32, 0xf2, 0x3d, 0x27, 0xfe, 0x67, 0x7a,
+ 0x1b, 0xe7, 0xc5, 0xff, 0xf8, 0xef, 0x75, 0x59, 0xb5, 0x2b, 0x73, 0xed, 0x8c, 0x72, 0x2d, 0xb7, 0xd0, 0x19, 0xe9, 0xc1,
+ 0xfb, 0x4a, 0x2f, 0xce, 0x67, 0xde, 0x7f, 0xfc, 0x3f, 0x5b, 0x53, 0xcf, 0xc6, 0xff, 0xfa, 0x2f, 0xfe, 0x36, 0xd1, 0x7e,
+ 0xa8, 0x6e, 0xff, 0xaf, 0x5c, 0x2f, 0x4f, 0x8a, 0xff, 0x36, 0x95, 0x8b, 0xec, 0xde, 0xf5, 0x7f, 0x65, 0x4e, 0xad, 0xfa,
+ 0xf8, 0x8f, 0x45, 0x78, 0xa4, 0x26, 0x9f, 0x5f, 0xf1, 0x60, 0xed, 0xbc, 0x8d, 0x5b, 0xf9, 0x3d, 0xd1, 0xfe, 0xdf, 0x11,
+ 0xff, 0xd5, 0xe3, 0x7f, 0xf1, 0x35, 0x3c, 0xf6, 0x8c, 0x74, 0x45, 0xc6, 0xff, 0xda, 0x09, 0xfd, 0xff, 0x51, 0x3b, 0x31,
+ 0x5a, 0x2a, 0xf5, 0x6b, 0x53, 0x55, 0x66, 0xdb, 0x5e, 0x8d, 0xff, 0x4c, 0xfd, 0x1f, 0x1d, 0x87, 0xc8, 0xb4, 0x10, 0xdb,
+ 0x60, 0xe4, 0x60, 0xf4, 0x9b, 0xeb, 0x59, 0x43, 0x73, 0xed, 0xff, 0x1d, 0xf1, 0x7f, 0x56, 0xff, 0xbf, 0x25, 0x47, 0x35,
+ 0xeb, 0xda, 0xff, 0x2d, 0xd1, 0xca, 0xcc, 0xdc, 0x6d, 0x22, 0xa5, 0xbd, 0x5e, 0x66, 0x57, 0xd6, 0xff, 0xb9, 0xd5, 0xe6,
+ 0xda, 0xb6, 0x7c, 0xa7, 0x91, 0xf6, 0xff, 0x9e, 0xa7, 0x70, 0xcf, 0xae, 0xff, 0xcf, 0x7c, 0x3a, 0xb9, 0x73, 0x7f, 0xee,
+ 0x93, 0x77, 0x6e, 0x4f, 0x1e, 0xe9, 0x3b, 0xf4, 0xff, 0x23, 0xe3, 0xff, 0xd1, 0x9c, 0xc7, 0xe3, 0xda, 0xb8, 0x0f, 0x46,
+ 0xd3, 0xbe, 0x35, 0xfe, 0xef, 0x91, 0x9b, 0xf9, 0x7b, 0xe3, 0xbf, 0xa5, 0xf2, 0x4f, 0x5f, 0x11, 0xff, 0x73, 0x2d, 0xab,
+ 0xd8, 0x8a, 0x88, 0xb9, 0x15, 0x93, 0xa3, 0x7d, 0xba, 0x76, 0xea, 0x95, 0x9e, 0x79, 0xfe, 0xb7, 0xe7, 0xfd, 0x9f, 0xda,
+ 0x37, 0x0d, 0x9e, 0xfb, 0x3e, 0xd4, 0x3b, 0x8e, 0xe0, 0x8c, 0xfb, 0xf9, 0x78, 0xd5, 0x82, 0xbe, 0xe9, 0x98, 0x62, 0x4f,
+ 0x75, 0xa3, 0xcf, 0x89, 0xf7, 0xdd, 0xef, 0xa3, 0xef, 0xff, 0x44, 0xcb, 0x54, 0xa6, 0xe5, 0x6f, 0xb9, 0x83, 0x5d, 0x19,
+ 0xff, 0xfb, 0x5b, 0x49, 0x55, 0xef, 0x30, 0x7c, 0xdb, 0x95, 0xa2, 0x64, 0xbe, 0xe5, 0xbc, 0xae, 0x8f, 0xf4, 0xbe, 0xa5,
+ 0x24, 0x5c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3b, 0xe7, 0x8a, 0xf5, 0xb2,
+ 0x4c, 0x0b, 0xb3, 0x79, 0xae, 0xfa, 0xc2, 0xcc, 0xcd, 0x36, 0xcc, 0xdd, 0x9c, 0xfd, 0x9e, 0x9f, 0xab, 0x1a, 0xf4, 0xc1,
+ 0xbf, 0x68, 0x81, 0x3d, 0xed, 0xe1, 0x79, 0xc8, 0xeb, 0x6b, 0x34, 0xfc, 0xdc, 0xe3, 0x96, 0x28, 0x91, 0x36, 0x31, 0x4f,
+ 0x75, 0x6d, 0xae, 0xde, 0xee, 0x63, 0xae, 0xc9, 0x96, 0x1e, 0xc9, 0xfb, 0x37, 0x9b, 0xbd, 0x64, 0x47, 0xa9, 0xe4, 0x66,
+ 0xbb, 0xf7, 0xa5, 0xbf, 0xc7, 0x72, 0x3f, 0xf4, 0xc3, 0x18, 0xaa, 0xb9, 0x3f, 0xcd, 0x65, 0xe8, 0x5b, 0x9f, 0xb3, 0x3e,
+ 0x97, 0xdf, 0xb3, 0x6d, 0xcc, 0x89, 0xbd, 0x7e, 0xb5, 0xc7, 0x23, 0x25, 0xb7, 0x75, 0x6e, 0xae, 0xfe, 0x8e, 0x63, 0x8e,
+ 0xe7, 0xb3, 0x9d, 0xff, 0x9e, 0x4c, 0xed, 0x37, 0x9e, 0x85, 0x99, 0xa9, 0x27, 0xda, 0xd4, 0xdd, 0x7a, 0x2d, 0xca, 0xa3,
+ 0x77, 0x99, 0xf5, 0xf8, 0xaf, 0x99, 0x83, 0xde, 0x87, 0xc7, 0x13, 0x5b, 0x81, 0x63, 0x26, 0xbf, 0xf7, 0xfb, 0x5a, 0x8b,
+ 0xf9, 0xf8, 0xff, 0xd6, 0x36, 0xf6, 0xfd, 0x4a, 0xa0, 0x2f, 0xd6, 0xf1, 0x9f, 0x23, 0x6c, 0xa6, 0x15, 0x5f, 0x13, 0xff,
+ 0xeb, 0xf7, 0xad, 0xfd, 0xf1, 0xdf, 0x43, 0xdf, 0x10, 0x6d, 0xcf, 0xde, 0x73, 0x6b, 0x2e, 0xfe, 0xc7, 0x57, 0xd0, 0x9e,
+ 0xad, 0x55, 0xab, 0x28, 0xe5, 0x72, 0x94, 0xb7, 0x60, 0xef, 0x21, 0x9b, 0x11, 0x68, 0x35, 0x1b, 0x5b, 0x0f, 0xf5, 0x46,
+ 0xf6, 0xd4, 0xff, 0xf9, 0xfe, 0xff, 0x7c, 0xbb, 0x2d, 0x3e, 0x7e, 0x90, 0xb9, 0x96, 0x76, 0xb4, 0xc3, 0xcf, 0xd8, 0x1a,
+ 0xc9, 0x1b, 0x77, 0xd5, 0xd6, 0xdd, 0xf1, 0xdf, 0xff, 0xb3, 0x8e, 0xe2, 0x51, 0x44, 0xad, 0xdf, 0x1d, 0xee, 0xd7, 0xb2,
+ 0x88, 0x8f, 0xff, 0xad, 0x1e, 0x43, 0xc5, 0x11, 0xcf, 0xf5, 0x0b, 0x67, 0xa3, 0xb4, 0xae, 0xfe, 0xcf, 0x9c, 0xf5, 0x2b,
+ 0xb7, 0x66, 0x46, 0xf7, 0xde, 0x1a, 0xff, 0x73, 0xe5, 0x76, 0x45, 0xfc, 0x57, 0xe7, 0x13, 0x9c, 0x69, 0x4d, 0x44, 0xb3,
+ 0x34, 0x5f, 0xd1, 0x97, 0x9c, 0xcd, 0xce, 0x9f, 0x5b, 0x7f, 0xf6, 0x4d, 0xf1, 0xdf, 0x8a, 0xda, 0xff, 0x67, 0x6e, 0xbd,
+ 0x47, 0xfb, 0xbf, 0xbf, 0xa0, 0xfe, 0xcf, 0x3e, 0xd7, 0x99, 0x3f, 0x86, 0x73, 0x8e, 0x36, 0x9e, 0x81, 0x3f, 0xf3, 0x04,
+ 0xe3, 0xca, 0xbe, 0x70, 0x76, 0x6b, 0x36, 0xfe, 0xbf, 0xb5, 0xfe, 0x7f, 0x43, 0xfc, 0xe7, 0x9f, 0x65, 0xaf, 0x8c, 0xff,
+ 0x9d, 0x75, 0x44, 0xf9, 0xf6, 0x51, 0xee, 0xd9, 0xff, 0x3b, 0xeb, 0xff, 0x9a, 0x35, 0xe7, 0x9f, 0x16, 0xff, 0x33, 0xa3,
+ 0x4c, 0x4f, 0x8d, 0xff, 0x8a, 0x18, 0xa9, 0x1a, 0xff, 0xaf, 0xbe, 0x03, 0xb4, 0xad, 0x99, 0xeb, 0x9f, 0x17, 0xe1, 0xe3,
+ 0xf8, 0x8f, 0xbc, 0xff, 0xf3, 0xee, 0xf8, 0x9f, 0x7b, 0x37, 0xe6, 0xd9, 0xf1, 0xdf, 0x93, 0x2b, 0xd6, 0xbc, 0xf3, 0xf9,
+ 0x70, 0x6c, 0xfd, 0xe9, 0xe7, 0xc5, 0x7f, 0xfc, 0xed, 0x8c, 0xb7, 0x3f, 0xff, 0xcb, 0xbd, 0x1d, 0xb0, 0xf7, 0xf9, 0xdf,
+ 0x13, 0xde, 0x2b, 0xe1, 0x4d, 0xf7, 0x42, 0xe7, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x6a, 0x46, 0x46, 0x3c, 0x67, 0xcf, 0xdc, 0x4c, 0xb1, 0x6b, 0x72, 0xdf, 0x47, 0x32, 0x15, 0xcc, 0xec, 0x4f, 0x3c,
+ 0xff, 0x41, 0x24, 0xdb, 0xfe, 0xd1, 0xb9, 0x89, 0xe6, 0x1c, 0xcf, 0xe4, 0x32, 0xda, 0x75, 0x8c, 0xeb, 0x59, 0xe1, 0xe7,
+ 0x7f, 0x61, 0x2e, 0xf7, 0x63, 0x2c, 0x2e, 0xee, 0x71, 0xae, 0x33, 0xf3, 0xee, 0x76, 0x67, 0x8a, 0xef, 0xc9, 0x5c, 0xef,
+ 0xf5, 0x7b, 0x95, 0xcd, 0xd3, 0x1f, 0xdb, 0xe7, 0x48, 0x09, 0xf7, 0xc4, 0x4a, 0x2c, 0x6d, 0xe2, 0x4a, 0xaa, 0xce, 0xef,
+ 0x93, 0x59, 0x99, 0x63, 0xfe, 0x8e, 0x5c, 0x99, 0xb3, 0xbf, 0x25, 0xf2, 0xf5, 0xdf, 0xe5, 0x5c, 0xdf, 0xb5, 0x65, 0x71,
+ 0x9c, 0xf1, 0xe8, 0xbe, 0xad, 0xa4, 0x1e, 0xca, 0x6e, 0xfa, 0x9c, 0x7c, 0x04, 0xb1, 0x3a, 0xf7, 0xbd, 0xed, 0xe2, 0xf7,
+ 0x1f, 0x73, 0x26, 0xb7, 0xc0, 0x4c, 0x1d, 0xde, 0x02, 0xf1, 0x7f, 0xc7, 0xfc, 0x55, 0xb9, 0xcc, 0x57, 0x33, 0xa5, 0x78,
+ 0xd6, 0xb6, 0x23, 0xbf, 0x07, 0x56, 0x62, 0xbb, 0xf2, 0x18, 0xf7, 0xe7, 0xec, 0x38, 0xce, 0x26, 0xf2, 0xe4, 0x73, 0xdd,
+ 0xb6, 0xe7, 0x82, 0x89, 0xd6, 0xff, 0x4f, 0x8d, 0xff, 0xd1, 0x6a, 0x04, 0x9f, 0xd7, 0x25, 0x3b, 0x6f, 0x5b, 0xc5, 0x5a,
+ 0x06, 0xab, 0x3d, 0xa0, 0x1d, 0xdb, 0xae, 0xcc, 0xd9, 0x75, 0xf6, 0xb1, 0xc6, 0xcb, 0xe8, 0xca, 0xf8, 0x9f, 0xe9, 0xd7,
+ 0x7d, 0x5b, 0xfd, 0xdf, 0x2f, 0xdf, 0x36, 0x7f, 0x17, 0xbb, 0xfb, 0xb5, 0xbd, 0x7f, 0xcd, 0x8e, 0x27, 0xc4, 0xf8, 0x5d,
+ 0xe3, 0xff, 0xaa, 0x8c, 0xc7, 0x35, 0x2b, 0x2d, 0x45, 0xfb, 0xff, 0x4f, 0xb8, 0x26, 0x7a, 0x72, 0x2d, 0xe3, 0xd8, 0x0a,
+ 0xce, 0xd5, 0xdb, 0xc4, 0xff, 0xdd, 0xeb, 0xff, 0x99, 0xb1, 0x95, 0xfb, 0xe5, 0xaf, 0xcc, 0xae, 0xd3, 0xfb, 0xee, 0xeb,
+ 0xa5, 0x85, 0x9e, 0x79, 0xed, 0xd8, 0x26, 0xfe, 0xc5, 0xbf, 0xf8, 0xbf, 0xe2, 0x7a, 0xe9, 0x5f, 0xd1, 0xff, 0x17, 0xff,
+ 0xe2, 0x3f, 0xf2, 0xcc, 0xec, 0xfe, 0xfd, 0xff, 0x5d, 0x4f, 0x2a, 0xdf, 0x36, 0xfe, 0x1f, 0x7d, 0xda, 0xfb, 0xa4, 0xf1,
+ 0xff, 0xdd, 0xcf, 0xff, 0xae, 0xf8, 0xdd, 0xdc, 0x3e, 0xbf, 0xff, 0x19, 0xf7, 0x3b, 0xf2, 0xc5, 0xf3, 0xfc, 0xeb, 0x50,
+ 0x19, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe7, 0x00, 0xaf, 0xbe,
+ 0xa7, 0x7f, 0x66, 0xbe, 0xf7, 0xc8, 0x9c, 0xcf, 0xb9, 0xef, 0x04, 0xf1, 0x1f, 0x9b, 0xa7, 0x73, 0x66, 0xbe, 0xf7, 0xfc,
+ 0xdc, 0x7c, 0xe7, 0x1a, 0xde, 0x37, 0x53, 0x5c, 0x6c, 0x43, 0x2e, 0xc2, 0xa3, 0x39, 0x3a, 0xef, 0xb2, 0xed, 0x1d, 0x2b,
+ 0x73, 0xc0, 0xbd, 0x6a, 0xd5, 0xa7, 0xc4, 0x7f, 0xdb, 0x96, 0xef, 0x12, 0xbe, 0xb1, 0xff, 0x2f, 0xfe, 0x41, 0xfc, 0x8b,
+ 0x7f, 0xd0, 0xfe, 0x17, 0xff, 0x60, 0xfc, 0xff, 0xaa, 0x58, 0x9d, 0x59, 0x27, 0xe6, 0xc9, 0x4f, 0x31, 0xe0, 0x7e, 0x77,
+ 0x80, 0xf8, 0xdd, 0xa1, 0x7a, 0x5b, 0x1b, 0xde, 0x37, 0x3c, 0x23, 0x84, 0xb3, 0xe2, 0xff, 0x9a, 0x51, 0x8a, 0xd5, 0xf8,
+ 0xd7, 0xfe, 0x87, 0x37, 0xf5, 0x46, 0x22, 0xef, 0xff, 0x89, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe9, 0xaf, 0xff, 0x94, 0x03, 0x88, 0x7f, 0xe0, 0xeb, 0xe2, 0xff,
+ 0x0f };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle enefeteFontRecs[189] = {
+ { 4, 4, 4 , 16 },
+ { 16, 4, 2 , 10 },
+ { 26, 4, 5 , 3 },
+ { 39, 4, 7 , 10 },
+ { 54, 4, 7 , 13 },
+ { 69, 4, 7 , 10 },
+ { 84, 4, 7 , 10 },
+ { 99, 4, 2 , 3 },
+ { 109, 4, 3 , 12 },
+ { 120, 4, 3 , 12 },
+ { 131, 4, 5 , 6 },
+ { 144, 4, 6 , 5 },
+ { 158, 4, 2 , 4 },
+ { 168, 4, 5 , 1 },
+ { 181, 4, 2 , 2 },
+ { 191, 4, 4 , 10 },
+ { 203, 4, 6 , 10 },
+ { 217, 4, 4 , 10 },
+ { 229, 4, 6 , 10 },
+ { 243, 4, 6 , 10 },
+ { 257, 4, 6 , 10 },
+ { 271, 4, 6 , 10 },
+ { 285, 4, 6 , 10 },
+ { 299, 4, 6 , 10 },
+ { 313, 4, 6 , 10 },
+ { 327, 4, 6 , 10 },
+ { 341, 4, 2 , 6 },
+ { 351, 4, 2 , 8 },
+ { 361, 4, 7 , 7 },
+ { 376, 4, 5 , 3 },
+ { 389, 4, 7 , 7 },
+ { 404, 4, 6 , 10 },
+ { 418, 4, 7 , 12 },
+ { 433, 4, 7 , 10 },
+ { 448, 4, 7 , 10 },
+ { 463, 4, 7 , 10 },
+ { 478, 4, 7 , 10 },
+ { 493, 4, 7 , 10 },
+ { 4, 28, 7 , 10 },
+ { 19, 28, 7 , 10 },
+ { 34, 28, 7 , 10 },
+ { 49, 28, 2 , 10 },
+ { 59, 28, 5 , 10 },
+ { 72, 28, 7 , 10 },
+ { 87, 28, 6 , 10 },
+ { 101, 28, 9 , 10 },
+ { 118, 28, 7 , 10 },
+ { 133, 28, 7 , 10 },
+ { 148, 28, 7 , 10 },
+ { 163, 28, 7 , 12 },
+ { 178, 28, 7 , 10 },
+ { 193, 28, 7 , 10 },
+ { 208, 28, 6 , 10 },
+ { 222, 28, 7 , 10 },
+ { 237, 28, 7 , 10 },
+ { 252, 28, 8 , 10 },
+ { 268, 28, 7 , 10 },
+ { 283, 28, 6 , 10 },
+ { 297, 28, 7 , 10 },
+ { 312, 28, 4 , 12 },
+ { 324, 28, 4 , 10 },
+ { 336, 28, 4 , 12 },
+ { 348, 28, 6 , 3 },
+ { 362, 28, 7 , 1 },
+ { 377, 28, 4 , 3 },
+ { 389, 28, 6 , 7 },
+ { 403, 28, 6 , 10 },
+ { 417, 28, 6 , 7 },
+ { 431, 28, 6 , 10 },
+ { 445, 28, 6 , 7 },
+ { 459, 28, 4 , 10 },
+ { 471, 28, 6 , 9 },
+ { 485, 28, 6 , 10 },
+ { 499, 28, 2 , 10 },
+ { 4, 52, 5 , 12 },
+ { 17, 52, 6 , 10 },
+ { 31, 52, 3 , 10 },
+ { 42, 52, 8 , 7 },
+ { 58, 52, 6 , 7 },
+ { 72, 52, 6 , 7 },
+ { 86, 52, 6 , 9 },
+ { 100, 52, 6 , 9 },
+ { 114, 52, 5 , 7 },
+ { 127, 52, 6 , 7 },
+ { 141, 52, 4 , 10 },
+ { 153, 52, 6 , 7 },
+ { 167, 52, 6 , 7 },
+ { 181, 52, 8 , 7 },
+ { 197, 52, 6 , 7 },
+ { 211, 52, 6 , 9 },
+ { 225, 52, 6 , 7 },
+ { 239, 52, 5 , 12 },
+ { 252, 52, 2 , 12 },
+ { 262, 52, 5 , 12 },
+ { 275, 52, 7 , 3 },
+ { 290, 52, 2 , 9 },
+ { 300, 52, 6 , 11 },
+ { 314, 52, 7 , 10 },
+ { 329, 52, 7 , 9 },
+ { 344, 52, 6 , 10 },
+ { 358, 52, 7 , 11 },
+ { 373, 52, 6 , 12 },
+ { 387, 52, 6 , 10 },
+ { 401, 52, 7 , 10 },
+ { 416, 52, 5 , 5 },
+ { 429, 52, 7 , 6 },
+ { 444, 52, 6 , 3 },
+ { 458, 52, 7 , 10 },
+ { 473, 52, 9 , 10 },
+ { 490, 52, 4 , 4 },
+ { 4, 76, 6 , 7 },
+ { 18, 76, 4 , 5 },
+ { 30, 76, 4 , 5 },
+ { 42, 76, 7 , 11 },
+ { 57, 76, 6 , 9 },
+ { 71, 76, 7 , 12 },
+ { 86, 76, 2 , 2 },
+ { 96, 76, 6 , 10 },
+ { 110, 76, 3 , 5 },
+ { 121, 76, 4 , 5 },
+ { 133, 76, 7 , 6 },
+ { 148, 76, 9 , 10 },
+ { 165, 76, 8 , 7 },
+ { 181, 76, 6 , 11 },
+ { 195, 76, 6 , 11 },
+ { 209, 76, 7 , 11 },
+ { 224, 76, 7 , 11 },
+ { 239, 76, 7 , 11 },
+ { 254, 76, 7 , 11 },
+ { 269, 76, 7 , 11 },
+ { 284, 76, 7 , 11 },
+ { 299, 76, 9 , 10 },
+ { 316, 76, 7 , 12 },
+ { 331, 76, 7 , 11 },
+ { 346, 76, 7 , 11 },
+ { 361, 76, 7 , 11 },
+ { 376, 76, 7 , 11 },
+ { 391, 76, 3 , 11 },
+ { 402, 76, 3 , 11 },
+ { 413, 76, 5 , 11 },
+ { 426, 76, 5 , 11 },
+ { 439, 76, 8 , 10 },
+ { 455, 76, 7 , 11 },
+ { 470, 76, 7 , 11 },
+ { 485, 76, 7 , 11 },
+ { 4, 100, 7 , 11 },
+ { 19, 100, 7 , 11 },
+ { 34, 100, 7 , 11 },
+ { 49, 100, 7 , 7 },
+ { 64, 100, 7 , 13 },
+ { 79, 100, 7 , 11 },
+ { 94, 100, 7 , 11 },
+ { 109, 100, 7 , 11 },
+ { 124, 100, 7 , 11 },
+ { 139, 100, 6 , 11 },
+ { 153, 100, 7 , 10 },
+ { 168, 100, 7 , 10 },
+ { 183, 100, 6 , 10 },
+ { 197, 100, 6 , 10 },
+ { 211, 100, 6 , 10 },
+ { 225, 100, 6 , 10 },
+ { 239, 100, 6 , 10 },
+ { 253, 100, 6 , 11 },
+ { 267, 100, 8 , 7 },
+ { 283, 100, 6 , 9 },
+ { 297, 100, 6 , 10 },
+ { 311, 100, 6 , 10 },
+ { 325, 100, 6 , 10 },
+ { 339, 100, 6 , 10 },
+ { 353, 100, 3 , 10 },
+ { 364, 100, 3 , 10 },
+ { 375, 100, 5 , 10 },
+ { 388, 100, 5 , 10 },
+ { 401, 100, 6 , 10 },
+ { 415, 100, 6 , 10 },
+ { 429, 100, 6 , 10 },
+ { 443, 100, 6 , 10 },
+ { 457, 100, 6 , 10 },
+ { 471, 100, 6 , 10 },
+ { 485, 100, 6 , 10 },
+ { 4, 124, 6 , 7 },
+ { 18, 124, 7 , 11 },
+ { 33, 124, 6 , 10 },
+ { 47, 124, 6 , 10 },
+ { 61, 124, 6 , 10 },
+ { 75, 124, 6 , 10 },
+ { 89, 124, 6 , 12 },
+ { 103, 124, 6 , 12 },
+ { 117, 124, 6 , 12 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo enefeteFontGlyphs[189] = {
+ { 32, 0, 12, 4, { 0 }},
+ { 33, 0, 2, 3, { 0 }},
+ { 34, 0, 2, 6, { 0 }},
+ { 35, 0, 2, 8, { 0 }},
+ { 36, 0, 1, 8, { 0 }},
+ { 37, 0, 2, 8, { 0 }},
+ { 38, 0, 2, 8, { 0 }},
+ { 39, 0, 2, 3, { 0 }},
+ { 40, 0, 2, 4, { 0 }},
+ { 41, 0, 2, 4, { 0 }},
+ { 42, 0, 4, 6, { 0 }},
+ { 43, 0, 6, 7, { 0 }},
+ { 44, 0, 10, 3, { 0 }},
+ { 45, 0, 8, 6, { 0 }},
+ { 46, 0, 10, 3, { 0 }},
+ { 47, 0, 2, 5, { 0 }},
+ { 48, 0, 2, 7, { 0 }},
+ { 49, 0, 2, 7, { 0 }},
+ { 50, 0, 2, 7, { 0 }},
+ { 51, 0, 2, 7, { 0 }},
+ { 52, 0, 2, 7, { 0 }},
+ { 53, 0, 2, 7, { 0 }},
+ { 54, 0, 2, 7, { 0 }},
+ { 55, 0, 2, 7, { 0 }},
+ { 56, 0, 2, 7, { 0 }},
+ { 57, 0, 2, 7, { 0 }},
+ { 58, 0, 4, 3, { 0 }},
+ { 59, 0, 4, 3, { 0 }},
+ { 60, 0, 4, 8, { 0 }},
+ { 61, 0, 6, 6, { 0 }},
+ { 62, 0, 4, 8, { 0 }},
+ { 63, 0, 2, 7, { 0 }},
+ { 64, 0, 2, 8, { 0 }},
+ { 65, 0, 2, 8, { 0 }},
+ { 66, 0, 2, 8, { 0 }},
+ { 67, 0, 2, 8, { 0 }},
+ { 68, 0, 2, 8, { 0 }},
+ { 69, 0, 2, 8, { 0 }},
+ { 70, 0, 2, 8, { 0 }},
+ { 71, 0, 2, 8, { 0 }},
+ { 72, 0, 2, 8, { 0 }},
+ { 73, 0, 2, 3, { 0 }},
+ { 74, 0, 2, 6, { 0 }},
+ { 75, 0, 2, 8, { 0 }},
+ { 76, 0, 2, 7, { 0 }},
+ { 77, 0, 2, 10, { 0 }},
+ { 78, 0, 2, 8, { 0 }},
+ { 79, 0, 2, 8, { 0 }},
+ { 80, 0, 2, 8, { 0 }},
+ { 81, 0, 2, 8, { 0 }},
+ { 82, 0, 2, 8, { 0 }},
+ { 83, 0, 2, 8, { 0 }},
+ { 84, 0, 2, 7, { 0 }},
+ { 85, 0, 2, 8, { 0 }},
+ { 86, 0, 2, 8, { 0 }},
+ { 87, 0, 2, 9, { 0 }},
+ { 88, 0, 2, 8, { 0 }},
+ { 89, 0, 2, 7, { 0 }},
+ { 90, 0, 2, 8, { 0 }},
+ { 91, 0, 2, 5, { 0 }},
+ { 92, 0, 2, 5, { 0 }},
+ { 93, 0, 2, 5, { 0 }},
+ { 94, 0, 2, 7, { 0 }},
+ { 95, 0, 14, 8, { 0 }},
+ { 96, 0, 2, 5, { 0 }},
+ { 97, 0, 5, 7, { 0 }},
+ { 98, 0, 2, 7, { 0 }},
+ { 99, 0, 5, 7, { 0 }},
+ { 100, 0, 2, 7, { 0 }},
+ { 101, 0, 5, 7, { 0 }},
+ { 102, 0, 2, 5, { 0 }},
+ { 103, 0, 5, 7, { 0 }},
+ { 104, 0, 2, 7, { 0 }},
+ { 105, 0, 2, 3, { 0 }},
+ { 106, 0, 2, 6, { 0 }},
+ { 107, 0, 2, 7, { 0 }},
+ { 108, 0, 2, 4, { 0 }},
+ { 109, 0, 5, 9, { 0 }},
+ { 110, 0, 5, 7, { 0 }},
+ { 111, 0, 5, 7, { 0 }},
+ { 112, 0, 5, 7, { 0 }},
+ { 113, 0, 5, 7, { 0 }},
+ { 114, 0, 5, 6, { 0 }},
+ { 115, 0, 5, 7, { 0 }},
+ { 116, 0, 2, 5, { 0 }},
+ { 117, 0, 5, 7, { 0 }},
+ { 118, 0, 5, 7, { 0 }},
+ { 119, 0, 5, 9, { 0 }},
+ { 120, 0, 5, 7, { 0 }},
+ { 121, 0, 5, 7, { 0 }},
+ { 122, 0, 5, 7, { 0 }},
+ { 123, 0, 2, 6, { 0 }},
+ { 124, 0, 2, 3, { 0 }},
+ { 125, 0, 2, 6, { 0 }},
+ { 126, 0, 6, 8, { 0 }},
+ { 161, 0, 5, 3, { 0 }},
+ { 162, 0, 3, 7, { 0 }},
+ { 163, 0, 2, 8, { 0 }},
+ { 8364, 0, 3, 8, { 0 }},
+ { 165, 0, 2, 7, { 0 }},
+ { 352, 0, 1, 8, { 0 }},
+ { 167, 0, 2, 7, { 0 }},
+ { 353, 0, 2, 7, { 0 }},
+ { 169, 0, 2, 8, { 0 }},
+ { 170, 0, 2, 6, { 0 }},
+ { 171, 0, 6, 8, { 0 }},
+ { 172, 0, 7, 7, { 0 }},
+ { 174, 0, 2, 8, { 0 }},
+ { 175, 1, 3, 14, { 0 }},
+ { 176, 0, 2, 5, { 0 }},
+ { 177, 0, 4, 7, { 0 }},
+ { 178, 0, 2, 5, { 0 }},
+ { 179, 0, 2, 5, { 0 }},
+ { 381, 0, 1, 8, { 0 }},
+ { 181, 0, 5, 7, { 0 }},
+ { 182, 0, 2, 8, { 0 }},
+ { 183, 0, 6, 3, { 0 }},
+ { 382, 0, 2, 7, { 0 }},
+ { 185, 0, 2, 4, { 0 }},
+ { 186, 0, 2, 5, { 0 }},
+ { 187, 0, 6, 8, { 0 }},
+ { 338, 0, 2, 10, { 0 }},
+ { 339, 0, 5, 9, { 0 }},
+ { 376, 0, 1, 7, { 0 }},
+ { 191, 0, 3, 7, { 0 }},
+ { 192, 0, 1, 8, { 0 }},
+ { 193, 0, 1, 8, { 0 }},
+ { 194, 0, 1, 8, { 0 }},
+ { 195, 0, 1, 8, { 0 }},
+ { 196, 0, 1, 8, { 0 }},
+ { 197, 0, 1, 8, { 0 }},
+ { 198, 0, 2, 10, { 0 }},
+ { 199, 0, 2, 8, { 0 }},
+ { 200, 0, 1, 8, { 0 }},
+ { 201, 0, 1, 8, { 0 }},
+ { 202, 0, 1, 8, { 0 }},
+ { 203, 0, 1, 8, { 0 }},
+ { 204, 0, 1, 4, { 0 }},
+ { 205, 0, 1, 4, { 0 }},
+ { 206, 0, 1, 6, { 0 }},
+ { 207, 0, 1, 6, { 0 }},
+ { 208, 0, 2, 9, { 0 }},
+ { 209, 0, 1, 8, { 0 }},
+ { 210, 0, 1, 8, { 0 }},
+ { 211, 0, 1, 8, { 0 }},
+ { 212, 0, 1, 8, { 0 }},
+ { 213, 0, 1, 8, { 0 }},
+ { 214, 0, 1, 8, { 0 }},
+ { 215, 0, 5, 8, { 0 }},
+ { 216, 0, 1, 8, { 0 }},
+ { 217, 0, 1, 8, { 0 }},
+ { 218, 0, 1, 8, { 0 }},
+ { 219, 0, 1, 8, { 0 }},
+ { 220, 0, 1, 8, { 0 }},
+ { 221, 0, 1, 7, { 0 }},
+ { 222, 0, 2, 8, { 0 }},
+ { 223, 0, 2, 8, { 0 }},
+ { 224, 0, 2, 7, { 0 }},
+ { 225, 0, 2, 7, { 0 }},
+ { 226, 0, 2, 7, { 0 }},
+ { 227, 0, 2, 7, { 0 }},
+ { 228, 0, 2, 7, { 0 }},
+ { 229, 0, 1, 7, { 0 }},
+ { 230, 0, 5, 9, { 0 }},
+ { 231, 0, 5, 7, { 0 }},
+ { 232, 0, 2, 7, { 0 }},
+ { 233, 0, 2, 7, { 0 }},
+ { 234, 0, 2, 7, { 0 }},
+ { 235, 0, 2, 7, { 0 }},
+ { 236, 0, 2, 4, { 0 }},
+ { 237, 0, 2, 4, { 0 }},
+ { 238, 0, 2, 6, { 0 }},
+ { 239, 0, 2, 6, { 0 }},
+ { 240, 0, 2, 7, { 0 }},
+ { 241, 0, 2, 7, { 0 }},
+ { 242, 0, 2, 7, { 0 }},
+ { 243, 0, 2, 7, { 0 }},
+ { 244, 0, 2, 7, { 0 }},
+ { 245, 0, 2, 7, { 0 }},
+ { 246, 0, 2, 7, { 0 }},
+ { 247, 0, 4, 7, { 0 }},
+ { 248, 0, 3, 8, { 0 }},
+ { 249, 0, 2, 7, { 0 }},
+ { 250, 0, 2, 7, { 0 }},
+ { 251, 0, 2, 7, { 0 }},
+ { 252, 0, 2, 7, { 0 }},
+ { 253, 0, 2, 7, { 0 }},
+ { 254, 0, 2, 7, { 0 }},
+ { 255, 0, 2, 7, { 0 }},
+};
+
+// Style loading function: Enefete
+static void GuiLoadStyleEnefete(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < ENEFETE_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(enefeteStyleProps[i].controlId, enefeteStyleProps[i].propertyId, enefeteStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int enefeteFontDataSize = 0;
+ unsigned char *data = DecompressData(enefeteFontData, ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE, &enefeteFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 16;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, enefeteFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, enefeteFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_jungle.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_jungle.h
new file mode 100644
index 0000000000..8e9a5a31d5
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_jungle.h
@@ -0,0 +1,578 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleJungle(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define JUNGLE_STYLE_PROPS_COUNT 17
+
+// Custom style name: Jungle
+static const GuiStyleProp jungleStyleProps[JUNGLE_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0x60827dff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x2c3334ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0x82a29fff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0x5f9aa8ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0x334e57ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0x6aa9b8ff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0xa9cb8dff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0x3b6357ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0x97af81ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x5b6462ff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x2c3334ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x666b69ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x0000000c }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0x638465ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x2b3a3aff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000012 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "Pixel Intv.otf" (size: 12, spacing: 0)
+
+#define JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE 2030
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char jungleFontData[JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0x9d, 0x3d, 0x8e, 0x25, 0x35, 0x14, 0x85, 0x8d, 0xe9, 0x8c, 0x10, 0x11, 0x80, 0x84, 0x20, 0x41, 0x22, 0x21, 0x61, 0x34,
+ 0x12, 0x64, 0xb3, 0x00, 0x62, 0x84, 0x08, 0x10, 0x11, 0x09, 0xb0, 0x07, 0x66, 0x65, 0x93, 0x90, 0xb3, 0x01, 0x76, 0xc1,
+ 0x02, 0x2e, 0x9a, 0xbf, 0x9e, 0x9f, 0xae, 0xb2, 0x7d, 0x8f, 0xaf, 0xcb, 0xae, 0x7a, 0x5f, 0x7f, 0x9a, 0xd1, 0xcc, 0xf3,
+ 0x73, 0x95, 0xcb, 0xc7, 0xd7, 0x55, 0xaf, 0x7d, 0xde, 0xb5, 0x25, 0x00, 0x00, 0x00, 0x80, 0x07, 0x3c, 0xff, 0xd9, 0x7e,
+ 0x6d, 0xab, 0x24, 0xbd, 0x2a, 0x69, 0x3f, 0xd6, 0xeb, 0xd7, 0x5f, 0x96, 0xe4, 0xdd, 0x77, 0x6c, 0x1f, 0x31, 0xef, 0xb4,
+ 0x61, 0xaf, 0xd5, 0xfb, 0x2d, 0x4b, 0xae, 0x92, 0xfd, 0xe3, 0xef, 0xf7, 0x57, 0x72, 0x5c, 0xc3, 0xbb, 0x3f, 0xc9, 0x71,
+ 0x2d, 0xe5, 0x7a, 0xa3, 0xf5, 0x2f, 0xf7, 0xc1, 0x7e, 0xd9, 0xcb, 0x3f, 0xcf, 0x7b, 0x22, 0x3b, 0x8e, 0xb9, 0xff, 0xfe,
+ 0xe4, 0x1a, 0x81, 0xfe, 0x91, 0xe1, 0xeb, 0xdd, 0xd2, 0xbb, 0x6b, 0xd7, 0x60, 0xce, 0x16, 0xbc, 0x7e, 0x7d, 0xa4, 0xfe,
+ 0xe9, 0xfe, 0x1c, 0xed, 0xf1, 0x5f, 0x53, 0xc5, 0xec, 0x6e, 0xb3, 0x27, 0x52, 0x51, 0x9b, 0x2c, 0x9c, 0x29, 0x62, 0x34,
+ 0xa7, 0xa0, 0xde, 0xcd, 0xc5, 0x6b, 0x30, 0x41, 0x7f, 0x6d, 0x84, 0x46, 0x1d, 0x47, 0x8b, 0xff, 0xe7, 0xdc, 0xbd, 0x18,
+ 0x01, 0xe5, 0xa3, 0xf6, 0xb7, 0x38, 0x2a, 0xfe, 0xd3, 0x50, 0xf5, 0x7b, 0xf4, 0x3f, 0x62, 0xfe, 0x2f, 0xbf, 0xbf, 0xdc,
+ 0x67, 0xdb, 0xc7, 0xcb, 0xaf, 0xe2, 0xdf, 0x7f, 0xf7, 0x8c, 0xd0, 0xdf, 0x7f, 0xff, 0x1f, 0xab, 0x7e, 0xc4, 0xfc, 0xbf,
+ 0xe2, 0x73, 0x64, 0xed, 0x3e, 0xbe, 0x3d, 0x76, 0x6c, 0x78, 0xfc, 0xcf, 0xa0, 0xa4, 0x7e, 0xed, 0xf9, 0xcf, 0x3a, 0xe6,
+ 0xd9, 0xd1, 0xf1, 0xaf, 0x1c, 0xeb, 0x75, 0x4f, 0x98, 0x10, 0x9f, 0x67, 0xd5, 0xbf, 0xa4, 0x3e, 0x44, 0xcc, 0x35, 0x9e,
+ 0xbb, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x35, 0x57, 0x4c, 0xca, 0xeb, 0xef,
+ 0x91, 0x2b, 0x91, 0xa3, 0xca, 0xda, 0xdd, 0x06, 0x1e, 0xe7, 0x4a, 0x16, 0x7a, 0x6c, 0x56, 0xbf, 0x8c, 0x72, 0xfb, 0x25,
+ 0xb7, 0x37, 0xa3, 0xa5, 0x35, 0xea, 0xf9, 0x7a, 0xf4, 0xcf, 0xce, 0xb5, 0xd7, 0xb2, 0x43, 0x6f, 0xcf, 0xcf, 0xb8, 0xbf,
+ 0x72, 0xdd, 0x7b, 0x7d, 0xde, 0x32, 0xdf, 0x0c, 0x90, 0x0e, 0x89, 0xff, 0x36, 0x0f, 0xd3, 0x18, 0x77, 0xe3, 0xb6, 0xcf,
+ 0xac, 0xd4, 0xd6, 0x3b, 0xb7, 0xa3, 0xf0, 0xcd, 0x6a, 0xf3, 0xd8, 0xf1, 0x1d, 0xed, 0xfa, 0x54, 0x1d, 0x25, 0xca, 0x98,
+ 0x54, 0x1c, 0xac, 0x11, 0xf3, 0x7f, 0x4c, 0xfc, 0x97, 0xc6, 0xa9, 0xbd, 0xf7, 0x27, 0x66, 0x1e, 0x9f, 0xa5, 0xff, 0x88,
+ 0xb9, 0x3a, 0x35, 0xcc, 0x0a, 0x6a, 0x5b, 0xb4, 0xfb, 0xbf, 0xe2, 0xd4, 0x29, 0xb9, 0x95, 0xf4, 0xe7, 0xa9, 0x19, 0xf1,
+ 0xdf, 0x13, 0xe3, 0xda, 0xfc, 0x5f, 0xd6, 0x3f, 0xce, 0xdd, 0x66, 0x53, 0x9e, 0xa6, 0x5b, 0x62, 0x6c, 0xad, 0xfb, 0x3f,
+ 0x44, 0xfa, 0x19, 0xe7, 0x7d, 0x9e, 0x42, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0xeb, 0xc7, 0x3b, 0xca, 0x53, 0x62, 0x8d, 0x59, 0x7c, 0xf6, 0xfd, 0x5a, 0x47, 0xb9, 0xf5, 0x8e, 0xef, 0xef, 0x68,
+ 0xdf, 0x47, 0xc4, 0x9a, 0xb4, 0x92, 0xc1, 0xac, 0xdf, 0x8b, 0x68, 0x4b, 0x38, 0xf2, 0x46, 0xf4, 0xdb, 0x4c, 0xfd, 0x95,
+ 0xf6, 0xe8, 0xfa, 0x9b, 0x98, 0x61, 0xb0, 0x96, 0x19, 0x66, 0x2d, 0xfd, 0x15, 0xd7, 0x41, 0x8f, 0xfe, 0xf5, 0xb9, 0x2a,
+ 0x15, 0xf4, 0xf0, 0xcf, 0xf1, 0xaa, 0xfe, 0x26, 0xe6, 0x7d, 0x1c, 0x73, 0x17, 0x1b, 0xa3, 0xbf, 0xd2, 0x6f, 0x57, 0x99,
+ 0xff, 0xeb, 0xc7, 0xcc, 0xe2, 0xfc, 0x6f, 0xd5, 0x59, 0xc5, 0xc2, 0xdd, 0xa8, 0xfe, 0x98, 0x6a, 0xed, 0x9f, 0xdb, 0xd5,
+ 0x3f, 0x0d, 0xd1, 0x7f, 0xcc, 0x19, 0xcf, 0x73, 0xff, 0x57, 0xb2, 0x57, 0xcf, 0xf0, 0xb9, 0xf5, 0x79, 0xc3, 0x6b, 0xa5,
+ 0x47, 0xf4, 0xcc, 0xb8, 0xf9, 0x1f, 0x17, 0xe0, 0x79, 0x5c, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0xac, 0x51, 0xe8, 0x6b, 0x67, 0x23, 0x56, 0x00, 0x1f, 0xbe, 0x9e, 0x1b, 0xd6, 0x30, 0xdf, 0x7f,
+ 0x3d, 0xef, 0x38, 0x46, 0xcc, 0x99, 0xf3, 0x4f, 0xdb, 0x8f, 0xb7, 0x35, 0x0f, 0x9a, 0xee, 0x20, 0x8c, 0x58, 0x07, 0x3c,
+ 0x5e, 0xff, 0xd4, 0xb4, 0x1e, 0xfb, 0x50, 0xc9, 0x2c, 0x78, 0x86, 0xb2, 0x33, 0xe3, 0x53, 0x29, 0x43, 0x94, 0xdf, 0xcd,
+ 0x54, 0xef, 0x05, 0x25, 0xd7, 0x5d, 0xed, 0x68, 0xda, 0x0e, 0xc5, 0x25, 0x77, 0x4c, 0xcd, 0xcb, 0xe2, 0xbf, 0xf2, 0xec,
+ 0xbe, 0xb6, 0xdc, 0x30, 0x07, 0x8c, 0xf7, 0x48, 0x27, 0x77, 0x3c, 0xf6, 0xf9, 0xee, 0xc6, 0xeb, 0x9f, 0x1a, 0x3c, 0x7e,
+ 0xd1, 0x8e, 0x14, 0xab, 0xec, 0x7e, 0xab, 0x8c, 0x80, 0xd1, 0xfa, 0xd7, 0xae, 0x55, 0x77, 0x09, 0xa5, 0xd0, 0x71, 0x13,
+ 0xad, 0x7f, 0xcb, 0x38, 0x8d, 0x1e, 0xc1, 0xca, 0x08, 0x38, 0x26, 0xfe, 0xcd, 0xad, 0x7f, 0x79, 0x6e, 0x88, 0xef, 0x3d,
+ 0xc5, 0x05, 0xa4, 0xcd, 0x28, 0xbd, 0x6e, 0x35, 0x45, 0xc5, 0x2c, 0xcd, 0x1c, 0x47, 0x3c, 0x41, 0x6b, 0x7b, 0x55, 0x47,
+ 0x3b, 0x36, 0xb5, 0x9e, 0x38, 0x5e, 0x7f, 0x93, 0x77, 0xfc, 0xce, 0xcb, 0xed, 0x7e, 0xad, 0x45, 0x9d, 0xee, 0xd8, 0x8b,
+ 0x8f, 0xff, 0xf5, 0xbe, 0x8d, 0x76, 0x44, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xdb, 0xcc, 0x51, 0xe0, 0xcf, 0x54, 0x53, 0xaf, 0xa1, 0xee, 0x9d, 0x75, 0xe4, 0xde, 0xb9, 0xa3, 0xf6, 0xb7, 0xd3, 0xf3,
+ 0x82, 0xd9, 0x90, 0x1d, 0xe0, 0xe2, 0xd7, 0xcd, 0xfa, 0xb2, 0x98, 0xd5, 0x7a, 0x48, 0xcd, 0xb8, 0xe5, 0xf5, 0x60, 0xf4,
+ 0xf8, 0x7a, 0x54, 0xcf, 0x47, 0xbc, 0x0f, 0x2f, 0xc6, 0xdb, 0xa6, 0xc5, 0xbf, 0xe6, 0x0b, 0x59, 0x4d, 0xff, 0x74, 0x90,
+ 0x3f, 0xaf, 0x47, 0xff, 0xde, 0xdd, 0x9f, 0x75, 0x47, 0x96, 0xbf, 0x57, 0xaf, 0xa0, 0x7f, 0x9b, 0x7b, 0x57, 0xf1, 0x11,
+ 0x46, 0xfb, 0xf0, 0x66, 0xe9, 0x6f, 0xd2, 0xde, 0xb9, 0x3d, 0xfa, 0xf7, 0xf9, 0xe5, 0x8f, 0x8b, 0x7f, 0xfd, 0x8c, 0x69,
+ 0xc8, 0xce, 0xe8, 0xbd, 0xd1, 0xea, 0xcb, 0xd4, 0x38, 0xc3, 0xa9, 0x15, 0xef, 0x97, 0x1b, 0xe5, 0xec, 0x9a, 0xeb, 0x5e,
+ 0x8c, 0xf2, 0xaf, 0xf6, 0x66, 0xff, 0x9e, 0xa1, 0x3f, 0xde, 0xb1, 0x6b, 0x8f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5b, 0x5b, 0xc7, 0x89, 0xdb, 0x8f, 0xca, 0x9b, 0xd5, 0xcd, 0x36, 0x33, 0x7a, 0xa8,
+ 0xb9, 0x63, 0xbc, 0xde, 0x8a, 0xd2, 0x5a, 0xe5, 0x77, 0xf6, 0xe5, 0x3d, 0x8f, 0xec, 0x13, 0x57, 0xef, 0xd4, 0xea, 0xe6,
+ 0xb7, 0xea, 0x66, 0x77, 0xed, 0xd7, 0x59, 0x50, 0xb2, 0x70, 0x66, 0xbf, 0x03, 0xc0, 0x97, 0xab, 0xcd, 0xf7, 0x6a, 0x2e,
+ 0x3a, 0x45, 0x62, 0x5c, 0x17, 0x6a, 0x86, 0xbe, 0xc7, 0xef, 0xf4, 0xc1, 0xa3, 0xe0, 0xba, 0xf9, 0x1d, 0x25, 0x7d, 0xb5,
+ 0xf3, 0x7d, 0x66, 0xc3, 0xec, 0xae, 0xeb, 0xd3, 0x3f, 0xbb, 0x73, 0xb5, 0xf9, 0xd5, 0x89, 0xf1, 0x15, 0x6a, 0x59, 0x71,
+ 0x4a, 0xc7, 0xfc, 0xb2, 0xf0, 0xbf, 0xda, 0x35, 0xd5, 0xeb, 0xbe, 0x3d, 0xf3, 0xfa, 0x6b, 0xdf, 0xdd, 0xff, 0xed, 0xad,
+ 0xeb, 0x75, 0xf2, 0x68, 0x2e, 0xae, 0xde, 0x11, 0x10, 0x99, 0x4d, 0x51, 0x75, 0x64, 0xb5, 0xe8, 0xbf, 0x77, 0xce, 0x36,
+ 0xfd, 0xdf, 0xfc, 0xdb, 0x57, 0xbb, 0x14, 0xff, 0x9a, 0xfe, 0x71, 0x3e, 0xf7, 0xb1, 0xf1, 0x3f, 0x22, 0x2b, 0xde, 0x5e,
+ 0x49, 0x6b, 0xfc, 0x6b, 0x63, 0xa7, 0x27, 0xfe, 0x4b, 0xf7, 0x7f, 0xbf, 0xfe, 0xaa, 0x0b, 0xee, 0x68, 0xfd, 0x93, 0xec,
+ 0x53, 0xd5, 0x9e, 0x1a, 0xeb, 0x3d, 0xd9, 0x33, 0x77, 0x94, 0xee, 0xff, 0xaa, 0x86, 0xd1, 0xf1, 0xbf, 0x9e, 0xfe, 0xa9,
+ 0xc3, 0x59, 0xeb, 0x1d, 0x53, 0xad, 0x3d, 0x69, 0xe2, 0x0c, 0xbe, 0xff, 0xfc, 0x7f, 0xac, 0xfe, 0xb1, 0xce, 0x4a, 0x2d,
+ 0xab, 0xe3, 0x8a, 0xfc, 0xf2, 0xd6, 0x27, 0xa9, 0xc7, 0xf6, 0xbd, 0x6b, 0xfe, 0xaf, 0xd5, 0xed, 0x3b, 0xf3, 0xa8, 0xba,
+ 0x10, 0x39, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xa3, 0xd7, 0x89, 0xf6, 0xe9,
+ 0xa6, 0x43, 0xa4, 0x56, 0x6f, 0x74, 0x79, 0xcd, 0xd3, 0xf6, 0x95, 0x7d, 0x63, 0x9f, 0x3f, 0x78, 0xf5, 0x99, 0x3d, 0xb3,
+ 0x5f, 0x27, 0xb4, 0x35, 0xef, 0xee, 0x70, 0xbc, 0xf5, 0xa3, 0xbc, 0xa7, 0xb4, 0x8a, 0xd1, 0xe3, 0x44, 0xfb, 0xc1, 0x9e,
+ 0xd8, 0x1f, 0x1b, 0x47, 0xad, 0xd5, 0x1b, 0x5d, 0x5e, 0xd2, 0xff, 0x33, 0xfb, 0xd7, 0xfe, 0xb1, 0xa7, 0xf6, 0xc5, 0x66,
+ 0xad, 0xbf, 0x0e, 0x6f, 0x6b, 0xc9, 0xcd, 0xe3, 0xd9, 0x47, 0x59, 0xcb, 0x03, 0xd5, 0xe7, 0x44, 0xf9, 0xd9, 0x3e, 0xb0,
+ 0x1f, 0x37, 0x7c, 0x68, 0xb5, 0x7a, 0xa3, 0xcb, 0x4b, 0xfa, 0xff, 0x69, 0x66, 0x7f, 0xdb, 0x6f, 0xf6, 0xe1, 0x83, 0x92,
+ 0x27, 0xf6, 0x64, 0x42, 0x5b, 0x93, 0xdd, 0xbd, 0x68, 0xe7, 0x5d, 0xe7, 0x3e, 0xda, 0x6a, 0xfc, 0xf7, 0x38, 0xd1, 0x3e,
+ 0xb6, 0x9f, 0xec, 0x5b, 0xc1, 0x85, 0x30, 0x53, 0xff, 0xaf, 0xed, 0xbf, 0x1d, 0xfd, 0x35, 0x47, 0x45, 0x6f, 0x79, 0x6b,
+ 0xfc, 0xdb, 0xa0, 0xfc, 0x6f, 0x3d, 0xfa, 0xcf, 0xea, 0xb3, 0x76, 0x6f, 0xe6, 0x56, 0x9f, 0x7c, 0x64, 0x4f, 0x17, 0xd2,
+ 0xbf, 0x76, 0xff, 0x4f, 0x8e, 0x8c, 0xb3, 0xd1, 0xf7, 0xff, 0x33, 0xeb, 0x5f, 0x6a, 0xdf, 0xef, 0x0b, 0xe9, 0xdf, 0xe2,
+ 0xb0, 0x1a, 0xe7, 0x31, 0x19, 0xe3, 0x44, 0x43, 0xff, 0x38, 0xfd, 0xf5, 0xd8, 0x1e, 0xef, 0x81, 0x53, 0xeb, 0x8d, 0x2e,
+ 0xaf, 0xe1, 0xd1, 0x7f, 0x76, 0x5b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xb4,
+ 0xe4, 0x8b, 0x2b, 0xaf, 0x3e, 0xe7, 0xe2, 0xda, 0x62, 0x69, 0xd5, 0x31, 0x17, 0x4a, 0x14, 0xa7, 0x43, 0xdb, 0xce, 0xc2,
+ 0x26, 0xe6, 0x3a, 0x8c, 0xbd, 0xce, 0xfa, 0xb5, 0xc4, 0x9e, 0x6f, 0x0f, 0x7f, 0xbe, 0xb8, 0xd6, 0xb6, 0xa4, 0x62, 0xf6,
+ 0xb0, 0xbc, 0xab, 0x71, 0x4f, 0x9f, 0x99, 0xbc, 0x8a, 0x5e, 0x7b, 0x4f, 0xfc, 0x75, 0x1e, 0x7b, 0xbe, 0x9e, 0x7c, 0x31,
+ 0x67, 0xcf, 0x70, 0xe1, 0xd1, 0xff, 0xd6, 0x68, 0x75, 0x52, 0x79, 0x33, 0xa0, 0xac, 0x5a, 0xa6, 0xe6, 0x0f, 0x3d, 0xdb,
+ 0x75, 0x46, 0xea, 0xaf, 0xc4, 0xd5, 0x59, 0xca, 0x3c, 0xd7, 0x79, 0x54, 0xd9, 0xc8, 0xe3, 0xaa, 0xfa, 0x9f, 0x59, 0xe3,
+ 0xde, 0xfb, 0xff, 0xad, 0xeb, 0x7f, 0xf6, 0xb9, 0xaf, 0xc5, 0x21, 0x6f, 0xe2, 0x3e, 0xe1, 0x23, 0xca, 0x8e, 0xd4, 0xbf,
+ 0xc7, 0x9d, 0x76, 0xb6, 0x18, 0x6f, 0xbd, 0x9e, 0x5b, 0x8a, 0xff, 0x51, 0xcf, 0xd5, 0xe7, 0xd3, 0xdf, 0xd0, 0xff, 0xa6,
+ 0xf5, 0x4f, 0x37, 0xf9, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa5, 0xf6, 0x3b, 0x55,
+ 0xab, 0xec, 0x0c, 0x6a, 0x8b, 0xfb, 0x02, 0xdb, 0xae, 0x6f, 0x0d, 0xcf, 0x5f, 0x96, 0xf6, 0xce, 0xec, 0xfb, 0x9d, 0xaf,
+ 0xde, 0x77, 0x65, 0xaf, 0xe1, 0x3a, 0xbe, 0x40, 0x3d, 0x73, 0xd6, 0xd1, 0x9e, 0xbf, 0xd2, 0x4e, 0xbb, 0xca, 0x0e, 0xd6,
+ 0x31, 0xeb, 0x1e, 0xd7, 0xf1, 0xff, 0x6d, 0xbd, 0x9e, 0x4f, 0xb0, 0x5e, 0x32, 0x72, 0xdd, 0x4b, 0x1d, 0x5b, 0x56, 0xe8,
+ 0xdb, 0xb5, 0xd6, 0xbd, 0x6a, 0x25, 0xf9, 0x02, 0xde, 0xa6, 0xbe, 0x11, 0xac, 0xf8, 0xa6, 0x29, 0xbb, 0x1d, 0xdf, 0xcb,
+ 0x7e, 0xcc, 0x9d, 0xbb, 0x0f, 0xce, 0xa4, 0xf1, 0xc8, 0xfb, 0x7f, 0xdd, 0xdf, 0x1d, 0x79, 0xdf, 0x58, 0x4b, 0xff, 0x33,
+ 0x5c, 0x43, 0xdd, 0xef, 0x63, 0x43, 0xf4, 0xaf, 0xd7, 0x39, 0xb7, 0xfe, 0xab, 0xcd, 0x0d, 0xb3, 0xbc, 0x3b, 0xba, 0xfe,
+ 0xd7, 0xf5, 0x7e, 0xcd, 0x68, 0xe7, 0x2c, 0xed, 0x95, 0x71, 0x67, 0x85, 0xac, 0xd1, 0x57, 0xf0, 0xbd, 0xcd, 0x68, 0x27,
+ 0xbe, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x46, 0xf3, 0x39, 0xcd, 0xce, 0xe1, 0xb7, 0xba,
+ 0x9b, 0xef, 0xd8, 0xf3, 0xf5, 0x79, 0x00, 0x95, 0x96, 0x1e, 0x9b, 0xc3, 0xaf, 0x7f, 0x75, 0xe5, 0xec, 0x19, 0xfc, 0xea,
+ 0xab, 0x5c, 0x57, 0x5e, 0x3f, 0x68, 0x8b, 0xff, 0x5b, 0x76, 0x71, 0x6b, 0x33, 0xc0, 0xd1, 0xb9, 0x8d, 0x7a, 0xca, 0xfa,
+ 0xb2, 0xa2, 0xcc, 0x70, 0x1d, 0x7a, 0x33, 0xcd, 0xa8, 0x65, 0xbd, 0x2e, 0xc0, 0xf5, 0x33, 0xe3, 0xf5, 0xdd, 0xff, 0x57,
+ 0x5b, 0xcd, 0x8f, 0x2e, 0xd3, 0xf5, 0x3f, 0x4b, 0xfc, 0x47, 0x39, 0xd9, 0xd6, 0x58, 0xcd, 0x5f, 0x4b, 0xff, 0x24, 0xcc,
+ 0xb9, 0x47, 0x97, 0x79, 0xbe, 0xaf, 0x30, 0x7f, 0x0e, 0x9b, 0xa1, 0xbf, 0x75, 0xc6, 0xff, 0x95, 0xf3, 0x57, 0x5d, 0x25,
+ 0x8b, 0x25, 0xd9, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xcd, 0xfb, 0x67, 0x15,
+ 0x3f, 0xda, 0x3a, 0xde, 0x40, 0xc5, 0xfb, 0x12, 0x7d, 0x05, 0x3d, 0x59, 0xfc, 0x4c, 0xf0, 0xb5, 0x8d, 0x76, 0x0e, 0x95,
+ 0xf3, 0xf8, 0xad, 0xe4, 0x0d, 0xdc, 0xef, 0xbb, 0x1c, 0xee, 0xfb, 0x8c, 0xcf, 0xe2, 0x97, 0x96, 0xd4, 0xff, 0x7c, 0x0e,
+ 0xb7, 0xed, 0x92, 0x7c, 0x82, 0xbe, 0x5b, 0x71, 0xfd, 0xf6, 0xfc, 0x2b, 0xdc, 0x6a, 0x76, 0xbc, 0x51, 0x65, 0x4a, 0xcd,
+ 0x99, 0x99, 0x36, 0xcf, 0x93, 0xc7, 0x4d, 0xf3, 0x76, 0x1d, 0xeb, 0x52, 0x9a, 0xe5, 0x7d, 0xba, 0x05, 0xfd, 0xd3, 0xf2,
+ 0xee, 0x36, 0xf4, 0x47, 0x7f, 0x6b, 0xf0, 0x30, 0x9f, 0x47, 0xff, 0x73, 0x3b, 0xdc, 0xe6, 0x65, 0x1b, 0x36, 0xf9, 0x1b,
+ 0x0a, 0x3c, 0xeb, 0x5f, 0xe3, 0xd3, 0x8a, 0xf2, 0xfd, 0x2c, 0xf4, 0xbf, 0xee, 0xe7, 0xd4, 0xf3, 0x7d, 0x36, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xb2,
+ 0x0c, 0xa2, 0x3f, 0xfa, 0xdf, 0xb8, 0xfe, 0xff, 0x03 };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle jungleFontRecs[189] = {
+ { 4, 4, 5 , 12 },
+ { 17, 4, 2 , 7 },
+ { 27, 4, 5 , 3 },
+ { 40, 4, 5 , 5 },
+ { 53, 4, 6 , 7 },
+ { 67, 4, 7 , 7 },
+ { 82, 4, 5 , 7 },
+ { 95, 4, 3 , 3 },
+ { 106, 4, 4 , 8 },
+ { 118, 4, 4 , 8 },
+ { 130, 4, 5 , 5 },
+ { 143, 4, 5 , 5 },
+ { 156, 4, 2 , 3 },
+ { 166, 4, 5 , 1 },
+ { 179, 4, 2 , 2 },
+ { 189, 4, 7 , 7 },
+ { 204, 4, 7 , 6 },
+ { 219, 4, 6 , 6 },
+ { 233, 4, 6 , 6 },
+ { 4, 24, 6 , 6 },
+ { 18, 24, 6 , 6 },
+ { 32, 24, 6 , 6 },
+ { 46, 24, 6 , 6 },
+ { 60, 24, 6 , 6 },
+ { 74, 24, 6 , 6 },
+ { 88, 24, 6 , 6 },
+ { 102, 24, 2 , 5 },
+ { 112, 24, 2 , 6 },
+ { 122, 24, 3 , 5 },
+ { 133, 24, 5 , 3 },
+ { 146, 24, 3 , 5 },
+ { 157, 24, 6 , 7 },
+ { 171, 24, 7 , 7 },
+ { 186, 24, 6 , 7 },
+ { 200, 24, 6 , 7 },
+ { 214, 24, 6 , 7 },
+ { 228, 24, 6 , 7 },
+ { 4, 44, 6 , 7 },
+ { 18, 44, 6 , 7 },
+ { 32, 44, 6 , 7 },
+ { 46, 44, 6 , 7 },
+ { 60, 44, 6 , 7 },
+ { 74, 44, 6 , 7 },
+ { 88, 44, 6 , 7 },
+ { 102, 44, 6 , 7 },
+ { 116, 44, 7 , 7 },
+ { 131, 44, 6 , 7 },
+ { 145, 44, 6 , 7 },
+ { 159, 44, 6 , 7 },
+ { 173, 44, 7 , 8 },
+ { 188, 44, 6 , 7 },
+ { 202, 44, 6 , 7 },
+ { 216, 44, 6 , 7 },
+ { 230, 44, 6 , 7 },
+ { 4, 64, 6 , 7 },
+ { 18, 64, 7 , 7 },
+ { 33, 64, 6 , 7 },
+ { 47, 64, 6 , 7 },
+ { 61, 64, 6 , 7 },
+ { 75, 64, 4 , 8 },
+ { 87, 64, 7 , 7 },
+ { 102, 64, 4 , 8 },
+ { 114, 64, 4 , 2 },
+ { 126, 64, 6 , 1 },
+ { 140, 64, 2 , 2 },
+ { 150, 64, 6 , 5 },
+ { 164, 64, 6 , 7 },
+ { 178, 64, 6 , 5 },
+ { 192, 64, 6 , 7 },
+ { 206, 64, 6 , 5 },
+ { 220, 64, 6 , 7 },
+ { 234, 64, 6 , 7 },
+ { 4, 84, 6 , 7 },
+ { 18, 84, 6 , 7 },
+ { 32, 84, 5 , 8 },
+ { 45, 84, 6 , 7 },
+ { 59, 84, 6 , 7 },
+ { 73, 84, 7 , 5 },
+ { 88, 84, 6 , 5 },
+ { 102, 84, 6 , 5 },
+ { 116, 84, 6 , 7 },
+ { 130, 84, 6 , 7 },
+ { 144, 84, 6 , 5 },
+ { 158, 84, 6 , 5 },
+ { 172, 84, 6 , 6 },
+ { 186, 84, 6 , 5 },
+ { 200, 84, 6 , 5 },
+ { 214, 84, 7 , 5 },
+ { 229, 84, 6 , 5 },
+ { 4, 104, 6 , 7 },
+ { 18, 104, 6 , 5 },
+ { 32, 104, 4 , 8 },
+ { 44, 104, 2 , 8 },
+ { 54, 104, 4 , 8 },
+ { 66, 104, 5 , 2 },
+ { 79, 104, 2 , 7 },
+ { 89, 104, 6 , 6 },
+ { 103, 104, 6 , 7 },
+ { 117, 104, 6 , 7 },
+ { 131, 104, 6 , 7 },
+ { 145, 104, 8 , 8 },
+ { 161, 104, 6 , 9 },
+ { 175, 104, 8 , 8 },
+ { 191, 104, 7 , 7 },
+ { 206, 104, 8 , 8 },
+ { 222, 104, 6 , 5 },
+ { 236, 104, 8 , 8 },
+ { 4, 124, 7 , 7 },
+ { 19, 124, 8 , 8 },
+ { 35, 124, 4 , 4 },
+ { 47, 124, 8 , 8 },
+ { 63, 124, 8 , 8 },
+ { 79, 124, 8 , 8 },
+ { 95, 124, 8 , 8 },
+ { 111, 124, 6 , 7 },
+ { 125, 124, 5 , 8 },
+ { 138, 124, 3 , 3 },
+ { 149, 124, 8 , 8 },
+ { 165, 124, 8 , 8 },
+ { 181, 124, 8 , 8 },
+ { 197, 124, 6 , 5 },
+ { 211, 124, 10 , 7 },
+ { 229, 124, 10 , 5 },
+ { 4, 144, 8 , 8 },
+ { 20, 144, 6 , 7 },
+ { 34, 144, 6 , 10 },
+ { 48, 144, 6 , 10 },
+ { 62, 144, 6 , 10 },
+ { 76, 144, 6 , 10 },
+ { 90, 144, 6 , 10 },
+ { 104, 144, 6 , 10 },
+ { 118, 144, 10 , 7 },
+ { 136, 144, 6 , 9 },
+ { 150, 144, 6 , 10 },
+ { 164, 144, 6 , 10 },
+ { 178, 144, 6 , 10 },
+ { 192, 144, 6 , 10 },
+ { 206, 144, 6 , 10 },
+ { 220, 144, 6 , 10 },
+ { 234, 144, 6 , 10 },
+ { 4, 164, 6 , 10 },
+ { 18, 164, 6 , 7 },
+ { 32, 164, 6 , 10 },
+ { 46, 164, 6 , 10 },
+ { 60, 164, 6 , 10 },
+ { 74, 164, 6 , 10 },
+ { 88, 164, 6 , 10 },
+ { 102, 164, 6 , 10 },
+ { 116, 164, 6 , 5 },
+ { 130, 164, 6 , 7 },
+ { 144, 164, 6 , 10 },
+ { 158, 164, 6 , 10 },
+ { 172, 164, 6 , 10 },
+ { 186, 164, 6 , 10 },
+ { 200, 164, 6 , 10 },
+ { 214, 164, 6 , 7 },
+ { 228, 164, 6 , 7 },
+ { 4, 184, 6 , 8 },
+ { 18, 184, 6 , 8 },
+ { 32, 184, 6 , 8 },
+ { 46, 184, 6 , 8 },
+ { 60, 184, 6 , 8 },
+ { 74, 184, 6 , 8 },
+ { 88, 184, 9 , 5 },
+ { 105, 184, 6 , 7 },
+ { 119, 184, 6 , 8 },
+ { 133, 184, 6 , 8 },
+ { 147, 184, 6 , 8 },
+ { 161, 184, 6 , 8 },
+ { 175, 184, 6 , 8 },
+ { 189, 184, 6 , 8 },
+ { 203, 184, 6 , 8 },
+ { 217, 184, 6 , 8 },
+ { 231, 184, 6 , 7 },
+ { 4, 204, 6 , 8 },
+ { 18, 204, 6 , 8 },
+ { 32, 204, 6 , 8 },
+ { 46, 204, 6 , 8 },
+ { 60, 204, 6 , 8 },
+ { 74, 204, 6 , 8 },
+ { 88, 204, 5 , 5 },
+ { 101, 204, 6 , 5 },
+ { 115, 204, 6 , 8 },
+ { 129, 204, 6 , 8 },
+ { 143, 204, 6 , 8 },
+ { 157, 204, 6 , 8 },
+ { 171, 204, 6 , 10 },
+ { 185, 204, 6 , 9 },
+ { 199, 204, 6 , 10 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo jungleFontGlyphs[189] = {
+ { 32, 0, 9, 5, { 0 }},
+ { 33, 0, 2, 3, { 0 }},
+ { 34, 0, 2, 6, { 0 }},
+ { 35, 0, 3, 6, { 0 }},
+ { 36, 0, 2, 7, { 0 }},
+ { 37, 0, 2, 8, { 0 }},
+ { 38, 0, 2, 6, { 0 }},
+ { 39, 0, 2, 4, { 0 }},
+ { 40, 0, 2, 5, { 0 }},
+ { 41, 0, 2, 5, { 0 }},
+ { 42, 0, 2, 6, { 0 }},
+ { 43, 0, 3, 6, { 0 }},
+ { 44, 0, 7, 3, { 0 }},
+ { 45, 0, 5, 6, { 0 }},
+ { 46, 0, 7, 3, { 0 }},
+ { 47, 0, 2, 8, { 0 }},
+ { 48, 0, 3, 8, { 0 }},
+ { 49, 0, 3, 7, { 0 }},
+ { 50, 0, 3, 7, { 0 }},
+ { 51, 0, 3, 7, { 0 }},
+ { 52, 0, 3, 7, { 0 }},
+ { 53, 0, 3, 7, { 0 }},
+ { 54, 0, 3, 7, { 0 }},
+ { 55, 0, 3, 7, { 0 }},
+ { 56, 0, 3, 7, { 0 }},
+ { 57, 0, 3, 7, { 0 }},
+ { 58, 0, 4, 3, { 0 }},
+ { 59, 0, 4, 3, { 0 }},
+ { 60, 0, 3, 4, { 0 }},
+ { 61, 0, 4, 6, { 0 }},
+ { 62, 0, 3, 4, { 0 }},
+ { 63, 0, 2, 7, { 0 }},
+ { 64, 0, 2, 8, { 0 }},
+ { 65, 0, 2, 7, { 0 }},
+ { 66, 0, 2, 7, { 0 }},
+ { 67, 0, 2, 7, { 0 }},
+ { 68, 0, 2, 7, { 0 }},
+ { 69, 0, 2, 7, { 0 }},
+ { 70, 0, 2, 7, { 0 }},
+ { 71, 0, 2, 7, { 0 }},
+ { 72, 0, 2, 7, { 0 }},
+ { 73, 0, 2, 7, { 0 }},
+ { 74, 0, 2, 7, { 0 }},
+ { 75, 0, 2, 7, { 0 }},
+ { 76, 0, 2, 7, { 0 }},
+ { 77, 0, 2, 8, { 0 }},
+ { 78, 0, 2, 7, { 0 }},
+ { 79, 0, 2, 7, { 0 }},
+ { 80, 0, 2, 7, { 0 }},
+ { 81, 0, 2, 7, { 0 }},
+ { 82, 0, 2, 7, { 0 }},
+ { 83, 0, 2, 7, { 0 }},
+ { 84, 0, 2, 7, { 0 }},
+ { 85, 0, 2, 7, { 0 }},
+ { 86, 0, 2, 7, { 0 }},
+ { 87, 0, 2, 8, { 0 }},
+ { 88, 0, 2, 7, { 0 }},
+ { 89, 0, 2, 7, { 0 }},
+ { 90, 0, 2, 7, { 0 }},
+ { 91, 0, 2, 5, { 0 }},
+ { 92, 0, 2, 8, { 0 }},
+ { 93, 0, 2, 5, { 0 }},
+ { 94, 0, -1, 5, { 0 }},
+ { 95, 0, 10, 7, { 0 }},
+ { 96, 0, -1, 3, { 0 }},
+ { 97, 0, 4, 7, { 0 }},
+ { 98, 0, 2, 7, { 0 }},
+ { 99, 0, 4, 7, { 0 }},
+ { 100, 0, 2, 7, { 0 }},
+ { 101, 0, 4, 7, { 0 }},
+ { 102, 0, 2, 7, { 0 }},
+ { 103, 0, 4, 7, { 0 }},
+ { 104, 0, 2, 7, { 0 }},
+ { 105, 0, 2, 7, { 0 }},
+ { 106, 0, 2, 6, { 0 }},
+ { 107, 0, 2, 7, { 0 }},
+ { 108, 0, 2, 7, { 0 }},
+ { 109, 0, 4, 8, { 0 }},
+ { 110, 0, 4, 7, { 0 }},
+ { 111, 0, 4, 7, { 0 }},
+ { 112, 0, 4, 7, { 0 }},
+ { 113, 0, 4, 7, { 0 }},
+ { 114, 0, 4, 7, { 0 }},
+ { 115, 0, 4, 7, { 0 }},
+ { 116, 0, 3, 7, { 0 }},
+ { 117, 0, 4, 7, { 0 }},
+ { 118, 0, 4, 7, { 0 }},
+ { 119, 0, 4, 8, { 0 }},
+ { 120, 0, 4, 7, { 0 }},
+ { 121, 0, 4, 7, { 0 }},
+ { 122, 0, 4, 7, { 0 }},
+ { 123, 0, 2, 5, { 0 }},
+ { 124, 0, 2, 3, { 0 }},
+ { 125, 0, 2, 5, { 0 }},
+ { 126, 0, -1, 6, { 0 }},
+ { 161, 0, 2, 3, { 0 }},
+ { 162, 0, 3, 7, { 0 }},
+ { 163, 0, 2, 7, { 0 }},
+ { 8364, 0, 2, 7, { 0 }},
+ { 165, 0, 2, 7, { 0 }},
+ { 352, 0, 1, 8, { 0 }},
+ { 167, 0, 1, 7, { 0 }},
+ { 353, 0, 1, 8, { 0 }},
+ { 169, 0, 2, 8, { 0 }},
+ { 170, 0, 1, 8, { 0 }},
+ { 171, 0, 3, 7, { 0 }},
+ { 172, 0, 1, 8, { 0 }},
+ { 174, 0, 2, 8, { 0 }},
+ { 175, 0, 1, 8, { 0 }},
+ { 176, 0, 1, 2, { 0 }},
+ { 177, 0, 1, 8, { 0 }},
+ { 178, 0, 1, 8, { 0 }},
+ { 179, 0, 1, 8, { 0 }},
+ { 381, 0, 1, 8, { 0 }},
+ { 181, 0, 4, 7, { 0 }},
+ { 182, 0, 1, 4, { 0 }},
+ { 183, 0, 4, 4, { 0 }},
+ { 382, 0, 1, 8, { 0 }},
+ { 185, 0, 1, 8, { 0 }},
+ { 186, 0, 1, 8, { 0 }},
+ { 187, 0, 3, 7, { 0 }},
+ { 338, 0, 2, 11, { 0 }},
+ { 339, 0, 4, 11, { 0 }},
+ { 376, 0, 1, 8, { 0 }},
+ { 191, 0, 2, 7, { 0 }},
+ { 192, 0, -1, 7, { 0 }},
+ { 193, 0, -1, 7, { 0 }},
+ { 194, 0, -1, 7, { 0 }},
+ { 195, 0, -1, 7, { 0 }},
+ { 196, 0, -1, 7, { 0 }},
+ { 197, 0, -1, 7, { 0 }},
+ { 198, 0, 2, 11, { 0 }},
+ { 199, 0, 2, 7, { 0 }},
+ { 200, 0, -1, 7, { 0 }},
+ { 201, 0, -1, 7, { 0 }},
+ { 202, 0, -1, 7, { 0 }},
+ { 203, 0, -1, 7, { 0 }},
+ { 204, 0, -1, 7, { 0 }},
+ { 205, 0, -1, 7, { 0 }},
+ { 206, 0, -1, 7, { 0 }},
+ { 207, 0, -1, 7, { 0 }},
+ { 208, 0, 2, 7, { 0 }},
+ { 209, 0, -1, 7, { 0 }},
+ { 210, 0, -1, 7, { 0 }},
+ { 211, 0, -1, 7, { 0 }},
+ { 212, 0, -1, 7, { 0 }},
+ { 213, 0, -1, 7, { 0 }},
+ { 214, 0, -1, 7, { 0 }},
+ { 215, 0, 3, 7, { 0 }},
+ { 216, 0, 2, 7, { 0 }},
+ { 217, 0, -1, 7, { 0 }},
+ { 218, 0, -1, 7, { 0 }},
+ { 219, 0, -1, 7, { 0 }},
+ { 220, 0, -1, 7, { 0 }},
+ { 221, 0, -1, 7, { 0 }},
+ { 222, 0, 2, 7, { 0 }},
+ { 223, 0, 2, 7, { 0 }},
+ { 224, 0, 1, 7, { 0 }},
+ { 225, 0, 1, 7, { 0 }},
+ { 226, 0, 1, 7, { 0 }},
+ { 227, 0, 1, 7, { 0 }},
+ { 228, 0, 1, 7, { 0 }},
+ { 229, 0, 1, 7, { 0 }},
+ { 230, 0, 4, 10, { 0 }},
+ { 231, 0, 4, 7, { 0 }},
+ { 232, 0, 1, 7, { 0 }},
+ { 233, 0, 1, 7, { 0 }},
+ { 234, 0, 1, 7, { 0 }},
+ { 235, 0, 1, 7, { 0 }},
+ { 236, 0, 1, 7, { 0 }},
+ { 237, 0, 1, 7, { 0 }},
+ { 238, 0, 1, 7, { 0 }},
+ { 239, 0, 1, 7, { 0 }},
+ { 240, 0, 2, 7, { 0 }},
+ { 241, 0, 1, 7, { 0 }},
+ { 242, 0, 1, 7, { 0 }},
+ { 243, 0, 1, 7, { 0 }},
+ { 244, 0, 1, 7, { 0 }},
+ { 245, 0, 1, 7, { 0 }},
+ { 246, 0, 1, 7, { 0 }},
+ { 247, 0, 3, 6, { 0 }},
+ { 248, 0, 4, 7, { 0 }},
+ { 249, 0, 1, 7, { 0 }},
+ { 250, 0, 1, 7, { 0 }},
+ { 251, 0, 1, 7, { 0 }},
+ { 252, 0, 1, 7, { 0 }},
+ { 253, 0, 1, 7, { 0 }},
+ { 254, 0, 2, 7, { 0 }},
+ { 255, 0, 1, 7, { 0 }},
+};
+
+// Style loading function: Jungle
+static void GuiLoadStyleJungle(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < JUNGLE_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(jungleStyleProps[i].controlId, jungleStyleProps[i].propertyId, jungleStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int jungleFontDataSize = 0;
+ unsigned char *data = DecompressData(jungleFontData, JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE, &jungleFontDataSize);
+ Image imFont = { data, 256, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 12;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, jungleFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, jungleFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 254, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_lavanda.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_lavanda.h
new file mode 100644
index 0000000000..4682cabbfd
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_lavanda.h
@@ -0,0 +1,607 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleLavanda(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define LAVANDA_STYLE_PROPS_COUNT 16
+
+// Custom style name: Lavanda
+static const GuiStyleProp lavandaStyleProps[LAVANDA_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0xab9bd3ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x3e4350ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0xdadaf4ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0xee84a0ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0xf4b7c7ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0xb7657bff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0xd5c8dbff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0x966ec0ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0xd7ccf7ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x8fa2bdff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x6b798dff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x8292a9ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE
+ { 0, 18, 0x84adb7ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x5b5b81ff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "Cartridge.ttf" (size: 16, spacing: 1)
+
+#define LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE 2636
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char lavandaFontData[LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0xdb, 0xd2, 0xa4, 0xba, 0x0d, 0x06, 0x50, 0xde, 0xff, 0xa5, 0xbf, 0x5c, 0xa4, 0x52, 0x49, 0xaa, 0x66, 0x63, 0x24,
+ 0x0b, 0x9a, 0xee, 0x59, 0xb3, 0xee, 0x7e, 0xa6, 0x4f, 0x06, 0xf9, 0x04, 0x96, 0x73, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7f,
+ 0xfc, 0x4b, 0x4e, 0xfe, 0x6f, 0x2e, 0xbf, 0xd3, 0x7f, 0xfe, 0x9e, 0xc5, 0xff, 0xf8, 0xff, 0xff, 0x75, 0xed, 0x7d, 0x73,
+ 0xf9, 0xf3, 0x3b, 0x47, 0xf2, 0xc7, 0xef, 0x97, 0x8d, 0xd7, 0xff, 0xd3, 0x3b, 0xd4, 0xff, 0xff, 0x7f, 0xff, 0x55, 0xca,
+ 0xf1, 0xfc, 0x35, 0x47, 0xf1, 0x73, 0xb2, 0xf8, 0x9c, 0xab, 0xbf, 0xb0, 0x56, 0xfa, 0xb5, 0x73, 0x9e, 0xd3, 0x2b, 0xb2,
+ 0xf3, 0xca, 0xf3, 0xd7, 0x1d, 0xe5, 0xb2, 0x3a, 0x96, 0x25, 0x5c, 0x3d, 0xcb, 0xef, 0x8b, 0xff, 0x5c, 0x78, 0xe5, 0xf9,
+ 0xf1, 0x6c, 0xd4, 0x09, 0xeb, 0x72, 0xac, 0xd6, 0x18, 0x3b, 0xa5, 0x7a, 0xf6, 0x1d, 0x2b, 0xff, 0xff, 0x5a, 0x6d, 0xbb,
+ 0x5f, 0x3b, 0xae, 0x4a, 0xbf, 0xfe, 0xad, 0xaf, 0x94, 0x5c, 0x06, 0xfe, 0x7f, 0x5a, 0xdf, 0x7e, 0xe2, 0xfa, 0xcf, 0xf6,
+ 0xb5, 0x7d, 0xa5, 0xad, 0x9c, 0xb8, 0x46, 0xab, 0xf1, 0x9f, 0x56, 0x8b, 0x90, 0x45, 0x99, 0xde, 0x1d, 0xff, 0x9d, 0x76,
+ 0x34, 0x37, 0x95, 0x6a, 0xb5, 0xbe, 0xad, 0x5f, 0x37, 0x29, 0xb6, 0xb4, 0xbd, 0xf8, 0x5f, 0x7f, 0x4e, 0xc6, 0xca, 0x6d,
+ 0xdd, 0x7b, 0xa9, 0x97, 0x76, 0xef, 0xb7, 0x75, 0x6b, 0x95, 0x34, 0x7a, 0x40, 0xfd, 0xfa, 0x7a, 0xaa, 0xc4, 0x6b, 0x51,
+ 0x7a, 0xa5, 0x75, 0xcb, 0x58, 0xbd, 0x9f, 0x72, 0x6b, 0x95, 0x47, 0xca, 0xf2, 0x68, 0xb7, 0x3a, 0xd5, 0x5f, 0x94, 0x72,
+ 0x5c, 0x56, 0xfa, 0xe5, 0xfd, 0xab, 0x30, 0xa5, 0xd1, 0x59, 0x6e, 0x6b, 0xff, 0xd7, 0xad, 0x71, 0x9a, 0x57, 0x72, 0xca,
+ 0x7d, 0x83, 0x94, 0x47, 0x95, 0xeb, 0x73, 0xbc, 0x1e, 0x8b, 0xcc, 0xc7, 0x7f, 0xaf, 0x1f, 0xf3, 0xa7, 0x72, 0xef, 0xf6,
+ 0x12, 0xe6, 0xeb, 0xc6, 0xb7, 0xc7, 0x7f, 0x1a, 0x7d, 0x8c, 0xea, 0x6b, 0x52, 0x9e, 0x7b, 0x39, 0x6f, 0x23, 0xaf, 0x5f,
+ 0x99, 0x19, 0xba, 0x26, 0x3b, 0xad, 0x41, 0x1a, 0xe3, 0xc5, 0xdd, 0x96, 0x7c, 0x7a, 0xce, 0xea, 0xc9, 0xf8, 0xcf, 0x85,
+ 0x19, 0x89, 0xd5, 0x95, 0x97, 0x65, 0x29, 0xe4, 0x86, 0xf6, 0xff, 0x0d, 0x73, 0xaa, 0x4f, 0xc5, 0x7f, 0x96, 0x73, 0x5b,
+ 0x13, 0xd7, 0x74, 0x46, 0xce, 0x43, 0x3e, 0x70, 0x16, 0xae, 0xc4, 0xff, 0xd1, 0x6c, 0xc9, 0x7f, 0x3b, 0xfe, 0x8f, 0x8b,
+ 0xbd, 0xf8, 0xa3, 0x31, 0x0b, 0xf8, 0x5b, 0xf1, 0x9f, 0x46, 0xcc, 0x64, 0x6c, 0x64, 0xde, 0xeb, 0x33, 0xcc, 0xc6, 0xff,
+ 0x7b, 0x6b, 0xe1, 0x55, 0xff, 0x3f, 0x17, 0xef, 0x30, 0xfd, 0x4e, 0xfc, 0x1f, 0xa3, 0xfd, 0xff, 0xf5, 0x15, 0x33, 0x31,
+ 0x6b, 0xf4, 0x77, 0xc4, 0x7f, 0x9a, 0xf5, 0x70, 0x06, 0x67, 0x6e, 0xbe, 0x39, 0xfe, 0x3b, 0xd1, 0x93, 0x76, 0x5d, 0x79,
+ 0xde, 0xba, 0xe5, 0xa4, 0xc7, 0x56, 0xad, 0x19, 0xee, 0x9e, 0xff, 0xef, 0xdf, 0xb7, 0xc9, 0xf6, 0xab, 0xf3, 0xf0, 0xf8,
+ 0xff, 0xb9, 0xf8, 0x3f, 0xca, 0x33, 0xd8, 0xe7, 0xf7, 0x5a, 0xea, 0xf5, 0x4f, 0x1a, 0xf7, 0xbb, 0x8f, 0x91, 0xdf, 0xf2,
+ 0xb6, 0xf3, 0x70, 0xed, 0x35, 0x29, 0xcf, 0x6d, 0x9c, 0xdf, 0x01, 0xfb, 0xe7, 0xd9, 0x88, 0xce, 0xbc, 0xec, 0xfb, 0xea,
+ 0xd8, 0xbc, 0xa6, 0x8d, 0xfd, 0x5b, 0x4a, 0x81, 0x67, 0x9e, 0x31, 0x40, 0xfc, 0x8b, 0x7f, 0x78, 0xfb, 0x73, 0xcb, 0xe2,
+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdf, 0x5a, 0xa1, 0x57, 0x5b, 0x15, 0xbe,
+ 0x93, 0xcb, 0xb8, 0x93, 0x9d, 0x6e, 0xbd, 0x42, 0x3d, 0xad, 0x9c, 0x04, 0xbd, 0xd7, 0xe5, 0x34, 0x0b, 0x5a, 0x46, 0xf2,
+ 0x13, 0x74, 0xf3, 0x4e, 0x55, 0x32, 0x08, 0x54, 0xf7, 0x32, 0xe8, 0xee, 0x1b, 0x50, 0xfb, 0x8c, 0xce, 0x6a, 0xfd, 0x0c,
+ 0x65, 0x41, 0xe8, 0xe4, 0x16, 0xde, 0x5b, 0x95, 0x5a, 0xcf, 0xd1, 0xb6, 0x93, 0xf5, 0x23, 0xad, 0x55, 0x73, 0x93, 0xf1,
+ 0x9f, 0x4b, 0xb9, 0x0e, 0x3a, 0x19, 0x6a, 0x3a, 0x59, 0x6a, 0x32, 0x9c, 0x5f, 0xe7, 0x5a, 0x94, 0x5e, 0xcb, 0x39, 0x95,
+ 0xe2, 0x77, 0xaa, 0xef, 0xca, 0x90, 0x46, 0xa4, 0xd5, 0xca, 0xb0, 0xb3, 0x3e, 0x72, 0xa7, 0x55, 0xd9, 0xbb, 0x7a, 0x53,
+ 0xca, 0x45, 0x7c, 0x77, 0xde, 0x9d, 0x94, 0xe3, 0xe7, 0xd9, 0xf8, 0x4f, 0xe3, 0x17, 0xe5, 0x52, 0xce, 0xe5, 0x6e, 0x46,
+ 0xb6, 0x6e, 0x26, 0xa7, 0x5e, 0x16, 0x81, 0x7e, 0xfc, 0x5f, 0x3b, 0x03, 0xbf, 0x1d, 0xff, 0x3b, 0xfb, 0xc7, 0x4c, 0xc4,
+ 0x7f, 0xb6, 0x3f, 0x39, 0x23, 0xe5, 0x5a, 0x79, 0x97, 0x55, 0xfc, 0x3c, 0x19, 0xff, 0xfd, 0x8c, 0x85, 0x67, 0xbf, 0x38,
+ 0x5b, 0xf1, 0x3f, 0xf9, 0xba, 0xa3, 0x99, 0x5f, 0x6b, 0x3f, 0xfe, 0xd3, 0xec, 0xb9, 0xce, 0xf5, 0x3d, 0xa7, 0xf2, 0x06,
+ 0x77, 0xae, 0xcf, 0x5c, 0xc8, 0xd7, 0xbb, 0xdb, 0x33, 0xa8, 0xe5, 0xae, 0xce, 0xb2, 0x35, 0xde, 0x8d, 0xff, 0x3c, 0xd8,
+ 0xff, 0xaf, 0x8c, 0xc8, 0x32, 0xde, 0xfe, 0x7f, 0x57, 0xfc, 0xdf, 0xd5, 0xff, 0xbf, 0xd2, 0x92, 0x75, 0xf7, 0xf5, 0x7a,
+ 0x3a, 0xfe, 0xef, 0x98, 0x97, 0xca, 0x48, 0xcb, 0xd5, 0xaf, 0x31, 0xae, 0xf6, 0xff, 0x33, 0xb4, 0x2b, 0x55, 0x6f, 0xdc,
+ 0x92, 0x9b, 0xdb, 0xff, 0x34, 0x46, 0x4a, 0xbb, 0xf1, 0x7f, 0x5c, 0xca, 0x83, 0x9a, 0xe6, 0xb9, 0xae, 0xd4, 0xe1, 0x3b,
+ 0x3b, 0xef, 0xed, 0xf4, 0xe0, 0xd3, 0xdc, 0x79, 0x2e, 0x8d, 0x91, 0xea, 0x6f, 0xc4, 0xff, 0xce, 0x2e, 0x5d, 0x4f, 0xf5,
+ 0xdc, 0x8f, 0x0b, 0x6d, 0xde, 0x1b, 0xe3, 0x7f, 0x7e, 0xfe, 0x6f, 0xfd, 0x1d, 0xf2, 0xf0, 0xf8, 0x3f, 0x8d, 0x28, 0x7e,
+ 0x5f, 0xfc, 0xd7, 0xdb, 0xa3, 0x99, 0xfd, 0x90, 0xa7, 0x6b, 0x80, 0xce, 0xee, 0x99, 0x9d, 0x9d, 0x53, 0x53, 0xda, 0x89,
+ 0x6c, 0xae, 0x47, 0x32, 0xd5, 0xff, 0x7f, 0x2e, 0xfe, 0xd3, 0xba, 0x0e, 0x3b, 0xdf, 0xbf, 0xbf, 0x3b, 0x40, 0xb6, 0x5a,
+ 0x95, 0x8c, 0xc6, 0xff, 0xc4, 0x2c, 0x5d, 0xb7, 0x4e, 0x7a, 0x7e, 0x3f, 0xf4, 0xe7, 0xee, 0x59, 0xa7, 0xb9, 0xab, 0x5b,
+ 0x46, 0xee, 0x8c, 0x67, 0x64, 0x2e, 0x2d, 0x5b, 0xf1, 0xbf, 0x7f, 0x2e, 0xaa, 0xfb, 0x32, 0xae, 0xfb, 0xc6, 0xf5, 0x79,
+ 0x91, 0x6e, 0xfc, 0xf7, 0x32, 0xd4, 0x5f, 0xfd, 0x1d, 0xff, 0x3c, 0x57, 0x72, 0x8c, 0xdf, 0x91, 0x4e, 0xab, 0xae, 0xea,
+ 0xf6, 0x2c, 0xd2, 0xda, 0x35, 0xff, 0x7d, 0xf1, 0xff, 0x44, 0xad, 0x31, 0x33, 0xf3, 0xd9, 0xb9, 0x17, 0x99, 0xf2, 0x35,
+ 0x3d, 0x3d, 0xc2, 0xfa, 0xfc, 0x19, 0xbd, 0x6f, 0x47, 0xa3, 0x37, 0x65, 0xe3, 0x9d, 0x88, 0xff, 0xa3, 0x71, 0xbf, 0x62,
+ 0xff, 0x4e, 0xdf, 0x77, 0x66, 0x35, 0xce, 0x8d, 0x4f, 0x25, 0xcc, 0xbd, 0xbf, 0x67, 0x10, 0x3f, 0x17, 0x75, 0x7f, 0x6b,
+ 0xa9, 0xfd, 0x1d, 0xf1, 0xff, 0x4c, 0x8d, 0x3d, 0x3d, 0x12, 0x81, 0x4f, 0x8e, 0xa9, 0x33, 0x32, 0x02, 0xe7, 0xb7, 0xda,
+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xa9, 0xf5, 0x63, 0x33, 0xf9, 0x89, 0xd6,
+ 0x6b, 0x9a, 0x6b, 0x2b, 0x21, 0xd2, 0x58, 0xaf, 0xbc, 0x97, 0x47, 0xbf, 0x9a, 0xd5, 0xe5, 0x7c, 0xbd, 0x4c, 0x2e, 0xae,
+ 0xa1, 0x59, 0xad, 0x10, 0xc9, 0xf6, 0x5a, 0xbc, 0xee, 0xae, 0x06, 0xab, 0x4f, 0xeb, 0x64, 0x65, 0x38, 0xdf, 0x4d, 0xa0,
+ 0xbb, 0x0f, 0xc0, 0x59, 0x96, 0x83, 0x94, 0x3f, 0xef, 0xec, 0x95, 0x29, 0xe7, 0x0a, 0x4b, 0x61, 0xed, 0x54, 0x5a, 0x57,
+ 0x68, 0x27, 0xa3, 0xc3, 0xff, 0x7e, 0x5e, 0xe5, 0x6c, 0x65, 0x79, 0xa5, 0x55, 0xb2, 0xf1, 0xd5, 0xf3, 0x9d, 0xac, 0x32,
+ 0x10, 0xf6, 0xf3, 0xe8, 0x67, 0x70, 0x05, 0x7e, 0x86, 0xfe, 0x5a, 0x59, 0x25, 0x96, 0xad, 0x3a, 0x3e, 0x43, 0x75, 0xed,
+ 0x6e, 0x79, 0xa5, 0x51, 0x73, 0xa7, 0x5d, 0xe3, 0x1f, 0xad, 0x0c, 0x09, 0x19, 0xc8, 0x08, 0x90, 0x56, 0x09, 0x9d, 0xb5,
+ 0x42, 0x69, 0xaf, 0x42, 0xac, 0x67, 0x39, 0x4a, 0xf9, 0x3b, 0x1e, 0x8d, 0x3c, 0xa8, 0xb3, 0xd9, 0x97, 0x76, 0xf6, 0xfd,
+ 0x98, 0xc9, 0x98, 0x39, 0xb5, 0x86, 0xbe, 0x97, 0x9b, 0xa9, 0xfe, 0xd9, 0x9d, 0xab, 0x2a, 0x1b, 0xbd, 0xd0, 0x14, 0x7f,
+ 0x5d, 0x2e, 0xb7, 0x71, 0x7f, 0x6e, 0xf5, 0xea, 0x71, 0x53, 0xcf, 0xa9, 0x34, 0x95, 0x3b, 0xe9, 0xae, 0xf8, 0x3f, 0xc6,
+ 0xb3, 0x9c, 0xf5, 0x7a, 0x21, 0xbb, 0x3d, 0xf5, 0xbd, 0xf8, 0x5f, 0xef, 0x52, 0xb4, 0x5f, 0xe3, 0xdf, 0x19, 0xff, 0xbd,
+ 0x5c, 0x88, 0x59, 0xf6, 0xba, 0xbb, 0x7b, 0xaf, 0xd5, 0xfa, 0xf1, 0x69, 0x67, 0x97, 0xed, 0xe5, 0xd1, 0xc8, 0x22, 0xb7,
+ 0x6c, 0x6f, 0xdd, 0xfe, 0x7e, 0xff, 0x7f, 0xdd, 0x8f, 0x3f, 0xab, 0x1b, 0xef, 0xc8, 0xff, 0x77, 0x7f, 0xfc, 0xd7, 0xb2,
+ 0x26, 0xf7, 0xda, 0xf0, 0x6b, 0x79, 0x74, 0x27, 0xb3, 0xdf, 0x7d, 0x2a, 0xfe, 0xeb, 0xe3, 0xea, 0xe9, 0x31, 0x45, 0xe7,
+ 0x0c, 0xe5, 0x42, 0x2e, 0xc3, 0xb4, 0xf2, 0xa7, 0x9e, 0x8f, 0x7a, 0x67, 0xb3, 0xf0, 0xdc, 0xf9, 0x3e, 0x57, 0xc6, 0x62,
+ 0xcf, 0xc5, 0x7f, 0x36, 0x46, 0xe0, 0x7b, 0xed, 0x56, 0x2e, 0xb7, 0x22, 0xf7, 0xc7, 0xff, 0xdc, 0x9e, 0x95, 0xfb, 0x79,
+ 0xfa, 0x7a, 0x7d, 0xfc, 0x6c, 0xcc, 0x82, 0x75, 0xce, 0xe8, 0xb5, 0xb9, 0x8e, 0x3c, 0x32, 0xeb, 0x9d, 0xad, 0xb8, 0xb9,
+ 0x7f, 0x4e, 0xbe, 0x36, 0x1b, 0x34, 0x1f, 0xff, 0x47, 0x71, 0xfc, 0x7d, 0x5c, 0xdc, 0xab, 0x63, 0x77, 0xdc, 0x9a, 0xad,
+ 0xfe, 0xf8, 0xec, 0x9c, 0x55, 0xfd, 0xbb, 0x3f, 0xdf, 0xff, 0xdf, 0xcb, 0x1a, 0x9b, 0x56, 0x3f, 0x38, 0x1b, 0x75, 0x69,
+ 0x27, 0xf3, 0xf2, 0x4e, 0x8c, 0x4d, 0xee, 0x53, 0x36, 0xf1, 0x1d, 0xcf, 0x47, 0x11, 0xd3, 0xf1, 0x5f, 0x2f, 0x85, 0x7c,
+ 0xb4, 0x1f, 0xd4, 0xbf, 0x5a, 0xfb, 0x11, 0x98, 0xc1, 0xb3, 0xf8, 0xfc, 0xfc, 0x5f, 0xda, 0x75, 0x5f, 0x36, 0x33, 0x9e,
+ 0x57, 0xdb, 0x8e, 0x67, 0xf3, 0x09, 0xe6, 0xa5, 0xf9, 0x0b, 0xfb, 0xb9, 0xff, 0xf3, 0x48, 0xa4, 0x4d, 0xe7, 0x9c, 0xbe,
+ 0xbf, 0x1e, 0xd9, 0xbb, 0x77, 0x96, 0xdb, 0xcf, 0x62, 0x6e, 0x7f, 0xf7, 0x2c, 0x9f, 0x33, 0xe8, 0xde, 0xdf, 0xc8, 0xe0,
+ 0xfd, 0x44, 0x8e, 0xad, 0x79, 0x9a, 0x7c, 0xf8, 0x3b, 0x1e, 0xce, 0xef, 0x43, 0xf1, 0xff, 0xe9, 0x72, 0xef, 0xcf, 0xd5,
+ 0xc9, 0x7a, 0xfb, 0xfd, 0xf1, 0xcf, 0x3b, 0xe3, 0xff, 0x78, 0x49, 0xfc, 0xf3, 0x7c, 0x0d, 0x2e, 0xfe, 0xdf, 0x77, 0x2e,
+ 0x77, 0x9f, 0xff, 0x7d, 0xfb, 0xaf, 0xd3, 0x96, 0xdf, 0x55, 0xaa, 0xca, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0xaf, 0x1c, 0xca, 0x50, 0x46, 0xa0, 0xe3, 0xff, 0x72, 0x97, 0xac, 0x73, 0x4d, 0x76, 0xf2,
+ 0xc6, 0xf7, 0x57, 0x53, 0xa5, 0x7d, 0x6c, 0x27, 0x17, 0x4b, 0x2e, 0xad, 0x00, 0xc9, 0xc8, 0x7e, 0x09, 0xfd, 0x52, 0x4a,
+ 0x29, 0x9b, 0x68, 0x25, 0x7f, 0x5b, 0x1a, 0x2b, 0x83, 0x7b, 0x59, 0x9f, 0x3e, 0x75, 0x9e, 0x57, 0x19, 0x57, 0xfa, 0xbf,
+ 0x26, 0x37, 0xac, 0x1e, 0xbc, 0xfa, 0x3d, 0x7a, 0x59, 0x58, 0x73, 0x69, 0xa5, 0x5b, 0xda, 0xb9, 0x5c, 0xfb, 0xeb, 0x29,
+ 0xd3, 0x5c, 0x4f, 0x99, 0xed, 0xd2, 0x5e, 0x45, 0x63, 0x2f, 0x5f, 0x6a, 0xb7, 0x8e, 0xdc, 0xcf, 0xf0, 0x9d, 0xed, 0x77,
+ 0xbe, 0xb2, 0x47, 0x41, 0xbe, 0xe8, 0x3c, 0x77, 0xeb, 0x86, 0xfe, 0xef, 0xcc, 0xed, 0xb1, 0xb3, 0x9b, 0xf9, 0xef, 0xca,
+ 0x55, 0xdf, 0xdb, 0x87, 0xe6, 0x8d, 0xab, 0x38, 0x77, 0xea, 0xf0, 0x6e, 0x1e, 0xb3, 0x6f, 0x58, 0xdf, 0x9b, 0x8f, 0xfe,
+ 0xae, 0xe7, 0xce, 0xf3, 0x3a, 0xcf, 0xe1, 0x1b, 0x7e, 0x6b, 0x25, 0xc3, 0x6b, 0xa7, 0xfd, 0xcf, 0xa5, 0xf2, 0xba, 0x92,
+ 0xdd, 0xb4, 0xb7, 0xeb, 0xd5, 0x67, 0x8e, 0x1e, 0x9b, 0xd9, 0xb6, 0x3a, 0xd9, 0xae, 0xcf, 0x77, 0xac, 0xaa, 0x1f, 0xd9,
+ 0x6d, 0xff, 0xbb, 0x7f, 0xed, 0xec, 0x43, 0xf4, 0x89, 0xf3, 0xdc, 0xdb, 0x1d, 0x2d, 0x8b, 0x51, 0xf7, 0x95, 0x32, 0xae,
+ 0x1d, 0xdb, 0xed, 0x25, 0xef, 0x8d, 0xff, 0xab, 0xed, 0xff, 0x51, 0xbe, 0xea, 0x77, 0x7a, 0xda, 0x6f, 0x3b, 0xba, 0x93,
+ 0x71, 0xf3, 0xa9, 0x23, 0x77, 0xc4, 0x7f, 0x4e, 0xb3, 0xf1, 0xe7, 0xd2, 0x2c, 0xc3, 0x4e, 0x66, 0xe7, 0xfa, 0xd1, 0x5c,
+ 0x2a, 0x8f, 0xf3, 0x36, 0xf4, 0xfb, 0xe2, 0x7f, 0xef, 0xbd, 0xd7, 0xf1, 0x5d, 0xcf, 0x50, 0x7b, 0xb4, 0xe7, 0xe1, 0xee,
+ 0x8b, 0xe1, 0xa3, 0xfd, 0xad, 0xf2, 0x9a, 0x28, 0xaf, 0xe5, 0x04, 0xbd, 0xbb, 0xfd, 0xbf, 0x96, 0xdd, 0xfc, 0x3d, 0x47,
+ 0xaf, 0xb5, 0x49, 0xef, 0x88, 0xff, 0xdc, 0x3a, 0x26, 0x4c, 0x69, 0xa6, 0xf5, 0x28, 0xee, 0x7d, 0x94, 0xd7, 0xb5, 0x0b,
+ 0xeb, 0x3d, 0x35, 0xae, 0xb4, 0x29, 0xb3, 0x11, 0xdb, 0x3b, 0xf2, 0xa6, 0xfe, 0xff, 0x2f, 0xc5, 0xff, 0x1d, 0x31, 0xfe,
+ 0x4c, 0xfc, 0xef, 0xf5, 0x00, 0xfa, 0xfb, 0x2d, 0x75, 0x6a, 0x86, 0x9d, 0xbd, 0x6d, 0x76, 0x8f, 0x76, 0x6b, 0x87, 0xfc,
+ 0xa1, 0x36, 0xec, 0xcd, 0xb4, 0x7e, 0x5b, 0xff, 0xff, 0xfc, 0xfe, 0x4f, 0xda, 0xf3, 0xcb, 0xef, 0x8b, 0xff, 0x7e, 0x0b,
+ 0x70, 0x4f, 0xfc, 0xe7, 0xc1, 0x79, 0xd2, 0xb4, 0x67, 0x3d, 0xd3, 0xb8, 0x6f, 0xfc, 0xc6, 0x71, 0x61, 0xe5, 0xec, 0x77,
+ 0xf6, 0xd0, 0xfc, 0xee, 0xf8, 0x5f, 0xcf, 0x2f, 0xfd, 0x4a, 0xff, 0x3f, 0x1b, 0xb3, 0xa0, 0xd3, 0xf1, 0xff, 0x3d, 0xf9,
+ 0x46, 0x33, 0x36, 0xee, 0xf8, 0xbe, 0x56, 0xa3, 0x1b, 0x57, 0x3b, 0xa3, 0x89, 0xeb, 0x73, 0xae, 0xcf, 0xec, 0x76, 0x92,
+ 0x57, 0x9d, 0xab, 0x3b, 0xee, 0x58, 0x7e, 0x66, 0xfe, 0xef, 0x5b, 0x22, 0x5f, 0xfc, 0xaf, 0xe6, 0xd0, 0xcf, 0xc7, 0xcf,
+ 0xb5, 0x23, 0x95, 0xe7, 0x0c, 0x3f, 0x17, 0xff, 0x9f, 0x9b, 0xe7, 0xb9, 0x67, 0x37, 0x93, 0xce, 0x33, 0x36, 0xc7, 0x2d,
+ 0xcf, 0xce, 0xbd, 0xef, 0x59, 0x8b, 0xe3, 0x0b, 0xe2, 0x7f, 0x66, 0x36, 0xb4, 0x53, 0x12, 0x59, 0xec, 0x8b, 0x9c, 0xe2,
+ 0x33, 0xd7, 0x77, 0xf5, 0xff, 0x67, 0x5b, 0xc5, 0x4f, 0x3e, 0xe7, 0xf1, 0xfc, 0x95, 0xde, 0x3d, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf6, 0xda, 0xba, 0x7a, 0xd6, 0xbd, 0x34, 0xd7, 0xef, 0xf6, 0xd7,
+ 0xa9, 0xd6, 0x77, 0x0d, 0xb8, 0xf2, 0x9e, 0x29, 0xaf, 0xbf, 0xa9, 0x7d, 0x52, 0xe5, 0x5b, 0xdf, 0x93, 0x75, 0xff, 0x58,
+ 0xe4, 0x18, 0xc8, 0xc8, 0x35, 0x91, 0x72, 0x4e, 0x87, 0xa3, 0x99, 0x95, 0x28, 0xe5, 0xab, 0x2e, 0x8d, 0xbf, 0xa7, 0xbc,
+ 0x32, 0xf3, 0x68, 0x7c, 0xef, 0x37, 0xaf, 0xb9, 0xef, 0x66, 0xf2, 0xec, 0xef, 0x50, 0x31, 0xbd, 0xea, 0x31, 0xcd, 0x3c,
+ 0xdc, 0x19, 0x5b, 0xef, 0x9a, 0x8d, 0x15, 0xcd, 0x9d, 0x48, 0xaf, 0xd4, 0xd7, 0x69, 0xc7, 0x46, 0xad, 0x3e, 0xcb, 0xe8,
+ 0x75, 0x3a, 0xb7, 0x43, 0x4c, 0x46, 0x33, 0x69, 0xbe, 0x79, 0x5d, 0x5e, 0x9a, 0xd9, 0x35, 0xf2, 0x05, 0xeb, 0x90, 0xb3,
+ 0xb1, 0x5b, 0x4a, 0x1a, 0x3b, 0x9d, 0x7c, 0x66, 0xa5, 0xf3, 0xde, 0x95, 0xf9, 0xce, 0x55, 0xa3, 0xd5, 0x7c, 0x6e, 0x4f,
+ 0x5d, 0x75, 0xbd, 0x9c, 0x1f, 0x19, 0x7f, 0xc7, 0x67, 0xe2, 0xbf, 0x93, 0x77, 0x37, 0xcb, 0x3e, 0xe5, 0xb3, 0xab, 0x9e,
+ 0xbb, 0xd9, 0xc6, 0xd2, 0xda, 0x6d, 0x60, 0xff, 0xef, 0x9f, 0xc8, 0xba, 0x73, 0x6f, 0xfb, 0x3f, 0xdf, 0xc7, 0xae, 0x66,
+ 0x38, 0xe8, 0x5d, 0xdd, 0xdd, 0x9d, 0x2e, 0xf2, 0x33, 0xf1, 0xbf, 0xce, 0xba, 0x98, 0x91, 0xd9, 0x84, 0x4f, 0x1c, 0x4b,
+ 0x73, 0xd7, 0xa7, 0x0c, 0x8d, 0x17, 0xd6, 0xb9, 0x2e, 0x9f, 0x88, 0xff, 0x9c, 0xf4, 0xce, 0xd3, 0xd8, 0xd9, 0x62, 0xea,
+ 0xef, 0x93, 0xb3, 0x15, 0xfd, 0x5d, 0x6b, 0xe6, 0xe2, 0x3f, 0xc3, 0x3b, 0xb0, 0xbd, 0x3d, 0xfe, 0xa7, 0x67, 0x00, 0xfa,
+ 0x31, 0x9e, 0xf6, 0x68, 0x6d, 0x62, 0x94, 0xdb, 0xf9, 0xfb, 0x73, 0x59, 0xf7, 0xcf, 0xf2, 0x2a, 0xa7, 0x75, 0x45, 0x64,
+ 0x60, 0x1e, 0x25, 0xed, 0x1e, 0xf6, 0xfd, 0xf1, 0xbf, 0xb3, 0xe7, 0x4f, 0xbe, 0x2e, 0xfe, 0x57, 0x35, 0x5a, 0x3d, 0xbf,
+ 0x6d, 0x5a, 0xb1, 0xda, 0x3b, 0x96, 0x8d, 0xd9, 0x9f, 0x2c, 0xb3, 0xe6, 0xdf, 0xd3, 0xfb, 0xaf, 0x7d, 0xdb, 0x99, 0xf8,
+ 0x9f, 0x89, 0xce, 0x4f, 0xc6, 0x7f, 0x36, 0xf6, 0x8e, 0x99, 0x6c, 0xdd, 0xd2, 0xcc, 0x14, 0x9a, 0x97, 0xce, 0xff, 0x75,
+ 0x46, 0x34, 0xf3, 0x7b, 0x75, 0xdc, 0x71, 0x6c, 0x6f, 0xe6, 0x2b, 0x37, 0x8e, 0x7d, 0x8f, 0x0f, 0xb4, 0xff, 0x13, 0x35,
+ 0xc3, 0x67, 0xdb, 0xff, 0x63, 0xf4, 0x7a, 0x5c, 0xff, 0xfa, 0x3c, 0xd0, 0xa3, 0x7c, 0x4b, 0xfc, 0xe7, 0x4b, 0xe3, 0xff,
+ 0xb8, 0xb0, 0xa3, 0xdc, 0x5b, 0x6b, 0x80, 0x3c, 0x3a, 0xfe, 0x7f, 0x57, 0xfc, 0xcf, 0xde, 0x01, 0xc9, 0xf2, 0x1e, 0x67,
+ 0x2d, 0xca, 0xd3, 0xb8, 0xd3, 0x98, 0xe2, 0x6e, 0x6a, 0xef, 0x79, 0xfe, 0x27, 0xcd, 0xd1, 0x49, 0x35, 0x1e, 0xef, 0x39,
+ 0x76, 0xcf, 0xac, 0x6b, 0xca, 0x73, 0x8a, 0x19, 0xb9, 0xce, 0x9f, 0xcc, 0xba, 0xbb, 0x1a, 0xc5, 0x3d, 0xff, 0xeb, 0x77,
+ 0xef, 0xa7, 0x66, 0xe8, 0xc8, 0xe4, 0xb3, 0x44, 0x6f, 0x79, 0x3a, 0x60, 0xfa, 0x1e, 0xda, 0x37, 0xe4, 0x21, 0xce, 0xcf,
+ 0x67, 0x4c, 0xbf, 0xef, 0xa9, 0x01, 0xee, 0xed, 0xe9, 0x7d, 0xcf, 0xb3, 0xc1, 0x88, 0x7e, 0xd6, 0xcf, 0xa8, 0xfc, 0xe6,
+ 0xef, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa6, 0xfd, 0xfb, 0x9f, 0x72, 0x00, 0xf1, 0x0f, 0xfc, 0x75, 0xf1, 0xff, 0x2f };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle lavandaFontRecs[189] = {
+ { 4, 4, 5 , 16 },
+ { 17, 4, 1 , 9 },
+ { 26, 4, 3 , 3 },
+ { 37, 4, 7 , 8 },
+ { 52, 4, 5 , 11 },
+ { 65, 4, 10 , 8 },
+ { 83, 4, 7 , 9 },
+ { 98, 4, 1 , 3 },
+ { 107, 4, 3 , 12 },
+ { 118, 4, 3 , 12 },
+ { 129, 4, 5 , 4 },
+ { 142, 4, 5 , 5 },
+ { 155, 4, 2 , 3 },
+ { 165, 4, 3 , 1 },
+ { 176, 4, 1 , 1 },
+ { 185, 4, 4 , 12 },
+ { 197, 4, 5 , 9 },
+ { 210, 4, 3 , 9 },
+ { 221, 4, 5 , 9 },
+ { 234, 4, 5 , 9 },
+ { 247, 4, 5 , 9 },
+ { 260, 4, 5 , 9 },
+ { 273, 4, 5 , 9 },
+ { 286, 4, 5 , 9 },
+ { 299, 4, 5 , 9 },
+ { 312, 4, 5 , 9 },
+ { 325, 4, 1 , 4 },
+ { 334, 4, 2 , 6 },
+ { 344, 4, 4 , 5 },
+ { 356, 4, 4 , 3 },
+ { 368, 4, 4 , 5 },
+ { 380, 4, 5 , 9 },
+ { 393, 4, 7 , 10 },
+ { 408, 4, 7 , 9 },
+ { 423, 4, 6 , 9 },
+ { 437, 4, 5 , 9 },
+ { 450, 4, 6 , 9 },
+ { 464, 4, 5 , 9 },
+ { 477, 4, 5 , 9 },
+ { 490, 4, 6 , 9 },
+ { 4, 28, 5 , 10 },
+ { 17, 28, 1 , 9 },
+ { 26, 28, 6 , 9 },
+ { 40, 28, 6 , 9 },
+ { 54, 28, 5 , 9 },
+ { 67, 28, 8 , 11 },
+ { 83, 28, 6 , 10 },
+ { 97, 28, 7 , 9 },
+ { 112, 28, 5 , 9 },
+ { 125, 28, 7 , 11 },
+ { 140, 28, 5 , 9 },
+ { 153, 28, 6 , 9 },
+ { 167, 28, 7 , 9 },
+ { 182, 28, 6 , 9 },
+ { 196, 28, 6 , 10 },
+ { 210, 28, 9 , 10 },
+ { 227, 28, 6 , 11 },
+ { 241, 28, 5 , 10 },
+ { 254, 28, 5 , 9 },
+ { 267, 28, 3 , 12 },
+ { 278, 28, 4 , 12 },
+ { 290, 28, 3 , 12 },
+ { 301, 28, 5 , 4 },
+ { 314, 28, 6 , 1 },
+ { 328, 28, 3 , 3 },
+ { 339, 28, 6 , 7 },
+ { 353, 28, 5 , 9 },
+ { 366, 28, 4 , 7 },
+ { 378, 28, 5 , 10 },
+ { 391, 28, 4 , 7 },
+ { 403, 28, 3 , 10 },
+ { 414, 28, 4 , 11 },
+ { 426, 28, 5 , 11 },
+ { 439, 28, 1 , 9 },
+ { 448, 28, 5 , 12 },
+ { 461, 28, 5 , 9 },
+ { 474, 28, 1 , 9 },
+ { 483, 28, 8 , 9 },
+ { 4, 52, 5 , 9 },
+ { 17, 52, 4 , 7 },
+ { 29, 52, 5 , 10 },
+ { 42, 52, 5 , 10 },
+ { 55, 52, 5 , 7 },
+ { 68, 52, 5 , 7 },
+ { 81, 52, 3 , 9 },
+ { 92, 52, 5 , 7 },
+ { 105, 52, 5 , 8 },
+ { 118, 52, 9 , 8 },
+ { 135, 52, 5 , 9 },
+ { 148, 52, 6 , 9 },
+ { 162, 52, 4 , 7 },
+ { 174, 52, 5 , 12 },
+ { 187, 52, 1 , 12 },
+ { 196, 52, 5 , 12 },
+ { 209, 52, 6 , 2 },
+ { 223, 52, 1 , 9 },
+ { 232, 52, 5 , 10 },
+ { 245, 52, 6 , 9 },
+ { 259, 52, 7 , 9 },
+ { 274, 52, 5 , 9 },
+ { 287, 52, 6 , 12 },
+ { 301, 52, 5 , 10 },
+ { 314, 52, 5 , 10 },
+ { 327, 52, 8 , 8 },
+ { 343, 52, 4 , 7 },
+ { 355, 52, 6 , 5 },
+ { 369, 52, 6 , 3 },
+ { 383, 52, 8 , 8 },
+ { 399, 52, 5 , 1 },
+ { 412, 52, 4 , 4 },
+ { 424, 52, 5 , 7 },
+ { 437, 52, 3 , 4 },
+ { 448, 52, 3 , 4 },
+ { 459, 52, 5 , 12 },
+ { 472, 52, 5 , 10 },
+ { 485, 52, 7 , 11 },
+ { 500, 52, 1 , 1 },
+ { 4, 76, 4 , 10 },
+ { 16, 76, 2 , 4 },
+ { 26, 76, 4 , 7 },
+ { 38, 76, 6 , 5 },
+ { 52, 76, 11 , 9 },
+ { 71, 76, 7 , 7 },
+ { 86, 76, 5 , 12 },
+ { 99, 76, 5 , 9 },
+ { 112, 76, 7 , 12 },
+ { 127, 76, 7 , 12 },
+ { 142, 76, 7 , 12 },
+ { 157, 76, 7 , 12 },
+ { 172, 76, 7 , 11 },
+ { 187, 76, 7 , 12 },
+ { 202, 76, 10 , 9 },
+ { 220, 76, 5 , 12 },
+ { 233, 76, 5 , 12 },
+ { 246, 76, 5 , 12 },
+ { 259, 76, 5 , 12 },
+ { 272, 76, 5 , 11 },
+ { 285, 76, 2 , 12 },
+ { 295, 76, 2 , 12 },
+ { 305, 76, 3 , 12 },
+ { 316, 76, 3 , 11 },
+ { 327, 76, 7 , 9 },
+ { 342, 76, 6 , 12 },
+ { 356, 76, 7 , 12 },
+ { 371, 76, 7 , 12 },
+ { 386, 76, 7 , 12 },
+ { 401, 76, 7 , 12 },
+ { 416, 76, 7 , 11 },
+ { 431, 76, 5 , 5 },
+ { 444, 76, 7 , 9 },
+ { 459, 76, 6 , 12 },
+ { 473, 76, 6 , 12 },
+ { 487, 76, 6 , 12 },
+ { 4, 100, 6 , 11 },
+ { 18, 100, 5 , 13 },
+ { 31, 100, 5 , 9 },
+ { 44, 100, 5 , 11 },
+ { 57, 100, 6 , 10 },
+ { 71, 100, 6 , 10 },
+ { 85, 100, 6 , 10 },
+ { 99, 100, 6 , 10 },
+ { 113, 100, 6 , 9 },
+ { 127, 100, 6 , 11 },
+ { 141, 100, 7 , 7 },
+ { 156, 100, 4 , 10 },
+ { 168, 100, 4 , 10 },
+ { 180, 100, 4 , 10 },
+ { 192, 100, 4 , 10 },
+ { 204, 100, 4 , 9 },
+ { 216, 100, 2 , 10 },
+ { 226, 100, 2 , 10 },
+ { 236, 100, 3 , 10 },
+ { 247, 100, 3 , 9 },
+ { 258, 100, 5 , 9 },
+ { 271, 100, 5 , 12 },
+ { 284, 100, 4 , 10 },
+ { 296, 100, 4 , 10 },
+ { 308, 100, 4 , 10 },
+ { 320, 100, 5 , 10 },
+ { 333, 100, 4 , 9 },
+ { 345, 100, 5 , 5 },
+ { 358, 100, 6 , 7 },
+ { 372, 100, 5 , 10 },
+ { 385, 100, 5 , 10 },
+ { 398, 100, 5 , 10 },
+ { 411, 100, 5 , 9 },
+ { 424, 100, 6 , 12 },
+ { 438, 100, 5 , 12 },
+ { 451, 100, 6 , 11 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo lavandaFontGlyphs[189] = {
+ { 32, 0, 12, 5, { 0 }},
+ { 33, 0, 3, 2, { 0 }},
+ { 34, 0, 3, 4, { 0 }},
+ { 35, 0, 3, 8, { 0 }},
+ { 36, 0, 2, 6, { 0 }},
+ { 37, 0, 4, 11, { 0 }},
+ { 38, 0, 3, 8, { 0 }},
+ { 39, 0, 3, 2, { 0 }},
+ { 40, 0, 2, 4, { 0 }},
+ { 41, 0, 2, 4, { 0 }},
+ { 42, 0, 3, 6, { 0 }},
+ { 43, 0, 5, 6, { 0 }},
+ { 44, 0, 10, 3, { 0 }},
+ { 45, 0, 7, 4, { 0 }},
+ { 46, 0, 11, 2, { 0 }},
+ { 47, 0, 2, 5, { 0 }},
+ { 48, 0, 3, 6, { 0 }},
+ { 49, 0, 3, 4, { 0 }},
+ { 50, 0, 3, 6, { 0 }},
+ { 51, 0, 3, 6, { 0 }},
+ { 52, 0, 3, 6, { 0 }},
+ { 53, 0, 3, 6, { 0 }},
+ { 54, 0, 3, 6, { 0 }},
+ { 55, 0, 3, 6, { 0 }},
+ { 56, 0, 3, 6, { 0 }},
+ { 57, 0, 3, 6, { 0 }},
+ { 58, 0, 7, 2, { 0 }},
+ { 59, 0, 7, 3, { 0 }},
+ { 60, 0, 5, 5, { 0 }},
+ { 61, 0, 6, 5, { 0 }},
+ { 62, 0, 5, 5, { 0 }},
+ { 63, 0, 3, 6, { 0 }},
+ { 64, 0, 4, 8, { 0 }},
+ { 65, 0, 3, 8, { 0 }},
+ { 66, 0, 3, 7, { 0 }},
+ { 67, 0, 3, 6, { 0 }},
+ { 68, 0, 3, 7, { 0 }},
+ { 69, 0, 3, 6, { 0 }},
+ { 70, 0, 3, 6, { 0 }},
+ { 71, 0, 3, 7, { 0 }},
+ { 72, 0, 2, 6, { 0 }},
+ { 73, 0, 3, 2, { 0 }},
+ { 74, 0, 3, 7, { 0 }},
+ { 75, 0, 3, 7, { 0 }},
+ { 76, 0, 3, 6, { 0 }},
+ { 77, 0, 3, 9, { 0 }},
+ { 78, 0, 2, 7, { 0 }},
+ { 79, 0, 3, 8, { 0 }},
+ { 80, 0, 3, 6, { 0 }},
+ { 81, 0, 3, 8, { 0 }},
+ { 82, 0, 3, 6, { 0 }},
+ { 83, 0, 3, 7, { 0 }},
+ { 84, 0, 3, 8, { 0 }},
+ { 85, 0, 3, 7, { 0 }},
+ { 86, 0, 2, 7, { 0 }},
+ { 87, 0, 2, 10, { 0 }},
+ { 88, 0, 3, 7, { 0 }},
+ { 89, 0, 3, 6, { 0 }},
+ { 90, 0, 3, 6, { 0 }},
+ { 91, 0, 2, 4, { 0 }},
+ { 92, 0, 2, 5, { 0 }},
+ { 93, 0, 2, 4, { 0 }},
+ { 94, 0, 3, 6, { 0 }},
+ { 95, 0, 13, 7, { 0 }},
+ { 96, 0, 3, 4, { 0 }},
+ { 97, 0, 5, 7, { 0 }},
+ { 98, 0, 3, 6, { 0 }},
+ { 99, 0, 5, 5, { 0 }},
+ { 100, 0, 2, 6, { 0 }},
+ { 101, 0, 5, 5, { 0 }},
+ { 102, 0, 2, 4, { 0 }},
+ { 103, 0, 4, 5, { 0 }},
+ { 104, 0, 3, 6, { 0 }},
+ { 105, 0, 3, 2, { 0 }},
+ { 106, -1, 3, 5, { 0 }},
+ { 107, 0, 3, 6, { 0 }},
+ { 108, 0, 3, 2, { 0 }},
+ { 109, 0, 5, 9, { 0 }},
+ { 110, 0, 5, 6, { 0 }},
+ { 111, 0, 5, 5, { 0 }},
+ { 112, 0, 5, 6, { 0 }},
+ { 113, 0, 5, 6, { 0 }},
+ { 114, 0, 5, 6, { 0 }},
+ { 115, 0, 5, 6, { 0 }},
+ { 116, 0, 3, 4, { 0 }},
+ { 117, 0, 5, 6, { 0 }},
+ { 118, 0, 4, 6, { 0 }},
+ { 119, 0, 4, 10, { 0 }},
+ { 120, 0, 5, 6, { 0 }},
+ { 121, -1, 5, 6, { 0 }},
+ { 122, 0, 5, 5, { 0 }},
+ { 123, 0, 2, 6, { 0 }},
+ { 124, 0, 2, 2, { 0 }},
+ { 125, 0, 2, 6, { 0 }},
+ { 126, 0, 7, 7, { 0 }},
+ { 161, 0, 5, 2, { 0 }},
+ { 162, 0, 4, 6, { 0 }},
+ { 163, 0, 3, 7, { 0 }},
+ { 8364, 0, 3, 8, { 0 }},
+ { 165, 0, 3, 6, { 0 }},
+ { 352, 0, 0, 7, { 0 }},
+ { 167, 0, 3, 6, { 0 }},
+ { 353, 0, 2, 6, { 0 }},
+ { 169, 0, 4, 9, { 0 }},
+ { 170, 0, 3, 5, { 0 }},
+ { 171, 0, 6, 7, { 0 }},
+ { 172, 0, 6, 7, { 0 }},
+ { 174, 0, 4, 9, { 0 }},
+ { 175, 0, 2, 6, { 0 }},
+ { 176, 0, 3, 5, { 0 }},
+ { 177, 0, 5, 6, { 0 }},
+ { 178, 0, 3, 4, { 0 }},
+ { 179, 0, 3, 4, { 0 }},
+ { 381, 0, 0, 6, { 0 }},
+ { 181, 0, 5, 6, { 0 }},
+ { 182, 0, 3, 8, { 0 }},
+ { 183, 0, 7, 2, { 0 }},
+ { 382, 0, 2, 5, { 0 }},
+ { 185, 0, 3, 3, { 0 }},
+ { 186, 0, 3, 5, { 0 }},
+ { 187, 0, 6, 7, { 0 }},
+ { 338, 0, 3, 12, { 0 }},
+ { 339, 0, 5, 8, { 0 }},
+ { 376, 0, 1, 6, { 0 }},
+ { 191, 0, 5, 6, { 0 }},
+ { 192, 0, 0, 8, { 0 }},
+ { 193, 0, 0, 8, { 0 }},
+ { 194, 0, 0, 8, { 0 }},
+ { 195, 0, 0, 8, { 0 }},
+ { 196, 0, 1, 8, { 0 }},
+ { 197, 0, 0, 8, { 0 }},
+ { 198, 0, 3, 11, { 0 }},
+ { 199, 0, 3, 6, { 0 }},
+ { 200, 0, 0, 6, { 0 }},
+ { 201, 0, 0, 6, { 0 }},
+ { 202, 0, 0, 6, { 0 }},
+ { 203, 0, 1, 6, { 0 }},
+ { 204, -1, 0, 2, { 0 }},
+ { 205, 0, 0, 3, { 0 }},
+ { 206, -1, 0, 3, { 0 }},
+ { 207, -1, 1, 3, { 0 }},
+ { 208, -1, 3, 7, { 0 }},
+ { 209, 0, 0, 7, { 0 }},
+ { 210, 0, 0, 8, { 0 }},
+ { 211, 0, 0, 8, { 0 }},
+ { 212, 0, 0, 8, { 0 }},
+ { 213, 0, 0, 8, { 0 }},
+ { 214, 0, 1, 8, { 0 }},
+ { 215, 0, 5, 6, { 0 }},
+ { 216, 0, 3, 8, { 0 }},
+ { 217, 0, 0, 7, { 0 }},
+ { 218, 0, 0, 7, { 0 }},
+ { 219, 0, 0, 7, { 0 }},
+ { 220, 0, 1, 7, { 0 }},
+ { 221, 0, 0, 6, { 0 }},
+ { 222, 0, 3, 6, { 0 }},
+ { 223, 0, 3, 6, { 0 }},
+ { 224, 0, 2, 7, { 0 }},
+ { 225, 0, 2, 7, { 0 }},
+ { 226, 0, 2, 7, { 0 }},
+ { 227, 0, 2, 7, { 0 }},
+ { 228, 0, 3, 7, { 0 }},
+ { 229, 0, 1, 7, { 0 }},
+ { 230, 0, 5, 8, { 0 }},
+ { 231, 0, 5, 5, { 0 }},
+ { 232, 0, 2, 5, { 0 }},
+ { 233, 0, 2, 5, { 0 }},
+ { 234, 0, 2, 5, { 0 }},
+ { 235, 0, 3, 5, { 0 }},
+ { 236, -1, 2, 2, { 0 }},
+ { 237, 0, 2, 3, { 0 }},
+ { 238, -1, 2, 3, { 0 }},
+ { 239, -1, 3, 3, { 0 }},
+ { 240, 0, 3, 6, { 0 }},
+ { 241, 0, 2, 6, { 0 }},
+ { 242, 0, 2, 5, { 0 }},
+ { 243, 0, 2, 5, { 0 }},
+ { 244, 0, 2, 5, { 0 }},
+ { 245, 0, 2, 6, { 0 }},
+ { 246, 0, 3, 5, { 0 }},
+ { 247, 0, 5, 6, { 0 }},
+ { 248, -1, 5, 6, { 0 }},
+ { 249, 0, 2, 6, { 0 }},
+ { 250, 0, 2, 6, { 0 }},
+ { 251, 0, 2, 6, { 0 }},
+ { 252, 0, 3, 6, { 0 }},
+ { 253, -1, 2, 6, { 0 }},
+ { 254, 0, 3, 6, { 0 }},
+ { 255, -1, 3, 6, { 0 }},
+};
+
+// Style loading function: Lavanda
+static void GuiLoadStyleLavanda(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < LAVANDA_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(lavandaStyleProps[i].controlId, lavandaStyleProps[i].propertyId, lavandaStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int lavandaFontDataSize = 0;
+ unsigned char *data = DecompressData(lavandaFontData, LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE, &lavandaFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 16;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, lavandaFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, lavandaFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_sunny.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_sunny.h
new file mode 100644
index 0000000000..8b3b1b2870
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_sunny.h
@@ -0,0 +1,616 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleSunny(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define SUNNY_STYLE_PROPS_COUNT 33
+
+// Custom style name: Sunny
+static const GuiStyleProp sunnyStyleProps[SUNNY_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0x9c760aff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x594006ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0xf6d519ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0xf6ee89ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0xf5f3d1ff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0xf4cd19ff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0xf7e580ff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0xf7f2c1ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0x52470aff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0xc0be92ff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0xd3d3a1ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0xbcbc89ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0x725706ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0xf0be4bff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
+ { 1, 2, 0x504506ff }, // LABEL_TEXT_COLOR_NORMAL
+ { 1, 5, 0xfdeb9bff }, // LABEL_TEXT_COLOR_FOCUSED
+ { 1, 8, 0xf5e8a4ff }, // LABEL_TEXT_COLOR_PRESSED
+ { 2, 2, 0xebc21fff }, // BUTTON_TEXT_COLOR_NORMAL
+ { 3, 2, 0xebc21fff }, // TOGGLE_TEXT_COLOR_NORMAL
+ { 4, 2, 0x81700fff }, // SLIDER_TEXT_COLOR_NORMAL
+ { 4, 5, 0xf4e49aff }, // SLIDER_TEXT_COLOR_FOCUSED
+ { 7, 2, 0xebc21fff }, // COMBOBOX_TEXT_COLOR_NORMAL
+ { 8, 2, 0xefd87bff }, // DROPDOWNBOX_TEXT_COLOR_NORMAL
+ { 8, 5, 0xd4b219ff }, // DROPDOWNBOX_TEXT_COLOR_FOCUSED
+ { 9, 2, 0x7a680bff }, // TEXTBOX_TEXT_COLOR_NORMAL
+ { 9, 5, 0xad931fff }, // TEXTBOX_TEXT_COLOR_FOCUSED
+ { 10, 2, 0x62570eff }, // VALUEBOX_TEXT_COLOR_NORMAL
+ { 10, 5, 0xf2df88ff }, // VALUEBOX_TEXT_COLOR_FOCUSED
+ { 12, 2, 0xf4e798ff }, // LISTVIEW_TEXT_COLOR_NORMAL
+ { 15, 2, 0xebc21fff }, // STATUSBAR_TEXT_COLOR_NORMAL
+};
+
+// WARNING: This style uses a custom font: "GenericMobileSystemNuevo.ttf" (size: 16, spacing: 0)
+
+#define SUNNY_STYLE_FONT_ATLAS_COMP_SIZE 2462
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char sunnyFontData[SUNNY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0x59, 0xb2, 0xeb, 0x34, 0x10, 0x00, 0x50, 0x6d, 0x83, 0xfd, 0xef, 0x8d, 0x6d, 0x88, 0xa2, 0x28, 0x0a, 0xb8, 0x8f,
+ 0x58, 0x52, 0x77, 0xcb, 0x53, 0x0e, 0xa7, 0xf8, 0xb9, 0x7e, 0x49, 0x6c, 0xd9, 0x6d, 0x0d, 0xb6, 0x5a, 0xbd, 0x01, 0x00,
+ 0x00, 0x00, 0x5f, 0xef, 0xcf, 0xff, 0xfe, 0xff, 0x6f, 0xff, 0xb7, 0xe5, 0x78, 0xdb, 0xdf, 0xff, 0x62, 0xb4, 0xa5, 0x7f,
+ 0xdc, 0x93, 0x7e, 0xb0, 0x6d, 0xee, 0xb7, 0x62, 0xfb, 0xd5, 0x97, 0xca, 0xa6, 0x1f, 0x94, 0x5a, 0x4b, 0xff, 0xbd, 0x1d,
+ 0x96, 0x7d, 0x0f, 0x94, 0x5e, 0x3b, 0xdc, 0xe7, 0xcf, 0x9f, 0x1c, 0x6f, 0xa9, 0xdc, 0xcf, 0x95, 0x32, 0xad, 0x3c, 0x3f,
+ 0x2b, 0x25, 0xd8, 0x96, 0xb7, 0x1e, 0x97, 0x54, 0x9b, 0x2a, 0xc7, 0xf1, 0x37, 0xf7, 0x9b, 0xc4, 0xff, 0xf1, 0xd1, 0xfc,
+ 0x1d, 0x83, 0x47, 0x67, 0x7f, 0xfe, 0xda, 0x68, 0xd3, 0xf7, 0x84, 0x7f, 0x7e, 0xbb, 0x2e, 0x42, 0xb3, 0xdf, 0xd2, 0x87,
+ 0x77, 0xc2, 0x95, 0x12, 0x3a, 0x2e, 0xbd, 0x16, 0x8a, 0x89, 0xd1, 0x77, 0x46, 0xf6, 0x65, 0x66, 0xdb, 0xdc, 0xfe, 0xc5,
+ 0xae, 0xf9, 0xf1, 0xf7, 0x1d, 0x5f, 0x69, 0x47, 0x67, 0x78, 0x74, 0xe5, 0x1e, 0x1f, 0xdf, 0xfa, 0x59, 0xcd, 0x44, 0xfd,
+ 0x9e, 0xf8, 0xef, 0xff, 0x8a, 0xb3, 0x1e, 0x8c, 0xc1, 0x7c, 0xdd, 0xb0, 0x5e, 0x2b, 0x1c, 0xdf, 0xb3, 0xf6, 0x95, 0xf0,
+ 0x51, 0x39, 0xf5, 0xc0, 0x35, 0xbc, 0x7e, 0xce, 0xa2, 0xbf, 0xb3, 0x23, 0xfe, 0x2b, 0xa2, 0xb8, 0x4d, 0xd4, 0x88, 0x91,
+ 0x36, 0xc5, 0x71, 0x8b, 0x33, 0x1f, 0xe1, 0xa3, 0x7d, 0x89, 0xb4, 0x67, 0xf2, 0x65, 0xb9, 0xda, 0xe6, 0xd8, 0x17, 0xff,
+ 0x15, 0xf5, 0xed, 0x7a, 0x5d, 0xb2, 0xaf, 0x7c, 0x67, 0xea, 0xeb, 0xfb, 0xc7, 0xff, 0xfa, 0xb1, 0x55, 0xc4, 0x7f, 0xcd,
+ 0x59, 0x59, 0x8f, 0xff, 0x2e, 0xfe, 0xa7, 0xeb, 0xff, 0xcf, 0xa5, 0xde, 0x83, 0xfd, 0xaf, 0x7c, 0xaf, 0xbd, 0xaa, 0x9d,
+ 0x7f, 0x6d, 0xfc, 0x8f, 0xfa, 0x83, 0x6d, 0x39, 0xfe, 0x63, 0xbd, 0xcf, 0x48, 0x6f, 0xa3, 0xaa, 0xfd, 0xbf, 0xb7, 0xf5,
+ 0x70, 0xdc, 0x7b, 0x8c, 0x44, 0xf8, 0xda, 0x98, 0x47, 0xcd, 0x37, 0x5f, 0x11, 0xff, 0x6d, 0x62, 0x6f, 0xfa, 0xb0, 0xff,
+ 0x3f, 0x7b, 0x87, 0x5f, 0x8b, 0xff, 0xba, 0xba, 0xe3, 0xca, 0xf8, 0xef, 0xc1, 0x11, 0xb1, 0xea, 0x7e, 0x7c, 0xfc, 0xd8,
+ 0xd6, 0xc6, 0xe7, 0xce, 0xeb, 0xff, 0x8f, 0xda, 0x81, 0x99, 0xf8, 0xff, 0x96, 0xf6, 0xff, 0x4c, 0x4b, 0x7b, 0x54, 0x8a,
+ 0xf3, 0xf7, 0xb3, 0x2b, 0x6a, 0xf3, 0x6b, 0xe3, 0xbf, 0x4f, 0x8d, 0x61, 0xdf, 0x3b, 0xfe, 0xdb, 0x72, 0x2f, 0xaf, 0xf2,
+ 0xda, 0x8d, 0x5e, 0x51, 0xa3, 0x2b, 0x77, 0xe6, 0xae, 0x76, 0xcf, 0xf8, 0x8f, 0x5d, 0xcf, 0x7d, 0xd8, 0xca, 0xef, 0x89,
+ 0xf8, 0x6f, 0xaf, 0x89, 0xff, 0x1e, 0x1c, 0xed, 0xf8, 0xdc, 0xde, 0x8b, 0x8d, 0xc7, 0x45, 0x5a, 0xf2, 0x99, 0x36, 0x4a,
+ 0x55, 0xfc, 0xdf, 0xe3, 0x4c, 0xaa, 0xff, 0x2b, 0xc6, 0xff, 0xdb, 0x61, 0x0b, 0xff, 0xbb, 0xe2, 0xff, 0xf8, 0xf9, 0x5f,
+ 0xbb, 0xfd, 0xb3, 0xba, 0x68, 0xfc, 0xd7, 0x8c, 0xff, 0x9f, 0x7f, 0xb7, 0x9e, 0xe9, 0xb9, 0xe6, 0xe2, 0xff, 0x4e, 0xcf,
+ 0xff, 0xf6, 0xc6, 0xff, 0xe8, 0xa9, 0xf7, 0x9b, 0xda, 0xff, 0x95, 0xe3, 0xf8, 0xf1, 0x77, 0x6e, 0xf6, 0xbd, 0x53, 0xd4,
+ 0x42, 0x6f, 0x72, 0xdd, 0x33, 0xfa, 0xa3, 0xcf, 0x81, 0x72, 0xa3, 0x74, 0x57, 0xbf, 0xff, 0x53, 0x5f, 0x82, 0xe7, 0xed,
+ 0x4f, 0xbf, 0x71, 0x9b, 0x91, 0x77, 0xbd, 0x25, 0xeb, 0xea, 0x3a, 0xf3, 0xf9, 0x6c, 0xfc, 0xb7, 0x9c, 0x1f, 0x76, 0xd6,
+ 0x6c, 0x4a, 0xe2, 0x19, 0x63, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xe4, 0xf9,
+ 0x0b, 0x91, 0xb9, 0x86, 0xd1, 0x3c, 0x04, 0xb5, 0xf9, 0x10, 0xfa, 0x8f, 0x3c, 0xac, 0xab, 0xdf, 0x3d, 0x3b, 0xd7, 0x32,
+ 0x33, 0x4f, 0xb3, 0xf6, 0xb3, 0x55, 0x99, 0x25, 0x6a, 0x67, 0x9e, 0x8f, 0xf3, 0xdd, 0xac, 0x66, 0x6b, 0x8e, 0x65, 0x41,
+ 0x5b, 0xcf, 0x69, 0x9e, 0xc9, 0xc3, 0x57, 0x3d, 0xb7, 0xba, 0x26, 0x3f, 0xda, 0xfc, 0x9c, 0xf7, 0x9a, 0x4c, 0x23, 0x75,
+ 0xf1, 0xbf, 0x7e, 0x1e, 0xfa, 0x8f, 0xfd, 0xe8, 0x17, 0x64, 0x62, 0xa8, 0xdf, 0x3a, 0xf7, 0xf7, 0x3b, 0xc5, 0xff, 0xec,
+ 0x3d, 0x38, 0x7b, 0xf5, 0xc6, 0x67, 0xdc, 0x8d, 0xb2, 0x4f, 0x5c, 0x9f, 0x5b, 0xa5, 0x15, 0xe5, 0x47, 0xad, 0x8f, 0xff,
+ 0x76, 0x52, 0xfd, 0x1f, 0x8d, 0xff, 0x3e, 0x5c, 0xcd, 0xe6, 0xbe, 0xf1, 0xbf, 0x9e, 0x77, 0x22, 0xfb, 0xab, 0xb9, 0x95,
+ 0x1c, 0xe2, 0xb9, 0xc6, 0xf3, 0xf1, 0x9f, 0xcb, 0x14, 0x74, 0x6e, 0xdd, 0x7a, 0x7d, 0xfc, 0x47, 0x4b, 0xe4, 0xaa, 0xf8,
+ 0x8f, 0x5f, 0x25, 0x7d, 0x98, 0xcd, 0xfa, 0x8e, 0xf1, 0xdf, 0xbf, 0x3e, 0xfe, 0xeb, 0x73, 0xf9, 0x46, 0x23, 0x20, 0x92,
+ 0x07, 0x7d, 0xa6, 0x5f, 0xbd, 0xda, 0xb3, 0x8b, 0xf7, 0xbb, 0xa2, 0xf5, 0xff, 0xe8, 0xf3, 0x33, 0x47, 0x72, 0x75, 0xfc,
+ 0xb7, 0x61, 0x84, 0xf7, 0x44, 0x94, 0xc6, 0x47, 0x40, 0x32, 0x39, 0xaf, 0xae, 0x89, 0xff, 0x16, 0x5a, 0x31, 0x30, 0x5e,
+ 0xcf, 0xdf, 0x3d, 0xfe, 0xab, 0xfb, 0x06, 0xd1, 0x11, 0x83, 0xea, 0x7d, 0xbc, 0x5f, 0xff, 0xbf, 0x17, 0xb4, 0x12, 0x77,
+ 0xc4, 0x7f, 0xb6, 0x7c, 0xa2, 0xd1, 0x14, 0x8b, 0xff, 0xf9, 0xda, 0x3d, 0xb6, 0x9a, 0x40, 0x6c, 0xdb, 0x7b, 0xe3, 0xbf,
+ 0x36, 0x7f, 0xea, 0xfa, 0x58, 0xf1, 0x9b, 0xe2, 0x3f, 0xda, 0xff, 0x9f, 0xef, 0x71, 0xdd, 0x2b, 0xfe, 0xdb, 0xc4, 0xfa,
+ 0x3c, 0x67, 0xc7, 0xff, 0x28, 0xdb, 0xea, 0xdb, 0xe2, 0x3f, 0x1a, 0x5b, 0xd1, 0xf5, 0x8c, 0x5a, 0xb8, 0xa6, 0x7b, 0x7b,
+ 0xfd, 0xdf, 0x5e, 0x1a, 0xff, 0xf1, 0xf5, 0x65, 0x9e, 0x15, 0xff, 0xd5, 0xad, 0x86, 0xeb, 0xf3, 0xea, 0x45, 0x47, 0x1b,
+ 0xe3, 0xa3, 0x94, 0xef, 0x6e, 0xff, 0xf7, 0x0d, 0xad, 0xf0, 0xec, 0xf3, 0xff, 0xab, 0xe2, 0x7f, 0xd7, 0xf3, 0xbf, 0x36,
+ 0xbd, 0xe6, 0xdf, 0xae, 0xbd, 0x12, 0xff, 0xd5, 0xf1, 0x5f, 0xb9, 0x76, 0xe2, 0xda, 0xbf, 0xa8, 0x7e, 0xff, 0xa7, 0x7e,
+ 0x24, 0x6d, 0xff, 0xfb, 0x3f, 0x7b, 0xca, 0xa7, 0x4d, 0xad, 0x98, 0xb6, 0xfe, 0xab, 0x6d, 0x72, 0x55, 0xe3, 0xd8, 0x3e,
+ 0xd7, 0xbf, 0x7d, 0x73, 0xf7, 0xf8, 0x8f, 0xbd, 0x6d, 0x10, 0xfd, 0x64, 0xfc, 0x13, 0xf7, 0x59, 0x0b, 0xec, 0x3b, 0xdf,
+ 0xa2, 0x54, 0x0a, 0xd5, 0x25, 0xa4, 0x54, 0x71, 0x07, 0x78, 0xd7, 0x7b, 0xe6, 0xbb, 0xfe, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0xcd, 0x5e, 0x99, 0xcd, 0xb9, 0xfd, 0xeb, 0x5f, 0x7b, 0x68, 0xbe,
+ 0x6b, 0x4f, 0x7e, 0xae, 0x2f, 0xe7, 0xc1, 0x58, 0x9b, 0x77, 0x5a, 0x91, 0x83, 0xa1, 0x3a, 0x8f, 0xd4, 0xb8, 0x5c, 0x66,
+ 0xcf, 0xf4, 0x78, 0x26, 0xf1, 0xea, 0x15, 0x12, 0x99, 0xd7, 0x93, 0xc9, 0xa8, 0x93, 0x59, 0x4b, 0x20, 0x9e, 0x09, 0xb1,
+ 0x2d, 0x7e, 0x6b, 0xec, 0xac, 0xfd, 0x3a, 0xbf, 0x3a, 0x9a, 0xef, 0xb3, 0x26, 0xfe, 0x63, 0xb9, 0x25, 0xaf, 0xc8, 0xb4,
+ 0x16, 0xbf, 0x9a, 0x6a, 0xf7, 0xb0, 0xbe, 0x54, 0xe6, 0xf6, 0x36, 0xf7, 0xf7, 0xcc, 0x9c, 0xfe, 0x5c, 0xee, 0x81, 0xd5,
+ 0x92, 0xe8, 0x53, 0xd9, 0x52, 0x56, 0x3f, 0xf9, 0xf9, 0x73, 0xc7, 0xdb, 0xfa, 0x54, 0xe6, 0x88, 0xd5, 0x6f, 0xfd, 0x6d,
+ 0xf0, 0xf9, 0x7e, 0x78, 0xe7, 0xad, 0x9d, 0xd1, 0xfa, 0x94, 0xf8, 0x5f, 0xbf, 0x77, 0x9f, 0x1d, 0xff, 0xf1, 0xfb, 0x54,
+ 0x2b, 0xcc, 0xd2, 0xb3, 0xbe, 0x36, 0x46, 0x64, 0xe6, 0x6e, 0x3e, 0x47, 0xd0, 0x19, 0x19, 0x35, 0x7e, 0x8d, 0xa6, 0x95,
+ 0xb3, 0x36, 0x17, 0xfd, 0x9f, 0xe2, 0xf7, 0xa8, 0xb5, 0xb5, 0x2f, 0xfe, 0x6b, 0x32, 0xf2, 0x3d, 0x27, 0xfe, 0x67, 0x7a,
+ 0x1b, 0xe7, 0xc5, 0xff, 0xf8, 0xef, 0x75, 0x59, 0xb5, 0x2b, 0x73, 0xed, 0x8c, 0x72, 0x2d, 0xb7, 0xd0, 0x19, 0xe9, 0xc1,
+ 0xfb, 0x4a, 0x2f, 0xce, 0x67, 0xde, 0x7f, 0xfc, 0x3f, 0x5b, 0x53, 0xcf, 0xc6, 0xff, 0xfa, 0x2f, 0xfe, 0x36, 0xd1, 0x7e,
+ 0xa8, 0x6e, 0xff, 0xaf, 0x5c, 0x2f, 0x4f, 0x8a, 0xff, 0x36, 0x95, 0x8b, 0xec, 0xde, 0xf5, 0x7f, 0x65, 0x4e, 0xad, 0xfa,
+ 0xf8, 0x8f, 0x45, 0x78, 0xa4, 0x26, 0x9f, 0x5f, 0xf1, 0x60, 0xed, 0xbc, 0x8d, 0x5b, 0xf9, 0x3d, 0xd1, 0xfe, 0xdf, 0x11,
+ 0xff, 0xd5, 0xe3, 0x7f, 0xf1, 0x35, 0x3c, 0xf6, 0x8c, 0x74, 0x45, 0xc6, 0xff, 0xda, 0x09, 0xfd, 0xff, 0x51, 0x3b, 0x31,
+ 0x5a, 0x2a, 0xf5, 0x6b, 0x53, 0x55, 0x66, 0xdb, 0x5e, 0x8d, 0xff, 0x4c, 0xfd, 0x1f, 0x1d, 0x87, 0xc8, 0xb4, 0x10, 0xdb,
+ 0x60, 0xe4, 0x60, 0xf4, 0x9b, 0xeb, 0x59, 0x43, 0x73, 0xed, 0xff, 0x1d, 0xf1, 0x7f, 0x56, 0xff, 0xbf, 0x25, 0x47, 0x35,
+ 0xeb, 0xda, 0xff, 0x2d, 0xd1, 0xca, 0xcc, 0xdc, 0x6d, 0x22, 0xa5, 0xbd, 0x5e, 0x66, 0x57, 0xd6, 0xff, 0xb9, 0xd5, 0xe6,
+ 0xda, 0xb6, 0x7c, 0xa7, 0x91, 0xf6, 0xff, 0x9e, 0xa7, 0x70, 0xcf, 0xae, 0xff, 0xcf, 0x7c, 0x3a, 0xb9, 0x73, 0x7f, 0xee,
+ 0x93, 0x77, 0x6e, 0x4f, 0x1e, 0xe9, 0x3b, 0xf4, 0xff, 0x23, 0xe3, 0xff, 0xd1, 0x9c, 0xc7, 0xe3, 0xda, 0xb8, 0x0f, 0x46,
+ 0xd3, 0xbe, 0x35, 0xfe, 0xef, 0x91, 0x9b, 0xf9, 0x7b, 0xe3, 0xbf, 0xa5, 0xf2, 0x4f, 0x5f, 0x11, 0xff, 0x73, 0x2d, 0xab,
+ 0xd8, 0x8a, 0x88, 0xb9, 0x15, 0x93, 0xa3, 0x7d, 0xba, 0x76, 0xea, 0x95, 0x9e, 0x79, 0xfe, 0xb7, 0xe7, 0xfd, 0x9f, 0xda,
+ 0x37, 0x0d, 0x9e, 0xfb, 0x3e, 0xd4, 0x3b, 0x8e, 0xe0, 0x8c, 0xfb, 0xf9, 0x78, 0xd5, 0x82, 0xbe, 0xe9, 0x98, 0x62, 0x4f,
+ 0x75, 0xa3, 0xcf, 0x89, 0xf7, 0xdd, 0xef, 0xa3, 0xef, 0xff, 0x44, 0xcb, 0x54, 0xa6, 0xe5, 0x6f, 0xb9, 0x83, 0x5d, 0x19,
+ 0xff, 0xfb, 0x5b, 0x49, 0x55, 0xef, 0x30, 0x7c, 0xdb, 0x95, 0xa2, 0x64, 0xbe, 0xe5, 0xbc, 0xae, 0x8f, 0xf4, 0xbe, 0xa5,
+ 0x24, 0x5c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3b, 0xe7, 0x8a, 0xf5, 0xb2,
+ 0x4c, 0x0b, 0xb3, 0x79, 0xae, 0xfa, 0xc2, 0xcc, 0xcd, 0x36, 0xcc, 0xdd, 0x9c, 0xfd, 0x9e, 0x9f, 0xab, 0x1a, 0xf4, 0xc1,
+ 0xbf, 0x68, 0x81, 0x3d, 0xed, 0xe1, 0x79, 0xc8, 0xeb, 0x6b, 0x34, 0xfc, 0xdc, 0xe3, 0x96, 0x28, 0x91, 0x36, 0x31, 0x4f,
+ 0x75, 0x6d, 0xae, 0xde, 0xee, 0x63, 0xae, 0xc9, 0x96, 0x1e, 0xc9, 0xfb, 0x37, 0x9b, 0xbd, 0x64, 0x47, 0xa9, 0xe4, 0x66,
+ 0xbb, 0xf7, 0xa5, 0xbf, 0xc7, 0x72, 0x3f, 0xf4, 0xc3, 0x18, 0xaa, 0xb9, 0x3f, 0xcd, 0x65, 0xe8, 0x5b, 0x9f, 0xb3, 0x3e,
+ 0x97, 0xdf, 0xb3, 0x6d, 0xcc, 0x89, 0xbd, 0x7e, 0xb5, 0xc7, 0x23, 0x25, 0xb7, 0x75, 0x6e, 0xae, 0xfe, 0x8e, 0x63, 0x8e,
+ 0xe7, 0xb3, 0x9d, 0xff, 0x9e, 0x4c, 0xed, 0x37, 0x9e, 0x85, 0x99, 0xa9, 0x27, 0xda, 0xd4, 0xdd, 0x7a, 0x2d, 0xca, 0xa3,
+ 0x77, 0x99, 0xf5, 0xf8, 0xaf, 0x99, 0x83, 0xde, 0x87, 0xc7, 0x13, 0x5b, 0x81, 0x63, 0x26, 0xbf, 0xf7, 0xfb, 0x5a, 0x8b,
+ 0xf9, 0xf8, 0xff, 0xd6, 0x36, 0xf6, 0xfd, 0x4a, 0xa0, 0x2f, 0xd6, 0xf1, 0x9f, 0x23, 0x6c, 0xa6, 0x15, 0x5f, 0x13, 0xff,
+ 0xeb, 0xf7, 0xad, 0xfd, 0xf1, 0xdf, 0x43, 0xdf, 0x10, 0x6d, 0xcf, 0xde, 0x73, 0x6b, 0x2e, 0xfe, 0xc7, 0x57, 0xd0, 0x9e,
+ 0xad, 0x55, 0xab, 0x28, 0xe5, 0x72, 0x94, 0xb7, 0x60, 0xef, 0x21, 0x9b, 0x11, 0x68, 0x35, 0x1b, 0x5b, 0x0f, 0xf5, 0x46,
+ 0xf6, 0xd4, 0xff, 0xf9, 0xfe, 0xff, 0x7c, 0xbb, 0x2d, 0x3e, 0x7e, 0x90, 0xb9, 0x96, 0x76, 0xb4, 0xc3, 0xcf, 0xd8, 0x1a,
+ 0xc9, 0x1b, 0x77, 0xd5, 0xd6, 0xdd, 0xf1, 0xdf, 0xff, 0xb3, 0x8e, 0xe2, 0x51, 0x44, 0xad, 0xdf, 0x1d, 0xee, 0xd7, 0xb2,
+ 0x88, 0x8f, 0xff, 0xad, 0x1e, 0x43, 0xc5, 0x11, 0xcf, 0xf5, 0x0b, 0x67, 0xa3, 0xb4, 0xae, 0xfe, 0xcf, 0x9c, 0xf5, 0x2b,
+ 0xb7, 0x66, 0x46, 0xf7, 0xde, 0x1a, 0xff, 0x73, 0xe5, 0x76, 0x45, 0xfc, 0x57, 0xe7, 0x13, 0x9c, 0x69, 0x4d, 0x44, 0xb3,
+ 0x34, 0x5f, 0xd1, 0x97, 0x9c, 0xcd, 0xce, 0x9f, 0x5b, 0x7f, 0xf6, 0x4d, 0xf1, 0xdf, 0x8a, 0xda, 0xff, 0x67, 0x6e, 0xbd,
+ 0x47, 0xfb, 0xbf, 0xbf, 0xa0, 0xfe, 0xcf, 0x3e, 0xd7, 0x99, 0x3f, 0x86, 0x73, 0x8e, 0x36, 0x9e, 0x81, 0x3f, 0xf3, 0x04,
+ 0xe3, 0xca, 0xbe, 0x70, 0x76, 0x6b, 0x36, 0xfe, 0xbf, 0xb5, 0xfe, 0x7f, 0x43, 0xfc, 0xe7, 0x9f, 0x65, 0xaf, 0x8c, 0xff,
+ 0x9d, 0x75, 0x44, 0xf9, 0xf6, 0x51, 0xee, 0xd9, 0xff, 0x3b, 0xeb, 0xff, 0x9a, 0x35, 0xe7, 0x9f, 0x16, 0xff, 0x33, 0xa3,
+ 0x4c, 0x4f, 0x8d, 0xff, 0x8a, 0x18, 0xa9, 0x1a, 0xff, 0xaf, 0xbe, 0x03, 0xb4, 0xad, 0x99, 0xeb, 0x9f, 0x17, 0xe1, 0xe3,
+ 0xf8, 0x8f, 0xbc, 0xff, 0xf3, 0xee, 0xf8, 0x9f, 0x7b, 0x37, 0xe6, 0xd9, 0xf1, 0xdf, 0x93, 0x2b, 0xd6, 0xbc, 0xf3, 0xf9,
+ 0x70, 0x6c, 0xfd, 0xe9, 0xe7, 0xc5, 0x7f, 0xfc, 0xed, 0x8c, 0xb7, 0x3f, 0xff, 0xcb, 0xbd, 0x1d, 0xb0, 0xf7, 0xf9, 0xdf,
+ 0x13, 0xde, 0x2b, 0xe1, 0x4d, 0xf7, 0x42, 0xe7, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x6a, 0x46, 0x46, 0x3c, 0x67, 0xcf, 0xdc, 0x4c, 0xb1, 0x6b, 0x72, 0xdf, 0x47, 0x32, 0x15, 0xcc, 0xec, 0x4f, 0x3c,
+ 0xff, 0x41, 0x24, 0xdb, 0xfe, 0xd1, 0xb9, 0x89, 0xe6, 0x1c, 0xcf, 0xe4, 0x32, 0xda, 0x75, 0x8c, 0xeb, 0x59, 0xe1, 0xe7,
+ 0x7f, 0x61, 0x2e, 0xf7, 0x63, 0x2c, 0x2e, 0xee, 0x71, 0xae, 0x33, 0xf3, 0xee, 0x76, 0x67, 0x8a, 0xef, 0xc9, 0x5c, 0xef,
+ 0xf5, 0x7b, 0x95, 0xcd, 0xd3, 0x1f, 0xdb, 0xe7, 0x48, 0x09, 0xf7, 0xc4, 0x4a, 0x2c, 0x6d, 0xe2, 0x4a, 0xaa, 0xce, 0xef,
+ 0x93, 0x59, 0x99, 0x63, 0xfe, 0x8e, 0x5c, 0x99, 0xb3, 0xbf, 0x25, 0xf2, 0xf5, 0xdf, 0xe5, 0x5c, 0xdf, 0xb5, 0x65, 0x71,
+ 0x9c, 0xf1, 0xe8, 0xbe, 0xad, 0xa4, 0x1e, 0xca, 0x6e, 0xfa, 0x9c, 0x7c, 0x04, 0xb1, 0x3a, 0xf7, 0xbd, 0xed, 0xe2, 0xf7,
+ 0x1f, 0x73, 0x26, 0xb7, 0xc0, 0x4c, 0x1d, 0xde, 0x02, 0xf1, 0x7f, 0xc7, 0xfc, 0x55, 0xb9, 0xcc, 0x57, 0x33, 0xa5, 0x78,
+ 0xd6, 0xb6, 0x23, 0xbf, 0x07, 0x56, 0x62, 0xbb, 0xf2, 0x18, 0xf7, 0xe7, 0xec, 0x38, 0xce, 0x26, 0xf2, 0xe4, 0x73, 0xdd,
+ 0xb6, 0xe7, 0x82, 0x89, 0xd6, 0xff, 0x4f, 0x8d, 0xff, 0xd1, 0x6a, 0x04, 0x9f, 0xd7, 0x25, 0x3b, 0x6f, 0x5b, 0xc5, 0x5a,
+ 0x06, 0xab, 0x3d, 0xa0, 0x1d, 0xdb, 0xae, 0xcc, 0xd9, 0x75, 0xf6, 0xb1, 0xc6, 0xcb, 0xe8, 0xca, 0xf8, 0x9f, 0xe9, 0xd7,
+ 0x7d, 0x5b, 0xfd, 0xdf, 0x2f, 0xdf, 0x36, 0x7f, 0x17, 0xbb, 0xfb, 0xb5, 0xbd, 0x7f, 0xcd, 0x8e, 0x27, 0xc4, 0xf8, 0x5d,
+ 0xe3, 0xff, 0xaa, 0x8c, 0xc7, 0x35, 0x2b, 0x2d, 0x45, 0xfb, 0xff, 0x4f, 0xb8, 0x26, 0x7a, 0x72, 0x2d, 0xe3, 0xd8, 0x0a,
+ 0xce, 0xd5, 0xdb, 0xc4, 0xff, 0xdd, 0xeb, 0xff, 0x99, 0xb1, 0x95, 0xfb, 0xe5, 0xaf, 0xcc, 0xae, 0xd3, 0xfb, 0xee, 0xeb,
+ 0xa5, 0x85, 0x9e, 0x79, 0xed, 0xd8, 0x26, 0xfe, 0xc5, 0xbf, 0xf8, 0xbf, 0xe2, 0x7a, 0xe9, 0x5f, 0xd1, 0xff, 0x17, 0xff,
+ 0xe2, 0x3f, 0xf2, 0xcc, 0xec, 0xfe, 0xfd, 0xff, 0x5d, 0x4f, 0x2a, 0xdf, 0x36, 0xfe, 0x1f, 0x7d, 0xda, 0xfb, 0xa4, 0xf1,
+ 0xff, 0xdd, 0xcf, 0xff, 0xae, 0xf8, 0xdd, 0xdc, 0x3e, 0xbf, 0xff, 0x19, 0xf7, 0x3b, 0xf2, 0xc5, 0xf3, 0xfc, 0xeb, 0x50,
+ 0x19, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe7, 0x00, 0xaf, 0xbe,
+ 0xa7, 0x7f, 0x66, 0xbe, 0xf7, 0xc8, 0x9c, 0xcf, 0xb9, 0xef, 0x04, 0xf1, 0x1f, 0x9b, 0xa7, 0x73, 0x66, 0xbe, 0xf7, 0xfc,
+ 0xdc, 0x7c, 0xe7, 0x1a, 0xde, 0x37, 0x53, 0x5c, 0x6c, 0x43, 0x2e, 0xc2, 0xa3, 0x39, 0x3a, 0xef, 0xb2, 0xed, 0x1d, 0x2b,
+ 0x73, 0xc0, 0xbd, 0x6a, 0xd5, 0xa7, 0xc4, 0x7f, 0xdb, 0x96, 0xef, 0x12, 0xbe, 0xb1, 0xff, 0x2f, 0xfe, 0x41, 0xfc, 0x8b,
+ 0x7f, 0xd0, 0xfe, 0x17, 0xff, 0x60, 0xfc, 0xff, 0xaa, 0x58, 0x9d, 0x59, 0x27, 0xe6, 0xc9, 0x4f, 0x31, 0xe0, 0x7e, 0x77,
+ 0x80, 0xf8, 0xdd, 0xa1, 0x7a, 0x5b, 0x1b, 0xde, 0x37, 0x3c, 0x23, 0x84, 0xb3, 0xe2, 0xff, 0x9a, 0x51, 0x8a, 0xd5, 0xf8,
+ 0xd7, 0xfe, 0x87, 0x37, 0xf5, 0x46, 0x22, 0xef, 0xff, 0x89, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe9, 0xaf, 0xff, 0x94, 0x03, 0x88, 0x7f, 0xe0, 0xeb, 0xe2, 0xff,
+ 0x0f };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle sunnyFontRecs[189] = {
+ { 4, 4, 4 , 16 },
+ { 16, 4, 2 , 10 },
+ { 26, 4, 5 , 3 },
+ { 39, 4, 7 , 10 },
+ { 54, 4, 7 , 13 },
+ { 69, 4, 7 , 10 },
+ { 84, 4, 7 , 10 },
+ { 99, 4, 2 , 3 },
+ { 109, 4, 3 , 12 },
+ { 120, 4, 3 , 12 },
+ { 131, 4, 5 , 6 },
+ { 144, 4, 6 , 5 },
+ { 158, 4, 2 , 4 },
+ { 168, 4, 5 , 1 },
+ { 181, 4, 2 , 2 },
+ { 191, 4, 4 , 10 },
+ { 203, 4, 6 , 10 },
+ { 217, 4, 4 , 10 },
+ { 229, 4, 6 , 10 },
+ { 243, 4, 6 , 10 },
+ { 257, 4, 6 , 10 },
+ { 271, 4, 6 , 10 },
+ { 285, 4, 6 , 10 },
+ { 299, 4, 6 , 10 },
+ { 313, 4, 6 , 10 },
+ { 327, 4, 6 , 10 },
+ { 341, 4, 2 , 6 },
+ { 351, 4, 2 , 8 },
+ { 361, 4, 7 , 7 },
+ { 376, 4, 5 , 3 },
+ { 389, 4, 7 , 7 },
+ { 404, 4, 6 , 10 },
+ { 418, 4, 7 , 12 },
+ { 433, 4, 7 , 10 },
+ { 448, 4, 7 , 10 },
+ { 463, 4, 7 , 10 },
+ { 478, 4, 7 , 10 },
+ { 493, 4, 7 , 10 },
+ { 4, 28, 7 , 10 },
+ { 19, 28, 7 , 10 },
+ { 34, 28, 7 , 10 },
+ { 49, 28, 2 , 10 },
+ { 59, 28, 5 , 10 },
+ { 72, 28, 7 , 10 },
+ { 87, 28, 6 , 10 },
+ { 101, 28, 9 , 10 },
+ { 118, 28, 7 , 10 },
+ { 133, 28, 7 , 10 },
+ { 148, 28, 7 , 10 },
+ { 163, 28, 7 , 12 },
+ { 178, 28, 7 , 10 },
+ { 193, 28, 7 , 10 },
+ { 208, 28, 6 , 10 },
+ { 222, 28, 7 , 10 },
+ { 237, 28, 7 , 10 },
+ { 252, 28, 8 , 10 },
+ { 268, 28, 7 , 10 },
+ { 283, 28, 6 , 10 },
+ { 297, 28, 7 , 10 },
+ { 312, 28, 4 , 12 },
+ { 324, 28, 4 , 10 },
+ { 336, 28, 4 , 12 },
+ { 348, 28, 6 , 3 },
+ { 362, 28, 7 , 1 },
+ { 377, 28, 4 , 3 },
+ { 389, 28, 6 , 7 },
+ { 403, 28, 6 , 10 },
+ { 417, 28, 6 , 7 },
+ { 431, 28, 6 , 10 },
+ { 445, 28, 6 , 7 },
+ { 459, 28, 4 , 10 },
+ { 471, 28, 6 , 9 },
+ { 485, 28, 6 , 10 },
+ { 499, 28, 2 , 10 },
+ { 4, 52, 5 , 12 },
+ { 17, 52, 6 , 10 },
+ { 31, 52, 3 , 10 },
+ { 42, 52, 8 , 7 },
+ { 58, 52, 6 , 7 },
+ { 72, 52, 6 , 7 },
+ { 86, 52, 6 , 9 },
+ { 100, 52, 6 , 9 },
+ { 114, 52, 5 , 7 },
+ { 127, 52, 6 , 7 },
+ { 141, 52, 4 , 10 },
+ { 153, 52, 6 , 7 },
+ { 167, 52, 6 , 7 },
+ { 181, 52, 8 , 7 },
+ { 197, 52, 6 , 7 },
+ { 211, 52, 6 , 9 },
+ { 225, 52, 6 , 7 },
+ { 239, 52, 5 , 12 },
+ { 252, 52, 2 , 12 },
+ { 262, 52, 5 , 12 },
+ { 275, 52, 7 , 3 },
+ { 290, 52, 2 , 9 },
+ { 300, 52, 6 , 11 },
+ { 314, 52, 7 , 10 },
+ { 329, 52, 7 , 9 },
+ { 344, 52, 6 , 10 },
+ { 358, 52, 7 , 11 },
+ { 373, 52, 6 , 12 },
+ { 387, 52, 6 , 10 },
+ { 401, 52, 7 , 10 },
+ { 416, 52, 5 , 5 },
+ { 429, 52, 7 , 6 },
+ { 444, 52, 6 , 3 },
+ { 458, 52, 7 , 10 },
+ { 473, 52, 9 , 10 },
+ { 490, 52, 4 , 4 },
+ { 4, 76, 6 , 7 },
+ { 18, 76, 4 , 5 },
+ { 30, 76, 4 , 5 },
+ { 42, 76, 7 , 11 },
+ { 57, 76, 6 , 9 },
+ { 71, 76, 7 , 12 },
+ { 86, 76, 2 , 2 },
+ { 96, 76, 6 , 10 },
+ { 110, 76, 3 , 5 },
+ { 121, 76, 4 , 5 },
+ { 133, 76, 7 , 6 },
+ { 148, 76, 9 , 10 },
+ { 165, 76, 8 , 7 },
+ { 181, 76, 6 , 11 },
+ { 195, 76, 6 , 11 },
+ { 209, 76, 7 , 11 },
+ { 224, 76, 7 , 11 },
+ { 239, 76, 7 , 11 },
+ { 254, 76, 7 , 11 },
+ { 269, 76, 7 , 11 },
+ { 284, 76, 7 , 11 },
+ { 299, 76, 9 , 10 },
+ { 316, 76, 7 , 12 },
+ { 331, 76, 7 , 11 },
+ { 346, 76, 7 , 11 },
+ { 361, 76, 7 , 11 },
+ { 376, 76, 7 , 11 },
+ { 391, 76, 3 , 11 },
+ { 402, 76, 3 , 11 },
+ { 413, 76, 5 , 11 },
+ { 426, 76, 5 , 11 },
+ { 439, 76, 8 , 10 },
+ { 455, 76, 7 , 11 },
+ { 470, 76, 7 , 11 },
+ { 485, 76, 7 , 11 },
+ { 4, 100, 7 , 11 },
+ { 19, 100, 7 , 11 },
+ { 34, 100, 7 , 11 },
+ { 49, 100, 7 , 7 },
+ { 64, 100, 7 , 13 },
+ { 79, 100, 7 , 11 },
+ { 94, 100, 7 , 11 },
+ { 109, 100, 7 , 11 },
+ { 124, 100, 7 , 11 },
+ { 139, 100, 6 , 11 },
+ { 153, 100, 7 , 10 },
+ { 168, 100, 7 , 10 },
+ { 183, 100, 6 , 10 },
+ { 197, 100, 6 , 10 },
+ { 211, 100, 6 , 10 },
+ { 225, 100, 6 , 10 },
+ { 239, 100, 6 , 10 },
+ { 253, 100, 6 , 11 },
+ { 267, 100, 8 , 7 },
+ { 283, 100, 6 , 9 },
+ { 297, 100, 6 , 10 },
+ { 311, 100, 6 , 10 },
+ { 325, 100, 6 , 10 },
+ { 339, 100, 6 , 10 },
+ { 353, 100, 3 , 10 },
+ { 364, 100, 3 , 10 },
+ { 375, 100, 5 , 10 },
+ { 388, 100, 5 , 10 },
+ { 401, 100, 6 , 10 },
+ { 415, 100, 6 , 10 },
+ { 429, 100, 6 , 10 },
+ { 443, 100, 6 , 10 },
+ { 457, 100, 6 , 10 },
+ { 471, 100, 6 , 10 },
+ { 485, 100, 6 , 10 },
+ { 4, 124, 6 , 7 },
+ { 18, 124, 7 , 11 },
+ { 33, 124, 6 , 10 },
+ { 47, 124, 6 , 10 },
+ { 61, 124, 6 , 10 },
+ { 75, 124, 6 , 10 },
+ { 89, 124, 6 , 12 },
+ { 103, 124, 6 , 12 },
+ { 117, 124, 6 , 12 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo sunnyFontGlyphs[189] = {
+ { 32, 0, 12, 4, { 0 }},
+ { 33, 0, 2, 3, { 0 }},
+ { 34, 0, 2, 6, { 0 }},
+ { 35, 0, 2, 8, { 0 }},
+ { 36, 0, 1, 8, { 0 }},
+ { 37, 0, 2, 8, { 0 }},
+ { 38, 0, 2, 8, { 0 }},
+ { 39, 0, 2, 3, { 0 }},
+ { 40, 0, 2, 4, { 0 }},
+ { 41, 0, 2, 4, { 0 }},
+ { 42, 0, 4, 6, { 0 }},
+ { 43, 0, 6, 7, { 0 }},
+ { 44, 0, 10, 3, { 0 }},
+ { 45, 0, 8, 6, { 0 }},
+ { 46, 0, 10, 3, { 0 }},
+ { 47, 0, 2, 5, { 0 }},
+ { 48, 0, 2, 7, { 0 }},
+ { 49, 0, 2, 7, { 0 }},
+ { 50, 0, 2, 7, { 0 }},
+ { 51, 0, 2, 7, { 0 }},
+ { 52, 0, 2, 7, { 0 }},
+ { 53, 0, 2, 7, { 0 }},
+ { 54, 0, 2, 7, { 0 }},
+ { 55, 0, 2, 7, { 0 }},
+ { 56, 0, 2, 7, { 0 }},
+ { 57, 0, 2, 7, { 0 }},
+ { 58, 0, 4, 3, { 0 }},
+ { 59, 0, 4, 3, { 0 }},
+ { 60, 0, 4, 8, { 0 }},
+ { 61, 0, 6, 6, { 0 }},
+ { 62, 0, 4, 8, { 0 }},
+ { 63, 0, 2, 7, { 0 }},
+ { 64, 0, 2, 8, { 0 }},
+ { 65, 0, 2, 8, { 0 }},
+ { 66, 0, 2, 8, { 0 }},
+ { 67, 0, 2, 8, { 0 }},
+ { 68, 0, 2, 8, { 0 }},
+ { 69, 0, 2, 8, { 0 }},
+ { 70, 0, 2, 8, { 0 }},
+ { 71, 0, 2, 8, { 0 }},
+ { 72, 0, 2, 8, { 0 }},
+ { 73, 0, 2, 3, { 0 }},
+ { 74, 0, 2, 6, { 0 }},
+ { 75, 0, 2, 8, { 0 }},
+ { 76, 0, 2, 7, { 0 }},
+ { 77, 0, 2, 10, { 0 }},
+ { 78, 0, 2, 8, { 0 }},
+ { 79, 0, 2, 8, { 0 }},
+ { 80, 0, 2, 8, { 0 }},
+ { 81, 0, 2, 8, { 0 }},
+ { 82, 0, 2, 8, { 0 }},
+ { 83, 0, 2, 8, { 0 }},
+ { 84, 0, 2, 7, { 0 }},
+ { 85, 0, 2, 8, { 0 }},
+ { 86, 0, 2, 8, { 0 }},
+ { 87, 0, 2, 9, { 0 }},
+ { 88, 0, 2, 8, { 0 }},
+ { 89, 0, 2, 7, { 0 }},
+ { 90, 0, 2, 8, { 0 }},
+ { 91, 0, 2, 5, { 0 }},
+ { 92, 0, 2, 5, { 0 }},
+ { 93, 0, 2, 5, { 0 }},
+ { 94, 0, 2, 7, { 0 }},
+ { 95, 0, 14, 8, { 0 }},
+ { 96, 0, 2, 5, { 0 }},
+ { 97, 0, 5, 7, { 0 }},
+ { 98, 0, 2, 7, { 0 }},
+ { 99, 0, 5, 7, { 0 }},
+ { 100, 0, 2, 7, { 0 }},
+ { 101, 0, 5, 7, { 0 }},
+ { 102, 0, 2, 5, { 0 }},
+ { 103, 0, 5, 7, { 0 }},
+ { 104, 0, 2, 7, { 0 }},
+ { 105, 0, 2, 3, { 0 }},
+ { 106, 0, 2, 6, { 0 }},
+ { 107, 0, 2, 7, { 0 }},
+ { 108, 0, 2, 4, { 0 }},
+ { 109, 0, 5, 9, { 0 }},
+ { 110, 0, 5, 7, { 0 }},
+ { 111, 0, 5, 7, { 0 }},
+ { 112, 0, 5, 7, { 0 }},
+ { 113, 0, 5, 7, { 0 }},
+ { 114, 0, 5, 6, { 0 }},
+ { 115, 0, 5, 7, { 0 }},
+ { 116, 0, 2, 5, { 0 }},
+ { 117, 0, 5, 7, { 0 }},
+ { 118, 0, 5, 7, { 0 }},
+ { 119, 0, 5, 9, { 0 }},
+ { 120, 0, 5, 7, { 0 }},
+ { 121, 0, 5, 7, { 0 }},
+ { 122, 0, 5, 7, { 0 }},
+ { 123, 0, 2, 6, { 0 }},
+ { 124, 0, 2, 3, { 0 }},
+ { 125, 0, 2, 6, { 0 }},
+ { 126, 0, 6, 8, { 0 }},
+ { 161, 0, 5, 3, { 0 }},
+ { 162, 0, 3, 7, { 0 }},
+ { 163, 0, 2, 8, { 0 }},
+ { 8364, 0, 3, 8, { 0 }},
+ { 165, 0, 2, 7, { 0 }},
+ { 352, 0, 1, 8, { 0 }},
+ { 167, 0, 2, 7, { 0 }},
+ { 353, 0, 2, 7, { 0 }},
+ { 169, 0, 2, 8, { 0 }},
+ { 170, 0, 2, 6, { 0 }},
+ { 171, 0, 6, 8, { 0 }},
+ { 172, 0, 7, 7, { 0 }},
+ { 174, 0, 2, 8, { 0 }},
+ { 175, 1, 3, 14, { 0 }},
+ { 176, 0, 2, 5, { 0 }},
+ { 177, 0, 4, 7, { 0 }},
+ { 178, 0, 2, 5, { 0 }},
+ { 179, 0, 2, 5, { 0 }},
+ { 381, 0, 1, 8, { 0 }},
+ { 181, 0, 5, 7, { 0 }},
+ { 182, 0, 2, 8, { 0 }},
+ { 183, 0, 6, 3, { 0 }},
+ { 382, 0, 2, 7, { 0 }},
+ { 185, 0, 2, 4, { 0 }},
+ { 186, 0, 2, 5, { 0 }},
+ { 187, 0, 6, 8, { 0 }},
+ { 338, 0, 2, 10, { 0 }},
+ { 339, 0, 5, 9, { 0 }},
+ { 376, 0, 1, 7, { 0 }},
+ { 191, 0, 3, 7, { 0 }},
+ { 192, 0, 1, 8, { 0 }},
+ { 193, 0, 1, 8, { 0 }},
+ { 194, 0, 1, 8, { 0 }},
+ { 195, 0, 1, 8, { 0 }},
+ { 196, 0, 1, 8, { 0 }},
+ { 197, 0, 1, 8, { 0 }},
+ { 198, 0, 2, 10, { 0 }},
+ { 199, 0, 2, 8, { 0 }},
+ { 200, 0, 1, 8, { 0 }},
+ { 201, 0, 1, 8, { 0 }},
+ { 202, 0, 1, 8, { 0 }},
+ { 203, 0, 1, 8, { 0 }},
+ { 204, 0, 1, 4, { 0 }},
+ { 205, 0, 1, 4, { 0 }},
+ { 206, 0, 1, 6, { 0 }},
+ { 207, 0, 1, 6, { 0 }},
+ { 208, 0, 2, 9, { 0 }},
+ { 209, 0, 1, 8, { 0 }},
+ { 210, 0, 1, 8, { 0 }},
+ { 211, 0, 1, 8, { 0 }},
+ { 212, 0, 1, 8, { 0 }},
+ { 213, 0, 1, 8, { 0 }},
+ { 214, 0, 1, 8, { 0 }},
+ { 215, 0, 5, 8, { 0 }},
+ { 216, 0, 1, 8, { 0 }},
+ { 217, 0, 1, 8, { 0 }},
+ { 218, 0, 1, 8, { 0 }},
+ { 219, 0, 1, 8, { 0 }},
+ { 220, 0, 1, 8, { 0 }},
+ { 221, 0, 1, 7, { 0 }},
+ { 222, 0, 2, 8, { 0 }},
+ { 223, 0, 2, 8, { 0 }},
+ { 224, 0, 2, 7, { 0 }},
+ { 225, 0, 2, 7, { 0 }},
+ { 226, 0, 2, 7, { 0 }},
+ { 227, 0, 2, 7, { 0 }},
+ { 228, 0, 2, 7, { 0 }},
+ { 229, 0, 1, 7, { 0 }},
+ { 230, 0, 5, 9, { 0 }},
+ { 231, 0, 5, 7, { 0 }},
+ { 232, 0, 2, 7, { 0 }},
+ { 233, 0, 2, 7, { 0 }},
+ { 234, 0, 2, 7, { 0 }},
+ { 235, 0, 2, 7, { 0 }},
+ { 236, 0, 2, 4, { 0 }},
+ { 237, 0, 2, 4, { 0 }},
+ { 238, 0, 2, 6, { 0 }},
+ { 239, 0, 2, 6, { 0 }},
+ { 240, 0, 2, 7, { 0 }},
+ { 241, 0, 2, 7, { 0 }},
+ { 242, 0, 2, 7, { 0 }},
+ { 243, 0, 2, 7, { 0 }},
+ { 244, 0, 2, 7, { 0 }},
+ { 245, 0, 2, 7, { 0 }},
+ { 246, 0, 2, 7, { 0 }},
+ { 247, 0, 4, 7, { 0 }},
+ { 248, 0, 3, 8, { 0 }},
+ { 249, 0, 2, 7, { 0 }},
+ { 250, 0, 2, 7, { 0 }},
+ { 251, 0, 2, 7, { 0 }},
+ { 252, 0, 2, 7, { 0 }},
+ { 253, 0, 2, 7, { 0 }},
+ { 254, 0, 2, 7, { 0 }},
+ { 255, 0, 2, 7, { 0 }},
+};
+
+// Style loading function: Sunny
+static void GuiLoadStyleSunny(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < SUNNY_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(sunnyStyleProps[i].controlId, sunnyStyleProps[i].propertyId, sunnyStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int sunnyFontDataSize = 0;
+ unsigned char *data = DecompressData(sunnyFontData, SUNNY_STYLE_FONT_ATLAS_COMP_SIZE, &sunnyFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 16;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, sunnyFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, sunnyFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_terminal.h b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_terminal.h
new file mode 100644
index 0000000000..4fe22517da
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/examples/styles/style_terminal.h
@@ -0,0 +1,569 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// StyleAsCode exporter v2.0 - Style data exported as a values array //
+// //
+// USAGE: On init call: GuiLoadStyleTerminal(); //
+// //
+// more info and bugs-report: github.com/raysan5/raygui //
+// feedback and support: ray[at]raylibtech.com //
+// //
+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define TERMINAL_STYLE_PROPS_COUNT 17
+
+// Custom style name: Terminal
+static const GuiStyleProp terminalStyleProps[TERMINAL_STYLE_PROPS_COUNT] = {
+ { 0, 0, 0x1c8d00ff }, // DEFAULT_BORDER_COLOR_NORMAL
+ { 0, 1, 0x161313ff }, // DEFAULT_BASE_COLOR_NORMAL
+ { 0, 2, 0x38f620ff }, // DEFAULT_TEXT_COLOR_NORMAL
+ { 0, 3, 0xc3fbc6ff }, // DEFAULT_BORDER_COLOR_FOCUSED
+ { 0, 4, 0x43bf2eff }, // DEFAULT_BASE_COLOR_FOCUSED
+ { 0, 5, 0xdcfadcff }, // DEFAULT_TEXT_COLOR_FOCUSED
+ { 0, 6, 0x1f5b19ff }, // DEFAULT_BORDER_COLOR_PRESSED
+ { 0, 7, 0x43ff28ff }, // DEFAULT_BASE_COLOR_PRESSED
+ { 0, 8, 0x1e6f15ff }, // DEFAULT_TEXT_COLOR_PRESSED
+ { 0, 9, 0x223b22ff }, // DEFAULT_BORDER_COLOR_DISABLED
+ { 0, 10, 0x182c18ff }, // DEFAULT_BASE_COLOR_DISABLED
+ { 0, 11, 0x244125ff }, // DEFAULT_TEXT_COLOR_DISABLED
+ { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE
+ { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
+ { 0, 18, 0xe6fce3ff }, // DEFAULT_LINE_COLOR
+ { 0, 19, 0x0c1505ff }, // DEFAULT_BACKGROUND_COLOR
+ { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
+};
+
+// WARNING: This style uses a custom font: "Mecha.ttf" (size: 16, spacing: 0)
+
+#define TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE 1860
+
+// Font atlas image pixels data: DEFLATE compressed
+static unsigned char terminalFontData[TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
+ 0xdd, 0x41, 0x92, 0xa4, 0x36, 0x10, 0x05, 0x50, 0xee, 0x7f, 0xe9, 0xf4, 0x62, 0x62, 0x16, 0x76, 0xb8, 0x1b, 0x94, 0x4a,
+ 0x89, 0x04, 0x9e, 0x5f, 0x78, 0xd3, 0xd5, 0x53, 0x4d, 0x01, 0xbf, 0x24, 0x84, 0x94, 0xc4, 0x01, 0x00, 0x00, 0x00, 0x7c,
+ 0x5e, 0xfc, 0xef, 0x4f, 0xe2, 0xc7, 0xdf, 0x8c, 0xcb, 0xef, 0xf3, 0xe7, 0xa7, 0xf1, 0xe3, 0x5f, 0xf9, 0xfb, 0xdf, 0x95,
+ 0x77, 0xba, 0xfe, 0x5b, 0x31, 0xb4, 0x75, 0x73, 0x5b, 0x95, 0x7b, 0x9f, 0xd1, 0xdf, 0xfe, 0x7d, 0x7b, 0xaa, 0xde, 0xad,
+ 0xf6, 0x95, 0xb1, 0xb3, 0x23, 0xbf, 0xe7, 0xae, 0x6e, 0x61, 0x6c, 0xdf, 0x2b, 0xc7, 0xa6, 0x7d, 0x1c, 0x0d, 0xf2, 0x7f,
+ 0x7e, 0xcc, 0x46, 0xf2, 0x14, 0xe9, 0xf4, 0x8e, 0x7f, 0x3b, 0xad, 0xfc, 0x0e, 0x1d, 0xdd, 0xc6, 0xdc, 0x3e, 0x89, 0x92,
+ 0xf7, 0x9f, 0xf9, 0x3b, 0x51, 0xb6, 0xd7, 0x72, 0xff, 0x26, 0x86, 0xdb, 0x88, 0xf9, 0x4f, 0x78, 0xbe, 0x8f, 0x63, 0xd1,
+ 0x71, 0xef, 0x99, 0xff, 0xfc, 0x51, 0xcb, 0x9f, 0x29, 0x57, 0xb7, 0x3c, 0xd7, 0xa6, 0xaf, 0x3a, 0x27, 0xe5, 0xff, 0xec,
+ 0x9b, 0xfa, 0xe7, 0x16, 0xb4, 0xa2, 0xdd, 0x90, 0xff, 0x5c, 0x06, 0x62, 0x22, 0x47, 0xbb, 0xf2, 0x5f, 0xdb, 0xd6, 0xc8,
+ 0xff, 0x33, 0xda, 0xff, 0xb3, 0x6d, 0xff, 0xf7, 0x79, 0x2b, 0xff, 0xd9, 0xa3, 0x90, 0x6d, 0xff, 0x63, 0x7a, 0xfb, 0x3b,
+ 0xe7, 0x7f, 0x74, 0xdc, 0x43, 0xfe, 0xcf, 0xaf, 0xe8, 0x73, 0xbf, 0x7d, 0xb6, 0x27, 0xe4, 0x7f, 0x5d, 0xfe, 0x7f, 0xeb,
+ 0xb3, 0x9d, 0xf5, 0xf4, 0x76, 0xe4, 0xff, 0xd8, 0x9e, 0xff, 0xb3, 0xeb, 0xa8, 0xeb, 0xfb, 0x62, 0xc7, 0x08, 0xd4, 0x91,
+ 0x1c, 0xdb, 0x89, 0xc1, 0x0c, 0xdf, 0xd3, 0x0b, 0x3b, 0xcb, 0x7f, 0x66, 0x4f, 0x66, 0xf2, 0x7f, 0x76, 0x5c, 0x8e, 0x5f,
+ 0x7a, 0x30, 0xab, 0xf6, 0x7e, 0x45, 0xfe, 0x67, 0x46, 0xe4, 0x9e, 0x9d, 0xff, 0x38, 0xd9, 0x57, 0x31, 0x31, 0xbe, 0xb9,
+ 0xb3, 0xcf, 0x30, 0xd3, 0x4f, 0xeb, 0x7b, 0x1c, 0xde, 0xd3, 0xff, 0x8f, 0xd6, 0xed, 0xbf, 0xfc, 0xcf, 0x5d, 0xff, 0xbf,
+ 0x2d, 0xff, 0xb1, 0xfd, 0x58, 0xc5, 0x85, 0x33, 0x56, 0xfe, 0xe7, 0xf6, 0xf0, 0x79, 0x8f, 0x23, 0x16, 0x5d, 0xbf, 0x74,
+ 0xcd, 0x7f, 0xee, 0xd3, 0x7d, 0xb1, 0xfd, 0x8f, 0x1b, 0x8f, 0x8f, 0xfc, 0xaf, 0xd8, 0x9b, 0x23, 0x77, 0xd8, 0x66, 0xe7,
+ 0x2f, 0xc8, 0xbf, 0xfc, 0xcb, 0x7f, 0xef, 0xfe, 0x7f, 0x0c, 0x8e, 0xdc, 0xc6, 0xe3, 0xc7, 0xff, 0xe2, 0x52, 0x6f, 0x69,
+ 0x7e, 0xb6, 0xe0, 0x78, 0x9f, 0x2b, 0xf7, 0x6e, 0xf9, 0xd9, 0x75, 0x4f, 0xb9, 0xfe, 0xdf, 0x39, 0x93, 0xf2, 0x28, 0x99,
+ 0x87, 0xb2, 0x7e, 0xfe, 0xdf, 0x33, 0xe7, 0x28, 0x77, 0xcf, 0x3f, 0xb0, 0x7a, 0x95, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x65, 0x0d, 0x4d, 0x94, 0xad, 0x7b, 0x8c, 0x16, 0x95, 0xe7, 0xf7, 0xd4, 0x58,
+ 0xbf, 0xb6, 0x87, 0xaa, 0xde, 0x71, 0xec, 0x59, 0x02, 0x63, 0xeb, 0x30, 0x73, 0x2b, 0xff, 0x56, 0xaf, 0x6e, 0x9b, 0x59,
+ 0xdd, 0x58, 0xb3, 0x65, 0x15, 0xb5, 0x2d, 0xee, 0x49, 0xc7, 0xca, 0x75, 0xe2, 0x71, 0x69, 0x75, 0x70, 0x6d, 0x92, 0x56,
+ 0xaf, 0xd8, 0xce, 0xac, 0x7d, 0xdf, 0x99, 0xff, 0xb1, 0x33, 0x70, 0xfc, 0x73, 0x46, 0x62, 0x35, 0x55, 0x6d, 0x0d, 0x98,
+ 0x63, 0xe9, 0xb9, 0x19, 0x8b, 0xd6, 0x90, 0x8d, 0xef, 0x83, 0x3d, 0xe9, 0x90, 0xff, 0x2f, 0xe7, 0x3f, 0x57, 0x23, 0x7b,
+ 0xc7, 0xb3, 0x50, 0xe4, 0x5f, 0xfe, 0xe5, 0xff, 0xad, 0xf9, 0x8f, 0xe2, 0xfe, 0x77, 0xbe, 0x5a, 0x47, 0xcd, 0x95, 0x55,
+ 0x6d, 0x4a, 0xe4, 0x5f, 0xfe, 0x7f, 0xef, 0x6d, 0xc7, 0xc5, 0x56, 0x6c, 0xa4, 0xc5, 0xdb, 0x59, 0xb3, 0x64, 0x5f, 0x15,
+ 0xad, 0xd1, 0x6f, 0x93, 0x28, 0x4c, 0xf0, 0x57, 0xf2, 0x9f, 0xaf, 0x7b, 0xbe, 0x67, 0xdc, 0x2b, 0xb3, 0xe5, 0x99, 0xda,
+ 0x57, 0xf5, 0xf9, 0x3f, 0x7b, 0x1e, 0x42, 0xe6, 0xfb, 0xe9, 0x5b, 0xf9, 0x1f, 0xfd, 0x6c, 0xf2, 0x7f, 0x6c, 0x7e, 0xb6,
+ 0xcc, 0xfd, 0x35, 0x16, 0x23, 0xd9, 0xd2, 0x57, 0x6d, 0x75, 0xa4, 0x46, 0xdb, 0xaa, 0x7e, 0x9e, 0xab, 0xd2, 0xf8, 0xde,
+ 0xfc, 0x47, 0xc1, 0x7d, 0xae, 0xb9, 0x56, 0x52, 0xfe, 0xe5, 0xff, 0x98, 0xac, 0xc0, 0xdb, 0x3d, 0xff, 0x2b, 0xae, 0xbf,
+ 0x2b, 0x9f, 0xe6, 0xfa, 0xcc, 0xf6, 0xff, 0x59, 0xf7, 0xff, 0xbe, 0x92, 0xff, 0xb3, 0x63, 0x79, 0x77, 0xfe, 0x3b, 0xd5,
+ 0x4c, 0xcd, 0x8c, 0x30, 0xce, 0xfc, 0x9b, 0x8e, 0xf9, 0xdf, 0x35, 0x9f, 0x47, 0xfe, 0x77, 0xe5, 0xff, 0xe7, 0xa7, 0x8d,
+ 0xcb, 0x7f, 0xaf, 0xfc, 0xaf, 0xeb, 0xff, 0x3f, 0x3b, 0xff, 0xeb, 0x7a, 0x5f, 0xab, 0xfb, 0x73, 0xb5, 0x5b, 0x9e, 0x99,
+ 0x01, 0xf7, 0xdb, 0xfc, 0xbb, 0x48, 0x57, 0x6d, 0xaf, 0x98, 0x87, 0x37, 0x33, 0x3b, 0x68, 0xf7, 0x95, 0x41, 0xf5, 0xbf,
+ 0xa9, 0x1f, 0xb3, 0xe8, 0x9b, 0x7f, 0x78, 0x46, 0xfe, 0xbf, 0xb0, 0xaf, 0x71, 0x3c, 0xee, 0x69, 0x59, 0x57, 0xfe, 0x3e,
+ 0xce, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xd3, 0x2a, 0xac, 0xaa, 0xba, 0x8d, 0x3b,
+ 0xab, 0x65, 0xe4, 0xd6, 0xf9, 0xc5, 0xe5, 0xba, 0x2e, 0x99, 0x55, 0xe4, 0x23, 0x6b, 0xf9, 0x6a, 0xd6, 0x34, 0xe6, 0xcf,
+ 0x81, 0x48, 0xad, 0x96, 0x3b, 0x3f, 0x53, 0x32, 0x35, 0xec, 0xd7, 0xcd, 0xb6, 0xff, 0xbd, 0x7e, 0x43, 0xbe, 0x92, 0xc8,
+ 0xaa, 0xf5, 0x05, 0x75, 0xf5, 0x9f, 0x8e, 0x82, 0xd5, 0x8a, 0xd9, 0x35, 0xf4, 0xf7, 0xe6, 0x7f, 0x74, 0xf5, 0xdb, 0xf5,
+ 0x9f, 0x55, 0xd4, 0x5b, 0x89, 0xc4, 0xca, 0xbc, 0xca, 0xfc, 0x57, 0x9c, 0xe3, 0x51, 0xf6, 0xbe, 0xb1, 0xb8, 0x4e, 0xc1,
+ 0x95, 0x56, 0xe2, 0xd9, 0x6b, 0xa2, 0xe2, 0xd5, 0xf9, 0xaf, 0xad, 0x96, 0x5b, 0xff, 0x9d, 0x90, 0xaf, 0x4f, 0x70, 0x5f,
+ 0xfe, 0xff, 0x6e, 0x57, 0x75, 0xfe, 0x33, 0xef, 0x5b, 0x53, 0xd9, 0x6a, 0x2e, 0xff, 0x3d, 0x56, 0xf6, 0xc5, 0xf2, 0x9e,
+ 0x47, 0x26, 0xff, 0x63, 0xfd, 0xb6, 0x15, 0xf9, 0xcf, 0x57, 0xe6, 0x39, 0x36, 0x65, 0xfd, 0x28, 0x4e, 0xf9, 0xfa, 0xfc,
+ 0xd7, 0x9f, 0x69, 0xf1, 0x9f, 0xff, 0xbb, 0xac, 0xb6, 0x7d, 0x4b, 0xfe, 0x73, 0xd5, 0x69, 0x66, 0xf3, 0x9f, 0xbd, 0xe2,
+ 0xbd, 0xbb, 0xfd, 0x5f, 0x73, 0x4d, 0xb0, 0x3e, 0xff, 0x91, 0xaa, 0x0c, 0xde, 0x27, 0xff, 0xb1, 0x20, 0xb9, 0xf2, 0x9f,
+ 0x6d, 0x03, 0xdf, 0x90, 0xff, 0xea, 0xe7, 0x7c, 0x74, 0xc8, 0x7f, 0x6e, 0xc4, 0x2b, 0x4a, 0x73, 0x1a, 0xed, 0xdb, 0xff,
+ 0x63, 0xdb, 0xf8, 0x5f, 0xff, 0xfc, 0x47, 0x49, 0xbf, 0xf0, 0xce, 0xfc, 0xd7, 0x57, 0xcb, 0xcd, 0x56, 0x0d, 0xbc, 0x3e,
+ 0xd6, 0xd7, 0xa7, 0xfd, 0xaf, 0xbf, 0x1e, 0x5e, 0xd1, 0xfe, 0x1f, 0x0b, 0xee, 0x52, 0xac, 0xbf, 0xaa, 0xee, 0x9f, 0xff,
+ 0xaa, 0xeb, 0xc2, 0xcc, 0x73, 0x93, 0x46, 0xef, 0xff, 0xc5, 0xe9, 0x59, 0x3c, 0x7a, 0xe7, 0x68, 0x3c, 0x4f, 0x31, 0xf8,
+ 0xf4, 0xa2, 0xfe, 0xd7, 0xff, 0x95, 0xed, 0xff, 0x9a, 0x51, 0xef, 0xae, 0xa3, 0xe9, 0xd7, 0x9e, 0x2f, 0xde, 0x63, 0x8b,
+ 0xf3, 0x4f, 0xdc, 0x8a, 0xed, 0x57, 0x56, 0x7d, 0x8e, 0xf1, 0xfc, 0x67, 0x5f, 0x93, 0xff, 0x8a, 0x8a, 0xd3, 0xf5, 0xed,
+ 0xe1, 0xf7, 0xe6, 0xbc, 0xcc, 0xdc, 0x75, 0xef, 0xb1, 0xb5, 0xd5, 0xe7, 0xc5, 0x3b, 0xf2, 0x5f, 0xf7, 0xd9, 0x63, 0xc9,
+ 0xb7, 0x4a, 0xa6, 0x96, 0x77, 0x2c, 0x9f, 0x0f, 0x23, 0xff, 0xcf, 0xcd, 0x7f, 0xdc, 0x70, 0xcf, 0xf0, 0x58, 0x3c, 0x1e,
+ 0xdd, 0x61, 0x0f, 0xef, 0xcd, 0x3f, 0xfd, 0xce, 0x88, 0xee, 0xf9, 0x5f, 0x3f, 0x2f, 0xf4, 0xcb, 0xed, 0x81, 0x2a, 0xf9,
+ 0x3c, 0xf1, 0x5a, 0x56, 0xfe, 0x73, 0xfd, 0x96, 0xd9, 0xf9, 0xff, 0x20, 0xff, 0xdf, 0xdd, 0xeb, 0xd0, 0x7f, 0x76, 0x03,
+ 0xf2, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfb, 0x67, 0xbb, 0x45, 0x6a, 0x7d, 0x5b, 0x0c, 0x56,
+ 0x32, 0x88, 0x74, 0xa5, 0xf8, 0x6c, 0x7d, 0x8c, 0x18, 0x5c, 0xf7, 0x35, 0x5f, 0x37, 0xf8, 0xfa, 0xf3, 0x15, 0x66, 0xd6,
+ 0x0f, 0xae, 0x3f, 0x8e, 0x75, 0x15, 0xd6, 0xeb, 0x8f, 0x52, 0xe6, 0xef, 0x47, 0x79, 0xed, 0xb5, 0xfe, 0x99, 0x99, 0xdf,
+ 0xcf, 0x99, 0x95, 0xbe, 0xb5, 0x67, 0xd4, 0xb5, 0x63, 0x5b, 0xb7, 0xba, 0x33, 0x26, 0x92, 0x3e, 0x3e, 0x4f, 0xfb, 0xf7,
+ 0xaa, 0x9f, 0x5d, 0x8f, 0x63, 0x2e, 0x4b, 0x51, 0xba, 0x06, 0x37, 0xf7, 0xd7, 0x9f, 0xb6, 0xaf, 0xaf, 0x57, 0x01, 0xd8,
+ 0xdd, 0x5f, 0xc8, 0x3f, 0x35, 0x28, 0x6e, 0x9f, 0x8b, 0xbf, 0xae, 0xa2, 0x4e, 0x5d, 0xad, 0xe2, 0xbb, 0x8f, 0xe3, 0x71,
+ 0xfa, 0x0c, 0x93, 0x68, 0xb8, 0xbe, 0xe5, 0xac, 0xff, 0x18, 0x2d, 0xf7, 0x75, 0x5c, 0xee, 0x23, 0xe6, 0xf3, 0x9f, 0x7f,
+ 0x3e, 0x53, 0x14, 0x57, 0xe6, 0xcd, 0x57, 0xc7, 0xac, 0xde, 0xfa, 0x7c, 0xfb, 0x9f, 0xb9, 0x52, 0x88, 0xe5, 0x9f, 0xaa,
+ 0xf6, 0x3b, 0x39, 0x4e, 0x6a, 0xb9, 0xae, 0x3e, 0x2b, 0x56, 0xbc, 0x12, 0x1b, 0xce, 0xad, 0xdc, 0xf5, 0xde, 0xb5, 0x33,
+ 0x64, 0x26, 0xff, 0x7d, 0x8f, 0xcd, 0xd1, 0xe6, 0x95, 0xdd, 0xf9, 0x7f, 0xee, 0x2b, 0xef, 0xc9, 0x7f, 0x9f, 0xb3, 0xef,
+ 0xb7, 0xcf, 0x33, 0xfb, 0xac, 0xc2, 0x0e, 0x47, 0xe0, 0xac, 0x4e, 0xec, 0x5b, 0xf3, 0x1f, 0x3f, 0x8e, 0x0c, 0xf6, 0xff,
+ 0x4e, 0xfe, 0xb9, 0x5f, 0xf0, 0xb4, 0xfc, 0x57, 0xb6, 0xcb, 0x15, 0x6d, 0xf9, 0xde, 0x6b, 0x66, 0xed, 0xbf, 0xf6, 0xff,
+ 0xdb, 0xf9, 0xbf, 0xff, 0x2a, 0x6c, 0x6f, 0x66, 0xfa, 0xed, 0xb3, 0x3e, 0xf9, 0x1f, 0x19, 0xf3, 0x92, 0xff, 0xb7, 0xe7,
+ 0xff, 0x09, 0xdf, 0x4d, 0xb3, 0xf7, 0xff, 0xde, 0x31, 0xfe, 0x57, 0xf5, 0x8a, 0xf6, 0x7f, 0x6e, 0x8c, 0xfd, 0xee, 0x6d,
+ 0xcb, 0x1f, 0xf3, 0xb7, 0x1c, 0x85, 0xd1, 0x3e, 0x80, 0xfe, 0xbf, 0xfc, 0xbf, 0x27, 0xff, 0x47, 0x7a, 0xf6, 0xc1, 0xb3,
+ 0xae, 0x33, 0x46, 0x8e, 0xc7, 0x73, 0xf2, 0x5f, 0x79, 0xc7, 0xee, 0x29, 0xe3, 0x7f, 0x4f, 0xfb, 0x66, 0x78, 0x63, 0xfe,
+ 0xef, 0xbd, 0xd7, 0xda, 0x63, 0xe6, 0xef, 0x33, 0xfb, 0x32, 0x4f, 0xce, 0xff, 0xb3, 0xfb, 0x64, 0xc7, 0x6d, 0x57, 0x85,
+ 0x51, 0xb8, 0xa7, 0x79, 0x46, 0xfe, 0x63, 0x53, 0xfe, 0x47, 0xc6, 0x06, 0xde, 0x9d, 0xff, 0xf1, 0xd6, 0x2a, 0x6e, 0x1f,
+ 0x63, 0x96, 0xff, 0xbb, 0xf3, 0xbf, 0x7f, 0xeb, 0x77, 0xf5, 0xc4, 0x62, 0x49, 0xd2, 0xc7, 0x8f, 0xc9, 0x13, 0xfb, 0xa4,
+ 0x3b, 0xb7, 0x4d, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xcc, 0x00, 0x1e, 0x7b, 0xb5,
+ 0x43, 0x05, 0xfd, 0x23, 0x5d, 0x6d, 0xbd, 0xee, 0xf3, 0x1e, 0x89, 0xaa, 0xee, 0x99, 0x6d, 0xe8, 0x5c, 0x41, 0xdf, 0xac,
+ 0xdb, 0xb7, 0x7e, 0x03, 0xf4, 0xae, 0xa0, 0x7f, 0x5e, 0xe5, 0x63, 0xfd, 0xe7, 0xad, 0x9c, 0x3f, 0xdf, 0xbb, 0x82, 0x7e,
+ 0xbf, 0xb5, 0xab, 0xf4, 0xfb, 0x26, 0xd9, 0x59, 0x41, 0x7f, 0xbc, 0xbf, 0x71, 0x6c, 0xdc, 0xae, 0x6c, 0x35, 0x83, 0xae,
+ 0x15, 0xf4, 0xbb, 0xaf, 0x05, 0xe3, 0xfe, 0xb5, 0x59, 0x63, 0xcf, 0xb4, 0xa8, 0xaa, 0xa0, 0xf1, 0xb4, 0x0a, 0xfa, 0x67,
+ 0x19, 0x7b, 0x52, 0x9d, 0x6c, 0xf9, 0xb7, 0xfe, 0xf7, 0xbe, 0xfc, 0xf7, 0xad, 0x93, 0x91, 0xad, 0x52, 0xd3, 0xbb, 0x82,
+ 0xa6, 0xfc, 0xcb, 0xbf, 0xfc, 0xaf, 0xaa, 0x91, 0x20, 0xff, 0x3c, 0x3d, 0xff, 0x3b, 0x2b, 0xe8, 0xa8, 0xa0, 0xb9, 0xbb,
+ 0x22, 0xd0, 0x21, 0xff, 0xae, 0xff, 0x1f, 0xf1, 0x04, 0x3d, 0xf9, 0x5f, 0xf3, 0x8a, 0xfc, 0x7f, 0xfd, 0xde, 0x9f, 0x0a,
+ 0xda, 0x2b, 0xf3, 0x1f, 0x4d, 0xc7, 0xff, 0xf6, 0xdf, 0xf1, 0xe1, 0x89, 0xf9, 0xd7, 0xff, 0xcf, 0xe7, 0xe2, 0xfe, 0x0a,
+ 0x9a, 0xf9, 0x34, 0xcb, 0xbf, 0xfe, 0x7f, 0xc5, 0xfc, 0x9f, 0x9a, 0xb6, 0x47, 0x05, 0xcd, 0xb9, 0x6d, 0x93, 0x7f, 0xd0,
+ 0x2b, 0xd4, 0xff, 0x07, 0xbd, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf9, 0xf3, 0x9f, 0xfd, 0x00, 0xf2, 0x0f, 0x7c, 0x2e, 0xff, 0xff, 0x00 };
+
+// Font glyphs rectangles data (on atlas)
+static const Rectangle terminalFontRecs[189] = {
+ { 4, 4, 4 , 16 },
+ { 16, 4, 1 , 11 },
+ { 25, 4, 3 , 3 },
+ { 36, 4, 6 , 11 },
+ { 50, 4, 5 , 11 },
+ { 63, 4, 5 , 11 },
+ { 76, 4, 5 , 11 },
+ { 89, 4, 1 , 2 },
+ { 98, 4, 2 , 13 },
+ { 108, 4, 2 , 13 },
+ { 118, 4, 3 , 3 },
+ { 129, 4, 5 , 5 },
+ { 142, 4, 1 , 3 },
+ { 151, 4, 5 , 1 },
+ { 164, 4, 1 , 1 },
+ { 173, 4, 6 , 12 },
+ { 187, 4, 5 , 11 },
+ { 200, 4, 2 , 11 },
+ { 210, 4, 5 , 11 },
+ { 223, 4, 5 , 11 },
+ { 236, 4, 5 , 11 },
+ { 249, 4, 5 , 11 },
+ { 262, 4, 5 , 11 },
+ { 275, 4, 5 , 11 },
+ { 288, 4, 5 , 11 },
+ { 301, 4, 5 , 11 },
+ { 314, 4, 1 , 8 },
+ { 323, 4, 1 , 10 },
+ { 332, 4, 4 , 5 },
+ { 344, 4, 5 , 3 },
+ { 357, 4, 4 , 5 },
+ { 369, 4, 5 , 11 },
+ { 382, 4, 11 , 11 },
+ { 401, 4, 5 , 11 },
+ { 414, 4, 5 , 11 },
+ { 427, 4, 5 , 11 },
+ { 440, 4, 5 , 11 },
+ { 453, 4, 5 , 11 },
+ { 466, 4, 5 , 11 },
+ { 479, 4, 5 , 11 },
+ { 492, 4, 5 , 11 },
+ { 4, 28, 1 , 11 },
+ { 13, 28, 5 , 11 },
+ { 26, 28, 5 , 11 },
+ { 39, 28, 5 , 11 },
+ { 52, 28, 7 , 11 },
+ { 67, 28, 5 , 11 },
+ { 80, 28, 5 , 11 },
+ { 93, 28, 5 , 11 },
+ { 106, 28, 5 , 13 },
+ { 119, 28, 5 , 11 },
+ { 132, 28, 5 , 11 },
+ { 145, 28, 5 , 11 },
+ { 158, 28, 5 , 11 },
+ { 171, 28, 5 , 11 },
+ { 184, 28, 7 , 11 },
+ { 199, 28, 5 , 11 },
+ { 212, 28, 5 , 11 },
+ { 225, 28, 5 , 11 },
+ { 238, 28, 2 , 13 },
+ { 248, 28, 6 , 12 },
+ { 262, 28, 2 , 13 },
+ { 272, 28, 5 , 4 },
+ { 285, 28, 5 , 1 },
+ { 298, 28, 2 , 2 },
+ { 308, 28, 5 , 8 },
+ { 321, 28, 5 , 11 },
+ { 334, 28, 5 , 8 },
+ { 347, 28, 5 , 11 },
+ { 360, 28, 5 , 8 },
+ { 373, 28, 4 , 11 },
+ { 385, 28, 5 , 10 },
+ { 398, 28, 5 , 11 },
+ { 411, 28, 1 , 11 },
+ { 420, 28, 1 , 13 },
+ { 429, 28, 5 , 11 },
+ { 442, 28, 1 , 11 },
+ { 451, 28, 7 , 8 },
+ { 466, 28, 5 , 8 },
+ { 479, 28, 5 , 8 },
+ { 492, 28, 5 , 10 },
+ { 4, 52, 5 , 10 },
+ { 17, 52, 4 , 8 },
+ { 29, 52, 5 , 8 },
+ { 42, 52, 3 , 11 },
+ { 53, 52, 5 , 8 },
+ { 66, 52, 5 , 8 },
+ { 79, 52, 7 , 8 },
+ { 94, 52, 5 , 8 },
+ { 107, 52, 5 , 10 },
+ { 120, 52, 5 , 8 },
+ { 133, 52, 3 , 13 },
+ { 144, 52, 1 , 15 },
+ { 153, 52, 3 , 13 },
+ { 164, 52, 5 , 3 },
+ { 177, 52, 1 , 11 },
+ { 186, 52, 5 , 11 },
+ { 199, 52, 5 , 10 },
+ { 212, 52, 5 , 10 },
+ { 225, 52, 5 , 10 },
+ { 238, 52, 0 , 0 },
+ { 246, 52, 0 , 0 },
+ { 254, 52, 0 , 0 },
+ { 262, 52, 7 , 8 },
+ { 277, 52, 0 , 0 },
+ { 285, 52, 0 , 0 },
+ { 293, 52, 5 , 3 },
+ { 306, 52, 7 , 8 },
+ { 321, 52, 5 , 1 },
+ { 334, 52, 3 , 3 },
+ { 345, 52, 5 , 7 },
+ { 358, 52, 0 , 0 },
+ { 366, 52, 0 , 0 },
+ { 374, 52, 0 , 0 },
+ { 382, 52, 5 , 10 },
+ { 395, 52, 7 , 11 },
+ { 410, 52, 1 , 1 },
+ { 419, 52, 0 , 0 },
+ { 427, 52, 0 , 0 },
+ { 435, 52, 0 , 0 },
+ { 443, 52, 0 , 0 },
+ { 451, 52, 0 , 0 },
+ { 459, 52, 0 , 0 },
+ { 467, 52, 5 , 13 },
+ { 480, 52, 5 , 11 },
+ { 493, 52, 5 , 14 },
+ { 4, 76, 5 , 14 },
+ { 17, 76, 5 , 14 },
+ { 30, 76, 5 , 14 },
+ { 43, 76, 5 , 13 },
+ { 56, 76, 5 , 13 },
+ { 69, 76, 9 , 11 },
+ { 86, 76, 5 , 13 },
+ { 99, 76, 5 , 14 },
+ { 112, 76, 5 , 14 },
+ { 125, 76, 5 , 14 },
+ { 138, 76, 5 , 13 },
+ { 151, 76, 2 , 14 },
+ { 161, 76, 2 , 14 },
+ { 171, 76, 3 , 14 },
+ { 182, 76, 3 , 13 },
+ { 193, 76, 5 , 11 },
+ { 206, 76, 5 , 14 },
+ { 219, 76, 5 , 14 },
+ { 232, 76, 5 , 14 },
+ { 245, 76, 5 , 14 },
+ { 258, 76, 5 , 14 },
+ { 271, 76, 5 , 13 },
+ { 284, 76, 5 , 5 },
+ { 297, 76, 5 , 13 },
+ { 310, 76, 5 , 14 },
+ { 323, 76, 5 , 14 },
+ { 336, 76, 5 , 14 },
+ { 349, 76, 5 , 13 },
+ { 362, 76, 5 , 14 },
+ { 375, 76, 5 , 11 },
+ { 388, 76, 5 , 11 },
+ { 401, 76, 5 , 11 },
+ { 414, 76, 5 , 11 },
+ { 427, 76, 5 , 11 },
+ { 440, 76, 5 , 11 },
+ { 453, 76, 5 , 10 },
+ { 466, 76, 5 , 10 },
+ { 479, 76, 9 , 8 },
+ { 496, 76, 5 , 10 },
+ { 4, 100, 5 , 11 },
+ { 17, 100, 5 , 11 },
+ { 30, 100, 5 , 11 },
+ { 43, 100, 5 , 10 },
+ { 56, 100, 2 , 11 },
+ { 66, 100, 2 , 11 },
+ { 76, 100, 3 , 11 },
+ { 87, 100, 3 , 10 },
+ { 98, 100, 5 , 11 },
+ { 111, 100, 5 , 11 },
+ { 124, 100, 5 , 11 },
+ { 137, 100, 5 , 11 },
+ { 150, 100, 5 , 11 },
+ { 163, 100, 5 , 11 },
+ { 176, 100, 5 , 10 },
+ { 189, 100, 5 , 5 },
+ { 202, 100, 5 , 10 },
+ { 215, 100, 5 , 11 },
+ { 228, 100, 5 , 11 },
+ { 241, 100, 5 , 11 },
+ { 254, 100, 5 , 10 },
+ { 267, 100, 5 , 13 },
+ { 280, 100, 4 , 8 },
+ { 292, 100, 5 , 12 },
+};
+
+// Font glyphs info data
+// NOTE: No glyphs.image data provided
+static const GlyphInfo terminalFontGlyphs[189] = {
+ { 32, 0, 14, 4, { 0 }},
+ { 33, 1, 3, 3, { 0 }},
+ { 34, 1, 3, 5, { 0 }},
+ { 35, 1, 3, 8, { 0 }},
+ { 36, 1, 3, 7, { 0 }},
+ { 37, 1, 3, 7, { 0 }},
+ { 38, 1, 3, 7, { 0 }},
+ { 39, 1, 3, 3, { 0 }},
+ { 40, 1, 2, 4, { 0 }},
+ { 41, 1, 2, 4, { 0 }},
+ { 42, 1, 3, 5, { 0 }},
+ { 43, 1, 7, 7, { 0 }},
+ { 44, 1, 13, 3, { 0 }},
+ { 45, 1, 9, 7, { 0 }},
+ { 46, 1, 13, 3, { 0 }},
+ { 47, 1, 2, 8, { 0 }},
+ { 48, 1, 3, 7, { 0 }},
+ { 49, 1, 3, 4, { 0 }},
+ { 50, 1, 3, 7, { 0 }},
+ { 51, 1, 3, 7, { 0 }},
+ { 52, 1, 3, 7, { 0 }},
+ { 53, 1, 3, 7, { 0 }},
+ { 54, 1, 3, 7, { 0 }},
+ { 55, 1, 3, 7, { 0 }},
+ { 56, 1, 3, 7, { 0 }},
+ { 57, 1, 3, 7, { 0 }},
+ { 58, 1, 6, 3, { 0 }},
+ { 59, 1, 6, 3, { 0 }},
+ { 60, 1, 7, 6, { 0 }},
+ { 61, 1, 8, 7, { 0 }},
+ { 62, 1, 7, 6, { 0 }},
+ { 63, 1, 3, 7, { 0 }},
+ { 64, 2, 3, 15, { 0 }},
+ { 65, 1, 3, 7, { 0 }},
+ { 66, 1, 3, 7, { 0 }},
+ { 67, 1, 3, 7, { 0 }},
+ { 68, 1, 3, 7, { 0 }},
+ { 69, 1, 3, 7, { 0 }},
+ { 70, 1, 3, 7, { 0 }},
+ { 71, 1, 3, 7, { 0 }},
+ { 72, 1, 3, 7, { 0 }},
+ { 73, 1, 3, 3, { 0 }},
+ { 74, 1, 3, 7, { 0 }},
+ { 75, 1, 3, 7, { 0 }},
+ { 76, 1, 3, 7, { 0 }},
+ { 77, 1, 3, 9, { 0 }},
+ { 78, 1, 3, 7, { 0 }},
+ { 79, 1, 3, 7, { 0 }},
+ { 80, 1, 3, 7, { 0 }},
+ { 81, 1, 3, 7, { 0 }},
+ { 82, 1, 3, 7, { 0 }},
+ { 83, 1, 3, 7, { 0 }},
+ { 84, 1, 3, 7, { 0 }},
+ { 85, 1, 3, 7, { 0 }},
+ { 86, 1, 3, 7, { 0 }},
+ { 87, 1, 3, 9, { 0 }},
+ { 88, 1, 3, 7, { 0 }},
+ { 89, 1, 3, 7, { 0 }},
+ { 90, 1, 3, 7, { 0 }},
+ { 91, 1, 2, 4, { 0 }},
+ { 92, 1, 2, 8, { 0 }},
+ { 93, 1, 2, 4, { 0 }},
+ { 94, 1, 3, 7, { 0 }},
+ { 95, 1, 15, 7, { 0 }},
+ { 96, 1, 0, 4, { 0 }},
+ { 97, 1, 6, 7, { 0 }},
+ { 98, 1, 3, 7, { 0 }},
+ { 99, 1, 6, 7, { 0 }},
+ { 100, 1, 3, 7, { 0 }},
+ { 101, 1, 6, 7, { 0 }},
+ { 102, 1, 3, 6, { 0 }},
+ { 103, 1, 6, 7, { 0 }},
+ { 104, 1, 3, 7, { 0 }},
+ { 105, 1, 3, 3, { 0 }},
+ { 106, 1, 3, 3, { 0 }},
+ { 107, 1, 3, 7, { 0 }},
+ { 108, 1, 3, 3, { 0 }},
+ { 109, 1, 6, 9, { 0 }},
+ { 110, 1, 6, 7, { 0 }},
+ { 111, 1, 6, 7, { 0 }},
+ { 112, 1, 6, 7, { 0 }},
+ { 113, 1, 6, 7, { 0 }},
+ { 114, 1, 6, 6, { 0 }},
+ { 115, 1, 6, 7, { 0 }},
+ { 116, 1, 3, 5, { 0 }},
+ { 117, 1, 6, 7, { 0 }},
+ { 118, 1, 6, 7, { 0 }},
+ { 119, 1, 6, 9, { 0 }},
+ { 120, 1, 6, 7, { 0 }},
+ { 121, 1, 6, 7, { 0 }},
+ { 122, 1, 6, 7, { 0 }},
+ { 123, 1, 2, 5, { 0 }},
+ { 124, 1, 1, 3, { 0 }},
+ { 125, 1, 2, 5, { 0 }},
+ { 126, 1, 8, 7, { 0 }},
+ { 161, 1, 3, 3, { 0 }},
+ { 162, 1, 3, 7, { 0 }},
+ { 163, 1, 3, 7, { 0 }},
+ { 8364, 1, 3, 7, { 0 }},
+ { 165, 1, 3, 7, { 0 }},
+ { 352, 0, 14, 4, { 0 }},
+ { 167, 0, 14, 4, { 0 }},
+ { 353, 0, 14, 4, { 0 }},
+ { 169, 1, 3, 9, { 0 }},
+ { 170, 0, 14, 4, { 0 }},
+ { 171, 0, 14, 4, { 0 }},
+ { 172, 1, 8, 7, { 0 }},
+ { 174, 1, 3, 9, { 0 }},
+ { 175, 1, 1, 7, { 0 }},
+ { 176, 1, 0, 5, { 0 }},
+ { 177, 1, 7, 7, { 0 }},
+ { 178, 0, 14, 4, { 0 }},
+ { 179, 0, 14, 4, { 0 }},
+ { 381, 0, 14, 4, { 0 }},
+ { 181, 1, 6, 7, { 0 }},
+ { 182, 1, 3, 9, { 0 }},
+ { 183, 1, 8, 3, { 0 }},
+ { 382, 0, 14, 4, { 0 }},
+ { 185, 0, 14, 4, { 0 }},
+ { 186, 0, 14, 4, { 0 }},
+ { 187, 0, 14, 4, { 0 }},
+ { 338, 0, 14, 4, { 0 }},
+ { 339, 0, 14, 4, { 0 }},
+ { 376, 1, 1, 7, { 0 }},
+ { 191, 1, 3, 7, { 0 }},
+ { 192, 1, 0, 7, { 0 }},
+ { 193, 1, 0, 7, { 0 }},
+ { 194, 1, 0, 7, { 0 }},
+ { 195, 1, 0, 7, { 0 }},
+ { 196, 1, 1, 7, { 0 }},
+ { 197, 1, 1, 7, { 0 }},
+ { 198, 1, 3, 11, { 0 }},
+ { 199, 1, 3, 7, { 0 }},
+ { 200, 1, 0, 7, { 0 }},
+ { 201, 1, 0, 7, { 0 }},
+ { 202, 1, 0, 7, { 0 }},
+ { 203, 1, 1, 7, { 0 }},
+ { 204, 0, 0, 3, { 0 }},
+ { 205, 1, 0, 3, { 0 }},
+ { 206, 0, 0, 3, { 0 }},
+ { 207, 0, 1, 3, { 0 }},
+ { 208, 1, 3, 7, { 0 }},
+ { 209, 1, 0, 7, { 0 }},
+ { 210, 1, 0, 7, { 0 }},
+ { 211, 1, 0, 7, { 0 }},
+ { 212, 1, 0, 7, { 0 }},
+ { 213, 1, 0, 7, { 0 }},
+ { 214, 1, 1, 7, { 0 }},
+ { 215, 1, 7, 7, { 0 }},
+ { 216, 1, 2, 7, { 0 }},
+ { 217, 1, 0, 7, { 0 }},
+ { 218, 1, 0, 7, { 0 }},
+ { 219, 1, 0, 7, { 0 }},
+ { 220, 1, 1, 7, { 0 }},
+ { 221, 1, 0, 7, { 0 }},
+ { 222, 1, 3, 7, { 0 }},
+ { 223, 1, 3, 7, { 0 }},
+ { 224, 1, 3, 7, { 0 }},
+ { 225, 1, 3, 7, { 0 }},
+ { 226, 1, 3, 7, { 0 }},
+ { 227, 1, 3, 7, { 0 }},
+ { 228, 1, 4, 7, { 0 }},
+ { 229, 1, 4, 7, { 0 }},
+ { 230, 1, 6, 11, { 0 }},
+ { 231, 1, 6, 7, { 0 }},
+ { 232, 1, 3, 7, { 0 }},
+ { 233, 1, 3, 7, { 0 }},
+ { 234, 1, 3, 7, { 0 }},
+ { 235, 1, 4, 7, { 0 }},
+ { 236, 0, 3, 3, { 0 }},
+ { 237, 1, 3, 3, { 0 }},
+ { 238, 0, 3, 3, { 0 }},
+ { 239, 0, 4, 3, { 0 }},
+ { 240, 1, 3, 7, { 0 }},
+ { 241, 1, 3, 7, { 0 }},
+ { 242, 1, 3, 7, { 0 }},
+ { 243, 1, 3, 7, { 0 }},
+ { 244, 1, 3, 7, { 0 }},
+ { 245, 1, 3, 7, { 0 }},
+ { 246, 1, 4, 7, { 0 }},
+ { 247, 1, 7, 7, { 0 }},
+ { 248, 1, 5, 7, { 0 }},
+ { 249, 1, 3, 7, { 0 }},
+ { 250, 1, 3, 7, { 0 }},
+ { 251, 1, 3, 7, { 0 }},
+ { 252, 1, 4, 7, { 0 }},
+ { 253, 1, 3, 7, { 0 }},
+ { 254, 1, 6, 6, { 0 }},
+ { 255, 1, 4, 7, { 0 }},
+};
+
+// Style loading function: Terminal
+static void GuiLoadStyleTerminal(void)
+{
+ // Load style properties provided
+ // NOTE: Default properties are propagated
+ for (int i = 0; i < TERMINAL_STYLE_PROPS_COUNT; i++)
+ {
+ GuiSetStyle(terminalStyleProps[i].controlId, terminalStyleProps[i].propertyId, terminalStyleProps[i].propertyValue);
+ }
+
+ // Custom font loading
+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
+ int terminalFontDataSize = 0;
+ unsigned char *data = DecompressData(terminalFontData, TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE, &terminalFontDataSize);
+ Image imFont = { data, 512, 256, 1, 2 };
+
+ Font font = { 0 };
+ font.baseSize = 16;
+ font.glyphCount = 189;
+
+ // Load texture from image
+ font.texture = LoadTextureFromImage(imFont);
+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
+
+ // Copy char recs data from global fontRecs
+ // NOTE: Required to avoid issues if trying to free font
+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
+ memcpy(font.recs, terminalFontRecs, font.glyphCount*sizeof(Rectangle));
+
+ // Copy font char info data from global fontChars
+ // NOTE: Required to avoid issues if trying to free font
+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
+ memcpy(font.glyphs, terminalFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
+
+ GuiSetFont(font);
+
+ // Setup a white rectangle on the font to be used on shapes drawing,
+ // it makes possible to draw shapes and text (full UI) in a single draw call
+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };
+ SetShapesTexture(font.texture, fontWhiteRec);
+
+ //-----------------------------------------------------------------
+
+ // TODO: Custom user style setup: Set specific properties here (if required)
+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
+}
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_controls_panel.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_controls_panel.png
new file mode 100644
index 0000000000..50dbc9c31b
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_controls_panel.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_ricons.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_ricons.png
new file mode 100644
index 0000000000..d269476e37
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_ricons.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_style_table_multi.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_style_table_multi.png
new file mode 100644
index 0000000000..ab41b5d377
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/raygui_style_table_multi.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguiicons_v100.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguiicons_v100.png
new file mode 100644
index 0000000000..4d29b1ef9a
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguiicons_v100.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguilayout_v220.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguilayout_v220.png
new file mode 100644
index 0000000000..2318fd0a25
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguilayout_v220.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguistyler_v210.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguistyler_v210.png
new file mode 100644
index 0000000000..abf4838134
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguistyler_v210.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguistyler_v300.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguistyler_v300.png
new file mode 100644
index 0000000000..82bbcb0110
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/images/rguistyler_v300.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui.ico b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui.ico
new file mode 100644
index 0000000000..cc8498b123
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui.ico differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_128x128.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_128x128.png
new file mode 100644
index 0000000000..d22ea7dbcf
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_128x128.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_16x16.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_16x16.png
new file mode 100644
index 0000000000..0e9c4858e0
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_16x16.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_24x24.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_24x24.png
new file mode 100644
index 0000000000..4cea8e0a3f
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_24x24.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_256x256.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_256x256.png
new file mode 100644
index 0000000000..75a76a0f63
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_256x256.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_32x32.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_32x32.png
new file mode 100644
index 0000000000..d56878a0d3
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_32x32.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_48x48.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_48x48.png
new file mode 100644
index 0000000000..863e07f027
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_48x48.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_512x512.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_512x512.png
new file mode 100644
index 0000000000..bde57037ac
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_512x512.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_64x64.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_64x64.png
new file mode 100644
index 0000000000..c72b09dfd1
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_64x64.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_96x96.png b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_96x96.png
new file mode 100644
index 0000000000..d0098c7a0f
Binary files /dev/null and b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/logo/raygui_96x96.png differ
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/CMake/CMakeLists.txt b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/CMake/CMakeLists.txt
new file mode 100644
index 0000000000..046f6e3691
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/CMake/CMakeLists.txt
@@ -0,0 +1,76 @@
+cmake_minimum_required(VERSION 3.11)
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
+project(raygui C)
+
+# Config options
+option(BUILD_RAYGUI_EXAMPLES "Build the examples." OFF)
+
+# Force building examples if building in the root as standalone.
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ set(BUILD_RAYGUI_EXAMPLES TRUE)
+endif()
+
+# Directory Variables
+set(RAYGUI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
+set(RAYGUI_SRC ${RAYGUI_ROOT}/src)
+set(RAYGUI_EXAMPLES ${RAYGUI_ROOT}/examples)
+
+# raygui
+add_library(raygui INTERFACE)
+file(GLOB sources ${RAYGUI_SRC}/*.h)
+set(RAYGUI_HEADERS ${sources})
+install(FILES
+ ${RAYGUI_HEADERS} DESTINATION include
+)
+target_include_directories(raygui INTERFACE ${RAYGUI_SRC})
+
+# Examples
+if(${BUILD_RAYGUI_EXAMPLES})
+ find_package(Raylib)
+
+ # Get the sources together
+ set(example_dirs
+ animation_curve
+ controls_test_suite
+ custom_file_dialog
+ custom_sliders
+ image_exporter
+ image_importer_raw
+ portable_window
+ property_list
+ scroll_panel
+ style_selector
+ )
+
+ set(example_sources)
+ set(example_resources)
+
+ foreach(example_dir ${example_dirs})
+ # Get the .c files
+ file(GLOB sources ${RAYGUI_EXAMPLES}/${example_dir}/*.c)
+ list(APPEND example_sources ${sources})
+
+ # Any any resources
+ file(GLOB resources ${RAYGUI_EXAMPLES}/${example_dir}/resources/*)
+ list(APPEND example_resources ${resources})
+ endforeach()
+
+ # Do each example
+ foreach(example_source ${example_sources})
+ # Create the basename for the example
+ get_filename_component(example_name ${example_source} NAME)
+ string(REPLACE ".c" "${OUTPUT_EXT}" example_name ${example_name})
+
+ # Setup the example
+ add_executable(${example_name} ${example_source})
+
+ target_link_libraries(${example_name} PUBLIC raylib raygui)
+
+ string(REGEX MATCH ".*/.*/" resources_dir ${example_source})
+ string(APPEND resources_dir "resources")
+ endforeach()
+
+ # Copy all of the resource files to the destination
+ file(COPY ${example_resources} DESTINATION "resources/")
+endif()
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/CMake/cmake/FindRaylib.cmake b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/CMake/cmake/FindRaylib.cmake
new file mode 100644
index 0000000000..c8c3a64626
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/CMake/cmake/FindRaylib.cmake
@@ -0,0 +1,17 @@
+find_package(raylib 4.5.0 QUIET CONFIG)
+if (NOT raylib_FOUND)
+ include(FetchContent)
+ FetchContent_Declare(
+ raylib
+ GIT_REPOSITORY https://github.com/raysan5/raylib.git
+ GIT_TAG 4.5.0
+ )
+ FetchContent_GetProperties(raylib)
+ if (NOT raylib_POPULATED) # Have we downloaded raylib yet?
+ set(FETCHCONTENT_QUIET NO)
+ FetchContent_Populate(raylib)
+ set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples
+ set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # or games
+ add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR})
+ endif()
+endif()
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/animation_curve.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/animation_curve.vcxproj
new file mode 100644
index 0000000000..8e90f64210
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/animation_curve.vcxproj
@@ -0,0 +1,363 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {50A98C3D-C898-4830-A00B-3F78DC2E742B}
+ Win32Proj
+ style_selector
+ animation_curve
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/controls_test_suite.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/controls_test_suite.vcxproj
new file mode 100644
index 0000000000..e9a5715188
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/controls_test_suite.vcxproj
@@ -0,0 +1,360 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {0981CA98-E4A5-4DF1-987F-A41D09131EFC}
+ Win32Proj
+ controls_test_suite
+ controls_test_suite
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/custom_file_dialog.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/custom_file_dialog.vcxproj
new file mode 100644
index 0000000000..fcf7fe8530
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/custom_file_dialog.vcxproj
@@ -0,0 +1,363 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {E1CF5310-BCF6-4063-861D-EDFF65D9FE2A}
+ Win32Proj
+ custom_file_dialog
+ custom_file_dialog
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/image_exporter.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/image_exporter.vcxproj
new file mode 100644
index 0000000000..a1bc4db5d2
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/image_exporter.vcxproj
@@ -0,0 +1,360 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {67B2B88C-EA52-403F-A596-5107008C71F2}
+ Win32Proj
+ image_exporter
+ image_exporter
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/image_importer_raw.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/image_importer_raw.vcxproj
new file mode 100644
index 0000000000..69f2a90255
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/image_importer_raw.vcxproj
@@ -0,0 +1,360 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {6628D753-270D-418D-A87F-6E2E63B9E3D0}
+ Win32Proj
+ image_importer_raw
+ image_importer_raw
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/portable_window.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/portable_window.vcxproj
new file mode 100644
index 0000000000..508ac8479f
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/portable_window.vcxproj
@@ -0,0 +1,360 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {FFDA97F5-4BAF-410A-AE87-0C8E3CB8C0D8}
+ Win32Proj
+ portable_window
+ portable_window
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/property_list.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/property_list.vcxproj
new file mode 100644
index 0000000000..9bfa63f340
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/property_list.vcxproj
@@ -0,0 +1,360 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {D28301C9-C293-4F41-9F58-F2609F33134E}
+ Win32Proj
+ property_list
+ property_list
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/scroll_panel.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/scroll_panel.vcxproj
new file mode 100644
index 0000000000..365d029505
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/scroll_panel.vcxproj
@@ -0,0 +1,360 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {56EE93DF-A3AF-4856-A4EC-E27358C6DA87}
+ Win32Proj
+ scroll_panel
+ scroll_panel
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/style_selector.vcxproj b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/style_selector.vcxproj
new file mode 100644
index 0000000000..90da635cdb
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/style_selector.vcxproj
@@ -0,0 +1,360 @@
+ο»Ώ
+
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {BCF5E746-FDBF-4CAC-9B95-44FE9A498430}
+ Win32Proj
+ style_selector
+ style_selector
+ 10.0
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ $(SolutionDir)..\..\src;$(SolutionDir)..\..\src\external;$(SolutionDir)..\..\..\raylib\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/test.props b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/test.props
new file mode 100644
index 0000000000..e3a6e091e1
--- /dev/null
+++ b/zig-pkg/N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo/projects/VS2022/examples/test.props
@@ -0,0 +1,27 @@
+#
+# Property types:
+# b // Bool
+# i // Int
+# f