# 機能設計書 15-Numericクラス

## 概要

本ドキュメントは、mrubyにおけるNumericクラス群（Numeric, Integer, Float）の機能設計を記述する。四則演算・比較・型変換等の数値操作全般を提供する組み込み型クラスである。

### 本機能の処理概要

Numericクラスは全数値型の基底クラスであり、Integer（整数）とFloat（浮動小数点数）のサブクラスを持つ。ISO 15.2.7（Numeric）、15.2.8（Integer）、15.2.9（Float）に準拠する。整数のオーバーフロー検出、ゼロ除算エラー、BigInt（多倍長整数、オプション）への自動昇格、Rational/Complex型との連携など、堅牢な数値演算基盤を提供する。Comparableモジュールをインクルードしている。

**業務上の目的・背景**：数値演算はプログラミングの最も基本的な機能であり、計算処理、インデックス操作、カウンター、条件判定など全ての場面で使用される。組み込み環境では、整数オーバーフローの安全な検出（コンパイラのビルトイン関数を利用）や、メモリ効率の良い数値表現（NaN Boxing / Word Boxing）が重要となる。

**機能の利用シーン**：算術演算（+, -, *, /, %, **）、比較（==, <, >, <=>, etc.）、型変換（to_i, to_f, to_s）、ビット演算（&, |, ^, ~, <<, >>）、イテレーション（times, upto, downto, step）、絶対値・正負判定など。

**主要な処理内容**：
1. Numericクラス: abs, +@, -@等の共通メソッド
2. Integerクラス: 四則演算、ビット演算、イテレーション（times, upto, downto, step）
3. Floatクラス: 浮動小数点演算、丸め処理（ceil, floor, round, truncate）
4. 整数オーバーフロー検出（ビルトイン関数またはマニュアル実装）
5. ゼロ除算エラー処理
6. 型間の自動変換（Integer <-> Float、BigInt昇格）
7. 文字列変換（to_s、基数指定対応）
8. 数値パースとの連携

**関連システム・外部連携**：Comparableモジュールをインクルード。BigInt（mruby-bigint gem）が有効な場合は自動昇格。Rational/Complex型との演算連携（オプション）。

**権限による制御**：なし。Integer/Floatのnewメソッドは未定義化（undef）されている。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIベースのランタイム機能のため関連画面なし |

## 機能種別

計算処理 / 型変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| other | Numeric | Yes（演算） | 演算対象の数値 | 非数値型はTypeError |
| base | Integer | No（to_s） | 基数（2-36） | 範囲外はArgumentError |
| num | Integer | Yes（upto/downto） | 範囲の終端値 | なし |
| step | Numeric | No（step） | ステップ値 | 0はArgumentError |

### 入力データソース

リテラル記法、文字列からのパース、C APIからの生成。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 数値 | Integer/Float | 演算結果 |
| 文字列 | String | to_s、inspectの変換結果 |
| 真偽値 | Boolean | 比較、判定メソッドの結果 |
| self | Object | times, upto, downto, stepの戻り値 |

### 出力先

呼び出し元への戻り値として返却。

## 処理フロー

### 処理シーケンス

```
1. 数値演算の実行
   └─ オペランドの型を確認
   └─ 同型なら直接演算
   └─ 異型の場合は型変換（Integer→Float等）
   └─ オーバーフロー検出
       ├─ ビルトイン関数あり: __builtin_add_overflow等
       └─ ビルトイン関数なし: マニュアル検出
   └─ オーバーフロー時: BigInt昇格（有効時）またはRangeError
2. イテレーション（times, upto, downto, step）
   └─ Rubyレベルのwhileループで実装
```

### フローチャート

```mermaid
flowchart TD
    A[数値演算要求] --> B{オペランドの型?}
    B -->|Integer + Integer| C[整数演算]
    C --> D{オーバーフロー?}
    D -->|Yes| E{BigInt有効?}
    E -->|Yes| F[BigInt昇格]
    E -->|No| G[RangeError]
    D -->|No| H[結果返却]
    B -->|Integer + Float| I[Floatに変換して演算]
    I --> H
    B -->|Float + Float| J[浮動小数点演算]
    J --> H
    F --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-15-01 | オーバーフロー検出 | 整数演算のオーバーフローを検出してエラーまたはBigInt昇格 | Integer演算時 |
| BR-15-02 | ゼロ除算 | 整数のゼロ除算でZeroDivisionError | 除算時 |
| BR-15-03 | new未定義 | Integer/Floatのnewメソッドは使用不可 | クラスメソッド呼び出し時 |
| BR-15-04 | Comparable包含 | NumericはComparableをインクルード | 常時 |
| BR-15-05 | Fixnum互換 | Fixnum定数はIntegerクラスのエイリアス | 後方互換性 |
| BR-15-06 | Float定数 | INFINITY, NAN定数が定義される | MRB_NO_FLOAT未定義時 |

### 計算ロジック

- **オーバーフロー検出（ビルトイン）**: `__builtin_add_overflow`, `__builtin_sub_overflow`, `__builtin_mul_overflow`
- **オーバーフロー検出（マニュアル）**: `((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK` パターン
- **累乗**: `mrb_int_pow` - 負の指数はFloat変換、オーバーフローはBigInt昇格

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

該当なし（インメモリ操作のみ）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RangeError | 整数演算のオーバーフロー（BigInt無効時） | BigIntを有効にするか、値を確認する |
| - | ZeroDivisionError | ゼロ除算 | 除数を確認する |
| - | TypeError | 非数値型との演算 | 型を確認する |
| - | ArgumentError | step値が0 | 0以外のstep値を指定する |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- 整数演算はネイティブCPU命令レベルの速度
- オーバーフロー検出はコンパイラビルトイン利用時はほぼゼロコスト
- NaN Boxing / Word Boxing によるメモリ効率の最適化

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

- 整数オーバーフローの安全な検出によるセキュリティリスクの軽減
- ゼロ除算の確実なエラー処理

## 備考

- ISO 15.2.7（Numeric）、15.2.8（Integer）、15.2.9（Float）に準拠
- MRB_NO_FLOAT定義時はFloat無効（整数のみモード）
- MRB_USE_FLOAT32定義時はfloat（32bit）、未定義時はdouble（64bit）
- MRB_INT64定義時は64ビット整数

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | numeric.h | `include/mruby/numeric.h` | 型定義、オーバーフロー検出マクロ、Float定数 |

**読解のコツ**: numeric.hには2つのオーバーフロー検出実装がある。`MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS` 定義時はGCCビルトイン（__builtin_add_overflow等）を使用し、未定義時はマニュアル実装を使用する。マニュアル実装は符号ビットの伝播パターンで検出している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | numeric.c | `src/numeric.c` | `mrb_init_numeric()`関数（2384行目）でクラス階層定義 |

**主要処理フロー**:
1. **2384-2420行目**: Numeric→Integer→Float のクラス階層定義
2. **2396-2400行目**: Integer定義（newメソッドundef、Fixnum互換定数）
3. **2405-2418行目**: Float定義（INFINITY, NAN定数）

#### Step 3: C実装の主要関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | numeric.c | `src/numeric.c` | mrb_int_overflow, mrb_int_zerodiv, mrb_int_pow等 |
| 3-2 | numops.c | `src/numops.c` | mrb_num_add, mrb_num_sub, mrb_num_mul（型横断演算） |

**主要処理フロー**:
- **33-37行目**: mrb_int_overflow - RangeError発生
- **45-49行目**: mrb_int_zerodiv - ZeroDivisionError発生
- **72-100行目**: mrb_int_pow - 累乗演算（BigInt/Float対応）

#### Step 4: Rubyレベルメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | numeric.rb | `mrblib/numeric.rb` | Numeric#abs, Integer#times/upto/downto/step, Float#step |

**主要処理フロー**:
- **6行目**: `include Comparable`
- **11-13行目**: `+@` - 単項プラス
- **19-21行目**: `-@` - 単項マイナス（0 - self）
- **27-33行目**: `abs` - 絶対値
- **47-56行目**: `downto` - 降順イテレーション
- **72-81行目**: `times` - N回イテレーション
- **88-97行目**: `upto` - 昇順イテレーション
- **103-127行目**: `Integer#step` - ステップ付きイテレーション
- **135-159行目**: `Float#step` - Float版ステップイテレーション

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

```
mrb_init_numeric()
    |
    +-- mrb_define_class_id(Numeric)
    |       +-- MRB_MT_INIT_ROM(numeric_rom_entries)
    |
    +-- mrb_define_class_id(Integer < Numeric)
    |       +-- MRB_MT_INIT_ROM(integer_rom_entries)
    |       +-- mrb_define_const_id(Fixnum = Integer)
    |
    +-- mrb_define_class_id(Float < Numeric)
            +-- MRB_MT_INIT_ROM(float_rom_entries)
            +-- mrb_define_const_id(INFINITY, NAN)

演算処理:
    mrb_num_add / mrb_num_sub / mrb_num_mul
        |
        +-- mrb_integer_p? → mrb_int_add (オーバーフロー検出)
        +-- mrb_float_p? → mrb_float + mrb_as_float
        +-- mrb_bigint_p? → mrb_bint_add
        +-- mrb_rational? → mrb_rational_add
        +-- mrb_complex? → mrb_complex_add
```

### データフロー図

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

数値リテラル         型判定                             数値結果
/演算対象   ---->   Integer/Float/BigInt       ---->   Integer / Float
                       |                                / BigInt
                       +-- 整数演算
                       |   +-- オーバーフロー検出
                       |   +-- BigInt昇格（オプション）
                       +-- 浮動小数点演算
                       +-- 型変換（to_i, to_f, to_s）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| numeric.c | `src/numeric.c` | ソース（C） | Numeric/Integer/Floatの主要実装 |
| numops.c | `src/numops.c` | ソース（C） | 型横断演算（add/sub/mul） |
| numeric.rb | `mrblib/numeric.rb` | ソース（Ruby） | abs, times, upto, downto, step等 |
| numeric.h | `include/mruby/numeric.h` | ヘッダ | 数値型定義とオーバーフロー検出 |
| compar.rb | `mrblib/compar.rb` | ソース（Ruby） | Comparableモジュール（Numericがインクルード） |
