# 通知設計書 26-GMP/MPFRビット不一致エラー

## 概要

本ドキュメントは、JuliaのGMPモジュール初期化時に、動的にリンクされたGMPライブラリのバージョンまたはビット幅がコンパイル時の値と一致しない場合に出力されるエラー/警告通知の設計を記述する。

### 本通知の処理概要

本通知は、`GMP.__init__` 関数内で、ランタイムにロードされたGMPライブラリのメジャーバージョンまたは `__gmp_bits_per_limb` の値がコンパイル時に記録された値と一致しないことを検出した場合に出力される。

**業務上の目的・背景**：Juliaは任意精度整数（`BigInt`）の実装にGMP（GNU Multiple Precision Arithmetic Library）を使用する。GMPの `mp_limb_t` 型のビット幅（32ビットまたは64ビット）はコンパイル時に決定され、この値に基づいてJulia側のデータ構造（`Limb` 型）が定義される。ランタイムに異なるビット幅のGMPライブラリがロードされると、メモリレイアウトの不一致によりデータ破損やクラッシュが発生する。このため、初期化時にバージョンチェックを行い、不一致を検出した場合は適切な警告/エラーを出力する。

**通知の送信タイミング**：`GMP.__init__` 関数の実行時（Juliaプロセスの初期化段階）。

**通知の受信者**：Juliaユーザーおよびシステム管理者。

**通知内容の概要**：動的ロードされたGMPのバージョンとビット幅、コンパイル時のバージョンとビット幅を表示し、Juliaの再ビルドを推奨する。

**期待されるアクション**：ユーザーはJuliaを再ビルドするか、正しいバージョンのGMPライブラリを使用するよう環境を修正する。

## 通知種別

ログ（Error / Warn） -- Julia標準ロギングフレームワーク（`@error` / `@warn` マクロ）によるコンソール出力。ビット幅の不一致は `@error`（致命的）、メジャーバージョンのみの不一致は `@warn`（警告）。

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（モジュール初期化時に即時出力） |
| 優先度 | ビット不一致: 最高（Error）、バージョン不一致のみ: 高（Warn） |
| リトライ | 無し |

### 送信先決定ロジック

Julia の標準ロギングフレームワークに従い、`stderr` に出力される。

## 通知テンプレート

### メール通知の場合

該当なし（コンソールログ出力）

### 本文テンプレート

```
┌ Error: The dynamically loaded GMP library (v"X.Y.Z" with __gmp_bits_per_limb == NN)
│        does not correspond to the compile time version (v"A.B.C" with __gmp_bits_per_limb == MM).
│        Please rebuild Julia.
└ @ GMP gmp.jl:114
```

または（メジャーバージョンのみ不一致の場合）:

```
┌ Warning: The dynamically loaded GMP library (v"X.Y.Z" with __gmp_bits_per_limb == NN)
│          does not correspond to the compile time version (v"A.B.C" with __gmp_bits_per_limb == MM).
│          Please rebuild Julia.
└ @ GMP gmp.jl:114
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| version() | ランタイムのGMPバージョン | `GMP.version()` -- `__gmp_version` のCグローバル変数から取得 | Yes |
| bits_per_limb() | ランタイムの `__gmp_bits_per_limb` | `GMP.bits_per_limb()` -- Cグローバル変数から取得 | Yes |
| VERSION | コンパイル時のGMPバージョン | `GMP.VERSION` 定数 | Yes |
| BITS_PER_LIMB | コンパイル時の `__gmp_bits_per_limb` | `GMP.BITS_PER_LIMB` 定数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| モジュール初期化 | `GMP.__init__` | `major_version() != MAJOR_VERSION` OR `bits_per_limb() != BITS_PER_LIMB` | GMPのメジャーバージョンまたはビット幅の不一致 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| バージョンとビット幅がともに一致 | 正常状態。通知なし |

### ログレベル判定ロジック

```
if bits_per_limb() != BITS_PER_LIMB
    @error(msg)  # ビット幅不一致は致命的
else
    @warn(msg)   # メジャーバージョンのみ不一致は警告
end
```

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A["GMP.__init__() 呼び出し"] --> B["try ブロック開始"]
    B --> C{"major_version() != MAJOR_VERSION OR bits_per_limb() != BITS_PER_LIMB?"}
    C -->|No| D["正常初期化続行"]
    C -->|Yes| E["メッセージ生成"]
    E --> F{"bits_per_limb() != BITS_PER_LIMB?"}
    F -->|Yes| G["@error(msg)"]
    F -->|No| H["@warn(msg)"]
    G --> D
    H --> D
    D --> I["__gmp_set_memory_functions 呼び出し"]
    I --> J["ZERO, ONE 初期化"]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| データ構造 | 参照先 | 参照目的 |
|----------|--------|---------|
| `GMP.VERSION` | コンパイル時定数 | コンパイル時のGMPバージョンとの比較 |
| `GMP.BITS_PER_LIMB` | コンパイル時定数 | コンパイル時のビット幅との比較 |
| `__gmp_version` | C グローバル変数 | ランタイムのGMPバージョン取得 |
| `__gmp_bits_per_limb` | C グローバル変数 | ランタイムのビット幅取得 |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 初期化例外 | `__init__` 内で任意の例外が発生 | `showerror_nostdio(ex, "WARNING: Error during initialization of module GMP")` で出力 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | プロセス起動時に1回のみ |

### 配信時間帯

制限なし

## セキュリティ考慮事項

GMPライブラリのバージョン情報とパス情報がログに含まれる。これはシステム構成情報の一部であるが、GMP自体はオープンソースライブラリであり、一般的に機密性は低い。

## 備考

- `BITS_PER_LIMB` が不一致の場合は `@error`、メジャーバージョンのみ不一致の場合は `@warn` という非対称な重要度設定が行われている。これは、ビット幅の不一致がデータ構造のメモリレイアウト破壊につながるため、より深刻であるためである
- `__init__` 全体が `try-catch` で囲まれており、初期化エラーが他の処理に影響しないようになっている
- GMP メモリアロケータは `jl_gc_counted_malloc` 等に置き換えられ、JuliaのGCと統合される
- `ALLOC_OVERFLOW_FUNCTION` は、パッチ済みGMPで巨大メモリ確保時にabortではなく `OutOfMemoryError` をスローする機能を検出する

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | gmp.jl | `base/gmp.jl` | 35-42行目: `_version()`, `version()`, `bits_per_limb()` 関数。Cグローバル変数からの値取得 |
| 1-2 | gmp.jl | `base/gmp.jl` | 40-42行目: `VERSION`, `MAJOR_VERSION`, `BITS_PER_LIMB` コンパイル時定数 |
| 1-3 | gmp.jl | `base/gmp.jl` | 47-57行目: `Limb` 型の定義。`BITS_PER_LIMB` に基づく条件分岐 |

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | gmp.jl | `base/gmp.jl` | 108-139行目: `__init__` 関数全体 |

#### Step 3: 通知発生箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | gmp.jl | `base/gmp.jl` | 110-115行目: バージョンチェックと通知出力 |

**主要処理フロー**:
- **109行目**: `try` ブロック開始
- **110行目**: `major_version() != MAJOR_VERSION || bits_per_limb() != BITS_PER_LIMB` の条件チェック
- **111-113行目**: メッセージ文字列の生成（文字列補間で動的/静的値を含む）
- **114行目**: `bits_per_limb() != BITS_PER_LIMB ? @error(msg) : @warn(msg)` で条件的にログレベルを選択
- **117-121行目**: `__gmp_set_memory_functions` でJuliaのGCメモリ管理関数を設定
- **122-123行目**: `ZERO` と `ONE` の初期化

### プログラム呼び出し階層図

```
Julia 初期化
    │
    └─ GMP.__init__() [gmp.jl:108]
           │
           ├─ major_version() [gmp.jl:37]
           │      └─ _version() [gmp.jl:35]
           │             └─ cglobal(:__gmp_version)
           │
           ├─ bits_per_limb() [gmp.jl:38]
           │      └─ cglobal(:__gmp_bits_per_limb)
           │
           ├─ @error / @warn [gmp.jl:114] (条件付き)
           │
           ├─ ccall(:__gmp_set_memory_functions) [gmp.jl:117]
           │
           └─ ccall(:__gmp_set_alloc_overflow_function) [gmp.jl:129]
```

### データフロー図

```
[入力]                          [処理]                         [出力]

__gmp_version (C global) ─────▶ version() ───────▶ 比較
GMP.VERSION (定数) ────────────▶                    │
                                                   ├──▶ @error/@warn ──▶ stderr
__gmp_bits_per_limb (C global) ▶ bits_per_limb() ──▶ 比較
GMP.BITS_PER_LIMB (定数) ─────▶                    │
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| gmp.jl | `base/gmp.jl` | ソース | 通知の発生元。GMPモジュール全体と `__init__` 関数 |
| mpfr.jl | `base/mpfr.jl` | ソース | 同様のバージョンチェックがMPFRにも存在する可能性 |
| logging.jl | `base/logging/logging.jl` | ソース | `@error`, `@warn` マクロの実装 |
