# 機能設計書 35-Numeric拡張

## 概要

本ドキュメントは、mrubyのNumericクラスにzero?, positive?, negative?, nonzero?, integer?等、Integerクラスにbit_length, remainder, pow, digits, size, even?, odd?, gcd, lcm, allbits?, anybits?, nobits?, ceildiv, Integer.sqrt等、Floatクラスにremainder及び各種定数を追加するgem（mruby-numeric-ext）の機能設計を記述する。

### 本機能の処理概要

**業務上の目的・背景**：CRuby互換の数値操作メソッドを提供し、数値型の判定・演算・ビット操作の表現力を向上させる。数論的計算（gcd, lcm）、べき乗剰余（pow）、整数平方根（Integer.sqrt）等の数学的操作も含む。

**機能の利用シーン**：数値バリデーション（zero?, positive?, even?）、暗号学的計算（pow(b,m)によるべき乗剰余）、ビット操作（allbits?, anybits?, nobits?, bit_length）、数論計算（gcd, lcm）、数値分解（digits）等。

**主要な処理内容**：
1. Numeric判定系: zero?, nonzero?, positive?, negative?, integer?
2. Integer演算系: remainder, pow（通常/モジュラー）, gcd, lcm, Integer.sqrt, ceildiv
3. Integerビット系: bit_length, even?, odd?, allbits?, anybits?, nobits?
4. Integer情報系: digits, size
5. Float系: remainder, Float定数（RADIX, MANT_DIG, EPSILON, DIG, MIN_EXP等）

**関連システム・外部連携**：MRB_USE_BIGINT有効時はBigInt対応。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面なし |

## 機能種別

計算処理 / 数値操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| numeric | Integer/Float | Yes(remainder) | 除数 | ゼロでないこと |
| base | Integer | No(digits) | 基数（デフォルト10） | 2以上 |
| exp | Integer | Yes(pow) | 指数 | pow(n,m)形式ではn>=0 |
| mod | Integer | No(pow) | 法（モジュラー計算用） | ゼロでないこと |
| mask | Integer | Yes(bits系) | ビットマスク | - |
| n | Integer | Yes(sqrt) | 非負整数 | n>=0 |

### 入力データソース

メソッド呼び出し時の引数。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Boolean | true/false | zero?, even?, odd?等の判定結果 |
| Integer | Integer | bit_length, gcd, lcm, sqrt等の計算結果 |
| Array | Array | digits（基数変換した桁配列） |
| Numeric | Numeric | remainder, powの計算結果 |

### 出力先

メソッドの戻り値。

## 処理フロー

### 処理シーケンス

```
1. pow(b, m) - モジュラーべき乗
   └─ 二分法（binary exponentiation）でresult = base^exp % modを計算
2. gcd - 最大公約数
   └─ ユークリッドの互除法で計算
3. lcm - 最小公倍数
   └─ lcm = |a/gcd(a,b)| * |b|
4. Integer.sqrt - 整数平方根
   └─ バビロニアン法（ニュートン法）で反復計算
5. digits - 桁分解
   └─ n % base で最下位桁を取得し、n /= baseで桁を進める
```

### フローチャート

```mermaid
flowchart TD
    A[pow b m 呼び出し] --> B{引数2個?}
    B -->|No 1個| C[通常のべき乗 a**b]
    B -->|Yes| D{exp >= 0?}
    D -->|No| E[ArgumentError]
    D -->|Yes| F{mod == 0?}
    F -->|Yes| G[ZeroDivisionError]
    F -->|No| H[二分法でモジュラーべき乗計算]
    H --> I[result返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | digits基数制約 | base < 2 の場合はArgumentError | digits呼び出し時 |
| BR-02 | digits非負制約 | 負の整数に対してはArgumentError | digits呼び出し時 |
| BR-03 | モジュラーべき乗型制約 | pow(n,m)形式では第1引数は整数のみ | pow呼び出し時 |
| BR-04 | sqrt非負制約 | 負の整数に対してはArgumentError | Integer.sqrt呼び出し時 |
| BR-05 | BigInt透過 | MRB_USE_BIGINT有効時はBigInt演算にフォールバック | 各メソッド |

### 計算ロジック

- **gcd**: ユークリッドの互除法 `while(y!=0){temp=y; y=x%y; x=temp;}`
- **lcm**: `(a/gcd(a,b)) * b` （オーバーフロー検出付き）
- **isqrt**: バビロニアン法 `y=(x+n/x)/2` を `y<x` が成立する間反復
- **pow(b,m)**: 二分法 `if(exp&1) result=result*base%mod; base=base*base%mod; exp>>=1`

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | digitsに2未満の基数 | "negative radix" / "invalid radix X" |
| - | ArgumentError | digitsに負の整数 | "number should be positive" |
| - | ArgumentError | pow(n,m)でn<0 | "int.pow(n,m): n must be positive" |
| - | ArgumentError | Integer.sqrtに負数 | "non-negative integer required" |
| - | TypeError | pow(n,m)でnが非整数 | "2nd argument not allowed unless..." |
| - | TypeError | gcd/lcmで非整数引数 | "can't convert X into Integer" |
| - | ZeroDivisionError | remainder/powでゼロ除算 | 標準のゼロ除算エラー |

### リトライ仕様

なし。

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

なし。

## パフォーマンス要件

gcd: O(log(min(a,b)))、pow(b,m): O(log(exp))、isqrt: O(log(n))、digits: O(log_base(n))。

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

- pow(b,m)はモジュラー演算により中間値のオーバーフローを回避し、暗号学的用途に適する
- オーバーフロー検出（mrb_int_mul_overflow）付きで安全な整数演算を提供

## 備考

- CとRubyのハイブリッド実装
- MRB_USE_BIGINT有効時は自動的にBigInt演算にフォールバック
- Float定数はビルド環境の浮動小数点仕様に基づいて定義される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | numeric_ext.rb | `mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb` | Numeric/Integerクラスの構造 |

#### Step 2: C実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | numeric_ext.c | `mrbgems/mruby-numeric-ext/src/numeric_ext.c` | C実装メソッド群 |

**主要処理フロー**:
- **21-45行目**: int_bit_length - ビット長計算
- **55-81行目**: int_remainder - 剰余演算
- **85-98行目**: mrb_int_gcd - GCD内部関数（ユークリッド互除法）
- **107-127行目**: int_gcd - GCD公開関数
- **136-171行目**: int_lcm - LCM計算
- **183-262行目**: int_powm - モジュラーべき乗
- **280-341行目**: int_digits - 桁分解
- **358-368行目**: int_size - メモリサイズ
- **376-387行目**: int_even - 偶数判定
- **395-401行目**: int_odd - 奇数判定
- **430-446行目**: isqrt - 整数平方根（バビロニアン法）
- **461-481行目**: int_sqrt - Integer.sqrt公開関数
- **496-522行目**: gem_init - メソッド登録とFloat定数定義

#### Step 3: Ruby実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | numeric_ext.rb | `mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb` | Ruby実装メソッド群 |

**主要処理フロー**:
- **11-13行目**: zero? - ゼロ判定
- **22-28行目**: nonzero? - 非ゼロ判定
- **36-38行目**: positive? - 正数判定
- **47-49行目**: negative? - 負数判定
- **71-73行目**: allbits? - 全ビット判定
- **81-83行目**: anybits? - 任意ビット判定
- **91-93行目**: nobits? - ビットなし判定
- **109-111行目**: ceildiv - 切り上げ除算

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

```
Integer#pow(exp, mod)
    |
    +-- [1引数] mrb_int_pow (通常べき乗)
    +-- [2引数] int_powm
            +-- mrb_int_mul_overflow (オーバーフロー検出)
            +-- mrb_bint_powm (BigIntフォールバック)

Integer#gcd
    +-- int_gcd -> mrb_int_gcd (ユークリッド互除法)
    +-- mrb_bint_gcd (BigIntフォールバック)

Integer.sqrt
    +-- int_sqrt -> isqrt (バビロニアン法)
    +-- mrb_bint_sqrt (BigIntフォールバック)
```

### データフロー図

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

Integer (self) ──────▶ C計算関数 ──────▶ Integer/Float/Boolean/Array
引数 (base, exp等)     数値演算処理        計算結果
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| numeric_ext.c | `mrbgems/mruby-numeric-ext/src/numeric_ext.c` | ソース(C) | C実装メソッド群 |
| numeric_ext.rb | `mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb` | ソース(Ruby) | Ruby実装メソッド群 |
| mrbgem.rake | `mrbgems/mruby-numeric-ext/mrbgem.rake` | 設定 | gem定義 |
| numeric.rb | `mrbgems/mruby-numeric-ext/test/numeric.rb` | テスト | テストケース |
