MATLABの小ネタ：行列に対する"all"とインデックスの指定方法について

<details><summary>「はじめに」の前に</summary>

以前から、日常でちょっと嬉しかったプログラム系の小テクとかは、大したことでもないので"X"(旧Twitter)でつぶやいていたんですね。
ですが自分がわからないことを調べるとき、ググってもあんまりXがひっかかることはなかったというか、それこそQiitaとか他のサイトは出てきますが、あんまりXは見かけなかったんです。
ということは、前述のような「ちょっと嬉しかった小テク」みたいなものは、Xというよりもここで書いたほうが有益なのでは、と考えてこれを書いてみました。
</details>

## 前フリ
普段から[MathWorks社様](https://jp.mathworks.com/)の[MATLAB](https://jp.mathworks.com/products/matlab.html)をよく利用させていただいているんですが、プログラムを書いている中で「これができたらいいな」というのは調べたり考えたりしているんですね。
たまにXでつぶやいたりもしているんですが、中でも2つ小ネタというか「これいいな」と思ったものがあったので、ここに改めて記載しておこうと思います。
本当は1個1個分けたほうがよさそうなんですが、分けるほどのことでもないと(内容も多少被るかなとも)思ってまとめて記載しました。すみません。

なお、実行環境は次の通りです。重い処理は全くないのでメモリ等々は省略。
* Windows 11
* MATLAB R2023a

## 1. 行列に対する"all"
今、何らかの理由で「行列の中身がすべて1になっているか、そうでないか」を取得したいものとします。例えば`logical_flag`という変数を用いて、その要素がすべて1になっていればTRUE、そうでなければFALSEを返したい、というわけです。
例えば、ベクトルであれば次のようにすれば問題ありません。
```MATLAB:logical_vector.m
clearvars

logical_data_1 = [0 0 0 0 0 0]; % zeros(1,6);
logical_data_2 = [1 0 1 0 0 0];
logical_data_3 = [1 1 1 1 1 1]; % ones(1,6);

TF_data_1 = all(logical_data_1); % false
TF_data_2 = all(logical_data_2); % false
TF_data_3 = all(logical_data_3); % これだけtrue
```

これがもし行列であれば、複数回allを書くなどの工夫が必要と思っていました。
ですが、これをXでつぶやいたところMATLABのmichio様から「ベクトルにすると1回で済むのでは」・「または`all(hoge,'all')`のように`'all'`オプションを使うとよい」というのを[ご教示いただきました](https://twitter.com/michio_MWJ/status/1716982941409251332)(ありがとうございました)。次のような感じですね。

```MATLAB:logical_matrix.m
clearvars

logical_data = ones(3,4);
TF_case1 = all(all(logical_data)); % 自分の思いつき(1)
TF_case2 = isequal(logical_data,ones(size(logical_data))); % 自分の思いつき(2)
TF_case3 = all(logical_data(:)); % ご教示いただいた方法(1)
TF_case4 = all(logical_data,'all'); % ご教示いただいた方法(2)
```
すげーって感じですが、どれでも目的は達成できます。個人的には`'all'`オプションを使うのが好きですね。

### 参考
* [MATLABのヘルプページ：all](https://jp.mathworks.com/help/matlab/ref/all.html)
* [MATLABのヘルプページ：logical 配列を 1 つの値にする](https://jp.mathworks.com/help/matlab/matlab_prog/reduce-logical-arrays-to-single-value.html)


## 2. 多次元行列に対するインデックスの指定方法
今、これまた何らかの事情で多次元行列について、特定のインデックスで指定される要素を抽出する必要があったとします。例えば何らかの事情で8次元行列を扱わないといけない、としてみましょう。サンプルは以下の通りです。

```MATLAB:multi_dimension_matrix.m
matrix_size = [2,3,5,7,4,9,6,8]; % 使う行列のサイズ
rng(10) % R2011a以降ではこれで乱数発生のシードを指定
matrix_data = rand(matrix_size); % 対象とする行列を作成

matrix_index = [1,2,4,3,1,6,2,7]; % このインデックスで指定される部分の要素を取りたい。
val_from_index = matrix_data(1,2,4,3,1,6,2,7); % 安直に書くとこうなる。ちなみに0.6102

matrix_index_cell = num2cell(matrix_index,1); % 上で指定したindexを1個ずつ分けてcellにする。
val_from_cell_index = matrix_data(matrix_index_cell{:}); % このcellにしたindexで要素を指定

if isequal(val_from_index,val_from_cell_index)
    disp("Value is correct.") % あってたらこれがコマンドウィンドウに表示される
end
```

なんかよくわかんないけどこれで出来ます！MATLABすげー……となる今日この頃です。
ちなみに自分が参考にしたURLを下に書きましたが、どうやらこれでコンマ区切りリストになっているらしいです。それでうまくいっている模様。
なんかよくわからんけどすごい。多次元行列は全くイメージが湧かないので……じゃあ使うなという話ですが……。

### 参考
* [MATLAB Answers:Accessing the nth dimension in a variable sized multidimensional array](https://jp.mathworks.com/matlabcentral/answers/564101-accessing-the-nth-dimension-in-a-variable-sized-multidimensional-array)
* [MATLAB Answers:Variable Indexing for N-dimension data](https://jp.mathworks.com/matlabcentral/answers/362211-variable-indexing-for-n-dimension-data)


## 終わりに
以上です。とりあえずまた何か日々の疑問が解消出来たら書きたいと思います。でも適当にXでつぶやくより疲れますね……当然か……。
MATLAB様(擬人化)、MathWorks社の皆様、今後ともどうぞよろしくお願いいたします。