# 機能設計書 17-SubArray（ビュー）

## 概要

本ドキュメントは、Julia言語におけるSubArray（ビュー）機能の設計を記述する。view / @view / @views によるコピーなしの配列部分参照を提供する。

### 本機能の処理概要

SubArray{T,N,P,I,L}は親配列の一部分をコピーせずに参照するビュー型である。メモリコピーを避けることで大規模配列の部分操作を効率的に行える。@viewマクロと@viewsマクロにより、通常のインデックス構文をビュー操作に変換する。

**業務上の目的・背景**：大規模な数値計算では、配列のスライス操作が頻繁に行われる。デフォルトのスライス（A[1:100, :]）はコピーを生成するため、メモリ使用量と計算時間の両面で非効率である。SubArrayはコピーなしの参照を提供し、メモリ効率と性能を大幅に向上させる。特に、行列分解やイテレーティブソルバーでの部分行列操作で重要。

**機能の利用シーン**：（1）大規模行列の部分行列操作（線形代数）、（2）時系列データのウィンドウ処理、（3）画像データの部分領域処理、（4）@viewsマクロによるブロック全体のビュー化、（5）in-placeブロードキャスト代入（@view(A[...]) .+= 1）。

**主要な処理内容**：
1. SubArray{T,N,P,I,L}型定義（親配列参照+インデックスタプル+オフセット+ストライド）
2. view(A, inds...)関数によるSubArray生成
3. @viewマクロによる単一インデックス式のビュー変換
4. @viewsマクロによるブロック全体のビュー変換
5. viewindexing関数によるIndexLinear/IndexCartesianの自動判定
6. compute_stride1/compute_offset1によるリニアインデックス最適化
7. maybeview関数によるスカラーインデックスとスライスの使い分け

**関連システム・外部連携**：特になし。Base内部で完結。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Juliaプロンプト（julia>） | 参照画面 | REPL上でview/@view操作を実行 |

## 機能種別

データ管理（配列ビュー・部分参照）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| A | AbstractArray | Yes | 親配列 | - |
| inds... | ViewIndex | Yes | ビューのインデックス指定 | 親配列の次元数と一致 |

### 入力データソース

Julia式からの直接入力。view(A, 1:10, :) や @view A[1:10, :]。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| subarray | SubArray{T,N,P,I,L} | 親配列の部分参照 |
| element | T | getindexによる要素取得 |

### 出力先

メモリ上のSubArrayオブジェクトとして返却（親配列のメモリを共有）。

## 処理フロー

### 処理シーケンス

```
1. view(A, inds...) 呼び出し
   └─ ensure_indexable(indices)でインデックスを正規化
2. IndexStyle判定
   └─ viewindexing(indices)でLinear/Cartesianを判定
3. SubArray生成
   └─ L==true: compute_stride1/compute_offset1を計算
   └─ L==false: offset1=0, stride1=0
4. 要素アクセス
   └─ 親配列のインデックスに変換 → 親配列のgetindex/setindex!を呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A["view(A, inds...)"] --> B[ensure_indexable]
    B --> C[viewindexing判定]
    C -->|IndexLinear| D[compute_stride1/offset1]
    C -->|IndexCartesian| E[offset1=0, stride1=0]
    D --> F["SubArray{T,N,P,I,true}"]
    E --> G["SubArray{T,N,P,I,false}"]
    F --> H[要素アクセス: 親配列に委譲]
    G --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | コピーなし | SubArrayは親配列のメモリを共有（コピーしない） | 全ビュー操作 |
| BR-02 | 親配列変更の反映 | 親配列の変更はSubArrayに反映される | 参照中 |
| BR-03 | 次元数一致 | インデックス数は親配列の次元数と一致必須 | view呼び出し時 |
| BR-04 | スカラーインデックス | @viewsでスカラーインデックスはgetindex（コピー） | maybeview |
| BR-05 | L型パラメータ | L==trueで高速リニアインデックス、L==falseでCartesian | SubArray生成時 |

### 計算ロジック

- viewindexing: インデックスタプルの型に基づきIndexLinear/IndexCartesianを判定
  - 先頭のスカラーインデックス、Slice、UnitRangeの組み合わせでLinear
  - AbstractArrayインデックスがある場合はCartesian
- compute_stride1: 親配列のストライドとインデックスから最初の次元のストライドを計算
- compute_offset1: 先頭要素のリニアオフセットを計算
- maybeview: スカラーインデックスのみの場合はgetindex、スライスがある場合はview

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | インデックス数と親配列次元数の不一致 | 正しい次元数のインデックスを指定 |
| - | BoundsError | インデックスが親配列の範囲外 | 有効な範囲のインデックスを指定 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- コピーなしのためメモリ割り当てコストが極めて低い
- L==trueの場合、リニアインデックスでの高速アクセス
- @viewsマクロでブロック全体のスライスをビュー化し、中間配列の生成を回避

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

- 親配列のライフタイム管理：SubArrayが親配列への参照を保持するため、親配列のGCを防止
- @viewsマクロの左辺値（代入先）ではビューを生成しない（意図しない副作用を防止）

## 備考

- @viewsマクロはop=代入（A[i] += 1）を正しく処理するため、一時変数を使用して評価順序を保持
- replace_ref_begin_end!でbegin/endキーワードをfirstindex/lastindexに変換
- SubArray(copy)は親配列の該当部分のコピーを返す

---

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

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

### 推奨読解順序

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

SubArrayの型定義と内部構造。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | subarray.jl | `base/subarray.jl` | SubArray{T,N,P,I,L}構造体定義（8-24行目）：parent, indices, offset1, stride1 |
| 1-2 | subarray.jl | `base/subarray.jl` | SubArrayコンストラクタ（26-39行目）：IndexStyle判定分岐 |

**読解のコツ**: L型パラメータがtrueの場合、offset1とstride1が有効で高速なリニアインデックスが可能。falseの場合はCartesianインデックスのみ。

#### Step 2: ビュー生成とIndexStyle判定を理解する

viewindexingによる自動IndexStyle判定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | subarray.jl | `base/subarray.jl` | viewindexing関数群（47-62行目）：インデックスタプルの型による判定 |
| 2-2 | subarray.jl | `base/subarray.jl` | check_parent_index_match（41-44行目）：次元数検証 |

**主要処理フロー**:
- **47行目**: viewindexing(()) = IndexLinear() - 空インデックスはLinear
- **49行目**: 先頭スカラーはskipしてtail再帰
- **51行目**: 連続Sliceはskipしてtail再帰
- **58行目**: ScalarIndex範囲のみの場合IndexLinear
- **60行目**: それ以外はIndexCartesian

#### Step 3: @view/@viewsマクロを理解する

マクロによるAST変換。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | views.jl | `base/views.jl` | @viewマクロ定義（210-228行目） |
| 3-2 | views.jl | `base/views.jl` | @viewsマクロ定義（332-334行目） |
| 3-3 | views.jl | `base/views.jl` | maybeview関数（235-239行目）：スカラー/スライス判定 |
| 3-4 | views.jl | `base/views.jl` | _views関数（248-294行目）：@viewsのAST変換 |
| 3-5 | views.jl | `base/views.jl` | replace_ref_begin_end!（17-160行目）：begin/end変換 |

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

```
@view A[1:10, :]
    |
    +-- replace_ref_begin_end!(ex)    [begin/end変換]
    +-- Expr(:call, view, A, 1:10, :) [view呼び出しに変換]

view(A, 1:10, :)
    |
    +-- SubArray(A, (1:10, :))
    |       +-- ensure_indexable(indices)
    |       +-- viewindexing(indices)    [IndexStyle判定]
    |       +-- compute_stride1/offset1  [L==true時]
    |
    +-- getindex(V::SubArray, i)
            +-- 親配列インデックスに変換
            +-- getindex(V.parent, ...)

@views block
    |
    +-- _views(ex)                     [AST変換]
    |       +-- maybeview(A, args...)   [ref式をmaybeviewに変換]
    |       +-- 左辺代入は変換しない
    +-- replace_ref_begin_end!(ex)
```

### データフロー図

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

A[1:10, :]       ──────> コピー（getindex）       ──────> 新Array
@view A[1:10, :] ──────> view → SubArray生成      ──────> SubArray（共有メモリ）
@views block     ──────> 全ref式をmaybeviewに変換  ──────> 変換済みブロック
SubArray V, i    ──────> 親インデックス変換 → get  ──────> 要素 T
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| subarray.jl | `base/subarray.jl` | ソース | SubArray型定義、viewindexing、compute_stride1等 |
| views.jl | `base/views.jl` | ソース | @view/@viewsマクロ、maybeview、replace_ref_begin_end! |
| abstractarray.jl | `base/abstractarray.jl` | ソース | AbstractArray基本インタフェース |
| indices.jl | `base/indices.jl` | ソース | Slice, OneTo等のインデックス型 |
