Ruby の多次元数値配列ライブラリ Numo::NArray で2つの配列を要素毎に二項演算したい際、演算子のあるもの(例えば ary1 + ary2
)は直感的ですぐわかるのだが、そうではない最大値や最小値の演算はどうすればいいのかわからなかった。インスタンスメソッドの #max
などは、その配列内の要素を返すものであり二項演算ではない。
あるときAPIリファレンスのメソッド一覧を眺めていたら、それらしい名前のメソッドが目に留まった。ドキュメントには何の説明も無く自信を持てなかったが、調べたところ合っていそうなのでメモとして残しておく。
確認バージョン: 0.9.1.6 ( AtCoder で使えるもの)
計算方法
クラスメソッド Numo::Int64.maximun(*args)
の類を使う。数値の型は自動で決定(拡張、upcast)してくれず、クラスを指定しなければならない。
require 'numo/narray'
ary1 = Numo::Int64[3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
ary2 = Numo::Int64[2, 7, 1, 8, 2, 8, 1, 8, 2, 8]
p Numo::Int64.maximum(ary1, ary2) # 要素毎の最大値
#=>
# Numo::Int64#shape=[10]
# [3, 7, 4, 8, 5, 9, 2, 8, 5, 8]
次元拡張(broadcast)については演算子のある二項演算と同様に働き、したがってスカラー(→ 0次元配列)も使える。
p Numo::Int64.maximum(ary1, 3) # 3未満の要素は3にする
#=>
# Numo::Int64#shape=[10]
# [3, 3, 4, 3, 5, 9, 3, 6, 5, 3]
メソッド定義の引数が任意個なので3項以上もできるのかと思ったが、さすがにそれはダメだった。
p Numo::Int64.maximum(ary1, ary1, ary1)
# ArgumentError (wrong number of arguments (given 3, expected 2))
ドキュメントを確認
APIリファレンスから得られる情報は以下のソースコードしか無い。 int64.c はGitリポジトリに無いので自動生成していると思われる。
https://ruby-numo.github.io/narray/narray/Numo/Int64.html
# File 'ext/numo/narray/types/int64.c', line 4452
static VALUE
int64_s_maximum(int argc, VALUE *argv, VALUE mod)
{
VALUE a1 = Qnil;
VALUE a2 = Qnil;
ndfunc_arg_in_t ain[2] = {{cT,0},{cT,0}};
ndfunc_arg_out_t aout[1] = {{cT,0}};
ndfunc_t ndf = { iter_int64_s_maximum, STRIDE_LOOP_NIP, 2, 1, ain, aout };
#line 60 "gen/tmpl/ewcomp.c"
rb_scan_args(argc, argv, "20", &a1, &a2);
return na_ndloop(&ndf, 2, a1, a2);
}
ewcomp.c は存在する。ERBでテンプレート化されているものの読みやすいし、きちんとドキュメントがある。これで心配は解消した。
https://github.com/ruby-numo/numo-narray/blob/master/ext/numo/narray/gen/tmpl/ewcomp.c
/*
Element-wise <%=name%> of two arrays.
<% if is_float %>
@overload <%=name%>(a1, a2, nan:false)
@param [Numo::NArray,Numeric] a1 The array to be compared.
@param [Numo::NArray,Numeric] a2 The array to be compared.
@param [TrueClass] nan If true, apply NaN-aware algorithm (return NaN if exist).
<% else %>
@overload <%=name%>(a1, a2)
@param [Numo::NArray,Numeric] a1,a2 The arrays holding the elements to be compared.
<% end %>
@return [Numo::<%=class_name%>]
*/
このファイルが作られたコミットは 60d6f2b で、タグを見ると v0.9.1.1 でリリースされたらしい。テストコードも追加されている。