# 機能設計書 62-CMathモジュール

## 概要

本ドキュメントは、mrubyにおける複素数対応数学関数（CMathモジュール）の設計を記述する。mruby-cmath gemとして実装され、Mathモジュールの関数を複素数引数に拡張する。

### 本機能の処理概要

CMathモジュールは、標準のMathモジュールが提供する数学関数を複素数（Complex）に対応させた拡張版を提供する。実数に対しては通常のMathモジュールと同じ結果を返し、複素数が引数の場合や負の実数の対数・平方根のように結果が複素数になる場合にComplex型の結果を返す。C99の_Complex機能を利用して実装される。

**業務上の目的・背景**：科学技術計算や信号処理等において、負の数の平方根や対数を扱う必要がある。標準のMathモジュールではドメインエラーとなるこれらの計算を、複素数を介して正しく処理できるようにする。

**機能の利用シーン**：負の数の平方根（CMath.sqrt(-1)）、負の数の対数（CMath.log(-1)）、複素数の三角関数・双曲線関数の計算、信号処理におけるフーリエ変換関連の計算等で使用される。

**主要な処理内容**：
1. 三角関数（sin, cos, tan）の複素数拡張
2. 逆三角関数（asin, acos, atan）の複素数拡張
3. 双曲線関数（sinh, cosh, tanh）の複素数拡張
4. 逆双曲線関数（asinh, acosh, atanh）の複素数拡張
5. 指数関数（exp）の複素数拡張
6. 対数関数（log, log2, log10）の複素数拡張
7. 平方根（sqrt）の複素数拡張

**関連システム・外部連携**：mruby-complexに依存。Mathモジュールをincludeして基本メソッドを継承する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIベースのため画面なし |

## 機能種別

計算処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| z | Numeric (Integer/Float/Complex) | Yes | 数学関数の引数 | Numericでない場合はTypeError |
| base | Float | No | log関数の底（デフォルトe） | log関数のみ |

### 入力データソース

mrubyスクリプトからの直接呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 計算結果 | Float / Complex | 実数結果の場合はFloat、複素数結果の場合はComplex |

### 出力先

mruby値スタック上に結果を返却

## 処理フロー

### 処理シーケンス

```
1. 引数の型判定
   └─ cmath_get_complex()で引数からreal/imagパートを抽出
2. 複素数判定
   └─ 引数がComplex型 or 実数でも結果が複素数になる場合はComplex計算
3. C99 _Complex関数による計算
   └─ csin/ccos/clog等のC標準関数を呼び出し
4. 結果の返却
   └─ 複素数結果ならmrb_complex_new()、実数ならmrb_float_value()
```

### フローチャート

```mermaid
flowchart TD
    A[CMath関数呼び出し] --> B{引数の型チェック}
    B -->|Integer| C[real=引数, imag=0]
    B -->|Float| C
    B -->|Complex| D[real/imagを抽出]
    B -->|その他| E[TypeError]
    C --> F{複素数計算が必要?}
    D --> G[C99 _Complex関数で計算]
    F -->|Yes| G
    F -->|No| H[通常のmath関数で計算]
    G --> I[Complex値を返却]
    H --> J[Float値を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-62-01 | 実数透過性 | 実数引数で結果も実数の場合はFloatを返す | 全関数共通 |
| BR-62-02 | 複素数拡張 | 実数引数でも結果が複素数になる場合はComplexを返す | log/sqrt等で負の実数の場合 |
| BR-62-03 | Math継承 | MathモジュールをincludeしてE, PI等の定数を継承 | モジュール初期化時 |

### 計算ロジック

C99の`<complex.h>`ヘッダで定義されるcsin, ccos, ctan, casin, cacos, catan, csinh, ccosh, ctanh, casinh, cacosh, catanh, cexp, clog, csqrt関数を使用。float32モードの場合はcsinf等のfloat版を使用。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeError | Numeric以外の引数 | 引数の型を確認 |
| - | コンパイルエラー | MRB_NO_FLOAT設定時 | 浮動小数点を有効にする |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

C99のネイティブ複素数関数を直接呼び出すため、パフォーマンスは十分。

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

特になし

## 備考

- C99以降のコンパイラが必要
- Windows環境では_Fcomplex/_Dcomplexを使用、その他はC99標準の_Complexを使用
- C++コンパイラの場合はstd::complexを使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cmath.c | `mrbgems/mruby-cmath/src/cmath.c` | mrb_complex型の定義、CX/cresl/cimagマクロ |

**読解のコツ**:
- **47-51行目**: F(x)マクロ - float32/float64の切り替え
- **53-125行目**: プラットフォーム別の複素数型定義（Windows/C++/C99）
- **119行目**: CX(r,i)マクロ - C99の`(r)+(i)*_Complex_I`

#### Step 2: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cmath.c | `mrbgems/mruby-cmath/src/cmath.c` | cmath_get_complex()による型判定 |

**主要処理フロー**:
- **24-45行目**: cmath_get_complex() - Integer/Float/Complexの判定と実部・虚部の抽出

#### Step 3: DEF_CMATH_METHODマクロを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cmath.c | `mrbgems/mruby-cmath/src/cmath.c` | DEF_CMATH_METHODマクロパターン |

**主要処理フロー**:
- **131-143行目**: DEF_CMATH_METHODマクロ - 引数が複素数ならFC(name)、実数ならF(name)を呼び出す共通パターン
- **171-192行目**: cmath_log() - log関数は底の引数を持つため個別実装

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | cmath.c | `mrbgems/mruby-cmath/src/cmath.c` | mrb_mruby_cmath_gem_init() |

**主要処理フロー**:
- **393-421行目**: gem初期化 - CMathモジュール定義、Mathのinclude、各関数のモジュール関数登録

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

```
CMath.sin(z) 等
    |
    +-- cmath_sin() [DEF_CMATH_METHODで生成]
    |       |
    |       +-- cmath_get_complex()    ... 引数型判定
    |       +-- FC(sin) = csin()       ... C99複素数sin（Complex引数時）
    |       +-- F(sin) = sin()         ... 通常sin（実数引数時）
    |       +-- mrb_complex_new()      ... Complex結果生成
    |       +-- mrb_float_value()      ... Float結果生成
    |
    +-- cmath_log() [個別実装]
            |
            +-- cmath_get_complex()
            +-- FC(log) = clog()
            +-- F(log) = log()
```

### データフロー図

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

Integer/Float    ──+
                   |──▶ cmath_get_complex()  ──▶ real/imag抽出
Complex          ──+           |
                               v
                       C99 _Complex関数     ──▶ Complex or Float結果
                       (csin/ccos/clog等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cmath.c | `mrbgems/mruby-cmath/src/cmath.c` | ソース | CMathモジュール全実装（427行） |
| mrbgem.rake | `mrbgems/mruby-cmath/mrbgem.rake` | 設定 | gem仕様定義、mruby-complex依存宣言 |
| cmath.rb | `mrbgems/mruby-cmath/test/cmath.rb` | テスト | CMath関数のテストケース |
