MATLABのbsxfunを独自実装する

アルゴリズム
スポンサーリンク

はじめに

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的な動作が再現できます。配列演算を効率化したいときや、移植性を高めたいときにぜひ役立ててみてください。

コメント

タイトルとURLをコピーしました