# 機能設計書：47-math

## 1. 概要

### 機能名
math - 基本数学ルーチン

### 目的
Nim言語の基本的な数学関数群を提供する標準ライブラリモジュール。三角関数、対数関数、指数関数、丸め関数、統計関数、数論関数など、科学技術計算に必要な数学演算を包括的に実装している。

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

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

## 2. 入力仕様

### 数値型
| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| x, y | float32/float64 | Yes | 浮動小数点演算の入力値 |
| x, y | SomeInteger | Yes | 整数演算の入力値 |
| x, y | SomeNumber | Yes | 汎用数値演算の入力値 |
| n, k | int | Yes | 二項係数・階乗の入力値 |

### 配列型
| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| x | openArray[T] | Yes | 集計関数（sum, prod, gcd, lcm）の入力配列 |

## 3. 出力仕様

### 数値結果
| 項目 | 型 | 説明 |
|------|-----|------|
| 関数結果 | float32/float64 | 浮動小数点演算結果 |
| 関数結果 | int | 整数演算結果 |
| 関数結果 | T | ジェネリック型演算結果 |

### 複合結果
| 項目 | 型 | 説明 |
|------|-----|------|
| frexp結果 | tuple[frac: T, exp: int] | 仮数部と指数部 |
| splitDecimal結果 | tuple[intpart: T, floatpart: T] | 整数部と小数部 |
| divmod結果 | (T, T) | 商と余り |

## 4. 定数定義

### 数学定数（162-179行目）
```nim
const
  PI* = 3.1415926535897932384626433          # 円周率
  TAU* = 2.0 * PI                            # TAU = 2 * PI
  E* = 2.71828182845904523536028747          # 自然対数の底

  MaxFloat64Precision* = 16                  # float64の有効桁数
  MaxFloat32Precision* = 8                   # float32の有効桁数
  MaxFloatPrecision* = MaxFloat64Precision   # floatの有効桁数
  MinFloatNormal* = 2.225073858507201e-308   # 最小正規化数 (= 2^-1022)
  RadPerDeg = PI / 180.0                     # 度からラジアンへの変換係数
```

## 5. 型定義

### FloatClass列挙型（182-191行目）
```nim
type
  FloatClass* = enum
    fcNormal,        # 通常の非ゼロ浮動小数点値
    fcSubnormal,     # 非正規化数（非常に小さい値）
    fcZero,          # 正のゼロ
    fcNegZero,       # 負のゼロ
    fcNan,           # NaN (Not a Number)
    fcInf,           # 正の無限大
    fcNegInf         # 負の無限大
```

## 6. 処理フロー

### 6.1 三角関数群

```
[sin/cos/tan] ─┬─ [C backend] ── sinf/cosf/tanf/sin/cos/tan (math.h)
               └─ [JS backend] ── Math.sin/cos/tan
```

### 6.2 丸め関数群

```
[round(x, places)]
    │
    ├── [places == 0] ── round(x)
    │
    └── [places != 0]
            │
            ├── mult = pow(10.0, places)
            └── result = round(x * mult) / mult
```

### 6.3 GCD（最大公約数）アルゴリズム

```
[gcd(x, y)]
    │
    ├── [float版] ── ユークリッドの互除法
    │       while y != 0:
    │           x = x mod y
    │           swap x, y
    │       return abs(x)
    │
    └── [integer版] ── バイナリGCD（スタインのアルゴリズム）
            shift = countTrailingZeroBits(x or y)
            y = y shr countTrailingZeroBits(y)
            while x != 0:
                x = x shr countTrailingZeroBits(x)
                if y > x: swap y, x
                x -= y
            return y shl shift
```

### 6.4 べき乗演算（^演算子）

```
[x ^ y (Natural)]
    │
    ├── [y == 0] ── return 1
    ├── [y == 1] ── return x
    ├── [y == 2] ── return x * x
    ├── [y == 3] ── return x * x * x
    └── [y > 3] ── 二進展開法
            result = 1
            while true:
                if (y and 1) != 0: result *= x
                y = y shr 1
                if y == 0: break
                x *= x
```

## 7. API一覧

### 7.1 基本数学関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| sqrt | `func sqrt*(x: float64): float64` | 平方根 | 369 |
| cbrt | `func cbrt*(x: float64): float64` | 立方根 | 378 |
| pow | `func pow*(x, y: float64): float64` | べき乗 | 628 |
| hypot | `func hypot*(x, y: float64): float64` | 斜辺の長さ | 622 |

### 7.2 対数・指数関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| ln | `func ln*(x: float64): float64` | 自然対数 | 388 |
| log | `func log*[T: SomeFloat](x, base: T): T` | 任意底の対数 | 412 |
| log10 | `func log10*(x: float64): float64` | 常用対数 | 429 |
| log2 | `func log2*(x: float64): float64` | 二進対数 | 1048 |
| exp | `func exp*(x: float64): float64` | 指数関数 | 441 |

### 7.3 三角関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| sin | `func sin*(x: float64): float64` | 正弦 | 451 |
| cos | `func cos*(x: float64): float64` | 余弦 | 460 |
| tan | `func tan*(x: float64): float64` | 正接 | 469 |
| arcsin | `func arcsin*(x: float64): float64` | 逆正弦 | 505 |
| arccos | `func arccos*(x: float64): float64` | 逆余弦 | 514 |
| arctan | `func arctan*(x: float64): float64` | 逆正接 | 523 |
| arctan2 | `func arctan2*(y, x: float64): float64` | 2引数逆正接 | 533 |

### 7.4 双曲線関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| sinh | `func sinh*(x: float64): float64` | 双曲線正弦 | 478 |
| cosh | `func cosh*(x: float64): float64` | 双曲線余弦 | 487 |
| tanh | `func tanh*(x: float64): float64` | 双曲線正接 | 496 |
| arcsinh | `func arcsinh*(x: float64): float64` | 逆双曲線正弦 | 545 |
| arccosh | `func arccosh*(x: float64): float64` | 逆双曲線余弦 | 551 |
| arctanh | `func arctanh*(x: float64): float64` | 逆双曲線正接 | 557 |

### 7.5 補助三角関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| cot | `func cot*[T: float32\|float64](x: T): T` | 余接 (1/tan) | 590 |
| sec | `func sec*[T: float32\|float64](x: T): T` | 正割 (1/cos) | 592 |
| csc | `func csc*[T: float32\|float64](x: T): T` | 余割 (1/sin) | 594 |
| coth | `func coth*[T: float32\|float64](x: T): T` | 双曲線余接 | 597 |
| sech | `func sech*[T: float32\|float64](x: T): T` | 双曲線正割 | 599 |
| csch | `func csch*[T: float32\|float64](x: T): T` | 双曲線余割 | 601 |

### 7.6 丸め・切り捨て関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| floor | `func floor*(x: float64): float64` | 床関数（切り捨て） | 676 |
| ceil | `func ceil*(x: float64): float64` | 天井関数（切り上げ） | 689 |
| round | `func round*(x: float64): float64` | 四捨五入 | 759 |
| round | `func round*[T: float32\|float64](x: T, places: int): T` | 指定桁数丸め | 840 |
| trunc | `func trunc*(x: float64): float64` | 切り捨て（ゼロ方向） | 777 |

### 7.7 除算・剰余関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| mod | `func \`mod\`*(x, y: float64): float64` | 浮動小数点剰余 | 789 |
| floorDiv | `func floorDiv*[T: SomeInteger](x, y: T): T` | 床除算 | 860 |
| floorMod | `func floorMod*[T: SomeNumber](x, y: T): T` | 床剰余 | 880 |
| euclDiv | `func euclDiv*[T: SomeInteger](x, y: T): T` | ユークリッド除算 | 897 |
| euclMod | `func euclMod*[T: SomeNumber](x, y: T): T` | ユークリッド剰余 | 912 |
| ceilDiv | `func ceilDiv*[T: SomeInteger](x, y: T): T` | 天井除算 | 925 |
| divmod | `func divmod*[T: SomeInteger](x, y: T): (T, T)` | 商と余りを同時計算 | 98 |

### 7.8 浮動小数点分析関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| classify | `func classify*(x: float): FloatClass` | 浮動小数点分類 | 270 |
| isNaN | `func isNaN*(x: SomeFloat): bool` | NaN判定 | 193 |
| signbit | `proc signbit*(x: SomeFloat): bool` | 符号ビット取得 | 231 |
| copySign | `func copySign*[T: SomeFloat](x, y: T): T` | 符号コピー | 245 |
| almostEqual | `func almostEqual*[T: SomeFloat](x, y: T; unitsInLastPlace: Natural = 4): bool` | 近似等価判定 | 295 |
| frexp | `func frexp*[T: float32\|float64](x: T): tuple[frac: T, exp: int]` | 仮数・指数分解 | 977 |
| splitDecimal | `func splitDecimal*[T: float32\|float64](x: T): tuple[intpart: T, floatpart: T]` | 整数・小数分解 | 1061 |

### 7.9 角度変換関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| degToRad | `func degToRad*[T: float32\|float64](d: T): T` | 度からラジアンへ | 1081 |
| radToDeg | `func radToDeg*[T: float32\|float64](d: T): T` | ラジアンから度へ | 1091 |

### 7.10 符号関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| sgn | `func sgn*[T: SomeNumber](x: T): int` | 符号関数 | 1101 |

### 7.11 集計関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| sum | `func sum*[T](x: openArray[T]): T` | 合計 | 1118 |
| prod | `func prod*[T](x: openArray[T]): T` | 積 | 1133 |
| cumsum | `func cumsum*[T](x: var openArray[T])` | 累積和（破壊的） | 1197 |
| cumsummed | `func cumsummed*[T](x: openArray[T]): seq[T]` | 累積和（非破壊的） | 1179 |
| cumprod | `func cumprod*[T](x: var openArray[T])` | 累積積（破壊的） | 1148 |
| cumproded | `func cumproded*[T](x: openArray[T]): seq[T]` | 累積積（非破壊的） | 1162 |

### 7.12 べき乗・累乗関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| ^ | `func \`^\`*[T: SomeNumber](x: T, y: Natural): T` | 整数べき乗 | 1212 |
| ^ | `func \`^\`*[T: SomeNumber, U: SomeFloat](x: T, y: U): float` | 浮動小数点べき乗 | 1248 |
| isPowerOfTwo | `func isPowerOfTwo*(x: int): bool` | 2のべき乗判定 | 324 |
| nextPowerOfTwo | `func nextPowerOfTwo*(x: int): int` | 次の2のべき乗 | 339 |

### 7.13 数論関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| gcd | `func gcd*[T](x, y: T): T` | 最大公約数（float） | 1286 |
| gcd | `func gcd*(x, y: SomeInteger): SomeInteger` | 最大公約数（integer） | 1307 |
| gcd | `func gcd*[T](x: openArray[T]): T` | 最大公約数（配列） | 1341 |
| lcm | `func lcm*[T](x, y: T): T` | 最小公倍数 | 1353 |
| lcm | `func lcm*[T](x: openArray[T]): T` | 最小公倍数（配列） | 1376 |
| binom | `func binom*(n, k: int): int` | 二項係数 | 117 |
| fac | `func fac*(n: int): int` | 階乗 | 135 |

### 7.14 特殊関数（Cバックエンドのみ）

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| erf | `func erf*(x: float64): float64` | 誤差関数 | 645 |
| erfc | `func erfc*(x: float64): float64` | 相補誤差関数 | 650 |
| gamma | `func gamma*(x: float64): float64` | ガンマ関数 | 655 |
| lgamma | `func lgamma*(x: float64): float64` | 対数ガンマ関数 | 667 |

### 7.15 クランプ関数

| 関数名 | シグネチャ | 説明 | 行番号 |
|--------|-----------|------|--------|
| clamp | `func clamp*[T](val: T, bounds: Slice[T]): T` | 範囲制限（スライス版） | 1364 |

## 8. ビジネスルール

### BR-001: 三角関数はラジアン単位
- 全ての三角関数（sin, cos, tan等）はラジアン単位で動作する
- 度数法を使用する場合はdegToRad/radToDegで変換が必要

### BR-002: 階乗のルックアップテーブル
- fac関数は事前計算されたテーブルを使用（146-155行目）
- int型サイズに応じてテーブルサイズが変化
  - 2バイト: 最大4!まで
  - 4バイト: 最大12!まで
  - 8バイト: 最大20!まで

### BR-003: 整数GCDのバイナリアルゴリズム
- 整数版gcdはスタインのアルゴリズム（バイナリGCD）を使用（1307-1339行目）
- ビット演算を活用して除算を回避し高速化

### BR-004: ceilDivの入力制約
- x >= 0 かつ y > 0 が前提条件（958行目）
- 符号なし整数の場合、x + y - 1 がオーバーフローしないことが必要
- 制約外の入力には divmath パッケージを推奨

### BR-005: almostEqualのULP比較
- デフォルトで4ULP（Units in Last Place）の誤差を許容（296行目）
- 計算式: `diff <= epsilon(T) * abs(x + y) * unitsInLastPlace`

### BR-006: JavaScriptバックエンドの特殊処理
- 一部の関数（round等）はJSバックエンドで異なる実装
- `1^Inf` や `-1^Inf` の結果がIEEE 754の旧仕様に従う（1277-1282行目）

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

### VR-001: 階乗の入力検証
- n >= 0 であることを検証（153行目）
- nがルックアップテーブルの範囲内であることを検証（154行目）

### VR-002: divmodのゼロ除算チェック
- overflowChecksが有効な場合、y == 0 でDivByZeroDefectを発生（106-107行目）
- x == T.low かつ y == -1 でOverflowDefectを発生（108-109行目）

### VR-003: clampの境界検証
- bounds.a <= bounds.b であることをアサート（1373行目）
- 無効な範囲でAssertionDefectを発生

### VR-004: べき乗演算子の入力検証
- x == 0 かつ y < 0 の組み合わせをアサートで禁止（1269-1272行目）
- x < 0 かつ y が非整数の組み合わせを禁止（1273行目）

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

| エラー種別 | 発生条件 | 処理 |
|-----------|---------|------|
| DivByZeroDefect | divmodでy == 0 | 例外発生 |
| OverflowDefect | divmodでx == T.low, y == -1 | 例外発生 |
| AssertionDefect | fac(n)でn < 0またはn >= テーブルサイズ | アサート失敗 |
| AssertionDefect | clampで無効な範囲 | アサート失敗 |
| NaN | 不正な演算（負数の対数等） | NaN値を返却 |
| Inf/-Inf | オーバーフロー/ゼロ除算 | 無限大を返却 |

## 11. プラットフォーム依存性

### C/C++バックエンド
- math.hの関数を直接importc（67-799行目）
- POSIX環境では `-lm` リンクフラグを追加（159-160行目）
- Windows CC89（MSVC 2010以前）では一部関数を自前実装（702-756行目）

### JavaScriptバックエンド
- Math オブジェクトの関数を使用（800-838行目）
- toBitsImpl でArrayBufferを使用して浮動小数点のビット操作を実現（210-216行目）

### NimScript
- 一部の関数が利用不可（67行目の条件分岐）

## 12. 関連モジュール

- `std/complex` - 複素数演算
- `std/rationals` - 有理数演算
- `std/fenv` - 浮動小数点環境制御
- `std/random` - 乱数生成
- `std/stats` - 統計関数
- `std/bitops` - ビット演算（内部使用）

## 13. バージョン履歴

| バージョン | 追加機能 |
|-----------|---------|
| 1.1 | gcd(openArray), lcm(openArray) |
| 1.5 | almostEqual, clamp(Slice) |
| 1.5.1 | isNaN, signbit, copySign, euclDiv, euclMod, ceilDiv |

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

### 14.1 推奨読解順序

1. **定数・型定義** (162-191行目)
   - PI, TAU, E などの数学定数
   - FloatClass 列挙型

2. **浮動小数点分析** (193-322行目)
   - isNaN, signbit, copySign, classify
   - almostEqual のULP比較ロジック

3. **基本数学関数** (367-561行目)
   - Cバックエンド: math.h からのimportc
   - JSバックエンド: Math オブジェクトからのimport

4. **丸め関数** (675-858行目)
   - floor, ceil, round, trunc
   - Windows CC89 の特殊処理

5. **除算・剰余** (860-975行目)
   - floorDiv/floorMod vs euclDiv/euclMod の違い
   - ceilDiv の最適化手法

6. **集計・数論関数** (1118-1387行目)
   - sum, prod, cumsum, cumsummed
   - gcd, lcm のアルゴリズム

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

```
math.nim
├── [C backend]
│   ├── <math.h>
│   │   ├── sqrt, cbrt (368-386)
│   │   ├── sin, cos, tan (450-476)
│   │   ├── sinh, cosh, tanh (477-503)
│   │   ├── arcsin, arccos, arctan, arctan2 (504-543)
│   │   ├── ln, log10, log2 (387-400, 427-439, 1047-1059)
│   │   ├── exp (440-449)
│   │   ├── pow, hypot (621-640)
│   │   ├── floor, ceil, round, trunc (675-786)
│   │   ├── erf, erfc, gamma, lgamma (644-673)
│   │   └── frexp (77-80)
│   └── <stdlib.h>
│       └── div, ldiv, lldiv (94-97)
│
├── [JS backend]
│   └── Math object
│       ├── Math.sqrt, Math.cbrt (403-407)
│       ├── Math.sin, Math.cos, Math.tan (571-573)
│       ├── Math.sinh, Math.cosh, Math.tanh (575-577)
│       ├── Math.asin, Math.acos, Math.atan, Math.atan2 (579-584)
│       ├── Math.log, Math.log10, Math.log2 (409-410, 564-567)
│       ├── Math.exp (568-569)
│       ├── Math.pow, Math.hypot (801-804)
│       └── Math.floor, Math.ceil, Math.round, Math.trunc (805-821)
│
└── [Internal dependencies]
    ├── std/bitops
    │   └── countTrailingZeroBits (1332-1335)
    ├── std/fenv
    │   └── epsilon, minimumPositiveValue (321-322)
    └── system/countbits_impl (61)
```

### 14.3 データフロー図

```
[入力値 x, y]
      │
      ▼
┌─────────────────┐
│ バックエンド判定 │
│  (js/c/nimscript)│
└─────────────────┘
      │
      ├── [C] ──────────────────────────┐
      │                                  │
      ▼                                  ▼
┌─────────────────┐            ┌─────────────────┐
│ math.h / stdlib.h│            │ importc pragma  │
│  のC関数呼び出し │            │ で直接バインド  │
└─────────────────┘            └─────────────────┘
      │
      ├── [JS] ─────────────────────────┐
      │                                  │
      ▼                                  ▼
┌─────────────────┐            ┌─────────────────┐
│ Math オブジェクト│            │ ArrayBuffer を  │
│  のメソッド呼び出し│          │ 使ったビット操作│
└─────────────────┘            └─────────────────┘
      │
      ▼
┌─────────────────┐
│   演算結果      │
│ (float/int/tuple)│
└─────────────────┘
```

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

| ファイルパス | 役割 |
|-------------|------|
| lib/pure/math.nim | メインモジュール（1388行） |
| lib/std/private/since.nim | バージョンプラグマ |
| lib/std/bitops.nim | ビット演算（GCDで使用） |
| lib/std/fenv.nim | 浮動小数点環境 |
| lib/system/countbits_impl.nim | ビットカウント実装 |
| lib/std/private/jsutils.nim | JS用ユーティリティ |
