# 機能設計書 58-Mathモジュール

## 概要

本ドキュメントは、mrubyにおけるMathモジュールの設計を記述する。MathモジュールはC標準ライブラリの数学関数をラップして、三角関数・対数関数・指数関数等の標準的な数学関数をRubyから利用可能にする。

### 本機能の処理概要

Mathモジュールは数学定数（PI, E）と各種数学関数をモジュール関数として提供する。全ての関数は引数をmrb_float型として受け取り、mrb_float型で結果を返す。

**業務上の目的・背景**：科学計算、信号処理、グラフィックス、物理シミュレーション等において数学関数は不可欠である。C標準の数学ライブラリ関数をRubyから直接利用可能にすることで、組み込みシステムにおける数値計算の生産性を向上させる。

**機能の利用シーン**：三角関数によるグラフィックス処理、対数・指数関数による信号処理、誤差関数による統計計算、sqrt/hypotによる距離計算など。

**主要な処理内容**：
1. 三角関数: sin, cos, tan
2. 逆三角関数: asin, acos, atan, atan2
3. 双曲線関数: sinh, cosh, tanh
4. 逆双曲線関数: asinh, acosh, atanh
5. 指数・対数: exp, expm1, log, log1p, log2, log10
6. 累乗根: sqrt, cbrt
7. 浮動小数点分解: frexp, ldexp
8. その他: hypot, erf, erfc

**関連システム・外部連携**：C標準数学ライブラリ（math.h）に依存。MRB_NO_FLOAT設定時はコンパイルエラーとなる。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ライブラリ機能であり、画面との直接的関連なし |

## 機能種別

数学計算処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| x | Float | Yes | 数学関数の引数 | 関数の定義域内 |
| y | Float | No | atan2, ldexp, hypotの第2引数 | - |
| base | Float | No | logの底（省略時は自然対数） | 正の数 |

### 入力データソース

Rubyプログラムからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 計算結果 | Float | 数学関数の計算結果 |
| frexp結果 | Array | [fraction, exponent]の2要素配列 |

### 出力先

呼び出し元のRubyプログラムへの戻り値。

## 処理フロー

### 処理シーケンス

```
1. Math.sin(x) 等の呼び出し
   └─ get_float_arg(mrb)で引数をmrb_floatに変換
2. 定義域チェック（該当する関数のみ）
   └─ asin/acos: -1.0 <= x <= 1.0
   └─ acosh: x >= 1.0
   └─ atanh: -1.0 <= x <= 1.0
   └─ log/log2/log10/sqrt: x >= 0.0
   └─ log1p: x >= -1.0
3. C標準ライブラリ関数を呼び出し
   └─ sin(), cos(), tan() 等
4. 結果をmrb_float_valueで返却
```

### フローチャート

```mermaid
flowchart TD
    A[Math.func x 呼び出し] --> B[get_float_arg で引数取得]
    B --> C{定義域チェック必要?}
    C -->|Yes| D{定義域内?}
    D -->|No| E[Math::DomainError発生]
    D -->|Yes| F[C数学関数呼び出し]
    C -->|No| F
    F --> G[mrb_float_value で返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | 定義域エラー | 数学関数の定義域外の引数にはMath::DomainErrorを発生 | asin, acos, acosh, atanh, log系, sqrt |
| BR-58-02 | PI定数 | M_PIが定義されていればそれを使用、なければatan(1.0)*4.0で算出 | 常時 |
| BR-58-03 | E定数 | M_Eが定義されていればそれを使用、なければexp(1.0)で算出 | 常時 |
| BR-58-04 | logの底指定 | Math.log(x, base)で任意の底を指定可能。log(x)/log(base)で計算 | log第2引数あり時 |
| BR-58-05 | MRB_NO_FLOAT | MRB_NO_FLOAT設定時はコンパイルエラー | ビルド時 |

### 計算ロジック

- 各数学関数はC標準ライブラリのmath.h関数を直接呼び出す
- log(x, base) = log(x) / log(base)
- frexp: mantissa * 2^exp = x
- ldexp: x * 2^i

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Math::DomainError | asinに[-1,1]範囲外の値 | 定義域内の値を指定 |
| - | Math::DomainError | acosに[-1,1]範囲外の値 | 定義域内の値を指定 |
| - | Math::DomainError | acoshに1未満の値 | 1以上の値を指定 |
| - | Math::DomainError | atanhに[-1,1]範囲外の値 | 定義域内の値を指定 |
| - | Math::DomainError | log/log2/log10/sqrtに負の値 | 0以上の値を指定 |
| - | Math::DomainError | log1pに-1未満の値 | -1以上の値を指定 |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

- 各数学関数はC標準ライブラリへの直接呼び出しであり、Ruby層のオーバーヘッドは最小限
- get_float_argマクロにより引数変換がインライン化

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

特になし。

## 備考

- MSVC 2012以前のプラットフォーム向けにasinh, acosh, atanh, cbrt, erf, erfc, log2のポリフィルを提供
- Math::DomainErrorはStandardErrorのサブクラスとして定義
- 全関数がモジュール関数（mrb_define_module_function_id）として定義

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | math.c | `mrbgems/mruby-math/src/math.c` | get_float_argマクロ: mrb_as_floatで引数をfloatに変換（177行目） |
| 1-2 | math.c | `mrbgems/mruby-math/src/math.c` | domain_error(): DomainError例外の発生（16-22行目） |

**読解のコツ**: 各数学関数は`static mrb_value math_xxx(mrb_state *mrb, mrb_value obj)`の統一的な形式で実装されている。get_float_arg(mrb)で引数を取得し、C関数を呼び出し、mrb_float_value()で返す3ステップの構造である。

#### Step 2: 三角関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | math.c | `mrbgems/mruby-math/src/math.c` | math_sin/cos/tan: 基本三角関数（190-222行目） |
| 2-2 | math.c | `mrbgems/mruby-math/src/math.c` | math_asin/acos/atan/atan2: 逆三角関数（235-308行目） |
| 2-3 | math.c | `mrbgems/mruby-math/src/math.c` | math_sinh/cosh/tanh: 双曲線関数（320-352行目） |
| 2-4 | math.c | `mrbgems/mruby-math/src/math.c` | math_asinh/acosh/atanh: 逆双曲線関数（365-408行目） |

**主要処理フロー**:
- **240-242行目**: asinの定義域チェック（-1.0 <= x <= 1.0）
- **259-261行目**: acosの定義域チェック
- **302-305行目**: atan2は2引数（y, x）で呼び出し

#### Step 3: 指数・対数・累乗根を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | math.c | `mrbgems/mruby-math/src/math.c` | math_exp/expm1/log1p/log/log2/log10: 指数対数関数（425-543行目） |
| 3-2 | math.c | `mrbgems/mruby-math/src/math.c` | math_sqrt/cbrt: 累乗根（552-602行目） |
| 3-3 | math.c | `mrbgems/mruby-math/src/math.c` | math_frexp/ldexp: 浮動小数点分解（616-646行目） |

#### Step 4: gem初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | math.c | `mrbgems/mruby-math/src/math.c` | mrb_mruby_math_gem_init(): モジュール定義と関数登録（697-748行目） |

**主要処理フロー**:
- **699行目**: Mathモジュール定義
- **701行目**: Math::DomainErrorクラス定義
- **703-707行目**: PI定数の定義（M_PIまたはatan(1.0)*4.0）
- **709-713行目**: E定数の定義（M_Eまたはexp(1.0)）
- **715-747行目**: 全数学関数のモジュール関数登録

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

```
Math.sin(x) / Math.cos(x) / ...
    |
    +-- get_float_arg(mrb) [引数取得]
    +-- [定義域チェック] -> domain_error() [エラー時]
    +-- C数学関数 sin()/cos()/... [計算]
    +-- mrb_float_value() [結果返却]

Math.log(x, base)
    |
    +-- mrb_get_args("f|f")
    +-- log(x)
    +-- [base指定時] log(x) / log(base)
    +-- mrb_float_value()
```

### データフロー図

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

x (Float)      ──────> get_float_arg()  ──────────>
                        |
                        +-- 定義域チェック
                        |
                        +-- C math.h関数呼び出し
                        |    sin(), cos(), log() 等
                        |
                        +-- mrb_float_value()  ──────> Float (計算結果)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| math.c | `mrbgems/mruby-math/src/math.c` | ソース | Mathモジュールの全C実装 |
| math.rb | `mrbgems/mruby-math/test/math.rb` | テスト | Mathモジュールの動作テスト |
| mrbgem.rake | `mrbgems/mruby-math/mrbgem.rake` | 設定 | gemメタデータ定義 |
