diff --git a/CHANGELOG.md b/CHANGELOG.md index 77e38e8f..169c8f45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ - **Explicit SIMD128 bodies for every sidecar matmul kernel**: Q4_K, Q5_K, Q6_K, Q5_0 and Q5_1 join Q8_0 and Q4_0 with hand-written `__wasm_simd128__` paths (the K-quant int8 dots on `i32x4.dot_i16x8_s`, the Q5 fifth-bit plane via a byte swizzle); the dense FP32 GEMM gets a 4×8 register-blocked, k-blocked micro-kernel; BF16 and FP16 widen eight weights per step. BF16 and FP16 also gain NEON bodies (none existed on any tier). Results stay bit-identical in accumulation order to the portable bodies. - **Threaded dense kernels**: `skainet_fp32_matmul`, `skainet_bf16_matmul` and `skainet_fp16_matmul` now split the output over the shared row-thread pool like the packed kernels do (the GEMM over the longer side of `C`, the 16-bit kernels over columns) — the mt sidecar's pthreads in a browser, the native pool on the JVM. - **`WasmCpuOps.matmul`**: a dense 2-D `A · B` on heap FP32 operands runs the sidecar GEMM; the common `[k, n]` loop no longer serves that shape on wasm (it was the only dense path that never reached the sidecar). +- **Ternary kernels on the wasm tier**: the sidecar now exports `skainet_ternary_f32_gemv`, `skainet_ternary_lmhead_stage1` and `skainet_bitnet_gemv_tq2_0`, and `WasmTernaryKernelPack` (installed by `WasmSimd.install()`) registers them under the same `KernelDispatch` keys the JVM FFM and Android JNI ternary packs serve — exact FP32 × `BitNet-b1.58`, the fused multi-plane `BitNet-planes` lm_head and int8 × `TQ2_0`. A BitNet weight in a browser previously went to the decoding reference kernel. The portable branch of `skainet_ternary_f32.c` (MSVC and Emscripten) now holds the vendored kernel's 256-entry decode table as a compile-time constant with a SIMD128 body and threads over output rows through the shared row pool; `bitnet_gemv` gains a SIMD128 block body and the same row threading on every tier. +- **Direct `x · Wᵀ` on the JVM**: `Fp32MatmulWtKernel` / `KernelProvider.matmulFp32Wt()` (and the JVM-only `Fp32MemSegMatmulWtKernel` / `MemSegKernelProvider.matmulFp32WtMemSeg()`) expose `skainet_fp32_matmul_wt`, which the wasm sidecar has served since 0.61.0 and the JVM never bound. `NativeKernelProvider` carries it; `DefaultCpuOpsJvm.matmulWeightTransposed` multiplies a dense `[out, in]` FP32 weight in place through it — a segment-backed weight where it lies, a heap weight after one resident off-heap copy — instead of transposing the weight once into `[k, n]` and caching the copy. The wasm provider exposes the same accessor (`WasmFp32MatmulWtKernel`), and `KernelProvider.supports("matmul_wt", …)` reports it. +- **Kernel support matrix, fourth table** *Kernel packs (view dispatch)*: the ternary formats and the direct `x · Wᵀ` per platform, which the `matmul` accessors the first table introspects do not cover. +- **`engine-fp32-linear`** in `jvm-cpu-publish` and `wasm-bench`: a `Linear` layer's `x · Wᵀ` (16 tokens, 768 → 3072) through `ctx.ops.matmulWeightTransposed`; on the JVM `--provider panama` measures the cached-transpose path and `--provider ffm` the direct kernel. +- **Resident activations on the wasm tier**: `PlatformStorage.offHeapAllocator` (Kotlin/Wasm) binds `MemoryDomain.HOST_OFFHEAP` to a backend's memory; `WasmSimd.install()` binds it to the SIMD128 sidecar's linear memory (`WasmLinearStorage : Storage.OffHeap`, `WasmLinearTensorData : FloatArrayTensorData`), so `StorageCapabilities.current()` reports off-heap support in a browser and a `ForwardScope` frees sidecar activations at `reset()`. `WasmCpuOps` now keeps the outputs of `matmul`/`matmulWeightTransposed` resident and runs `add`/`subtract`/`multiply`/`divide`, `relu`/`sigmoid`/`silu`/`gelu`/`erf`/`tanh` and `sum`/`mean` in the sidecar on resident operands (transcendentals also on heap ones), reading a tensor back to the Kotlin heap only when something outside the sidecar needs it. Ambient outputs are freed when their tensor is collected (`FinalizationRegistry`); `WasmSimd.residentBudgetBytes` bounds what stays resident and `WasmCpuOps.toResident()` uploads an input once. New shared C kernels `skainet_f32_binary` / `skainet_f32_unary` / `skainet_f32_reduce_all` / `skainet_f32_reduce_axis` (SIMD128 and NEON bodies, row-pool threading) are in every native build as well. +- **`wasm-bench`**: a `laya.chain` case (`x · Wᵀ`, GELU, multiply, bias add, sum, end to end) and `operands=resident` variants of `engine-elementwise-add` and `engine-reductions-sum`. - **`wasm-bench` runs the `engine-*` scenarios** of the JVM publish harness (`engine-fp32-gemm`, `engine-kernel-matmul`, `engine-bf16-matmul`, `engine-q8-matmul`, `engine-q4-gemm`, `engine-ternary-f32-gemv`, `engine-elementwise-add`, `engine-reductions-sum/mean`) with identical shapes and metrics on every tier it measures, so the JVM and wasm numbers sit in one table. ## [0.61.0] - 2026-10-16 diff --git a/build-logic/convention/src/main/kotlin/GenerateKernelMatrixTask.kt b/build-logic/convention/src/main/kotlin/GenerateKernelMatrixTask.kt index 6964d6e0..17d2ebe1 100644 --- a/build-logic/convention/src/main/kotlin/GenerateKernelMatrixTask.kt +++ b/build-logic/convention/src/main/kotlin/GenerateKernelMatrixTask.kt @@ -128,6 +128,33 @@ abstract class GenerateKernelMatrixTask : DefaultTask() { appendLine("|===") appendLine("") } + if (module.packs.isNotEmpty()) { + appendLine("== Kernel packs (view dispatch)") + appendLine("") + appendLine( + "Kernels that are not reached through the `matmul` accessors above: the ternary formats " + + "are served by `ViewKernelPack`s keyed in `KernelDispatch` (`BitNet-b1.58` with exact " + + "FP32 activations, the fused multi-plane `BitNet-planes` lm_head, `TQ2_0` with int8 " + + "activations), and the dense `x · Wᵀ` of a `Linear` layer by the `matmulFp32Wt` " + + "accessor, which multiplies a row-major `[out, in]` weight in place instead of " + + "transposing and caching a copy. The scalar reference kernels serve every cell that " + + "is empty here (`—`), at reference speed; the common row-dot serves `x · Wᵀ` there.", + ) + appendLine("") + appendLine("[cols=\"$colSpec\", options=\"header\"]") + appendLine("|===") + append("| Kernel ") + module.platforms.forEach { append("| $it ") } + appendLine("") + appendLine("") + module.packs.forEach { fmt -> + append("| `${fmt.name}` ") + module.platforms.forEach { p -> append("| ${fmt.byPlatform[p] ?: "—"} ") } + appendLine("") + } + appendLine("|===") + appendLine("") + } appendLine( "See also the eager backends & kernels mindmap " + "(xref:explanation/eager-execution.adoc[]) for the narrative overview and gaps.", diff --git a/build-logic/convention/src/main/kotlin/models/KernelSupportModels.kt b/build-logic/convention/src/main/kotlin/models/KernelSupportModels.kt index 90da5388..fe8a43eb 100644 --- a/build-logic/convention/src/main/kotlin/models/KernelSupportModels.kt +++ b/build-logic/convention/src/main/kotlin/models/KernelSupportModels.kt @@ -23,6 +23,12 @@ data class KernelSupportModule( */ val mapped: List = emptyList(), val resident: List = emptyList(), + /** + * Kernel packs (view dispatch): the ternary formats and the direct dense `x · Wᵀ`, served by + * `ViewKernelPack`s / the `matmulFp32Wt` accessor rather than the `matmul` accessors. Absent in + * older JSON. + */ + val packs: List = emptyList(), ) @Serializable diff --git a/docs/modules/ROOT/pages/contributing/benchmarks.adoc b/docs/modules/ROOT/pages/contributing/benchmarks.adoc index 69a2ed12..737ee21e 100644 --- a/docs/modules/ROOT/pages/contributing/benchmarks.adoc +++ b/docs/modules/ROOT/pages/contributing/benchmarks.adoc @@ -33,6 +33,7 @@ microbench tests under `skainet-backends/skainet-backend-native-cpu`: |=== | Scenario | What it exercises | Unit | Direction | engine-fp32-gemm | `ctx.ops.matmul` end-to-end FP32 square matmul | GFLOPS | higher is better +| engine-fp32-linear | `ctx.ops.matmulWeightTransposed` — a `Linear` layer's `x · Wᵀ` with the weight stored `[out, in]` (panama: cached transpose + GEMM; ffm: native direct kernel, no transposed copy) | GFLOPS | higher is better | engine-q4-gemm | `PanamaVectorQ4KMatmulKernel` F32 × Q4_K matmul at LLM shapes | GOP/s | higher is better | engine-kernel-matmul | Direct `Fp32MatmulKernel` (scalar vs panama-vector) | GFLOPS | higher is better | engine-bf16-matmul | `Bf16MatmulKernel` F32 × BF16-packed matmul (scalar vs panama-vector) | GFLOPS | higher is better diff --git a/docs/modules/ROOT/pages/explanation/eager-execution.adoc b/docs/modules/ROOT/pages/explanation/eager-execution.adoc index f251bfbe..caba747d 100644 --- a/docs/modules/ROOT/pages/explanation/eager-execution.adoc +++ b/docs/modules/ROOT/pages/explanation/eager-execution.adoc @@ -29,7 +29,8 @@ mindmap Native FFM JVM only — C kernels via CMake Q4_K MemSeg zero-copy - Q6_K missing + direct x·Wᵀ, no transposed copy + ternary LUT gemv and planes lm_head Native JNI Android only — same C kernels via JNI two .so tiers, cpuinfo-gated armv8-a vs armv8.2+dotprod @@ -47,7 +48,7 @@ mindmap Android — scalar, Native-JNI Native linux — scalar, Native-cinterop Native apple — scalar, Accelerate, Native-cinterop - JS and WASM — scalar; packed weights relaid once into kernel feed order (SKEEP-007) + JS and WASM — scalar; wasmJs plus the SIMD128 sidecar pack: every matmul format, ternary, direct x·Wᵀ (SKEEP-007) ---- == Kernel × provider (matmul, FP32 activations) @@ -56,6 +57,7 @@ mindmap |=== | Weight format | Scalar (all targets) | Panama (JVM) | Native FFM (JVM) | Native JNI (Android) | Native cinterop (K/N) | Wasm SIMD128 (wasmJs) | FP32 | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ +| FP32 `x · Wᵀ` direct (weight `[out, in]`, no transposed copy) | row-dot | ❌ (cached transpose) | ✅ | ❌ | ❌ | ✅ | BF16 | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | FP16 | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | Q8_0 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ @@ -65,9 +67,9 @@ mindmap | Q5_K | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | Q5_1 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | Q5_0 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ -| TQ2_0 / BitNet b1.58 (int8 activations) | ✅ | — | — | ✅ NEON | — | — -| BitNet b1.58 (exact FP32 activations, vendored NeoGPU kernel) | ✅ | ✅ FFM | — | ✅ JNI + fused lm_head | ✅ K/N cinterop | ❌ (reference) -| BITNET_PLANES (multi-plane ternary packing) | ✅ | via kernel pack | — | via kernel pack | via kernel pack | ❌ (reference) +| TQ2_0 / BitNet b1.58 (int8 activations) | ✅ | — | — | ✅ NEON | — | ✅ SIMD128 +| BitNet b1.58 (exact FP32 activations, LUT gemv) | ✅ | — | ✅ FFM (vendored NeoGPU) | ✅ JNI | ✅ K/N cinterop | ✅ SIMD128 LUT +| BITNET_PLANES (multi-plane ternary packing, fused lm_head) | ✅ | — | ✅ FFM (vendored NeoGPU) | ✅ JNI | ✅ K/N cinterop | ✅ SIMD128 LUT | Q2_K / Q3_K / Q8_K / IQ4 | ❌ (dequant to FP32 only) | ❌ | ❌ | ❌ | ❌ | ❌ |=== @@ -78,7 +80,15 @@ columns are mutually exclusive per platform rather than stacked. The Wasm SIMD12 sidecar pack (`skainet-backend-wasm-simd`), present only after `WasmSimd.install()`; every matmul kernel in it has an explicit SIMD128 body (the K-quant int8 dots on `i32x4.dot_i16x8_s`, a 4×8 register-blocked dense GEMM, eight-wide BF16/FP16 widening), and the dense kernels thread over the -sidecar's pthread pool like the packed ones when the page is cross-origin isolated. +sidecar's pthread pool like the packed ones when the page is cross-origin isolated. The ternary +kernels in the sidecar are the portable mirror of the vendored NeoGPU kernel — the same 256-entry +decode table as a compile-time constant, read four codes at a time in SIMD128 — registered under the +same dispatch keys as the FFM and JNI ternary packs (`WasmTernaryKernelPack`). + +The dense `x · Wᵀ` row is the product a `Linear` layer computes. The JVM and the wasm tier multiply +the `[out, in]` weight in place through `skainet_fp32_matmul_wt` (`KernelProvider.matmulFp32Wt`; +the JVM makes a heap weight resident off-heap once, the sidecar keeps it in its linear memory) and +never materialise the transposed copy the Panama path caches per weight. Packed weights reach a kernel through the registry by declaring their xref:explanation/packed-weight-layout.adoc[block order]; a canonical weight is relayouted once, @@ -93,7 +103,7 @@ not per call. | *Android* | Scalar + Native-JNI | Panama (`jdk.incubator.vector`) and FFM (`java.lang.foreign`) are JDK-only — ART has neither, so Android's native tier is JNI, not a degraded JVM. Includes the NEON `bitnet_gemv` pack. | *Kotlin/Native — linux x64/arm64* | Scalar + Native-cinterop | Static archive embedded in the klib; manual `installNativeKernels()`, no ServiceLoader on K/N. | *Kotlin/Native — macOS/iOS* | Scalar + Apple Accelerate + Native-cinterop | Accelerate covers dense FP32 and reductions; cinterop covers packed quant with runtime `FEAT_DotProd` dispatch, so one archive serves A12 through M-series. -| *JS / WASM (Js, Wasi)* | Scalar; wasmJs + `skainet-backend-wasm-simd` | No SIMD in Kotlin code: packed weights are relaid once per weight into kernel feed order and served by the scalar packed kernels; dense `[out, in]` weights are multiplied in place without a transpose copy (SKEEP-007 Tier 0). On wasmJs, `WasmSimd.install()` adds the SIMD128 sidecar pack — the engine's C kernels compiled by Emscripten, with pthreads on cross-origin-isolated pages (SKEEP-007 Tier 1). +| *JS / WASM (Js, Wasi)* | Scalar; wasmJs + `skainet-backend-wasm-simd` | No SIMD in Kotlin code: packed weights are relaid once per weight into kernel feed order and served by the scalar packed kernels; dense `[out, in]` weights are multiplied in place without a transpose copy (SKEEP-007 Tier 0). On wasmJs, `WasmSimd.install()` adds the SIMD128 sidecar pack — the engine's C kernels compiled by Emscripten, with pthreads on cross-origin-isolated pages (SKEEP-007 Tier 1) — and binds `HOST_OFFHEAP` to the sidecar's linear memory, so matmul outputs, elementwise arithmetic, activations and reductions stay resident there between kernels and cross back to the Kotlin heap only when read. |=== Packed-quant matmul works on every target: those formats have a `commonMain` scalar kernel and @@ -101,11 +111,10 @@ Packed-quant matmul works on every target: those formats have a `commonMain` sca == Gaps -* *Wasm ternary / BitNet* — the ternary gemv and planes lm-head kernels are not in the sidecar -build yet, so BitNet models in a browser run the decoding reference kernel. -* *Wasm beyond matmul* — elementwise, activations, reductions, normalisation and attention are the -common scalar Kotlin paths on wasmJs; Kotlin/Wasm has no SIMD types and no shared-memory threads, so -these follow the matmuls into the sidecar (SKEEP-007 rollout step 3). +* *Wasm beyond matmul, part two* — softmax, the normalisations and attention are still the common +scalar Kotlin paths on wasmJs. Elementwise arithmetic, the activations and `sum`/`mean` already run +in the sidecar with the activations kept resident in its linear memory (`Storage.WasmLinear`, +`WasmCpuOps`); the remaining ops follow as fused kernels on both tiers (SKEEP-007 rollout step 3). * *Native JNI dense FP32/BF16* — the Android JNI provider has no GEMM shim, so dense ops fall through to scalar there whichever `.so` tier loaded (SKaiNET#920). * *Dense FP32/BF16 SIMD on Kotlin/Native linux* — still the scalar floor; Apple has Accelerate diff --git a/docs/modules/ROOT/pages/explanation/kernel-selection.adoc b/docs/modules/ROOT/pages/explanation/kernel-selection.adoc index b522b017..a7a58253 100644 --- a/docs/modules/ROOT/pages/explanation/kernel-selection.adoc +++ b/docs/modules/ROOT/pages/explanation/kernel-selection.adoc @@ -91,7 +91,7 @@ platform support is absent (a missing native library, no vector unit). | Kotlin/Native, wasm, JS | manual — e.g. `installNativeKernels()`; on wasmJs `WasmSimd.install()` (SKEEP-007) -| manual — call the pack's `install()` yourself; `WasmSimd.install()` registers the browser pack and its provider +| manual — call the pack's `install()` yourself; `WasmSimd.install()` registers the browser pack, its ternary pack and its provider |=== Without a row-major pack, a canonical packed weight is relaid **once per weight** into kernel feed diff --git a/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc b/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc index a3317ed3..a7de8e00 100644 --- a/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc +++ b/docs/modules/ROOT/pages/reference/kernel-support-matrix.adoc @@ -58,4 +58,18 @@ The browser has no files to map, so the wasm tier keeps weights *resident* in th | `Q5_0` | — | — | — | — | wasm-resident |=== +== Kernel packs (view dispatch) + +Kernels that are not reached through the `matmul` accessors above: the ternary formats are served by `ViewKernelPack`s keyed in `KernelDispatch` (`BitNet-b1.58` with exact FP32 activations, the fused multi-plane `BitNet-planes` lm_head, `TQ2_0` with int8 activations), and the dense `x · Wᵀ` of a `Linear` layer by the `matmulFp32Wt` accessor, which multiplies a row-major `[out, in]` weight in place instead of transposing and caching a copy. The scalar reference kernels serve every cell that is empty here (`—`), at reference speed; the common row-dot serves `x · Wᵀ` there. + +[cols="1,1,1,1,1,1", options="header"] +|=== +| Kernel | JVM | Android | Native·linux | Native·apple | JS/WASM + +| `BitNet-b1.58 (FP32 activations)` | ffm-ternary | native-jni | native-cinterop | native-cinterop | wasm-simd128 +| `BitNet-planes` | ffm-ternary | native-jni | native-cinterop | native-cinterop | wasm-simd128 +| `TQ2_0 (int8 activations)` | — | native-jni | — | — | wasm-simd128 +| `Float32 x·Wᵀ direct` | native-ffm | — | — | — | wasm-simd128 +|=== + See also the eager backends & kernels mindmap (xref:explanation/eager-execution.adoc[]) for the narrative overview and gaps. diff --git a/docs/modules/skeep/pages/007-browser-lane.adoc b/docs/modules/skeep/pages/007-browser-lane.adoc index 087cc1de..095eda06 100644 --- a/docs/modules/skeep/pages/007-browser-lane.adoc +++ b/docs/modules/skeep/pages/007-browser-lane.adoc @@ -1,7 +1,7 @@ = SKEEP-007: The browser lane — packed SIMD kernels and quantize-at-load :description: SKaiNET proposal for making inference in a browser usable and quick: stop the scalar wasm lane from falling to the decoding reference kernel, serve dense weights without transpose copies, keep token tables narrow, add a SIMD128 kernel pack with pthreads as a sidecar wasm module, and let the SafeTensors loader quantize at load so Hugging Face checkpoints are served packed on every target. -Status: Implemented (Tiers 0, 1 and 2 in engine 0.61.0); the resident-activation step, the SKaiNET-transformers consumer and the WebGPU proposal remain open + +Status: Implemented (Tiers 0, 1 and 2 in engine 0.61.0; resident activations with sidecar elementwise, activation and reduction kernels in the parity series that followed); the SKaiNET-transformers consumer and the WebGPU proposal remain open + Implementation: Tier 0 https://github.com/SKaiNET-developers/SKaiNET/pull/1352[#1352], Tier 2 quantize-at-load https://github.com/SKaiNET-developers/SKaiNET/pull/1353[#1353], Tier 1 `skainet-backend-wasm-simd` https://github.com/SKaiNET-developers/SKaiNET/pull/1354[#1354] — engine 0.61.0; the consumer work in SKaiNET-transformers follows, see <<_rollout_plan>>. + Audience: SKaiNET maintainers and contributors; SKaiNET-transformers maintainers (Laya and BERT in the browser); SKaiNET-examples maintainers (every web sample runs through this lane) + Created: 2026-10-16 + diff --git a/skainet-backends/benchmarks/jvm-cpu-publish/src/main/kotlin/sk/ainet/bench/publish/scenarios/Fp32LinearScenario.kt b/skainet-backends/benchmarks/jvm-cpu-publish/src/main/kotlin/sk/ainet/bench/publish/scenarios/Fp32LinearScenario.kt new file mode 100644 index 00000000..2600d365 --- /dev/null +++ b/skainet-backends/benchmarks/jvm-cpu-publish/src/main/kotlin/sk/ainet/bench/publish/scenarios/Fp32LinearScenario.kt @@ -0,0 +1,79 @@ +package sk.ainet.bench.publish.scenarios + +import sk.ainet.backend.api.kernel.KernelRegistry +import sk.ainet.bench.publish.runner.Scenario +import sk.ainet.context.DirectCpuExecutionContext +import sk.ainet.exec.kernel.NativeKernelProvider +import sk.ainet.exec.kernel.PanamaVectorKernelProvider +import sk.ainet.exec.kernel.ScalarKernelProvider +import sk.ainet.lang.tensor.Shape +import sk.ainet.lang.tensor.Tensor +import sk.ainet.lang.types.FP32 + +/** + * A `Linear` layer's product, `x · Wᵀ` with the weight stored `[out, in]`, through the public + * `ctx.ops.matmulWeightTransposed` path — what every projection of a transformer pays, as opposed to + * the `[k, n]` GEMM of `engine-fp32-gemm`. Shape: a 16-token prefill against a 768 → 3072 FFN + * projection. Primary metric: GFLOP/s over `2·m·n·k`. + * + * The provider selects the path: `panama` (the default) transposes the weight once into `[k, n]` + * and runs the Vector API GEMM; `ffm` runs the native direct kernel (`skainet_fp32_matmul_wt`) over a + * weight made resident off-heap, no transposed copy; `scalar` is the common row-dot. Only the chosen + * provider is registered, so the ops layer cannot fall through to another. + */ +internal class Fp32LinearScenario( + smoke: Boolean, + private val providerName: String, +) : Scenario { + override val id: String = "engine-fp32-linear" + override val suite: String = "skainet-engine" + override val primaryMetric: String = "gflops" + override val unit: String = "gflops" + override val higherIsBetter: Boolean = true + override val kernelProvider: String = providerName + + private val m: Int = 16 + private val k: Int = 768 + private val n: Int = if (smoke) 768 else 3072 + override val parameters: Map = mapOf( + "m" to m.toString(), + "k" to k.toString(), + "n" to n.toString(), + "kernel" to providerName, + ) + + private lateinit var ctx: DirectCpuExecutionContext + private lateinit var x: Tensor + private lateinit var w: Tensor + + override fun setup() { + KernelRegistry.clearForTesting() + when (providerName.lowercase()) { + "panama", "panama-vector" -> KernelRegistry.register(PanamaVectorKernelProvider) + "ffm", "native", "native-ffm" -> { + check(NativeKernelProvider.isAvailable()) { "bundled libskainet_kernels missing — the ffm provider cannot run" } + KernelRegistry.register(NativeKernelProvider) + } + "scalar" -> KernelRegistry.register(ScalarKernelProvider) + else -> error("unknown kernel provider: $providerName (use 'panama', 'ffm' or 'scalar')") + } + ctx = DirectCpuExecutionContext() + x = ctx.fromFloatArray(Shape(m, k), FP32::class, FloatArray(m * k) { ((it % 251) - 125).toFloat() / 127f }) + w = ctx.fromFloatArray(Shape(n, k), FP32::class, FloatArray(n * k) { ((it * 13 % 257) - 128).toFloat() / 127f }) + // First call: the transpose cache or the resident copy is built here, not in a measured run. + ctx.ops.matmulWeightTransposed(x, w) + } + + override fun runOnce(): Double { + val start = System.nanoTime() + val result = ctx.ops.matmulWeightTransposed(x, w) + val elapsedNs = System.nanoTime() - start + @Suppress("UNUSED_VARIABLE") val sink = result.hashCode() + val flops = 2.0 * m.toDouble() * n.toDouble() * k.toDouble() + return (flops / (elapsedNs / 1_000_000_000.0)) / 1e9 + } + + override fun teardown() { + KernelRegistry.clearForTesting() + } +} diff --git a/skainet-backends/benchmarks/jvm-cpu-publish/src/main/kotlin/sk/ainet/bench/publish/scenarios/ScenarioRegistry.kt b/skainet-backends/benchmarks/jvm-cpu-publish/src/main/kotlin/sk/ainet/bench/publish/scenarios/ScenarioRegistry.kt index 74a595fe..a3f0550e 100644 --- a/skainet-backends/benchmarks/jvm-cpu-publish/src/main/kotlin/sk/ainet/bench/publish/scenarios/ScenarioRegistry.kt +++ b/skainet-backends/benchmarks/jvm-cpu-publish/src/main/kotlin/sk/ainet/bench/publish/scenarios/ScenarioRegistry.kt @@ -6,6 +6,7 @@ public object ScenarioRegistry { public fun ids(): List = listOf( "engine-fp32-gemm", + "engine-fp32-linear", "engine-q4-gemm", "engine-kernel-matmul", "engine-bf16-matmul", @@ -18,6 +19,7 @@ public object ScenarioRegistry { public fun byId(id: String, provider: String, smoke: Boolean): Scenario? = when (id) { "engine-fp32-gemm" -> Fp32GemmScenario(smoke = smoke, providerName = provider) + "engine-fp32-linear" -> Fp32LinearScenario(smoke = smoke, providerName = provider) "engine-q4-gemm" -> Q4GemmScenario(smoke = smoke, providerName = provider) "engine-kernel-matmul" -> KernelMatmulScenario(smoke = smoke, providerName = provider) "engine-bf16-matmul" -> Bf16MatmulScenario(smoke = smoke, providerName = provider) diff --git a/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Main.kt b/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Main.kt index 72c13007..b1108a97 100644 --- a/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Main.kt +++ b/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Main.kt @@ -1,6 +1,7 @@ package sk.ainet.bench.wasm import sk.ainet.context.DirectCpuExecutionContext +import sk.ainet.exec.wasm.WasmCpuOps import sk.ainet.exec.wasm.WasmKernels import sk.ainet.exec.wasm.WasmSimd import sk.ainet.lang.tensor.Shape @@ -90,8 +91,15 @@ private fun report(tier: String, case: Case, form: String, ms: Double) { /** * Three passes: the scalar lane, then the SIMD128 sidecar single-threaded, then with pthreads when * the runtime allows them (Node, or a cross-origin-isolated page). Each line carries `tier=`. + * + * `SKAINET_WASM_RESIDENT=0` in the environment (Node) runs the sidecar passes with + * `WasmSimd.residentBudgetBytes = 0`, i.e. every op output read back to the heap — the A/B for the + * resident-activation step. */ suspend fun main() { + val resident = envVar("SKAINET_WASM_RESIDENT") != "0" + if (!resident) WasmSimd.residentBudgetBytes = 0L + println("[SKAINET_PERF_WASM] residentActivations=$resident") runPass("scalar") WasmSimd.install(threads = false) runPass(WasmKernels.mode) @@ -122,4 +130,39 @@ private fun runPass(tier: String) { report(tier, case, "dense", timeMedianMs(reps) { ctx.ops.matmulWeightTransposed(x, dense) }) report(tier, case, "q8_0", timeMedianMs(reps) { ctx.ops.matmulWeightTransposed(x, packed) }) } + runChain(tier, ctx) +} + +/** + * The resident-activation case: one Laya MLP block's shape of ops between two matmuls — + * `x · Wᵢᵀ`, GELU, a gated multiply, a bias add, then a reduction that reads the result back — + * timed end to end. On the scalar lane every op allocates and walks a heap array; on the sidecar + * the intermediates stay in linear memory and only the final scalar crosses the boundary. + * + * `[SKAINET_PERF_WASM] tier= laya.chain m=150 n=2304 k=768 ops=matmulWt+gelu+mul+add+sum residentBudget= ms=` + */ +private fun runChain(tier: String, ctx: DirectCpuExecutionContext) { + val m = 150; val n = 2304; val k = 768 + val x = ctx.fromFloatArray(Shape(m, k), FP32::class, pseudo(m * k, 3)) + val w = ctx.fromFloatArray(Shape(n, k), FP32::class, pseudo(n * k, 7)) + val bias = ctx.fromFloatArray(Shape(n), FP32::class, pseudo(n, 11)) + fun chain(): Float { + val h = ctx.ops.matmulWeightTransposed(x, w) + val g = ctx.ops.gelu(h) + val s = ctx.ops.multiply(g, h) + val o = ctx.ops.add(s, bias) + return ctx.ops.sum(o).data.copyToFloatArray()[0] + } + chain() + val ms = timeMedianMs(5) { chain() } + val msText = ((ms * 100).roundToInt() / 100.0).toString() + val budget = if (ctx.ops is WasmCpuOps) WasmSimd.residentBudgetBytes else 0L + println("[SKAINET_PERF_WASM] tier=$tier laya.chain m=$m n=$n k=$k ops=matmulWt+gelu+mul+add+sum residentBudget=$budget ms=$msText") } + +@OptIn(kotlin.js.ExperimentalWasmJsInterop::class) +private fun envVar(name: String): String? = jsEnvVar(name)?.toString() + +@OptIn(kotlin.js.ExperimentalWasmJsInterop::class) +private fun jsEnvVar(name: String): JsString? = + js("(typeof process !== 'undefined' && process.env && process.env[name] != null) ? process.env[name] : null") diff --git a/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Scenarios.kt b/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Scenarios.kt index 271fc27b..bd43d07e 100644 --- a/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Scenarios.kt +++ b/skainet-backends/benchmarks/wasm-bench/src/wasmJsMain/kotlin/sk/ainet/bench/wasm/Scenarios.kt @@ -4,6 +4,7 @@ import sk.ainet.backend.api.kernel.KernelDispatch import sk.ainet.backend.api.kernel.KernelKey import sk.ainet.backend.api.kernel.KernelRegistry import sk.ainet.context.DirectCpuExecutionContext +import sk.ainet.exec.wasm.WasmCpuOps import sk.ainet.lang.memory.Scope import sk.ainet.lang.memory.Storage import sk.ainet.lang.memory.TensorView @@ -48,6 +49,15 @@ internal fun engineScenarios(): List = listOf( val flops = 2.0 * n * n * n; { flops / seconds { ctx.ops.matmul(a, b) } / 1e9 } }, + WasmScenario("engine-fp32-linear", "gflops", mapOf("m" to "16", "k" to "768", "n" to "3072"), reps = 10) { + val m = 16; val k = 768; val n = 3072 + val ctx = DirectCpuExecutionContext() + val x = ctx.fromFloatArray(Shape(m, k), FP32::class, FloatArray(m * k) { ((it % 251) - 125).toFloat() / 127f }) + val w = ctx.fromFloatArray(Shape(n, k), FP32::class, FloatArray(n * k) { ((it * 13 % 257) - 128).toFloat() / 127f }) + ctx.ops.matmulWeightTransposed(x, w) // the resident upload happens here, not in a measured run + val flops = 2.0 * m * n * k; + { flops / seconds { ctx.ops.matmulWeightTransposed(x, w) } / 1e9 } + }, WasmScenario("engine-kernel-matmul", "gflops", mapOf("size" to "1024"), reps = 3) { val n = 1024 DirectCpuExecutionContext() @@ -123,6 +133,23 @@ internal fun engineScenarios(): List = listOf( val b = ctx.fromFloatArray(Shape(n), FP32::class, FloatArray(n) { 1f }); { n / seconds { ctx.ops.add(a, b) } / 1e6 } }, + // The same three ops on operands already resident in the sidecar (the shape a chain between two + // matmuls has); heap operands above stay on the common lane by design. + WasmScenario("engine-elementwise-add", "melems_per_sec", mapOf("elements" to "1000000", "operands" to "resident"), reps = 10) { + val n = 1_000_000 + val ctx = DirectCpuExecutionContext() + val ops = ctx.ops as? WasmCpuOps ?: error("resident operands need the sidecar") + val a = ops.toResident(ctx.fromFloatArray(Shape(n), FP32::class, FloatArray(n) { it.toFloat() * 0.5f })) + val b = ops.toResident(ctx.fromFloatArray(Shape(n), FP32::class, FloatArray(n) { 1f })); + { n / seconds { ctx.ops.add(a, b) } / 1e6 } + }, + WasmScenario("engine-reductions-sum", "melems_per_sec", mapOf("elements" to "1000000", "op" to "sum", "operands" to "resident"), reps = 10) { + val n = 1_000_000 + val ctx = DirectCpuExecutionContext() + val ops = ctx.ops as? WasmCpuOps ?: error("resident operands need the sidecar") + val a = ops.toResident(ctx.fromFloatArray(Shape(n), FP32::class, FloatArray(n) { (it % 1024).toFloat() * 0.25f })); + { n / seconds { ctx.ops.sum(a).data.copyToFloatArray() } / 1e6 } + }, WasmScenario("engine-reductions-sum", "melems_per_sec", mapOf("elements" to "1000000", "op" to "sum"), reps = 10) { val n = 1_000_000 val ctx = DirectCpuExecutionContext() diff --git a/skainet-backends/skainet-backend-api/src/commonMain/kotlin/sk/ainet/backend/api/kernel/Fp32MatmulWtKernel.kt b/skainet-backends/skainet-backend-api/src/commonMain/kotlin/sk/ainet/backend/api/kernel/Fp32MatmulWtKernel.kt new file mode 100644 index 00000000..d85d77a1 --- /dev/null +++ b/skainet-backends/skainet-backend-api/src/commonMain/kotlin/sk/ainet/backend/api/kernel/Fp32MatmulWtKernel.kt @@ -0,0 +1,28 @@ +package sk.ainet.backend.api.kernel + +/** + * Dense `x · Wᵀ` for a row-major `[out, in]` FP32 weight — the shape a `Linear` layer stores its + * weight in, multiplied in place: + * + * `out[i, o] = Σ_p x[i, p] · w[o, p]` + * + * Every output is one contiguous dot product over the weight's own row, so no transposed copy of + * the weight is ever made. This is the SPI face of `skainet_fp32_matmul_wt` (SKEEP-007), which the + * wasm sidecar has served since 0.61.0 and the JVM FFM provider binds as well: a tier whose + * [Fp32MatmulKernel] wants the weight input-major (`[k, n]`) otherwise pays a scattered transpose + * copy per weight and caches it — about 0.5 GB for a 22-layer encoder. + * + * Operands are contiguous: `x` is `m` rows of `k`, `w` is `n` rows of `k`, `out` is `m` rows of + * `n`, each from its offset. Implementations must not mutate `x` or `w`, must fully overwrite the + * `m × n` block of `out`, and may assume the arrays do not alias. `k == 0` zeroes the block; + * `m == 0` or `n == 0` is a no-op. Each output accumulates its products in ascending `p`, so a + * conforming kernel is bit-identical to transpose-then-GEMM with the same accumulation order. + */ +public interface Fp32MatmulWtKernel { + public fun matmulWt( + x: FloatArray, xOffset: Int, + w: FloatArray, wOffset: Int, + out: FloatArray, outOffset: Int, + m: Int, n: Int, k: Int, + ) +} diff --git a/skainet-backends/skainet-backend-api/src/commonMain/kotlin/sk/ainet/backend/api/kernel/KernelProvider.kt b/skainet-backends/skainet-backend-api/src/commonMain/kotlin/sk/ainet/backend/api/kernel/KernelProvider.kt index d1126a82..734c97e4 100644 --- a/skainet-backends/skainet-backend-api/src/commonMain/kotlin/sk/ainet/backend/api/kernel/KernelProvider.kt +++ b/skainet-backends/skainet-backend-api/src/commonMain/kotlin/sk/ainet/backend/api/kernel/KernelProvider.kt @@ -103,6 +103,13 @@ public interface KernelProvider { */ public fun matmulQ5_0(): Q5_0MatmulKernel? = null + /** + * Dense `x · Wᵀ` over a row-major `[out, in]` FP32 weight ([Fp32MatmulWtKernel]), or `null` + * when this provider has no direct kernel for it and the caller should transpose once and use + * [matmulFp32]. Same fall-through pattern as [matmulQ4K]. + */ + public fun matmulFp32Wt(): Fp32MatmulWtKernel? = null + /** * Capability query: does this provider carry a kernel for * [opName] with the given [dtypeKeys]? @@ -122,15 +129,18 @@ public interface KernelProvider { * - For ops that aren't matmul (future: SDPA, gather, RMSNorm…), * providers can override this method to declare those kernels. * - * The default body covers the four matmul accessors that exist - * on this interface today. Providers that ship additional + * The default body covers the matmul accessors on this interface, + * plus `"matmul_wt"` with `["Float32", "Float32"]` for the direct + * `x · Wᵀ` kernel ([matmulFp32Wt]). Providers that ship additional * kernels override and chain through `super.supports(...)` for * the matmul base cases. */ public fun supports(opName: String, dtypeKeys: List): Boolean { - if (opName != "matmul" || dtypeKeys.size != 2) return false + if (dtypeKeys.size != 2) return false val (input, weight) = dtypeKeys if (input != "Float32") return false + if (opName == "matmul_wt") return weight == "Float32" && matmulFp32Wt() != null + if (opName != "matmul") return false return when (weight) { "Float32" -> matmulFp32() != null "BFloat16" -> matmulBf16() != null diff --git a/skainet-backends/skainet-backend-api/src/jvmMain/kotlin/sk/ainet/backend/api/kernel/Fp32MemSegMatmulWtKernel.kt b/skainet-backends/skainet-backend-api/src/jvmMain/kotlin/sk/ainet/backend/api/kernel/Fp32MemSegMatmulWtKernel.kt new file mode 100644 index 00000000..6b95f271 --- /dev/null +++ b/skainet-backends/skainet-backend-api/src/jvmMain/kotlin/sk/ainet/backend/api/kernel/Fp32MemSegMatmulWtKernel.kt @@ -0,0 +1,24 @@ +package sk.ainet.backend.api.kernel + +import java.lang.foreign.MemorySegment + +/** + * [Fp32MatmulWtKernel] with the `[out, in]` FP32 weight supplied as an off-heap + * `java.lang.foreign.MemorySegment` instead of a heap `FloatArray`. JVM-only sibling, for the same + * reason [Q4KMemSegMatmulKernel] exists: a downcall cannot read heap memory on JDK 21, so the heap + * face copies the whole weight on every call — and the weight is the large operand. A weight that + * already lives in a segment (loaded off-heap, or made resident once by the ops layer) is passed + * through with no copy at all; only the `m × k` activation and the `m × n` output are staged. + * + * Same contract as [Fp32MatmulWtKernel]: contiguous operands, `out` fully overwritten, products + * accumulated in ascending `p`. The caller owns the segment's arena and keeps it alive for the + * duration of the call; the kernel retains nothing past return. + */ +public interface Fp32MemSegMatmulWtKernel { + public fun matmulWt( + x: FloatArray, xOffset: Int, + weight: MemorySegment, weightByteOffset: Long, + out: FloatArray, outOffset: Int, + m: Int, n: Int, k: Int, + ) +} diff --git a/skainet-backends/skainet-backend-api/src/jvmMain/kotlin/sk/ainet/backend/api/kernel/MemSegKernelProvider.kt b/skainet-backends/skainet-backend-api/src/jvmMain/kotlin/sk/ainet/backend/api/kernel/MemSegKernelProvider.kt index 527401a5..c567aa11 100644 --- a/skainet-backends/skainet-backend-api/src/jvmMain/kotlin/sk/ainet/backend/api/kernel/MemSegKernelProvider.kt +++ b/skainet-backends/skainet-backend-api/src/jvmMain/kotlin/sk/ainet/backend/api/kernel/MemSegKernelProvider.kt @@ -34,4 +34,10 @@ public interface MemSegKernelProvider { * keep compiling. */ public fun matmulQ4KMemSeg(): Q4KMemSegMatmulKernel? = null + + /** + * Dense `x · Wᵀ` with the `[out, in]` FP32 weight supplied as a `MemorySegment` + * ([Fp32MemSegMatmulWtKernel]), or `null`. Same `null` default as [matmulQ4KMemSeg]. + */ + public fun matmulFp32WtMemSeg(): Fp32MemSegMatmulWtKernel? = null } diff --git a/skainet-backends/skainet-backend-cpu/api/jvm/skainet-backend-cpu.api b/skainet-backends/skainet-backend-cpu/api/jvm/skainet-backend-cpu.api index e0b80980..eddcc360 100644 --- a/skainet-backends/skainet-backend-cpu/api/jvm/skainet-backend-cpu.api +++ b/skainet-backends/skainet-backend-cpu/api/jvm/skainet-backend-cpu.api @@ -67,6 +67,7 @@ public final class sk/ainet/exec/kernel/PanamaVectorKernelProvider : sk/ainet/ba public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel; public fun matmulFp16 ()Lsk/ainet/backend/api/kernel/Fp16MatmulKernel; public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel; + public fun matmulFp32Wt ()Lsk/ainet/backend/api/kernel/Fp32MatmulWtKernel; public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel; public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel; public fun matmulQ5K ()Lsk/ainet/backend/api/kernel/Q5KMatmulKernel; @@ -85,6 +86,7 @@ public final class sk/ainet/exec/kernel/PanamaVectorKernelProviderFactory : sk/a public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel; public fun matmulFp16 ()Lsk/ainet/backend/api/kernel/Fp16MatmulKernel; public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel; + public fun matmulFp32Wt ()Lsk/ainet/backend/api/kernel/Fp32MatmulWtKernel; public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel; public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel; public fun matmulQ5K ()Lsk/ainet/backend/api/kernel/Q5KMatmulKernel; @@ -168,6 +170,7 @@ public final class sk/ainet/exec/kernel/ScalarKernelProvider : sk/ainet/backend/ public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel; public fun matmulFp16 ()Lsk/ainet/backend/api/kernel/Fp16MatmulKernel; public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel; + public fun matmulFp32Wt ()Lsk/ainet/backend/api/kernel/Fp32MatmulWtKernel; public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel; public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel; public fun matmulQ5K ()Lsk/ainet/backend/api/kernel/Q5KMatmulKernel; @@ -186,6 +189,7 @@ public final class sk/ainet/exec/kernel/ScalarKernelProviderFactory : sk/ainet/b public fun matmulBf16 ()Lsk/ainet/backend/api/kernel/Bf16MatmulKernel; public fun matmulFp16 ()Lsk/ainet/backend/api/kernel/Fp16MatmulKernel; public fun matmulFp32 ()Lsk/ainet/backend/api/kernel/Fp32MatmulKernel; + public fun matmulFp32Wt ()Lsk/ainet/backend/api/kernel/Fp32MatmulWtKernel; public fun matmulQ4K ()Lsk/ainet/backend/api/kernel/Q4KMatmulKernel; public fun matmulQ4_0 ()Lsk/ainet/backend/api/kernel/Q4_0MatmulKernel; public fun matmulQ5K ()Lsk/ainet/backend/api/kernel/Q5KMatmulKernel; diff --git a/skainet-backends/skainet-backend-cpu/src/jvmMain/kotlin/sk/ainet/exec/tensor/ops/DefaultCpuOpsJvm.kt b/skainet-backends/skainet-backend-cpu/src/jvmMain/kotlin/sk/ainet/exec/tensor/ops/DefaultCpuOpsJvm.kt index 8fe1cf91..3b2157b2 100644 --- a/skainet-backends/skainet-backend-cpu/src/jvmMain/kotlin/sk/ainet/exec/tensor/ops/DefaultCpuOpsJvm.kt +++ b/skainet-backends/skainet-backend-cpu/src/jvmMain/kotlin/sk/ainet/exec/tensor/ops/DefaultCpuOpsJvm.kt @@ -6,7 +6,9 @@ import jdk.incubator.vector.VectorOperators import sk.ainet.backend.api.kernel.Bf16MatmulKernel import sk.ainet.backend.api.kernel.Fp16MatmulKernel import sk.ainet.backend.api.kernel.Fp32MatmulKernel +import sk.ainet.backend.api.kernel.Fp32MemSegMatmulWtKernel import sk.ainet.backend.api.kernel.KernelRegistry +import sk.ainet.backend.api.kernel.MemSegKernelProvider import sk.ainet.backend.api.kernel.KernelServiceLoader import sk.ainet.backend.api.kernel.KernelStrictness import sk.ainet.backend.api.kernel.Q4KMatmulKernel @@ -196,12 +198,19 @@ internal class DefaultCpuOpsJvm( * tensor nothing could decode correctly (#1124). Here the kernels do exist, so the relayout * pays: once per weight, cached by the identity of its bytes. */ - /** The JVM keeps the cached transpose: its vectorised `[k, n]` kernels are the fast path (SKEEP-007 §T0.2). */ + /** + * The common row-dot is not this tier's direct path: a dense weight goes to the native `x · Wᵀ` + * kernel ([matmulDenseWeightTransposedNative]) when the FFM provider is loaded, and to the cached + * transpose plus the vectorised `[k, n]` kernels otherwise (SKEEP-007 §T0.2). + */ override fun preferDirectWeightTransposed(): Boolean = false @Suppress("UNCHECKED_CAST") override fun matmulWeightTransposed(x: Tensor, weight: Tensor): Tensor { if (weight.shape.rank != 2 || !isHeapPackedWeightForJvm(weight.data)) { + // Dense FP32 `[out, in]` weight with a native direct kernel: multiplied in place, no + // transposed copy made or cached (the weight is made resident off-heap once instead). + matmulDenseWeightTransposedNative(x, weight)?.let { return it } // Packed weights OUTSIDE the JVM relayout list (the ternary formats, #1136) go to the // common views→KernelDispatch path — whose kernels and reference are commonMain and // cannot read a MemorySegment-backed activation (SKEEP-004 forbids element access over @@ -265,6 +274,94 @@ internal class DefaultCpuOpsJvm( private val prepackedWeightsJvm: MutableList>> = mutableListOf() private val PREPACK_CACHE_LIMIT_JVM: Int = 64 + /** + * The direct `x · Wᵀ` kernel over an off-heap weight (`skainet_fp32_matmul_wt` through FFM), from + * the highest-priority available provider that carries one; `null` on a JVM without the native + * library, where the cached-transpose path below still serves. + */ + private val fp32WtKernel: Fp32MemSegMatmulWtKernel? by lazy { + ensureKernelProviders() + KernelRegistry.providers().asSequence() + .filter { it.isAvailable() } + .mapNotNull { (it as? MemSegKernelProvider)?.matmulFp32WtMemSeg() } + .firstOrNull() + } + + /** + * Dense weights made resident off-heap for [fp32WtKernel], keyed by the identity of their + * `TensorData` — the counterpart of the transposed-weight cache this path replaces, holding the + * same bytes untransposed where a downcall can read them without a per-call copy. Bounded like + * that cache; an evicted weight is simply copied again on its next use. Segments come from + * `Arena.ofAuto()`, so a dropped entry is reclaimed with the tensor that owned it. + */ + private val residentDenseWeights: MutableList> = mutableListOf() + private val RESIDENT_DENSE_CACHE_LIMIT: Int = 256 + + /** + * `x · Wᵀ` for a dense FP32 `[out, in]` weight through the native direct kernel — the JVM-side + * half of SKEEP-007 §T0.2: no transposed copy of the weight is made, the weight is read where it + * lies (a segment-backed weight as is, a heap one after a single off-heap copy), and the C kernel + * threads over output rows. `null` when the kernel is not available or the operands are not + * dense FP32 the kernel can take, in which case the caller continues to the cached transpose. + */ + @Suppress("UNCHECKED_CAST") + private fun matmulDenseWeightTransposedNative(x: Tensor, weight: Tensor): Tensor? { + if (weight.shape.rank != 2 || x.rank < 1 || x.dtype != FP32::class || weight.dtype != FP32::class) return null + val kernel = fp32WtKernel ?: return null + val n = weight.shape[0] + val k = weight.shape[1] + if (x.shape.dimensions.last() != k) return null + val resident = residentDenseWeight(weight, n.toLong() * k) ?: return null + val activation = heapActivation(x) ?: return null + val m = if (k == 0) 0 else x.shape.volume / k + val out = FloatArray(m * n) + if (m > 0 && n > 0) kernel.matmulWt(activation.first, activation.second, resident.first, resident.second, out, 0, m, n, k) + val outShape = if (x.rank == 1) Shape(n) else Shape(*(x.shape.dimensions.copyOf(x.rank - 1) + n)) + val outData = dataFactory.adoptFloatArray(outShape, x.dtype, out) as TensorData + return newTensor(outData, x.dtype, x, weight) + } + + /** + * The activation's floats and their offset on the heap; a dense segment-backed activation is + * copied (it is `m × k`, small). `MemorySegmentTensorData` specifically, not the marker + * interface: the Q4/Q8 segment types implement that too and hold packed bytes, not floats. + */ + private fun heapActivation(x: Tensor<*, *>): Pair? = when (val d = x.data) { + is FloatArrayTensorData<*> -> d.buffer to 0 + is MemorySegmentTensorData<*> -> { + val count = x.shape.volume + val arr = FloatArray(count) + java.lang.foreign.MemorySegment.copy(d.segment, java.lang.foreign.ValueLayout.JAVA_FLOAT, d.segmentByteOffset, arr, 0, count) + arr to 0 + } + else -> null + } + + /** The weight's `floats` floats as an off-heap segment and byte offset: its own segment, or the resident copy of its heap array. */ + private fun residentDenseWeight(weight: Tensor<*, *>, floats: Long): Pair? { + val bytes = floats * java.lang.Float.BYTES + when (val d = weight.data) { + is MemorySegmentTensorData<*> -> { + if (d.segmentByteOffset + bytes > d.segment.byteSize()) return null + return d.segment to d.segmentByteOffset + } + is FloatArrayTensorData<*> -> { + if (d.buffer.size.toLong() < floats) return null + synchronized(residentDenseWeights) { + residentDenseWeights.firstOrNull { it.first === d }?.let { return it.second to 0L } + val seg = Arena.ofAuto().allocate(maxOf(bytes, 4L), 64L) + if (floats > 0) { + java.lang.foreign.MemorySegment.copy(d.buffer, 0, seg, java.lang.foreign.ValueLayout.JAVA_FLOAT, 0L, floats.toInt()) + } + if (residentDenseWeights.size >= RESIDENT_DENSE_CACHE_LIMIT) residentDenseWeights.removeAt(0) + residentDenseWeights.add(Pair(d, seg)) + return seg to 0L + } + } + else -> return null + } + } + /** * Below this many multiply-accumulates a dense FP32 matmul is faster done directly than handed * to the tile-blocked SPI kernel, whose per-call setup dominates at these sizes. Sized to cover diff --git a/skainet-backends/skainet-backend-native-cpu/native/CMakeLists.txt b/skainet-backends/skainet-backend-native-cpu/native/CMakeLists.txt index b85ed75a..53cc1c10 100644 --- a/skainet-backends/skainet-backend-native-cpu/native/CMakeLists.txt +++ b/skainet-backends/skainet-backend-native-cpu/native/CMakeLists.txt @@ -26,6 +26,7 @@ set(SKAINET_KERNEL_SOURCES src/q5_0_matmul.c src/q5_1_matmul.c src/skainet_ternary_f32.c + src/f32_ops.c ) # Vendored NeoGPU ternary LUT kernel (MIT, verbatim — src/vendor/neogpu/). diff --git a/skainet-backends/skainet-backend-native-cpu/native/include/skainet_kernels.h b/skainet-backends/skainet-backend-native-cpu/native/include/skainet_kernels.h index 60663bfc..a5a19afa 100644 --- a/skainet-backends/skainet-backend-native-cpu/native/include/skainet_kernels.h +++ b/skainet-backends/skainet-backend-native-cpu/native/include/skainet_kernels.h @@ -426,6 +426,10 @@ SKAINET_API void skainet_q5_1_matmul( * unpacking, after which `sdot` accumulates sixteen products per instruction * where the core has ARMv8.2 dotprod. * + * The Emscripten sidecar runs the same block in SIMD128 (`i32x4.dot_i16x8_s` on + * widened halves). Output rows are split over the shared row pool once there + * are enough of them (#1195 pattern); bit-identical to a single thread. + * * @param activation int8 codes of one token, `input_dim` of them * @param activation_scale the token's absmax scale (`absmax / 127`) * @param weight canonical TQ2_0 blocks, row-major per output row @@ -454,9 +458,10 @@ SKAINET_API void skainet_bitnet_gemv_tq2_0( * input_dim must be a multiple of 4. Unlike the int8 `bitnet_gemv` path * there is no activation quantization: results are exact. Backed by the * vendored NeoGPU LUT kernel (baseline NEON, no dotprod — the fast path for - * Cortex-A72/Pi-4 class cores); it threads internally with pthreads once - * output_dim >= 512. A portable scalar build stands in where the vendored - * file cannot compile (MSVC). + * Cortex-A72/Pi-4 class cores), driven from the shared row pool. Where the + * vendored file cannot compile (MSVC, the Emscripten sidecar) a portable + * mirror with the same compile-time LUT stands in — scalar on MSVC, SIMD128 + * in the sidecar — threaded over output rows through the same pool. */ SKAINET_API void skainet_ternary_f32_gemv( const float* input, int32_t input_offset, @@ -477,7 +482,9 @@ SKAINET_API void skainet_ternary_f32_gemv( * plane_stride_bytes == output_dim * input_dim / 4. row_scale holds raw * little-endian IEEE binary16 bit patterns, one per output row (sign * ignored — encoders store max|row| >= 0). input_dim must be a multiple - * of 4. Threads internally with pthreads at any output_dim. + * of 4. The vendored kernel threads internally with pthreads at any + * output_dim; the portable mirror (MSVC, Emscripten) threads over output + * rows through the shared row pool. */ SKAINET_API void skainet_ternary_lmhead_stage1( const float* input, int32_t input_offset, @@ -503,6 +510,36 @@ SKAINET_API void skainet_fp32_matmul_wt( int32_t m, int32_t n, int32_t k ); +/* + * Dense FP32 elementwise, activation and reduction kernels (SKEEP-007 resident + * activations; see src/f32_ops.c for the contracts). Operands are contiguous. + * + * skainet_f32_binary: out[i] = a[ia] op b[ib], op ∈ {0 add, 1 sub, 2 mul, 3 div}; + * a_mode / b_mode ∈ {0 full (ia = i), 1 scalar (ia = 0), 2 bias (ia = i % inner)}. + * skainet_f32_unary: out[i] = f(in[i]), f ∈ {0 relu, 1 sigmoid, 2 silu, + * 3 gelu (tanh form), 4 gelu (erf form), 5 erf, 6 tanh}. + * skainet_f32_reduce_all: *out = Σ in[0..n) (/ n when mean != 0). + * skainet_f32_reduce_axis: out[o*inner + x] = Σ_k in[(o*red + k)*inner + x] + * (/ red when mean != 0). + * + * Threaded over chunks of the output through the shared row pool; per-element + * results do not depend on the partition. + */ +SKAINET_API void skainet_f32_binary( + int32_t op, + const float* a, int32_t a_mode, + const float* b, int32_t b_mode, + float* out, int32_t n, int32_t inner +); + +SKAINET_API void skainet_f32_unary(int32_t op, const float* in, float* out, int32_t n); + +SKAINET_API void skainet_f32_reduce_all(const float* in, int32_t n, int32_t mean, float* out); + +SKAINET_API void skainet_f32_reduce_axis( + const float* in, int32_t outer, int32_t red, int32_t inner, int32_t mean, float* out +); + #ifdef __cplusplus } #endif diff --git a/skainet-backends/skainet-backend-native-cpu/native/src/bitnet_gemv.c b/skainet-backends/skainet-backend-native-cpu/native/src/bitnet_gemv.c index e9144287..2f187817 100644 --- a/skainet-backends/skainet-backend-native-cpu/native/src/bitnet_gemv.c +++ b/skainet-backends/skainet-backend-native-cpu/native/src/bitnet_gemv.c @@ -1,5 +1,6 @@ #include "skainet_kernels.h" #include "skainet_simd.h" +#include "skainet_row_threads.h" #include #include @@ -31,6 +32,17 @@ * than it saves, and a checkpoint that is going to be run through this kernel * ships as TQ2_0. TQ1_0's base-3 packing is likewise scalar — it is a storage * format, not a runtime one. + * + * The Emscripten sidecar has the same block body in SIMD128: the unpacking is + * identical (shift, mask) and the sixteen int8 products go through + * `i32x4.dot_i16x8_s` on widened halves, the stand-in for `sdot` every other + * int8 kernel in the sidecar uses. + * + * Output rows are independent, so they are split over the shared row pool + * (skainet_row_threads.h) when there are enough of them — the mt sidecar's + * pthreads in a browser, the native pool elsewhere. Per-row arithmetic never + * changes with the partition, so the result is bit-identical to a single + * thread's. */ #define SKAINET_TQ2_0_BLOCK_SIZE 256 @@ -160,7 +172,76 @@ static inline int32_t skainet_tq2_0_block_neon( return vaddvq_s32(acc); } -#endif /* SKAINET_HAVE_NEON */ +#define skainet_tq2_0_block_simd skainet_tq2_0_block_neon +#elif defined(SKAINET_HAVE_WASM_SIMD128) +/* + * The NEON block in SIMD128: the same two chunks × four bit pairs, codes kept in + * {0,1,2} with the Σ a bias removed by the caller. `wasm_u8x16_shr` takes a + * runtime shift, so the strips can loop over the bit pair. + */ +static inline int32_t skainet_tq2_0_block_wasm( + const uint8_t* SKAINET_RESTRICT qs, + const int8_t* SKAINET_RESTRICT act) { + const v128_t mask = wasm_u8x16_splat(3); + v128_t acc = wasm_i32x4_splat(0); + for (int32_t c = 0; c < 2; ++c) { + const v128_t lo = wasm_v128_load(qs + c * 32); + const v128_t hi = wasm_v128_load(qs + c * 32 + 16); + for (int32_t l = 0; l < 4; ++l) { + const v128_t wlo = wasm_v128_and(wasm_u8x16_shr(lo, (uint32_t) (2 * l)), mask); + const v128_t whi = wasm_v128_and(wasm_u8x16_shr(hi, (uint32_t) (2 * l)), mask); + const int8_t* a = act + c * 128 + l * 32; + acc = wasm_i32x4_add(acc, skainet_wasm_dot_u8x16_i8x16(wlo, wasm_v128_load(a))); + acc = wasm_i32x4_add(acc, skainet_wasm_dot_u8x16_i8x16(whi, wasm_v128_load(a + 16))); + } + } + return skainet_wasm_hadd_i32(acc); +} +#define skainet_tq2_0_block_simd skainet_tq2_0_block_wasm +#endif /* SKAINET_HAVE_NEON / SKAINET_HAVE_WASM_SIMD128 */ + +typedef struct { + const int8_t* act; + const uint8_t* w; + const int32_t* activation_sums; + float* out; + float activation_scale; + int32_t input_dim; + int32_t blocks_per_row; +} skainet_bitnet_gemv_job; + +/* Output rows [o_start, o_end): every block of the row, scaled and summed. */ +static void skainet_bitnet_gemv_rows(void* ctx, int32_t o_start, int32_t o_end) { + const skainet_bitnet_gemv_job* j = (const skainet_bitnet_gemv_job*) ctx; + const int8_t* act = j->act; + const int32_t input_dim = j->input_dim; + const int32_t blocks_per_row = j->blocks_per_row; + for (int32_t o = o_start; o < o_end; ++o) { + float sum = 0.0f; + for (int32_t b = 0; b < blocks_per_row; ++b) { + const uint8_t* block = j->w + (size_t)(o * blocks_per_row + b) * SKAINET_TQ2_0_BYTES_PER_BLOCK; + const int32_t first = b * SKAINET_TQ2_0_BLOCK_SIZE; + const int32_t count = (input_dim - first) < SKAINET_TQ2_0_BLOCK_SIZE + ? (input_dim - first) + : SKAINET_TQ2_0_BLOCK_SIZE; + uint16_t scale_bits; + memcpy(&scale_bits, block + 64, sizeof(scale_bits)); + const float d = skainet_bitnet_fp16(scale_bits); + int32_t partial; +#ifdef skainet_tq2_0_block_simd + if (count == SKAINET_TQ2_0_BLOCK_SIZE) { + partial = skainet_tq2_0_block_simd(block, act + first) - j->activation_sums[b]; + } else { + partial = skainet_tq2_0_block_scalar(block, act + first, count); + } +#else + partial = skainet_tq2_0_block_scalar(block, act + first, count); +#endif + sum += (float)partial * d; + } + j->out[o] = sum * j->activation_scale; + } +} SKAINET_API void skainet_bitnet_gemv_tq2_0( const int8_t* SKAINET_RESTRICT activation, int32_t activation_offset, @@ -203,30 +284,14 @@ SKAINET_API void skainet_bitnet_gemv_tq2_0( activation_sums[b] = s; } - for (int32_t o = 0; o < output_dim; ++o) { - float sum = 0.0f; - for (int32_t b = 0; b < blocks_per_row; ++b) { - const uint8_t* block = w + (size_t)(o * blocks_per_row + b) * SKAINET_TQ2_0_BYTES_PER_BLOCK; - const int32_t first = b * SKAINET_TQ2_0_BLOCK_SIZE; - const int32_t count = (input_dim - first) < SKAINET_TQ2_0_BLOCK_SIZE - ? (input_dim - first) - : SKAINET_TQ2_0_BLOCK_SIZE; - uint16_t scale_bits; - memcpy(&scale_bits, block + 64, sizeof(scale_bits)); - const float d = skainet_bitnet_fp16(scale_bits); - int32_t partial; -#if defined(SKAINET_HAVE_NEON) - if (count == SKAINET_TQ2_0_BLOCK_SIZE) { - partial = skainet_tq2_0_block_neon(block, act + first) - activation_sums[b]; - } else { - partial = skainet_tq2_0_block_scalar(block, act + first, count); - } -#else - partial = skainet_tq2_0_block_scalar(block, act + first, count); -#endif - sum += (float)partial * d; - } - output[output_offset + o] = sum * activation_scale; - } + skainet_bitnet_gemv_job job; + job.act = act; + job.w = w; + job.activation_sums = activation_sums; + job.out = output + output_offset; + job.activation_scale = activation_scale; + job.input_dim = input_dim; + job.blocks_per_row = blocks_per_row; + skainet_run_rows(skainet_bitnet_gemv_rows, &job, output_dim); free(heap_sums); } diff --git a/skainet-backends/skainet-backend-native-cpu/native/src/f32_ops.c b/skainet-backends/skainet-backend-native-cpu/native/src/f32_ops.c new file mode 100644 index 00000000..75336783 --- /dev/null +++ b/skainet-backends/skainet-backend-native-cpu/native/src/f32_ops.c @@ -0,0 +1,335 @@ +#include "skainet_kernels.h" +#include "skainet_simd.h" +#include "skainet_row_threads.h" + +#include +#include +#include + +/* + * Dense FP32 elementwise, activation and reduction kernels (SKEEP-007 resident activations). + * + * These exist for the wasm tier first: Kotlin/Wasm has no SIMD and no shared-memory threads, so + * everything between two matmuls of a browser forward pass — bias add, GELU, residual add, the + * reductions of a norm — ran as scalar Kotlin on one thread while the matmuls ran in the SIMD128 + * sidecar. With these exports the activations can stay in the sidecar's linear memory from one + * op to the next (`Storage.WasmLinear`) and only cross the boundary when something outside the + * sidecar needs them. They are compiled into every native build as well, so a JVM/Android/K-N + * binding is a few lines when wanted; the JVM has Vector API bodies for all of them today. + * + * Contracts (all operands contiguous): + * + * skainet_f32_binary(op, a, a_mode, b, b_mode, out, n, inner) + * out[i] = a[ia] (op) b[ib] for i in [0, n), where an operand's index follows its mode: + * SKAINET_F32_FULL ia = i (same shape as the output) + * SKAINET_F32_SCALAR ia = 0 (a single value broadcast over the output) + * SKAINET_F32_BIAS ia = i % inner (a vector over the last dimension, `inner` long) + * — the three broadcast shapes the common ops layer takes on its fast path (same shape, + * scalar, last-dim "bias"); anything else is the caller's generic path. + * + * skainet_f32_unary(op, in, out, n) + * out[i] = f(in[i]) with f one of relu, sigmoid, silu, gelu (tanh form), gelu (erf form), + * erf, tanh. The formulas are those of the Kotlin reference ops, so results agree to the + * last-ulp differences between libm and the Kotlin math functions. The transcendental ones are + * scalar libm calls (no vector libm in wasm or portable C); relu has SIMD bodies. + * + * skainet_f32_reduce_all(in, n, mean, out) *out = Σ in[i], divided by n when mean != 0 + * skainet_f32_reduce_axis(in, outer, red, inner, mean, out) + * out[o * inner + x] = Σ_k in[(o * red + k) * inner + x] (/ red when mean != 0) + * — the (outer, reduced, inner) decomposition of a reduction over one axis. + * + * Threading: the work is split into fixed-size chunks of output elements (rows for the axis + * reduction) and handed to the shared row pool when there are enough of them + * (skainet_row_threads.h), so a 1M-element op uses the mt sidecar's pthreads and a 768-wide bias + * add stays on the caller. Per-element results do not depend on the partition. The full + * reduction accumulates in four lanes, so its rounding differs from a sequential sum in the last + * bits, as the JVM Vector API path's does. + */ + +#define SKAINET_F32_FULL 0 +#define SKAINET_F32_SCALAR 1 +#define SKAINET_F32_BIAS 2 + +#define SKAINET_F32_ADD 0 +#define SKAINET_F32_SUB 1 +#define SKAINET_F32_MUL 2 +#define SKAINET_F32_DIV 3 + +#define SKAINET_F32_RELU 0 +#define SKAINET_F32_SIGMOID 1 +#define SKAINET_F32_SILU 2 +#define SKAINET_F32_GELU_TANH 3 +#define SKAINET_F32_GELU_EXACT 4 +#define SKAINET_F32_ERF 5 +#define SKAINET_F32_TANH 6 + +/* Output elements per pool "row": the pool threads at 512 rows, so 1024 → 512K elements. */ +#define SKAINET_F32_BINARY_CHUNK 1024 +/* The transcendental unaries cost ~20 ns a lane in scalar libm; thread earlier. */ +#define SKAINET_F32_UNARY_CHUNK 256 + +/* ---------------------------------------------------------------- binary */ + +typedef struct { + const float* a; + const float* b; + float* out; + int32_t n, inner; + int32_t op, a_mode, b_mode; +} skainet_f32_binary_ctx; + +/* The two SIMD shapes: lane-wise a[i] (op) b[i], and lane-wise a[i] (op) splat. */ +#if defined(SKAINET_HAVE_WASM_SIMD128) +#define SKAINET_F32_VEC v128_t +#define SKAINET_F32_LOAD(p) wasm_v128_load(p) +#define SKAINET_F32_STORE(p, v) wasm_v128_store((p), (v)) +#define SKAINET_F32_SPLAT(x) wasm_f32x4_splat(x) +#define SKAINET_F32_VADD wasm_f32x4_add +#define SKAINET_F32_VSUB wasm_f32x4_sub +#define SKAINET_F32_VMUL wasm_f32x4_mul +#define SKAINET_F32_VDIV wasm_f32x4_div +#define SKAINET_F32_VMAX wasm_f32x4_max +#define SKAINET_F32_HAVE_VEC 1 +#elif defined(SKAINET_HAVE_NEON) +#define SKAINET_F32_VEC float32x4_t +#define SKAINET_F32_LOAD(p) vld1q_f32(p) +#define SKAINET_F32_STORE(p, v) vst1q_f32((p), (v)) +#define SKAINET_F32_SPLAT(x) vdupq_n_f32(x) +#define SKAINET_F32_VADD vaddq_f32 +#define SKAINET_F32_VSUB vsubq_f32 +#define SKAINET_F32_VMUL vmulq_f32 +#define SKAINET_F32_VDIV vdivq_f32 +#define SKAINET_F32_VMAX vmaxq_f32 +#define SKAINET_F32_HAVE_VEC 1 +#endif + +static inline float skainet_f32_apply(int32_t op, float x, float y) { + switch (op) { + case SKAINET_F32_ADD: return x + y; + case SKAINET_F32_SUB: return x - y; + case SKAINET_F32_MUL: return x * y; + default: return x / y; + } +} + +#ifdef SKAINET_F32_HAVE_VEC +static inline SKAINET_F32_VEC skainet_f32_vapply(int32_t op, SKAINET_F32_VEC x, SKAINET_F32_VEC y) { + switch (op) { + case SKAINET_F32_ADD: return SKAINET_F32_VADD(x, y); + case SKAINET_F32_SUB: return SKAINET_F32_VSUB(x, y); + case SKAINET_F32_MUL: return SKAINET_F32_VMUL(x, y); + default: return SKAINET_F32_VDIV(x, y); + } +} +#endif + +/* out[i0..i1) = a[i0..i1) (op) b[i0..i1): both full. */ +static void skainet_f32_binary_full(int32_t op, const float* SKAINET_RESTRICT a, const float* SKAINET_RESTRICT b, + float* SKAINET_RESTRICT out, int32_t i0, int32_t i1) { + int32_t i = i0; +#ifdef SKAINET_F32_HAVE_VEC + for (; i + 4 <= i1; i += 4) { + SKAINET_F32_STORE(out + i, skainet_f32_vapply(op, SKAINET_F32_LOAD(a + i), SKAINET_F32_LOAD(b + i))); + } +#endif + for (; i < i1; ++i) out[i] = skainet_f32_apply(op, a[i], b[i]); +} + +/* out[i0..i1) = a[i0..i1) (op) s, or s (op) a[i0..i1) when `swap`. */ +static void skainet_f32_binary_scalar(int32_t op, const float* SKAINET_RESTRICT a, float s, int swap, + float* SKAINET_RESTRICT out, int32_t i0, int32_t i1) { + int32_t i = i0; +#ifdef SKAINET_F32_HAVE_VEC + const SKAINET_F32_VEC vs = SKAINET_F32_SPLAT(s); + for (; i + 4 <= i1; i += 4) { + const SKAINET_F32_VEC va = SKAINET_F32_LOAD(a + i); + SKAINET_F32_STORE(out + i, swap ? skainet_f32_vapply(op, vs, va) : skainet_f32_vapply(op, va, vs)); + } +#endif + for (; i < i1; ++i) out[i] = swap ? skainet_f32_apply(op, s, a[i]) : skainet_f32_apply(op, a[i], s); +} + +static void skainet_f32_binary_chunks(void* vctx, int32_t c0, int32_t c1) { + const skainet_f32_binary_ctx* c = (const skainet_f32_binary_ctx*) vctx; + const int32_t i0 = c0 * SKAINET_F32_BINARY_CHUNK; + const int32_t i1 = (c1 * SKAINET_F32_BINARY_CHUNK < c->n) ? c1 * SKAINET_F32_BINARY_CHUNK : c->n; + if (c->a_mode == SKAINET_F32_FULL && c->b_mode == SKAINET_F32_FULL) { + skainet_f32_binary_full(c->op, c->a, c->b, c->out, i0, i1); + return; + } + if (c->a_mode == SKAINET_F32_FULL && c->b_mode == SKAINET_F32_SCALAR) { + skainet_f32_binary_scalar(c->op, c->a, c->b[0], 0, c->out, i0, i1); + return; + } + if (c->a_mode == SKAINET_F32_SCALAR && c->b_mode == SKAINET_F32_FULL) { + skainet_f32_binary_scalar(c->op, c->b, c->a[0], 1, c->out, i0, i1); + return; + } + if (c->a_mode == SKAINET_F32_FULL && c->b_mode == SKAINET_F32_BIAS) { + /* Walk the chunk row by row of the last dimension so the bias is read contiguously. */ + int32_t i = i0; + while (i < i1) { + const int32_t x = i % c->inner; + const int32_t run = (c->inner - x < i1 - i) ? c->inner - x : i1 - i; + skainet_f32_binary_full(c->op, c->a + i, c->b + x, c->out + i, 0, run); + i += run; + } + return; + } + if (c->a_mode == SKAINET_F32_BIAS && c->b_mode == SKAINET_F32_FULL) { + int32_t i = i0; + while (i < i1) { + const int32_t x = i % c->inner; + const int32_t run = (c->inner - x < i1 - i) ? c->inner - x : i1 - i; + skainet_f32_binary_full(c->op, c->a + x, c->b + i, c->out + i, 0, run); + i += run; + } + return; + } + /* Remaining mode pairs (scalar×scalar, bias×bias, scalar×bias): index each side by its mode. */ + for (int32_t i = i0; i < i1; ++i) { + const int32_t ia = c->a_mode == SKAINET_F32_FULL ? i : (c->a_mode == SKAINET_F32_SCALAR ? 0 : i % c->inner); + const int32_t ib = c->b_mode == SKAINET_F32_FULL ? i : (c->b_mode == SKAINET_F32_SCALAR ? 0 : i % c->inner); + c->out[i] = skainet_f32_apply(c->op, c->a[ia], c->b[ib]); + } +} + +SKAINET_API void skainet_f32_binary( + int32_t op, + const float* a, int32_t a_mode, + const float* b, int32_t b_mode, + float* out, int32_t n, int32_t inner +) { + if (n <= 0) return; + skainet_f32_binary_ctx ctx; + ctx.a = a; ctx.b = b; ctx.out = out; + ctx.n = n; + ctx.inner = inner > 0 ? inner : 1; + ctx.op = op; ctx.a_mode = a_mode; ctx.b_mode = b_mode; + skainet_run_rows(skainet_f32_binary_chunks, &ctx, (n + SKAINET_F32_BINARY_CHUNK - 1) / SKAINET_F32_BINARY_CHUNK); +} + +/* ----------------------------------------------------------------- unary */ + +typedef struct { + const float* in; + float* out; + int32_t n; + int32_t op; +} skainet_f32_unary_ctx; + +static inline float skainet_f32_sigmoid(float x) { return 1.0f / (1.0f + expf(-x)); } + +static void skainet_f32_unary_chunks(void* vctx, int32_t c0, int32_t c1) { + const skainet_f32_unary_ctx* c = (const skainet_f32_unary_ctx*) vctx; + const float* SKAINET_RESTRICT in = c->in; + float* SKAINET_RESTRICT out = c->out; + const int32_t i0 = c0 * SKAINET_F32_UNARY_CHUNK; + const int32_t i1 = (c1 * SKAINET_F32_UNARY_CHUNK < c->n) ? c1 * SKAINET_F32_UNARY_CHUNK : c->n; + switch (c->op) { + case SKAINET_F32_RELU: { + int32_t i = i0; +#ifdef SKAINET_F32_HAVE_VEC + const SKAINET_F32_VEC zero = SKAINET_F32_SPLAT(0.0f); + for (; i + 4 <= i1; i += 4) SKAINET_F32_STORE(out + i, SKAINET_F32_VMAX(SKAINET_F32_LOAD(in + i), zero)); +#endif + for (; i < i1; ++i) out[i] = in[i] < 0.0f ? 0.0f : in[i]; + break; + } + case SKAINET_F32_SIGMOID: + for (int32_t i = i0; i < i1; ++i) out[i] = skainet_f32_sigmoid(in[i]); + break; + case SKAINET_F32_SILU: + for (int32_t i = i0; i < i1; ++i) out[i] = in[i] * skainet_f32_sigmoid(in[i]); + break; + case SKAINET_F32_GELU_TANH: + for (int32_t i = i0; i < i1; ++i) { + const float x = in[i]; + const float inner = x + 0.044715f * (x * x * x); + out[i] = 0.5f * x * (1.0f + tanhf(0.7978845608f * inner)); + } + break; + case SKAINET_F32_GELU_EXACT: + for (int32_t i = i0; i < i1; ++i) { + const double x = (double) in[i]; + out[i] = (float) (0.5 * x * (1.0 + erf(x * 0.70710678118654752440))); + } + break; + case SKAINET_F32_ERF: + for (int32_t i = i0; i < i1; ++i) out[i] = (float) erf((double) in[i]); + break; + default: /* SKAINET_F32_TANH */ + for (int32_t i = i0; i < i1; ++i) out[i] = tanhf(in[i]); + break; + } +} + +SKAINET_API void skainet_f32_unary(int32_t op, const float* in, float* out, int32_t n) { + if (n <= 0) return; + skainet_f32_unary_ctx ctx; + ctx.in = in; ctx.out = out; ctx.n = n; ctx.op = op; + skainet_run_rows(skainet_f32_unary_chunks, &ctx, (n + SKAINET_F32_UNARY_CHUNK - 1) / SKAINET_F32_UNARY_CHUNK); +} + +/* ------------------------------------------------------------- reductions */ + +SKAINET_API void skainet_f32_reduce_all(const float* in, int32_t n, int32_t mean, float* out) { + float s = 0.0f; + if (n > 0) { + int32_t i = 0; +#ifdef SKAINET_F32_HAVE_VEC + SKAINET_F32_VEC acc0 = SKAINET_F32_SPLAT(0.0f), acc1 = acc0, acc2 = acc0, acc3 = acc0; + for (; i + 16 <= n; i += 16) { + acc0 = SKAINET_F32_VADD(acc0, SKAINET_F32_LOAD(in + i)); + acc1 = SKAINET_F32_VADD(acc1, SKAINET_F32_LOAD(in + i + 4)); + acc2 = SKAINET_F32_VADD(acc2, SKAINET_F32_LOAD(in + i + 8)); + acc3 = SKAINET_F32_VADD(acc3, SKAINET_F32_LOAD(in + i + 12)); + } + const SKAINET_F32_VEC acc = SKAINET_F32_VADD(SKAINET_F32_VADD(acc0, acc1), SKAINET_F32_VADD(acc2, acc3)); +#if defined(SKAINET_HAVE_WASM_SIMD128) + s = skainet_wasm_hadd_f32(acc); +#else + s = skainet_neon_hadd_f32(acc); +#endif +#endif + for (; i < n; ++i) s += in[i]; + } + *out = (mean && n > 0) ? s / (float) n : s; +} + +typedef struct { + const float* in; + float* out; + int32_t red, inner; + int32_t mean; +} skainet_f32_reduce_axis_ctx; + +static void skainet_f32_reduce_axis_rows(void* vctx, int32_t o0, int32_t o1) { + const skainet_f32_reduce_axis_ctx* c = (const skainet_f32_reduce_axis_ctx*) vctx; + const int32_t inner = c->inner; + const int32_t red = c->red; + for (int32_t o = o0; o < o1; ++o) { + float* SKAINET_RESTRICT out = c->out + (size_t) o * inner; + const float* SKAINET_RESTRICT base = c->in + (size_t) o * red * inner; + for (int32_t x = 0; x < inner; ++x) out[x] = 0.0f; + for (int32_t k = 0; k < red; ++k) { + const float* SKAINET_RESTRICT row = base + (size_t) k * inner; + skainet_f32_binary_full(SKAINET_F32_ADD, out, row, out, 0, inner); + } + if (c->mean && red > 0) { + const float inv = 1.0f / (float) red; + skainet_f32_binary_scalar(SKAINET_F32_MUL, out, inv, 0, out, 0, inner); + } + } +} + +SKAINET_API void skainet_f32_reduce_axis(const float* in, int32_t outer, int32_t red, int32_t inner, int32_t mean, float* out) { + if (outer <= 0 || inner <= 0) return; + if (red <= 0) { + for (int32_t i = 0; i < outer * inner; ++i) out[i] = 0.0f; + return; + } + skainet_f32_reduce_axis_ctx ctx; + ctx.in = in; ctx.out = out; ctx.red = red; ctx.inner = inner; ctx.mean = mean; + skainet_run_rows(skainet_f32_reduce_axis_rows, &ctx, outer); +} diff --git a/skainet-backends/skainet-backend-native-cpu/native/src/skainet_ternary_f32.c b/skainet-backends/skainet-backend-native-cpu/native/src/skainet_ternary_f32.c index b9cf2824..cdf4015a 100644 --- a/skainet-backends/skainet-backend-native-cpu/native/src/skainet_ternary_f32.c +++ b/skainet-backends/skainet-backend-native-cpu/native/src/skainet_ternary_f32.c @@ -6,10 +6,13 @@ * pthread_once warm-up, so first use is race-free under any threading. * * The vendored file needs pthreads and GNU/Clang builtins, so it is only in - * the build where SKAINET_HAVE_NEOGPU_TERNARY is defined (non-MSVC). The - * fallback branch below is a portable scalar mirror with identical semantics, - * including the byte-code-3 → +2.0 decode (loaders reject code 3 at import; - * the kernel contract is "garbage in, garbage out", never a crash). + * the build where SKAINET_HAVE_NEOGPU_TERNARY is defined (non-MSVC native + * builds). The other branch below is a portable mirror with identical + * semantics, including the byte-code-3 → +2.0 decode (loaders reject code 3 + * at import; the kernel contract is "garbage in, garbage out", never a + * crash). It is what MSVC and the Emscripten sidecar compile: the same + * 256-entry LUT as a compile-time constant (no init guard to race on), a + * SIMD128 body in the sidecar, and the shared row pool for threading. */ #include "skainet_kernels.h" @@ -108,12 +111,92 @@ void skainet_ternary_lmhead_stage1( (uint32_t)input_dim); } -#else /* !SKAINET_HAVE_NEOGPU_TERNARY — portable scalar mirror (MSVC etc.) */ +#else /* !SKAINET_HAVE_NEOGPU_TERNARY — portable mirror (MSVC, Emscripten) */ -/* decode(byte, lane) = ((byte >> (lane*2)) & 3) - 1, exactly the vendored LUT - * (so byte code 3 yields +2, matching TernaryCodec.decodeBitNet). */ -static float skainet_ternary_decode(uint8_t b, int lane) { - return (float)((int)((b >> (lane * 2)) & 3) - 1); +#include "skainet_simd.h" +#include "skainet_row_threads.h" + +/* + * decode(byte, lane) = ((byte >> (lane*2)) & 3) - 1 — exactly the vendored + * LUT (so byte code 3 yields +2, matching TernaryCodec.decodeBitNet), as a + * compile-time constant: one 16-byte row per weight byte, the four decoded + * codes of its four elements. The vendored file builds the same table on + * first use behind a non-atomic flag; a constant needs no guard, which is + * what makes the row pool below safe without pthread_once. + */ +#define SKAINET_TERNARY_D(b, lane) ((float) ((int) (((b) >> ((lane) * 2)) & 3) - 1)) +#define SKAINET_TERNARY_E(b) \ + { SKAINET_TERNARY_D(b, 0), SKAINET_TERNARY_D(b, 1), SKAINET_TERNARY_D(b, 2), SKAINET_TERNARY_D(b, 3) } +#define SKAINET_TERNARY_E16(b) \ + SKAINET_TERNARY_E(b + 0), SKAINET_TERNARY_E(b + 1), SKAINET_TERNARY_E(b + 2), SKAINET_TERNARY_E(b + 3), \ + SKAINET_TERNARY_E(b + 4), SKAINET_TERNARY_E(b + 5), SKAINET_TERNARY_E(b + 6), SKAINET_TERNARY_E(b + 7), \ + SKAINET_TERNARY_E(b + 8), SKAINET_TERNARY_E(b + 9), SKAINET_TERNARY_E(b + 10), SKAINET_TERNARY_E(b + 11), \ + SKAINET_TERNARY_E(b + 12), SKAINET_TERNARY_E(b + 13), SKAINET_TERNARY_E(b + 14), SKAINET_TERNARY_E(b + 15) + +static const float skainet_ternary_lut[256][4] = { + SKAINET_TERNARY_E16(0), SKAINET_TERNARY_E16(16), SKAINET_TERNARY_E16(32), SKAINET_TERNARY_E16(48), + SKAINET_TERNARY_E16(64), SKAINET_TERNARY_E16(80), SKAINET_TERNARY_E16(96), SKAINET_TERNARY_E16(112), + SKAINET_TERNARY_E16(128), SKAINET_TERNARY_E16(144), SKAINET_TERNARY_E16(160), SKAINET_TERNARY_E16(176), + SKAINET_TERNARY_E16(192), SKAINET_TERNARY_E16(208), SKAINET_TERNARY_E16(224), SKAINET_TERNARY_E16(240), +}; + +#undef SKAINET_TERNARY_E16 +#undef SKAINET_TERNARY_E +#undef SKAINET_TERNARY_D + +/* FP16 row scale decode, same bit arithmetic as the vendored file (sign + * ignored — encoders store max|row| >= 0). */ +static inline float skainet_ternary_row_scale(uint16_t h16) { + const uint32_t eu = (h16 >> 10) & 0x1Fu; + const uint32_t mu = h16 & 0x03FFu; + const uint32_t fu = ((eu + 112u) << 23) | (mu << 13); + float rsc; + memcpy(&rsc, &fu, 4); + return rsc; +} + +typedef struct { + float* out; + const float* in; + const uint8_t* w; + int32_t row_bytes; +} skainet_ternary_gemv_job; + +/* out[o] = Σ_bi lut[w[o][bi]] · in[bi*4 .. bi*4+3] for rows [o_start, o_end). */ +static void skainet_ternary_gemv_rows(void* ctx, int32_t o_start, int32_t o_end) { + const skainet_ternary_gemv_job* j = (const skainet_ternary_gemv_job*) ctx; + const float* in = j->in; + const int32_t row_bytes = j->row_bytes; + for (int32_t o = o_start; o < o_end; ++o) { + const uint8_t* wrow = j->w + (size_t) o * row_bytes; +#ifdef SKAINET_HAVE_WASM_SIMD128 + /* One LUT row is one f32x4 of decoded codes against four activations: + * a load, a multiply and an add per weight byte. Four accumulators + * keep the adds independent; the vendored NEON body does the same. */ + v128_t acc0 = wasm_f32x4_splat(0.0f), acc1 = acc0, acc2 = acc0, acc3 = acc0; + int32_t bi = 0; + for (; bi + 4 <= row_bytes; bi += 4) { + acc0 = wasm_f32x4_add(acc0, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[wrow[bi]]), wasm_v128_load(in + (size_t) bi * 4))); + acc1 = wasm_f32x4_add(acc1, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[wrow[bi + 1]]), wasm_v128_load(in + (size_t) bi * 4 + 4))); + acc2 = wasm_f32x4_add(acc2, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[wrow[bi + 2]]), wasm_v128_load(in + (size_t) bi * 4 + 8))); + acc3 = wasm_f32x4_add(acc3, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[wrow[bi + 3]]), wasm_v128_load(in + (size_t) bi * 4 + 12))); + } + for (; bi < row_bytes; ++bi) { + acc0 = wasm_f32x4_add(acc0, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[wrow[bi]]), wasm_v128_load(in + (size_t) bi * 4))); + } + j->out[o] = skainet_wasm_hadd_f32(wasm_f32x4_add(wasm_f32x4_add(acc0, acc1), wasm_f32x4_add(acc2, acc3))); +#else + float acc = 0.0f; + for (int32_t bi = 0; bi < row_bytes; ++bi) { + const float* d = skainet_ternary_lut[wrow[bi]]; + acc += d[0] * in[bi * 4 ]; + acc += d[1] * in[bi * 4 + 1]; + acc += d[2] * in[bi * 4 + 2]; + acc += d[3] * in[bi * 4 + 3]; + } + j->out[o] = acc; +#endif + } } void skainet_ternary_f32_gemv( @@ -123,20 +206,76 @@ void skainet_ternary_f32_gemv( float* output, int32_t output_offset) { if (output_dim <= 0) return; - const float* in = input + input_offset; - const uint8_t* w = weight + weight_byte_offset; - const int32_t row_bytes = input_dim / 4; - for (int32_t n = 0; n < output_dim; n++) { - const uint8_t* wrow = w + (size_t)n * row_bytes; - float acc = 0.0f; - for (int32_t bi = 0; bi < row_bytes; bi++) { - const uint8_t b = wrow[bi]; - acc += skainet_ternary_decode(b, 0) * in[bi * 4 ]; - acc += skainet_ternary_decode(b, 1) * in[bi * 4 + 1]; - acc += skainet_ternary_decode(b, 2) * in[bi * 4 + 2]; - acc += skainet_ternary_decode(b, 3) * in[bi * 4 + 3]; + skainet_ternary_gemv_job job = { + output + output_offset, + input + input_offset, + weight + weight_byte_offset, + input_dim / 4, + }; + /* input_dim == 0: row_bytes 0, every row is written as 0.0f. */ + skainet_run_rows(skainet_ternary_gemv_rows, &job, output_dim); +} + +typedef struct { + float* out; + const float* in; + const uint8_t* p0; + const uint8_t* p1; + const uint8_t* p2; + const uint8_t* p3; + const uint16_t* row_scale; + int32_t row_bytes; +} skainet_ternary_lmhead_job; + +/* out[o] = rs[o] · Σ_bi (lut[p0] + lut[p1]/3 + lut[p2]/9 + lut[p3]/27) · in[bi*4 ..]. */ +static void skainet_ternary_lmhead_rows(void* ctx, int32_t o_start, int32_t o_end) { + const skainet_ternary_lmhead_job* j = (const skainet_ternary_lmhead_job*) ctx; + const float* in = j->in; + const int32_t row_bytes = j->row_bytes; + const float w1 = 1.0f / 3.0f, w2 = 1.0f / 9.0f, w3 = 1.0f / 27.0f; + for (int32_t o = o_start; o < o_end; ++o) { + const uint8_t* r0 = j->p0 + (size_t) o * row_bytes; + const uint8_t* r1 = j->p1 + (size_t) o * row_bytes; + const uint8_t* r2 = j->p2 + (size_t) o * row_bytes; + const uint8_t* r3 = j->p3 + (size_t) o * row_bytes; +#ifdef SKAINET_HAVE_WASM_SIMD128 + const v128_t vw1 = wasm_f32x4_splat(w1), vw2 = wasm_f32x4_splat(w2), vw3 = wasm_f32x4_splat(w3); + v128_t acc0 = wasm_f32x4_splat(0.0f), acc1 = acc0; + int32_t bi = 0; + for (; bi + 2 <= row_bytes; bi += 2) { + v128_t u0 = wasm_v128_load(skainet_ternary_lut[r0[bi]]); + u0 = wasm_f32x4_add(u0, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r1[bi]]), vw1)); + u0 = wasm_f32x4_add(u0, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r2[bi]]), vw2)); + u0 = wasm_f32x4_add(u0, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r3[bi]]), vw3)); + acc0 = wasm_f32x4_add(acc0, wasm_f32x4_mul(u0, wasm_v128_load(in + (size_t) bi * 4))); + v128_t u1 = wasm_v128_load(skainet_ternary_lut[r0[bi + 1]]); + u1 = wasm_f32x4_add(u1, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r1[bi + 1]]), vw1)); + u1 = wasm_f32x4_add(u1, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r2[bi + 1]]), vw2)); + u1 = wasm_f32x4_add(u1, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r3[bi + 1]]), vw3)); + acc1 = wasm_f32x4_add(acc1, wasm_f32x4_mul(u1, wasm_v128_load(in + (size_t) bi * 4 + 4))); } - output[output_offset + n] = acc; + for (; bi < row_bytes; ++bi) { + v128_t u = wasm_v128_load(skainet_ternary_lut[r0[bi]]); + u = wasm_f32x4_add(u, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r1[bi]]), vw1)); + u = wasm_f32x4_add(u, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r2[bi]]), vw2)); + u = wasm_f32x4_add(u, wasm_f32x4_mul(wasm_v128_load(skainet_ternary_lut[r3[bi]]), vw3)); + acc0 = wasm_f32x4_add(acc0, wasm_f32x4_mul(u, wasm_v128_load(in + (size_t) bi * 4))); + } + const float s = skainet_wasm_hadd_f32(wasm_f32x4_add(acc0, acc1)); +#else + float s = 0.0f; + for (int32_t bi = 0; bi < row_bytes; ++bi) { + const float* d0 = skainet_ternary_lut[r0[bi]]; + const float* d1 = skainet_ternary_lut[r1[bi]]; + const float* d2 = skainet_ternary_lut[r2[bi]]; + const float* d3 = skainet_ternary_lut[r3[bi]]; + for (int lane = 0; lane < 4; ++lane) { + const float u = d0[lane] + d1[lane] * w1 + d2[lane] * w2 + d3[lane] * w3; + s += u * in[bi * 4 + lane]; + } + } +#endif + j->out[o] = s * skainet_ternary_row_scale(j->row_scale[o]); } } @@ -148,34 +287,18 @@ void skainet_ternary_lmhead_stage1( float* output, int32_t output_offset) { if (output_dim <= 0) return; - const float* in = input + input_offset; const uint8_t* base = planes + planes_byte_offset; - const uint16_t* rs = row_scale + row_scale_offset; - const int32_t row_bytes = input_dim / 4; - const float pw[4] = { 1.0f, 1.0f / 3.0f, 1.0f / 9.0f, 1.0f / 27.0f }; - for (int32_t n = 0; n < output_dim; n++) { - float acc = 0.0f; - for (int32_t bi = 0; bi < row_bytes; bi++) { - for (int lane = 0; lane < 4; lane++) { - float u = 0.0f; - for (int p = 0; p < 4; p++) { - const uint8_t b = - base[(size_t)plane_stride_bytes * p + (size_t)n * row_bytes + bi]; - u += skainet_ternary_decode(b, lane) * pw[p]; - } - acc += u * in[bi * 4 + lane]; - } - } - /* FP16 row scale decode, same bit arithmetic as the vendored file - * (sign ignored — encoders store max|row| >= 0). */ - const uint32_t h16 = rs[n]; - const uint32_t eu = (h16 >> 10) & 0x1Fu; - const uint32_t mu = h16 & 0x03FFu; - const uint32_t fu = ((eu + 112u) << 23) | (mu << 13); - float rsc; - memcpy(&rsc, &fu, 4); - output[output_offset + n] = acc * rsc; - } + skainet_ternary_lmhead_job job = { + output + output_offset, + input + input_offset, + base, + base + (size_t) plane_stride_bytes, + base + (size_t) plane_stride_bytes * 2, + base + (size_t) plane_stride_bytes * 3, + row_scale + row_scale_offset, + input_dim / 4, + }; + skainet_run_rows(skainet_ternary_lmhead_rows, &job, output_dim); } #endif /* SKAINET_HAVE_NEOGPU_TERNARY */ diff --git a/skainet-backends/skainet-backend-native-cpu/src/jvmMain/kotlin/sk/ainet/exec/kernel/NativeFp32MatmulWtKernel.kt b/skainet-backends/skainet-backend-native-cpu/src/jvmMain/kotlin/sk/ainet/exec/kernel/NativeFp32MatmulWtKernel.kt new file mode 100644 index 00000000..1ec68d77 --- /dev/null +++ b/skainet-backends/skainet-backend-native-cpu/src/jvmMain/kotlin/sk/ainet/exec/kernel/NativeFp32MatmulWtKernel.kt @@ -0,0 +1,116 @@ +package sk.ainet.exec.kernel + +import java.lang.foreign.Arena +import java.lang.foreign.FunctionDescriptor +import java.lang.foreign.Linker +import java.lang.foreign.MemorySegment +import java.lang.foreign.ValueLayout +import java.lang.invoke.MethodHandle +import sk.ainet.backend.api.kernel.Fp32MatmulWtKernel +import sk.ainet.backend.api.kernel.Fp32MemSegMatmulWtKernel + +/** + * Native (FFM) `x · Wᵀ` over a row-major `[out, in]` FP32 weight — the JVM binding of + * + * void skainet_fp32_matmul_wt( + * const float* in, int32_t in_offset, + * const float* w, int32_t w_offset, + * float* out, int32_t out_offset, + * int32_t m, int32_t n, int32_t k); + * + * which the wasm sidecar has served since 0.61.0 and the JVM never bound: `DefaultCpuOpsJvm` + * transposed every dense weight once into `[k, n]` for the GEMM kernels and cached the copy. The C + * kernel computes every output as one contiguous dot product over the weight's own row (NEON or + * auto-vectorised portable body, four rows per tile), threads over output rows through the shared + * row pool, and accumulates in ascending `p` — bit-identical to transpose-then-GEMM. + * + * Two faces. The heap face ([Fp32MatmulWtKernel]) stages both operands off-heap per call, like + * [NativeFp32MatmulKernel]; for a decode step that copy is the weight, so it is the slow one. The + * segment face ([Fp32MemSegMatmulWtKernel]) takes the weight where it lies and copies only the + * `m × k` activation and the `m × n` output, which is what the ops layer uses once it has made a + * weight resident off-heap (the JVM counterpart of the sidecar's resident dense weights). + */ +internal object NativeFp32MatmulWtKernel : Fp32MatmulWtKernel, Fp32MemSegMatmulWtKernel { + + fun isAvailable(): Boolean = handle != null + + override fun matmulWt( + x: FloatArray, xOffset: Int, + w: FloatArray, wOffset: Int, + out: FloatArray, outOffset: Int, + m: Int, n: Int, k: Int, + ) { + require(m >= 0 && n >= 0 && k >= 0) { "NativeFp32MatmulWtKernel: m, n, k must be non-negative; got m=$m n=$n k=$k" } + if (m == 0 || n == 0) return + val mh = handle ?: error("NativeFp32MatmulWtKernel invoked while native library unavailable") + val wFloats = n.toLong() * k + require(wOffset >= 0 && wOffset + wFloats <= w.size) { + "NativeFp32MatmulWtKernel: weight needs $wFloats floats from $wOffset, array has ${w.size}" + } + Arena.ofConfined().use { arena -> + val align = ValueLayout.JAVA_FLOAT.byteAlignment() + val wSeg: MemorySegment = if (wFloats > 0) arena.allocate(wFloats * java.lang.Float.BYTES, align) else MemorySegment.NULL + if (wFloats > 0) MemorySegment.copy(w, wOffset, wSeg, ValueLayout.JAVA_FLOAT, 0L, wFloats.toInt()) + invoke(mh, arena, x, xOffset, wSeg, out, outOffset, m, n, k) + } + } + + override fun matmulWt( + x: FloatArray, xOffset: Int, + weight: MemorySegment, weightByteOffset: Long, + out: FloatArray, outOffset: Int, + m: Int, n: Int, k: Int, + ) { + require(m >= 0 && n >= 0 && k >= 0) { "NativeFp32MatmulWtKernel: m, n, k must be non-negative; got m=$m n=$n k=$k" } + if (m == 0 || n == 0) return + val mh = handle ?: error("NativeFp32MatmulWtKernel invoked while native library unavailable") + val wBytes = n.toLong() * k * java.lang.Float.BYTES + require(weightByteOffset >= 0 && weightByteOffset + wBytes <= weight.byteSize()) { + "NativeFp32MatmulWtKernel: weight segment too small — needs $wBytes bytes from offset " + + "$weightByteOffset, segment is ${weight.byteSize()} bytes" + } + Arena.ofConfined().use { arena -> + invoke(mh, arena, x, xOffset, if (wBytes > 0) weight.asSlice(weightByteOffset) else MemorySegment.NULL, out, outOffset, m, n, k) + } + } + + /** Stage the activation and the output, run, copy the output back. The weight is already a segment. */ + private fun invoke( + mh: MethodHandle, arena: Arena, + x: FloatArray, xOffset: Int, wSeg: MemorySegment, + out: FloatArray, outOffset: Int, + m: Int, n: Int, k: Int, + ) { + val xFloats = m.toLong() * k + val outFloats = m.toLong() * n + require(xOffset >= 0 && xOffset + xFloats <= x.size) { + "NativeFp32MatmulWtKernel: activation needs $xFloats floats from $xOffset, array has ${x.size}" + } + require(outOffset >= 0 && outOffset + outFloats <= out.size) { + "NativeFp32MatmulWtKernel: output needs $outFloats floats from $outOffset, array has ${out.size}" + } + val align = ValueLayout.JAVA_FLOAT.byteAlignment() + val xSeg: MemorySegment = if (xFloats > 0) arena.allocate(xFloats * java.lang.Float.BYTES, align) else MemorySegment.NULL + val outSeg: MemorySegment = arena.allocate(outFloats * java.lang.Float.BYTES, align) + if (xFloats > 0) MemorySegment.copy(x, xOffset, xSeg, ValueLayout.JAVA_FLOAT, 0L, xFloats.toInt()) + mh.invoke(xSeg, 0, wSeg, 0, outSeg, 0, m, n, k) + MemorySegment.copy(outSeg, ValueLayout.JAVA_FLOAT, 0L, out, outOffset, outFloats.toInt()) + } + + private val handle: MethodHandle? by lazy { + val lookup = NativeLibraryLoader.lookup() ?: return@lazy null + val symbol = lookup.find("skainet_fp32_matmul_wt").orElse(null) ?: return@lazy null + val descriptor = FunctionDescriptor.ofVoid( + ValueLayout.ADDRESS, // in + ValueLayout.JAVA_INT, // in_offset + ValueLayout.ADDRESS, // w + ValueLayout.JAVA_INT, // w_offset + ValueLayout.ADDRESS, // out + ValueLayout.JAVA_INT, // out_offset + ValueLayout.JAVA_INT, // m + ValueLayout.JAVA_INT, // n + ValueLayout.JAVA_INT, // k + ) + runCatching { Linker.nativeLinker().downcallHandle(symbol, descriptor) }.getOrNull() + } +} diff --git a/skainet-backends/skainet-backend-native-cpu/src/jvmMain/kotlin/sk/ainet/exec/kernel/NativeKernelProvider.kt b/skainet-backends/skainet-backend-native-cpu/src/jvmMain/kotlin/sk/ainet/exec/kernel/NativeKernelProvider.kt index cff68465..08011ba3 100644 --- a/skainet-backends/skainet-backend-native-cpu/src/jvmMain/kotlin/sk/ainet/exec/kernel/NativeKernelProvider.kt +++ b/skainet-backends/skainet-backend-native-cpu/src/jvmMain/kotlin/sk/ainet/exec/kernel/NativeKernelProvider.kt @@ -3,6 +3,8 @@ package sk.ainet.exec.kernel import sk.ainet.backend.api.kernel.Bf16MatmulKernel import sk.ainet.backend.api.kernel.Fp16MatmulKernel import sk.ainet.backend.api.kernel.Fp32MatmulKernel +import sk.ainet.backend.api.kernel.Fp32MatmulWtKernel +import sk.ainet.backend.api.kernel.Fp32MemSegMatmulWtKernel import sk.ainet.backend.api.kernel.KernelProvider import sk.ainet.backend.api.kernel.MemSegKernelProvider import sk.ainet.backend.api.kernel.Q4KMatmulKernel @@ -82,6 +84,9 @@ import sk.ainet.backend.api.kernel.Q8_0MatmulKernel * Every narrow-float accessor the SPI declares is wired here; a format * served natively on one side and by the JVM fallback on the other looks * like a slow kernel rather than a missing one. + * - Now: the direct `x · Wᵀ` kernel (`skainet_fp32_matmul_wt`) in + * [matmulFp32Wt] and its segment face [matmulFp32WtMemSeg], so a dense + * `[out, in]` weight is multiplied in place instead of transposed and cached. */ public object NativeKernelProvider : KernelProvider, MemSegKernelProvider { override val name: String = "native-ffm" @@ -92,6 +97,12 @@ public object NativeKernelProvider : KernelProvider, MemSegKernelProvider { override fun matmulFp32(): Fp32MatmulKernel? = if (NativeFp32MatmulKernel.isAvailable()) NativeFp32MatmulKernel else null + override fun matmulFp32Wt(): Fp32MatmulWtKernel? = + if (NativeFp32MatmulWtKernel.isAvailable()) NativeFp32MatmulWtKernel else null + + override fun matmulFp32WtMemSeg(): Fp32MemSegMatmulWtKernel? = + if (NativeFp32MatmulWtKernel.isAvailable()) NativeFp32MatmulWtKernel else null + override fun matmulQ4K(): Q4KMatmulKernel? = if (NativeQ4KMatmulKernel.isAvailable()) NativeQ4KMatmulKernel else null diff --git a/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/JvmDirectWeightTransposedTest.kt b/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/JvmDirectWeightTransposedTest.kt new file mode 100644 index 00000000..80662290 --- /dev/null +++ b/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/JvmDirectWeightTransposedTest.kt @@ -0,0 +1,79 @@ +package sk.ainet.exec.kernel + +import kotlin.math.abs +import kotlin.random.Random +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import sk.ainet.backend.api.kernel.KernelRegistry +import sk.ainet.backend.api.kernel.KernelServiceLoader +import sk.ainet.context.DirectCpuExecutionContext +import sk.ainet.lang.tensor.Shape +import sk.ainet.lang.tensor.Tensor +import sk.ainet.lang.tensor.data.MemorySegmentBackedData +import sk.ainet.lang.tensor.data.MemorySegmentTensorDataFactory +import sk.ainet.lang.types.FP32 + +/** + * `x · Wᵀ` on the JVM ops layer with a dense `[out, in]` weight goes through the native direct + * kernel (`skainet_fp32_matmul_wt`) when the FFM provider is loaded — heap weights after one + * resident off-heap copy, segment-backed weights where they lie — and agrees with the + * transpose-then-matmul result it replaces, for every activation rank a `Linear` layer sees. + */ +class JvmDirectWeightTransposedTest { + + @BeforeTest + fun setUp() { + KernelRegistry.clearForTesting() + KernelServiceLoader.installAll() + assertTrue(NativeFp32MatmulWtKernel.isAvailable(), "bundled libskainet_kernels must resolve") + } + + @AfterTest + fun tearDown() = KernelRegistry.clearForTesting() + + private fun assertClose(expected: FloatArray, actual: FloatArray, what: String) { + assertEquals(expected.size, actual.size, "$what size") + var maxAbs = 0f + for (v in expected) maxAbs = maxOf(maxAbs, abs(v)) + val tol = maxAbs * 1e-5f + 1e-6f + for (i in expected.indices) { + assertTrue(abs(expected[i] - actual[i]) <= tol, "$what[$i]: ${actual[i]} vs ${expected[i]} (tol $tol)") + } + } + + private fun check(ctx: DirectCpuExecutionContext, xShape: Shape, n: Int, seed: Int, what: String) { + val rng = Random(seed) + val k = xShape.dimensions.last() + val x: Tensor = ctx.fromFloatArray(xShape, FP32::class, FloatArray(xShape.volume) { rng.nextFloat() - 0.5f }) + val w: Tensor = ctx.fromFloatArray(Shape(n, k), FP32::class, FloatArray(n * k) { rng.nextFloat() - 0.5f }) + val got = ctx.ops.matmulWeightTransposed(x, w) + val expectedShape = if (xShape.rank == 1) Shape(n) else Shape(*(xShape.dimensions.copyOf(xShape.rank - 1) + n)) + assertEquals(expectedShape, got.shape, "$what shape") + val expected = ctx.ops.matmul(x, ctx.ops.transpose(w)).data.copyToFloatArray() + assertClose(expected, got.data.copyToFloatArray(), what) + // A second call reuses the resident weight: same answer. + assertClose(expected, ctx.ops.matmulWeightTransposed(x, w).data.copyToFloatArray(), "$what again") + } + + @Test + fun heap_weights_match_transpose_then_matmul_for_every_activation_rank() { + val ctx = DirectCpuExecutionContext() + assertEquals("native-ffm", KernelRegistry.bestAvailable()?.name, "the FFM provider must win on this runner") + check(ctx, Shape(40), 70, 1, "rank-1") + check(ctx, Shape(3, 40), 70, 2, "rank-2") + check(ctx, Shape(2, 3, 40), 600, 3, "rank-3, threaded rows") + check(ctx, Shape(1, 1), 1, 4, "1×1") + } + + @Test + fun segment_backed_weights_are_read_where_they_lie() { + val ctx = DirectCpuExecutionContext(tensorDataFactory = MemorySegmentTensorDataFactory()) + val w: Tensor = ctx.fromFloatArray(Shape(5, 8), FP32::class, FloatArray(40) { it.toFloat() }) + assertTrue(w.data is MemorySegmentBackedData, "this factory stages tensors off-heap: ${w.data::class.simpleName}") + check(ctx, Shape(4, 32), 48, 5, "segment-backed") + check(ctx, Shape(32), 520, 6, "segment-backed rank-1, threaded rows") + } +} diff --git a/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/KernelSupportMatrixTest.kt b/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/KernelSupportMatrixTest.kt index 84bf97d5..ce2fc048 100644 --- a/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/KernelSupportMatrixTest.kt +++ b/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/KernelSupportMatrixTest.kt @@ -4,6 +4,7 @@ import java.io.File import kotlin.test.AfterTest import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue import sk.ainet.backend.api.kernel.KernelDispatch import sk.ainet.backend.api.kernel.KernelProvider import sk.ainet.lang.memory.plan.StorageCapabilities @@ -106,6 +107,34 @@ class KernelSupportMatrixTest { Tier("ffm-rowmajor", 100, setOf("JVM"), KernelDispatch.mappedServableEncodings().map { it.name }.toSet()), ) + /** + * Kernel packs (view dispatch): the ternary formats and the direct dense `x · Wᵀ` are not served + * through the `matmul` accessors the tables above introspect — the ternary kernels are + * `ViewKernelPack`s keyed in `KernelDispatch` (`FfmTernaryKernelPackFactory`, the JNI ternary pack, + * `NativeKnTernaryF32Gemv` / `NativeKnTernaryLmhead`, `WasmTernaryKernelPack`), and `x · Wᵀ` is the + * `matmulFp32Wt` accessor the ops layer consults before transposing a weight. Hand-declared per + * platform like the Android rows; the JVM cells are gated below against what the FFM provider and + * pack actually expose on this runner. Row names are the encodings as `TensorEncoding.name` spells + * them, plus the dense direct product. + */ + private val packRows = listOf( + TensorEncoding.BITNET_B1_58.name + " (FP32 activations)", + TensorEncoding.BITNET_PLANES.name, + TensorEncoding.TQ2_0.name + " (int8 activations)", + "Float32 x·Wᵀ direct", + ) + + private fun packTiers(): List { + val b158 = packRows[0]; val planes = packRows[1]; val tq2 = packRows[2]; val wt = packRows[3] + return listOf( + Tier("ffm-ternary", 100, setOf("JVM"), setOf(b158, planes)), + Tier("native-ffm", 100, setOf("JVM"), setOf(wt)), + Tier("native-jni", 100, setOf("Android"), setOf(b158, planes, tq2)), + Tier("native-cinterop", 100, setOf("Native·linux", "Native·apple"), setOf(b158, planes)), + Tier("wasm-simd128", 50, setOf("JS/WASM"), setOf(b158, planes, tq2, wt)), + ) + } + private fun best(fmt: String, platform: String, tiers: List): String? = tiers.filter { platform in it.platforms && fmt in it.formats }.maxByOrNull { it.priority }?.name @@ -145,6 +174,15 @@ class KernelSupportMatrixTest { .append(cells.joinToString(", ")).append("}}") sb.append(if (i == residentFormats.lastIndex) "\n" else ",\n") } + sb.append(" ],\n") + val packs = packTiers() + sb.append(" \"packs\": [\n") + packRows.forEachIndexed { i, fmt -> + val cells = platforms.mapNotNull { p -> best(fmt, p, packs)?.let { "\"$p\": \"$it\"" } } + sb.append(" {\"name\": \"").append(fmt).append("\", \"byPlatform\": {") + .append(cells.joinToString(", ")).append("}}") + sb.append(if (i == packRows.lastIndex) "\n" else ",\n") + } sb.append(" ]\n}\n") return sb.toString() } @@ -189,6 +227,14 @@ class KernelSupportMatrixTest { "native-jni-direct row", ) + // Drift gate on the JVM pack rows, where the environment allows it: the FFM provider must + // carry the direct `x · Wᵀ` kernel and the ternary pack both of its kernels. + if (NativeKernelProvider.isAvailable()) { + assertTrue(NativeKernelProvider.matmulFp32Wt() != null, "native-ffm lost its direct x·Wᵀ kernel — update packTiers()") + assertTrue(NativeTernaryF32GemvKernel.isAvailable() && NativeTernaryLmheadKernel.isAvailable(), + "ffm-ternary lost a kernel — update packTiers()") + } + val jsonText = renderJson(tiers) val outDir = File("build/generated/kernel-support").apply { mkdirs() } File(outDir, "kernel-support.json").writeText(jsonText) diff --git a/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/NativeFp32MatmulWtKernelTest.kt b/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/NativeFp32MatmulWtKernelTest.kt new file mode 100644 index 00000000..78b56d8f --- /dev/null +++ b/skainet-backends/skainet-backend-native-cpu/src/jvmTest/kotlin/sk/ainet/exec/kernel/NativeFp32MatmulWtKernelTest.kt @@ -0,0 +1,111 @@ +package sk.ainet.exec.kernel + +import java.lang.foreign.Arena +import java.lang.foreign.MemorySegment +import java.lang.foreign.ValueLayout +import kotlin.math.abs +import kotlin.random.Random +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + +/** + * [NativeFp32MatmulWtKernel] — the JVM binding of `skainet_fp32_matmul_wt` — against a plain + * row-dot reference, on both of its faces. The row-pool threshold (512 output rows) is crossed by + * one shape so the threaded partition is covered; per-row arithmetic does not depend on it. + */ +class NativeFp32MatmulWtKernelTest { + + @BeforeTest + fun checkAvailable() { + assertTrue(NativeFp32MatmulWtKernel.isAvailable(), "bundled libskainet_kernels must resolve skainet_fp32_matmul_wt") + } + + private fun reference(x: FloatArray, xOff: Int, w: FloatArray, wOff: Int, m: Int, n: Int, k: Int): FloatArray { + val out = FloatArray(m * n) + for (i in 0 until m) for (o in 0 until n) { + var acc = 0.0 + for (p in 0 until k) acc += x[xOff + i * k + p].toDouble() * w[wOff + o * k + p] + out[i * n + o] = acc.toFloat() + } + return out + } + + private fun assertClose(expected: FloatArray, actual: FloatArray, what: String) { + assertEquals(expected.size, actual.size, "$what size") + var maxAbs = 0f + for (v in expected) maxAbs = maxOf(maxAbs, abs(v)) + val tol = maxAbs * 1e-5f + 1e-6f + for (i in expected.indices) { + assertTrue(abs(expected[i] - actual[i]) <= tol, "$what[$i]: ${actual[i]} vs ${expected[i]} (tol $tol)") + } + } + + @Test + fun heap_face_matches_the_row_dot_reference_on_every_shape() { + val rng = Random(3) + // (m, n, k): a single token; a prefill against a threaded row count with a 4-lane tail; one row of weight. + for ((m, n, k) in listOf(Triple(1, 7, 5), Triple(3, 600, 37), Triple(5, 1, 64))) { + val x = FloatArray(m * k) { rng.nextFloat() - 0.5f } + val w = FloatArray(n * k) { rng.nextFloat() - 0.5f } + val out = FloatArray(m * n) + NativeFp32MatmulWtKernel.matmulWt(x, 0, w, 0, out, 0, m, n, k) + assertClose(reference(x, 0, w, 0, m, n, k), out, "wt $m×$k · ($n×$k)ᵀ") + } + } + + @Test + fun offsets_are_honoured_and_the_rest_of_the_arrays_is_left_alone() { + val rng = Random(5) + val m = 2; val n = 9; val k = 12 + val x = FloatArray(3 + m * k) { rng.nextFloat() } + val w = FloatArray(2 + n * k) { rng.nextFloat() } + val out = FloatArray(1 + m * n + 4) { 7f } + NativeFp32MatmulWtKernel.matmulWt(x, 3, w, 2, out, 1, m, n, k) + assertClose(reference(x, 3, w, 2, m, n, k), out.copyOfRange(1, 1 + m * n), "offset wt") + assertEquals(7f, out[0]) + for (i in 1 + m * n until out.size) assertEquals(7f, out[i], "tail[$i] untouched") + } + + @Test + fun k_zero_zeroes_the_block_and_empty_shapes_are_no_ops() { + val out = FloatArray(6) { 1f } + NativeFp32MatmulWtKernel.matmulWt(FloatArray(0), 0, FloatArray(0), 0, out, 0, 2, 3, 0) + assertContentEquals(FloatArray(6), out) + val untouched = FloatArray(4) { 2f } + NativeFp32MatmulWtKernel.matmulWt(FloatArray(0), 0, FloatArray(8), 0, untouched, 0, 0, 4, 2) + NativeFp32MatmulWtKernel.matmulWt(FloatArray(4), 0, FloatArray(0), 0, untouched, 0, 2, 0, 2) + assertContentEquals(FloatArray(4) { 2f }, untouched) + } + + @Test + fun segment_face_is_bit_identical_to_the_heap_face() { + val rng = Random(11) + val m = 4; val n = 530; val k = 96 + val x = FloatArray(m * k) { rng.nextFloat() - 0.5f } + val w = FloatArray(n * k) { rng.nextFloat() - 0.5f } + val viaHeap = FloatArray(m * n) + NativeFp32MatmulWtKernel.matmulWt(x, 0, w, 0, viaHeap, 0, m, n, k) + Arena.ofConfined().use { arena -> + // The weight sits 16 bytes into a larger segment: the offset is honoured and no copy is made. + val seg = arena.allocate(16L + n.toLong() * k * java.lang.Float.BYTES, 64L) + MemorySegment.copy(w, 0, seg, ValueLayout.JAVA_FLOAT, 16L, n * k) + val viaSegment = FloatArray(m * n) + NativeFp32MatmulWtKernel.matmulWt(x, 0, seg, 16L, viaSegment, 0, m, n, k) + assertContentEquals(viaHeap, viaSegment) + } + assertClose(reference(x, 0, w, 0, m, n, k), viaHeap, "threaded wt") + } + + @Test + fun the_provider_exposes_both_faces() { + assertTrue(NativeKernelProvider.isAvailable()) + assertNotNull(NativeKernelProvider.matmulFp32Wt()) + assertNotNull(NativeKernelProvider.matmulFp32WtMemSeg()) + assertTrue(NativeKernelProvider.supports("matmul_wt", listOf("Float32", "Float32"))) + assertTrue(!ScalarKernelProvider.supports("matmul_wt", listOf("Float32", "Float32")), "the scalar floor has no direct kernel") + } +} diff --git a/skainet-backends/skainet-backend-wasm-simd/native/build-wasm.sh b/skainet-backends/skainet-backend-wasm-simd/native/build-wasm.sh index 0c9009de..7583f01d 100644 --- a/skainet-backends/skainet-backend-wasm-simd/native/build-wasm.sh +++ b/skainet-backends/skainet-backend-wasm-simd/native/build-wasm.sh @@ -11,8 +11,9 @@ # # The sources are skainet-backend-native-cpu/native/src — the same files the JVM FFM and Android JNI # packs are built from — compiled with Emscripten. Only the portable (#else) kernel bodies and the -# explicit __wasm_simd128__ bodies are used; NEON, Apple dispatch and the vendored ternary kernels -# are not part of this build. +# explicit __wasm_simd128__ bodies are used; NEON and Apple dispatch are not part of this build. +# The ternary kernels come from the portable branch of skainet_ternary_f32.c (the compile-time LUT +# with its SIMD128 body), not from the vendored NeoGPU file, which needs native pthreads and NEON. # # Toolchain: emsdk, pinned below. `EMSDK_PYTHON` must point at a Python >= 3.10 when the default # python3 is older (pyenv). Usage: @@ -44,11 +45,16 @@ SOURCES=( "$NATIVE/src/q4k_matmul.c" "$NATIVE/src/q5k_matmul.c" "$NATIVE/src/q6k_matmul.c" + "$NATIVE/src/skainet_ternary_f32.c" + "$NATIVE/src/bitnet_gemv.c" + "$NATIVE/src/f32_ops.c" "$NATIVE/src/skainet_row_threads.c" "$NATIVE/src/skainet_cpu_features.c" ) EXPORTS='_malloc,_free,_skainet_fp32_matmul,_skainet_fp32_matmul_wt,_skainet_bf16_matmul,_skainet_fp16_matmul' +EXPORTS="$EXPORTS,_skainet_ternary_f32_gemv,_skainet_ternary_lmhead_stage1,_skainet_bitnet_gemv_tq2_0" +EXPORTS="$EXPORTS,_skainet_f32_binary,_skainet_f32_unary,_skainet_f32_reduce_all,_skainet_f32_reduce_axis" for f in q4_0 q5_0 q5_1 q8_0 q4k q5k q6k; do EXPORTS="$EXPORTS,_skainet_${f}_matmul,_skainet_${f}_matmul_rm" done diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/SidecarArtifacts.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/SidecarArtifacts.kt index b33356e5..5130c5ae 100644 --- a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/SidecarArtifacts.kt +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/SidecarArtifacts.kt @@ -1,13 +1,13 @@ // GENERATED by native/build-wasm.sh (emsdk 4.0.14) -- do not edit. // SKEEP-007 Tier 1: the SIMD128 kernel sidecar, embedded so every consumer of this module carries it. -// sha256 st: c1a6213df16738714532551430ae508eb29154459336c5069bf27be3205ba3f3 -// sha256 mt: 590e0bfe8a35c5fa259305688d3c964c5bf3013fab611b5557dcce65d3b8b097 +// sha256 st: 46b11b3cef2f64b3f9db201343f5007737aac85775b6393e1b8fc2dbe748829c +// sha256 mt: 12d0eb119a81609ebfa18102e0d5b29b97987f29312e3b3fb99016be2ffac472 package sk.ainet.exec.wasm internal object SidecarArtifacts { const val EMSDK: String = "4.0.14" - const val ST_MJS: String = "YXN5bmMgZnVuY3Rpb24gY3JlYXRlU2thaW5ldEtlcm5lbHMobW9kdWxlQXJnPXt9KXt2YXIgbW9kdWxlUnRuO3ZhciBNb2R1bGU9bW9kdWxlQXJnO3ZhciBFTlZJUk9OTUVOVF9JU19XRUI9dHlwZW9mIHdpbmRvdz09Im9iamVjdCI7dmFyIEVOVklST05NRU5UX0lTX1dPUktFUj10eXBlb2YgV29ya2VyR2xvYmFsU2NvcGUhPSJ1bmRlZmluZWQiO3ZhciBFTlZJUk9OTUVOVF9JU19OT0RFPXR5cGVvZiBwcm9jZXNzPT0ib2JqZWN0IiYmcHJvY2Vzcy52ZXJzaW9ucz8ubm9kZSYmcHJvY2Vzcy50eXBlIT0icmVuZGVyZXIiO2lmKEVOVklST05NRU5UX0lTX05PREUpe2NvbnN0e2NyZWF0ZVJlcXVpcmV9PWF3YWl0IGltcG9ydCgibW9kdWxlIik7dmFyIHJlcXVpcmU9Y3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwuc3RhcnRzV2l0aCgiZmlsZToiKT9pbXBvcnQubWV0YS51cmw6cHJvY2Vzcy5jd2QoKSsiLyIpfXZhciBhcmd1bWVudHNfPVtdO3ZhciB0aGlzUHJvZ3JhbT0iLi90aGlzLnByb2dyYW0iO3ZhciBxdWl0Xz0oc3RhdHVzLHRvVGhyb3cpPT57dGhyb3cgdG9UaHJvd307dmFyIF9zY3JpcHROYW1lPWltcG9ydC5tZXRhLnVybDt2YXIgc2NyaXB0RGlyZWN0b3J5PSIiO2Z1bmN0aW9uIGxvY2F0ZUZpbGUocGF0aCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBNb2R1bGVbImxvY2F0ZUZpbGUiXShwYXRoLHNjcmlwdERpcmVjdG9yeSl9cmV0dXJuIHNjcmlwdERpcmVjdG9yeStwYXRofXZhciByZWFkQXN5bmMscmVhZEJpbmFyeTtpZihFTlZJUk9OTUVOVF9JU19OT0RFKXt2YXIgZnM9cmVxdWlyZSgiZnMiKTtpZihfc2NyaXB0TmFtZS5zdGFydHNXaXRoKCJmaWxlOiIpKXtzY3JpcHREaXJlY3Rvcnk9cmVxdWlyZSgicGF0aCIpLmRpcm5hbWUocmVxdWlyZSgidXJsIikuZmlsZVVSTFRvUGF0aChfc2NyaXB0TmFtZSkpKyIvIn1yZWFkQmluYXJ5PWZpbGVuYW1lPT57ZmlsZW5hbWU9aXNGaWxlVVJJKGZpbGVuYW1lKT9uZXcgVVJMKGZpbGVuYW1lKTpmaWxlbmFtZTt2YXIgcmV0PWZzLnJlYWRGaWxlU3luYyhmaWxlbmFtZSk7cmV0dXJuIHJldH07cmVhZEFzeW5jPWFzeW5jKGZpbGVuYW1lLGJpbmFyeT10cnVlKT0+e2ZpbGVuYW1lPWlzRmlsZVVSSShmaWxlbmFtZSk/bmV3IFVSTChmaWxlbmFtZSk6ZmlsZW5hbWU7dmFyIHJldD1mcy5yZWFkRmlsZVN5bmMoZmlsZW5hbWUsYmluYXJ5P3VuZGVmaW5lZDoidXRmOCIpO3JldHVybiByZXR9O2lmKHByb2Nlc3MuYXJndi5sZW5ndGg+MSl7dGhpc1Byb2dyYW09cHJvY2Vzcy5hcmd2WzFdLnJlcGxhY2UoL1xcL2csIi8iKX1hcmd1bWVudHNfPXByb2Nlc3MuYXJndi5zbGljZSgyKTtxdWl0Xz0oc3RhdHVzLHRvVGhyb3cpPT57cHJvY2Vzcy5leGl0Q29kZT1zdGF0dXM7dGhyb3cgdG9UaHJvd319ZWxzZSBpZihFTlZJUk9OTUVOVF9JU19XRUJ8fEVOVklST05NRU5UX0lTX1dPUktFUil7dHJ5e3NjcmlwdERpcmVjdG9yeT1uZXcgVVJMKCIuIixfc2NyaXB0TmFtZSkuaHJlZn1jYXRjaHt9e2lmKEVOVklST05NRU5UX0lTX1dPUktFUil7cmVhZEJpbmFyeT11cmw9Pnt2YXIgeGhyPW5ldyBYTUxIdHRwUmVxdWVzdDt4aHIub3BlbigiR0VUIix1cmwsZmFsc2UpO3hoci5yZXNwb25zZVR5cGU9ImFycmF5YnVmZmVyIjt4aHIuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoeGhyLnJlc3BvbnNlKX19cmVhZEFzeW5jPWFzeW5jIHVybD0+e3ZhciByZXNwb25zZT1hd2FpdCBmZXRjaCh1cmwse2NyZWRlbnRpYWxzOiJzYW1lLW9yaWdpbiJ9KTtpZihyZXNwb25zZS5vayl7cmV0dXJuIHJlc3BvbnNlLmFycmF5QnVmZmVyKCl9dGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLnN0YXR1cysiIDogIityZXNwb25zZS51cmwpfX19ZWxzZXt9dmFyIG91dD1jb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpO3ZhciBlcnI9Y29uc29sZS5lcnJvci5iaW5kKGNvbnNvbGUpO3ZhciB3YXNtQmluYXJ5O3ZhciBBQk9SVD1mYWxzZTt2YXIgaXNGaWxlVVJJPWZpbGVuYW1lPT5maWxlbmFtZS5zdGFydHNXaXRoKCJmaWxlOi8vIik7dmFyIHJlYWR5UHJvbWlzZVJlc29sdmUscmVhZHlQcm9taXNlUmVqZWN0O3ZhciB3YXNtTWVtb3J5O3ZhciBIRUFQOCxIRUFQVTgsSEVBUDE2LEhFQVBVMTYsSEVBUDMyLEhFQVBVMzIsSEVBUEYzMixIRUFQRjY0O3ZhciBIRUFQNjQsSEVBUFU2NDt2YXIgcnVudGltZUluaXRpYWxpemVkPWZhbHNlO2Z1bmN0aW9uIHVwZGF0ZU1lbW9yeVZpZXdzKCl7dmFyIGI9d2FzbU1lbW9yeS5idWZmZXI7SEVBUDg9bmV3IEludDhBcnJheShiKTtIRUFQMTY9bmV3IEludDE2QXJyYXkoYik7SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO0hFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO0hFQVAzMj1uZXcgSW50MzJBcnJheShiKTtIRUFQVTMyPW5ldyBVaW50MzJBcnJheShiKTtIRUFQRjMyPW5ldyBGbG9hdDMyQXJyYXkoYik7SEVBUEY2ND1uZXcgRmxvYXQ2NEFycmF5KGIpO0hFQVA2ND1uZXcgQmlnSW50NjRBcnJheShiKTtIRUFQVTY0PW5ldyBCaWdVaW50NjRBcnJheShiKX1mdW5jdGlvbiBwcmVSdW4oKXtpZihNb2R1bGVbInByZVJ1biJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInByZVJ1biJdPVtNb2R1bGVbInByZVJ1biJdXTt3aGlsZShNb2R1bGVbInByZVJ1biJdLmxlbmd0aCl7YWRkT25QcmVSdW4oTW9kdWxlWyJwcmVSdW4iXS5zaGlmdCgpKX19Y2FsbFJ1bnRpbWVDYWxsYmFja3Mob25QcmVSdW5zKX1mdW5jdGlvbiBpbml0UnVudGltZSgpe3J1bnRpbWVJbml0aWFsaXplZD10cnVlO3dhc21FeHBvcnRzWyJjIl0oKX1mdW5jdGlvbiBwb3N0UnVuKCl7aWYoTW9kdWxlWyJwb3N0UnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInBvc3RSdW4iXT1bTW9kdWxlWyJwb3N0UnVuIl1dO3doaWxlKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCl7YWRkT25Qb3N0UnVuKE1vZHVsZVsicG9zdFJ1biJdLnNoaWZ0KCkpfX1jYWxsUnVudGltZUNhbGxiYWNrcyhvblBvc3RSdW5zKX1mdW5jdGlvbiBhYm9ydCh3aGF0KXtNb2R1bGVbIm9uQWJvcnQiXT8uKHdoYXQpO3doYXQ9IkFib3J0ZWQoIit3aGF0KyIpIjtlcnIod2hhdCk7QUJPUlQ9dHJ1ZTt3aGF0Kz0iLiBCdWlsZCB3aXRoIC1zQVNTRVJUSU9OUyBmb3IgbW9yZSBpbmZvLiI7dmFyIGU9bmV3IFdlYkFzc2VtYmx5LlJ1bnRpbWVFcnJvcih3aGF0KTtyZWFkeVByb21pc2VSZWplY3Q/LihlKTt0aHJvdyBlfXZhciB3YXNtQmluYXJ5RmlsZTtmdW5jdGlvbiBmaW5kV2FzbUJpbmFyeSgpe2lmKE1vZHVsZVsibG9jYXRlRmlsZSJdKXtyZXR1cm4gbG9jYXRlRmlsZSgic2thaW5ldF9rZXJuZWxzX3N0Lndhc20iKX10cnl7cmV0dXJuIG5ldyBVUkwoInNrYWluZXRfa2VybmVsc19zdC53YXNtIixpbXBvcnQubWV0YS51cmwpLmhyZWZ9Y2F0Y2goZSl7cmV0dXJuICJza2FpbmV0X2tlcm5lbHNfc3Qud2FzbSJ9fWZ1bmN0aW9uIGdldEJpbmFyeVN5bmMoZmlsZSl7aWYoZmlsZT09d2FzbUJpbmFyeUZpbGUmJndhc21CaW5hcnkpe3JldHVybiBuZXcgVWludDhBcnJheSh3YXNtQmluYXJ5KX1pZihyZWFkQmluYXJ5KXtyZXR1cm4gcmVhZEJpbmFyeShmaWxlKX10aHJvdyJib3RoIGFzeW5jIGFuZCBzeW5jIGZldGNoaW5nIG9mIHRoZSB3YXNtIGZhaWxlZCJ9YXN5bmMgZnVuY3Rpb24gZ2V0V2FzbUJpbmFyeShiaW5hcnlGaWxlKXtpZighd2FzbUJpbmFyeSl7dHJ5e3ZhciByZXNwb25zZT1hd2FpdCByZWFkQXN5bmMoYmluYXJ5RmlsZSk7cmV0dXJuIG5ldyBVaW50OEFycmF5KHJlc3BvbnNlKX1jYXRjaHt9fXJldHVybiBnZXRCaW5hcnlTeW5jKGJpbmFyeUZpbGUpfWFzeW5jIGZ1bmN0aW9uIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzKXt0cnl7dmFyIGJpbmFyeT1hd2FpdCBnZXRXYXNtQmluYXJ5KGJpbmFyeUZpbGUpO3ZhciBpbnN0YW5jZT1hd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShiaW5hcnksaW1wb3J0cyk7cmV0dXJuIGluc3RhbmNlfWNhdGNoKHJlYXNvbil7ZXJyKGBmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAke3JlYXNvbn1gKTthYm9ydChyZWFzb24pfX1hc3luYyBmdW5jdGlvbiBpbnN0YW50aWF0ZUFzeW5jKGJpbmFyeSxiaW5hcnlGaWxlLGltcG9ydHMpe2lmKCFiaW5hcnkmJiFFTlZJUk9OTUVOVF9JU19OT0RFKXt0cnl7dmFyIHJlc3BvbnNlPWZldGNoKGJpbmFyeUZpbGUse2NyZWRlbnRpYWxzOiJzYW1lLW9yaWdpbiJ9KTt2YXIgaW5zdGFudGlhdGlvblJlc3VsdD1hd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhyZXNwb25zZSxpbXBvcnRzKTtyZXR1cm4gaW5zdGFudGlhdGlvblJlc3VsdH1jYXRjaChyZWFzb24pe2Vycihgd2FzbSBzdHJlYW1pbmcgY29tcGlsZSBmYWlsZWQ6ICR7cmVhc29ufWApO2VycigiZmFsbGluZyBiYWNrIHRvIEFycmF5QnVmZmVyIGluc3RhbnRpYXRpb24iKX19cmV0dXJuIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzKX1mdW5jdGlvbiBnZXRXYXNtSW1wb3J0cygpe3JldHVybnthOndhc21JbXBvcnRzfX1hc3luYyBmdW5jdGlvbiBjcmVhdGVXYXNtKCl7ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLG1vZHVsZSl7d2FzbUV4cG9ydHM9aW5zdGFuY2UuZXhwb3J0czt3YXNtRXhwb3J0cz1hcHBseVNpZ25hdHVyZUNvbnZlcnNpb25zKHdhc21FeHBvcnRzKTt3YXNtTWVtb3J5PXdhc21FeHBvcnRzWyJiIl07TW9kdWxlWyJ3YXNtTWVtb3J5Il09d2FzbU1lbW9yeTt1cGRhdGVNZW1vcnlWaWV3cygpO2Fzc2lnbldhc21FeHBvcnRzKHdhc21FeHBvcnRzKTtyZXR1cm4gd2FzbUV4cG9ydHN9ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZXR1cm4gcmVjZWl2ZUluc3RhbmNlKHJlc3VsdFsiaW5zdGFuY2UiXSl9dmFyIGluZm89Z2V0V2FzbUltcG9ydHMoKTtpZihNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKXtyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUscmVqZWN0KT0+e01vZHVsZVsiaW5zdGFudGlhdGVXYXNtIl0oaW5mbywobW9kLGluc3QpPT57cmVzb2x2ZShyZWNlaXZlSW5zdGFuY2UobW9kLGluc3QpKX0pfSl9d2FzbUJpbmFyeUZpbGU/Pz1maW5kV2FzbUJpbmFyeSgpO3ZhciByZXN1bHQ9YXdhaXQgaW5zdGFudGlhdGVBc3luYyh3YXNtQmluYXJ5LHdhc21CaW5hcnlGaWxlLGluZm8pO3ZhciBleHBvcnRzPXJlY2VpdmVJbnN0YW50aWF0aW9uUmVzdWx0KHJlc3VsdCk7cmV0dXJuIGV4cG9ydHN9Y2xhc3MgRXhpdFN0YXR1c3tuYW1lPSJFeGl0U3RhdHVzIjtjb25zdHJ1Y3RvcihzdGF0dXMpe3RoaXMubWVzc2FnZT1gUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdCgke3N0YXR1c30pYDt0aGlzLnN0YXR1cz1zdGF0dXN9fXZhciBjYWxsUnVudGltZUNhbGxiYWNrcz1jYWxsYmFja3M9Pnt3aGlsZShjYWxsYmFja3MubGVuZ3RoPjApe2NhbGxiYWNrcy5zaGlmdCgpKE1vZHVsZSl9fTt2YXIgb25Qb3N0UnVucz1bXTt2YXIgYWRkT25Qb3N0UnVuPWNiPT5vblBvc3RSdW5zLnB1c2goY2IpO3ZhciBvblByZVJ1bnM9W107dmFyIGFkZE9uUHJlUnVuPWNiPT5vblByZVJ1bnMucHVzaChjYik7dmFyIG5vRXhpdFJ1bnRpbWU9dHJ1ZTt2YXIgZ2V0SGVhcE1heD0oKT0+NDI5NDkwMTc2MDt2YXIgYWxpZ25NZW1vcnk9KHNpemUsYWxpZ25tZW50KT0+TWF0aC5jZWlsKHNpemUvYWxpZ25tZW50KSphbGlnbm1lbnQ7dmFyIGdyb3dNZW1vcnk9c2l6ZT0+e3ZhciBvbGRIZWFwU2l6ZT13YXNtTWVtb3J5LmJ1ZmZlci5ieXRlTGVuZ3RoO3ZhciBwYWdlcz0oc2l6ZS1vbGRIZWFwU2l6ZSs2NTUzNSkvNjU1MzZ8MDt0cnl7d2FzbU1lbW9yeS5ncm93KHBhZ2VzKTt1cGRhdGVNZW1vcnlWaWV3cygpO3JldHVybiAxfWNhdGNoKGUpe319O2Z1bmN0aW9uIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwKHJlcXVlc3RlZFNpemUpe3JlcXVlc3RlZFNpemU+Pj49MDt2YXIgb2xkU2l6ZT1IRUFQVTgubGVuZ3RoO3ZhciBtYXhIZWFwU2l6ZT1nZXRIZWFwTWF4KCk7aWYocmVxdWVzdGVkU2l6ZT5tYXhIZWFwU2l6ZSl7cmV0dXJuIGZhbHNlfWZvcih2YXIgY3V0RG93bj0xO2N1dERvd248PTQ7Y3V0RG93bio9Mil7dmFyIG92ZXJHcm93bkhlYXBTaXplPW9sZFNpemUqKDErLjIvY3V0RG93bik7b3Zlckdyb3duSGVhcFNpemU9TWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUscmVxdWVzdGVkU2l6ZSsxMDA2NjMyOTYpO3ZhciBuZXdTaXplPU1hdGgubWluKG1heEhlYXBTaXplLGFsaWduTWVtb3J5KE1hdGgubWF4KHJlcXVlc3RlZFNpemUsb3Zlckdyb3duSGVhcFNpemUpLDY1NTM2KSk7dmFyIHJlcGxhY2VtZW50PWdyb3dNZW1vcnkobmV3U2l6ZSk7aWYocmVwbGFjZW1lbnQpe3JldHVybiB0cnVlfX1yZXR1cm4gZmFsc2V9e2lmKE1vZHVsZVsibm9FeGl0UnVudGltZSJdKW5vRXhpdFJ1bnRpbWU9TW9kdWxlWyJub0V4aXRSdW50aW1lIl07aWYoTW9kdWxlWyJwcmludCJdKW91dD1Nb2R1bGVbInByaW50Il07aWYoTW9kdWxlWyJwcmludEVyciJdKWVycj1Nb2R1bGVbInByaW50RXJyIl07aWYoTW9kdWxlWyJ3YXNtQmluYXJ5Il0pd2FzbUJpbmFyeT1Nb2R1bGVbIndhc21CaW5hcnkiXTtpZihNb2R1bGVbImFyZ3VtZW50cyJdKWFyZ3VtZW50c189TW9kdWxlWyJhcmd1bWVudHMiXTtpZihNb2R1bGVbInRoaXNQcm9ncmFtIl0pdGhpc1Byb2dyYW09TW9kdWxlWyJ0aGlzUHJvZ3JhbSJdO2lmKE1vZHVsZVsicHJlSW5pdCJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVJbml0Il09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVJbml0Il09W01vZHVsZVsicHJlSW5pdCJdXTt3aGlsZShNb2R1bGVbInByZUluaXQiXS5sZW5ndGg+MCl7TW9kdWxlWyJwcmVJbml0Il0uc2hpZnQoKSgpfX19TW9kdWxlWyJ3YXNtTWVtb3J5Il09d2FzbU1lbW9yeTt2YXIgX3NrYWluZXRfZnAzMl9tYXRtdWwsX3NrYWluZXRfZnAzMl9tYXRtdWxfd3QsX3NrYWluZXRfYmYxNl9tYXRtdWwsX3NrYWluZXRfZnAxNl9tYXRtdWwsX3NrYWluZXRfcTRfMF9tYXRtdWwsX3NrYWluZXRfcTRfMF9tYXRtdWxfcm0sX3NrYWluZXRfcTVfMF9tYXRtdWwsX21hbGxvYyxfZnJlZSxfc2thaW5ldF9xNV8wX21hdG11bF9ybSxfc2thaW5ldF9xNV8xX21hdG11bCxfc2thaW5ldF9xNV8xX21hdG11bF9ybSxfc2thaW5ldF9xOF8wX21hdG11bCxfc2thaW5ldF9xOF8wX21hdG11bF9ybSxfc2thaW5ldF9xNGtfbWF0bXVsLF9za2FpbmV0X3E0a19tYXRtdWxfcm0sX3NrYWluZXRfcTVrX21hdG11bCxfc2thaW5ldF9xNWtfbWF0bXVsX3JtLF9za2FpbmV0X3E2a19tYXRtdWwsX3NrYWluZXRfcTZrX21hdG11bF9ybTtmdW5jdGlvbiBhc3NpZ25XYXNtRXhwb3J0cyh3YXNtRXhwb3J0cyl7TW9kdWxlWyJfc2thaW5ldF9mcDMyX21hdG11bCJdPV9za2FpbmV0X2ZwMzJfbWF0bXVsPXdhc21FeHBvcnRzWyJkIl07TW9kdWxlWyJfc2thaW5ldF9mcDMyX21hdG11bF93dCJdPV9za2FpbmV0X2ZwMzJfbWF0bXVsX3d0PXdhc21FeHBvcnRzWyJlIl07TW9kdWxlWyJfc2thaW5ldF9iZjE2X21hdG11bCJdPV9za2FpbmV0X2JmMTZfbWF0bXVsPXdhc21FeHBvcnRzWyJmIl07TW9kdWxlWyJfc2thaW5ldF9mcDE2X21hdG11bCJdPV9za2FpbmV0X2ZwMTZfbWF0bXVsPXdhc21FeHBvcnRzWyJnIl07TW9kdWxlWyJfc2thaW5ldF9xNF8wX21hdG11bCJdPV9za2FpbmV0X3E0XzBfbWF0bXVsPXdhc21FeHBvcnRzWyJoIl07TW9kdWxlWyJfc2thaW5ldF9xNF8wX21hdG11bF9ybSJdPV9za2FpbmV0X3E0XzBfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJpIl07TW9kdWxlWyJfc2thaW5ldF9xNV8wX21hdG11bCJdPV9za2FpbmV0X3E1XzBfbWF0bXVsPXdhc21FeHBvcnRzWyJqIl07TW9kdWxlWyJfbWFsbG9jIl09X21hbGxvYz13YXNtRXhwb3J0c1siayJdO01vZHVsZVsiX2ZyZWUiXT1fZnJlZT13YXNtRXhwb3J0c1sibCJdO01vZHVsZVsiX3NrYWluZXRfcTVfMF9tYXRtdWxfcm0iXT1fc2thaW5ldF9xNV8wX21hdG11bF9ybT13YXNtRXhwb3J0c1sibSJdO01vZHVsZVsiX3NrYWluZXRfcTVfMV9tYXRtdWwiXT1fc2thaW5ldF9xNV8xX21hdG11bD13YXNtRXhwb3J0c1sibiJdO01vZHVsZVsiX3NrYWluZXRfcTVfMV9tYXRtdWxfcm0iXT1fc2thaW5ldF9xNV8xX21hdG11bF9ybT13YXNtRXhwb3J0c1sibyJdO01vZHVsZVsiX3NrYWluZXRfcThfMF9tYXRtdWwiXT1fc2thaW5ldF9xOF8wX21hdG11bD13YXNtRXhwb3J0c1sicCJdO01vZHVsZVsiX3NrYWluZXRfcThfMF9tYXRtdWxfcm0iXT1fc2thaW5ldF9xOF8wX21hdG11bF9ybT13YXNtRXhwb3J0c1sicSJdO01vZHVsZVsiX3NrYWluZXRfcTRrX21hdG11bCJdPV9za2FpbmV0X3E0a19tYXRtdWw9d2FzbUV4cG9ydHNbInIiXTtNb2R1bGVbIl9za2FpbmV0X3E0a19tYXRtdWxfcm0iXT1fc2thaW5ldF9xNGtfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJzIl07TW9kdWxlWyJfc2thaW5ldF9xNWtfbWF0bXVsIl09X3NrYWluZXRfcTVrX21hdG11bD13YXNtRXhwb3J0c1sidCJdO01vZHVsZVsiX3NrYWluZXRfcTVrX21hdG11bF9ybSJdPV9za2FpbmV0X3E1a19tYXRtdWxfcm09d2FzbUV4cG9ydHNbInUiXTtNb2R1bGVbIl9za2FpbmV0X3E2a19tYXRtdWwiXT1fc2thaW5ldF9xNmtfbWF0bXVsPXdhc21FeHBvcnRzWyJ2Il07TW9kdWxlWyJfc2thaW5ldF9xNmtfbWF0bXVsX3JtIl09X3NrYWluZXRfcTZrX21hdG11bF9ybT13YXNtRXhwb3J0c1sidyJdfXZhciB3YXNtSW1wb3J0cz17YTpfZW1zY3JpcHRlbl9yZXNpemVfaGVhcH07ZnVuY3Rpb24gYXBwbHlTaWduYXR1cmVDb252ZXJzaW9ucyh3YXNtRXhwb3J0cyl7d2FzbUV4cG9ydHM9T2JqZWN0LmFzc2lnbih7fSx3YXNtRXhwb3J0cyk7dmFyIG1ha2VXcmFwcGVyX3BwPWY9PmEwPT5mKGEwKT4+PjA7dmFyIG1ha2VXcmFwcGVyX3A9Zj0+KCk9PmYoKT4+PjA7d2FzbUV4cG9ydHNbImsiXT1tYWtlV3JhcHBlcl9wcCh3YXNtRXhwb3J0c1siayJdKTt3YXNtRXhwb3J0c1siX2Vtc2NyaXB0ZW5fc3RhY2tfYWxsb2MiXT1tYWtlV3JhcHBlcl9wcCh3YXNtRXhwb3J0c1siX2Vtc2NyaXB0ZW5fc3RhY2tfYWxsb2MiXSk7d2FzbUV4cG9ydHNbImVtc2NyaXB0ZW5fc3RhY2tfZ2V0X2N1cnJlbnQiXT1tYWtlV3JhcHBlcl9wKHdhc21FeHBvcnRzWyJlbXNjcmlwdGVuX3N0YWNrX2dldF9jdXJyZW50Il0pO3JldHVybiB3YXNtRXhwb3J0c31mdW5jdGlvbiBydW4oKXtwcmVSdW4oKTtmdW5jdGlvbiBkb1J1bigpe01vZHVsZVsiY2FsbGVkUnVuIl09dHJ1ZTtpZihBQk9SVClyZXR1cm47aW5pdFJ1bnRpbWUoKTtyZWFkeVByb21pc2VSZXNvbHZlPy4oTW9kdWxlKTtNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0/LigpO3Bvc3RSdW4oKX1pZihNb2R1bGVbInNldFN0YXR1cyJdKXtNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7c2V0VGltZW91dCgoKT0+e3NldFRpbWVvdXQoKCk9Pk1vZHVsZVsic2V0U3RhdHVzIl0oIiIpLDEpO2RvUnVuKCl9LDEpfWVsc2V7ZG9SdW4oKX19dmFyIHdhc21FeHBvcnRzO3dhc21FeHBvcnRzPWF3YWl0IChjcmVhdGVXYXNtKCkpO3J1bigpO2lmKHJ1bnRpbWVJbml0aWFsaXplZCl7bW9kdWxlUnRuPU1vZHVsZX1lbHNle21vZHVsZVJ0bj1uZXcgUHJvbWlzZSgocmVzb2x2ZSxyZWplY3QpPT57cmVhZHlQcm9taXNlUmVzb2x2ZT1yZXNvbHZlO3JlYWR5UHJvbWlzZVJlamVjdD1yZWplY3R9KX0KO3JldHVybiBtb2R1bGVSdG59ZXhwb3J0IGRlZmF1bHQgY3JlYXRlU2thaW5ldEtlcm5lbHM7Cg==" - const val ST_WASM: String = "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" - const val MT_MJS: String = "YXN5bmMgZnVuY3Rpb24gY3JlYXRlU2thaW5ldEtlcm5lbHMobW9kdWxlQXJnPXt9KXt2YXIgbW9kdWxlUnRuO3ZhciBNb2R1bGU9bW9kdWxlQXJnO3ZhciBFTlZJUk9OTUVOVF9JU19XRUI9dHlwZW9mIHdpbmRvdz09Im9iamVjdCI7dmFyIEVOVklST05NRU5UX0lTX1dPUktFUj10eXBlb2YgV29ya2VyR2xvYmFsU2NvcGUhPSJ1bmRlZmluZWQiO3ZhciBFTlZJUk9OTUVOVF9JU19OT0RFPXR5cGVvZiBwcm9jZXNzPT0ib2JqZWN0IiYmcHJvY2Vzcy52ZXJzaW9ucz8ubm9kZSYmcHJvY2Vzcy50eXBlIT0icmVuZGVyZXIiO3ZhciBFTlZJUk9OTUVOVF9JU19QVEhSRUFEPUVOVklST05NRU5UX0lTX1dPUktFUiYmc2VsZi5uYW1lPy5zdGFydHNXaXRoKCJlbS1wdGhyZWFkIik7aWYoRU5WSVJPTk1FTlRfSVNfTk9ERSl7Y29uc3R7Y3JlYXRlUmVxdWlyZX09YXdhaXQgaW1wb3J0KCJtb2R1bGUiKTt2YXIgcmVxdWlyZT1jcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybC5zdGFydHNXaXRoKCJmaWxlOiIpP2ltcG9ydC5tZXRhLnVybDpwcm9jZXNzLmN3ZCgpKyIvIik7dmFyIHdvcmtlcl90aHJlYWRzPXJlcXVpcmUoIndvcmtlcl90aHJlYWRzIik7Z2xvYmFsLldvcmtlcj13b3JrZXJfdGhyZWFkcy5Xb3JrZXI7RU5WSVJPTk1FTlRfSVNfV09SS0VSPSF3b3JrZXJfdGhyZWFkcy5pc01haW5UaHJlYWQ7RU5WSVJPTk1FTlRfSVNfUFRIUkVBRD1FTlZJUk9OTUVOVF9JU19XT1JLRVImJndvcmtlcl90aHJlYWRzWyJ3b3JrZXJEYXRhIl09PSJlbS1wdGhyZWFkIn12YXIgYXJndW1lbnRzXz1bXTt2YXIgdGhpc1Byb2dyYW09Ii4vdGhpcy5wcm9ncmFtIjt2YXIgcXVpdF89KHN0YXR1cyx0b1Rocm93KT0+e3Rocm93IHRvVGhyb3d9O3ZhciBfc2NyaXB0TmFtZT1pbXBvcnQubWV0YS51cmw7dmFyIHNjcmlwdERpcmVjdG9yeT0iIjtmdW5jdGlvbiBsb2NhdGVGaWxlKHBhdGgpe2lmKE1vZHVsZVsibG9jYXRlRmlsZSJdKXtyZXR1cm4gTW9kdWxlWyJsb2NhdGVGaWxlIl0ocGF0aCxzY3JpcHREaXJlY3RvcnkpfXJldHVybiBzY3JpcHREaXJlY3RvcnkrcGF0aH12YXIgcmVhZEFzeW5jLHJlYWRCaW5hcnk7aWYoRU5WSVJPTk1FTlRfSVNfTk9ERSl7dmFyIGZzPXJlcXVpcmUoImZzIik7aWYoX3NjcmlwdE5hbWUuc3RhcnRzV2l0aCgiZmlsZToiKSl7c2NyaXB0RGlyZWN0b3J5PXJlcXVpcmUoInBhdGgiKS5kaXJuYW1lKHJlcXVpcmUoInVybCIpLmZpbGVVUkxUb1BhdGgoX3NjcmlwdE5hbWUpKSsiLyJ9cmVhZEJpbmFyeT1maWxlbmFtZT0+e2ZpbGVuYW1lPWlzRmlsZVVSSShmaWxlbmFtZSk/bmV3IFVSTChmaWxlbmFtZSk6ZmlsZW5hbWU7dmFyIHJldD1mcy5yZWFkRmlsZVN5bmMoZmlsZW5hbWUpO3JldHVybiByZXR9O3JlYWRBc3luYz1hc3luYyhmaWxlbmFtZSxiaW5hcnk9dHJ1ZSk9PntmaWxlbmFtZT1pc0ZpbGVVUkkoZmlsZW5hbWUpP25ldyBVUkwoZmlsZW5hbWUpOmZpbGVuYW1lO3ZhciByZXQ9ZnMucmVhZEZpbGVTeW5jKGZpbGVuYW1lLGJpbmFyeT91bmRlZmluZWQ6InV0ZjgiKTtyZXR1cm4gcmV0fTtpZihwcm9jZXNzLmFyZ3YubGVuZ3RoPjEpe3RoaXNQcm9ncmFtPXByb2Nlc3MuYXJndlsxXS5yZXBsYWNlKC9cXC9nLCIvIil9YXJndW1lbnRzXz1wcm9jZXNzLmFyZ3Yuc2xpY2UoMik7cXVpdF89KHN0YXR1cyx0b1Rocm93KT0+e3Byb2Nlc3MuZXhpdENvZGU9c3RhdHVzO3Rocm93IHRvVGhyb3d9fWVsc2UgaWYoRU5WSVJPTk1FTlRfSVNfV0VCfHxFTlZJUk9OTUVOVF9JU19XT1JLRVIpe3RyeXtzY3JpcHREaXJlY3Rvcnk9bmV3IFVSTCgiLiIsX3NjcmlwdE5hbWUpLmhyZWZ9Y2F0Y2h7fWlmKCFFTlZJUk9OTUVOVF9JU19OT0RFKXtpZihFTlZJUk9OTUVOVF9JU19XT1JLRVIpe3JlYWRCaW5hcnk9dXJsPT57dmFyIHhocj1uZXcgWE1MSHR0cFJlcXVlc3Q7eGhyLm9wZW4oIkdFVCIsdXJsLGZhbHNlKTt4aHIucmVzcG9uc2VUeXBlPSJhcnJheWJ1ZmZlciI7eGhyLnNlbmQobnVsbCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KHhoci5yZXNwb25zZSl9fXJlYWRBc3luYz1hc3luYyB1cmw9Pnt2YXIgcmVzcG9uc2U9YXdhaXQgZmV0Y2godXJsLHtjcmVkZW50aWFsczoic2FtZS1vcmlnaW4ifSk7aWYocmVzcG9uc2Uub2spe3JldHVybiByZXNwb25zZS5hcnJheUJ1ZmZlcigpfXRocm93IG5ldyBFcnJvcihyZXNwb25zZS5zdGF0dXMrIiA6ICIrcmVzcG9uc2UudXJsKX19fWVsc2V7fXZhciBkZWZhdWx0UHJpbnQ9Y29uc29sZS5sb2cuYmluZChjb25zb2xlKTt2YXIgZGVmYXVsdFByaW50RXJyPWNvbnNvbGUuZXJyb3IuYmluZChjb25zb2xlKTtpZihFTlZJUk9OTUVOVF9JU19OT0RFKXt2YXIgdXRpbHM9cmVxdWlyZSgidXRpbCIpO3ZhciBzdHJpbmdpZnk9YT0+dHlwZW9mIGE9PSJvYmplY3QiP3V0aWxzLmluc3BlY3QoYSk6YTtkZWZhdWx0UHJpbnQ9KC4uLmFyZ3MpPT5mcy53cml0ZVN5bmMoMSxhcmdzLm1hcChzdHJpbmdpZnkpLmpvaW4oIiAiKSsiXG4iKTtkZWZhdWx0UHJpbnRFcnI9KC4uLmFyZ3MpPT5mcy53cml0ZVN5bmMoMixhcmdzLm1hcChzdHJpbmdpZnkpLmpvaW4oIiAiKSsiXG4iKX12YXIgb3V0PWRlZmF1bHRQcmludDt2YXIgZXJyPWRlZmF1bHRQcmludEVycjt2YXIgd2FzbUJpbmFyeTt2YXIgd2FzbU1vZHVsZTt2YXIgQUJPUlQ9ZmFsc2U7dmFyIEVYSVRTVEFUVVM7dmFyIGlzRmlsZVVSST1maWxlbmFtZT0+ZmlsZW5hbWUuc3RhcnRzV2l0aCgiZmlsZTovLyIpO2Z1bmN0aW9uIGdyb3dNZW1WaWV3cygpe2lmKHdhc21NZW1vcnkuYnVmZmVyIT1IRUFQOC5idWZmZXIpe3VwZGF0ZU1lbW9yeVZpZXdzKCl9fXZhciByZWFkeVByb21pc2VSZXNvbHZlLHJlYWR5UHJvbWlzZVJlamVjdDtpZihFTlZJUk9OTUVOVF9JU19OT0RFJiZFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt2YXIgcGFyZW50UG9ydD13b3JrZXJfdGhyZWFkc1sicGFyZW50UG9ydCJdO3BhcmVudFBvcnQub24oIm1lc3NhZ2UiLG1zZz0+Z2xvYmFsLm9ubWVzc2FnZT8uKHtkYXRhOm1zZ30pKTtPYmplY3QuYXNzaWduKGdsb2JhbFRoaXMse3NlbGY6Z2xvYmFsLHBvc3RNZXNzYWdlOm1zZz0+cGFyZW50UG9ydFsicG9zdE1lc3NhZ2UiXShtc2cpfSk7cHJvY2Vzcy5vbigidW5jYXVnaHRFeGNlcHRpb24iLGVycj0+e3Bvc3RNZXNzYWdlKHtjbWQ6InVuY2F1Z2h0RXhjZXB0aW9uIixlcnJvcjplcnJ9KTtwcm9jZXNzLmV4aXQoMSl9KX12YXIgc3RhcnRXb3JrZXI7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7dmFyIGluaXRpYWxpemVkSlM9ZmFsc2U7c2VsZi5vbnVuaGFuZGxlZHJlamVjdGlvbj1lPT57dGhyb3cgZS5yZWFzb258fGV9O2Z1bmN0aW9uIGhhbmRsZU1lc3NhZ2UoZSl7dHJ5e3ZhciBtc2dEYXRhPWVbImRhdGEiXTt2YXIgY21kPW1zZ0RhdGEuY21kO2lmKGNtZD09PSJsb2FkIil7bGV0IG1lc3NhZ2VRdWV1ZT1bXTtzZWxmLm9ubWVzc2FnZT1lPT5tZXNzYWdlUXVldWUucHVzaChlKTtzdGFydFdvcmtlcj0oKT0+e3Bvc3RNZXNzYWdlKHtjbWQ6ImxvYWRlZCJ9KTtmb3IobGV0IG1zZyBvZiBtZXNzYWdlUXVldWUpe2hhbmRsZU1lc3NhZ2UobXNnKX1zZWxmLm9ubWVzc2FnZT1oYW5kbGVNZXNzYWdlfTtmb3IoY29uc3QgaGFuZGxlciBvZiBtc2dEYXRhLmhhbmRsZXJzKXtpZighTW9kdWxlW2hhbmRsZXJdfHxNb2R1bGVbaGFuZGxlcl0ucHJveHkpe01vZHVsZVtoYW5kbGVyXT0oLi4uYXJncyk9Pntwb3N0TWVzc2FnZSh7Y21kOiJjYWxsSGFuZGxlciIsaGFuZGxlcixhcmdzfSl9O2lmKGhhbmRsZXI9PSJwcmludCIpb3V0PU1vZHVsZVtoYW5kbGVyXTtpZihoYW5kbGVyPT0icHJpbnRFcnIiKWVycj1Nb2R1bGVbaGFuZGxlcl19fXdhc21NZW1vcnk9bXNnRGF0YS53YXNtTWVtb3J5O3VwZGF0ZU1lbW9yeVZpZXdzKCk7d2FzbU1vZHVsZT1tc2dEYXRhLndhc21Nb2R1bGU7Y3JlYXRlV2FzbSgpO3J1bigpfWVsc2UgaWYoY21kPT09InJ1biIpe2VzdGFibGlzaFN0YWNrU3BhY2UobXNnRGF0YS5wdGhyZWFkX3B0cik7X19lbXNjcmlwdGVuX3RocmVhZF9pbml0KG1zZ0RhdGEucHRocmVhZF9wdHIsMCwwLDEsMCwwKTtQVGhyZWFkLnRocmVhZEluaXRUTFMoKTtfX2Vtc2NyaXB0ZW5fdGhyZWFkX21haWxib3hfYXdhaXQobXNnRGF0YS5wdGhyZWFkX3B0cik7aWYoIWluaXRpYWxpemVkSlMpe2luaXRpYWxpemVkSlM9dHJ1ZX10cnl7aW52b2tlRW50cnlQb2ludChtc2dEYXRhLnN0YXJ0X3JvdXRpbmUsbXNnRGF0YS5hcmcpfWNhdGNoKGV4KXtpZihleCE9InVud2luZCIpe3Rocm93IGV4fX19ZWxzZSBpZihtc2dEYXRhLnRhcmdldD09PSJzZXRpbW1lZGlhdGUiKXt9ZWxzZSBpZihjbWQ9PT0iY2hlY2tNYWlsYm94Iil7aWYoaW5pdGlhbGl6ZWRKUyl7Y2hlY2tNYWlsYm94KCl9fWVsc2UgaWYoY21kKXtlcnIoYHdvcmtlcjogcmVjZWl2ZWQgdW5rbm93biBjb21tYW5kICR7Y21kfWApO2Vycihtc2dEYXRhKX19Y2F0Y2goZXgpe19fZW1zY3JpcHRlbl90aHJlYWRfY3Jhc2hlZCgpO3Rocm93IGV4fX1zZWxmLm9ubWVzc2FnZT1oYW5kbGVNZXNzYWdlfXZhciB3YXNtTWVtb3J5O3ZhciBIRUFQOCxIRUFQVTgsSEVBUDE2LEhFQVBVMTYsSEVBUDMyLEhFQVBVMzIsSEVBUEYzMixIRUFQRjY0O3ZhciBIRUFQNjQsSEVBUFU2NDt2YXIgcnVudGltZUluaXRpYWxpemVkPWZhbHNlO2Z1bmN0aW9uIHVwZGF0ZU1lbW9yeVZpZXdzKCl7dmFyIGI9d2FzbU1lbW9yeS5idWZmZXI7SEVBUDg9bmV3IEludDhBcnJheShiKTtIRUFQMTY9bmV3IEludDE2QXJyYXkoYik7SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO0hFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO0hFQVAzMj1uZXcgSW50MzJBcnJheShiKTtIRUFQVTMyPW5ldyBVaW50MzJBcnJheShiKTtIRUFQRjMyPW5ldyBGbG9hdDMyQXJyYXkoYik7SEVBUEY2ND1uZXcgRmxvYXQ2NEFycmF5KGIpO0hFQVA2ND1uZXcgQmlnSW50NjRBcnJheShiKTtIRUFQVTY0PW5ldyBCaWdVaW50NjRBcnJheShiKX1mdW5jdGlvbiBpbml0TWVtb3J5KCl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7cmV0dXJufWlmKE1vZHVsZVsid2FzbU1lbW9yeSJdKXt3YXNtTWVtb3J5PU1vZHVsZVsid2FzbU1lbW9yeSJdfWVsc2V7dmFyIElOSVRJQUxfTUVNT1JZPU1vZHVsZVsiSU5JVElBTF9NRU1PUlkiXXx8NjcxMDg4NjQ7d2FzbU1lbW9yeT1uZXcgV2ViQXNzZW1ibHkuTWVtb3J5KHtpbml0aWFsOklOSVRJQUxfTUVNT1JZLzY1NTM2LG1heGltdW06NjU1MzYsc2hhcmVkOnRydWV9KX11cGRhdGVNZW1vcnlWaWV3cygpfWZ1bmN0aW9uIHByZVJ1bigpe2lmKE1vZHVsZVsicHJlUnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInByZVJ1biJdPT0iZnVuY3Rpb24iKU1vZHVsZVsicHJlUnVuIl09W01vZHVsZVsicHJlUnVuIl1dO3doaWxlKE1vZHVsZVsicHJlUnVuIl0ubGVuZ3RoKXthZGRPblByZVJ1bihNb2R1bGVbInByZVJ1biJdLnNoaWZ0KCkpfX1jYWxsUnVudGltZUNhbGxiYWNrcyhvblByZVJ1bnMpfWZ1bmN0aW9uIGluaXRSdW50aW1lKCl7cnVudGltZUluaXRpYWxpemVkPXRydWU7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRClyZXR1cm4gc3RhcnRXb3JrZXIoKTt3YXNtRXhwb3J0c1sibyJdKCl9ZnVuY3Rpb24gcG9zdFJ1bigpe2lmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpe3JldHVybn1pZihNb2R1bGVbInBvc3RSdW4iXSl7aWYodHlwZW9mIE1vZHVsZVsicG9zdFJ1biJdPT0iZnVuY3Rpb24iKU1vZHVsZVsicG9zdFJ1biJdPVtNb2R1bGVbInBvc3RSdW4iXV07d2hpbGUoTW9kdWxlWyJwb3N0UnVuIl0ubGVuZ3RoKXthZGRPblBvc3RSdW4oTW9kdWxlWyJwb3N0UnVuIl0uc2hpZnQoKSl9fWNhbGxSdW50aW1lQ2FsbGJhY2tzKG9uUG9zdFJ1bnMpfWZ1bmN0aW9uIGFib3J0KHdoYXQpe01vZHVsZVsib25BYm9ydCJdPy4od2hhdCk7d2hhdD0iQWJvcnRlZCgiK3doYXQrIikiO2Vycih3aGF0KTtBQk9SVD10cnVlO3doYXQrPSIuIEJ1aWxkIHdpdGggLXNBU1NFUlRJT05TIGZvciBtb3JlIGluZm8uIjt2YXIgZT1uZXcgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yKHdoYXQpO3JlYWR5UHJvbWlzZVJlamVjdD8uKGUpO3Rocm93IGV9dmFyIHdhc21CaW5hcnlGaWxlO2Z1bmN0aW9uIGZpbmRXYXNtQmluYXJ5KCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBsb2NhdGVGaWxlKCJza2FpbmV0X2tlcm5lbHNfbXQud2FzbSIpfXRyeXtyZXR1cm4gbmV3IFVSTCgic2thaW5ldF9rZXJuZWxzX210Lndhc20iLGltcG9ydC5tZXRhLnVybCkuaHJlZn1jYXRjaChlKXtyZXR1cm4gInNrYWluZXRfa2VybmVsc19tdC53YXNtIn19ZnVuY3Rpb24gZ2V0QmluYXJ5U3luYyhmaWxlKXtpZihmaWxlPT13YXNtQmluYXJ5RmlsZSYmd2FzbUJpbmFyeSl7cmV0dXJuIG5ldyBVaW50OEFycmF5KHdhc21CaW5hcnkpfWlmKHJlYWRCaW5hcnkpe3JldHVybiByZWFkQmluYXJ5KGZpbGUpfXRocm93ImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkIn1hc3luYyBmdW5jdGlvbiBnZXRXYXNtQmluYXJ5KGJpbmFyeUZpbGUpe2lmKCF3YXNtQmluYXJ5KXt0cnl7dmFyIHJlc3BvbnNlPWF3YWl0IHJlYWRBc3luYyhiaW5hcnlGaWxlKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkocmVzcG9uc2UpfWNhdGNoe319cmV0dXJuIGdldEJpbmFyeVN5bmMoYmluYXJ5RmlsZSl9YXN5bmMgZnVuY3Rpb24gaW5zdGFudGlhdGVBcnJheUJ1ZmZlcihiaW5hcnlGaWxlLGltcG9ydHMpe3RyeXt2YXIgYmluYXJ5PWF3YWl0IGdldFdhc21CaW5hcnkoYmluYXJ5RmlsZSk7dmFyIGluc3RhbmNlPWF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJpbmFyeSxpbXBvcnRzKTtyZXR1cm4gaW5zdGFuY2V9Y2F0Y2gocmVhc29uKXtlcnIoYGZhaWxlZCB0byBhc3luY2hyb25vdXNseSBwcmVwYXJlIHdhc206ICR7cmVhc29ufWApO2Fib3J0KHJlYXNvbil9fWFzeW5jIGZ1bmN0aW9uIGluc3RhbnRpYXRlQXN5bmMoYmluYXJ5LGJpbmFyeUZpbGUsaW1wb3J0cyl7aWYoIWJpbmFyeSYmIUVOVklST05NRU5UX0lTX05PREUpe3RyeXt2YXIgcmVzcG9uc2U9ZmV0Y2goYmluYXJ5RmlsZSx7Y3JlZGVudGlhbHM6InNhbWUtb3JpZ2luIn0pO3ZhciBpbnN0YW50aWF0aW9uUmVzdWx0PWF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKHJlc3BvbnNlLGltcG9ydHMpO3JldHVybiBpbnN0YW50aWF0aW9uUmVzdWx0fWNhdGNoKHJlYXNvbil7ZXJyKGB3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogJHtyZWFzb259YCk7ZXJyKCJmYWxsaW5nIGJhY2sgdG8gQXJyYXlCdWZmZXIgaW5zdGFudGlhdGlvbiIpfX1yZXR1cm4gaW5zdGFudGlhdGVBcnJheUJ1ZmZlcihiaW5hcnlGaWxlLGltcG9ydHMpfWZ1bmN0aW9uIGdldFdhc21JbXBvcnRzKCl7YXNzaWduV2FzbUltcG9ydHMoKTtyZXR1cm57YTp3YXNtSW1wb3J0c319YXN5bmMgZnVuY3Rpb24gY3JlYXRlV2FzbSgpe2Z1bmN0aW9uIHJlY2VpdmVJbnN0YW5jZShpbnN0YW5jZSxtb2R1bGUpe3dhc21FeHBvcnRzPWluc3RhbmNlLmV4cG9ydHM7d2FzbUV4cG9ydHM9YXBwbHlTaWduYXR1cmVDb252ZXJzaW9ucyh3YXNtRXhwb3J0cyk7cmVnaXN0ZXJUTFNJbml0KHdhc21FeHBvcnRzWyJLIl0pO3dhc21UYWJsZT13YXNtRXhwb3J0c1sicSJdO3dhc21Nb2R1bGU9bW9kdWxlO2Fzc2lnbldhc21FeHBvcnRzKHdhc21FeHBvcnRzKTtyZXR1cm4gd2FzbUV4cG9ydHN9ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZXR1cm4gcmVjZWl2ZUluc3RhbmNlKHJlc3VsdFsiaW5zdGFuY2UiXSxyZXN1bHRbIm1vZHVsZSJdKX12YXIgaW5mbz1nZXRXYXNtSW1wb3J0cygpO2lmKE1vZHVsZVsiaW5zdGFudGlhdGVXYXNtIl0pe3JldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSxyZWplY3QpPT57TW9kdWxlWyJpbnN0YW50aWF0ZVdhc20iXShpbmZvLChtb2QsaW5zdCk9PntyZXNvbHZlKHJlY2VpdmVJbnN0YW5jZShtb2QsaW5zdCkpfSl9KX1pZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt2YXIgaW5zdGFuY2U9bmV3IFdlYkFzc2VtYmx5Lkluc3RhbmNlKHdhc21Nb2R1bGUsZ2V0V2FzbUltcG9ydHMoKSk7cmV0dXJuIHJlY2VpdmVJbnN0YW5jZShpbnN0YW5jZSx3YXNtTW9kdWxlKX13YXNtQmluYXJ5RmlsZT8/PWZpbmRXYXNtQmluYXJ5KCk7dmFyIHJlc3VsdD1hd2FpdCBpbnN0YW50aWF0ZUFzeW5jKHdhc21CaW5hcnksd2FzbUJpbmFyeUZpbGUsaW5mbyk7dmFyIGV4cG9ydHM9cmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KTtyZXR1cm4gZXhwb3J0c31jbGFzcyBFeGl0U3RhdHVze25hbWU9IkV4aXRTdGF0dXMiO2NvbnN0cnVjdG9yKHN0YXR1cyl7dGhpcy5tZXNzYWdlPWBQcm9ncmFtIHRlcm1pbmF0ZWQgd2l0aCBleGl0KCR7c3RhdHVzfSlgO3RoaXMuc3RhdHVzPXN0YXR1c319dmFyIHRlcm1pbmF0ZVdvcmtlcj13b3JrZXI9Pnt3b3JrZXIudGVybWluYXRlKCk7d29ya2VyLm9ubWVzc2FnZT1lPT57fX07dmFyIGNsZWFudXBUaHJlYWQ9cHRocmVhZF9wdHI9Pnt2YXIgd29ya2VyPVBUaHJlYWQucHRocmVhZHNbcHRocmVhZF9wdHJdO1BUaHJlYWQucmV0dXJuV29ya2VyVG9Qb29sKHdvcmtlcil9O3ZhciBjYWxsUnVudGltZUNhbGxiYWNrcz1jYWxsYmFja3M9Pnt3aGlsZShjYWxsYmFja3MubGVuZ3RoPjApe2NhbGxiYWNrcy5zaGlmdCgpKE1vZHVsZSl9fTt2YXIgb25QcmVSdW5zPVtdO3ZhciBhZGRPblByZVJ1bj1jYj0+b25QcmVSdW5zLnB1c2goY2IpO3ZhciBydW5EZXBlbmRlbmNpZXM9MDt2YXIgZGVwZW5kZW5jaWVzRnVsZmlsbGVkPW51bGw7dmFyIHJlbW92ZVJ1bkRlcGVuZGVuY3k9aWQ9PntydW5EZXBlbmRlbmNpZXMtLTtNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXT8uKHJ1bkRlcGVuZGVuY2llcyk7aWYocnVuRGVwZW5kZW5jaWVzPT0wKXtpZihkZXBlbmRlbmNpZXNGdWxmaWxsZWQpe3ZhciBjYWxsYmFjaz1kZXBlbmRlbmNpZXNGdWxmaWxsZWQ7ZGVwZW5kZW5jaWVzRnVsZmlsbGVkPW51bGw7Y2FsbGJhY2soKX19fTt2YXIgYWRkUnVuRGVwZW5kZW5jeT1pZD0+e3J1bkRlcGVuZGVuY2llcysrO01vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdPy4ocnVuRGVwZW5kZW5jaWVzKX07dmFyIHNwYXduVGhyZWFkPXRocmVhZFBhcmFtcz0+e3ZhciB3b3JrZXI9UFRocmVhZC5nZXROZXdXb3JrZXIoKTtpZighd29ya2VyKXtyZXR1cm4gNn1QVGhyZWFkLnJ1bm5pbmdXb3JrZXJzLnB1c2god29ya2VyKTtQVGhyZWFkLnB0aHJlYWRzW3RocmVhZFBhcmFtcy5wdGhyZWFkX3B0cl09d29ya2VyO3dvcmtlci5wdGhyZWFkX3B0cj10aHJlYWRQYXJhbXMucHRocmVhZF9wdHI7dmFyIG1zZz17Y21kOiJydW4iLHN0YXJ0X3JvdXRpbmU6dGhyZWFkUGFyYW1zLnN0YXJ0Um91dGluZSxhcmc6dGhyZWFkUGFyYW1zLmFyZyxwdGhyZWFkX3B0cjp0aHJlYWRQYXJhbXMucHRocmVhZF9wdHJ9O2lmKEVOVklST05NRU5UX0lTX05PREUpe3dvcmtlci51bnJlZigpfXdvcmtlci5wb3N0TWVzc2FnZShtc2csdGhyZWFkUGFyYW1zLnRyYW5zZmVyTGlzdCk7cmV0dXJuIDB9O3ZhciBydW50aW1lS2VlcGFsaXZlQ291bnRlcj0wO3ZhciBrZWVwUnVudGltZUFsaXZlPSgpPT5ub0V4aXRSdW50aW1lfHxydW50aW1lS2VlcGFsaXZlQ291bnRlcj4wO3ZhciBzdGFja1NhdmU9KCk9Pl9lbXNjcmlwdGVuX3N0YWNrX2dldF9jdXJyZW50KCk7dmFyIHN0YWNrUmVzdG9yZT12YWw9Pl9fZW1zY3JpcHRlbl9zdGFja19yZXN0b3JlKHZhbCk7dmFyIHN0YWNrQWxsb2M9c3o9Pl9fZW1zY3JpcHRlbl9zdGFja19hbGxvYyhzeik7dmFyIHByb3h5VG9NYWluVGhyZWFkPShmdW5jSW5kZXgsZW1Bc21BZGRyLHN5bmMsLi4uY2FsbEFyZ3MpPT57dmFyIHNlcmlhbGl6ZWROdW1DYWxsQXJncz1jYWxsQXJncy5sZW5ndGgqMjt2YXIgc3A9c3RhY2tTYXZlKCk7dmFyIGFyZ3M9c3RhY2tBbGxvYyhzZXJpYWxpemVkTnVtQ2FsbEFyZ3MqOCk7dmFyIGI9YXJncz4+PjM7Zm9yKHZhciBpPTA7aTxjYWxsQXJncy5sZW5ndGg7aSsrKXt2YXIgYXJnPWNhbGxBcmdzW2ldO2lmKHR5cGVvZiBhcmc9PSJiaWdpbnQiKXsoZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaT4+PjBdPTFuOyhncm93TWVtVmlld3MoKSxIRUFQNjQpW2IrMippKzE+Pj4wXT1hcmd9ZWxzZXsoZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaT4+PjBdPTBuOyhncm93TWVtVmlld3MoKSxIRUFQRjY0KVtiKzIqaSsxPj4+MF09YXJnfX12YXIgcnRuPV9fZW1zY3JpcHRlbl9ydW5fanNfb25fbWFpbl90aHJlYWQoZnVuY0luZGV4LGVtQXNtQWRkcixzZXJpYWxpemVkTnVtQ2FsbEFyZ3MsYXJncyxzeW5jKTtzdGFja1Jlc3RvcmUoc3ApO3JldHVybiBydG59O2Z1bmN0aW9uIF9wcm9jX2V4aXQoY29kZSl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRClyZXR1cm4gcHJveHlUb01haW5UaHJlYWQoMCwwLDEsY29kZSk7RVhJVFNUQVRVUz1jb2RlO2lmKCFrZWVwUnVudGltZUFsaXZlKCkpe1BUaHJlYWQudGVybWluYXRlQWxsVGhyZWFkcygpO01vZHVsZVsib25FeGl0Il0/Lihjb2RlKTtBQk9SVD10cnVlfXF1aXRfKGNvZGUsbmV3IEV4aXRTdGF0dXMoY29kZSkpfWZ1bmN0aW9uIGV4aXRPbk1haW5UaHJlYWQocmV0dXJuQ29kZSl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRClyZXR1cm4gcHJveHlUb01haW5UaHJlYWQoMSwwLDAscmV0dXJuQ29kZSk7X2V4aXQocmV0dXJuQ29kZSl9dmFyIGV4aXRKUz0oc3RhdHVzLGltcGxpY2l0KT0+e0VYSVRTVEFUVVM9c3RhdHVzO2lmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpe2V4aXRPbk1haW5UaHJlYWQoc3RhdHVzKTt0aHJvdyJ1bndpbmQifV9wcm9jX2V4aXQoc3RhdHVzKX07dmFyIF9leGl0PWV4aXRKUzt2YXIgUFRocmVhZD17dW51c2VkV29ya2VyczpbXSxydW5uaW5nV29ya2VyczpbXSx0bHNJbml0RnVuY3Rpb25zOltdLHB0aHJlYWRzOnt9LGluaXQoKXtpZighRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7UFRocmVhZC5pbml0TWFpblRocmVhZCgpfX0saW5pdE1haW5UaHJlYWQoKXt2YXIgcHRocmVhZFBvb2xTaXplPTQ7d2hpbGUocHRocmVhZFBvb2xTaXplLS0pe1BUaHJlYWQuYWxsb2NhdGVVbnVzZWRXb3JrZXIoKX1hZGRPblByZVJ1bihhc3luYygpPT57dmFyIHB0aHJlYWRQb29sUmVhZHk9UFRocmVhZC5sb2FkV2FzbU1vZHVsZVRvQWxsV29ya2VycygpO2FkZFJ1bkRlcGVuZGVuY3koImxvYWRpbmctd29ya2VycyIpO2F3YWl0IHB0aHJlYWRQb29sUmVhZHk7cmVtb3ZlUnVuRGVwZW5kZW5jeSgibG9hZGluZy13b3JrZXJzIil9KX0sdGVybWluYXRlQWxsVGhyZWFkczooKT0+e2Zvcih2YXIgd29ya2VyIG9mIFBUaHJlYWQucnVubmluZ1dvcmtlcnMpe3Rlcm1pbmF0ZVdvcmtlcih3b3JrZXIpfWZvcih2YXIgd29ya2VyIG9mIFBUaHJlYWQudW51c2VkV29ya2Vycyl7dGVybWluYXRlV29ya2VyKHdvcmtlcil9UFRocmVhZC51bnVzZWRXb3JrZXJzPVtdO1BUaHJlYWQucnVubmluZ1dvcmtlcnM9W107UFRocmVhZC5wdGhyZWFkcz17fX0scmV0dXJuV29ya2VyVG9Qb29sOndvcmtlcj0+e3ZhciBwdGhyZWFkX3B0cj13b3JrZXIucHRocmVhZF9wdHI7ZGVsZXRlIFBUaHJlYWQucHRocmVhZHNbcHRocmVhZF9wdHJdO1BUaHJlYWQudW51c2VkV29ya2Vycy5wdXNoKHdvcmtlcik7UFRocmVhZC5ydW5uaW5nV29ya2Vycy5zcGxpY2UoUFRocmVhZC5ydW5uaW5nV29ya2Vycy5pbmRleE9mKHdvcmtlciksMSk7d29ya2VyLnB0aHJlYWRfcHRyPTA7X19lbXNjcmlwdGVuX3RocmVhZF9mcmVlX2RhdGEocHRocmVhZF9wdHIpfSx0aHJlYWRJbml0VExTKCl7UFRocmVhZC50bHNJbml0RnVuY3Rpb25zLmZvckVhY2goZj0+ZigpKX0sbG9hZFdhc21Nb2R1bGVUb1dvcmtlcjp3b3JrZXI9Pm5ldyBQcm9taXNlKG9uRmluaXNoZWRMb2FkaW5nPT57d29ya2VyLm9ubWVzc2FnZT1lPT57dmFyIGQ9ZVsiZGF0YSJdO3ZhciBjbWQ9ZC5jbWQ7aWYoZC50YXJnZXRUaHJlYWQmJmQudGFyZ2V0VGhyZWFkIT1fcHRocmVhZF9zZWxmKCkpe3ZhciB0YXJnZXRXb3JrZXI9UFRocmVhZC5wdGhyZWFkc1tkLnRhcmdldFRocmVhZF07aWYodGFyZ2V0V29ya2VyKXt0YXJnZXRXb3JrZXIucG9zdE1lc3NhZ2UoZCxkLnRyYW5zZmVyTGlzdCl9ZWxzZXtlcnIoYEludGVybmFsIGVycm9yISBXb3JrZXIgc2VudCBhIG1lc3NhZ2UgIiR7Y21kfSIgdG8gdGFyZ2V0IHB0aHJlYWQgJHtkLnRhcmdldFRocmVhZH0sIGJ1dCB0aGF0IHRocmVhZCBubyBsb25nZXIgZXhpc3RzIWApfXJldHVybn1pZihjbWQ9PT0iY2hlY2tNYWlsYm94Iil7Y2hlY2tNYWlsYm94KCl9ZWxzZSBpZihjbWQ9PT0ic3Bhd25UaHJlYWQiKXtzcGF3blRocmVhZChkKX1lbHNlIGlmKGNtZD09PSJjbGVhbnVwVGhyZWFkIil7Y2FsbFVzZXJDYWxsYmFjaygoKT0+Y2xlYW51cFRocmVhZChkLnRocmVhZCkpfWVsc2UgaWYoY21kPT09ImxvYWRlZCIpe3dvcmtlci5sb2FkZWQ9dHJ1ZTtpZihFTlZJUk9OTUVOVF9JU19OT0RFJiYhd29ya2VyLnB0aHJlYWRfcHRyKXt3b3JrZXIudW5yZWYoKX1vbkZpbmlzaGVkTG9hZGluZyh3b3JrZXIpfWVsc2UgaWYoZC50YXJnZXQ9PT0ic2V0aW1tZWRpYXRlIil7d29ya2VyLnBvc3RNZXNzYWdlKGQpfWVsc2UgaWYoY21kPT09InVuY2F1Z2h0RXhjZXB0aW9uIil7d29ya2VyLm9uZXJyb3IoZC5lcnJvcil9ZWxzZSBpZihjbWQ9PT0iY2FsbEhhbmRsZXIiKXtNb2R1bGVbZC5oYW5kbGVyXSguLi5kLmFyZ3MpfWVsc2UgaWYoY21kKXtlcnIoYHdvcmtlciBzZW50IGFuIHVua25vd24gY29tbWFuZCAke2NtZH1gKX19O3dvcmtlci5vbmVycm9yPWU9Pnt2YXIgbWVzc2FnZT0id29ya2VyIHNlbnQgYW4gZXJyb3IhIjtlcnIoYCR7bWVzc2FnZX0gJHtlLmZpbGVuYW1lfToke2UubGluZW5vfTogJHtlLm1lc3NhZ2V9YCk7dGhyb3cgZX07aWYoRU5WSVJPTk1FTlRfSVNfTk9ERSl7d29ya2VyLm9uKCJtZXNzYWdlIixkYXRhPT53b3JrZXIub25tZXNzYWdlKHtkYXRhfSkpO3dvcmtlci5vbigiZXJyb3IiLGU9Pndvcmtlci5vbmVycm9yKGUpKX12YXIgaGFuZGxlcnM9W107dmFyIGtub3duSGFuZGxlcnM9WyJvbkV4aXQiLCJvbkFib3J0IiwicHJpbnQiLCJwcmludEVyciJdO2Zvcih2YXIgaGFuZGxlciBvZiBrbm93bkhhbmRsZXJzKXtpZihNb2R1bGUucHJvcGVydHlJc0VudW1lcmFibGUoaGFuZGxlcikpe2hhbmRsZXJzLnB1c2goaGFuZGxlcil9fXdvcmtlci5wb3N0TWVzc2FnZSh7Y21kOiJsb2FkIixoYW5kbGVycyx3YXNtTWVtb3J5LHdhc21Nb2R1bGV9KX0pLGFzeW5jIGxvYWRXYXNtTW9kdWxlVG9BbGxXb3JrZXJzKCl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7cmV0dXJufWxldCBwdGhyZWFkUG9vbFJlYWR5PVByb21pc2UuYWxsKFBUaHJlYWQudW51c2VkV29ya2Vycy5tYXAoUFRocmVhZC5sb2FkV2FzbU1vZHVsZVRvV29ya2VyKSk7cmV0dXJuIHB0aHJlYWRQb29sUmVhZHl9LGFsbG9jYXRlVW51c2VkV29ya2VyKCl7dmFyIHdvcmtlcjtpZihNb2R1bGVbIm1haW5TY3JpcHRVcmxPckJsb2IiXSl7dmFyIHB0aHJlYWRNYWluSnM9TW9kdWxlWyJtYWluU2NyaXB0VXJsT3JCbG9iIl07aWYodHlwZW9mIHB0aHJlYWRNYWluSnMhPSJzdHJpbmciKXtwdGhyZWFkTWFpbkpzPVVSTC5jcmVhdGVPYmplY3RVUkwocHRocmVhZE1haW5Kcyl9d29ya2VyPW5ldyBXb3JrZXIoRU5WSVJPTk1FTlRfSVNfTk9ERSYmdHlwZW9mIHB0aHJlYWRNYWluSnM9PSJzdHJpbmciJiZwdGhyZWFkTWFpbkpzLnN0YXJ0c1dpdGgoImRhdGE6Iik/bmV3IFVSTChwdGhyZWFkTWFpbkpzKTpwdGhyZWFkTWFpbkpzLHt0eXBlOiJtb2R1bGUiLHdvcmtlckRhdGE6ImVtLXB0aHJlYWQiLG5hbWU6ImVtLXB0aHJlYWQifSl9ZWxzZSB3b3JrZXI9bmV3IFdvcmtlcihuZXcgVVJMKCJza2FpbmV0X2tlcm5lbHNfbXQubWpzIixpbXBvcnQubWV0YS51cmwpLHt0eXBlOiJtb2R1bGUiLHdvcmtlckRhdGE6ImVtLXB0aHJlYWQiLG5hbWU6ImVtLXB0aHJlYWQifSk7UFRocmVhZC51bnVzZWRXb3JrZXJzLnB1c2god29ya2VyKX0sZ2V0TmV3V29ya2VyKCl7aWYoUFRocmVhZC51bnVzZWRXb3JrZXJzLmxlbmd0aD09MCl7UFRocmVhZC5hbGxvY2F0ZVVudXNlZFdvcmtlcigpO1BUaHJlYWQubG9hZFdhc21Nb2R1bGVUb1dvcmtlcihQVGhyZWFkLnVudXNlZFdvcmtlcnNbMF0pfXJldHVybiBQVGhyZWFkLnVudXNlZFdvcmtlcnMucG9wKCl9fTt2YXIgb25Qb3N0UnVucz1bXTt2YXIgYWRkT25Qb3N0UnVuPWNiPT5vblBvc3RSdW5zLnB1c2goY2IpO2Z1bmN0aW9uIGVzdGFibGlzaFN0YWNrU3BhY2UocHRocmVhZF9wdHIpe3ZhciBzdGFja0hpZ2g9KGdyb3dNZW1WaWV3cygpLEhFQVBVMzIpW3B0aHJlYWRfcHRyKzUyPj4+Mj4+PjBdO3ZhciBzdGFja1NpemU9KGdyb3dNZW1WaWV3cygpLEhFQVBVMzIpW3B0aHJlYWRfcHRyKzU2Pj4+Mj4+PjBdO3ZhciBzdGFja0xvdz1zdGFja0hpZ2gtc3RhY2tTaXplO19lbXNjcmlwdGVuX3N0YWNrX3NldF9saW1pdHMoc3RhY2tIaWdoLHN0YWNrTG93KTtzdGFja1Jlc3RvcmUoc3RhY2tIaWdoKX12YXIgd2FzbVRhYmxlTWlycm9yPVtdO3ZhciB3YXNtVGFibGU7dmFyIGdldFdhc21UYWJsZUVudHJ5PWZ1bmNQdHI9Pnt2YXIgZnVuYz13YXNtVGFibGVNaXJyb3JbZnVuY1B0cl07aWYoIWZ1bmMpe3dhc21UYWJsZU1pcnJvcltmdW5jUHRyXT1mdW5jPXdhc21UYWJsZS5nZXQoZnVuY1B0cil9cmV0dXJuIGZ1bmN9O3ZhciBpbnZva2VFbnRyeVBvaW50PShwdHIsYXJnKT0+e3J1bnRpbWVLZWVwYWxpdmVDb3VudGVyPTA7bm9FeGl0UnVudGltZT0wO3ZhciByZXN1bHQ9Z2V0V2FzbVRhYmxlRW50cnkocHRyKShhcmcpO2Z1bmN0aW9uIGZpbmlzaChyZXN1bHQpe2lmKGtlZXBSdW50aW1lQWxpdmUoKSl7RVhJVFNUQVRVUz1yZXN1bHQ7cmV0dXJufV9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdChyZXN1bHQpfWZpbmlzaChyZXN1bHQpfTt2YXIgbm9FeGl0UnVudGltZT10cnVlO3ZhciByZWdpc3RlclRMU0luaXQ9dGxzSW5pdEZ1bmM9PlBUaHJlYWQudGxzSW5pdEZ1bmN0aW9ucy5wdXNoKHRsc0luaXRGdW5jKTtmdW5jdGlvbiBwdGhyZWFkQ3JlYXRlUHJveGllZChwdGhyZWFkX3B0cixhdHRyLHN0YXJ0Um91dGluZSxhcmcpe2lmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpcmV0dXJuIHByb3h5VG9NYWluVGhyZWFkKDIsMCwxLHB0aHJlYWRfcHRyLGF0dHIsc3RhcnRSb3V0aW5lLGFyZyk7cmV0dXJuIF9fX3B0aHJlYWRfY3JlYXRlX2pzKHB0aHJlYWRfcHRyLGF0dHIsc3RhcnRSb3V0aW5lLGFyZyl9dmFyIF9lbXNjcmlwdGVuX2hhc190aHJlYWRpbmdfc3VwcG9ydD0oKT0+dHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyIT0idW5kZWZpbmVkIjtmdW5jdGlvbiBfX19wdGhyZWFkX2NyZWF0ZV9qcyhwdGhyZWFkX3B0cixhdHRyLHN0YXJ0Um91dGluZSxhcmcpe3B0aHJlYWRfcHRyPj4+PTA7YXR0cj4+Pj0wO3N0YXJ0Um91dGluZT4+Pj0wO2FyZz4+Pj0wO2lmKCFfZW1zY3JpcHRlbl9oYXNfdGhyZWFkaW5nX3N1cHBvcnQoKSl7cmV0dXJuIDZ9dmFyIHRyYW5zZmVyTGlzdD1bXTt2YXIgZXJyb3I9MDtpZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEJiYodHJhbnNmZXJMaXN0Lmxlbmd0aD09PTB8fGVycm9yKSl7cmV0dXJuIHB0aHJlYWRDcmVhdGVQcm94aWVkKHB0aHJlYWRfcHRyLGF0dHIsc3RhcnRSb3V0aW5lLGFyZyl9aWYoZXJyb3IpcmV0dXJuIGVycm9yO3ZhciB0aHJlYWRQYXJhbXM9e3N0YXJ0Um91dGluZSxwdGhyZWFkX3B0cixhcmcsdHJhbnNmZXJMaXN0fTtpZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt0aHJlYWRQYXJhbXMuY21kPSJzcGF3blRocmVhZCI7cG9zdE1lc3NhZ2UodGhyZWFkUGFyYW1zLHRyYW5zZmVyTGlzdCk7cmV0dXJuIDB9cmV0dXJuIHNwYXduVGhyZWFkKHRocmVhZFBhcmFtcyl9ZnVuY3Rpb24gX19lbXNjcmlwdGVuX2luaXRfbWFpbl90aHJlYWRfanModGIpe3RiPj4+PTA7X19lbXNjcmlwdGVuX3RocmVhZF9pbml0KHRiLCFFTlZJUk9OTUVOVF9JU19XT1JLRVIsMSwhRU5WSVJPTk1FTlRfSVNfV0VCLDY1NTM2LGZhbHNlKTtQVGhyZWFkLnRocmVhZEluaXRUTFMoKX12YXIgaGFuZGxlRXhjZXB0aW9uPWU9PntpZihlIGluc3RhbmNlb2YgRXhpdFN0YXR1c3x8ZT09InVud2luZCIpe3JldHVybiBFWElUU1RBVFVTfXF1aXRfKDEsZSl9O3ZhciBtYXliZUV4aXQ9KCk9PntpZigha2VlcFJ1bnRpbWVBbGl2ZSgpKXt0cnl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7aWYoX3B0aHJlYWRfc2VsZigpKV9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdChFWElUU1RBVFVTKTtyZXR1cm59X2V4aXQoRVhJVFNUQVRVUyl9Y2F0Y2goZSl7aGFuZGxlRXhjZXB0aW9uKGUpfX19O3ZhciBjYWxsVXNlckNhbGxiYWNrPWZ1bmM9PntpZihBQk9SVCl7cmV0dXJufXRyeXtmdW5jKCk7bWF5YmVFeGl0KCl9Y2F0Y2goZSl7aGFuZGxlRXhjZXB0aW9uKGUpfX07ZnVuY3Rpb24gX19lbXNjcmlwdGVuX3RocmVhZF9tYWlsYm94X2F3YWl0KHB0aHJlYWRfcHRyKXtwdGhyZWFkX3B0cj4+Pj0wO2lmKHR5cGVvZiBBdG9taWNzLndhaXRBc3luYz09PSJmdW5jdGlvbiIpe3ZhciB3YWl0PUF0b21pY3Mud2FpdEFzeW5jKChncm93TWVtVmlld3MoKSxIRUFQMzIpLHB0aHJlYWRfcHRyPj4+MixwdGhyZWFkX3B0cik7d2FpdC52YWx1ZS50aGVuKGNoZWNrTWFpbGJveCk7dmFyIHdhaXRpbmdBc3luYz1wdGhyZWFkX3B0cisxMjg7QXRvbWljcy5zdG9yZSgoZ3Jvd01lbVZpZXdzKCksSEVBUDMyKSx3YWl0aW5nQXN5bmM+Pj4yLDEpfX12YXIgY2hlY2tNYWlsYm94PSgpPT5jYWxsVXNlckNhbGxiYWNrKCgpPT57dmFyIHB0aHJlYWRfcHRyPV9wdGhyZWFkX3NlbGYoKTtpZihwdGhyZWFkX3B0cil7X19lbXNjcmlwdGVuX3RocmVhZF9tYWlsYm94X2F3YWl0KHB0aHJlYWRfcHRyKTtfX2Vtc2NyaXB0ZW5fY2hlY2tfbWFpbGJveCgpfX0pO2Z1bmN0aW9uIF9fZW1zY3JpcHRlbl9ub3RpZnlfbWFpbGJveF9wb3N0bWVzc2FnZSh0YXJnZXRUaHJlYWQsY3VyclRocmVhZElkKXt0YXJnZXRUaHJlYWQ+Pj49MDtjdXJyVGhyZWFkSWQ+Pj49MDtpZih0YXJnZXRUaHJlYWQ9PWN1cnJUaHJlYWRJZCl7c2V0VGltZW91dChjaGVja01haWxib3gpfWVsc2UgaWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7cG9zdE1lc3NhZ2Uoe3RhcmdldFRocmVhZCxjbWQ6ImNoZWNrTWFpbGJveCJ9KX1lbHNle3ZhciB3b3JrZXI9UFRocmVhZC5wdGhyZWFkc1t0YXJnZXRUaHJlYWRdO2lmKCF3b3JrZXIpe3JldHVybn13b3JrZXIucG9zdE1lc3NhZ2Uoe2NtZDoiY2hlY2tNYWlsYm94In0pfX12YXIgcHJveGllZEpTQ2FsbEFyZ3M9W107ZnVuY3Rpb24gX19lbXNjcmlwdGVuX3JlY2VpdmVfb25fbWFpbl90aHJlYWRfanMoZnVuY0luZGV4LGVtQXNtQWRkcixjYWxsaW5nVGhyZWFkLG51bUNhbGxBcmdzLGFyZ3Mpe2VtQXNtQWRkcj4+Pj0wO2NhbGxpbmdUaHJlYWQ+Pj49MDthcmdzPj4+PTA7bnVtQ2FsbEFyZ3MvPTI7cHJveGllZEpTQ2FsbEFyZ3MubGVuZ3RoPW51bUNhbGxBcmdzO3ZhciBiPWFyZ3M+Pj4zO2Zvcih2YXIgaT0wO2k8bnVtQ2FsbEFyZ3M7aSsrKXtpZigoZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaT4+PjBdKXtwcm94aWVkSlNDYWxsQXJnc1tpXT0oZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaSsxPj4+MF19ZWxzZXtwcm94aWVkSlNDYWxsQXJnc1tpXT0oZ3Jvd01lbVZpZXdzKCksSEVBUEY2NClbYisyKmkrMT4+PjBdfX12YXIgZnVuYz1wcm94aWVkRnVuY3Rpb25UYWJsZVtmdW5jSW5kZXhdO1BUaHJlYWQuY3VycmVudFByb3hpZWRPcGVyYXRpb25DYWxsZXJUaHJlYWQ9Y2FsbGluZ1RocmVhZDt2YXIgcnRuPWZ1bmMoLi4ucHJveGllZEpTQ2FsbEFyZ3MpO1BUaHJlYWQuY3VycmVudFByb3hpZWRPcGVyYXRpb25DYWxsZXJUaHJlYWQ9MDtyZXR1cm4gcnRufWZ1bmN0aW9uIF9fZW1zY3JpcHRlbl90aHJlYWRfY2xlYW51cCh0aHJlYWQpe3RocmVhZD4+Pj0wO2lmKCFFTlZJUk9OTUVOVF9JU19QVEhSRUFEKWNsZWFudXBUaHJlYWQodGhyZWFkKTtlbHNlIHBvc3RNZXNzYWdlKHtjbWQ6ImNsZWFudXBUaHJlYWQiLHRocmVhZH0pfWZ1bmN0aW9uIF9fZW1zY3JpcHRlbl90aHJlYWRfc2V0X3N0cm9uZ3JlZih0aHJlYWQpe3RocmVhZD4+Pj0wO2lmKEVOVklST05NRU5UX0lTX05PREUpe1BUaHJlYWQucHRocmVhZHNbdGhyZWFkXS5yZWYoKX19dmFyIF9lbXNjcmlwdGVuX2dldF9ub3c9KCk9PnBlcmZvcm1hbmNlLnRpbWVPcmlnaW4rcGVyZm9ybWFuY2Uubm93KCk7dmFyIF9lbXNjcmlwdGVuX2NoZWNrX2Jsb2NraW5nX2FsbG93ZWQ9KCk9Pnt9O3ZhciBydW50aW1lS2VlcGFsaXZlUHVzaD0oKT0+e3J1bnRpbWVLZWVwYWxpdmVDb3VudGVyKz0xfTt2YXIgX2Vtc2NyaXB0ZW5fZXhpdF93aXRoX2xpdmVfcnVudGltZT0oKT0+e3J1bnRpbWVLZWVwYWxpdmVQdXNoKCk7dGhyb3cidW53aW5kIn07dmFyIGdldEhlYXBNYXg9KCk9PjQyOTQ5MDE3NjA7dmFyIGFsaWduTWVtb3J5PShzaXplLGFsaWdubWVudCk9Pk1hdGguY2VpbChzaXplL2FsaWdubWVudCkqYWxpZ25tZW50O3ZhciBncm93TWVtb3J5PXNpemU9Pnt2YXIgb2xkSGVhcFNpemU9d2FzbU1lbW9yeS5idWZmZXIuYnl0ZUxlbmd0aDt2YXIgcGFnZXM9KHNpemUtb2xkSGVhcFNpemUrNjU1MzUpLzY1NTM2fDA7dHJ5e3dhc21NZW1vcnkuZ3JvdyhwYWdlcyk7dXBkYXRlTWVtb3J5Vmlld3MoKTtyZXR1cm4gMX1jYXRjaChlKXt9fTtmdW5jdGlvbiBfZW1zY3JpcHRlbl9yZXNpemVfaGVhcChyZXF1ZXN0ZWRTaXplKXtyZXF1ZXN0ZWRTaXplPj4+PTA7dmFyIG9sZFNpemU9KGdyb3dNZW1WaWV3cygpLEhFQVBVOCkubGVuZ3RoO2lmKHJlcXVlc3RlZFNpemU8PW9sZFNpemUpe3JldHVybiBmYWxzZX12YXIgbWF4SGVhcFNpemU9Z2V0SGVhcE1heCgpO2lmKHJlcXVlc3RlZFNpemU+bWF4SGVhcFNpemUpe3JldHVybiBmYWxzZX1mb3IodmFyIGN1dERvd249MTtjdXREb3duPD00O2N1dERvd24qPTIpe3ZhciBvdmVyR3Jvd25IZWFwU2l6ZT1vbGRTaXplKigxKy4yL2N1dERvd24pO292ZXJHcm93bkhlYXBTaXplPU1hdGgubWluKG92ZXJHcm93bkhlYXBTaXplLHJlcXVlc3RlZFNpemUrMTAwNjYzMjk2KTt2YXIgbmV3U2l6ZT1NYXRoLm1pbihtYXhIZWFwU2l6ZSxhbGlnbk1lbW9yeShNYXRoLm1heChyZXF1ZXN0ZWRTaXplLG92ZXJHcm93bkhlYXBTaXplKSw2NTUzNikpO3ZhciByZXBsYWNlbWVudD1ncm93TWVtb3J5KG5ld1NpemUpO2lmKHJlcGxhY2VtZW50KXtyZXR1cm4gdHJ1ZX19cmV0dXJuIGZhbHNlfXZhciBwcmludENoYXJCdWZmZXJzPVtudWxsLFtdLFtdXTt2YXIgVVRGOERlY29kZXI9dHlwZW9mIFRleHREZWNvZGVyIT0idW5kZWZpbmVkIj9uZXcgVGV4dERlY29kZXI6dW5kZWZpbmVkO3ZhciBmaW5kU3RyaW5nRW5kPShoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQsaWdub3JlTnVsKT0+e3ZhciBtYXhJZHg9aWR4K21heEJ5dGVzVG9SZWFkO2lmKGlnbm9yZU51bClyZXR1cm4gbWF4SWR4O3doaWxlKGhlYXBPckFycmF5W2lkeF0mJiEoaWR4Pj1tYXhJZHgpKSsraWR4O3JldHVybiBpZHh9O3ZhciBVVEY4QXJyYXlUb1N0cmluZz0oaGVhcE9yQXJyYXksaWR4PTAsbWF4Qnl0ZXNUb1JlYWQsaWdub3JlTnVsKT0+e2lkeD4+Pj0wO3ZhciBlbmRQdHI9ZmluZFN0cmluZ0VuZChoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQsaWdub3JlTnVsKTtpZihlbmRQdHItaWR4PjE2JiZoZWFwT3JBcnJheS5idWZmZXImJlVURjhEZWNvZGVyKXtyZXR1cm4gVVRGOERlY29kZXIuZGVjb2RlKGhlYXBPckFycmF5LmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP2hlYXBPckFycmF5LnN1YmFycmF5KGlkeCxlbmRQdHIpOmhlYXBPckFycmF5LnNsaWNlKGlkeCxlbmRQdHIpKX12YXIgc3RyPSIiO3doaWxlKGlkeDxlbmRQdHIpe3ZhciB1MD1oZWFwT3JBcnJheVtpZHgrK107aWYoISh1MCYxMjgpKXtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUodTApO2NvbnRpbnVlfXZhciB1MT1oZWFwT3JBcnJheVtpZHgrK10mNjM7aWYoKHUwJjIyNCk9PTE5Mil7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKCh1MCYzMSk8PDZ8dTEpO2NvbnRpbnVlfXZhciB1Mj1oZWFwT3JBcnJheVtpZHgrK10mNjM7aWYoKHUwJjI0MCk9PTIyNCl7dTA9KHUwJjE1KTw8MTJ8dTE8PDZ8dTJ9ZWxzZXt1MD0odTAmNyk8PDE4fHUxPDwxMnx1Mjw8NnxoZWFwT3JBcnJheVtpZHgrK10mNjN9aWYodTA8NjU1MzYpe3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSh1MCl9ZWxzZXt2YXIgY2g9dTAtNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKX19cmV0dXJuIHN0cn07dmFyIHByaW50Q2hhcj0oc3RyZWFtLGN1cnIpPT57dmFyIGJ1ZmZlcj1wcmludENoYXJCdWZmZXJzW3N0cmVhbV07aWYoY3Vycj09PTB8fGN1cnI9PT0xMCl7KHN0cmVhbT09PTE/b3V0OmVycikoVVRGOEFycmF5VG9TdHJpbmcoYnVmZmVyKSk7YnVmZmVyLmxlbmd0aD0wfWVsc2V7YnVmZmVyLnB1c2goY3Vycil9fTtmdW5jdGlvbiBfZmRfd3JpdGUoZmQsaW92LGlvdmNudCxwbnVtKXtpZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXJldHVybiBwcm94eVRvTWFpblRocmVhZCgzLDAsMSxmZCxpb3YsaW92Y250LHBudW0pO2lvdj4+Pj0wO2lvdmNudD4+Pj0wO3BudW0+Pj49MDt2YXIgbnVtPTA7Zm9yKHZhciBpPTA7aTxpb3ZjbnQ7aSsrKXt2YXIgcHRyPShncm93TWVtVmlld3MoKSxIRUFQVTMyKVtpb3Y+Pj4yPj4+MF07dmFyIGxlbj0oZ3Jvd01lbVZpZXdzKCksSEVBUFUzMilbaW92KzQ+Pj4yPj4+MF07aW92Kz04O2Zvcih2YXIgaj0wO2o8bGVuO2orKyl7cHJpbnRDaGFyKGZkLChncm93TWVtVmlld3MoKSxIRUFQVTgpW3B0citqPj4+MF0pfW51bSs9bGVufShncm93TWVtVmlld3MoKSxIRUFQVTMyKVtwbnVtPj4+Mj4+PjBdPW51bTtyZXR1cm4gMH1QVGhyZWFkLmluaXQoKTt7aW5pdE1lbW9yeSgpO2lmKE1vZHVsZVsibm9FeGl0UnVudGltZSJdKW5vRXhpdFJ1bnRpbWU9TW9kdWxlWyJub0V4aXRSdW50aW1lIl07aWYoTW9kdWxlWyJwcmludCJdKW91dD1Nb2R1bGVbInByaW50Il07aWYoTW9kdWxlWyJwcmludEVyciJdKWVycj1Nb2R1bGVbInByaW50RXJyIl07aWYoTW9kdWxlWyJ3YXNtQmluYXJ5Il0pd2FzbUJpbmFyeT1Nb2R1bGVbIndhc21CaW5hcnkiXTtpZihNb2R1bGVbImFyZ3VtZW50cyJdKWFyZ3VtZW50c189TW9kdWxlWyJhcmd1bWVudHMiXTtpZihNb2R1bGVbInRoaXNQcm9ncmFtIl0pdGhpc1Byb2dyYW09TW9kdWxlWyJ0aGlzUHJvZ3JhbSJdO2lmKE1vZHVsZVsicHJlSW5pdCJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVJbml0Il09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVJbml0Il09W01vZHVsZVsicHJlSW5pdCJdXTt3aGlsZShNb2R1bGVbInByZUluaXQiXS5sZW5ndGg+MCl7TW9kdWxlWyJwcmVJbml0Il0uc2hpZnQoKSgpfX19TW9kdWxlWyJ3YXNtTWVtb3J5Il09d2FzbU1lbW9yeTt2YXIgcHJveGllZEZ1bmN0aW9uVGFibGU9W19wcm9jX2V4aXQsZXhpdE9uTWFpblRocmVhZCxwdGhyZWFkQ3JlYXRlUHJveGllZCxfZmRfd3JpdGVdO3ZhciBfc2thaW5ldF9mcDMyX21hdG11bCxfc2thaW5ldF9mcDMyX21hdG11bF93dCxfc2thaW5ldF9iZjE2X21hdG11bCxfc2thaW5ldF9mcDE2X21hdG11bCxfc2thaW5ldF9xNF8wX21hdG11bCxfc2thaW5ldF9xNF8wX21hdG11bF9ybSxfc2thaW5ldF9xNV8wX21hdG11bCxfbWFsbG9jLF9mcmVlLF9za2FpbmV0X3E1XzBfbWF0bXVsX3JtLF9za2FpbmV0X3E1XzFfbWF0bXVsLF9za2FpbmV0X3E1XzFfbWF0bXVsX3JtLF9za2FpbmV0X3E4XzBfbWF0bXVsLF9za2FpbmV0X3E4XzBfbWF0bXVsX3JtLF9za2FpbmV0X3E0a19tYXRtdWwsX3NrYWluZXRfcTRrX21hdG11bF9ybSxfc2thaW5ldF9xNWtfbWF0bXVsLF9za2FpbmV0X3E1a19tYXRtdWxfcm0sX3NrYWluZXRfcTZrX21hdG11bCxfc2thaW5ldF9xNmtfbWF0bXVsX3JtLF9fZW1zY3JpcHRlbl90bHNfaW5pdCxfcHRocmVhZF9zZWxmLF9fZW1zY3JpcHRlbl90aHJlYWRfaW5pdCxfX2Vtc2NyaXB0ZW5fdGhyZWFkX2NyYXNoZWQsX19lbXNjcmlwdGVuX3J1bl9qc19vbl9tYWluX3RocmVhZCxfX2Vtc2NyaXB0ZW5fdGhyZWFkX2ZyZWVfZGF0YSxfX2Vtc2NyaXB0ZW5fdGhyZWFkX2V4aXQsX19lbXNjcmlwdGVuX2NoZWNrX21haWxib3gsX2Vtc2NyaXB0ZW5fc3RhY2tfc2V0X2xpbWl0cyxfX2Vtc2NyaXB0ZW5fc3RhY2tfcmVzdG9yZSxfX2Vtc2NyaXB0ZW5fc3RhY2tfYWxsb2MsX2Vtc2NyaXB0ZW5fc3RhY2tfZ2V0X2N1cnJlbnQ7ZnVuY3Rpb24gYXNzaWduV2FzbUV4cG9ydHMod2FzbUV4cG9ydHMpe01vZHVsZVsiX3NrYWluZXRfZnAzMl9tYXRtdWwiXT1fc2thaW5ldF9mcDMyX21hdG11bD13YXNtRXhwb3J0c1sicCJdO01vZHVsZVsiX3NrYWluZXRfZnAzMl9tYXRtdWxfd3QiXT1fc2thaW5ldF9mcDMyX21hdG11bF93dD13YXNtRXhwb3J0c1siciJdO01vZHVsZVsiX3NrYWluZXRfYmYxNl9tYXRtdWwiXT1fc2thaW5ldF9iZjE2X21hdG11bD13YXNtRXhwb3J0c1sicyJdO01vZHVsZVsiX3NrYWluZXRfZnAxNl9tYXRtdWwiXT1fc2thaW5ldF9mcDE2X21hdG11bD13YXNtRXhwb3J0c1sidCJdO01vZHVsZVsiX3NrYWluZXRfcTRfMF9tYXRtdWwiXT1fc2thaW5ldF9xNF8wX21hdG11bD13YXNtRXhwb3J0c1sidSJdO01vZHVsZVsiX3NrYWluZXRfcTRfMF9tYXRtdWxfcm0iXT1fc2thaW5ldF9xNF8wX21hdG11bF9ybT13YXNtRXhwb3J0c1sidiJdO01vZHVsZVsiX3NrYWluZXRfcTVfMF9tYXRtdWwiXT1fc2thaW5ldF9xNV8wX21hdG11bD13YXNtRXhwb3J0c1sidyJdO01vZHVsZVsiX21hbGxvYyJdPV9tYWxsb2M9d2FzbUV4cG9ydHNbIngiXTtNb2R1bGVbIl9mcmVlIl09X2ZyZWU9d2FzbUV4cG9ydHNbInkiXTtNb2R1bGVbIl9za2FpbmV0X3E1XzBfbWF0bXVsX3JtIl09X3NrYWluZXRfcTVfMF9tYXRtdWxfcm09d2FzbUV4cG9ydHNbInoiXTtNb2R1bGVbIl9za2FpbmV0X3E1XzFfbWF0bXVsIl09X3NrYWluZXRfcTVfMV9tYXRtdWw9d2FzbUV4cG9ydHNbIkEiXTtNb2R1bGVbIl9za2FpbmV0X3E1XzFfbWF0bXVsX3JtIl09X3NrYWluZXRfcTVfMV9tYXRtdWxfcm09d2FzbUV4cG9ydHNbIkIiXTtNb2R1bGVbIl9za2FpbmV0X3E4XzBfbWF0bXVsIl09X3NrYWluZXRfcThfMF9tYXRtdWw9d2FzbUV4cG9ydHNbIkMiXTtNb2R1bGVbIl9za2FpbmV0X3E4XzBfbWF0bXVsX3JtIl09X3NrYWluZXRfcThfMF9tYXRtdWxfcm09d2FzbUV4cG9ydHNbIkQiXTtNb2R1bGVbIl9za2FpbmV0X3E0a19tYXRtdWwiXT1fc2thaW5ldF9xNGtfbWF0bXVsPXdhc21FeHBvcnRzWyJFIl07TW9kdWxlWyJfc2thaW5ldF9xNGtfbWF0bXVsX3JtIl09X3NrYWluZXRfcTRrX21hdG11bF9ybT13YXNtRXhwb3J0c1siRiJdO01vZHVsZVsiX3NrYWluZXRfcTVrX21hdG11bCJdPV9za2FpbmV0X3E1a19tYXRtdWw9d2FzbUV4cG9ydHNbIkciXTtNb2R1bGVbIl9za2FpbmV0X3E1a19tYXRtdWxfcm0iXT1fc2thaW5ldF9xNWtfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJIIl07TW9kdWxlWyJfc2thaW5ldF9xNmtfbWF0bXVsIl09X3NrYWluZXRfcTZrX21hdG11bD13YXNtRXhwb3J0c1siSSJdO01vZHVsZVsiX3NrYWluZXRfcTZrX21hdG11bF9ybSJdPV9za2FpbmV0X3E2a19tYXRtdWxfcm09d2FzbUV4cG9ydHNbIkoiXTtfX2Vtc2NyaXB0ZW5fdGxzX2luaXQ9d2FzbUV4cG9ydHNbIksiXTtfcHRocmVhZF9zZWxmPXdhc21FeHBvcnRzWyJMIl07X19lbXNjcmlwdGVuX3RocmVhZF9pbml0PXdhc21FeHBvcnRzWyJNIl07X19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkPXdhc21FeHBvcnRzWyJOIl07X19lbXNjcmlwdGVuX3J1bl9qc19vbl9tYWluX3RocmVhZD13YXNtRXhwb3J0c1siTyJdO19fZW1zY3JpcHRlbl90aHJlYWRfZnJlZV9kYXRhPXdhc21FeHBvcnRzWyJQIl07X19lbXNjcmlwdGVuX3RocmVhZF9leGl0PXdhc21FeHBvcnRzWyJRIl07X19lbXNjcmlwdGVuX2NoZWNrX21haWxib3g9d2FzbUV4cG9ydHNbIlIiXTtfZW1zY3JpcHRlbl9zdGFja19zZXRfbGltaXRzPXdhc21FeHBvcnRzWyJTIl07X19lbXNjcmlwdGVuX3N0YWNrX3Jlc3RvcmU9d2FzbUV4cG9ydHNbIlQiXTtfX2Vtc2NyaXB0ZW5fc3RhY2tfYWxsb2M9d2FzbUV4cG9ydHNbIlUiXTtfZW1zY3JpcHRlbl9zdGFja19nZXRfY3VycmVudD13YXNtRXhwb3J0c1siViJdfXZhciB3YXNtSW1wb3J0cztmdW5jdGlvbiBhc3NpZ25XYXNtSW1wb3J0cygpe3dhc21JbXBvcnRzPXtnOl9fX3B0aHJlYWRfY3JlYXRlX2pzLGs6X19lbXNjcmlwdGVuX2luaXRfbWFpbl90aHJlYWRfanMsbjpfX2Vtc2NyaXB0ZW5fbm90aWZ5X21haWxib3hfcG9zdG1lc3NhZ2UsbDpfX2Vtc2NyaXB0ZW5fcmVjZWl2ZV9vbl9tYWluX3RocmVhZF9qcyxjOl9fZW1zY3JpcHRlbl90aHJlYWRfY2xlYW51cCxqOl9fZW1zY3JpcHRlbl90aHJlYWRfbWFpbGJveF9hd2FpdCxpOl9fZW1zY3JpcHRlbl90aHJlYWRfc2V0X3N0cm9uZ3JlZixlOl9lbXNjcmlwdGVuX2NoZWNrX2Jsb2NraW5nX2FsbG93ZWQsaDpfZW1zY3JpcHRlbl9leGl0X3dpdGhfbGl2ZV9ydW50aW1lLGI6X2Vtc2NyaXB0ZW5fZ2V0X25vdyxtOl9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwLGY6X2V4aXQsZDpfZmRfd3JpdGUsYTp3YXNtTWVtb3J5fX1mdW5jdGlvbiBhcHBseVNpZ25hdHVyZUNvbnZlcnNpb25zKHdhc21FeHBvcnRzKXt3YXNtRXhwb3J0cz1PYmplY3QuYXNzaWduKHt9LHdhc21FeHBvcnRzKTt2YXIgbWFrZVdyYXBwZXJfcHA9Zj0+YTA9PmYoYTApPj4+MDt2YXIgbWFrZVdyYXBwZXJfcD1mPT4oKT0+ZigpPj4+MDt3YXNtRXhwb3J0c1sieCJdPW1ha2VXcmFwcGVyX3BwKHdhc21FeHBvcnRzWyJ4Il0pO3dhc21FeHBvcnRzWyJMIl09bWFrZVdyYXBwZXJfcCh3YXNtRXhwb3J0c1siTCJdKTt3YXNtRXhwb3J0c1siVSJdPW1ha2VXcmFwcGVyX3BwKHdhc21FeHBvcnRzWyJVIl0pO3dhc21FeHBvcnRzWyJWIl09bWFrZVdyYXBwZXJfcCh3YXNtRXhwb3J0c1siViJdKTtyZXR1cm4gd2FzbUV4cG9ydHN9ZnVuY3Rpb24gcnVuKCl7aWYocnVuRGVwZW5kZW5jaWVzPjApe2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1ydW47cmV0dXJufWlmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpe3JlYWR5UHJvbWlzZVJlc29sdmU/LihNb2R1bGUpO2luaXRSdW50aW1lKCk7cmV0dXJufXByZVJ1bigpO2lmKHJ1bkRlcGVuZGVuY2llcz4wKXtkZXBlbmRlbmNpZXNGdWxmaWxsZWQ9cnVuO3JldHVybn1mdW5jdGlvbiBkb1J1bigpe01vZHVsZVsiY2FsbGVkUnVuIl09dHJ1ZTtpZihBQk9SVClyZXR1cm47aW5pdFJ1bnRpbWUoKTtyZWFkeVByb21pc2VSZXNvbHZlPy4oTW9kdWxlKTtNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0/LigpO3Bvc3RSdW4oKX1pZihNb2R1bGVbInNldFN0YXR1cyJdKXtNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7c2V0VGltZW91dCgoKT0+e3NldFRpbWVvdXQoKCk9Pk1vZHVsZVsic2V0U3RhdHVzIl0oIiIpLDEpO2RvUnVuKCl9LDEpfWVsc2V7ZG9SdW4oKX19dmFyIHdhc21FeHBvcnRzO2lmKCFFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt3YXNtRXhwb3J0cz1hd2FpdCAoY3JlYXRlV2FzbSgpKTtydW4oKX1pZihydW50aW1lSW5pdGlhbGl6ZWQpe21vZHVsZVJ0bj1Nb2R1bGV9ZWxzZXttb2R1bGVSdG49bmV3IFByb21pc2UoKHJlc29sdmUscmVqZWN0KT0+e3JlYWR5UHJvbWlzZVJlc29sdmU9cmVzb2x2ZTtyZWFkeVByb21pc2VSZWplY3Q9cmVqZWN0fSl9CjtyZXR1cm4gbW9kdWxlUnRufWV4cG9ydCBkZWZhdWx0IGNyZWF0ZVNrYWluZXRLZXJuZWxzO3ZhciBpc1B0aHJlYWQ9Z2xvYmFsVGhpcy5zZWxmPy5uYW1lPy5zdGFydHNXaXRoKCJlbS1wdGhyZWFkIik7dmFyIGlzTm9kZT10eXBlb2YgcHJvY2Vzcz09Im9iamVjdCImJnByb2Nlc3MudmVyc2lvbnM/Lm5vZGUmJnByb2Nlc3MudHlwZSE9InJlbmRlcmVyIjtpZihpc05vZGUpaXNQdGhyZWFkPShhd2FpdCBpbXBvcnQoIndvcmtlcl90aHJlYWRzIikpLndvcmtlckRhdGE9PT0iZW0tcHRocmVhZCI7aXNQdGhyZWFkJiZjcmVhdGVTa2FpbmV0S2VybmVscygpOwo=" - const val MT_WASM: String = "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NgIAIAFBHGtBADYCACACIABBBHFBGHIiAmsiAUEgSQ0AIAAgAmohAANAIABCADcDGCAAQgA3AxAgAEIANwMIIABCADcDACAAQSBqIQAgAUEgayIBQR9LDQALCwvyAQEFfyMAQRBrIgMkACADQQA2AgwgAEEgaiIGEBogACgCFCICQQBHIQUCQCABRQ0AIAJFDQADQAJAIAJBCGpBAEEB/kgCAARAIAMgAygCDEEBajYCDCACIANBDGo2AhAMAQsgBCACIAQbIQQgAUEBayEBCyACKAIAIgJBAEchBSABRQ0BIAINAAsLAkAgBQRAIAIoAgQiAQRAIAFBADYCAAsgAkEANgIEDAELIABBADYCBAsgACACNgIUIAYQGSADKAIMIgIEQANAIANBDGpBACACEBMgAygCDCICDQALCyAEBEAgBEEMahAZCyADQRBqJAALYgEBfwJAIwUEQEGEDf4QAgANASMBIgAtAARFBEAgAEEBOgAEQZwLEA4aQZwLIwMQNiEAQZwLEA0CQCAARQ0AIAAoAiANACAAECcLIwFBADoABAsLDwtBhA3+EAIAEAcQBgALhwEBA38jAEEgayIBJAACQCAAKAIIRQRAIABBEGoiAhAOGiAAQQI2AgwgAhANIABBKGoQKAwBCyAAKAIYBEAgACgCECECIAAoAgwgASAANgIcIAEgADYCECABQRc2AhggAUEcNgIUIAEgASkCFDcDCCACIAFBCGoQHA0BCyAAEBYLIAFBIGokAAuCAQECfyAAKAIIRQRAIABBEGoQLQJAIABBKGoiACgCAEUNACAAKAIMRQ0AIABBDGoiAUGAgICAeP4zAgAaIABBCGoiAkEB/h4CABogAkH/////BxAPIAAoAgwiAEH/////B3FFDQADQCABQQAgABATIAEoAgAiAEH/////B3ENAAsLCwtlAQJ/IAAgACgCWEYEQCAAQgA3AlhBwAsoAgBBABAgDwsjAygCSEHACygCACIBQQJ0aigCACICIABGBEAgASACKAJYECALIAAoAlwiAiAAKAJYIgE2AlggASACNgJcIABCADcCWAueCQEOfwJAIAAgARA2IgJFBEAgACgCHCICIAAoAiBGBEACfyACQQF0QQEgAhsiD0ECdCEJIAAoAhgiDEUEQCAJEBEMAQsgCUFATwRAIwFBMDYCAEEADAELAkBBtBkt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" + const val ST_MJS: String = "YXN5bmMgZnVuY3Rpb24gY3JlYXRlU2thaW5ldEtlcm5lbHMobW9kdWxlQXJnPXt9KXt2YXIgbW9kdWxlUnRuO3ZhciBNb2R1bGU9bW9kdWxlQXJnO3ZhciBFTlZJUk9OTUVOVF9JU19XRUI9dHlwZW9mIHdpbmRvdz09Im9iamVjdCI7dmFyIEVOVklST05NRU5UX0lTX1dPUktFUj10eXBlb2YgV29ya2VyR2xvYmFsU2NvcGUhPSJ1bmRlZmluZWQiO3ZhciBFTlZJUk9OTUVOVF9JU19OT0RFPXR5cGVvZiBwcm9jZXNzPT0ib2JqZWN0IiYmcHJvY2Vzcy52ZXJzaW9ucz8ubm9kZSYmcHJvY2Vzcy50eXBlIT0icmVuZGVyZXIiO2lmKEVOVklST05NRU5UX0lTX05PREUpe2NvbnN0e2NyZWF0ZVJlcXVpcmV9PWF3YWl0IGltcG9ydCgibW9kdWxlIik7dmFyIHJlcXVpcmU9Y3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwuc3RhcnRzV2l0aCgiZmlsZToiKT9pbXBvcnQubWV0YS51cmw6cHJvY2Vzcy5jd2QoKSsiLyIpfXZhciBhcmd1bWVudHNfPVtdO3ZhciB0aGlzUHJvZ3JhbT0iLi90aGlzLnByb2dyYW0iO3ZhciBxdWl0Xz0oc3RhdHVzLHRvVGhyb3cpPT57dGhyb3cgdG9UaHJvd307dmFyIF9zY3JpcHROYW1lPWltcG9ydC5tZXRhLnVybDt2YXIgc2NyaXB0RGlyZWN0b3J5PSIiO2Z1bmN0aW9uIGxvY2F0ZUZpbGUocGF0aCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBNb2R1bGVbImxvY2F0ZUZpbGUiXShwYXRoLHNjcmlwdERpcmVjdG9yeSl9cmV0dXJuIHNjcmlwdERpcmVjdG9yeStwYXRofXZhciByZWFkQXN5bmMscmVhZEJpbmFyeTtpZihFTlZJUk9OTUVOVF9JU19OT0RFKXt2YXIgZnM9cmVxdWlyZSgiZnMiKTtpZihfc2NyaXB0TmFtZS5zdGFydHNXaXRoKCJmaWxlOiIpKXtzY3JpcHREaXJlY3Rvcnk9cmVxdWlyZSgicGF0aCIpLmRpcm5hbWUocmVxdWlyZSgidXJsIikuZmlsZVVSTFRvUGF0aChfc2NyaXB0TmFtZSkpKyIvIn1yZWFkQmluYXJ5PWZpbGVuYW1lPT57ZmlsZW5hbWU9aXNGaWxlVVJJKGZpbGVuYW1lKT9uZXcgVVJMKGZpbGVuYW1lKTpmaWxlbmFtZTt2YXIgcmV0PWZzLnJlYWRGaWxlU3luYyhmaWxlbmFtZSk7cmV0dXJuIHJldH07cmVhZEFzeW5jPWFzeW5jKGZpbGVuYW1lLGJpbmFyeT10cnVlKT0+e2ZpbGVuYW1lPWlzRmlsZVVSSShmaWxlbmFtZSk/bmV3IFVSTChmaWxlbmFtZSk6ZmlsZW5hbWU7dmFyIHJldD1mcy5yZWFkRmlsZVN5bmMoZmlsZW5hbWUsYmluYXJ5P3VuZGVmaW5lZDoidXRmOCIpO3JldHVybiByZXR9O2lmKHByb2Nlc3MuYXJndi5sZW5ndGg+MSl7dGhpc1Byb2dyYW09cHJvY2Vzcy5hcmd2WzFdLnJlcGxhY2UoL1xcL2csIi8iKX1hcmd1bWVudHNfPXByb2Nlc3MuYXJndi5zbGljZSgyKTtxdWl0Xz0oc3RhdHVzLHRvVGhyb3cpPT57cHJvY2Vzcy5leGl0Q29kZT1zdGF0dXM7dGhyb3cgdG9UaHJvd319ZWxzZSBpZihFTlZJUk9OTUVOVF9JU19XRUJ8fEVOVklST05NRU5UX0lTX1dPUktFUil7dHJ5e3NjcmlwdERpcmVjdG9yeT1uZXcgVVJMKCIuIixfc2NyaXB0TmFtZSkuaHJlZn1jYXRjaHt9e2lmKEVOVklST05NRU5UX0lTX1dPUktFUil7cmVhZEJpbmFyeT11cmw9Pnt2YXIgeGhyPW5ldyBYTUxIdHRwUmVxdWVzdDt4aHIub3BlbigiR0VUIix1cmwsZmFsc2UpO3hoci5yZXNwb25zZVR5cGU9ImFycmF5YnVmZmVyIjt4aHIuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoeGhyLnJlc3BvbnNlKX19cmVhZEFzeW5jPWFzeW5jIHVybD0+e3ZhciByZXNwb25zZT1hd2FpdCBmZXRjaCh1cmwse2NyZWRlbnRpYWxzOiJzYW1lLW9yaWdpbiJ9KTtpZihyZXNwb25zZS5vayl7cmV0dXJuIHJlc3BvbnNlLmFycmF5QnVmZmVyKCl9dGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLnN0YXR1cysiIDogIityZXNwb25zZS51cmwpfX19ZWxzZXt9dmFyIG91dD1jb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpO3ZhciBlcnI9Y29uc29sZS5lcnJvci5iaW5kKGNvbnNvbGUpO3ZhciB3YXNtQmluYXJ5O3ZhciBBQk9SVD1mYWxzZTt2YXIgaXNGaWxlVVJJPWZpbGVuYW1lPT5maWxlbmFtZS5zdGFydHNXaXRoKCJmaWxlOi8vIik7dmFyIHJlYWR5UHJvbWlzZVJlc29sdmUscmVhZHlQcm9taXNlUmVqZWN0O3ZhciB3YXNtTWVtb3J5O3ZhciBIRUFQOCxIRUFQVTgsSEVBUDE2LEhFQVBVMTYsSEVBUDMyLEhFQVBVMzIsSEVBUEYzMixIRUFQRjY0O3ZhciBIRUFQNjQsSEVBUFU2NDt2YXIgcnVudGltZUluaXRpYWxpemVkPWZhbHNlO2Z1bmN0aW9uIHVwZGF0ZU1lbW9yeVZpZXdzKCl7dmFyIGI9d2FzbU1lbW9yeS5idWZmZXI7SEVBUDg9bmV3IEludDhBcnJheShiKTtIRUFQMTY9bmV3IEludDE2QXJyYXkoYik7SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO0hFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO0hFQVAzMj1uZXcgSW50MzJBcnJheShiKTtIRUFQVTMyPW5ldyBVaW50MzJBcnJheShiKTtIRUFQRjMyPW5ldyBGbG9hdDMyQXJyYXkoYik7SEVBUEY2ND1uZXcgRmxvYXQ2NEFycmF5KGIpO0hFQVA2ND1uZXcgQmlnSW50NjRBcnJheShiKTtIRUFQVTY0PW5ldyBCaWdVaW50NjRBcnJheShiKX1mdW5jdGlvbiBwcmVSdW4oKXtpZihNb2R1bGVbInByZVJ1biJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInByZVJ1biJdPVtNb2R1bGVbInByZVJ1biJdXTt3aGlsZShNb2R1bGVbInByZVJ1biJdLmxlbmd0aCl7YWRkT25QcmVSdW4oTW9kdWxlWyJwcmVSdW4iXS5zaGlmdCgpKX19Y2FsbFJ1bnRpbWVDYWxsYmFja3Mob25QcmVSdW5zKX1mdW5jdGlvbiBpbml0UnVudGltZSgpe3J1bnRpbWVJbml0aWFsaXplZD10cnVlO3dhc21FeHBvcnRzWyJjIl0oKX1mdW5jdGlvbiBwb3N0UnVuKCl7aWYoTW9kdWxlWyJwb3N0UnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInBvc3RSdW4iXT1bTW9kdWxlWyJwb3N0UnVuIl1dO3doaWxlKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCl7YWRkT25Qb3N0UnVuKE1vZHVsZVsicG9zdFJ1biJdLnNoaWZ0KCkpfX1jYWxsUnVudGltZUNhbGxiYWNrcyhvblBvc3RSdW5zKX1mdW5jdGlvbiBhYm9ydCh3aGF0KXtNb2R1bGVbIm9uQWJvcnQiXT8uKHdoYXQpO3doYXQ9IkFib3J0ZWQoIit3aGF0KyIpIjtlcnIod2hhdCk7QUJPUlQ9dHJ1ZTt3aGF0Kz0iLiBCdWlsZCB3aXRoIC1zQVNTRVJUSU9OUyBmb3IgbW9yZSBpbmZvLiI7dmFyIGU9bmV3IFdlYkFzc2VtYmx5LlJ1bnRpbWVFcnJvcih3aGF0KTtyZWFkeVByb21pc2VSZWplY3Q/LihlKTt0aHJvdyBlfXZhciB3YXNtQmluYXJ5RmlsZTtmdW5jdGlvbiBmaW5kV2FzbUJpbmFyeSgpe2lmKE1vZHVsZVsibG9jYXRlRmlsZSJdKXtyZXR1cm4gbG9jYXRlRmlsZSgic2thaW5ldF9rZXJuZWxzX3N0Lndhc20iKX10cnl7cmV0dXJuIG5ldyBVUkwoInNrYWluZXRfa2VybmVsc19zdC53YXNtIixpbXBvcnQubWV0YS51cmwpLmhyZWZ9Y2F0Y2goZSl7cmV0dXJuICJza2FpbmV0X2tlcm5lbHNfc3Qud2FzbSJ9fWZ1bmN0aW9uIGdldEJpbmFyeVN5bmMoZmlsZSl7aWYoZmlsZT09d2FzbUJpbmFyeUZpbGUmJndhc21CaW5hcnkpe3JldHVybiBuZXcgVWludDhBcnJheSh3YXNtQmluYXJ5KX1pZihyZWFkQmluYXJ5KXtyZXR1cm4gcmVhZEJpbmFyeShmaWxlKX10aHJvdyJib3RoIGFzeW5jIGFuZCBzeW5jIGZldGNoaW5nIG9mIHRoZSB3YXNtIGZhaWxlZCJ9YXN5bmMgZnVuY3Rpb24gZ2V0V2FzbUJpbmFyeShiaW5hcnlGaWxlKXtpZighd2FzbUJpbmFyeSl7dHJ5e3ZhciByZXNwb25zZT1hd2FpdCByZWFkQXN5bmMoYmluYXJ5RmlsZSk7cmV0dXJuIG5ldyBVaW50OEFycmF5KHJlc3BvbnNlKX1jYXRjaHt9fXJldHVybiBnZXRCaW5hcnlTeW5jKGJpbmFyeUZpbGUpfWFzeW5jIGZ1bmN0aW9uIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzKXt0cnl7dmFyIGJpbmFyeT1hd2FpdCBnZXRXYXNtQmluYXJ5KGJpbmFyeUZpbGUpO3ZhciBpbnN0YW5jZT1hd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShiaW5hcnksaW1wb3J0cyk7cmV0dXJuIGluc3RhbmNlfWNhdGNoKHJlYXNvbil7ZXJyKGBmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAke3JlYXNvbn1gKTthYm9ydChyZWFzb24pfX1hc3luYyBmdW5jdGlvbiBpbnN0YW50aWF0ZUFzeW5jKGJpbmFyeSxiaW5hcnlGaWxlLGltcG9ydHMpe2lmKCFiaW5hcnkmJiFFTlZJUk9OTUVOVF9JU19OT0RFKXt0cnl7dmFyIHJlc3BvbnNlPWZldGNoKGJpbmFyeUZpbGUse2NyZWRlbnRpYWxzOiJzYW1lLW9yaWdpbiJ9KTt2YXIgaW5zdGFudGlhdGlvblJlc3VsdD1hd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhyZXNwb25zZSxpbXBvcnRzKTtyZXR1cm4gaW5zdGFudGlhdGlvblJlc3VsdH1jYXRjaChyZWFzb24pe2Vycihgd2FzbSBzdHJlYW1pbmcgY29tcGlsZSBmYWlsZWQ6ICR7cmVhc29ufWApO2VycigiZmFsbGluZyBiYWNrIHRvIEFycmF5QnVmZmVyIGluc3RhbnRpYXRpb24iKX19cmV0dXJuIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzKX1mdW5jdGlvbiBnZXRXYXNtSW1wb3J0cygpe3JldHVybnthOndhc21JbXBvcnRzfX1hc3luYyBmdW5jdGlvbiBjcmVhdGVXYXNtKCl7ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLG1vZHVsZSl7d2FzbUV4cG9ydHM9aW5zdGFuY2UuZXhwb3J0czt3YXNtRXhwb3J0cz1hcHBseVNpZ25hdHVyZUNvbnZlcnNpb25zKHdhc21FeHBvcnRzKTt3YXNtTWVtb3J5PXdhc21FeHBvcnRzWyJiIl07TW9kdWxlWyJ3YXNtTWVtb3J5Il09d2FzbU1lbW9yeTt1cGRhdGVNZW1vcnlWaWV3cygpO2Fzc2lnbldhc21FeHBvcnRzKHdhc21FeHBvcnRzKTtyZXR1cm4gd2FzbUV4cG9ydHN9ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZXR1cm4gcmVjZWl2ZUluc3RhbmNlKHJlc3VsdFsiaW5zdGFuY2UiXSl9dmFyIGluZm89Z2V0V2FzbUltcG9ydHMoKTtpZihNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKXtyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUscmVqZWN0KT0+e01vZHVsZVsiaW5zdGFudGlhdGVXYXNtIl0oaW5mbywobW9kLGluc3QpPT57cmVzb2x2ZShyZWNlaXZlSW5zdGFuY2UobW9kLGluc3QpKX0pfSl9d2FzbUJpbmFyeUZpbGU/Pz1maW5kV2FzbUJpbmFyeSgpO3ZhciByZXN1bHQ9YXdhaXQgaW5zdGFudGlhdGVBc3luYyh3YXNtQmluYXJ5LHdhc21CaW5hcnlGaWxlLGluZm8pO3ZhciBleHBvcnRzPXJlY2VpdmVJbnN0YW50aWF0aW9uUmVzdWx0KHJlc3VsdCk7cmV0dXJuIGV4cG9ydHN9Y2xhc3MgRXhpdFN0YXR1c3tuYW1lPSJFeGl0U3RhdHVzIjtjb25zdHJ1Y3RvcihzdGF0dXMpe3RoaXMubWVzc2FnZT1gUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdCgke3N0YXR1c30pYDt0aGlzLnN0YXR1cz1zdGF0dXN9fXZhciBjYWxsUnVudGltZUNhbGxiYWNrcz1jYWxsYmFja3M9Pnt3aGlsZShjYWxsYmFja3MubGVuZ3RoPjApe2NhbGxiYWNrcy5zaGlmdCgpKE1vZHVsZSl9fTt2YXIgb25Qb3N0UnVucz1bXTt2YXIgYWRkT25Qb3N0UnVuPWNiPT5vblBvc3RSdW5zLnB1c2goY2IpO3ZhciBvblByZVJ1bnM9W107dmFyIGFkZE9uUHJlUnVuPWNiPT5vblByZVJ1bnMucHVzaChjYik7dmFyIG5vRXhpdFJ1bnRpbWU9dHJ1ZTt2YXIgZ2V0SGVhcE1heD0oKT0+NDI5NDkwMTc2MDt2YXIgYWxpZ25NZW1vcnk9KHNpemUsYWxpZ25tZW50KT0+TWF0aC5jZWlsKHNpemUvYWxpZ25tZW50KSphbGlnbm1lbnQ7dmFyIGdyb3dNZW1vcnk9c2l6ZT0+e3ZhciBvbGRIZWFwU2l6ZT13YXNtTWVtb3J5LmJ1ZmZlci5ieXRlTGVuZ3RoO3ZhciBwYWdlcz0oc2l6ZS1vbGRIZWFwU2l6ZSs2NTUzNSkvNjU1MzZ8MDt0cnl7d2FzbU1lbW9yeS5ncm93KHBhZ2VzKTt1cGRhdGVNZW1vcnlWaWV3cygpO3JldHVybiAxfWNhdGNoKGUpe319O2Z1bmN0aW9uIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwKHJlcXVlc3RlZFNpemUpe3JlcXVlc3RlZFNpemU+Pj49MDt2YXIgb2xkU2l6ZT1IRUFQVTgubGVuZ3RoO3ZhciBtYXhIZWFwU2l6ZT1nZXRIZWFwTWF4KCk7aWYocmVxdWVzdGVkU2l6ZT5tYXhIZWFwU2l6ZSl7cmV0dXJuIGZhbHNlfWZvcih2YXIgY3V0RG93bj0xO2N1dERvd248PTQ7Y3V0RG93bio9Mil7dmFyIG92ZXJHcm93bkhlYXBTaXplPW9sZFNpemUqKDErLjIvY3V0RG93bik7b3Zlckdyb3duSGVhcFNpemU9TWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUscmVxdWVzdGVkU2l6ZSsxMDA2NjMyOTYpO3ZhciBuZXdTaXplPU1hdGgubWluKG1heEhlYXBTaXplLGFsaWduTWVtb3J5KE1hdGgubWF4KHJlcXVlc3RlZFNpemUsb3Zlckdyb3duSGVhcFNpemUpLDY1NTM2KSk7dmFyIHJlcGxhY2VtZW50PWdyb3dNZW1vcnkobmV3U2l6ZSk7aWYocmVwbGFjZW1lbnQpe3JldHVybiB0cnVlfX1yZXR1cm4gZmFsc2V9e2lmKE1vZHVsZVsibm9FeGl0UnVudGltZSJdKW5vRXhpdFJ1bnRpbWU9TW9kdWxlWyJub0V4aXRSdW50aW1lIl07aWYoTW9kdWxlWyJwcmludCJdKW91dD1Nb2R1bGVbInByaW50Il07aWYoTW9kdWxlWyJwcmludEVyciJdKWVycj1Nb2R1bGVbInByaW50RXJyIl07aWYoTW9kdWxlWyJ3YXNtQmluYXJ5Il0pd2FzbUJpbmFyeT1Nb2R1bGVbIndhc21CaW5hcnkiXTtpZihNb2R1bGVbImFyZ3VtZW50cyJdKWFyZ3VtZW50c189TW9kdWxlWyJhcmd1bWVudHMiXTtpZihNb2R1bGVbInRoaXNQcm9ncmFtIl0pdGhpc1Byb2dyYW09TW9kdWxlWyJ0aGlzUHJvZ3JhbSJdO2lmKE1vZHVsZVsicHJlSW5pdCJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVJbml0Il09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVJbml0Il09W01vZHVsZVsicHJlSW5pdCJdXTt3aGlsZShNb2R1bGVbInByZUluaXQiXS5sZW5ndGg+MCl7TW9kdWxlWyJwcmVJbml0Il0uc2hpZnQoKSgpfX19TW9kdWxlWyJ3YXNtTWVtb3J5Il09d2FzbU1lbW9yeTt2YXIgX3NrYWluZXRfZnAzMl9tYXRtdWwsX3NrYWluZXRfZnAzMl9tYXRtdWxfd3QsX3NrYWluZXRfYmYxNl9tYXRtdWwsX3NrYWluZXRfZnAxNl9tYXRtdWwsX3NrYWluZXRfcTRfMF9tYXRtdWwsX3NrYWluZXRfcTRfMF9tYXRtdWxfcm0sX3NrYWluZXRfcTVfMF9tYXRtdWwsX21hbGxvYyxfZnJlZSxfc2thaW5ldF9xNV8wX21hdG11bF9ybSxfc2thaW5ldF9xNV8xX21hdG11bCxfc2thaW5ldF9xNV8xX21hdG11bF9ybSxfc2thaW5ldF9xOF8wX21hdG11bCxfc2thaW5ldF9xOF8wX21hdG11bF9ybSxfc2thaW5ldF9xNGtfbWF0bXVsLF9za2FpbmV0X3E0a19tYXRtdWxfcm0sX3NrYWluZXRfcTVrX21hdG11bCxfc2thaW5ldF9xNWtfbWF0bXVsX3JtLF9za2FpbmV0X3E2a19tYXRtdWwsX3NrYWluZXRfcTZrX21hdG11bF9ybSxfc2thaW5ldF90ZXJuYXJ5X2YzMl9nZW12LF9za2FpbmV0X3Rlcm5hcnlfbG1oZWFkX3N0YWdlMSxfc2thaW5ldF9iaXRuZXRfZ2Vtdl90cTJfMCxfc2thaW5ldF9mMzJfYmluYXJ5LF9za2FpbmV0X2YzMl91bmFyeSxfc2thaW5ldF9mMzJfcmVkdWNlX2FsbCxfc2thaW5ldF9mMzJfcmVkdWNlX2F4aXM7ZnVuY3Rpb24gYXNzaWduV2FzbUV4cG9ydHMod2FzbUV4cG9ydHMpe01vZHVsZVsiX3NrYWluZXRfZnAzMl9tYXRtdWwiXT1fc2thaW5ldF9mcDMyX21hdG11bD13YXNtRXhwb3J0c1siZCJdO01vZHVsZVsiX3NrYWluZXRfZnAzMl9tYXRtdWxfd3QiXT1fc2thaW5ldF9mcDMyX21hdG11bF93dD13YXNtRXhwb3J0c1siZSJdO01vZHVsZVsiX3NrYWluZXRfYmYxNl9tYXRtdWwiXT1fc2thaW5ldF9iZjE2X21hdG11bD13YXNtRXhwb3J0c1siZiJdO01vZHVsZVsiX3NrYWluZXRfZnAxNl9tYXRtdWwiXT1fc2thaW5ldF9mcDE2X21hdG11bD13YXNtRXhwb3J0c1siZyJdO01vZHVsZVsiX3NrYWluZXRfcTRfMF9tYXRtdWwiXT1fc2thaW5ldF9xNF8wX21hdG11bD13YXNtRXhwb3J0c1siaCJdO01vZHVsZVsiX3NrYWluZXRfcTRfMF9tYXRtdWxfcm0iXT1fc2thaW5ldF9xNF8wX21hdG11bF9ybT13YXNtRXhwb3J0c1siaSJdO01vZHVsZVsiX3NrYWluZXRfcTVfMF9tYXRtdWwiXT1fc2thaW5ldF9xNV8wX21hdG11bD13YXNtRXhwb3J0c1siaiJdO01vZHVsZVsiX21hbGxvYyJdPV9tYWxsb2M9d2FzbUV4cG9ydHNbImsiXTtNb2R1bGVbIl9mcmVlIl09X2ZyZWU9d2FzbUV4cG9ydHNbImwiXTtNb2R1bGVbIl9za2FpbmV0X3E1XzBfbWF0bXVsX3JtIl09X3NrYWluZXRfcTVfMF9tYXRtdWxfcm09d2FzbUV4cG9ydHNbIm0iXTtNb2R1bGVbIl9za2FpbmV0X3E1XzFfbWF0bXVsIl09X3NrYWluZXRfcTVfMV9tYXRtdWw9d2FzbUV4cG9ydHNbIm4iXTtNb2R1bGVbIl9za2FpbmV0X3E1XzFfbWF0bXVsX3JtIl09X3NrYWluZXRfcTVfMV9tYXRtdWxfcm09d2FzbUV4cG9ydHNbIm8iXTtNb2R1bGVbIl9za2FpbmV0X3E4XzBfbWF0bXVsIl09X3NrYWluZXRfcThfMF9tYXRtdWw9d2FzbUV4cG9ydHNbInAiXTtNb2R1bGVbIl9za2FpbmV0X3E4XzBfbWF0bXVsX3JtIl09X3NrYWluZXRfcThfMF9tYXRtdWxfcm09d2FzbUV4cG9ydHNbInEiXTtNb2R1bGVbIl9za2FpbmV0X3E0a19tYXRtdWwiXT1fc2thaW5ldF9xNGtfbWF0bXVsPXdhc21FeHBvcnRzWyJyIl07TW9kdWxlWyJfc2thaW5ldF9xNGtfbWF0bXVsX3JtIl09X3NrYWluZXRfcTRrX21hdG11bF9ybT13YXNtRXhwb3J0c1sicyJdO01vZHVsZVsiX3NrYWluZXRfcTVrX21hdG11bCJdPV9za2FpbmV0X3E1a19tYXRtdWw9d2FzbUV4cG9ydHNbInQiXTtNb2R1bGVbIl9za2FpbmV0X3E1a19tYXRtdWxfcm0iXT1fc2thaW5ldF9xNWtfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJ1Il07TW9kdWxlWyJfc2thaW5ldF9xNmtfbWF0bXVsIl09X3NrYWluZXRfcTZrX21hdG11bD13YXNtRXhwb3J0c1sidiJdO01vZHVsZVsiX3NrYWluZXRfcTZrX21hdG11bF9ybSJdPV9za2FpbmV0X3E2a19tYXRtdWxfcm09d2FzbUV4cG9ydHNbInciXTtNb2R1bGVbIl9za2FpbmV0X3Rlcm5hcnlfZjMyX2dlbXYiXT1fc2thaW5ldF90ZXJuYXJ5X2YzMl9nZW12PXdhc21FeHBvcnRzWyJ4Il07TW9kdWxlWyJfc2thaW5ldF90ZXJuYXJ5X2xtaGVhZF9zdGFnZTEiXT1fc2thaW5ldF90ZXJuYXJ5X2xtaGVhZF9zdGFnZTE9d2FzbUV4cG9ydHNbInkiXTtNb2R1bGVbIl9za2FpbmV0X2JpdG5ldF9nZW12X3RxMl8wIl09X3NrYWluZXRfYml0bmV0X2dlbXZfdHEyXzA9d2FzbUV4cG9ydHNbInoiXTtNb2R1bGVbIl9za2FpbmV0X2YzMl9iaW5hcnkiXT1fc2thaW5ldF9mMzJfYmluYXJ5PXdhc21FeHBvcnRzWyJBIl07TW9kdWxlWyJfc2thaW5ldF9mMzJfdW5hcnkiXT1fc2thaW5ldF9mMzJfdW5hcnk9d2FzbUV4cG9ydHNbIkIiXTtNb2R1bGVbIl9za2FpbmV0X2YzMl9yZWR1Y2VfYWxsIl09X3NrYWluZXRfZjMyX3JlZHVjZV9hbGw9d2FzbUV4cG9ydHNbIkMiXTtNb2R1bGVbIl9za2FpbmV0X2YzMl9yZWR1Y2VfYXhpcyJdPV9za2FpbmV0X2YzMl9yZWR1Y2VfYXhpcz13YXNtRXhwb3J0c1siRCJdfXZhciB3YXNtSW1wb3J0cz17YTpfZW1zY3JpcHRlbl9yZXNpemVfaGVhcH07ZnVuY3Rpb24gYXBwbHlTaWduYXR1cmVDb252ZXJzaW9ucyh3YXNtRXhwb3J0cyl7d2FzbUV4cG9ydHM9T2JqZWN0LmFzc2lnbih7fSx3YXNtRXhwb3J0cyk7dmFyIG1ha2VXcmFwcGVyX3BwPWY9PmEwPT5mKGEwKT4+PjA7dmFyIG1ha2VXcmFwcGVyX3A9Zj0+KCk9PmYoKT4+PjA7d2FzbUV4cG9ydHNbImsiXT1tYWtlV3JhcHBlcl9wcCh3YXNtRXhwb3J0c1siayJdKTt3YXNtRXhwb3J0c1siX2Vtc2NyaXB0ZW5fc3RhY2tfYWxsb2MiXT1tYWtlV3JhcHBlcl9wcCh3YXNtRXhwb3J0c1siX2Vtc2NyaXB0ZW5fc3RhY2tfYWxsb2MiXSk7d2FzbUV4cG9ydHNbImVtc2NyaXB0ZW5fc3RhY2tfZ2V0X2N1cnJlbnQiXT1tYWtlV3JhcHBlcl9wKHdhc21FeHBvcnRzWyJlbXNjcmlwdGVuX3N0YWNrX2dldF9jdXJyZW50Il0pO3JldHVybiB3YXNtRXhwb3J0c31mdW5jdGlvbiBydW4oKXtwcmVSdW4oKTtmdW5jdGlvbiBkb1J1bigpe01vZHVsZVsiY2FsbGVkUnVuIl09dHJ1ZTtpZihBQk9SVClyZXR1cm47aW5pdFJ1bnRpbWUoKTtyZWFkeVByb21pc2VSZXNvbHZlPy4oTW9kdWxlKTtNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0/LigpO3Bvc3RSdW4oKX1pZihNb2R1bGVbInNldFN0YXR1cyJdKXtNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7c2V0VGltZW91dCgoKT0+e3NldFRpbWVvdXQoKCk9Pk1vZHVsZVsic2V0U3RhdHVzIl0oIiIpLDEpO2RvUnVuKCl9LDEpfWVsc2V7ZG9SdW4oKX19dmFyIHdhc21FeHBvcnRzO3dhc21FeHBvcnRzPWF3YWl0IChjcmVhdGVXYXNtKCkpO3J1bigpO2lmKHJ1bnRpbWVJbml0aWFsaXplZCl7bW9kdWxlUnRuPU1vZHVsZX1lbHNle21vZHVsZVJ0bj1uZXcgUHJvbWlzZSgocmVzb2x2ZSxyZWplY3QpPT57cmVhZHlQcm9taXNlUmVzb2x2ZT1yZXNvbHZlO3JlYWR5UHJvbWlzZVJlamVjdD1yZWplY3R9KX0KO3JldHVybiBtb2R1bGVSdG59ZXhwb3J0IGRlZmF1bHQgY3JlYXRlU2thaW5ldEtlcm5lbHM7Cg==" + const val ST_WASM: String = "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AIC/AAAAAAAAgL8AAIA/AACAvwAAAAAAAIC/AAAAQAAAgL8AAAAAAACAvwAAgL8AQc4KCwKAvwBB3goLBoC/AACAPwBB7goLBoC/AAAAQABB/goL0gGAvwAAgL8AAIA/AAAAAAAAgL8AAAAAAACAPwAAAAAAAIC/AACAPwAAgD8AAAAAAACAvwAAAEAAAIA/AAAAAAAAgL8AAIC/AAAAQAAAAAAAAIC/AAAAAAAAAEAAAAAAAACAvwAAgD8AAABAAAAAAAAAgL8AAABAAAAAQAAAAAAAAIC/AACAvwAAgL8AAIA/AACAvwAAAAAAAIC/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AAAAQAAAgL8AAIA/AACAvwAAgL8AAAAAAACAPwAAgL8AQdoMC/YBgD8AAIC/AACAPwAAAAAAAIA/AACAvwAAAEAAAAAAAACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AAAAAAAAgD8AAIA/AACAvwAAgD8AAIA/AACAPwAAgL8AAABAAACAPwAAgD8AAIC/AACAvwAAAEAAAIA/AACAvwAAAAAAAABAAACAPwAAgL8AAIA/AAAAQAAAgD8AAIC/AAAAQAAAAEAAAIA/AACAvwAAgL8AAIC/AAAAQAAAgL8AAAAAAACAvwAAAEAAAIC/AACAPwAAgL8AAABAAACAvwAAAEAAAIC/AAAAQAAAgL8AAIC/AAAAAAAAAEAAAIC/AEHbDguxAUAAAIC/AACAPwAAAAAAAABAAACAvwAAAEAAAAAAAAAAQAAAgL8AAIC/AACAPwAAAEAAAIC/AAAAAAAAgD8AAABAAACAvwAAgD8AAIA/AAAAQAAAgL8AAABAAACAPwAAAEAAAIC/AACAvwAAAEAAAABAAACAvwAAAAAAAABAAAAAQAAAgL8AAIA/AAAAQAAAAEAAAIC/AAAAQAAAAEAAAABAAACAvwAAgL8AAIC/AACAvwBBlhALNoC/AACAvwAAAAAAAIA/AACAvwAAgL8AAAAAAAAAQAAAgL8AAIC/AAAAAAAAgL8AAAAAAACAvwBB2hALMoC/AAAAAAAAgD8AAAAAAACAvwAAAAAAAABAAAAAAAAAgL8AAAAAAACAvwAAgD8AAIC/AEGWEQs2gD8AAIC/AAAAAAAAgD8AAIA/AACAvwAAAAAAAABAAACAPwAAgL8AAAAAAACAvwAAAEAAAIC/AEHXEQsxQAAAgL8AAAAAAACAPwAAAEAAAIC/AAAAAAAAAEAAAABAAACAvwAAAAAAAIC/AACAvwBBlhILAoC/AEGiEgsGgD8AAIC/AEGzEgsFQAAAgL8AQcISCwKAvwBB4hILAoA/AEHzEgsBQABBghMLBoC/AACAPwBBlhMLAoA/AEGiEwsGgD8AAIA/AEGzEwsFQAAAgD8AQcITCwaAvwAAAEAAQdcTCwFAAEHiEwsGgD8AAABAAEHzEwsFQAAAAEAAQYIUCwqAvwAAgL8AAIA/AEGWFAs2gL8AAIA/AAAAAAAAgD8AAIC/AACAPwAAAAAAAABAAACAvwAAgD8AAAAAAACAvwAAAAAAAIA/AEHaFAsygD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAEAAAAAAAACAPwAAAAAAAIC/AACAPwAAgD8AQZYVCzaAPwAAgD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAAEAAAIA/AACAPwAAAAAAAIC/AAAAQAAAgD8AQdcVCzVAAACAPwAAAAAAAIA/AAAAQAAAgD8AAAAAAAAAQAAAAEAAAIA/AAAAAAAAgL8AAIC/AAAAQABBlhYLNoC/AAAAQAAAAAAAAIA/AACAvwAAAEAAAAAAAAAAQAAAgL8AAABAAAAAAAAAgL8AAAAAAAAAQABB2xYLMUAAAAAAAACAPwAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAIC/AACAPwAAAEAAQZYXCzaAPwAAAEAAAAAAAACAPwAAgD8AAABAAAAAAAAAAEAAAIA/AAAAQAAAAAAAAIC/AAAAQAAAAEAAQdcXC3lAAAAAQAAAAAAAAIA/AAAAQAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAgL8AAIC/AACAvwAAgD8AAAAAAACAvwAAgL8AAIA/AACAPwAAgL8AAIC/AACAPwAAAEAAAIC/AACAvwAAgD8AAIC/AAAAAAAAgL8AAIA/AEHaGAvqAYC/AACAPwAAgD8AAAAAAACAvwAAgD8AAABAAAAAAAAAgL8AAIA/AACAvwAAgD8AAIC/AACAPwAAAAAAAIA/AACAvwAAgD8AAIA/AACAPwAAgL8AAIA/AAAAQAAAgD8AAIC/AACAPwAAgL8AAABAAACAvwAAgD8AAAAAAAAAQAAAgL8AAIA/AACAPwAAAEAAAIC/AACAPwAAAEAAAABAAACAvwAAgD8AAIC/AACAvwAAAAAAAIA/AAAAAAAAgL8AAAAAAACAPwAAgD8AAIC/AAAAAAAAgD8AAABAAACAvwAAAAAAAIA/AACAvwBBzhoLAoA/AEHeGgsGgD8AAIA/AEHuGgsGgD8AAABAAEH+GgvSAYA/AACAvwAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAIA/AAAAQAAAgD8AAAAAAACAPwAAgL8AAABAAAAAAAAAgD8AAAAAAAAAQAAAAAAAAIA/AACAPwAAAEAAAAAAAACAPwAAAEAAAABAAAAAAAAAgD8AAIC/AACAvwAAgD8AAIA/AAAAAAAAgL8AAIA/AACAPwAAgD8AAIC/AACAPwAAgD8AAABAAACAvwAAgD8AAIA/AACAvwAAAAAAAIA/AACAPwBB2hwL9gGAPwAAgD8AAIA/AAAAAAAAgD8AAIA/AAAAQAAAAAAAAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAAEAAAIA/AACAPwAAgD8AAIC/AAAAQAAAgD8AAIA/AAAAAAAAAEAAAIA/AACAPwAAgD8AAABAAACAPwAAgD8AAABAAAAAQAAAgD8AAIA/AACAvwAAgL8AAABAAACAPwAAAAAAAIC/AAAAQAAAgD8AAIA/AACAvwAAAEAAAIA/AAAAQAAAgL8AAABAAACAPwAAgL8AAAAAAAAAQAAAgD8AQdseC/UBQAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAQAAAAAAAAABAAACAPwAAgL8AAIA/AAAAQAAAgD8AAAAAAACAPwAAAEAAAIA/AACAPwAAgD8AAABAAACAPwAAAEAAAIA/AAAAQAAAgD8AAIC/AAAAQAAAAEAAAIA/AAAAAAAAAEAAAABAAACAPwAAgD8AAABAAAAAQAAAgD8AAABAAAAAQAAAAEAAAIA/AACAvwAAgL8AAIC/AAAAQAAAAAAAAIC/AACAvwAAAEAAAIA/AACAvwAAgL8AAABAAAAAQAAAgL8AAIC/AAAAQAAAgL8AAAAAAACAvwAAAEAAQdogC+oBgL8AAABAAACAPwAAAAAAAIC/AAAAQAAAAEAAAAAAAACAvwAAAEAAAIC/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" + const val MT_MJS: String = "YXN5bmMgZnVuY3Rpb24gY3JlYXRlU2thaW5ldEtlcm5lbHMobW9kdWxlQXJnPXt9KXt2YXIgbW9kdWxlUnRuO3ZhciBNb2R1bGU9bW9kdWxlQXJnO3ZhciBFTlZJUk9OTUVOVF9JU19XRUI9dHlwZW9mIHdpbmRvdz09Im9iamVjdCI7dmFyIEVOVklST05NRU5UX0lTX1dPUktFUj10eXBlb2YgV29ya2VyR2xvYmFsU2NvcGUhPSJ1bmRlZmluZWQiO3ZhciBFTlZJUk9OTUVOVF9JU19OT0RFPXR5cGVvZiBwcm9jZXNzPT0ib2JqZWN0IiYmcHJvY2Vzcy52ZXJzaW9ucz8ubm9kZSYmcHJvY2Vzcy50eXBlIT0icmVuZGVyZXIiO3ZhciBFTlZJUk9OTUVOVF9JU19QVEhSRUFEPUVOVklST05NRU5UX0lTX1dPUktFUiYmc2VsZi5uYW1lPy5zdGFydHNXaXRoKCJlbS1wdGhyZWFkIik7aWYoRU5WSVJPTk1FTlRfSVNfTk9ERSl7Y29uc3R7Y3JlYXRlUmVxdWlyZX09YXdhaXQgaW1wb3J0KCJtb2R1bGUiKTt2YXIgcmVxdWlyZT1jcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybC5zdGFydHNXaXRoKCJmaWxlOiIpP2ltcG9ydC5tZXRhLnVybDpwcm9jZXNzLmN3ZCgpKyIvIik7dmFyIHdvcmtlcl90aHJlYWRzPXJlcXVpcmUoIndvcmtlcl90aHJlYWRzIik7Z2xvYmFsLldvcmtlcj13b3JrZXJfdGhyZWFkcy5Xb3JrZXI7RU5WSVJPTk1FTlRfSVNfV09SS0VSPSF3b3JrZXJfdGhyZWFkcy5pc01haW5UaHJlYWQ7RU5WSVJPTk1FTlRfSVNfUFRIUkVBRD1FTlZJUk9OTUVOVF9JU19XT1JLRVImJndvcmtlcl90aHJlYWRzWyJ3b3JrZXJEYXRhIl09PSJlbS1wdGhyZWFkIn12YXIgYXJndW1lbnRzXz1bXTt2YXIgdGhpc1Byb2dyYW09Ii4vdGhpcy5wcm9ncmFtIjt2YXIgcXVpdF89KHN0YXR1cyx0b1Rocm93KT0+e3Rocm93IHRvVGhyb3d9O3ZhciBfc2NyaXB0TmFtZT1pbXBvcnQubWV0YS51cmw7dmFyIHNjcmlwdERpcmVjdG9yeT0iIjtmdW5jdGlvbiBsb2NhdGVGaWxlKHBhdGgpe2lmKE1vZHVsZVsibG9jYXRlRmlsZSJdKXtyZXR1cm4gTW9kdWxlWyJsb2NhdGVGaWxlIl0ocGF0aCxzY3JpcHREaXJlY3RvcnkpfXJldHVybiBzY3JpcHREaXJlY3RvcnkrcGF0aH12YXIgcmVhZEFzeW5jLHJlYWRCaW5hcnk7aWYoRU5WSVJPTk1FTlRfSVNfTk9ERSl7dmFyIGZzPXJlcXVpcmUoImZzIik7aWYoX3NjcmlwdE5hbWUuc3RhcnRzV2l0aCgiZmlsZToiKSl7c2NyaXB0RGlyZWN0b3J5PXJlcXVpcmUoInBhdGgiKS5kaXJuYW1lKHJlcXVpcmUoInVybCIpLmZpbGVVUkxUb1BhdGgoX3NjcmlwdE5hbWUpKSsiLyJ9cmVhZEJpbmFyeT1maWxlbmFtZT0+e2ZpbGVuYW1lPWlzRmlsZVVSSShmaWxlbmFtZSk/bmV3IFVSTChmaWxlbmFtZSk6ZmlsZW5hbWU7dmFyIHJldD1mcy5yZWFkRmlsZVN5bmMoZmlsZW5hbWUpO3JldHVybiByZXR9O3JlYWRBc3luYz1hc3luYyhmaWxlbmFtZSxiaW5hcnk9dHJ1ZSk9PntmaWxlbmFtZT1pc0ZpbGVVUkkoZmlsZW5hbWUpP25ldyBVUkwoZmlsZW5hbWUpOmZpbGVuYW1lO3ZhciByZXQ9ZnMucmVhZEZpbGVTeW5jKGZpbGVuYW1lLGJpbmFyeT91bmRlZmluZWQ6InV0ZjgiKTtyZXR1cm4gcmV0fTtpZihwcm9jZXNzLmFyZ3YubGVuZ3RoPjEpe3RoaXNQcm9ncmFtPXByb2Nlc3MuYXJndlsxXS5yZXBsYWNlKC9cXC9nLCIvIil9YXJndW1lbnRzXz1wcm9jZXNzLmFyZ3Yuc2xpY2UoMik7cXVpdF89KHN0YXR1cyx0b1Rocm93KT0+e3Byb2Nlc3MuZXhpdENvZGU9c3RhdHVzO3Rocm93IHRvVGhyb3d9fWVsc2UgaWYoRU5WSVJPTk1FTlRfSVNfV0VCfHxFTlZJUk9OTUVOVF9JU19XT1JLRVIpe3RyeXtzY3JpcHREaXJlY3Rvcnk9bmV3IFVSTCgiLiIsX3NjcmlwdE5hbWUpLmhyZWZ9Y2F0Y2h7fWlmKCFFTlZJUk9OTUVOVF9JU19OT0RFKXtpZihFTlZJUk9OTUVOVF9JU19XT1JLRVIpe3JlYWRCaW5hcnk9dXJsPT57dmFyIHhocj1uZXcgWE1MSHR0cFJlcXVlc3Q7eGhyLm9wZW4oIkdFVCIsdXJsLGZhbHNlKTt4aHIucmVzcG9uc2VUeXBlPSJhcnJheWJ1ZmZlciI7eGhyLnNlbmQobnVsbCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KHhoci5yZXNwb25zZSl9fXJlYWRBc3luYz1hc3luYyB1cmw9Pnt2YXIgcmVzcG9uc2U9YXdhaXQgZmV0Y2godXJsLHtjcmVkZW50aWFsczoic2FtZS1vcmlnaW4ifSk7aWYocmVzcG9uc2Uub2spe3JldHVybiByZXNwb25zZS5hcnJheUJ1ZmZlcigpfXRocm93IG5ldyBFcnJvcihyZXNwb25zZS5zdGF0dXMrIiA6ICIrcmVzcG9uc2UudXJsKX19fWVsc2V7fXZhciBkZWZhdWx0UHJpbnQ9Y29uc29sZS5sb2cuYmluZChjb25zb2xlKTt2YXIgZGVmYXVsdFByaW50RXJyPWNvbnNvbGUuZXJyb3IuYmluZChjb25zb2xlKTtpZihFTlZJUk9OTUVOVF9JU19OT0RFKXt2YXIgdXRpbHM9cmVxdWlyZSgidXRpbCIpO3ZhciBzdHJpbmdpZnk9YT0+dHlwZW9mIGE9PSJvYmplY3QiP3V0aWxzLmluc3BlY3QoYSk6YTtkZWZhdWx0UHJpbnQ9KC4uLmFyZ3MpPT5mcy53cml0ZVN5bmMoMSxhcmdzLm1hcChzdHJpbmdpZnkpLmpvaW4oIiAiKSsiXG4iKTtkZWZhdWx0UHJpbnRFcnI9KC4uLmFyZ3MpPT5mcy53cml0ZVN5bmMoMixhcmdzLm1hcChzdHJpbmdpZnkpLmpvaW4oIiAiKSsiXG4iKX12YXIgb3V0PWRlZmF1bHRQcmludDt2YXIgZXJyPWRlZmF1bHRQcmludEVycjt2YXIgd2FzbUJpbmFyeTt2YXIgd2FzbU1vZHVsZTt2YXIgQUJPUlQ9ZmFsc2U7dmFyIEVYSVRTVEFUVVM7dmFyIGlzRmlsZVVSST1maWxlbmFtZT0+ZmlsZW5hbWUuc3RhcnRzV2l0aCgiZmlsZTovLyIpO2Z1bmN0aW9uIGdyb3dNZW1WaWV3cygpe2lmKHdhc21NZW1vcnkuYnVmZmVyIT1IRUFQOC5idWZmZXIpe3VwZGF0ZU1lbW9yeVZpZXdzKCl9fXZhciByZWFkeVByb21pc2VSZXNvbHZlLHJlYWR5UHJvbWlzZVJlamVjdDtpZihFTlZJUk9OTUVOVF9JU19OT0RFJiZFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt2YXIgcGFyZW50UG9ydD13b3JrZXJfdGhyZWFkc1sicGFyZW50UG9ydCJdO3BhcmVudFBvcnQub24oIm1lc3NhZ2UiLG1zZz0+Z2xvYmFsLm9ubWVzc2FnZT8uKHtkYXRhOm1zZ30pKTtPYmplY3QuYXNzaWduKGdsb2JhbFRoaXMse3NlbGY6Z2xvYmFsLHBvc3RNZXNzYWdlOm1zZz0+cGFyZW50UG9ydFsicG9zdE1lc3NhZ2UiXShtc2cpfSk7cHJvY2Vzcy5vbigidW5jYXVnaHRFeGNlcHRpb24iLGVycj0+e3Bvc3RNZXNzYWdlKHtjbWQ6InVuY2F1Z2h0RXhjZXB0aW9uIixlcnJvcjplcnJ9KTtwcm9jZXNzLmV4aXQoMSl9KX12YXIgc3RhcnRXb3JrZXI7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7dmFyIGluaXRpYWxpemVkSlM9ZmFsc2U7c2VsZi5vbnVuaGFuZGxlZHJlamVjdGlvbj1lPT57dGhyb3cgZS5yZWFzb258fGV9O2Z1bmN0aW9uIGhhbmRsZU1lc3NhZ2UoZSl7dHJ5e3ZhciBtc2dEYXRhPWVbImRhdGEiXTt2YXIgY21kPW1zZ0RhdGEuY21kO2lmKGNtZD09PSJsb2FkIil7bGV0IG1lc3NhZ2VRdWV1ZT1bXTtzZWxmLm9ubWVzc2FnZT1lPT5tZXNzYWdlUXVldWUucHVzaChlKTtzdGFydFdvcmtlcj0oKT0+e3Bvc3RNZXNzYWdlKHtjbWQ6ImxvYWRlZCJ9KTtmb3IobGV0IG1zZyBvZiBtZXNzYWdlUXVldWUpe2hhbmRsZU1lc3NhZ2UobXNnKX1zZWxmLm9ubWVzc2FnZT1oYW5kbGVNZXNzYWdlfTtmb3IoY29uc3QgaGFuZGxlciBvZiBtc2dEYXRhLmhhbmRsZXJzKXtpZighTW9kdWxlW2hhbmRsZXJdfHxNb2R1bGVbaGFuZGxlcl0ucHJveHkpe01vZHVsZVtoYW5kbGVyXT0oLi4uYXJncyk9Pntwb3N0TWVzc2FnZSh7Y21kOiJjYWxsSGFuZGxlciIsaGFuZGxlcixhcmdzfSl9O2lmKGhhbmRsZXI9PSJwcmludCIpb3V0PU1vZHVsZVtoYW5kbGVyXTtpZihoYW5kbGVyPT0icHJpbnRFcnIiKWVycj1Nb2R1bGVbaGFuZGxlcl19fXdhc21NZW1vcnk9bXNnRGF0YS53YXNtTWVtb3J5O3VwZGF0ZU1lbW9yeVZpZXdzKCk7d2FzbU1vZHVsZT1tc2dEYXRhLndhc21Nb2R1bGU7Y3JlYXRlV2FzbSgpO3J1bigpfWVsc2UgaWYoY21kPT09InJ1biIpe2VzdGFibGlzaFN0YWNrU3BhY2UobXNnRGF0YS5wdGhyZWFkX3B0cik7X19lbXNjcmlwdGVuX3RocmVhZF9pbml0KG1zZ0RhdGEucHRocmVhZF9wdHIsMCwwLDEsMCwwKTtQVGhyZWFkLnRocmVhZEluaXRUTFMoKTtfX2Vtc2NyaXB0ZW5fdGhyZWFkX21haWxib3hfYXdhaXQobXNnRGF0YS5wdGhyZWFkX3B0cik7aWYoIWluaXRpYWxpemVkSlMpe2luaXRpYWxpemVkSlM9dHJ1ZX10cnl7aW52b2tlRW50cnlQb2ludChtc2dEYXRhLnN0YXJ0X3JvdXRpbmUsbXNnRGF0YS5hcmcpfWNhdGNoKGV4KXtpZihleCE9InVud2luZCIpe3Rocm93IGV4fX19ZWxzZSBpZihtc2dEYXRhLnRhcmdldD09PSJzZXRpbW1lZGlhdGUiKXt9ZWxzZSBpZihjbWQ9PT0iY2hlY2tNYWlsYm94Iil7aWYoaW5pdGlhbGl6ZWRKUyl7Y2hlY2tNYWlsYm94KCl9fWVsc2UgaWYoY21kKXtlcnIoYHdvcmtlcjogcmVjZWl2ZWQgdW5rbm93biBjb21tYW5kICR7Y21kfWApO2Vycihtc2dEYXRhKX19Y2F0Y2goZXgpe19fZW1zY3JpcHRlbl90aHJlYWRfY3Jhc2hlZCgpO3Rocm93IGV4fX1zZWxmLm9ubWVzc2FnZT1oYW5kbGVNZXNzYWdlfXZhciB3YXNtTWVtb3J5O3ZhciBIRUFQOCxIRUFQVTgsSEVBUDE2LEhFQVBVMTYsSEVBUDMyLEhFQVBVMzIsSEVBUEYzMixIRUFQRjY0O3ZhciBIRUFQNjQsSEVBUFU2NDt2YXIgcnVudGltZUluaXRpYWxpemVkPWZhbHNlO2Z1bmN0aW9uIHVwZGF0ZU1lbW9yeVZpZXdzKCl7dmFyIGI9d2FzbU1lbW9yeS5idWZmZXI7SEVBUDg9bmV3IEludDhBcnJheShiKTtIRUFQMTY9bmV3IEludDE2QXJyYXkoYik7SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO0hFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO0hFQVAzMj1uZXcgSW50MzJBcnJheShiKTtIRUFQVTMyPW5ldyBVaW50MzJBcnJheShiKTtIRUFQRjMyPW5ldyBGbG9hdDMyQXJyYXkoYik7SEVBUEY2ND1uZXcgRmxvYXQ2NEFycmF5KGIpO0hFQVA2ND1uZXcgQmlnSW50NjRBcnJheShiKTtIRUFQVTY0PW5ldyBCaWdVaW50NjRBcnJheShiKX1mdW5jdGlvbiBpbml0TWVtb3J5KCl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7cmV0dXJufWlmKE1vZHVsZVsid2FzbU1lbW9yeSJdKXt3YXNtTWVtb3J5PU1vZHVsZVsid2FzbU1lbW9yeSJdfWVsc2V7dmFyIElOSVRJQUxfTUVNT1JZPU1vZHVsZVsiSU5JVElBTF9NRU1PUlkiXXx8NjcxMDg4NjQ7d2FzbU1lbW9yeT1uZXcgV2ViQXNzZW1ibHkuTWVtb3J5KHtpbml0aWFsOklOSVRJQUxfTUVNT1JZLzY1NTM2LG1heGltdW06NjU1MzYsc2hhcmVkOnRydWV9KX11cGRhdGVNZW1vcnlWaWV3cygpfWZ1bmN0aW9uIHByZVJ1bigpe2lmKE1vZHVsZVsicHJlUnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInByZVJ1biJdPT0iZnVuY3Rpb24iKU1vZHVsZVsicHJlUnVuIl09W01vZHVsZVsicHJlUnVuIl1dO3doaWxlKE1vZHVsZVsicHJlUnVuIl0ubGVuZ3RoKXthZGRPblByZVJ1bihNb2R1bGVbInByZVJ1biJdLnNoaWZ0KCkpfX1jYWxsUnVudGltZUNhbGxiYWNrcyhvblByZVJ1bnMpfWZ1bmN0aW9uIGluaXRSdW50aW1lKCl7cnVudGltZUluaXRpYWxpemVkPXRydWU7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRClyZXR1cm4gc3RhcnRXb3JrZXIoKTt3YXNtRXhwb3J0c1sibyJdKCl9ZnVuY3Rpb24gcG9zdFJ1bigpe2lmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpe3JldHVybn1pZihNb2R1bGVbInBvc3RSdW4iXSl7aWYodHlwZW9mIE1vZHVsZVsicG9zdFJ1biJdPT0iZnVuY3Rpb24iKU1vZHVsZVsicG9zdFJ1biJdPVtNb2R1bGVbInBvc3RSdW4iXV07d2hpbGUoTW9kdWxlWyJwb3N0UnVuIl0ubGVuZ3RoKXthZGRPblBvc3RSdW4oTW9kdWxlWyJwb3N0UnVuIl0uc2hpZnQoKSl9fWNhbGxSdW50aW1lQ2FsbGJhY2tzKG9uUG9zdFJ1bnMpfWZ1bmN0aW9uIGFib3J0KHdoYXQpe01vZHVsZVsib25BYm9ydCJdPy4od2hhdCk7d2hhdD0iQWJvcnRlZCgiK3doYXQrIikiO2Vycih3aGF0KTtBQk9SVD10cnVlO3doYXQrPSIuIEJ1aWxkIHdpdGggLXNBU1NFUlRJT05TIGZvciBtb3JlIGluZm8uIjt2YXIgZT1uZXcgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yKHdoYXQpO3JlYWR5UHJvbWlzZVJlamVjdD8uKGUpO3Rocm93IGV9dmFyIHdhc21CaW5hcnlGaWxlO2Z1bmN0aW9uIGZpbmRXYXNtQmluYXJ5KCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBsb2NhdGVGaWxlKCJza2FpbmV0X2tlcm5lbHNfbXQud2FzbSIpfXRyeXtyZXR1cm4gbmV3IFVSTCgic2thaW5ldF9rZXJuZWxzX210Lndhc20iLGltcG9ydC5tZXRhLnVybCkuaHJlZn1jYXRjaChlKXtyZXR1cm4gInNrYWluZXRfa2VybmVsc19tdC53YXNtIn19ZnVuY3Rpb24gZ2V0QmluYXJ5U3luYyhmaWxlKXtpZihmaWxlPT13YXNtQmluYXJ5RmlsZSYmd2FzbUJpbmFyeSl7cmV0dXJuIG5ldyBVaW50OEFycmF5KHdhc21CaW5hcnkpfWlmKHJlYWRCaW5hcnkpe3JldHVybiByZWFkQmluYXJ5KGZpbGUpfXRocm93ImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkIn1hc3luYyBmdW5jdGlvbiBnZXRXYXNtQmluYXJ5KGJpbmFyeUZpbGUpe2lmKCF3YXNtQmluYXJ5KXt0cnl7dmFyIHJlc3BvbnNlPWF3YWl0IHJlYWRBc3luYyhiaW5hcnlGaWxlKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkocmVzcG9uc2UpfWNhdGNoe319cmV0dXJuIGdldEJpbmFyeVN5bmMoYmluYXJ5RmlsZSl9YXN5bmMgZnVuY3Rpb24gaW5zdGFudGlhdGVBcnJheUJ1ZmZlcihiaW5hcnlGaWxlLGltcG9ydHMpe3RyeXt2YXIgYmluYXJ5PWF3YWl0IGdldFdhc21CaW5hcnkoYmluYXJ5RmlsZSk7dmFyIGluc3RhbmNlPWF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJpbmFyeSxpbXBvcnRzKTtyZXR1cm4gaW5zdGFuY2V9Y2F0Y2gocmVhc29uKXtlcnIoYGZhaWxlZCB0byBhc3luY2hyb25vdXNseSBwcmVwYXJlIHdhc206ICR7cmVhc29ufWApO2Fib3J0KHJlYXNvbil9fWFzeW5jIGZ1bmN0aW9uIGluc3RhbnRpYXRlQXN5bmMoYmluYXJ5LGJpbmFyeUZpbGUsaW1wb3J0cyl7aWYoIWJpbmFyeSYmIUVOVklST05NRU5UX0lTX05PREUpe3RyeXt2YXIgcmVzcG9uc2U9ZmV0Y2goYmluYXJ5RmlsZSx7Y3JlZGVudGlhbHM6InNhbWUtb3JpZ2luIn0pO3ZhciBpbnN0YW50aWF0aW9uUmVzdWx0PWF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKHJlc3BvbnNlLGltcG9ydHMpO3JldHVybiBpbnN0YW50aWF0aW9uUmVzdWx0fWNhdGNoKHJlYXNvbil7ZXJyKGB3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogJHtyZWFzb259YCk7ZXJyKCJmYWxsaW5nIGJhY2sgdG8gQXJyYXlCdWZmZXIgaW5zdGFudGlhdGlvbiIpfX1yZXR1cm4gaW5zdGFudGlhdGVBcnJheUJ1ZmZlcihiaW5hcnlGaWxlLGltcG9ydHMpfWZ1bmN0aW9uIGdldFdhc21JbXBvcnRzKCl7YXNzaWduV2FzbUltcG9ydHMoKTtyZXR1cm57YTp3YXNtSW1wb3J0c319YXN5bmMgZnVuY3Rpb24gY3JlYXRlV2FzbSgpe2Z1bmN0aW9uIHJlY2VpdmVJbnN0YW5jZShpbnN0YW5jZSxtb2R1bGUpe3dhc21FeHBvcnRzPWluc3RhbmNlLmV4cG9ydHM7d2FzbUV4cG9ydHM9YXBwbHlTaWduYXR1cmVDb252ZXJzaW9ucyh3YXNtRXhwb3J0cyk7cmVnaXN0ZXJUTFNJbml0KHdhc21FeHBvcnRzWyJSIl0pO3dhc21UYWJsZT13YXNtRXhwb3J0c1sicSJdO3dhc21Nb2R1bGU9bW9kdWxlO2Fzc2lnbldhc21FeHBvcnRzKHdhc21FeHBvcnRzKTtyZXR1cm4gd2FzbUV4cG9ydHN9ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZXR1cm4gcmVjZWl2ZUluc3RhbmNlKHJlc3VsdFsiaW5zdGFuY2UiXSxyZXN1bHRbIm1vZHVsZSJdKX12YXIgaW5mbz1nZXRXYXNtSW1wb3J0cygpO2lmKE1vZHVsZVsiaW5zdGFudGlhdGVXYXNtIl0pe3JldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSxyZWplY3QpPT57TW9kdWxlWyJpbnN0YW50aWF0ZVdhc20iXShpbmZvLChtb2QsaW5zdCk9PntyZXNvbHZlKHJlY2VpdmVJbnN0YW5jZShtb2QsaW5zdCkpfSl9KX1pZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt2YXIgaW5zdGFuY2U9bmV3IFdlYkFzc2VtYmx5Lkluc3RhbmNlKHdhc21Nb2R1bGUsZ2V0V2FzbUltcG9ydHMoKSk7cmV0dXJuIHJlY2VpdmVJbnN0YW5jZShpbnN0YW5jZSx3YXNtTW9kdWxlKX13YXNtQmluYXJ5RmlsZT8/PWZpbmRXYXNtQmluYXJ5KCk7dmFyIHJlc3VsdD1hd2FpdCBpbnN0YW50aWF0ZUFzeW5jKHdhc21CaW5hcnksd2FzbUJpbmFyeUZpbGUsaW5mbyk7dmFyIGV4cG9ydHM9cmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KTtyZXR1cm4gZXhwb3J0c31jbGFzcyBFeGl0U3RhdHVze25hbWU9IkV4aXRTdGF0dXMiO2NvbnN0cnVjdG9yKHN0YXR1cyl7dGhpcy5tZXNzYWdlPWBQcm9ncmFtIHRlcm1pbmF0ZWQgd2l0aCBleGl0KCR7c3RhdHVzfSlgO3RoaXMuc3RhdHVzPXN0YXR1c319dmFyIHRlcm1pbmF0ZVdvcmtlcj13b3JrZXI9Pnt3b3JrZXIudGVybWluYXRlKCk7d29ya2VyLm9ubWVzc2FnZT1lPT57fX07dmFyIGNsZWFudXBUaHJlYWQ9cHRocmVhZF9wdHI9Pnt2YXIgd29ya2VyPVBUaHJlYWQucHRocmVhZHNbcHRocmVhZF9wdHJdO1BUaHJlYWQucmV0dXJuV29ya2VyVG9Qb29sKHdvcmtlcil9O3ZhciBjYWxsUnVudGltZUNhbGxiYWNrcz1jYWxsYmFja3M9Pnt3aGlsZShjYWxsYmFja3MubGVuZ3RoPjApe2NhbGxiYWNrcy5zaGlmdCgpKE1vZHVsZSl9fTt2YXIgb25QcmVSdW5zPVtdO3ZhciBhZGRPblByZVJ1bj1jYj0+b25QcmVSdW5zLnB1c2goY2IpO3ZhciBydW5EZXBlbmRlbmNpZXM9MDt2YXIgZGVwZW5kZW5jaWVzRnVsZmlsbGVkPW51bGw7dmFyIHJlbW92ZVJ1bkRlcGVuZGVuY3k9aWQ9PntydW5EZXBlbmRlbmNpZXMtLTtNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXT8uKHJ1bkRlcGVuZGVuY2llcyk7aWYocnVuRGVwZW5kZW5jaWVzPT0wKXtpZihkZXBlbmRlbmNpZXNGdWxmaWxsZWQpe3ZhciBjYWxsYmFjaz1kZXBlbmRlbmNpZXNGdWxmaWxsZWQ7ZGVwZW5kZW5jaWVzRnVsZmlsbGVkPW51bGw7Y2FsbGJhY2soKX19fTt2YXIgYWRkUnVuRGVwZW5kZW5jeT1pZD0+e3J1bkRlcGVuZGVuY2llcysrO01vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdPy4ocnVuRGVwZW5kZW5jaWVzKX07dmFyIHNwYXduVGhyZWFkPXRocmVhZFBhcmFtcz0+e3ZhciB3b3JrZXI9UFRocmVhZC5nZXROZXdXb3JrZXIoKTtpZighd29ya2VyKXtyZXR1cm4gNn1QVGhyZWFkLnJ1bm5pbmdXb3JrZXJzLnB1c2god29ya2VyKTtQVGhyZWFkLnB0aHJlYWRzW3RocmVhZFBhcmFtcy5wdGhyZWFkX3B0cl09d29ya2VyO3dvcmtlci5wdGhyZWFkX3B0cj10aHJlYWRQYXJhbXMucHRocmVhZF9wdHI7dmFyIG1zZz17Y21kOiJydW4iLHN0YXJ0X3JvdXRpbmU6dGhyZWFkUGFyYW1zLnN0YXJ0Um91dGluZSxhcmc6dGhyZWFkUGFyYW1zLmFyZyxwdGhyZWFkX3B0cjp0aHJlYWRQYXJhbXMucHRocmVhZF9wdHJ9O2lmKEVOVklST05NRU5UX0lTX05PREUpe3dvcmtlci51bnJlZigpfXdvcmtlci5wb3N0TWVzc2FnZShtc2csdGhyZWFkUGFyYW1zLnRyYW5zZmVyTGlzdCk7cmV0dXJuIDB9O3ZhciBydW50aW1lS2VlcGFsaXZlQ291bnRlcj0wO3ZhciBrZWVwUnVudGltZUFsaXZlPSgpPT5ub0V4aXRSdW50aW1lfHxydW50aW1lS2VlcGFsaXZlQ291bnRlcj4wO3ZhciBzdGFja1NhdmU9KCk9Pl9lbXNjcmlwdGVuX3N0YWNrX2dldF9jdXJyZW50KCk7dmFyIHN0YWNrUmVzdG9yZT12YWw9Pl9fZW1zY3JpcHRlbl9zdGFja19yZXN0b3JlKHZhbCk7dmFyIHN0YWNrQWxsb2M9c3o9Pl9fZW1zY3JpcHRlbl9zdGFja19hbGxvYyhzeik7dmFyIHByb3h5VG9NYWluVGhyZWFkPShmdW5jSW5kZXgsZW1Bc21BZGRyLHN5bmMsLi4uY2FsbEFyZ3MpPT57dmFyIHNlcmlhbGl6ZWROdW1DYWxsQXJncz1jYWxsQXJncy5sZW5ndGgqMjt2YXIgc3A9c3RhY2tTYXZlKCk7dmFyIGFyZ3M9c3RhY2tBbGxvYyhzZXJpYWxpemVkTnVtQ2FsbEFyZ3MqOCk7dmFyIGI9YXJncz4+PjM7Zm9yKHZhciBpPTA7aTxjYWxsQXJncy5sZW5ndGg7aSsrKXt2YXIgYXJnPWNhbGxBcmdzW2ldO2lmKHR5cGVvZiBhcmc9PSJiaWdpbnQiKXsoZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaT4+PjBdPTFuOyhncm93TWVtVmlld3MoKSxIRUFQNjQpW2IrMippKzE+Pj4wXT1hcmd9ZWxzZXsoZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaT4+PjBdPTBuOyhncm93TWVtVmlld3MoKSxIRUFQRjY0KVtiKzIqaSsxPj4+MF09YXJnfX12YXIgcnRuPV9fZW1zY3JpcHRlbl9ydW5fanNfb25fbWFpbl90aHJlYWQoZnVuY0luZGV4LGVtQXNtQWRkcixzZXJpYWxpemVkTnVtQ2FsbEFyZ3MsYXJncyxzeW5jKTtzdGFja1Jlc3RvcmUoc3ApO3JldHVybiBydG59O2Z1bmN0aW9uIF9wcm9jX2V4aXQoY29kZSl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRClyZXR1cm4gcHJveHlUb01haW5UaHJlYWQoMCwwLDEsY29kZSk7RVhJVFNUQVRVUz1jb2RlO2lmKCFrZWVwUnVudGltZUFsaXZlKCkpe1BUaHJlYWQudGVybWluYXRlQWxsVGhyZWFkcygpO01vZHVsZVsib25FeGl0Il0/Lihjb2RlKTtBQk9SVD10cnVlfXF1aXRfKGNvZGUsbmV3IEV4aXRTdGF0dXMoY29kZSkpfWZ1bmN0aW9uIGV4aXRPbk1haW5UaHJlYWQocmV0dXJuQ29kZSl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRClyZXR1cm4gcHJveHlUb01haW5UaHJlYWQoMSwwLDAscmV0dXJuQ29kZSk7X2V4aXQocmV0dXJuQ29kZSl9dmFyIGV4aXRKUz0oc3RhdHVzLGltcGxpY2l0KT0+e0VYSVRTVEFUVVM9c3RhdHVzO2lmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpe2V4aXRPbk1haW5UaHJlYWQoc3RhdHVzKTt0aHJvdyJ1bndpbmQifV9wcm9jX2V4aXQoc3RhdHVzKX07dmFyIF9leGl0PWV4aXRKUzt2YXIgUFRocmVhZD17dW51c2VkV29ya2VyczpbXSxydW5uaW5nV29ya2VyczpbXSx0bHNJbml0RnVuY3Rpb25zOltdLHB0aHJlYWRzOnt9LGluaXQoKXtpZighRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7UFRocmVhZC5pbml0TWFpblRocmVhZCgpfX0saW5pdE1haW5UaHJlYWQoKXt2YXIgcHRocmVhZFBvb2xTaXplPTQ7d2hpbGUocHRocmVhZFBvb2xTaXplLS0pe1BUaHJlYWQuYWxsb2NhdGVVbnVzZWRXb3JrZXIoKX1hZGRPblByZVJ1bihhc3luYygpPT57dmFyIHB0aHJlYWRQb29sUmVhZHk9UFRocmVhZC5sb2FkV2FzbU1vZHVsZVRvQWxsV29ya2VycygpO2FkZFJ1bkRlcGVuZGVuY3koImxvYWRpbmctd29ya2VycyIpO2F3YWl0IHB0aHJlYWRQb29sUmVhZHk7cmVtb3ZlUnVuRGVwZW5kZW5jeSgibG9hZGluZy13b3JrZXJzIil9KX0sdGVybWluYXRlQWxsVGhyZWFkczooKT0+e2Zvcih2YXIgd29ya2VyIG9mIFBUaHJlYWQucnVubmluZ1dvcmtlcnMpe3Rlcm1pbmF0ZVdvcmtlcih3b3JrZXIpfWZvcih2YXIgd29ya2VyIG9mIFBUaHJlYWQudW51c2VkV29ya2Vycyl7dGVybWluYXRlV29ya2VyKHdvcmtlcil9UFRocmVhZC51bnVzZWRXb3JrZXJzPVtdO1BUaHJlYWQucnVubmluZ1dvcmtlcnM9W107UFRocmVhZC5wdGhyZWFkcz17fX0scmV0dXJuV29ya2VyVG9Qb29sOndvcmtlcj0+e3ZhciBwdGhyZWFkX3B0cj13b3JrZXIucHRocmVhZF9wdHI7ZGVsZXRlIFBUaHJlYWQucHRocmVhZHNbcHRocmVhZF9wdHJdO1BUaHJlYWQudW51c2VkV29ya2Vycy5wdXNoKHdvcmtlcik7UFRocmVhZC5ydW5uaW5nV29ya2Vycy5zcGxpY2UoUFRocmVhZC5ydW5uaW5nV29ya2Vycy5pbmRleE9mKHdvcmtlciksMSk7d29ya2VyLnB0aHJlYWRfcHRyPTA7X19lbXNjcmlwdGVuX3RocmVhZF9mcmVlX2RhdGEocHRocmVhZF9wdHIpfSx0aHJlYWRJbml0VExTKCl7UFRocmVhZC50bHNJbml0RnVuY3Rpb25zLmZvckVhY2goZj0+ZigpKX0sbG9hZFdhc21Nb2R1bGVUb1dvcmtlcjp3b3JrZXI9Pm5ldyBQcm9taXNlKG9uRmluaXNoZWRMb2FkaW5nPT57d29ya2VyLm9ubWVzc2FnZT1lPT57dmFyIGQ9ZVsiZGF0YSJdO3ZhciBjbWQ9ZC5jbWQ7aWYoZC50YXJnZXRUaHJlYWQmJmQudGFyZ2V0VGhyZWFkIT1fcHRocmVhZF9zZWxmKCkpe3ZhciB0YXJnZXRXb3JrZXI9UFRocmVhZC5wdGhyZWFkc1tkLnRhcmdldFRocmVhZF07aWYodGFyZ2V0V29ya2VyKXt0YXJnZXRXb3JrZXIucG9zdE1lc3NhZ2UoZCxkLnRyYW5zZmVyTGlzdCl9ZWxzZXtlcnIoYEludGVybmFsIGVycm9yISBXb3JrZXIgc2VudCBhIG1lc3NhZ2UgIiR7Y21kfSIgdG8gdGFyZ2V0IHB0aHJlYWQgJHtkLnRhcmdldFRocmVhZH0sIGJ1dCB0aGF0IHRocmVhZCBubyBsb25nZXIgZXhpc3RzIWApfXJldHVybn1pZihjbWQ9PT0iY2hlY2tNYWlsYm94Iil7Y2hlY2tNYWlsYm94KCl9ZWxzZSBpZihjbWQ9PT0ic3Bhd25UaHJlYWQiKXtzcGF3blRocmVhZChkKX1lbHNlIGlmKGNtZD09PSJjbGVhbnVwVGhyZWFkIil7Y2FsbFVzZXJDYWxsYmFjaygoKT0+Y2xlYW51cFRocmVhZChkLnRocmVhZCkpfWVsc2UgaWYoY21kPT09ImxvYWRlZCIpe3dvcmtlci5sb2FkZWQ9dHJ1ZTtpZihFTlZJUk9OTUVOVF9JU19OT0RFJiYhd29ya2VyLnB0aHJlYWRfcHRyKXt3b3JrZXIudW5yZWYoKX1vbkZpbmlzaGVkTG9hZGluZyh3b3JrZXIpfWVsc2UgaWYoZC50YXJnZXQ9PT0ic2V0aW1tZWRpYXRlIil7d29ya2VyLnBvc3RNZXNzYWdlKGQpfWVsc2UgaWYoY21kPT09InVuY2F1Z2h0RXhjZXB0aW9uIil7d29ya2VyLm9uZXJyb3IoZC5lcnJvcil9ZWxzZSBpZihjbWQ9PT0iY2FsbEhhbmRsZXIiKXtNb2R1bGVbZC5oYW5kbGVyXSguLi5kLmFyZ3MpfWVsc2UgaWYoY21kKXtlcnIoYHdvcmtlciBzZW50IGFuIHVua25vd24gY29tbWFuZCAke2NtZH1gKX19O3dvcmtlci5vbmVycm9yPWU9Pnt2YXIgbWVzc2FnZT0id29ya2VyIHNlbnQgYW4gZXJyb3IhIjtlcnIoYCR7bWVzc2FnZX0gJHtlLmZpbGVuYW1lfToke2UubGluZW5vfTogJHtlLm1lc3NhZ2V9YCk7dGhyb3cgZX07aWYoRU5WSVJPTk1FTlRfSVNfTk9ERSl7d29ya2VyLm9uKCJtZXNzYWdlIixkYXRhPT53b3JrZXIub25tZXNzYWdlKHtkYXRhfSkpO3dvcmtlci5vbigiZXJyb3IiLGU9Pndvcmtlci5vbmVycm9yKGUpKX12YXIgaGFuZGxlcnM9W107dmFyIGtub3duSGFuZGxlcnM9WyJvbkV4aXQiLCJvbkFib3J0IiwicHJpbnQiLCJwcmludEVyciJdO2Zvcih2YXIgaGFuZGxlciBvZiBrbm93bkhhbmRsZXJzKXtpZihNb2R1bGUucHJvcGVydHlJc0VudW1lcmFibGUoaGFuZGxlcikpe2hhbmRsZXJzLnB1c2goaGFuZGxlcil9fXdvcmtlci5wb3N0TWVzc2FnZSh7Y21kOiJsb2FkIixoYW5kbGVycyx3YXNtTWVtb3J5LHdhc21Nb2R1bGV9KX0pLGFzeW5jIGxvYWRXYXNtTW9kdWxlVG9BbGxXb3JrZXJzKCl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7cmV0dXJufWxldCBwdGhyZWFkUG9vbFJlYWR5PVByb21pc2UuYWxsKFBUaHJlYWQudW51c2VkV29ya2Vycy5tYXAoUFRocmVhZC5sb2FkV2FzbU1vZHVsZVRvV29ya2VyKSk7cmV0dXJuIHB0aHJlYWRQb29sUmVhZHl9LGFsbG9jYXRlVW51c2VkV29ya2VyKCl7dmFyIHdvcmtlcjtpZihNb2R1bGVbIm1haW5TY3JpcHRVcmxPckJsb2IiXSl7dmFyIHB0aHJlYWRNYWluSnM9TW9kdWxlWyJtYWluU2NyaXB0VXJsT3JCbG9iIl07aWYodHlwZW9mIHB0aHJlYWRNYWluSnMhPSJzdHJpbmciKXtwdGhyZWFkTWFpbkpzPVVSTC5jcmVhdGVPYmplY3RVUkwocHRocmVhZE1haW5Kcyl9d29ya2VyPW5ldyBXb3JrZXIoRU5WSVJPTk1FTlRfSVNfTk9ERSYmdHlwZW9mIHB0aHJlYWRNYWluSnM9PSJzdHJpbmciJiZwdGhyZWFkTWFpbkpzLnN0YXJ0c1dpdGgoImRhdGE6Iik/bmV3IFVSTChwdGhyZWFkTWFpbkpzKTpwdGhyZWFkTWFpbkpzLHt0eXBlOiJtb2R1bGUiLHdvcmtlckRhdGE6ImVtLXB0aHJlYWQiLG5hbWU6ImVtLXB0aHJlYWQifSl9ZWxzZSB3b3JrZXI9bmV3IFdvcmtlcihuZXcgVVJMKCJza2FpbmV0X2tlcm5lbHNfbXQubWpzIixpbXBvcnQubWV0YS51cmwpLHt0eXBlOiJtb2R1bGUiLHdvcmtlckRhdGE6ImVtLXB0aHJlYWQiLG5hbWU6ImVtLXB0aHJlYWQifSk7UFRocmVhZC51bnVzZWRXb3JrZXJzLnB1c2god29ya2VyKX0sZ2V0TmV3V29ya2VyKCl7aWYoUFRocmVhZC51bnVzZWRXb3JrZXJzLmxlbmd0aD09MCl7UFRocmVhZC5hbGxvY2F0ZVVudXNlZFdvcmtlcigpO1BUaHJlYWQubG9hZFdhc21Nb2R1bGVUb1dvcmtlcihQVGhyZWFkLnVudXNlZFdvcmtlcnNbMF0pfXJldHVybiBQVGhyZWFkLnVudXNlZFdvcmtlcnMucG9wKCl9fTt2YXIgb25Qb3N0UnVucz1bXTt2YXIgYWRkT25Qb3N0UnVuPWNiPT5vblBvc3RSdW5zLnB1c2goY2IpO2Z1bmN0aW9uIGVzdGFibGlzaFN0YWNrU3BhY2UocHRocmVhZF9wdHIpe3ZhciBzdGFja0hpZ2g9KGdyb3dNZW1WaWV3cygpLEhFQVBVMzIpW3B0aHJlYWRfcHRyKzUyPj4+Mj4+PjBdO3ZhciBzdGFja1NpemU9KGdyb3dNZW1WaWV3cygpLEhFQVBVMzIpW3B0aHJlYWRfcHRyKzU2Pj4+Mj4+PjBdO3ZhciBzdGFja0xvdz1zdGFja0hpZ2gtc3RhY2tTaXplO19lbXNjcmlwdGVuX3N0YWNrX3NldF9saW1pdHMoc3RhY2tIaWdoLHN0YWNrTG93KTtzdGFja1Jlc3RvcmUoc3RhY2tIaWdoKX12YXIgd2FzbVRhYmxlTWlycm9yPVtdO3ZhciB3YXNtVGFibGU7dmFyIGdldFdhc21UYWJsZUVudHJ5PWZ1bmNQdHI9Pnt2YXIgZnVuYz13YXNtVGFibGVNaXJyb3JbZnVuY1B0cl07aWYoIWZ1bmMpe3dhc21UYWJsZU1pcnJvcltmdW5jUHRyXT1mdW5jPXdhc21UYWJsZS5nZXQoZnVuY1B0cil9cmV0dXJuIGZ1bmN9O3ZhciBpbnZva2VFbnRyeVBvaW50PShwdHIsYXJnKT0+e3J1bnRpbWVLZWVwYWxpdmVDb3VudGVyPTA7bm9FeGl0UnVudGltZT0wO3ZhciByZXN1bHQ9Z2V0V2FzbVRhYmxlRW50cnkocHRyKShhcmcpO2Z1bmN0aW9uIGZpbmlzaChyZXN1bHQpe2lmKGtlZXBSdW50aW1lQWxpdmUoKSl7RVhJVFNUQVRVUz1yZXN1bHQ7cmV0dXJufV9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdChyZXN1bHQpfWZpbmlzaChyZXN1bHQpfTt2YXIgbm9FeGl0UnVudGltZT10cnVlO3ZhciByZWdpc3RlclRMU0luaXQ9dGxzSW5pdEZ1bmM9PlBUaHJlYWQudGxzSW5pdEZ1bmN0aW9ucy5wdXNoKHRsc0luaXRGdW5jKTtmdW5jdGlvbiBwdGhyZWFkQ3JlYXRlUHJveGllZChwdGhyZWFkX3B0cixhdHRyLHN0YXJ0Um91dGluZSxhcmcpe2lmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpcmV0dXJuIHByb3h5VG9NYWluVGhyZWFkKDIsMCwxLHB0aHJlYWRfcHRyLGF0dHIsc3RhcnRSb3V0aW5lLGFyZyk7cmV0dXJuIF9fX3B0aHJlYWRfY3JlYXRlX2pzKHB0aHJlYWRfcHRyLGF0dHIsc3RhcnRSb3V0aW5lLGFyZyl9dmFyIF9lbXNjcmlwdGVuX2hhc190aHJlYWRpbmdfc3VwcG9ydD0oKT0+dHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyIT0idW5kZWZpbmVkIjtmdW5jdGlvbiBfX19wdGhyZWFkX2NyZWF0ZV9qcyhwdGhyZWFkX3B0cixhdHRyLHN0YXJ0Um91dGluZSxhcmcpe3B0aHJlYWRfcHRyPj4+PTA7YXR0cj4+Pj0wO3N0YXJ0Um91dGluZT4+Pj0wO2FyZz4+Pj0wO2lmKCFfZW1zY3JpcHRlbl9oYXNfdGhyZWFkaW5nX3N1cHBvcnQoKSl7cmV0dXJuIDZ9dmFyIHRyYW5zZmVyTGlzdD1bXTt2YXIgZXJyb3I9MDtpZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEJiYodHJhbnNmZXJMaXN0Lmxlbmd0aD09PTB8fGVycm9yKSl7cmV0dXJuIHB0aHJlYWRDcmVhdGVQcm94aWVkKHB0aHJlYWRfcHRyLGF0dHIsc3RhcnRSb3V0aW5lLGFyZyl9aWYoZXJyb3IpcmV0dXJuIGVycm9yO3ZhciB0aHJlYWRQYXJhbXM9e3N0YXJ0Um91dGluZSxwdGhyZWFkX3B0cixhcmcsdHJhbnNmZXJMaXN0fTtpZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt0aHJlYWRQYXJhbXMuY21kPSJzcGF3blRocmVhZCI7cG9zdE1lc3NhZ2UodGhyZWFkUGFyYW1zLHRyYW5zZmVyTGlzdCk7cmV0dXJuIDB9cmV0dXJuIHNwYXduVGhyZWFkKHRocmVhZFBhcmFtcyl9ZnVuY3Rpb24gX19lbXNjcmlwdGVuX2luaXRfbWFpbl90aHJlYWRfanModGIpe3RiPj4+PTA7X19lbXNjcmlwdGVuX3RocmVhZF9pbml0KHRiLCFFTlZJUk9OTUVOVF9JU19XT1JLRVIsMSwhRU5WSVJPTk1FTlRfSVNfV0VCLDY1NTM2LGZhbHNlKTtQVGhyZWFkLnRocmVhZEluaXRUTFMoKX12YXIgaGFuZGxlRXhjZXB0aW9uPWU9PntpZihlIGluc3RhbmNlb2YgRXhpdFN0YXR1c3x8ZT09InVud2luZCIpe3JldHVybiBFWElUU1RBVFVTfXF1aXRfKDEsZSl9O3ZhciBtYXliZUV4aXQ9KCk9PntpZigha2VlcFJ1bnRpbWVBbGl2ZSgpKXt0cnl7aWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7aWYoX3B0aHJlYWRfc2VsZigpKV9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdChFWElUU1RBVFVTKTtyZXR1cm59X2V4aXQoRVhJVFNUQVRVUyl9Y2F0Y2goZSl7aGFuZGxlRXhjZXB0aW9uKGUpfX19O3ZhciBjYWxsVXNlckNhbGxiYWNrPWZ1bmM9PntpZihBQk9SVCl7cmV0dXJufXRyeXtmdW5jKCk7bWF5YmVFeGl0KCl9Y2F0Y2goZSl7aGFuZGxlRXhjZXB0aW9uKGUpfX07ZnVuY3Rpb24gX19lbXNjcmlwdGVuX3RocmVhZF9tYWlsYm94X2F3YWl0KHB0aHJlYWRfcHRyKXtwdGhyZWFkX3B0cj4+Pj0wO2lmKHR5cGVvZiBBdG9taWNzLndhaXRBc3luYz09PSJmdW5jdGlvbiIpe3ZhciB3YWl0PUF0b21pY3Mud2FpdEFzeW5jKChncm93TWVtVmlld3MoKSxIRUFQMzIpLHB0aHJlYWRfcHRyPj4+MixwdGhyZWFkX3B0cik7d2FpdC52YWx1ZS50aGVuKGNoZWNrTWFpbGJveCk7dmFyIHdhaXRpbmdBc3luYz1wdGhyZWFkX3B0cisxMjg7QXRvbWljcy5zdG9yZSgoZ3Jvd01lbVZpZXdzKCksSEVBUDMyKSx3YWl0aW5nQXN5bmM+Pj4yLDEpfX12YXIgY2hlY2tNYWlsYm94PSgpPT5jYWxsVXNlckNhbGxiYWNrKCgpPT57dmFyIHB0aHJlYWRfcHRyPV9wdGhyZWFkX3NlbGYoKTtpZihwdGhyZWFkX3B0cil7X19lbXNjcmlwdGVuX3RocmVhZF9tYWlsYm94X2F3YWl0KHB0aHJlYWRfcHRyKTtfX2Vtc2NyaXB0ZW5fY2hlY2tfbWFpbGJveCgpfX0pO2Z1bmN0aW9uIF9fZW1zY3JpcHRlbl9ub3RpZnlfbWFpbGJveF9wb3N0bWVzc2FnZSh0YXJnZXRUaHJlYWQsY3VyclRocmVhZElkKXt0YXJnZXRUaHJlYWQ+Pj49MDtjdXJyVGhyZWFkSWQ+Pj49MDtpZih0YXJnZXRUaHJlYWQ9PWN1cnJUaHJlYWRJZCl7c2V0VGltZW91dChjaGVja01haWxib3gpfWVsc2UgaWYoRU5WSVJPTk1FTlRfSVNfUFRIUkVBRCl7cG9zdE1lc3NhZ2Uoe3RhcmdldFRocmVhZCxjbWQ6ImNoZWNrTWFpbGJveCJ9KX1lbHNle3ZhciB3b3JrZXI9UFRocmVhZC5wdGhyZWFkc1t0YXJnZXRUaHJlYWRdO2lmKCF3b3JrZXIpe3JldHVybn13b3JrZXIucG9zdE1lc3NhZ2Uoe2NtZDoiY2hlY2tNYWlsYm94In0pfX12YXIgcHJveGllZEpTQ2FsbEFyZ3M9W107ZnVuY3Rpb24gX19lbXNjcmlwdGVuX3JlY2VpdmVfb25fbWFpbl90aHJlYWRfanMoZnVuY0luZGV4LGVtQXNtQWRkcixjYWxsaW5nVGhyZWFkLG51bUNhbGxBcmdzLGFyZ3Mpe2VtQXNtQWRkcj4+Pj0wO2NhbGxpbmdUaHJlYWQ+Pj49MDthcmdzPj4+PTA7bnVtQ2FsbEFyZ3MvPTI7cHJveGllZEpTQ2FsbEFyZ3MubGVuZ3RoPW51bUNhbGxBcmdzO3ZhciBiPWFyZ3M+Pj4zO2Zvcih2YXIgaT0wO2k8bnVtQ2FsbEFyZ3M7aSsrKXtpZigoZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaT4+PjBdKXtwcm94aWVkSlNDYWxsQXJnc1tpXT0oZ3Jvd01lbVZpZXdzKCksSEVBUDY0KVtiKzIqaSsxPj4+MF19ZWxzZXtwcm94aWVkSlNDYWxsQXJnc1tpXT0oZ3Jvd01lbVZpZXdzKCksSEVBUEY2NClbYisyKmkrMT4+PjBdfX12YXIgZnVuYz1wcm94aWVkRnVuY3Rpb25UYWJsZVtmdW5jSW5kZXhdO1BUaHJlYWQuY3VycmVudFByb3hpZWRPcGVyYXRpb25DYWxsZXJUaHJlYWQ9Y2FsbGluZ1RocmVhZDt2YXIgcnRuPWZ1bmMoLi4ucHJveGllZEpTQ2FsbEFyZ3MpO1BUaHJlYWQuY3VycmVudFByb3hpZWRPcGVyYXRpb25DYWxsZXJUaHJlYWQ9MDtyZXR1cm4gcnRufWZ1bmN0aW9uIF9fZW1zY3JpcHRlbl90aHJlYWRfY2xlYW51cCh0aHJlYWQpe3RocmVhZD4+Pj0wO2lmKCFFTlZJUk9OTUVOVF9JU19QVEhSRUFEKWNsZWFudXBUaHJlYWQodGhyZWFkKTtlbHNlIHBvc3RNZXNzYWdlKHtjbWQ6ImNsZWFudXBUaHJlYWQiLHRocmVhZH0pfWZ1bmN0aW9uIF9fZW1zY3JpcHRlbl90aHJlYWRfc2V0X3N0cm9uZ3JlZih0aHJlYWQpe3RocmVhZD4+Pj0wO2lmKEVOVklST05NRU5UX0lTX05PREUpe1BUaHJlYWQucHRocmVhZHNbdGhyZWFkXS5yZWYoKX19dmFyIF9lbXNjcmlwdGVuX2dldF9ub3c9KCk9PnBlcmZvcm1hbmNlLnRpbWVPcmlnaW4rcGVyZm9ybWFuY2Uubm93KCk7dmFyIF9lbXNjcmlwdGVuX2NoZWNrX2Jsb2NraW5nX2FsbG93ZWQ9KCk9Pnt9O3ZhciBydW50aW1lS2VlcGFsaXZlUHVzaD0oKT0+e3J1bnRpbWVLZWVwYWxpdmVDb3VudGVyKz0xfTt2YXIgX2Vtc2NyaXB0ZW5fZXhpdF93aXRoX2xpdmVfcnVudGltZT0oKT0+e3J1bnRpbWVLZWVwYWxpdmVQdXNoKCk7dGhyb3cidW53aW5kIn07dmFyIGdldEhlYXBNYXg9KCk9PjQyOTQ5MDE3NjA7dmFyIGFsaWduTWVtb3J5PShzaXplLGFsaWdubWVudCk9Pk1hdGguY2VpbChzaXplL2FsaWdubWVudCkqYWxpZ25tZW50O3ZhciBncm93TWVtb3J5PXNpemU9Pnt2YXIgb2xkSGVhcFNpemU9d2FzbU1lbW9yeS5idWZmZXIuYnl0ZUxlbmd0aDt2YXIgcGFnZXM9KHNpemUtb2xkSGVhcFNpemUrNjU1MzUpLzY1NTM2fDA7dHJ5e3dhc21NZW1vcnkuZ3JvdyhwYWdlcyk7dXBkYXRlTWVtb3J5Vmlld3MoKTtyZXR1cm4gMX1jYXRjaChlKXt9fTtmdW5jdGlvbiBfZW1zY3JpcHRlbl9yZXNpemVfaGVhcChyZXF1ZXN0ZWRTaXplKXtyZXF1ZXN0ZWRTaXplPj4+PTA7dmFyIG9sZFNpemU9KGdyb3dNZW1WaWV3cygpLEhFQVBVOCkubGVuZ3RoO2lmKHJlcXVlc3RlZFNpemU8PW9sZFNpemUpe3JldHVybiBmYWxzZX12YXIgbWF4SGVhcFNpemU9Z2V0SGVhcE1heCgpO2lmKHJlcXVlc3RlZFNpemU+bWF4SGVhcFNpemUpe3JldHVybiBmYWxzZX1mb3IodmFyIGN1dERvd249MTtjdXREb3duPD00O2N1dERvd24qPTIpe3ZhciBvdmVyR3Jvd25IZWFwU2l6ZT1vbGRTaXplKigxKy4yL2N1dERvd24pO292ZXJHcm93bkhlYXBTaXplPU1hdGgubWluKG92ZXJHcm93bkhlYXBTaXplLHJlcXVlc3RlZFNpemUrMTAwNjYzMjk2KTt2YXIgbmV3U2l6ZT1NYXRoLm1pbihtYXhIZWFwU2l6ZSxhbGlnbk1lbW9yeShNYXRoLm1heChyZXF1ZXN0ZWRTaXplLG92ZXJHcm93bkhlYXBTaXplKSw2NTUzNikpO3ZhciByZXBsYWNlbWVudD1ncm93TWVtb3J5KG5ld1NpemUpO2lmKHJlcGxhY2VtZW50KXtyZXR1cm4gdHJ1ZX19cmV0dXJuIGZhbHNlfXZhciBwcmludENoYXJCdWZmZXJzPVtudWxsLFtdLFtdXTt2YXIgVVRGOERlY29kZXI9dHlwZW9mIFRleHREZWNvZGVyIT0idW5kZWZpbmVkIj9uZXcgVGV4dERlY29kZXI6dW5kZWZpbmVkO3ZhciBmaW5kU3RyaW5nRW5kPShoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQsaWdub3JlTnVsKT0+e3ZhciBtYXhJZHg9aWR4K21heEJ5dGVzVG9SZWFkO2lmKGlnbm9yZU51bClyZXR1cm4gbWF4SWR4O3doaWxlKGhlYXBPckFycmF5W2lkeF0mJiEoaWR4Pj1tYXhJZHgpKSsraWR4O3JldHVybiBpZHh9O3ZhciBVVEY4QXJyYXlUb1N0cmluZz0oaGVhcE9yQXJyYXksaWR4PTAsbWF4Qnl0ZXNUb1JlYWQsaWdub3JlTnVsKT0+e2lkeD4+Pj0wO3ZhciBlbmRQdHI9ZmluZFN0cmluZ0VuZChoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQsaWdub3JlTnVsKTtpZihlbmRQdHItaWR4PjE2JiZoZWFwT3JBcnJheS5idWZmZXImJlVURjhEZWNvZGVyKXtyZXR1cm4gVVRGOERlY29kZXIuZGVjb2RlKGhlYXBPckFycmF5LmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP2hlYXBPckFycmF5LnN1YmFycmF5KGlkeCxlbmRQdHIpOmhlYXBPckFycmF5LnNsaWNlKGlkeCxlbmRQdHIpKX12YXIgc3RyPSIiO3doaWxlKGlkeDxlbmRQdHIpe3ZhciB1MD1oZWFwT3JBcnJheVtpZHgrK107aWYoISh1MCYxMjgpKXtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUodTApO2NvbnRpbnVlfXZhciB1MT1oZWFwT3JBcnJheVtpZHgrK10mNjM7aWYoKHUwJjIyNCk9PTE5Mil7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKCh1MCYzMSk8PDZ8dTEpO2NvbnRpbnVlfXZhciB1Mj1oZWFwT3JBcnJheVtpZHgrK10mNjM7aWYoKHUwJjI0MCk9PTIyNCl7dTA9KHUwJjE1KTw8MTJ8dTE8PDZ8dTJ9ZWxzZXt1MD0odTAmNyk8PDE4fHUxPDwxMnx1Mjw8NnxoZWFwT3JBcnJheVtpZHgrK10mNjN9aWYodTA8NjU1MzYpe3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSh1MCl9ZWxzZXt2YXIgY2g9dTAtNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKX19cmV0dXJuIHN0cn07dmFyIHByaW50Q2hhcj0oc3RyZWFtLGN1cnIpPT57dmFyIGJ1ZmZlcj1wcmludENoYXJCdWZmZXJzW3N0cmVhbV07aWYoY3Vycj09PTB8fGN1cnI9PT0xMCl7KHN0cmVhbT09PTE/b3V0OmVycikoVVRGOEFycmF5VG9TdHJpbmcoYnVmZmVyKSk7YnVmZmVyLmxlbmd0aD0wfWVsc2V7YnVmZmVyLnB1c2goY3Vycil9fTtmdW5jdGlvbiBfZmRfd3JpdGUoZmQsaW92LGlvdmNudCxwbnVtKXtpZihFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXJldHVybiBwcm94eVRvTWFpblRocmVhZCgzLDAsMSxmZCxpb3YsaW92Y250LHBudW0pO2lvdj4+Pj0wO2lvdmNudD4+Pj0wO3BudW0+Pj49MDt2YXIgbnVtPTA7Zm9yKHZhciBpPTA7aTxpb3ZjbnQ7aSsrKXt2YXIgcHRyPShncm93TWVtVmlld3MoKSxIRUFQVTMyKVtpb3Y+Pj4yPj4+MF07dmFyIGxlbj0oZ3Jvd01lbVZpZXdzKCksSEVBUFUzMilbaW92KzQ+Pj4yPj4+MF07aW92Kz04O2Zvcih2YXIgaj0wO2o8bGVuO2orKyl7cHJpbnRDaGFyKGZkLChncm93TWVtVmlld3MoKSxIRUFQVTgpW3B0citqPj4+MF0pfW51bSs9bGVufShncm93TWVtVmlld3MoKSxIRUFQVTMyKVtwbnVtPj4+Mj4+PjBdPW51bTtyZXR1cm4gMH1QVGhyZWFkLmluaXQoKTt7aW5pdE1lbW9yeSgpO2lmKE1vZHVsZVsibm9FeGl0UnVudGltZSJdKW5vRXhpdFJ1bnRpbWU9TW9kdWxlWyJub0V4aXRSdW50aW1lIl07aWYoTW9kdWxlWyJwcmludCJdKW91dD1Nb2R1bGVbInByaW50Il07aWYoTW9kdWxlWyJwcmludEVyciJdKWVycj1Nb2R1bGVbInByaW50RXJyIl07aWYoTW9kdWxlWyJ3YXNtQmluYXJ5Il0pd2FzbUJpbmFyeT1Nb2R1bGVbIndhc21CaW5hcnkiXTtpZihNb2R1bGVbImFyZ3VtZW50cyJdKWFyZ3VtZW50c189TW9kdWxlWyJhcmd1bWVudHMiXTtpZihNb2R1bGVbInRoaXNQcm9ncmFtIl0pdGhpc1Byb2dyYW09TW9kdWxlWyJ0aGlzUHJvZ3JhbSJdO2lmKE1vZHVsZVsicHJlSW5pdCJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVJbml0Il09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVJbml0Il09W01vZHVsZVsicHJlSW5pdCJdXTt3aGlsZShNb2R1bGVbInByZUluaXQiXS5sZW5ndGg+MCl7TW9kdWxlWyJwcmVJbml0Il0uc2hpZnQoKSgpfX19TW9kdWxlWyJ3YXNtTWVtb3J5Il09d2FzbU1lbW9yeTt2YXIgcHJveGllZEZ1bmN0aW9uVGFibGU9W19wcm9jX2V4aXQsZXhpdE9uTWFpblRocmVhZCxwdGhyZWFkQ3JlYXRlUHJveGllZCxfZmRfd3JpdGVdO3ZhciBfc2thaW5ldF9mcDMyX21hdG11bCxfc2thaW5ldF9mcDMyX21hdG11bF93dCxfc2thaW5ldF9iZjE2X21hdG11bCxfc2thaW5ldF9mcDE2X21hdG11bCxfc2thaW5ldF9xNF8wX21hdG11bCxfc2thaW5ldF9xNF8wX21hdG11bF9ybSxfc2thaW5ldF9xNV8wX21hdG11bCxfbWFsbG9jLF9mcmVlLF9za2FpbmV0X3E1XzBfbWF0bXVsX3JtLF9za2FpbmV0X3E1XzFfbWF0bXVsLF9za2FpbmV0X3E1XzFfbWF0bXVsX3JtLF9za2FpbmV0X3E4XzBfbWF0bXVsLF9za2FpbmV0X3E4XzBfbWF0bXVsX3JtLF9za2FpbmV0X3E0a19tYXRtdWwsX3NrYWluZXRfcTRrX21hdG11bF9ybSxfc2thaW5ldF9xNWtfbWF0bXVsLF9za2FpbmV0X3E1a19tYXRtdWxfcm0sX3NrYWluZXRfcTZrX21hdG11bCxfc2thaW5ldF9xNmtfbWF0bXVsX3JtLF9za2FpbmV0X3Rlcm5hcnlfZjMyX2dlbXYsX3NrYWluZXRfdGVybmFyeV9sbWhlYWRfc3RhZ2UxLF9za2FpbmV0X2JpdG5ldF9nZW12X3RxMl8wLF9za2FpbmV0X2YzMl9iaW5hcnksX3NrYWluZXRfZjMyX3VuYXJ5LF9za2FpbmV0X2YzMl9yZWR1Y2VfYWxsLF9za2FpbmV0X2YzMl9yZWR1Y2VfYXhpcyxfX2Vtc2NyaXB0ZW5fdGxzX2luaXQsX3B0aHJlYWRfc2VsZixfX2Vtc2NyaXB0ZW5fdGhyZWFkX2luaXQsX19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkLF9fZW1zY3JpcHRlbl9ydW5fanNfb25fbWFpbl90aHJlYWQsX19lbXNjcmlwdGVuX3RocmVhZF9mcmVlX2RhdGEsX19lbXNjcmlwdGVuX3RocmVhZF9leGl0LF9fZW1zY3JpcHRlbl9jaGVja19tYWlsYm94LF9lbXNjcmlwdGVuX3N0YWNrX3NldF9saW1pdHMsX19lbXNjcmlwdGVuX3N0YWNrX3Jlc3RvcmUsX19lbXNjcmlwdGVuX3N0YWNrX2FsbG9jLF9lbXNjcmlwdGVuX3N0YWNrX2dldF9jdXJyZW50O2Z1bmN0aW9uIGFzc2lnbldhc21FeHBvcnRzKHdhc21FeHBvcnRzKXtNb2R1bGVbIl9za2FpbmV0X2ZwMzJfbWF0bXVsIl09X3NrYWluZXRfZnAzMl9tYXRtdWw9d2FzbUV4cG9ydHNbInAiXTtNb2R1bGVbIl9za2FpbmV0X2ZwMzJfbWF0bXVsX3d0Il09X3NrYWluZXRfZnAzMl9tYXRtdWxfd3Q9d2FzbUV4cG9ydHNbInIiXTtNb2R1bGVbIl9za2FpbmV0X2JmMTZfbWF0bXVsIl09X3NrYWluZXRfYmYxNl9tYXRtdWw9d2FzbUV4cG9ydHNbInMiXTtNb2R1bGVbIl9za2FpbmV0X2ZwMTZfbWF0bXVsIl09X3NrYWluZXRfZnAxNl9tYXRtdWw9d2FzbUV4cG9ydHNbInQiXTtNb2R1bGVbIl9za2FpbmV0X3E0XzBfbWF0bXVsIl09X3NrYWluZXRfcTRfMF9tYXRtdWw9d2FzbUV4cG9ydHNbInUiXTtNb2R1bGVbIl9za2FpbmV0X3E0XzBfbWF0bXVsX3JtIl09X3NrYWluZXRfcTRfMF9tYXRtdWxfcm09d2FzbUV4cG9ydHNbInYiXTtNb2R1bGVbIl9za2FpbmV0X3E1XzBfbWF0bXVsIl09X3NrYWluZXRfcTVfMF9tYXRtdWw9d2FzbUV4cG9ydHNbInciXTtNb2R1bGVbIl9tYWxsb2MiXT1fbWFsbG9jPXdhc21FeHBvcnRzWyJ4Il07TW9kdWxlWyJfZnJlZSJdPV9mcmVlPXdhc21FeHBvcnRzWyJ5Il07TW9kdWxlWyJfc2thaW5ldF9xNV8wX21hdG11bF9ybSJdPV9za2FpbmV0X3E1XzBfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJ6Il07TW9kdWxlWyJfc2thaW5ldF9xNV8xX21hdG11bCJdPV9za2FpbmV0X3E1XzFfbWF0bXVsPXdhc21FeHBvcnRzWyJBIl07TW9kdWxlWyJfc2thaW5ldF9xNV8xX21hdG11bF9ybSJdPV9za2FpbmV0X3E1XzFfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJCIl07TW9kdWxlWyJfc2thaW5ldF9xOF8wX21hdG11bCJdPV9za2FpbmV0X3E4XzBfbWF0bXVsPXdhc21FeHBvcnRzWyJDIl07TW9kdWxlWyJfc2thaW5ldF9xOF8wX21hdG11bF9ybSJdPV9za2FpbmV0X3E4XzBfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJEIl07TW9kdWxlWyJfc2thaW5ldF9xNGtfbWF0bXVsIl09X3NrYWluZXRfcTRrX21hdG11bD13YXNtRXhwb3J0c1siRSJdO01vZHVsZVsiX3NrYWluZXRfcTRrX21hdG11bF9ybSJdPV9za2FpbmV0X3E0a19tYXRtdWxfcm09d2FzbUV4cG9ydHNbIkYiXTtNb2R1bGVbIl9za2FpbmV0X3E1a19tYXRtdWwiXT1fc2thaW5ldF9xNWtfbWF0bXVsPXdhc21FeHBvcnRzWyJHIl07TW9kdWxlWyJfc2thaW5ldF9xNWtfbWF0bXVsX3JtIl09X3NrYWluZXRfcTVrX21hdG11bF9ybT13YXNtRXhwb3J0c1siSCJdO01vZHVsZVsiX3NrYWluZXRfcTZrX21hdG11bCJdPV9za2FpbmV0X3E2a19tYXRtdWw9d2FzbUV4cG9ydHNbIkkiXTtNb2R1bGVbIl9za2FpbmV0X3E2a19tYXRtdWxfcm0iXT1fc2thaW5ldF9xNmtfbWF0bXVsX3JtPXdhc21FeHBvcnRzWyJKIl07TW9kdWxlWyJfc2thaW5ldF90ZXJuYXJ5X2YzMl9nZW12Il09X3NrYWluZXRfdGVybmFyeV9mMzJfZ2Vtdj13YXNtRXhwb3J0c1siSyJdO01vZHVsZVsiX3NrYWluZXRfdGVybmFyeV9sbWhlYWRfc3RhZ2UxIl09X3NrYWluZXRfdGVybmFyeV9sbWhlYWRfc3RhZ2UxPXdhc21FeHBvcnRzWyJMIl07TW9kdWxlWyJfc2thaW5ldF9iaXRuZXRfZ2Vtdl90cTJfMCJdPV9za2FpbmV0X2JpdG5ldF9nZW12X3RxMl8wPXdhc21FeHBvcnRzWyJNIl07TW9kdWxlWyJfc2thaW5ldF9mMzJfYmluYXJ5Il09X3NrYWluZXRfZjMyX2JpbmFyeT13YXNtRXhwb3J0c1siTiJdO01vZHVsZVsiX3NrYWluZXRfZjMyX3VuYXJ5Il09X3NrYWluZXRfZjMyX3VuYXJ5PXdhc21FeHBvcnRzWyJPIl07TW9kdWxlWyJfc2thaW5ldF9mMzJfcmVkdWNlX2FsbCJdPV9za2FpbmV0X2YzMl9yZWR1Y2VfYWxsPXdhc21FeHBvcnRzWyJQIl07TW9kdWxlWyJfc2thaW5ldF9mMzJfcmVkdWNlX2F4aXMiXT1fc2thaW5ldF9mMzJfcmVkdWNlX2F4aXM9d2FzbUV4cG9ydHNbIlEiXTtfX2Vtc2NyaXB0ZW5fdGxzX2luaXQ9d2FzbUV4cG9ydHNbIlIiXTtfcHRocmVhZF9zZWxmPXdhc21FeHBvcnRzWyJTIl07X19lbXNjcmlwdGVuX3RocmVhZF9pbml0PXdhc21FeHBvcnRzWyJUIl07X19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkPXdhc21FeHBvcnRzWyJVIl07X19lbXNjcmlwdGVuX3J1bl9qc19vbl9tYWluX3RocmVhZD13YXNtRXhwb3J0c1siViJdO19fZW1zY3JpcHRlbl90aHJlYWRfZnJlZV9kYXRhPXdhc21FeHBvcnRzWyJXIl07X19lbXNjcmlwdGVuX3RocmVhZF9leGl0PXdhc21FeHBvcnRzWyJYIl07X19lbXNjcmlwdGVuX2NoZWNrX21haWxib3g9d2FzbUV4cG9ydHNbIlkiXTtfZW1zY3JpcHRlbl9zdGFja19zZXRfbGltaXRzPXdhc21FeHBvcnRzWyJaIl07X19lbXNjcmlwdGVuX3N0YWNrX3Jlc3RvcmU9d2FzbUV4cG9ydHNbIl8iXTtfX2Vtc2NyaXB0ZW5fc3RhY2tfYWxsb2M9d2FzbUV4cG9ydHNbIiQiXTtfZW1zY3JpcHRlbl9zdGFja19nZXRfY3VycmVudD13YXNtRXhwb3J0c1siYWEiXX12YXIgd2FzbUltcG9ydHM7ZnVuY3Rpb24gYXNzaWduV2FzbUltcG9ydHMoKXt3YXNtSW1wb3J0cz17ZzpfX19wdGhyZWFkX2NyZWF0ZV9qcyxrOl9fZW1zY3JpcHRlbl9pbml0X21haW5fdGhyZWFkX2pzLG46X19lbXNjcmlwdGVuX25vdGlmeV9tYWlsYm94X3Bvc3RtZXNzYWdlLGw6X19lbXNjcmlwdGVuX3JlY2VpdmVfb25fbWFpbl90aHJlYWRfanMsYzpfX2Vtc2NyaXB0ZW5fdGhyZWFkX2NsZWFudXAsajpfX2Vtc2NyaXB0ZW5fdGhyZWFkX21haWxib3hfYXdhaXQsaTpfX2Vtc2NyaXB0ZW5fdGhyZWFkX3NldF9zdHJvbmdyZWYsZTpfZW1zY3JpcHRlbl9jaGVja19ibG9ja2luZ19hbGxvd2VkLGg6X2Vtc2NyaXB0ZW5fZXhpdF93aXRoX2xpdmVfcnVudGltZSxiOl9lbXNjcmlwdGVuX2dldF9ub3csbTpfZW1zY3JpcHRlbl9yZXNpemVfaGVhcCxmOl9leGl0LGQ6X2ZkX3dyaXRlLGE6d2FzbU1lbW9yeX19ZnVuY3Rpb24gYXBwbHlTaWduYXR1cmVDb252ZXJzaW9ucyh3YXNtRXhwb3J0cyl7d2FzbUV4cG9ydHM9T2JqZWN0LmFzc2lnbih7fSx3YXNtRXhwb3J0cyk7dmFyIG1ha2VXcmFwcGVyX3BwPWY9PmEwPT5mKGEwKT4+PjA7dmFyIG1ha2VXcmFwcGVyX3A9Zj0+KCk9PmYoKT4+PjA7d2FzbUV4cG9ydHNbIngiXT1tYWtlV3JhcHBlcl9wcCh3YXNtRXhwb3J0c1sieCJdKTt3YXNtRXhwb3J0c1siUyJdPW1ha2VXcmFwcGVyX3Aod2FzbUV4cG9ydHNbIlMiXSk7d2FzbUV4cG9ydHNbIiQiXT1tYWtlV3JhcHBlcl9wcCh3YXNtRXhwb3J0c1siJCJdKTt3YXNtRXhwb3J0c1siYWEiXT1tYWtlV3JhcHBlcl9wKHdhc21FeHBvcnRzWyJhYSJdKTtyZXR1cm4gd2FzbUV4cG9ydHN9ZnVuY3Rpb24gcnVuKCl7aWYocnVuRGVwZW5kZW5jaWVzPjApe2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1ydW47cmV0dXJufWlmKEVOVklST05NRU5UX0lTX1BUSFJFQUQpe3JlYWR5UHJvbWlzZVJlc29sdmU/LihNb2R1bGUpO2luaXRSdW50aW1lKCk7cmV0dXJufXByZVJ1bigpO2lmKHJ1bkRlcGVuZGVuY2llcz4wKXtkZXBlbmRlbmNpZXNGdWxmaWxsZWQ9cnVuO3JldHVybn1mdW5jdGlvbiBkb1J1bigpe01vZHVsZVsiY2FsbGVkUnVuIl09dHJ1ZTtpZihBQk9SVClyZXR1cm47aW5pdFJ1bnRpbWUoKTtyZWFkeVByb21pc2VSZXNvbHZlPy4oTW9kdWxlKTtNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0/LigpO3Bvc3RSdW4oKX1pZihNb2R1bGVbInNldFN0YXR1cyJdKXtNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7c2V0VGltZW91dCgoKT0+e3NldFRpbWVvdXQoKCk9Pk1vZHVsZVsic2V0U3RhdHVzIl0oIiIpLDEpO2RvUnVuKCl9LDEpfWVsc2V7ZG9SdW4oKX19dmFyIHdhc21FeHBvcnRzO2lmKCFFTlZJUk9OTUVOVF9JU19QVEhSRUFEKXt3YXNtRXhwb3J0cz1hd2FpdCAoY3JlYXRlV2FzbSgpKTtydW4oKX1pZihydW50aW1lSW5pdGlhbGl6ZWQpe21vZHVsZVJ0bj1Nb2R1bGV9ZWxzZXttb2R1bGVSdG49bmV3IFByb21pc2UoKHJlc29sdmUscmVqZWN0KT0+e3JlYWR5UHJvbWlzZVJlc29sdmU9cmVzb2x2ZTtyZWFkeVByb21pc2VSZWplY3Q9cmVqZWN0fSl9CjtyZXR1cm4gbW9kdWxlUnRufWV4cG9ydCBkZWZhdWx0IGNyZWF0ZVNrYWluZXRLZXJuZWxzO3ZhciBpc1B0aHJlYWQ9Z2xvYmFsVGhpcy5zZWxmPy5uYW1lPy5zdGFydHNXaXRoKCJlbS1wdGhyZWFkIik7dmFyIGlzTm9kZT10eXBlb2YgcHJvY2Vzcz09Im9iamVjdCImJnByb2Nlc3MudmVyc2lvbnM/Lm5vZGUmJnByb2Nlc3MudHlwZSE9InJlbmRlcmVyIjtpZihpc05vZGUpaXNQdGhyZWFkPShhd2FpdCBpbXBvcnQoIndvcmtlcl90aHJlYWRzIikpLndvcmtlckRhdGE9PT0iZW0tcHRocmVhZCI7aXNQdGhyZWFkJiZjcmVhdGVTa2FpbmV0S2VybmVscygpOwo=" + const val MT_WASM: String = "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AgBBwD9BwD82AgBBjMAAQYzAADYCAEGgwABBqD82AgBB2D9BKjYCAEGIwABB8MAANgIAQcw/QcA/NgIAQcg/QcA/NgIAQcA/EAlB9D8jCDYCAEH4PyMIIwdrNgIAQcA/EEFBwD8QCAsLkjQEAcQKAACAvwAAgL8AAIC/AACAvwAAAAAAAIC/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AAAAQAAAgL8AAIC/AACAvwAAgL8AAAAAAACAvwAAgL8AAAAAAAAAAAAAgL8AAIC/AACAPwAAAAAAAIC/AACAvwAAAEAAAAAAAACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AAAAAAAAgD8AAIC/AACAvwAAgD8AAIA/AACAvwAAgL8AAABAAACAPwAAgL8AAIC/AACAvwAAAEAAAIC/AACAvwAAAAAAAABAAACAvwAAgL8AAIA/AAAAQAAAgL8AAIC/AAAAQAAAAEAAAIC/AACAvwAAgL8AAIC/AAAAAAAAgL8AAAAAAACAvwAAAAAAAIC/AACAPwAAgL8AAAAAAACAvwAAAEAAAIC/AAAAAAAAgL8AAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgL8AAABAAAAAAAAAAAAAAIC/AACAvwAAgD8AAAAAAACAvwAAAAAAAIA/AAAAAAAAgL8AAIA/AACAPwAAAAAAAIC/AAAAQAAAgD8AAAAAAACAvwAAgL8AAABAAAAAAAAAgL8AAAAAAAAAQAAAAAAAAIC/AACAPwAAAEAAAAAAAACAvwAAAEAAAABAAAAAAAAAgL8AAIC/AACAvwAAgD8AAIC/AAAAAAAAgL8AAIA/AACAvwAAgD8AAIC/AACAPwAAgL8AAABAAACAvwAAgD8AAIC/AACAvwAAAAAAAIA/AACAvwAAAAAAAAAAAACAPwAAgL8AAIA/AAAAAAAAgD8AAIC/AAAAQAAAAAAAAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAAAAAACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAvwAAAEAAAIA/AACAPwAAgL8AAIC/AAAAQAAAgD8AAIC/AAAAAAAAAEAAAIA/AACAvwAAgD8AAABAAACAPwAAgL8AAABAAAAAQAAAgD8AAIC/AACAvwAAgL8AAABAAACAvwAAAAAAAIC/AAAAQAAAgL8AAIA/AACAvwAAAEAAAIC/AAAAQAAAgL8AAABAAACAvwAAgL8AAAAAAAAAQAAAgL8AAAAAAAAAAAAAAEAAAIC/AACAPwAAAAAAAABAAACAvwAAAEAAAAAAAAAAQAAAgL8AAIC/AACAPwAAAEAAAIC/AAAAAAAAgD8AAABAAACAvwAAgD8AAIA/AAAAQAAAgL8AAABAAACAPwAAAEAAAIC/AACAvwAAAEAAAABAAACAvwAAAAAAAABAAAAAQAAAgL8AAIA/AAAAQAAAAEAAAIC/AAAAQAAAAEAAAABAAACAvwAAgL8AAIC/AACAvwAAAAAAAAAAAACAvwAAgL8AAAAAAACAPwAAgL8AAIC/AAAAAAAAAEAAAIC/AACAvwAAAAAAAIC/AAAAAAAAgL8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAAAAAACAvwAAAAAAAABAAAAAAAAAgL8AAAAAAACAvwAAgD8AAIC/AAAAAAAAAAAAAIA/AACAvwAAAAAAAIA/AACAPwAAgL8AAAAAAAAAQAAAgD8AAIC/AAAAAAAAgL8AAABAAACAvwAAAAAAAAAAAAAAQAAAgL8AAAAAAACAPwAAAEAAAIC/AAAAAAAAAEAAAABAAACAvwAAAAAAAIC/AACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAIC/AAAAAAAAAAAAAABAAACAvwAAAAAAAAAAAACAvwHWKIA/AAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAgL8AAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAAEAAAIA/AAAAAAAAAAAAAIC/AAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAACAvwAAgL8AAIA/AAAAAAAAAAAAAIC/AACAPwAAAAAAAIA/AACAvwAAgD8AAAAAAAAAQAAAgL8AAIA/AAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAEAAAAAAAACAPwAAAAAAAIC/AACAPwAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAABAAACAPwAAgD8AAAAAAACAvwAAAEAAAIA/AAAAAAAAAAAAAABAAACAPwAAAAAAAIA/AAAAQAAAgD8AAAAAAAAAQAAAAEAAAIA/AAAAAAAAgL8AAIC/AAAAQAAAAAAAAAAAAACAvwAAAEAAAAAAAACAPwAAgL8AAABAAAAAAAAAAEAAAIC/AAAAQAAAAAAAAIC/AAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAgD8AAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAACAvwAAgD8AAABAAAAAAAAAAAAAAIA/AAAAQAAAAAAAAIA/AACAPwAAAEAAAAAAAAAAQAAAgD8AAABAAAAAAAAAgL8AAABAAAAAQAAAAAAAAAAAAAAAQAAAAEAAAAAAAACAPwAAAEAAAABAAAAAAAAAAEAAAABAAAAAQAAAAAAAAIC/AACAvwAAgL8AAIA/AAAAAAAAgL8AAIC/AACAPwAAgD8AAIC/AACAvwAAgD8AAABAAACAvwAAgL8AAIA/AACAvwAAAAAAAIC/AACAPwAAAAAAAAAAAACAvwAAgD8AAIA/AAAAAAAAgL8AAIA/AAAAQAAAAAAAAIC/AACAPwAAgL8AAIA/AACAvwAAgD8AAAAAAACAPwAAgL8AAIA/AACAPwAAgD8AAIC/AACAPwAAAEAAAIA/AACAvwAAgD8AAIC/AAAAQAAAgL8AAIA/AAAAAAAAAEAAAIC/AACAPwAAgD8AAABAAACAvwAAgD8AAABAAAAAQAAAgL8AAIA/AACAvwAAgL8AAAAAAACAPwAAAAAAAIC/AAAAAAAAgD8AAIA/AACAvwAAAAAAAIA/AAAAQAAAgL8AAAAAAACAPwAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAEAAAAAAAAAAAAAAgD8AAIC/AACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAgD8AAABAAACAPwAAAAAAAIA/AACAvwAAAEAAAAAAAACAPwAAAAAAAABAAAAAAAAAgD8AAIA/AAAAQAAAAAAAAIA/AAAAQAAAAEAAAAAAAACAPwAAgL8AAIC/AACAPwAAgD8AAAAAAACAvwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAAEAAAIC/AACAPwAAgD8AAIC/AAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/AACAPwAAgD8AAAAAAACAPwAAgD8AAABAAAAAAAAAgD8AAIA/AACAvwAAgD8AAIA/AACAPwAAAAAAAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AAAAQAAAgD8AAIA/AACAPwAAgL8AAABAAACAPwAAgD8AAAAAAAAAQAAAgD8AAIA/AACAPwAAAEAAAIA/AACAPwAAAEAAAABAAACAPwAAgD8AAIC/AACAvwAAAEAAAIA/AAAAAAAAgL8AAABAAACAPwAAgD8AAIC/AAAAQAAAgD8AAABAAACAvwAAAEAAAIA/AACAvwAAAAAAAABAAACAPwAAAAAAAAAAAAAAQAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAQAAAAAAAAABAAACAPwAAgL8AAIA/AAAAQAAAgD8AAAAAAACAPwAAAEAAAIA/AACAPwAAgD8AAABAAACAPwAAAEAAAIA/AAAAQAAAgD8AAIC/AAAAQAAAAEAAAIA/AAAAAAAAAEAAAABAAACAPwAAgD8AAABAAAAAQAAAgD8AAABAAAAAQAAAAEAAAIA/AACAvwAAgL8AAIC/AAAAQAAAAAAAAIC/AACAvwAAAEAAAIA/AACAvwAAgL8AAABAAAAAQAAAgL8AAIC/AAAAQAAAgL8AAAAAAACAvwAAAEAAAAAAAAAAAAAAgL8AAABAAACAPwAAAAAAAIC/AAAAQAAAAEAAAAAAAACAvwAAAEAAAIC/AACAPwAAgL8AAABAAAAAAAAAgD8AAIC/AAAAQAAAgD8AAIA/AACAvwAAAEAAAABAAACAPwAAgL8AAABAAACAvwAAAEAAAIC/AAAAQAAAAAAAAABAAACAvwAAAEAAAIA/AAAAQAAAgL8AAABAAAAAQAAAAEAAAIC/AAAAQAAAgL8AAIC/AAAAAAAAAEAAAAAAAACAvwAAAAAAAABAAACAPwAAgL8AAAAAAAAAQAAAAEAAAIC/AAAAAAAAAEAAAIC/AAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAgD8AAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAABAAACAvwAAgD8AAAAAAAAAQAAAAAAAAIA/AAAAAAAAAEAAAIA/AACAPwAAAAAAAABAAAAAQAAAgD8AAAAA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" } diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmCpuOps.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmCpuOps.kt index eb1df89f..cf7ac877 100644 --- a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmCpuOps.kt +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmCpuOps.kt @@ -2,20 +2,43 @@ package sk.ainet.exec.wasm import sk.ainet.context.schedule.Schedule import sk.ainet.exec.tensor.ops.DefaultCpuOpsBase +import sk.ainet.lang.memory.Scope +import sk.ainet.lang.memory.ScopeKind import sk.ainet.lang.tensor.Shape import sk.ainet.lang.tensor.Tensor import sk.ainet.lang.tensor.data.FloatArrayTensorData +import sk.ainet.lang.tensor.data.StorageFloatTensorData import sk.ainet.lang.tensor.data.TensorData import sk.ainet.lang.tensor.data.TensorDataFactory import sk.ainet.lang.tensor.ops.TensorOps +import sk.ainet.lang.tensor.storage.MemoryDomain import sk.ainet.lang.types.DType import sk.ainet.lang.types.FP32 +import kotlin.reflect.KClass /** - * The browser tier's `TensorOps` (SKEEP-007 §T1): [DefaultCpuOpsBase] with the dense FP32 matmuls - * (`x · Wᵀ` and `A · B`) routed through the SIMD128 sidecar. Packed weights need no override — they reach the pack through - * `KernelDispatch` like on every other tier. Everything else is the common scalar implementation, - * and so is everything here while the sidecar is not ready. + * The browser tier's `TensorOps` (SKEEP-007 §T1 and the resident-activation step): [DefaultCpuOpsBase] + * with the dense matmuls, the elementwise arithmetic, the activations and the reductions routed + * through the SIMD128 sidecar, and their outputs kept **resident** in the sidecar's linear memory + * ([WasmLinearTensorData]) so a chain of them never copies an activation back to the Kotlin heap + * between kernels. Packed weights need no override — they reach the pack through `KernelDispatch` + * like on every other tier. Everything else is the common scalar implementation, which reads a + * resident tensor through its heap mirror (one bulk download, the first time), and so is + * everything here while the sidecar is not ready. + * + * What goes to the sidecar, and when: + * + * - `matmul`, `matmulWeightTransposed` (dense FP32): always; the output is resident. + * - `add`/`subtract`/`multiply`/`divide`: when at least one operand is already resident. Two heap + * operands stay on the common path — uploading both costs more than the scalar loop saves, and + * a chain starts resident at its first matmul anyway. + * - `sigmoid`/`silu`/`gelu`/`erf`/`tanh`: always — the transcendental loop is several times the + * upload. `relu`, `sum`, `mean`: when the operand is resident. + * + * An output is resident only while [WasmSimd.residentBudgetBytes] allows; above it the kernel still + * runs in the sidecar and the result is read back to the heap. Scoped contexts (`ForwardScope`) + * allocate the resident output from the scope, so `reset()` frees the sidecar bytes; ambient outputs + * are freed when their tensor is collected (see [WasmLinearStorage]). */ public class WasmCpuOps( dataFactory: TensorDataFactory, @@ -28,65 +51,280 @@ public class WasmCpuOps( /** The sidecar computes `x · Wᵀ` from the weight's rows itself; no Kotlin-side row-dot and no transposed copy. */ override fun preferDirectWeightTransposed(): Boolean = false + // ── operands and outputs ────────────────────────────────────────────────────────────────────── + + /** A sidecar address for an operand: a resident tensor's own, or a staged copy freed after the call. */ + private class Operand(val ptr: Int, val temp: Boolean) + + private fun isResident(t: Tensor<*, *>): Boolean = (t.data as? WasmLinearTensorData<*>)?.isResident == true + + /** Dense FP32 the sidecar can take: resident, a heap array, or a slab window. */ + private fun isSidecarFloat(t: Tensor<*, *>): Boolean = + t.dtype == FP32::class && (t.data is WasmLinearTensorData<*> || t.data is FloatArrayTensorData<*> || t.data is StorageFloatTensorData<*>) + + private fun operand(t: Tensor<*, *>): Operand? = when (val d = t.data) { + is WasmLinearTensorData<*> -> if (d.isResident) Operand(d.pointer(), false) else null + is FloatArrayTensorData<*> -> stage(d.buffer, 0, t.shape.volume) + is StorageFloatTensorData<*> -> { + val s = d.storage + s.checkAlive() + stage(s.floats!!, s.arrayOffset, t.shape.volume) + } + else -> null + } + + private fun stage(src: FloatArray, offset: Int, count: Int): Operand { + val ptr = WasmKernels.alloc(maxOf(count, 1) * 4) + if (count > 0) WasmKernels.writeFloats(ptr, src, offset, count) + return Operand(ptr, true) + } + + private fun release(o: Operand?) { + if (o != null && o.temp) WasmKernels.free(o.ptr) + } + + /** A resident output allocation from the active scope (ambient: GC-managed), or `null` when the scope cannot place it in the sidecar. */ + private fun residentStorage(bytes: Long): WasmLinearStorage? { + val scope = dispatchScope() + return if (scope === Scope.Ambient) WasmLinearStorage.allocate(bytes, ScopeKind.AMBIENT, zero = false) + else scope.allocate(bytes, MemoryDomain.HOST_OFFHEAP) as? WasmLinearStorage + } + /** - * Dense `A(m,k) · B(k,n)` on heap FP32 operands runs the sidecar GEMM. The common implementation - * serves this shape with its own `[k, n]` loop before it consults the registry, so without this - * override the SIMD128 kernel was reachable only through `KernelDispatch` (batched or view - * operands) and a plain 2-D matmul stayed at scalar speed. Both operands are staged per call: - * `B` here is not necessarily a parameter (attention scores, projections of activations), so - * nothing is kept resident. A packed weight is not `FloatArrayTensorData` and keeps its path. + * Run [fill] into an output buffer of [shape]: resident when the budget allows, otherwise a + * temporary that is read back to the heap and adopted through the factory. */ @Suppress("UNCHECKED_CAST") + private inline fun output( + shape: Shape, + dtype: KClass, + inputs: Array>, + fill: (outPtr: Int) -> Unit, + ): Tensor { + val n = shape.volume + val bytes = n.toLong() * 4 + if (WasmSimd.residentBudgetBytes - WasmKernels.residentActivationBytes() >= bytes) { + residentStorage(bytes)?.let { storage -> + fill(storage.pointer()) + return newTensor(WasmLinearTensorData(shape, storage) as TensorData, dtype, *inputs) + } + } + val tmp = WasmKernels.alloc(maxOf(n, 1) * 4) + try { + fill(tmp) + val out = FloatArray(n) + if (n > 0) WasmKernels.readFloats(tmp, out, 0, n) + return floatResult(shape, dtype, out, *inputs) + } finally { + WasmKernels.free(tmp) + } + } + + /** + * A resident copy of a dense FP32 [tensor] — the explicit "upload once" for an input that many + * sidecar ops will read (a bench's operands, a prompt's embeddings), so none of them stages it + * per call. The tensor itself if it is already resident; the common data unchanged when the + * sidecar is not ready or the budget is spent. + */ + public fun toResident(tensor: Tensor): Tensor { + if (!WasmKernels.isReady || !isSidecarFloat(tensor) || isResident(tensor)) return tensor + val n = tensor.shape.volume + val o = operand(tensor) ?: return tensor + try { + val src = o.ptr + val bytes = n.toLong() * 4 + if (WasmSimd.residentBudgetBytes - WasmKernels.residentActivationBytes() < bytes) return tensor + val storage = residentStorage(bytes) ?: return tensor + WasmKernels.copy(src, storage.pointer(), n * 4) + @Suppress("UNCHECKED_CAST") + return newTensor(WasmLinearTensorData(tensor.shape, storage) as TensorData, tensor.dtype, tensor) + } finally { + release(o) + } + } + + // ── matmuls ─────────────────────────────────────────────────────────────────────────────────── + + /** + * Dense `A(m,k) · B(k,n)` on FP32 operands runs the sidecar GEMM. The common implementation + * serves this shape with its own `[k, n]` loop before it consults the registry, so without this + * override the SIMD128 kernel was reachable only through `KernelDispatch`. Resident operands are + * read in place; heap operands are staged per call (`B` is not necessarily a parameter). A packed + * weight is not dense FP32 data and keeps its path. + */ override fun matmul(a: Tensor, b: Tensor): Tensor { - if (WasmKernels.isReady && a.rank == 2 && b.rank == 2 && a.dtype == FP32::class && b.dtype == FP32::class) { - val ad = a.data as? FloatArrayTensorData<*> - val bd = b.data as? FloatArrayTensorData<*> - if (ad != null && bd != null && untransposedWeight(b) == null) { - val m = a.shape[0] - val k = a.shape[1] - val n = b.shape[1] - require(k == b.shape[0]) { "Matrix multiplication shape mismatch: ${a.shape} vs ${b.shape}" } - val out = FloatArray(m * n) - if (m > 0 && n > 0) WasmFp32MatmulKernel.matmul(ad.buffer, 0, k, bd.buffer, 0, n, out, 0, n, m, n, k) - val outData = dataFactory.adoptFloatArray(Shape(m, n), a.dtype, out) as TensorData - return newTensor(outData, a.dtype, a, b) + if (WasmKernels.isReady && a.rank == 2 && b.rank == 2 && isSidecarFloat(a) && isSidecarFloat(b) && untransposedWeight(b) == null) { + val m = a.shape[0] + val k = a.shape[1] + val n = b.shape[1] + require(k == b.shape[0]) { "Matrix multiplication shape mismatch: ${a.shape} vs ${b.shape}" } + if (m > 0 && n > 0) { + var ao: Operand? = null + var bo: Operand? = null + try { + ao = operand(a) ?: return super.matmul(a, b) + bo = operand(b) ?: return super.matmul(a, b) + val aPtr = ao.ptr + val bPtr = bo.ptr + return output(Shape(m, n), a.dtype, arrayOf(a, b)) { out -> WasmKernels.fp32Matmul(aPtr, k, bPtr, n, out, n, m, n, k) } + } finally { + release(bo) + release(ao) + } } } return super.matmul(a, b) } - @Suppress("UNCHECKED_CAST") override fun matmulWeightTransposed(x: Tensor, weight: Tensor): Tensor { - if (WasmKernels.isReady && weight.shape.rank == 2 && x.rank >= 1 && x.dtype == FP32::class && weight.dtype == FP32::class) { - val w = weight.data as? FloatArrayTensorData<*> - val a = x.data as? FloatArrayTensorData<*> - if (w != null && a != null) { - val n = weight.shape[0] - val k = weight.shape[1] - if (x.shape.dimensions.last() == k) { - val m = if (k == 0) 0 else x.shape.volume / k - val out = FloatArray(m * n) - if (m > 0 && n > 0) { - val inPtr = WasmKernels.alloc(m * k * 4) - val outPtr = WasmKernels.alloc(m * n * 4) - try { - WasmKernels.writeFloats(inPtr, a.buffer, 0, m * k) - // Resident like a packed weight: a parameter is immutable once loaded, and - // re-uploading it per call made single-token decode run at copy speed. - val wPtr = WasmKernels.denseWeightHandle(w.buffer) - WasmKernels.fp32MatmulWt(inPtr, wPtr, outPtr, m, n, k) - WasmKernels.readFloats(outPtr, out, 0, m * n) - } finally { - WasmKernels.free(outPtr) - WasmKernels.free(inPtr) + if (WasmKernels.isReady && weight.shape.rank == 2 && x.rank >= 1 && isSidecarFloat(x) && isSidecarFloat(weight)) { + val n = weight.shape[0] + val k = weight.shape[1] + if (x.shape.dimensions.last() == k) { + val m = if (k == 0) 0 else x.shape.volume / k + if (m > 0 && n > 0) { + var xo: Operand? = null + var wo: Operand? = null + try { + xo = operand(x) ?: return super.matmulWeightTransposed(x, weight) + // A heap weight is a parameter: resident after its first call (re-uploading it + // per call made single-token decode run at copy speed). Resident and slab + // weights are read where they are. + wo = when (val wd = weight.data) { + is FloatArrayTensorData<*> -> Operand(WasmKernels.denseWeightHandle(wd.buffer), false) + else -> operand(weight) ?: return super.matmulWeightTransposed(x, weight) } + val xPtr = xo.ptr + val wPtr = wo.ptr + val outShape = if (x.rank == 1) Shape(n) else Shape(*(x.shape.dimensions.copyOf(x.rank - 1) + n)) + return output(outShape, x.dtype, arrayOf(x, weight)) { out -> WasmKernels.fp32MatmulWt(xPtr, wPtr, out, m, n, k) } + } finally { + release(wo) + release(xo) } - val outShape = if (x.rank == 1) Shape(n) else Shape(*(x.shape.dimensions.copyOf(x.rank - 1) + n)) - val outData = dataFactory.adoptFloatArray(outShape, x.dtype, out) as TensorData - return newTensor(outData, x.dtype, x, weight) } } } return super.matmulWeightTransposed(x, weight) } + + // ── elementwise ─────────────────────────────────────────────────────────────────────────────── + + /** The operand's index mode against the broadcast output shape, or `null` for a broadcast the kernel does not take. */ + private fun mode(s: Shape, out: Shape): Int? = when { + s == out -> WasmKernels.F32_FULL + s.volume == 1 -> WasmKernels.F32_SCALAR + s.rank >= 1 && out.rank >= 1 && s[s.rank - 1] == out[out.rank - 1] && s.dimensions.dropLast(1).all { it == 1 } -> WasmKernels.F32_BIAS + else -> null + } + + private fun binary(op: Int, a: Tensor, b: Tensor): Tensor? { + if (!WasmKernels.isReady || a.dtype != b.dtype || !isSidecarFloat(a) || !isSidecarFloat(b)) return null + if (!isResident(a) && !isResident(b)) return null + val outShape = try { + broadcastShapes(a.shape, b.shape) + } catch (e: IllegalArgumentException) { + return null + } + val n = outShape.volume + if (n == 0) return null + val aMode = mode(a.shape, outShape) ?: return null + val bMode = mode(b.shape, outShape) ?: return null + val inner = outShape[outShape.rank - 1] + var ao: Operand? = null + var bo: Operand? = null + try { + ao = operand(a) ?: return null + bo = operand(b) ?: return null + val aPtr = ao.ptr + val bPtr = bo.ptr + return output(outShape, a.dtype, arrayOf(a, b)) { out -> WasmKernels.f32Binary(op, aPtr, aMode, bPtr, bMode, out, n, inner) } + } finally { + release(bo) + release(ao) + } + } + + override fun add(a: Tensor, b: Tensor): Tensor = + binary(WasmKernels.F32_ADD, a, b) ?: super.add(a, b) + + override fun subtract(a: Tensor, b: Tensor): Tensor = + binary(WasmKernels.F32_SUB, a, b) ?: super.subtract(a, b) + + override fun multiply(a: Tensor, b: Tensor): Tensor = + binary(WasmKernels.F32_MUL, a, b) ?: super.multiply(a, b) + + override fun divide(a: Tensor, b: Tensor): Tensor = + binary(WasmKernels.F32_DIV, a, b) ?: super.divide(a, b) + + // ── activations ─────────────────────────────────────────────────────────────────────────────── + + private fun unary(op: Int, t: Tensor, heapToo: Boolean): Tensor? { + if (!WasmKernels.isReady || !isSidecarFloat(t)) return null + if (!heapToo && !isResident(t)) return null + val n = t.shape.volume + if (n == 0) return null + val o = operand(t) ?: return null + try { + val inPtr = o.ptr + return output(t.shape, t.dtype, arrayOf(t)) { out -> WasmKernels.f32Unary(op, inPtr, out, n) } + } finally { + release(o) + } + } + + override fun relu(tensor: Tensor): Tensor = + unary(WasmKernels.F32_RELU, tensor, heapToo = false) ?: super.relu(tensor) + + override fun sigmoid(tensor: Tensor): Tensor = + unary(WasmKernels.F32_SIGMOID, tensor, heapToo = true) ?: super.sigmoid(tensor) + + override fun silu(tensor: Tensor): Tensor = + unary(WasmKernels.F32_SILU, tensor, heapToo = true) ?: super.silu(tensor) + + override fun gelu(tensor: Tensor, approximate: Boolean): Tensor = + unary(if (approximate) WasmKernels.F32_GELU_TANH else WasmKernels.F32_GELU_EXACT, tensor, heapToo = true) + ?: super.gelu(tensor, approximate) + + override fun erf(tensor: Tensor): Tensor = + unary(WasmKernels.F32_ERF, tensor, heapToo = true) ?: super.erf(tensor) + + override fun tanh(tensor: Tensor): Tensor = + unary(WasmKernels.F32_TANH, tensor, heapToo = true) ?: super.tanh(tensor) + + // ── reductions ──────────────────────────────────────────────────────────────────────────────── + + private fun reduce(t: Tensor, dim: Int?, mean: Boolean): Tensor? { + if (!WasmKernels.isReady || !isSidecarFloat(t) || !isResident(t)) return null + val rank = t.rank + val volume = t.shape.volume + if (volume == 0) return null + val o = operand(t) ?: return null + try { + val inPtr = o.ptr + if (dim == null) { + return output(Shape(), t.dtype, arrayOf(t)) { out -> WasmKernels.f32ReduceAll(inPtr, volume, mean, out) } + } + val nd = if (dim < 0) dim + rank else dim + if (nd !in 0 until rank) return null + val dims = t.shape.dimensions + var outer = 1 + for (i in 0 until nd) outer *= dims[i] + val red = dims[nd] + var inner = 1 + for (i in nd + 1 until rank) inner *= dims[i] + val outDims = IntArray(rank - 1) + var oi = 0 + for (i in 0 until rank) { if (i == nd) continue; outDims[oi++] = dims[i] } + return output(Shape(outDims), t.dtype, arrayOf(t)) { out -> WasmKernels.f32ReduceAxis(inPtr, outer, red, inner, mean, out) } + } finally { + release(o) + } + } + + override fun sum(tensor: Tensor, dim: Int?): Tensor = + reduce(tensor, dim, mean = false) ?: super.sum(tensor, dim) + + override fun mean(tensor: Tensor, dim: Int?): Tensor = + reduce(tensor, dim, mean = true) ?: super.mean(tensor, dim) } diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernelProvider.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernelProvider.kt index 77848742..5ee5e209 100644 --- a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernelProvider.kt +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernelProvider.kt @@ -3,6 +3,7 @@ package sk.ainet.exec.wasm import sk.ainet.backend.api.kernel.Bf16MatmulKernel import sk.ainet.backend.api.kernel.Fp16MatmulKernel import sk.ainet.backend.api.kernel.Fp32MatmulKernel +import sk.ainet.backend.api.kernel.Fp32MatmulWtKernel import sk.ainet.backend.api.kernel.KernelProvider import sk.ainet.backend.api.kernel.Q4KMatmulKernel import sk.ainet.backend.api.kernel.Q4_0MatmulKernel @@ -23,6 +24,7 @@ public object WasmKernelProvider : KernelProvider { override fun isAvailable(): Boolean = WasmKernels.isReady override fun matmulFp32(): Fp32MatmulKernel = WasmFp32MatmulKernel + override fun matmulFp32Wt(): Fp32MatmulWtKernel = WasmFp32MatmulWtKernel override fun matmulBf16(): Bf16MatmulKernel = WasmBf16MatmulKernel override fun matmulFp16(): Fp16MatmulKernel = WasmFp16MatmulKernel @@ -165,3 +167,36 @@ public object WasmFp32MatmulKernel : Fp32MatmulKernel { } } } + +/** + * `out(m,n) = x(m,k) · w(n,k)ᵀ` in the sidecar (`skainet_fp32_matmul_wt`). A whole-array weight is a + * parameter and stays resident after its first call ([WasmKernels.denseWeightHandle]); a windowed + * weight is staged per call, as the activation always is. + */ +public object WasmFp32MatmulWtKernel : Fp32MatmulWtKernel { + override fun matmulWt( + x: FloatArray, xOffset: Int, + w: FloatArray, wOffset: Int, + out: FloatArray, outOffset: Int, + m: Int, n: Int, k: Int, + ) { + require(m >= 0 && n >= 0 && k >= 0) { "m, n, k must be non-negative; got m=$m n=$n k=$k" } + if (m == 0 || n == 0) return + val resident = wOffset == 0 && w.size == n * k + val inPtr = WasmKernels.alloc(maxOf(m * k, 1) * 4) + val wPtr = if (resident) WasmKernels.denseWeightHandle(w) else WasmKernels.alloc(maxOf(n * k, 1) * 4) + val outPtr = WasmKernels.alloc(m * n * 4) + try { + if (k > 0) { + WasmKernels.writeFloats(inPtr, x, xOffset, m * k) + if (!resident) WasmKernels.writeFloats(wPtr, w, wOffset, n * k) + } + WasmKernels.fp32MatmulWt(inPtr, wPtr, outPtr, m, n, k) + WasmKernels.readFloats(outPtr, out, outOffset, m * n) + } finally { + WasmKernels.free(outPtr) + if (!resident) WasmKernels.free(wPtr) + WasmKernels.free(inPtr) + } + } +} diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernels.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernels.kt index 19b00a64..5359884b 100644 --- a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernels.kt +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmKernels.kt @@ -51,6 +51,7 @@ public object WasmKernels { loadEmbeddedSidecar(mjs, wasm).await() } modeName = if (mt) "simd128-mt" else "simd128-st" + jsResidentState(mod()) } /** Drop the sidecar and every cached weight; the next [initialize] starts over. Tests only. */ @@ -138,6 +139,70 @@ public object WasmKernels { } } + /** Copy [count] bytes from sidecar memory at [srcPtr] into [dst]. */ + public fun readBytes(srcPtr: Int, dst: ByteArray, dstOffset: Int, count: Int) { + val m = mod() + var done = 0 + while (done < count) { + val n = minOf(count - done, CHUNK_BYTES) + withScopedMemoryAllocator { allocator -> + val base = allocator.allocate(n) + jsCopyOut(m, wasmMemory, srcPtr + done, base.address.toInt(), n) + var p: Pointer = base + var i = 0 + while (i + 4 <= n) { + val v = p.loadInt() + val o = dstOffset + done + i + dst[o] = (v and 0xFF).toByte() + dst[o + 1] = ((v ushr 8) and 0xFF).toByte() + dst[o + 2] = ((v ushr 16) and 0xFF).toByte() + dst[o + 3] = ((v ushr 24) and 0xFF).toByte() + p = p + 4 + i += 4 + } + while (i < n) { + dst[dstOffset + done + i] = p.loadByte() + p = p + 1 + i++ + } + } + done += n + } + } + + /** Copy [bytes] bytes inside sidecar memory from [srcPtr] to [dstPtr]. */ + public fun copy(srcPtr: Int, dstPtr: Int, bytes: Int) { + if (bytes > 0) jsCopyWithin(mod(), srcPtr, dstPtr, bytes) + } + + /** Zero [bytes] bytes of sidecar memory at [ptr]. */ + public fun zero(ptr: Int, bytes: Int) { + if (bytes > 0) jsZero(mod(), ptr, bytes) + } + + // ── resident activations (Storage.WasmLinear) ───────────────────────────────────────────────── + + /** + * Sidecar bytes currently held by resident activations ([WasmLinearStorage]), scoped and + * ambient — the figure [WasmSimd.residentBudgetBytes] is checked against. + */ + public fun residentActivationBytes(): Long = if (isReady) jsResidentBytes(mod()).toLong() else 0L + + /** Allocate [bytes] for a resident activation; counted in [residentActivationBytes]. */ + internal fun allocResident(bytes: Int): Int = jsResidentAlloc(mod(), bytes) + + /** Free a resident activation's bytes and stop counting them. */ + internal fun freeResident(ptr: Int, bytes: Int): Unit = jsResidentFree(mod(), ptr, bytes) + + /** + * Register an ambient (GC-managed) resident allocation with the sidecar's `FinalizationRegistry`: + * the returned token is held by the Kotlin storage object, and when that object is collected the + * registry frees the sidecar bytes. Explicit `close()` must [untrackResident] first. + */ + internal fun trackResident(ptr: Int, bytes: Int): JsAny = jsResidentTrack(mod(), ptr, bytes) + + internal fun untrackResident(token: JsAny): Unit = jsResidentUntrack(mod(), token) + // ── resident weights ────────────────────────────────────────────────────────────────────────── private class Resident(val ptr: Int, val bytes: Int) @@ -213,6 +278,59 @@ public object WasmKernels { public fun narrowFloatMatmul(fnName: String, aPtr: Int, aStride: Int, bPtr: Int, bByteStride: Int, cPtr: Int, cStride: Int, m: Int, n: Int, k: Int): Unit = jsNarrowFloatMatmul(mod(), fnName, aPtr, aStride, bPtr, bByteStride, cPtr, cStride, m, n, k) + /** + * `skainet_ternary_f32_gemv`: one FP32 activation row against a sequentially packed BitNet b1.58 + * weight (`inputDim / 4` bytes per output row), per-tensor scale not applied. + */ + public fun ternaryF32Gemv(inPtr: Int, weightPtr: Int, inputDim: Int, outputDim: Int, outPtr: Int): Unit = + jsTernaryF32Gemv(mod(), inPtr, weightPtr, inputDim, outputDim, outPtr) + + /** + * `skainet_ternary_lmhead_stage1`: four planes at [planesPtr] (each [planeStrideBytes] apart) with + * the fused weights `{1, ⅓, ⅑, 1/27}`, times the FP16 row scales at [rowScalePtr]. + */ + public fun ternaryLmheadStage1(inPtr: Int, planesPtr: Int, planeStrideBytes: Int, rowScalePtr: Int, inputDim: Int, outputDim: Int, outPtr: Int): Unit = + jsTernaryLmheadStage1(mod(), inPtr, planesPtr, planeStrideBytes, rowScalePtr, inputDim, outputDim, outPtr) + + /** `skainet_bitnet_gemv_tq2_0`: int8 activation codes with one absmax scale against TQ2_0 blocks. */ + public fun bitnetGemvTq2_0(activationPtr: Int, activationScale: Float, weightPtr: Int, inputDim: Int, outputDim: Int, outPtr: Int): Unit = + jsBitnetGemvTq2_0(mod(), activationPtr, activationScale, weightPtr, inputDim, outputDim, outPtr) + + /** Operand index modes of [f32Binary] (`skainet_f32_binary`). */ + public const val F32_FULL: Int = 0 + public const val F32_SCALAR: Int = 1 + public const val F32_BIAS: Int = 2 + + /** Operators of [f32Binary]. */ + public const val F32_ADD: Int = 0 + public const val F32_SUB: Int = 1 + public const val F32_MUL: Int = 2 + public const val F32_DIV: Int = 3 + + /** Functions of [f32Unary] (`skainet_f32_unary`). */ + public const val F32_RELU: Int = 0 + public const val F32_SIGMOID: Int = 1 + public const val F32_SILU: Int = 2 + public const val F32_GELU_TANH: Int = 3 + public const val F32_GELU_EXACT: Int = 4 + public const val F32_ERF: Int = 5 + public const val F32_TANH: Int = 6 + + /** `skainet_f32_binary`: `out[i] = a[ia] op b[ib]` over [n] outputs, each side indexed by its mode (full, scalar, last-dim bias of [inner]). */ + public fun f32Binary(op: Int, aPtr: Int, aMode: Int, bPtr: Int, bMode: Int, outPtr: Int, n: Int, inner: Int): Unit = + jsF32Binary(mod(), op, aPtr, aMode, bPtr, bMode, outPtr, n, inner) + + /** `skainet_f32_unary`: `out[i] = f(in[i])`. */ + public fun f32Unary(op: Int, inPtr: Int, outPtr: Int, n: Int): Unit = jsF32Unary(mod(), op, inPtr, outPtr, n) + + /** `skainet_f32_reduce_all`: the sum (or mean) of [n] floats into the single float at [outPtr]. */ + public fun f32ReduceAll(inPtr: Int, n: Int, mean: Boolean, outPtr: Int): Unit = + jsF32ReduceAll(mod(), inPtr, n, if (mean) 1 else 0, outPtr) + + /** `skainet_f32_reduce_axis`: sum (or mean) over the middle of an `(outer, red, inner)` decomposition. */ + public fun f32ReduceAxis(inPtr: Int, outer: Int, red: Int, inner: Int, mean: Boolean, outPtr: Int): Unit = + jsF32ReduceAxis(mod(), inPtr, outer, red, inner, if (mean) 1 else 0, outPtr) + // ── diagnostics ─────────────────────────────────────────────────────────────────────────────── /** @@ -227,10 +345,11 @@ public object WasmKernels { val crossOriginIsolated: Boolean, val hardwareConcurrency: Int, val residentWeightBytes: Long, + val residentActivationBytes: Long = 0L, ) { override fun toString(): String = "mode=$mode simd128=$simd128 threads=$threads crossOriginIsolated=$crossOriginIsolated " + - "cores=$hardwareConcurrency residentWeightBytes=$residentWeightBytes" + "cores=$hardwareConcurrency residentWeightBytes=$residentWeightBytes residentActivationBytes=$residentActivationBytes" } /** Current sidecar capabilities; `mode == "none"` before [initialize]. */ @@ -241,6 +360,7 @@ public object WasmKernels { crossOriginIsolated = jsCrossOriginIsolated(), hardwareConcurrency = jsHardwareConcurrency(), residentWeightBytes = if (isReady) residentWeightBytes() else 0L, + residentActivationBytes = residentActivationBytes(), ) } @@ -301,6 +421,94 @@ private fun jsFp32MatmulWt(mod: JsAny, inPtr: Int, wPtr: Int, outPtr: Int, m: In private fun jsNarrowFloatMatmul(mod: JsAny, fnName: String, aPtr: Int, aStride: Int, bPtr: Int, bByteStride: Int, cPtr: Int, cStride: Int, m: Int, n: Int, k: Int): Unit = js("mod[fnName](aPtr, 0, aStride, bPtr, 0, bByteStride, cPtr, 0, cStride, m, n, k)") +private fun jsTernaryF32Gemv(mod: JsAny, inPtr: Int, weightPtr: Int, inputDim: Int, outputDim: Int, outPtr: Int): Unit = + js("mod._skainet_ternary_f32_gemv(inPtr, 0, weightPtr, 0, inputDim, outputDim, outPtr, 0)") + +private fun jsTernaryLmheadStage1(mod: JsAny, inPtr: Int, planesPtr: Int, planeStrideBytes: Int, rowScalePtr: Int, inputDim: Int, outputDim: Int, outPtr: Int): Unit = + js("mod._skainet_ternary_lmhead_stage1(inPtr, 0, planesPtr, 0, planeStrideBytes, rowScalePtr, 0, inputDim, outputDim, outPtr, 0)") + +private fun jsBitnetGemvTq2_0(mod: JsAny, activationPtr: Int, activationScale: Float, weightPtr: Int, inputDim: Int, outputDim: Int, outPtr: Int): Unit = + js("mod._skainet_bitnet_gemv_tq2_0(activationPtr, 0, activationScale, weightPtr, 0, inputDim, outputDim, outPtr, 0)") + +private fun jsCopyWithin(mod: JsAny, srcPtr: Int, dstPtr: Int, bytes: Int): Unit = + js("new Uint8Array(mod.wasmMemory.buffer).copyWithin(dstPtr, srcPtr, srcPtr + bytes)") + +private fun jsZero(mod: JsAny, ptr: Int, bytes: Int): Unit = + js("new Uint8Array(mod.wasmMemory.buffer, ptr, bytes).fill(0)") + +// Resident-activation accounting lives on the module object: the byte count and, where the runtime +// has one, a FinalizationRegistry that frees an ambient allocation when its Kotlin storage object has +// been collected (Kotlin/Wasm objects are traced by the same GC as the token they hold). +private fun jsResidentState(mod: JsAny): JsAny = js( + """ + (function() { + if (!mod.__skainetResident) { + var st = { bytes: 0, registry: null }; + if (typeof FinalizationRegistry !== 'undefined') { + st.registry = new FinalizationRegistry(function (h) { mod._free(h.ptr); st.bytes -= h.bytes; }); + } + mod.__skainetResident = st; + } + return mod.__skainetResident; + })() + """, +) + +private fun jsResidentBytes(mod: JsAny): Double = js("(mod.__skainetResident ? mod.__skainetResident.bytes : 0)") + +private fun jsResidentAlloc(mod: JsAny, bytes: Int): Int = js( + """ + (function() { + var st = mod.__skainetResident; + var p = mod._malloc(bytes); + st.bytes += bytes; + return p; + })() + """, +) + +private fun jsResidentFree(mod: JsAny, ptr: Int, bytes: Int): Unit = js( + """ + (function() { + var st = mod.__skainetResident; + mod._free(ptr); + st.bytes -= bytes; + })() + """, +) + +private fun jsResidentTrack(mod: JsAny, ptr: Int, bytes: Int): JsAny = js( + """ + (function() { + var st = mod.__skainetResident; + var token = {}; + if (st.registry) st.registry.register(token, { ptr: ptr, bytes: bytes }, token); + return token; + })() + """, +) + +private fun jsResidentUntrack(mod: JsAny, token: JsAny): Unit = js( + """ + (function() { + var st = mod.__skainetResident; + if (st && st.registry) st.registry.unregister(token); + })() + """, +) + +private fun jsF32Binary(mod: JsAny, op: Int, aPtr: Int, aMode: Int, bPtr: Int, bMode: Int, outPtr: Int, n: Int, inner: Int): Unit = + js("mod._skainet_f32_binary(op, aPtr, aMode, bPtr, bMode, outPtr, n, inner)") + +private fun jsF32Unary(mod: JsAny, op: Int, inPtr: Int, outPtr: Int, n: Int): Unit = + js("mod._skainet_f32_unary(op, inPtr, outPtr, n)") + +private fun jsF32ReduceAll(mod: JsAny, inPtr: Int, n: Int, mean: Int, outPtr: Int): Unit = + js("mod._skainet_f32_reduce_all(inPtr, n, mean, outPtr)") + +private fun jsF32ReduceAxis(mod: JsAny, inPtr: Int, outer: Int, red: Int, inner: Int, mean: Int, outPtr: Int): Unit = + js("mod._skainet_f32_reduce_axis(inPtr, outer, red, inner, mean, outPtr)") + private fun jsCrossOriginIsolated(): Boolean = js("typeof crossOriginIsolated !== 'undefined' && crossOriginIsolated === true") private fun jsHardwareConcurrency(): Int = js( diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmLinearStorage.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmLinearStorage.kt new file mode 100644 index 00000000..64810975 --- /dev/null +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmLinearStorage.kt @@ -0,0 +1,191 @@ +@file:OptIn(kotlin.js.ExperimentalWasmJsInterop::class) + +package sk.ainet.exec.wasm + +import sk.ainet.lang.memory.OffHeapAllocator +import sk.ainet.lang.memory.Owner +import sk.ainet.lang.memory.ScopeKind +import sk.ainet.lang.memory.Storage +import sk.ainet.lang.memory.StorageId +import sk.ainet.lang.memory.trace.NoopTraceSink +import sk.ainet.lang.memory.trace.TraceEvent +import sk.ainet.lang.memory.trace.TraceSink +import sk.ainet.lang.tensor.Shape +import sk.ainet.lang.tensor.TensorId +import sk.ainet.lang.tensor.data.FloatArrayTensorData +import sk.ainet.lang.types.DType + +/** + * The wasm tier's [Storage.OffHeap]: a region of the SIMD128 sidecar's linear memory + * (SKEEP-007 resident activations). Bytes here are read and written by the sidecar's kernels in + * place; the Kotlin side sees them through [copyInto]/[copyFrom] (bulk copies across the module + * boundary), never element by element. This is the binding `PlatformStorage.offHeapAllocator` + * receives from [WasmSimd.install], so a `ForwardScope` or `ModelScope` asking for + * `MemoryDomain.HOST_OFFHEAP` gets sidecar memory that its `reset()`/`close()` frees. + * + * Lifetime. A scoped storage ([ScopeKind.FORWARD] / [ScopeKind.MODEL]) is freed exactly once, by its + * scope through [close]. An ambient storage ([ScopeKind.AMBIENT], the default for op outputs in a + * notebook-style forward pass) has no scope to free it, so it is registered with a + * `FinalizationRegistry` in the sidecar glue: when this Kotlin object is collected the registry + * frees the sidecar bytes — the same GC-managed lifetime a heap `FloatArray` has, one hop later. + * Finalization is not prompt, which is why the ops layer also keeps resident activations under + * [WasmSimd.residentBudgetBytes] and falls back to heap outputs above it. + */ +public class WasmLinearStorage private constructor( + override val id: StorageId, + private val base: Int, + override val sizeBytes: Long, + override val owner: Owner, + override val debugOrigin: TensorId?, + override val sink: TraceSink, + private val token: JsAny?, + private val mutable: Boolean, +) : Storage.OffHeap() { + + override val isMutable: Boolean get() = (owner as? Owner.Alias)?.parent?.isMutable ?: mutable + + /** The byte address in sidecar memory — kernels take it once per call. Throws when closed. */ + public fun pointer(): Int { + checkAlive() + return base + } + + override fun slice(offsetBytes: Long, lengthBytes: Long): WasmLinearStorage { + checkAlive() + require(offsetBytes >= 0 && lengthBytes >= 0 && offsetBytes + lengthBytes <= sizeBytes) { + "slice [$offsetBytes, ${offsetBytes + lengthBytes}) outside $sizeBytes bytes" + } + return WasmLinearStorage(StorageId.next(), base + offsetBytes.toInt(), lengthBytes, Owner.Alias(this), debugOrigin, sink, null, mutable) + } + + override fun copyInto(dest: ByteArray, destOffset: Int, offset: Long, length: Int) { + checkAlive() + require(offset >= 0 && length >= 0 && offset + length <= sizeBytes) { "copyInto [$offset, ${offset + length}) outside $sizeBytes bytes" } + WasmKernels.readBytes(base + offset.toInt(), dest, destOffset, length) + } + + override fun copyFrom(src: ByteArray, srcOffset: Int, offset: Long, length: Int) { + checkAlive() + require(isMutable) { "storage $id is not mutable" } + require(offset >= 0 && length >= 0 && offset + length <= sizeBytes) { "copyFrom [$offset, ${offset + length}) outside $sizeBytes bytes" } + WasmKernels.writeBytes(base + offset.toInt(), src, srcOffset, length) + } + + override fun onClose() { + if (owner !is Owner.Owned || !WasmKernels.isReady) return + token?.let { WasmKernels.untrackResident(it) } + WasmKernels.freeResident(base, sizeBytes.toInt()) + } + + override fun toString(): String = + "WasmLinear($id, $sizeBytes B @$base, $owner${debugOrigin?.let { ", $it" } ?: ""}${if (isAlive) "" else ", closed"})" + + /** The hook [WasmSimd.install] hands to `PlatformStorage.offHeapAllocator`. */ + public object Allocator : OffHeapAllocator { + override fun allocate(bytes: Long, scope: ScopeKind, origin: TensorId?, sink: TraceSink): Storage = + WasmLinearStorage.allocate(bytes, scope, origin, sink) + } + + public companion object { + /** + * Allocate [bytes] bytes of sidecar memory, zeroed unless [zero] is `false` (an op output that + * is fully written next), owned by a scope of kind [scope]. Requires the sidecar to be up. + */ + public fun allocate( + bytes: Long, + scope: ScopeKind = ScopeKind.AMBIENT, + origin: TensorId? = null, + sink: TraceSink = NoopTraceSink, + zero: Boolean = true, + ): WasmLinearStorage { + require(bytes in 0..Int.MAX_VALUE.toLong()) { "sidecar storage is limited to 2 GB per allocation, requested $bytes bytes" } + check(WasmKernels.isReady) { "WasmSimd.install() has not completed: no sidecar memory to allocate from" } + val size = bytes.toInt() + val ptr = WasmKernels.allocResident(size) + if (zero) WasmKernels.zero(ptr, size) + val token = if (scope == ScopeKind.AMBIENT) WasmKernels.trackResident(ptr, size) else null + val s = WasmLinearStorage(StorageId.next(), ptr, bytes, Owner.Owned(scope), origin, sink, token, true) + if (sink.isEnabled) sink.emit(TraceEvent.Allocation(s.id.value, scope, bytes, origin)) + return s + } + } +} + +/** + * Dense FP32 tensor data whose bytes live in the sidecar ([WasmLinearStorage]) — what the ops of + * [WasmCpuOps] hand out, so a chain `matmul → gelu → multiply → add` never copies an activation back + * to the Kotlin heap between kernels. + * + * It is a [FloatArrayTensorData] so every common fast path keeps working on it: the first access to + * [buffer] (or to an element, or [copyToFloatArray], or [view]) downloads the whole tensor once into + * a heap mirror that is kept for the tensor's life. A sidecar kernel never triggers that — it reads + * [pointer] — and the download is the same single bulk copy the matmul output paid before resident + * activations existed. Ops do not mutate their inputs, so the mirror and the sidecar copy agree; + * [set] writes both. + */ +public class WasmLinearTensorData( + initialShape: Shape, + public val storage: WasmLinearStorage, +) : FloatArrayTensorData { + + override val shape: Shape = Shape(initialShape.dimensions.copyOf()) + private val strides: IntArray = IntArray(shape.rank).also { st -> + var stride = 1 + for (i in shape.rank - 1 downTo 0) { + st[i] = stride + stride *= shape.dimensions[i] + } + } + private var mirror: FloatArray? = null + + init { + require(storage.sizeBytes >= shape.volume.toLong() * 4) { + "storage holds ${storage.sizeBytes} bytes, shape $shape needs ${shape.volume.toLong() * 4}" + } + } + + /** `true` while the sidecar bytes are alive: kernels use [pointer] and nothing is downloaded. */ + public val isResident: Boolean get() = storage.isAlive + + /** The sidecar address of element 0. Throws when the storage is closed. */ + public fun pointer(): Int = storage.pointer() + + /** `true` once a heap mirror has been downloaded (diagnostics and tests). */ + public val isMirrored: Boolean get() = mirror != null + + override val buffer: FloatArray + get() { + storage.checkAlive() + mirror?.let { return it } + val n = shape.volume + val arr = FloatArray(n) + if (n > 0) WasmKernels.readFloats(storage.pointer(), arr, 0, n) + mirror = arr + return arr + } + + private fun flatIndex(indices: IntArray): Int { + require(indices.size == shape.dimensions.size) { + "Number of indices (${indices.size}) must match tensor dimensions (${shape.dimensions.size})" + } + var flat = 0 + for (i in indices.indices) { + val idx = indices[i] + require(idx >= 0 && idx < shape.dimensions[i]) { "Index $idx out of bounds for dimension $i with size ${shape.dimensions[i]}" } + flat += idx * strides[i] + } + return flat + } + + override fun get(vararg indices: Int): Float = buffer[flatIndex(indices)] + + override fun set(vararg indices: Int, value: Float) { + storage.checkAlive() + require(storage.isMutable) { "storage ${storage.id} is not mutable" } + val flat = flatIndex(indices) + mirror?.let { it[flat] = value } + WasmKernels.writeFloats(storage.pointer() + flat * 4, floatArrayOf(value), 0, 1) + } + + override fun copyToFloatArray(): FloatArray = buffer.copyOf() +} diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmSimd.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmSimd.kt index 6038f5af..01f7cdee 100644 --- a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmSimd.kt +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmSimd.kt @@ -3,6 +3,7 @@ package sk.ainet.exec.wasm import sk.ainet.backend.api.kernel.KernelDispatch import sk.ainet.backend.api.kernel.KernelRegistry import sk.ainet.exec.tensor.ops.WasmCpuOpsOverride +import sk.ainet.lang.memory.PlatformStorage /** * Entry point of the browser kernel pack (SKEEP-007 §T1). @@ -13,13 +14,24 @@ import sk.ainet.exec.tensor.ops.WasmCpuOpsOverride * ``` * * [install] loads the SIMD128 sidecar (pthreads build when the page is cross-origin isolated), - * registers [WasmKernelProvider] and [WasmSimdKernelPack], and makes every context built afterwards - * use [WasmCpuOps]. Without it — or before it completes — the engine runs the common scalar lane, - * so an application may start rendering before the sidecar is up and simply get faster later. + * registers [WasmKernelProvider], [WasmSimdKernelPack] and [WasmTernaryKernelPack], binds + * `MemoryDomain.HOST_OFFHEAP` to the sidecar's linear memory ([WasmLinearStorage], so activations stay + * resident between kernels) and makes every context built afterwards use [WasmCpuOps]. Without it — + * or before it completes — the engine runs the common scalar lane, so an application may start + * rendering before the sidecar is up and simply get faster later. */ public object WasmSimd { public val isInstalled: Boolean get() = WasmKernels.isReady && WasmCpuOpsOverride.factory != null + /** + * How many sidecar bytes resident activations may hold before [WasmCpuOps] returns heap outputs + * instead (the kernels still run in the sidecar; only the result is copied back). Ambient + * activations are freed when their tensors are collected, which is not prompt, so this is the + * bound on what a long notebook-style session can pin in linear memory. 768 MB by default; the + * wasm32 sidecar has 4 GB in total, shared with the resident weights. + */ + public var residentBudgetBytes: Long = 768L * 1024 * 1024 + public suspend fun install(url: String? = null, threads: Boolean? = null) { WasmKernels.initialize(url, threads) KernelRegistry.register(WasmKernelProvider) @@ -27,6 +39,8 @@ public object WasmSimd { // the auto-install on the next dispatch picks the sidecar provider and this pack's kernels. KernelDispatch.clearForTesting() WasmSimdKernelPack.install() + WasmTernaryKernelPack.install() + PlatformStorage.offHeapAllocator = WasmLinearStorage.Allocator WasmCpuOpsOverride.factory = { factory, schedule -> WasmCpuOps(factory, schedule) } // The same one-line banner the JVM factory prints, so a console shows which tier runs. println("[SKaiNET] Using SIMD128 sidecar kernels (${WasmKernels.features()})") @@ -38,6 +52,7 @@ public object WasmSimd { /** Back to the scalar lane; frees every resident weight. Tests and model switching. */ public fun uninstall() { WasmCpuOpsOverride.factory = null + PlatformStorage.offHeapAllocator = null KernelDispatch.clearForTesting() WasmKernels.clearForTesting() } diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmTernaryKernelPack.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmTernaryKernelPack.kt new file mode 100644 index 00000000..2e348c79 --- /dev/null +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsMain/kotlin/sk/ainet/exec/wasm/WasmTernaryKernelPack.kt @@ -0,0 +1,124 @@ +package sk.ainet.exec.wasm + +import sk.ainet.backend.api.kernel.BitNetGemvNative +import sk.ainet.backend.api.kernel.TernaryF32GemvNative +import sk.ainet.backend.api.kernel.TernaryF32KernelPack +import sk.ainet.backend.api.kernel.TernaryKernelPacks +import sk.ainet.backend.api.kernel.TernaryLmheadNative +import sk.ainet.backend.api.kernel.TernaryPlanesKernelPack +import sk.ainet.backend.api.kernel.ViewKernelPack + +/** + * The ternary kernels of the browser pack — the wasm sibling of the JVM `FfmTernaryKernelPackFactory` + * and the Android JNI ternary pack. Three native faces over the sidecar's exports: + * + * - [WasmTernaryF32Gemv] — `skainet_ternary_f32_gemv`, exact FP32 activations × `BITNET_B1_58`; + * - [WasmTernaryLmhead] — `skainet_ternary_lmhead_stage1`, the fused four-plane `BITNET_PLANES` lm_head; + * - [WasmBitNetGemv] — `skainet_bitnet_gemv_tq2_0`, int8 activations × `TQ2_0`. + * + * Each hands its weight to the sidecar **once** ([WasmKernels.weightHandle]) and stages the + * activation and output per call, like every other kernel in this module. Without this pack a + * BitNet weight in a browser went to the decoding reference kernel — correct, and hours per + * projection at model size. Installed by [WasmSimd.install] after the sidecar is up; there is no + * `ServiceLoader` on wasm. + */ +public object WasmTernaryKernelPack : ViewKernelPack { + override val name: String = "wasm-simd128-ternary" + + override fun install() { + if (!WasmKernels.isReady) return + TernaryF32KernelPack.install(WasmTernaryF32Gemv) + TernaryPlanesKernelPack.install(WasmTernaryLmhead) + TernaryKernelPacks.install(WasmBitNetGemv) + } +} + +/** `skainet_ternary_f32_gemv` in the sidecar: the sequential b1.58 payload, scale applied by the pack. */ +public object WasmTernaryF32Gemv : TernaryF32GemvNative { + override val name: String get() = "wasm-simd128" + + override fun gemvPacked( + activation: FloatArray, activationOffset: Int, + weight: ByteArray, weightByteOffset: Int, + inputDim: Int, outputDim: Int, + out: FloatArray, outOffset: Int, + ) { + require(inputDim % 4 == 0) { "WasmTernaryF32Gemv: inputDim must be a multiple of 4; got $inputDim" } + if (outputDim == 0) return + if (inputDim == 0) { + out.fill(0f, outOffset, outOffset + outputDim) + return + } + val weightPtr = WasmKernels.weightHandle(weight, 0, weight.size) + weightByteOffset + val inPtr = WasmKernels.alloc(inputDim * 4) + val outPtr = WasmKernels.alloc(outputDim * 4) + try { + WasmKernels.writeFloats(inPtr, activation, activationOffset, inputDim) + WasmKernels.ternaryF32Gemv(inPtr, weightPtr, inputDim, outputDim, outPtr) + WasmKernels.readFloats(outPtr, out, outOffset, outputDim) + } finally { + WasmKernels.free(outPtr) + WasmKernels.free(inPtr) + } + } +} + +/** `skainet_ternary_lmhead_stage1` in the sidecar: planes and row scales read from the resident weight. */ +public object WasmTernaryLmhead : TernaryLmheadNative { + override val name: String get() = "wasm-simd128" + + override fun lmheadStage1( + activation: FloatArray, activationOffset: Int, + weight: ByteArray, planesByteOffset: Int, + planeStrideBytes: Int, rowScaleByteOffset: Int, + inputDim: Int, outputDim: Int, + out: FloatArray, outOffset: Int, + ) { + require(inputDim % 4 == 0) { "WasmTernaryLmhead: inputDim must be a multiple of 4; got $inputDim" } + require(rowScaleByteOffset % 2 == 0) { "WasmTernaryLmhead: rowScaleByteOffset must be 2-byte aligned; got $rowScaleByteOffset" } + if (outputDim == 0) return + val weightPtr = WasmKernels.weightHandle(weight, 0, weight.size) + val inPtr = WasmKernels.alloc(maxOf(inputDim, 1) * 4) + val outPtr = WasmKernels.alloc(outputDim * 4) + try { + if (inputDim > 0) WasmKernels.writeFloats(inPtr, activation, activationOffset, inputDim) + WasmKernels.ternaryLmheadStage1( + inPtr, weightPtr + planesByteOffset, planeStrideBytes, weightPtr + rowScaleByteOffset, + inputDim, outputDim, outPtr, + ) + WasmKernels.readFloats(outPtr, out, outOffset, outputDim) + } finally { + WasmKernels.free(outPtr) + WasmKernels.free(inPtr) + } + } +} + +/** `skainet_bitnet_gemv_tq2_0` in the sidecar: one token's int8 codes against resident TQ2_0 blocks. */ +public object WasmBitNetGemv : BitNetGemvNative { + override val name: String get() = "wasm-simd128" + + override fun gemvTq2_0( + activation: ByteArray, activationOffset: Int, activationScale: Float, + weight: ByteArray, weightByteOffset: Int, + inputDim: Int, outputDim: Int, + out: FloatArray, outOffset: Int, + ) { + if (outputDim == 0) return + if (inputDim == 0) { + out.fill(0f, outOffset, outOffset + outputDim) + return + } + val weightPtr = WasmKernels.weightHandle(weight, 0, weight.size) + weightByteOffset + val actPtr = WasmKernels.alloc(inputDim) + val outPtr = WasmKernels.alloc(outputDim * 4) + try { + WasmKernels.writeBytes(actPtr, activation, activationOffset, inputDim) + WasmKernels.bitnetGemvTq2_0(actPtr, activationScale, weightPtr, inputDim, outputDim, outPtr) + WasmKernels.readFloats(outPtr, out, outOffset, outputDim) + } finally { + WasmKernels.free(outPtr) + WasmKernels.free(actPtr) + } + } +} diff --git a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsTest/kotlin/sk/ainet/exec/wasm/WasmSimdParityTest.kt b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsTest/kotlin/sk/ainet/exec/wasm/WasmSimdParityTest.kt index 31c96f6e..7f8ce470 100644 --- a/skainet-backends/skainet-backend-wasm-simd/src/wasmJsTest/kotlin/sk/ainet/exec/wasm/WasmSimdParityTest.kt +++ b/skainet-backends/skainet-backend-wasm-simd/src/wasmJsTest/kotlin/sk/ainet/exec/wasm/WasmSimdParityTest.kt @@ -1,11 +1,32 @@ package sk.ainet.exec.wasm import kotlinx.coroutines.test.runTest +import sk.ainet.backend.api.kernel.BitNetGemvKernel import sk.ainet.backend.api.kernel.KernelDispatch import sk.ainet.backend.api.kernel.KernelRegistry import sk.ainet.backend.api.kernel.KernelStrictness import sk.ainet.backend.api.kernel.NoSuchKernelException +import sk.ainet.backend.api.kernel.TernaryF32GemvKernel +import sk.ainet.backend.api.kernel.TernaryPlanesMatmulKernel import sk.ainet.context.DirectCpuExecutionContext +import sk.ainet.context.ScopedExecutionContext +import sk.ainet.lang.memory.ForwardScope +import sk.ainet.lang.memory.PlatformStorage +import sk.ainet.lang.memory.StorageClosedException +import sk.ainet.lang.memory.plan.StorageCapabilities +import sk.ainet.lang.tensor.data.DenseFloatArrayTensorData +import sk.ainet.lang.tensor.storage.MemoryDomain +import sk.ainet.lang.memory.I8Absmax +import sk.ainet.lang.memory.Scope +import sk.ainet.lang.memory.Storage +import sk.ainet.lang.memory.TensorView +import sk.ainet.lang.memory.TernaryBlockDecoder +import sk.ainet.lang.memory.TernaryCodec +import sk.ainet.lang.memory.trace.RecordingTraceSink +import sk.ainet.lang.memory.trace.TraceEvent +import sk.ainet.lang.tensor.data.BitNetB158TensorData +import sk.ainet.lang.tensor.data.BitNetPlanesTensorData +import sk.ainet.lang.tensor.storage.TensorEncoding import sk.ainet.exec.kernel.ScalarBf16MatmulKernel import sk.ainet.exec.kernel.ScalarFp16MatmulKernel import sk.ainet.exec.kernel.ScalarQ4_KMatmulKernel @@ -36,8 +57,8 @@ import kotlin.test.assertTrue /** * SKEEP-007 §T1: the SIMD128 sidecar agrees with the common scalar lane on every path it takes - * over — row-major packed matmuls (Q8_0, Q4_0, Q4_K via the pack), dense `x · Wᵀ`, and the dense - * GEMM — and the wiring makes a freshly built context use [WasmCpuOps]. + * over — row-major packed matmuls (Q8_0, Q4_0, Q4_K via the pack), dense `x · Wᵀ`, the dense GEMM + * and the three ternary kernels — and the wiring makes a freshly built context use [WasmCpuOps]. * * Runs on Node (`wasmJsNodeTest`): the sidecar is loaded from the module's own resources. Lane * sums differ from the sequential scalar accumulation in the last bits, so comparisons are @@ -70,6 +91,8 @@ class WasmSimdParityTest { WasmSimd.uninstall() } + private fun heapFloats(view: TensorView): FloatArray = checkNotNull((view.storage as Storage.Heap).floats) + @Suppress("UNCHECKED_CAST") private fun q8(ctx: DirectCpuExecutionContext, n: Int, k: Int, seed: Int): Tensor = ctx.fromData(Q8_0Quantizer.quantize(pseudo(n * k, seed, 2f), Shape(n, k)) as TensorData, FP32::class) @@ -282,5 +305,225 @@ class WasmSimdParityTest { val direct = FloatArray(m * n) WasmFp32MatmulKernel.matmul(x, 0, k, b, 0, n, direct, 0, n, m, n, k) assertClose(refMm, direct, "provider gemm") + // The direct `x · Wᵀ` provider kernel: whole-array weight (resident) and a windowed one (staged). + val provider = checkNotNull(KernelRegistry.bestAvailable()) + val wt = checkNotNull(provider.matmulFp32Wt()) + assertTrue(provider.supports("matmul_wt", listOf("Float32", "Float32"))) + val directWt = FloatArray(m * n) + wt.matmulWt(x, 0, w, 0, directWt, 0, m, n, k) + assertClose(refWt, directWt, "provider x·Wᵀ") + val window = FloatArray(1 + n * k + 3).also { w.copyInto(it, 1) } + val windowed = FloatArray(2 + m * n) + wt.matmulWt(x, 0, window, 1, windowed, 2, m, n, k) + assertClose(refWt, windowed.copyOfRange(2, 2 + m * n), "windowed x·Wᵀ") + } + + /** + * The ternary kernels reach the sidecar through the same `KernelDispatch` keys the JVM FFM and + * Android JNI packs serve, and agree with the Kotlin reference kernels. Row counts above the row + * pool's threshold (512) so the mt sidecar splits the rows over its workers. + */ + @Test + fun `ternary weights run on the sidecar and match the reference kernels`() = runTest { + WasmSimd.install() + val rng = Random(31) + + // BITNET_B1_58, exact FP32 activations, two rows so the pack's row loop runs. + run { + val k = 256; val n = 600; val rows = 2 + val values = FloatArray(n * k) { (rng.nextInt(3) - 1) * 0.5f } + val w = BitNetB158TensorData.fromFloats(Shape(n, k), values).packedView + val a = TensorView.dense(Storage.Heap.wrap(FloatArray(rows * k) { rng.nextFloat() - 0.5f }), Shape(rows, k), FP32) + val out = TensorView.dense(Storage.Heap.floats(rows * n), Shape(rows, n), FP32) + val sink = RecordingTraceSink() + KernelDispatch.matmul(a, w, out, Scope.Ambient, sink) + assertEquals("ternary_f32_gemv/wasm-simd128", sink.eventsOf().single().kernel) + val ref = TensorView.dense(Storage.Heap.floats(rows * n), Shape(rows, n), FP32) + TernaryF32GemvKernel(TernaryF32GemvKernel.keyFor()).run(listOf(a, w), ref) + assertClose(heapFloats(ref), heapFloats(out), "ternary f32 gemv", rel = 1e-4f) + } + + // BITNET_PLANES: the fused four-plane lm_head, two calls per row, against the 8-plane reference. + run { + val k = 64; val n = 520 + val values = FloatArray(n * k) { (rng.nextFloat() - 0.5f) * 2f } + val w = BitNetPlanesTensorData.fromFloats(Shape(n, k), values).packedView + val a = TensorView.dense(Storage.Heap.wrap(FloatArray(k) { rng.nextFloat() - 0.5f }), Shape(1, k), FP32) + val out = TensorView.dense(Storage.Heap.floats(n), Shape(1, n), FP32) + val sink = RecordingTraceSink() + KernelDispatch.matmul(a, w, out, Scope.Ambient, sink) + assertEquals("ternary_planes_matmul/wasm-simd128", sink.eventsOf().single().kernel) + val ref = TensorView.dense(Storage.Heap.floats(n), Shape(1, n), FP32) + TernaryPlanesMatmulKernel(TernaryPlanesMatmulKernel.keyFor()).run(listOf(a, w), ref) + assertClose(heapFloats(ref), heapFloats(out), "ternary planes lm_head", rel = 1e-4f) + } + + // TQ2_0 with int8 activations: integer block sums, so the match is exact up to the scale products. + run { + val k = 768; val n = 600 + val values = FloatArray(n * k) { (rng.nextInt(3) - 1) * 0.5f } + val w = TensorView.packed( + Storage.Heap.wrap(TernaryCodec.encode(TensorEncoding.TQ2_0, values)), Shape(n, k), + TensorEncoding.TQ2_0, TernaryBlockDecoder(TensorEncoding.TQ2_0), + ) + val a = I8Absmax.requantize( + TensorView.dense(Storage.Heap.wrap(FloatArray(k) { rng.nextFloat() - 0.5f }), Shape(1, k), FP32), Scope.Ambient, + ) + val out = TensorView.dense(Storage.Heap.floats(n), Shape(1, n), FP32) + val sink = RecordingTraceSink() + KernelDispatch.matmul(a, w, out, Scope.Ambient, sink) + assertEquals("bitnet_gemv/wasm-simd128", sink.eventsOf().single().kernel) + val ref = TensorView.dense(Storage.Heap.floats(n), Shape(1, n), FP32) + BitNetGemvKernel(BitNetGemvKernel.keyFor(w.format)).run(listOf(a, w), ref) + assertClose(heapFloats(ref), heapFloats(out), "bitnet gemv tq2_0") + } + assertTrue(WasmKernels.residentWeightBytes() > 0, "the ternary weights stay resident") + } + + /** + * Resident activations: a matmul's output stays in the sidecar, the elementwise ops, activations + * and reductions that follow read it in place and leave their result there too, and every value + * agrees with the common scalar lane. Only the final read materialises a heap mirror. + */ + @Test + fun `an activation chain stays resident in the sidecar and matches the scalar lane`() = runTest { + val scalar = DirectCpuExecutionContext() + val m = 7; val n = 40; val k = 24 + val x = pseudo(m * k, 41) + val w = pseudo(n * k, 43) + val bias = pseudo(n, 47) + val xs = scalar.fromFloatArray(Shape(m, k), FP32::class, x) + val ws = scalar.fromFloatArray(Shape(n, k), FP32::class, w) + val bs = scalar.fromFloatArray(Shape(n), FP32::class, bias) + val two = scalar.fromFloatArray(Shape(1), FP32::class, floatArrayOf(2f)) + fun chain(ctx: DirectCpuExecutionContext, x: Tensor, w: Tensor, b: Tensor, c: Tensor, probe: (String, Tensor) -> Unit): Map { + val ops = ctx.ops + val out = LinkedHashMap() + fun keep(name: String, t: Tensor) { probe(name, t); out[name] = t.data.copyToFloatArray() } + val h = ops.matmulWeightTransposed(x, w); probe("h", h) + val g = ops.gelu(h); probe("gelu", g) + val ge = ops.gelu(h, approximate = false); keep("geluExact", ge) + val s = ops.multiply(g, h); probe("mul", s) + val o = ops.add(s, b); probe("addBias", o) + keep("biasAdd", ops.add(b, s)) + keep("subScalar", ops.subtract(o, c)) + keep("scalarSub", ops.subtract(c, o)) + keep("div", ops.divide(o, ops.add(ops.relu(o), c))) + keep("relu", ops.relu(o)) + keep("sigmoid", ops.sigmoid(o)) + keep("silu", ops.silu(o)) + keep("tanh", ops.tanh(o)) + keep("erf", ops.erf(o)) + keep("sumAll", ops.sum(o)) + keep("meanAll", ops.mean(o)) + keep("sumLast", ops.sum(o, -1)) + keep("meanFirst", ops.mean(o, 0)) + keep("out", o) + return out + } + val ref = chain(scalar, xs, ws, bs, two) { _, _ -> } + + WasmSimd.install() + val fast = DirectCpuExecutionContext() + val xf = fast.fromFloatArray(Shape(m, k), FP32::class, x) + val wf = fast.fromFloatArray(Shape(n, k), FP32::class, w) + val bf = fast.fromFloatArray(Shape(n), FP32::class, bias) + val cf = fast.fromFloatArray(Shape(1), FP32::class, floatArrayOf(2f)) + val before = WasmKernels.residentActivationBytes() + val got = chain(fast, xf, wf, bf, cf) { name, t -> + val d = t.data + assertIs>(d, "$name should be resident") + assertTrue(d.isResident, "$name alive") + if (name == "h" || name == "gelu" || name == "mul" || name == "addBias") assertTrue(!d.isMirrored, "$name was not downloaded") + } + assertTrue(WasmKernels.residentActivationBytes() > before, "resident bytes grew") + for ((name, values) in ref) { + assertClose(values, checkNotNull(got[name]) { name }, name) + } + // Shapes of the reductions follow the common lane. + assertEquals(m, got.getValue("sumLast").size) + assertEquals(n, got.getValue("meanFirst").size) + assertEquals(1, got.getValue("sumAll").size) + } + + @Test + fun `heap operands keep the common path while transcendental activations and matmul outputs go resident`() = runTest { + WasmSimd.install() + val ctx = DirectCpuExecutionContext() + assertIs(ctx.ops) + val a = ctx.fromFloatArray(Shape(3, 5), FP32::class, pseudo(15, 1)) + val b = ctx.fromFloatArray(Shape(3, 5), FP32::class, pseudo(15, 2)) + // Two heap operands: no upload, the common scalar lane answers on the heap. + assertIs>(ctx.ops.add(a, b).data) + assertIs>(ctx.ops.relu(a).data) + assertIs>(ctx.ops.sum(a).data) + // A transcendental on a heap operand is worth the upload; its output is resident. + val g = ctx.ops.gelu(a) + assertIs>(g.data) + // ... and from there the chain is resident, including a heap partner. + assertIs>(ctx.ops.add(g, b).data) + assertIs>(ctx.ops.relu(g).data) + assertIs>(ctx.ops.sum(g).data) + // Explicit upload once. + val r = (ctx.ops as WasmCpuOps).toResident(a) + assertIs>(r.data) + assertClose(a.data.copyToFloatArray(), r.data.copyToFloatArray(), "toResident") + assertIs>(ctx.ops.add(r, b).data) + // A resident tensor reads like a heap one: elements, the view, and a common op that has no override. + val gd = g.data as WasmLinearTensorData<*> + val expected = DirectCpuExecutionContext().let { s -> s.ops.gelu(s.fromFloatArray(Shape(3, 5), FP32::class, pseudo(15, 1))).data.copyToFloatArray() } + assertClose(expected, g.data.copyToFloatArray(), "gelu via mirror") + assertEquals(expected[7], gd.get(1, 2)) + assertTrue(gd.isMirrored) + assertClose(expected, ctx.ops.transpose(ctx.ops.transpose(g)).data.copyToFloatArray(), "common op on a resident tensor") + } + + @Test + fun `scoped resident outputs are freed at reset and the budget falls back to the heap`() = runTest { + WasmSimd.install() + assertTrue(StorageCapabilities.current().supportsOffHeap, "the hook binds HOST_OFFHEAP while installed") + val scope = ForwardScope(slabFloats = 0) + val ctx = ScopedExecutionContext(DirectCpuExecutionContext(), scope) + val x = ctx.fromFloatArray(Shape(4, 8), FP32::class, pseudo(32, 9)) + val before = WasmKernels.residentActivationBytes() + val y = ctx.ops.gelu(x) + val yd = assertIs>(y.data) + assertEquals(sk.ainet.lang.memory.ScopeKind.FORWARD, yd.storage.scope) + assertEquals(before + 32 * 4, WasmKernels.residentActivationBytes()) + val values = y.data.copyToFloatArray() + scope.reset() + assertEquals(before, WasmKernels.residentActivationBytes(), "reset freed the sidecar bytes") + assertTrue(!yd.isResident) + assertFailsWith { y.data.copyToFloatArray() } + assertEquals(32, values.size) + + // Budget: the kernel still runs in the sidecar, the result comes back to the heap. + val saved = WasmSimd.residentBudgetBytes + try { + WasmSimd.residentBudgetBytes = 0L + val plain = DirectCpuExecutionContext() + val h = plain.fromFloatArray(Shape(4, 8), FP32::class, pseudo(32, 9)) + val z = plain.ops.gelu(h) + assertIs>(z.data) + assertClose(values, z.data.copyToFloatArray(), "budget fallback") + } finally { + WasmSimd.residentBudgetBytes = saved + } + + // The storage itself: zeroed allocation, byte round trip, slice, close. + val s = assertIs(PlatformStorage.allocate(64, MemoryDomain.HOST_OFFHEAP)) + val zeros = ByteArray(64) { 1 } + s.copyInto(zeros) + assertTrue(zeros.all { it == 0.toByte() }, "allocated zeroed") + val bytes = ByteArray(64) { it.toByte() } + s.copyFrom(bytes) + val back = ByteArray(16) + s.slice(8, 16).copyInto(back) + assertTrue(back.contentEquals(bytes.copyOfRange(8, 24)), "slice reads the sub-range") + val held = WasmKernels.residentActivationBytes() + s.close() + assertEquals(held - 64, WasmKernels.residentActivationBytes()) + WasmSimd.uninstall() + assertTrue(!StorageCapabilities.current().supportsOffHeap, "heap only once uninstalled") } } diff --git a/skainet-lang/skainet-lang-core/src/wasmJsMain/kotlin/sk/ainet/lang/memory/PlatformStorage.web.kt b/skainet-lang/skainet-lang-core/src/wasmJsMain/kotlin/sk/ainet/lang/memory/PlatformStorage.web.kt index 59d28c3d..cafa9643 100644 --- a/skainet-lang/skainet-lang-core/src/wasmJsMain/kotlin/sk/ainet/lang/memory/PlatformStorage.web.kt +++ b/skainet-lang/skainet-lang-core/src/wasmJsMain/kotlin/sk/ainet/lang/memory/PlatformStorage.web.kt @@ -5,24 +5,51 @@ import sk.ainet.lang.tensor.TensorId import sk.ainet.lang.tensor.storage.MemoryDomain /** - * JS / Wasm: linear memory only — no off-heap, no mmap (SKEEP-003 §4.8.4). Off-heap requests resolve - * to the heap (the planner records the fallback); files arrive through fetch/range requests into - * heap slabs, so [mapFile] is unsupported here. + * A binding of [MemoryDomain.HOST_OFFHEAP] for Kotlin/Wasm, installed by a backend that owns + * memory outside the Kotlin heap — the SIMD128 kernel sidecar's linear memory + * (`skainet-backend-wasm-simd`, `WasmSimd.install()`), where activations can stay resident between + * kernels instead of crossing the boundary per op. This module cannot depend on that backend, so + * the binding is a hook, exactly like the ops override in `skainet-backend-cpu`. + */ +public fun interface OffHeapAllocator { + /** Allocate [bytes] zeroed bytes off the Kotlin heap, owned by a scope of kind [scope]. */ + public fun allocate(bytes: Long, scope: ScopeKind, origin: TensorId?, sink: TraceSink): Storage +} + +/** + * JS / Wasm: the Kotlin heap, plus whatever [offHeapAllocator] a backend installs for + * [MemoryDomain.HOST_OFFHEAP] (SKEEP-003 §4.8.4, SKEEP-007). With no allocator installed off-heap + * requests resolve to the heap (the planner records the fallback); with one they go off the Kotlin + * heap into the backend's memory and [supports] says so, so the planner can place activations + * there. Files arrive through fetch/range requests into heap slabs, so [mapFile] is unsupported. */ public actual object PlatformStorage { - public actual fun supports(domain: MemoryDomain): Boolean = domain == MemoryDomain.HOST_HEAP + /** + * The off-heap binding, or `null` for the heap fallback. Set by `WasmSimd.install()`, cleared + * by its `uninstall()`; a consumer with its own off-heap memory may set it as well. + */ + public var offHeapAllocator: OffHeapAllocator? = null + + public actual fun supports(domain: MemoryDomain): Boolean = + domain == MemoryDomain.HOST_HEAP || (domain == MemoryDomain.HOST_OFFHEAP && offHeapAllocator != null) public actual val supportsMappedFiles: Boolean get() = false public actual fun allocate(bytes: Long, domain: MemoryDomain, scope: ScopeKind, origin: TensorId?, sink: TraceSink): Storage { - require(bytes in 0..Int.MAX_VALUE.toLong()) { "heap storage is limited to 2 GB per array, requested $bytes bytes" } - return when (domain) { + require(bytes >= 0) { "bytes must be >= 0" } + when (domain) { MemoryDomain.MMAP_FILE, MemoryDomain.DEVICE_LOCAL -> throw IllegalArgumentException("$domain is not allocatable on this target") - else -> Storage.Heap.bytes(bytes.toInt(), scope, origin, sink) // HOST_OFFHEAP / PINNED / UNIFIED fall back to the heap + MemoryDomain.HOST_OFFHEAP, MemoryDomain.HOST_PINNED, MemoryDomain.UNIFIED -> { + offHeapAllocator?.let { return it.allocate(bytes, scope, origin, sink) } + } + MemoryDomain.HOST_HEAP -> Unit } + require(bytes <= Int.MAX_VALUE.toLong()) { "heap storage is limited to 2 GB per array, requested $bytes bytes" } + return Storage.Heap.bytes(bytes.toInt(), scope, origin, sink) } public actual fun mapFile(path: String, fileOffset: Long, length: Long, scope: ScopeKind, origin: TensorId?, sink: TraceSink): Storage = throw UnsupportedOperationException("memory-mapped files are not available on this target (use the suspend RandomAccessSource into heap slabs)") - public val info: PlatformStorageInfo = PlatformStorageInfo("heap (fallback)", "none") + public val info: PlatformStorageInfo + get() = PlatformStorageInfo(if (offHeapAllocator != null) "backend linear memory (installed allocator)" else "heap (fallback)", "none") }