# 機能設計書：49-rationals

## 1. 概要

### 機能名
rationals - 有理数モジュール

### 目的
分子（numerator）と分母（denominator）からなる有理数を実装するモジュール。精密な分数演算を提供し、浮動小数点数では表現できない正確な比率計算を可能にする。四則演算、比較、べき乗、整数・浮動小数点数との相互変換などを提供する。

### 関連画面
- 該当なし（ライブラリモジュール）

### 機能種別
- [x] ライブラリ
- [ ] バッチ
- [ ] 画面
- [ ] API
- [ ] イベント

## 2. 入力仕様

### 有理数生成パラメータ
| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| num | T (SomeInteger) | Yes | 分子 |
| den | T (SomeInteger) | Yes | 分母（0以外） |

### 浮動小数点数変換パラメータ
| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
|-------------|-----|------|-----------|------|
| x | float | Yes | - | 変換対象の浮動小数点数 |
| n | int | No | high(int) shr (sizeof(int) div 2 * 8) | 分母の最大値 |

## 3. 出力仕様

### 有理数結果
| 項目 | 型 | 説明 |
|------|-----|------|
| 有理数 | Rational[T] | 約分済みの有理数 |
| 浮動小数点数 | float | 有理数の浮動小数点表現 |
| 整数 | int / T | 有理数の整数部分（切り捨て） |
| 文字列 | string | "num/den" 形式の文字列 |

## 4. 型定義

### Rational型（28-30行目）
```nim
type Rational*[T] = object
  ## 有理数。分子 `num` と分母 `den` から構成される。
  num*, den*: T
```

## 5. 処理フロー

### 5.1 約分アルゴリズム（reduce関数）

```
[reduce(x: var Rational[T])]
    │
    ├── [den == 0] ── DivByZeroDefect を発生
    │
    ├── common = gcd(x.num, x.den)
    │
    ├── [den > 0]
    │       x.num = x.num div common
    │       x.den = x.den div common
    │
    └── [den < 0] (符号付き整数の場合)
            x.num = -x.num div common
            x.den = -x.den div common
```

### 5.2 加算アルゴリズム

```
[x + y: Rational[T]]
    │
    ├── common = lcm(x.den, y.den)
    │
    ├── result.num = common div x.den * x.num + common div y.den * y.num
    │
    ├── result.den = common
    │
    └── reduce(result)
```

### 5.3 浮動小数点数からの変換（連分数アルゴリズム）

```
[toRational(x: float, n: int): Rational[int]]
    │
    ├── m11, m22 = 1
    ├── m12, m21 = 0
    ├── ai = int(x)
    │
    while m21 * ai + m22 <= n:
        │
        ├── swap(m12, m11); swap(m22, m21)
        ├── m11 = m12 * ai + m11
        ├── m21 = m22 * ai + m21
        │
        ├── [x == float(ai)] ── break (除算ゼロ回避)
        │
        ├── x = 1 / (x - float(ai))
        │
        ├── [x > float(high(int32))] ── break (オーバーフロー回避)
        │
        └── ai = int(x)
    │
    └── result = m11 // m21
```

## 6. API一覧

### 6.1 生成関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| initRational | `func initRational*[T: SomeInteger](num, den: T): Rational[T]` | 有理数を生成（約分済み） | 54 |
| // | `func \`//\`*[T](num, den: T): Rational[T]` | 有理数生成の短縮記法 | 63 |
| toRational | `func toRational*[T: SomeInteger](x: T): Rational[T]` | 整数を有理数に変換 | 78 |
| toRational | `func toRational*(x: float, n: int = ...): Rational[int]` | 浮動小数点数を有理数に近似 | 84 |

### 6.2 変換関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| toFloat | `func toFloat*[T](x: Rational[T]): float` | 有理数を浮動小数点数に変換 | 113 |
| toInt | `func toInt*[T](x: Rational[T]): int` | 有理数を整数に変換（切り捨て） | 117 |
| $ | `func \`$\`*[T](x: Rational[T]): string` | 有理数を文字列に変換 | 71 |

### 6.3 算術演算子

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| + | `func \`+\`*[T](x, y: Rational[T]): Rational[T]` | 有理数同士の加算 | 122 |
| + | `func \`+\`*[T](x: Rational[T], y: T): Rational[T]` | 有理数と整数の加算 | 130 |
| + | `func \`+\`*[T](x: T, y: Rational[T]): Rational[T]` | 整数と有理数の加算 | 134 |
| += | `func \`+=\`*[T](x: var Rational[T], y: Rational[T])` | 有理数同士の加算代入 | 138 |
| += | `func \`+=\`*[T](x: var Rational[T], y: T)` | 有理数と整数の加算代入 | 145 |
| - | `func \`-\`*[T](x: Rational[T]): Rational[T]` | 単項マイナス | 149 |
| - | `func \`-\`*[T](x, y: Rational[T]): Rational[T]` | 有理数同士の減算 | 153 |
| - | `func \`-\`*[T](x: Rational[T], y: T): Rational[T]` | 有理数から整数を減算 | 161 |
| - | `func \`-\`*[T](x: T, y: Rational[T]): Rational[T]` | 整数から有理数を減算 | 165 |
| -= | `func \`-=\`*[T](x: var Rational[T], y: Rational[T])` | 有理数同士の減算代入 | 169 |
| -= | `func \`-=\`*[T](x: var Rational[T], y: T)` | 有理数と整数の減算代入 | 176 |
| * | `func \`*\`*[T](x, y: Rational[T]): Rational[T]` | 有理数同士の乗算 | 180 |
| * | `func \`*\`*[T](x: Rational[T], y: T): Rational[T]` | 有理数と整数の乗算 | 185 |
| * | `func \`*\`*[T](x: T, y: Rational[T]): Rational[T]` | 整数と有理数の乗算 | 190 |
| *= | `func \`*=\`*[T](x: var Rational[T], y: Rational[T])` | 有理数同士の乗算代入 | 195 |
| *= | `func \`*=\`*[T](x: var Rational[T], y: T)` | 有理数と整数の乗算代入 | 201 |
| / | `func \`/\`*[T](x, y: Rational[T]): Rational[T]` | 有理数同士の除算 | 216 |
| / | `func \`/\`*[T](x: Rational[T], y: T): Rational[T]` | 有理数を整数で除算 | 221 |
| / | `func \`/\`*[T](x: T, y: Rational[T]): Rational[T]` | 整数を有理数で除算 | 226 |
| /= | `func \`/=\`*[T](x: var Rational[T], y: Rational[T])` | 有理数同士の除算代入 | 231 |
| /= | `func \`/=\`*[T](x: var Rational[T], y: T)` | 有理数と整数の除算代入 | 237 |

### 6.4 比較演算子

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| cmp | `func cmp*(x, y: Rational): int` | 有理数の比較 | 242 |
| < | `func \`<\`*(x, y: Rational): bool` | 小なり比較 | 249 |
| <= | `func \`<=\`*(x, y: Rational): bool` | 以下比較 | 253 |
| == | `func \`==\`*(x, y: Rational): bool` | 等値比較 | 257 |

### 6.5 その他の演算

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| reduce | `func reduce*[T: SomeInteger](x: var Rational[T])` | 約分（破壊的） | 32 |
| reciprocal | `func reciprocal*[T](x: Rational[T]): Rational[T]` | 逆数（1/x） | 206 |
| abs | `func abs*[T](x: Rational[T]): Rational[T]` | 絶対値 | 261 |
| div | `func \`div\`*[T: SomeInteger](x, y: Rational[T]): T` | 整数除算（切り捨て） | 268 |
| mod | `func \`mod\`*[T: SomeInteger](x, y: Rational[T]): Rational[T]` | 整数除算の余り | 272 |
| floorDiv | `func floorDiv*[T: SomeInteger](x, y: Rational[T]): T` | 床除算 | 278 |
| floorMod | `func floorMod*[T: SomeInteger](x, y: Rational[T]): Rational[T]` | 床剰余 | 287 |
| hash | `func hash*[T](x: Rational[T]): Hash` | ハッシュ値計算 | 295 |
| ^ | `func \`^\`*[T: SomeInteger](x: Rational[T], y: T): Rational[T]` | べき乗 | 307 |

## 7. ビジネスルール

### BR-001: 分母は0にできない
- 分母が0の有理数は生成できない（12, 43-44行目）
- reduce関数で分母が0の場合、DivByZeroDefectを発生

### BR-002: 自動約分
- 全ての演算結果は自動的に約分される（37行目）
- reduce関数が各演算後に呼び出される

### BR-003: 符号の正規化
- 分母が負の場合、分子と分母の符号を反転して正規化（50-52行目）
- 結果として分母は常に正になる

### BR-004: 連分数による浮動小数点数近似
- toRational(float)は連分数理論に基づくアルゴリズムを使用（90-91行目）
- David Eppstein（UC Irvine）のアルゴリズムを採用
- 分母がn以下の最良近似を返却

### BR-005: べき乗の特殊処理
- 約分済み有理数のべき乗は常に約分済みになる（322-323行目）
- 負の指数は逆数のべき乗として計算（320-321行目）

### BR-006: 加減算のLCM使用
- 加減算では分母の最小公倍数（LCM）を共通分母として使用（124, 140, 155, 171行目）
- オーバーフローを防ぎつつ効率的な計算を実現

## 8. バリデーションルール

### VR-001: 分母の非ゼロ検証
- initRationalで den != 0 をアサート（59行目）
- reduce関数で den == 0 の場合 DivByZeroDefect を発生（43-44行目）

### VR-002: reciprocalのゼロ検証
- x.num == 0 の場合 DivByZeroDefect を発生（213-214行目）

## 9. 例外・エラー処理

| エラー種別 | 発生条件 | 処理 |
|-----------|---------|------|
| DivByZeroDefect | 分母が0の有理数 | 例外発生（44行目） |
| DivByZeroDefect | 0の逆数を計算 | 例外発生（214行目） |
| AssertionDefect | initRationalでden == 0 | アサート失敗（59行目） |

## 10. 数学的性質

### 加算の性質
- 交換法則: x + y == y + x
- 結合法則: (x + y) + z == x + (y + z)
- 単位元: x + 0 == x

### 乗算の性質
- 交換法則: x * y == y * x
- 結合法則: (x * y) * z == x * (y * z)
- 単位元: x * 1 == x
- 逆元: x * reciprocal(x) == 1 (x != 0)

### 比較の性質
- cmp(x, y) は (x - y).num を返却
- 約分済みのため、分子の符号で大小が決定

## 11. 使用例

### 基本的な演算
```nim
let
  r1 = 1 // 2      # 1/2
  r2 = -3 // 4     # -3/4

r1 + r2  # -1/4
r1 - r2  #  5/4
r1 * r2  # -3/8
r1 / r2  # -2/3
```

### 浮動小数点数との変換
```nim
let x = 1.2
let r = x.toRational  # 6/5
r.toFloat             # 1.2 (元の値に戻る)
```

### べき乗
```nim
(-3 // 5) ^ 2   # 9/25
(-3 // 5) ^ -2  # 25/9
```

## 12. 関連モジュール

- `std/math` - gcd, lcm 関数を使用（24行目）
- `std/hashes` - hash 関数を使用（24行目）

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

### 13.1 推奨読解順序

1. **型定義と基本操作** (28-76行目)
   - Rational 型の定義
   - reduce 関数（約分の核心）
   - initRational と // 演算子

2. **変換関数** (78-120行目)
   - toRational（整数・浮動小数点数）
   - toFloat, toInt

3. **四則演算** (122-240行目)
   - 加算・減算（LCM使用）
   - 乗算・除算
   - 複合代入演算子

4. **比較と特殊演算** (242-324行目)
   - cmp, <, <=, ==
   - div, mod, floorDiv, floorMod
   - べき乗

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

```
rationals.nim
├── [Type]
│   └── Rational[T] (28-30)
│       └── num, den: T
│
├── [Core Operations]
│   ├── reduce(x) (32-52)
│   │   └── gcd(x.num, x.den)
│   │
│   ├── initRational(num, den) (54-61)
│   │   └── reduce(result)
│   │
│   └── //(num, den) (63-69)
│       └── initRational(num, den)
│
├── [Conversion]
│   ├── toRational(int) (78-82)
│   │   └── Rational[T](num: x, den: 1)
│   │
│   ├── toRational(float, n) (84-111)
│   │   └── 連分数アルゴリズム
│   │
│   ├── toFloat(x) (113-115)
│   │   └── x.num / x.den
│   │
│   └── toInt(x) (117-120)
│       └── x.num div x.den
│
├── [Arithmetic]
│   ├── +(x, y) (122-147)
│   │   ├── lcm(x.den, y.den)
│   │   └── reduce(result)
│   │
│   ├── -(x) (149-151)
│   │   └── Rational(num: -x.num, den: x.den)
│   │
│   ├── -(x, y) (153-178)
│   │   ├── lcm(x.den, y.den)
│   │   └── reduce(result)
│   │
│   ├── *(x, y) (180-204)
│   │   ├── x.num * y.num, x.den * y.den
│   │   └── reduce(result)
│   │
│   ├── reciprocal(x) (206-214)
│   │   └── Rational(num: x.den, den: x.num)
│   │
│   └── /(x, y) (216-240)
│       ├── x.num * y.den, x.den * y.num
│       └── reduce(result)
│
├── [Comparison]
│   ├── cmp(x, y) (242-247)
│   │   └── (x - y).num
│   │
│   ├── <(x, y) (249-251)
│   │   └── (x - y).num < 0
│   │
│   ├── <=(x, y) (253-255)
│   │   └── (x - y).num <= 0
│   │
│   └── ==(x, y) (257-259)
│       └── (x - y).num == 0
│
├── [Special Operations]
│   ├── abs(x) (261-266)
│   │   └── Rational(num: abs x.num, den: abs x.den)
│   │
│   ├── div(x, y) (268-270)
│   │   └── (x.num * y.den) div (y.num * x.den)
│   │
│   ├── mod(x, y) (272-276)
│   │   └── ((x.num * y.den) mod (y.num * x.den)) // (x.den * y.den)
│   │
│   ├── floorDiv(x, y) (278-285)
│   │   └── floorDiv(x.num * y.den, y.num * x.den)
│   │
│   ├── floorMod(x, y) (287-293)
│   │   └── floorMod(x.num * y.den, y.num * x.den) // (x.den * y.den)
│   │
│   ├── hash(x) (295-305)
│   │   ├── reduce(copy)
│   │   └── hash(copy.num) !& hash(copy.den)
│   │
│   └── ^(x, y) (307-323)
│       ├── [y >= 0] ── (x.num ^ y, x.den ^ y)
│       └── [y < 0] ── (x.den ^ -y, x.num ^ -y)
│
└── [Dependencies]
    └── std/math
        ├── gcd(x.num, x.den)
        └── lcm(x.den, y.den)
```

### 13.3 データフロー図

```
[入力]
   │
   ├── [整数ペア (num, den)]
   │       │
   │       ▼
   │   ┌─────────────────┐
   │   │ initRational    │
   │   │ または //演算子  │
   │   └─────────────────┘
   │           │
   │           ▼
   │   ┌─────────────────┐
   │   │   reduce()      │
   │   │ GCDで約分       │
   │   │ 符号正規化      │
   │   └─────────────────┘
   │           │
   │           ▼
   └──────────────────────┐
                          │
   ├── [float]            │
   │       │              │
   │       ▼              │
   │   ┌─────────────────┐│
   │   │ toRational()    ││
   │   │ 連分数アルゴリズム││
   │   └─────────────────┘│
   │           │          │
   └───────────┼──────────┘
               │
               ▼
       ┌─────────────────┐
       │  Rational[T]    │
       │  (num, den)     │
       └─────────────────┘
               │
               ├── 四則演算 ── reduce() ── Rational[T]
               │
               ├── 比較演算 ── bool / int
               │
               ├── toFloat() ── float
               │
               └── toInt() ── int
```

### 13.4 関連ファイル一覧

| ファイルパス | 役割 |
|-------------|------|
| lib/pure/rationals.nim | メインモジュール（324行） |
| lib/pure/math.nim | gcd, lcm 関数 |
| lib/pure/hashes.nim | hash 関数 |
