# 機能設計書 27-多次元配列操作

## 概要

本ドキュメントは、Julia Base ライブラリが提供する多次元配列操作機能の設計について記述する。多次元配列の変形（reshape）、次元の入れ替え（permutedims）、配列の結合（cat / hcat / vcat / stack）、スライス操作（selectdim / eachslice）などを提供する。

### 本機能の処理概要

多次元配列操作機能は、配列の形状を変更する `reshape`、次元を並べ替える `permutedims` / `PermutedDimsArray`、配列を結合する `cat` / `hcat` / `vcat` / `hvcat` / `hvncat` / `stack`、特定次元に沿ったスライスを操作する `selectdim` / `eachslice`、多次元インデックスを管理する `CartesianIndex` / `CartesianIndices` を提供する。

**業務上の目的・背景**：科学計算・データ分析において、多次元データ（行列、テンソル等）の形状変換や次元操作は頻繁に必要とされる。行列の転置、テンソルの軸入れ替え、複数データセットの結合、次元ごとのスライス処理など、多次元データを柔軟に操作するための基盤を提供する。reshape は O(1) でデータのコピーなしに実行でき、PermutedDimsArray もビュー（コピーなし）として動作する。

**機能の利用シーン**：行列の転置（permutedims）、1次元配列から行列への変換（reshape）、複数配列の結合（hcat/vcat/cat）、テンソル操作における軸の並べ替え、バッチ処理でのスライス取得（eachslice）、CartesianIndices による多次元ループで利用される。

**主要な処理内容**：
1. `reshape(A, dims)` - 配列の形状変更（データ共有）
2. `permutedims(A, perm)` - 次元の並べ替え（コピー）
3. `PermutedDimsArray(A, perm)` - 次元並べ替えビュー（コピーなし）
4. `cat(A...; dims)` - 指定次元での配列結合
5. `hcat(A...)` / `vcat(A...)` - 水平・垂直結合
6. `stack(iter; dims)` - イテレータから配列のスタッキング
7. `selectdim(A, d, i)` - 特定次元のスライス取得
8. `eachslice(A; dims)` - 特定次元に沿ったスライスイテレータ
9. `CartesianIndex` / `CartesianIndices` - 多次元インデックス管理
10. `vec(A)` - 1次元への平坦化

**関連システム・外部連携**：なし。Base モジュール内で完結する。

**権限による制御**：なし。すべてのユーザーが利用可能である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面関連なし（ライブラリ関数） |

## 機能種別

計算処理（配列変形・結合・スライス）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| A | AbstractArray | Yes | 操作対象の配列 | 有効な配列であること |
| dims | Tuple{Int...} / Int | No | 新しい次元サイズ / 操作する次元 | 要素数が一致すること（reshape）/ 有効な次元番号 |
| perm | Tuple{Int...} | No | 次元の並べ替え順序 | 有効な順列であること |

### 入力データソース

Julia プログラム内の配列オブジェクト。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | AbstractArray | 変形・結合・スライス後の配列 |
| iterator | Slices | eachslice のスライスイテレータ |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
1. reshape(A, dims)
   └─ Array の場合: 同じメモリ参照で新しい Array{T,N} を構築（O(1)）
   └─ その他: ReshapedArray ラッパーを作成
2. permutedims(A, perm)
   └─ 出力配列を allocate
   └─ CartesianIndices で走査して要素をコピー
3. PermutedDimsArray(A, perm)
   └─ PermutedDimsArray ラッパーを作成（ビュー、O(1)）
   └─ getindex でアクセス時に次元マッピングを適用
4. cat(A...; dims)
   └─ 出力配列サイズを計算
   └─ 各入力配列を対応する位置にコピー
5. CartesianIndices(axes)
   └─ 多次元範囲オブジェクトを作成
   └─ iterate で辞書式順序にCartesianIndex を生成
```

### フローチャート

```mermaid
flowchart TD
    A[多次元配列操作] --> B{操作種別}
    B -->|reshape| C{Array型?}
    C -->|Yes| D[同じメモリ参照で新Array構築 O_1]
    C -->|No| E[ReshapedArray ラッパー作成]
    B -->|permutedims| F[出力配列allocate + コピー]
    B -->|PermutedDimsArray| G[ビューラッパー作成 O_1]
    B -->|cat/hcat/vcat| H[出力サイズ計算 + 要素コピー]
    B -->|eachslice| I[Slices イテレータ作成]
    B -->|CartesianIndices| J[多次元Range作成]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | reshape要素数一致 | reshape の新しい dims の積は元の配列の要素数と一致しなければならない | reshape 時 |
| BR-02 | reshape共有メモリ | reshape はデータをコピーせず、元の配列とメモリを共有する | 常時 |
| BR-03 | permutedims有効順列 | perm は 1:N の有効な順列でなければならない | permutedims 時 |
| BR-04 | PermutedDimsArrayビュー | PermutedDimsArray はコピーなしのビューとして動作する | 常時 |
| BR-05 | CartesianIndex辞書式 | CartesianIndices のイテレーション順序は列優先（最初の次元が最速で変化） | 常時 |

### 計算ロジック

- `reshape(A, dims)`: prod(dims) == length(A) を検証、同じメモリの新 Array を構築
- `PermutedDimsArray`: `getindex(A, I...)` = `parent[genperm(I, iperm)...]` で次元マッピング
- `CartesianIndex` の比較: `isless(I1, I2)` = `isless(reverse(I1.I), reverse(I2.I))` （列優先）

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

### 操作別データベース影響一覧

該当なし（インメモリ計算のみ）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | DimensionMismatch | reshape で要素数不一致 | 正しい dims を指定 |
| - | ArgumentError | permutedims に無効な順列 | 有効な順列を指定 |
| - | BoundsError | CartesianIndex での範囲外アクセス | インデックスを確認 |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

- reshape: O(1)（データコピーなし）
- PermutedDimsArray: O(1) 作成、各アクセスで次元マッピングのオーバーヘッド
- permutedims: O(n)（全要素コピー）
- cat/hcat/vcat: O(n)（結果配列サイズに比例）
- CartesianIndices のイテレーション: O(1) per step

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

特になし。

## 備考

- `reshape!` は Array に対してインプレースで dims を変更する（Julia 内部用）
- `stack` は Julia 1.9 で追加された関数で、イテレータの各要素を配列として積み重ねる
- `eachslice` は Julia 1.1 で追加され、1.9 で Slices 型として改良
- CartesianIndex は broadcast において「スカラー」として扱われる（Julia 1.10以降）

---

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

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

### 推奨読解順序

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

多次元配列操作で使用される主要なラッパー型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | multidimensional.jl | `base/multidimensional.jl` | CartesianIndex, CartesianIndices の定義 |
| 1-2 | reshapedarray.jl | `base/reshapedarray.jl` | ReshapedArray の定義 |
| 1-3 | permuteddimsarray.jl | `base/permuteddimsarray.jl` | PermutedDimsArray の定義 |

**読解のコツ**: Julia では型パラメータに順列情報を含めることで（例: `PermutedDimsArray{T,N,perm,iperm,AA}`）、コンパイル時に次元マッピングを解決できる。`genperm` 関数による次元インデックスの変換パターンに注目。

- **multidimensional.jl 75-78行目**: `CartesianIndex{N}` - NTuple{N,Int} をラップ
- **reshapedarray.jl 5-9行目**: `ReshapedArray{T,N,P,MI}` - 親配列と新しい dims を保持
- **permuteddimsarray.jl 9-18行目**: `PermutedDimsArray{T,N,perm,iperm,AA}` - perm/iperm を型パラメータに持つ

#### Step 2: reshape を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | reshapedarray.jl | `base/reshapedarray.jl` | reshape の実装（Array 特殊版と汎用版） |

**主要処理フロー**:
1. **43-51行目**: `reshape(a::Array{T,M}, dims)` - 同じメモリ参照で新 Array を構築
2. **55-62行目**: `reshape!` - インプレースで dims を変更
3. **66-80行目**: `reshape` docstring - `:` による自動計算の説明

#### Step 3: PermutedDimsArray を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | permuteddimsarray.jl | `base/permuteddimsarray.jl` | PermutedDimsArray のビュー実装 |

**主要処理フロー**:
- **42-46行目**: コンストラクタ - invperm で逆順列を計算
- **68-72行目**: `getindex` - genperm(I, iperm) で次元マッピング
- **73-77行目**: `setindex!` - 同様に次元マッピングして親配列に書き込み

#### Step 4: CartesianIndex / CartesianIndices を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | multidimensional.jl | `base/multidimensional.jl` | CartesianIndex の算術演算と CartesianIndices のイテレーション |

**主要処理フロー**:
- **75-78行目**: CartesianIndex 構造体定義
- **80-86行目**: コンストラクタ群
- **126-136行目**: 算術演算（+, -, min, max）
- **142行目**: `isless` - reverse で列優先の辞書式順序

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

```
reshape(A, dims) / permutedims(A, perm) / cat(A...; dims)
    |
    +-- reshape(a::Array, dims)
    |       +-- Core.checked_dims(dims...)  # オーバーフロー検査
    |       +-- 新 Array{T,N} 構築（同じ ref）
    |
    +-- PermutedDimsArray(A, perm)
    |       +-- invperm(perm)
    |       +-- PermutedDimsArray{T,N,perm,iperm,AA}(A)
    |       +-- getindex → genperm(I, iperm) → parent[...]
    |
    +-- permutedims(A, perm)
    |       +-- similar(A, genperm(size(A), perm))
    |       +-- permutedims!(dest, A, perm)
    |
    +-- cat(A...; dims=d)
    |       +-- __cat(A...; dims=d)
    |       +-- 出力サイズ計算 + copyto! で各入力を配置
    |
    +-- CartesianIndices(axes)
            +-- iterate → CartesianIndex 列を生成
```

### データフロー図

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

A (Array)            ---->  reshape(A, (m, n))
                            +-- 同メモリ参照                   ---->  Array{T,2}

A (AbstractArray)    ---->  PermutedDimsArray(A, (2,1))
                            +-- ビューラッパー                 ---->  PermutedDimsArray (転置ビュー)

A, B (Arrays)        ---->  hcat(A, B)
                            +-- 出力配列allocate + copyto!    ---->  結合配列

axes (Tuple)         ---->  CartesianIndices(axes)
                            +-- iterate で列優先巡回           ---->  CartesianIndex 列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| multidimensional.jl | `base/multidimensional.jl` | ソース | CartesianIndex, CartesianIndices, selectdim, eachslice 等 |
| reshapedarray.jl | `base/reshapedarray.jl` | ソース | ReshapedArray, reshape の実装 |
| permuteddimsarray.jl | `base/permuteddimsarray.jl` | ソース | PermutedDimsArray, permutedims の実装 |
| abstractarray.jl | `base/abstractarray.jl` | ソース | cat, hcat, vcat, hvcat, stack 等の結合関数 |
| array.jl | `base/array.jl` | ソース | Array 型の基本定義 |
