# 機能設計書 141-MPFR_jll

## 概要

本ドキュメントは、Julia標準ライブラリに含まれるMPFR_jllパッケージの機能設計を記述する。MPFR_jllは、MPFR（Multiple Precision Floating-Point Reliable）ライブラリのJLLバイナリラッパーであり、任意精度浮動小数点演算のためのネイティブライブラリをJuliaから利用可能にする。

### 本機能の処理概要

MPFR_jllは、MPFR Cライブラリ（libmpfr）のプリビルドバイナリをJuliaのパッケージシステムを通じて提供するJLLラッパーパッケージである。libmpfrの動的ライブラリパスの解決、プラットフォーム別のライブラリ名マッピング、依存ライブラリ（GMP）の自動ロードを行う。

**業務上の目的・背景**：Juliaの`BigFloat`型は内部的にMPFRライブラリを使用して任意精度浮動小数点演算を実現している。MPFR_jllは、このMPFRライブラリのバイナリ配布と動的リンクを管理するためのラッパーであり、ユーザーがMPFRを個別にインストールする必要なく、クロスプラットフォームで一貫した多倍長浮動小数点演算を提供する基盤となる。

**機能の利用シーン**：BigFloat型を用いた高精度数値計算、科学技術計算における精度保証付き演算、数値解析アルゴリズムの検証など、標準のFloat64では不十分な精度が求められる場面でMPFRライブラリが利用される。Julia起動時にシステムイメージの一部として自動ロードされる。

**主要な処理内容**：
1. プラットフォーム（Windows/macOS/Linux/FreeBSD）に応じたlibmpfr共有ライブラリパスの解決
2. 依存ライブラリ（GMP_jll、Windows環境ではCompilerSupportLibraries_jll）の自動ロード
3. `LazyLibrary`メカニズムを用いた遅延ライブラリロード
4. モジュール初期化時のライブラリパスとアーティファクトディレクトリの設定

**関連システム・外部連携**：GMP_jll（GNU Multiple Precision Arithmetic Library）への依存。Windows環境ではCompilerSupportLibraries_jll（GCCランタイムライブラリ）への追加依存。上流のMPFRプロジェクト（https://www.mpfr.org/）のバージョン4.2.2に対応。

**権限による制御**：特になし。全ユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はUI画面を持たない。ccall経由でBigFloat演算時に内部的に使用される |

## 機能種別

データ連携（ネイティブライブラリバイナリ配布・動的リンク管理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Sys.KERNEL | Symbol | Yes | 実行プラットフォームのカーネル識別子 | Windows/macOS/Linux/FreeBSDのいずれか |
| Sys.BINDIR | String | Yes | Juliaバイナリのインストールディレクトリ | 有効なディレクトリパス |

### 入力データソース

- プラットフォーム情報: `Sys.iswindows()`, `Sys.isapple()`, `Sys.islinux()`, `Sys.isfreebsd()` による実行時判定
- Juliaインストールパス: `Sys.BINDIR` から算出されるプライベート共有ライブラリディレクトリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| libmpfr | LazyLibrary | libmpfr共有ライブラリへのハンドル（遅延ロード） |
| libmpfr_path | String | libmpfrの絶対ファイルパス |
| artifact_dir | String | アーティファクトディレクトリ（Juliaプレフィックスディレクトリ） |
| PATH | Ref{String} | 実行可能ファイルの検索パス |
| LIBPATH | Ref{String} | ライブラリの検索パス |

### 出力先

- メモリ内グローバル変数としてモジュール内に保持
- ccall経由でネイティブ関数呼び出し時に使用

## 処理フロー

### 処理シーケンス

```
1. モジュール定義（baremodule）
   └─ GMP_jll, Libdl, Base をusing
2. プラットフォーム判定によるライブラリパス決定
   └─ BundledLazyLibraryPathでOS別のlibmpfrファイル名を設定
3. LazyLibrary定数の定義
   └─ 依存ライブラリ（libgmp、Windowsではlibgcc_s）を指定
4. __init__()実行（モジュールロード時）
   └─ libmpfr_path, artifact_dir, LIBPATH の設定
5. eager_mode()（必要時に明示呼び出し）
   └─ 依存JLLのeager_mode呼び出し後、dlopen(libmpfr)
```

### フローチャート

```mermaid
flowchart TD
    A[モジュールロード] --> B{プラットフォーム判定}
    B -->|Windows| C["libmpfr-6.dll"]
    B -->|macOS| D["libmpfr.6.dylib"]
    B -->|Linux/FreeBSD| E["libmpfr.so.6"]
    B -->|その他| F[error発生]
    C --> G[LazyLibrary生成]
    D --> G
    E --> G
    G --> H{依存ライブラリ判定}
    H -->|Windows| I["deps: libgmp, libgcc_s"]
    H -->|その他| J["deps: libgmp"]
    I --> K["__init__() 実行"]
    J --> K
    K --> L["libmpfr_path 設定"]
    L --> M["artifact_dir 設定"]
    M --> N["LIBPATH 設定"]
    N --> O[初期化完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-141-01 | プラットフォーム別ライブラリ名 | Windows: .dll, macOS: .dylib, Linux/FreeBSD: .so の拡張子を使用 | 全環境 |
| BR-141-02 | 依存ライブラリ自動ロード | libmpfrロード前にlibgmpを先にロード | 全環境 |
| BR-141-03 | Windows追加依存 | Windows環境ではlibgcc_sも依存に追加 | Windows環境のみ |
| BR-141-04 | LazyLibraryによる遅延ロード | ライブラリは初回アクセス時に動的にロード | 全環境 |

### 計算ロジック

特になし。ライブラリの動的ロードとパス解決のみ。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ErrorException | 未対応プラットフォーム | `error("MPFR_jll: Library 'libmpfr' is not available for $(Sys.KERNEL)")` |
| - | DLError | ライブラリファイルが見つからない | dlopen失敗時のOSエラーメッセージ表示 |

### リトライ仕様

リトライは行わない。ライブラリロード失敗は致命的エラーとして扱う。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- LazyLibraryメカニズムにより、ライブラリは初回使用時まで遅延ロードされる
- eager_mode()を呼び出すことで、起動時に即座にロードすることも可能

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

- バンドルされたバイナリはJuliaインストールディレクトリ内のプライベート共有ライブラリディレクトリに格納
- ライブラリパスはSys.BINDIRからの相対パスで解決され、外部パスインジェクションのリスクを低減

## 備考

- バージョン: MPFR 4.2.2+0
- UUID: 3a97d323-0669-5f0c-9066-3539efd106a3
- JuliaBinaryWrappersの上流リポジトリ: https://github.com/JuliaBinaryWrappers/MPFR_jll.jl
- Julia標準ライブラリ内ではスタブ実装（baremodule）として提供

---

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

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

### 推奨読解順序

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

LazyLibraryとBundledLazyLibraryPathの仕組みを理解することが前提となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | libdl.jl | `base/libdl.jl` | LazyLibrary構造体（428-460行目）とBundledLazyLibraryPath（372行目）の定義。遅延ロードの基本メカニズム |
| 1-2 | libdl.jl | `base/libdl.jl` | LazyLibraryPath構造体（339-341行目）。パスの遅延結合の仕組み |

**読解のコツ**: `baremodule`はBase以外のモジュール機能を自動的にインポートしないため、`using Base, Libdl`が明示的に必要。LazyLibraryはdlopen呼び出し時に初めてライブラリをロードする遅延評価パターンを採用している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MPFR_jll.jl | `stdlib/MPFR_jll/src/MPFR_jll.jl` | モジュール全体の定義（53行）。baremoduleとして定義 |

**主要処理フロー**:
1. **4行目**: `baremodule MPFR_jll` - モジュール定義開始
2. **5行目**: `using Base, Libdl, GMP_jll` - 依存モジュールのインポート
3. **6-8行目**: Windows環境でのCompilerSupportLibraries_jllの条件付きインポート
4. **10行目**: `export libmpfr` - 公開シンボルの宣言
5. **20-35行目**: `libmpfr` LazyLibrary定数の定義。プラットフォーム別パスと依存ライブラリの指定
6. **37-43行目**: `eager_mode()` - 即座にライブラリをロードする関数
7. **46-51行目**: `__init__()` - モジュール初期化。パス変数の設定

#### Step 3: 依存ライブラリを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | GMP_jll.jl | `stdlib/GMP_jll/src/GMP_jll.jl` | MPFRが依存するGMPライブラリのJLLラッパー |
| 3-2 | Project.toml | `stdlib/MPFR_jll/Project.toml` | パッケージメタデータと依存関係の定義 |

**主要処理フロー**:
- **Project.toml 3行目**: `version = "4.2.2+0"` - MPFRバージョン定義
- **Project.toml 6-9行目**: 依存パッケージ一覧（Artifacts, CompilerSupportLibraries_jll, GMP_jll, Libdl）

#### Step 4: テストを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | runtests.jl | `stdlib/MPFR_jll/test/runtests.jl` | ccallでmpfr_get_versionを呼び出し、バージョン検証を行うテスト |

**主要処理フロー**:
- **6行目**: `ccall((:mpfr_get_version,libmpfr), Cstring, ())` - libmpfrのC関数を直接呼び出してバージョン文字列を取得
- **7行目**: バージョンがv"4.2.2"であることを検証

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

```
MPFR_jll.__init__()
    |
    +-- libmpfr.path (LazyLibrary.path アクセス)
    |       |
    |       +-- BundledLazyLibraryPath 解決
    |               |
    |               +-- Sys.BINDIR / PRIVATE_LIBDIR / "libmpfr.so.6"
    |
    +-- artifact_dir = dirname(Sys.BINDIR)
    |
    +-- LIBPATH[] = dirname(libmpfr_path)

MPFR_jll.eager_mode()
    |
    +-- GMP_jll.eager_mode()
    |       |
    |       +-- dlopen(libgmp)
    |
    +-- CompilerSupportLibraries_jll.eager_mode() [Windows のみ]
    |
    +-- dlopen(libmpfr)
            |
            +-- 依存ライブラリの自動ロード (libgmp, [libgcc_s])
```

### データフロー図

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

Sys.KERNEL (OS種別) ---------> プラットフォーム判定 ---------> ライブラリファイル名
Sys.BINDIR (Juliaパス) ------> BundledLazyLibraryPath ------> libmpfr_path
GMP_jll.libgmp (依存) -------> LazyLibrary依存解決 ----------> libmpfrハンドル
                                      |
                                      v
                               dlopen(libmpfr) ------------> ccall利用可能状態
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MPFR_jll.jl | `stdlib/MPFR_jll/src/MPFR_jll.jl` | ソース | メインモジュール定義。libmpfrのLazyLibrary定義と初期化 |
| Project.toml | `stdlib/MPFR_jll/Project.toml` | 設定 | パッケージメタデータ・依存関係・バージョン情報 |
| runtests.jl | `stdlib/MPFR_jll/test/runtests.jl` | テスト | ccallによるバージョン検証テスト |
| libdl.jl | `base/libdl.jl` | ソース | LazyLibrary/BundledLazyLibraryPathの基盤実装 |
| GMP_jll.jl | `stdlib/GMP_jll/src/GMP_jll.jl` | ソース | 依存ライブラリGMPのJLLラッパー |
| mpfr.jl | `base/mpfr.jl` | ソース | BigFloat型の実装。libmpfrを使用する主要な利用先 |
