はじめに
MATLABの配列演算でよく使われる便利な関数のひとつにbsxfunがあります。bsxfun
は、サイズの異なる配列同士を自動的に拡張(ブロードキャスト)して、要素ごとの演算をしてくれる関数です。例えば、ベクトルやスカラーとの演算も簡単に書けて、とても重宝します。
しかし、古いバージョンのMATLABやOctaveなど、一部の環境ではbsxfun
が使えないことも…。そんなときのために、自分でbsxfunっぽい動きを実装する方法を紹介します。
bsxfun
役割について
bsxfun
は、以下のような使い方ができます。
A = [1; 2; 3]; B = [10, 20, 30]; C = bsxfun(@plus, A, B); % 結果:各行+各列の足し算が自動的に行われる
このように、形が違う配列でも自動的に拡張しながら演算してくれるのが特徴です。
独自実装例
下記はMATLABでbsxfun
の基本的な動きを再現する関数例です。
複数の演算子(加算、減算、掛け算、割り算など)に対応しています。
function [ out ] = bsxfun( func, target, data ) %[ out ] = bsxfun( func, target, data ) %MATLABの新しいのにある、bsxfunっぽいもの。 %http://www.mathworks.co.jp/access/helpdesk_ja_JP/help/techdoc/ref/bsxfun.html %『入力』 %func 種類 %target A %data B %『出力』 %out 出力 name = func2str(func); MINUS = 0; TIMES = 1; RDIVIDE = 2; LDIVIDE = 3; PLUS = 4; type = -1; if strcmp(name,'plus'), type = PLUS; elseif strcmp(name,'minus'), type = MINUS; elseif strcmp(name,'times'), type = TIMES; elseif strcmp(name,'rdivide'), type = RDIVIDE; elseif strcmp(name,'ldivide'), type = LDIVIDE; end %row height %column width [row, column] = size(target); [height, width] = size(data); if ((height==1)&&(width==1)), if (type == PLUS), out = target + data; elseif (type == MINUS), out = target – data; elseif (type == TIMES), out = target .* data; elseif (type == RDIVIDE), out = target ./ data; elseif (type == LDIVIDE), out = target .\ data; end else out = zeros(row,column); for x=1:row, for y=1:column, a = mod(x – 1,height) + 1; b = mod(y – 1,width) + 1; if (type == PLUS), out(x,y) = target(x,y) + data(a,b); elseif (type == MINUS), out(x,y) = target(x,y) – data(a,b); elseif (type == TIMES), out(x,y) = target(x,y) * data(a,b); elseif (type == RDIVIDE), out(x,y) = target(x,y) / data(a,b); elseif (type == LDIVIDE), out(x,y) = target(x,y) \ data(a,b); end end end end
おわりに
bsxfunは、配列サイズが違っても自動で演算できる便利な関数です。この独自実装を使えば、古いMATLAB環境やOctaveなどでもbsxfun的な動作が再現できます。配列演算を効率化したいときや、移植性を高めたいときにぜひ役立ててみてください。
コメント