> ## Documentation Index
> Fetch the complete documentation index at: https://docs.makkii.jp/llms.txt
> Use this file to discover all available pages before exploring further.

# パッキング方式

> Stormworks の数値チャンネルの精度制約と、4 種類のパッキング方式

## Stormworks の数値チャンネルの制約

Stormworks のコンポジット数値チャンネルは、値がワイヤ上で IEEE-754 単精度浮動小数点数 (float32) として往復します。Lua の数値自体は倍精度 (float64) ですが、チャンネルを経由すると float32 の精度に丸められます。

float32 の仮数部は 24 bit ぶんの精度を持つため、`2^24` (16,777,216) 以下の整数であれば float64 → float32 → float64 と変換しても値が変わりません。Number Codec Compiler はこの性質を利用して、パッキングした状態数がこの範囲に収まるかどうかで、そのまま送るか・ビットを再解釈して送るかを切り替えています。

## 4 種類のパッキング方式

フィールドをチャンネルへ割り当てたあと、そのチャンネルに詰め込まれた状態数の組み合わせ数に応じて、次の 4 方式のいずれかが自動選択されます。

| 方式       | 適用条件 (状態数)                                                             | 送信される内容                                                                                  | UI 表示          |
| -------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------------- |
| `int24`  | `2^24` (16,777,216) 以下                                                 | 量子化した整数をそのまま `output.setNumber(ch, n)` で送信                                               | 24-bit整数       |
| `raw`    | `2,139,095,041` 以下、かつ `backend ≠ "raw32"`                              | `u2f(n)` で 32bit 整数のビットパターンを float32 として再解釈してから送信                                        | raw float32    |
| `stable` | `2,139,095,041` 超、`PURE_CAP = 4,286,578,690` 以下、かつ `backend ≠ "raw32"` | `raw` と同じビット再解釈だが、float32 の Infinity/NaN に相当するビットパターン域を避けるよう `put()`/`get()` で値をずらしてから送信 | stable float32 |
| `raw32`  | `2^24` 超、`2^32` (4,294,967,296) 以下、かつ `backend = "raw32"`              | `raw` と同じビット再解釈。Infinity/NaN を避けるずらしは行わない                                                | raw32 HW       |

float32 の `+Infinity` のビットパターンは `0x7F800000` (= 2,139,095,040) で、`raw` の上限 `2,139,095,041` はその 1 つ先の値です。2,139,095,040 未満の整数であれば、ビット再解釈しても常に有限かつ NaN でない float32 になります。`stable` 方式はこの上限を超えても、Infinity/NaN のビットパターン域 (合計で約 839 万状態ぶん) を避けて残りの空間を使うことで、送信中の値が Infinity/NaN にならないようにしています。

`backend` を `"raw32"` にすると、この Infinity/NaN 回避を行わない代わりに `2^32` までのフル範囲を 1 チャンネルで使えます。`backend` の切り替えは UI 上の操作としては用意されておらず、プロジェクト JSON を直接編集するか、HTTP API 経由で指定する必要があります。

<Warning>
  生成コードに含まれる `u2f`/`f2u`/`put`/`get` ヘルパー関数と、その内部の定数 (`2139095040`、`4194303`、`4286578688` など) は、この Infinity/NaN 回避のために必要な値です。手動で変更すると送受信の値がずれます。
</Warning>

## フィールドをチャンネルへ割り当てる 2 つの戦略

候補となるチャンネル数 `k` ごとに、次の 2 つの戦略を両方試し、生成される Lua コードの合計文字数が小さい方を採用します。

1. **フィールド単位のグループ化**: 各フィールドをまるごと `k` 個のチャンネルのいずれかに割り当てます。同じチャンネルに割り当てられたフィールドは、それぞれの状態数を基数とした多基数 (mixed-radix) の掛け算で 1 つの整数にまとめられ、受信側で逆順に `%`/`//` で取り出されます。フィールド数が 10 以下なら全探索、それを超えると貪欲法で探索します。
2. **多基数リム分割**: `backend` が `"pure"` で、かつすべてのフィールドの状態数が `raw32` の上限未満に収まる場合にのみ試されます。パケット全体の状態数 (全フィールドの状態数の積) を 1 つの巨大な整数とみなし、固定の基数 (`PURE_CAP = 4,286,578,690`) で `k` 個の `stable` 方式チャンネルに均等に分割します。この積は float64 の安全な整数範囲 (`2^53`) を超えることがあるため、ネイティブの Lua 演算ではなく、桁ごとに計算する手製の乗除算ヘルパーで処理されます。

どちらの戦略でも有効なパッキングが見つからない `k` は、候補一覧に表示されません。


## Related topics

- [フィールドの定義](/codec-compiler/guides/fields.md)
- [FAQ・トラブルシューティング](/codec-compiler/faq.md)
- [生成コードの組み込み](/codec-compiler/guides/lua-integration.md)
- [プロジェクト JSON スキーマ](/codec-compiler/reference/json-schema.md)
- [AI アシスタント連携](/codec-compiler/guides/ai-export.md)
