[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dennou-ruby:000090] NMDArray



堀之内です。

数値型多次元配列の習作を ruby で作ってみました。多々変なところも
あるかも知れませんが、ruby に慣れることを兼ねた習作ということで
許して下さい。こう書いた方が良いとかいったアドバイス歓迎します。
なお全部 ruby で書いてますので、巨大配列を実用的に扱えるもんじゃ
ないです。動作のテストはあまいのでバグは結構あるかも。各メソッド
の入力のチェックは甘いです。(エラーになればトレースバック出るし。)

置場は

ftp://dennou-t.ms.u-tokyo.ac.jp/arch/davis/ex/1999-09-08-horinout/

です。

先ずは1次元の Array クラスを inherit して数値データ用に変えた 
NArray クラス(Numerical Array)を作り、"+"を足し算に再定義したり、
Mathをインクルードしたりしました。そして NArray のオブジェクトを
内部に持つ形で多次元配列 NMDArray を構成しました。ファイル 
NMDArray.rb には、クラス定義のあとにテスト用のスクリプトをつけて
ますので、ruby NMDArray.rb で実行して下さい。

# NMDArray も NArray の子孫にしようか迷ったけど、そうすると
  initialize が定義できないのでやめた(∵Array.newは再定義不可)。

論争になってましたサブセット指定法ですが、-1:最後, -2:最後から二
番目,..は採用してます。cyclic/非cyclic 属性はありません(あれば嬉
しいとは思いますが、とりあえず「普通」の配列を作ってみたかった...
何が普通と思うかは人によって違うでしょうけど)。範囲に加えてステッ
プも実装しました。3次元配列で a[{0..-1,2},1..3,0] とやると 
Fortran90表現では a[::2,1:3,0] に対応します(ここではFotran90配列
も添字は0から始まるとしました)。まだ実装してませんが、インデック
スを配列で指定する方法やラバー次元も取り入れたいと思っています。
ラバーは '..' だと認識しやすいのですが、それでは parse エラーに
なりますので Fill とか適当に名付けた定数を使おうと思っています。
(a[0,0,..] もとい a[0,0,Fill] は a が4次元なら a[0,0,0..-1,0..-1]
に対応する。Fill以外に大文字で始まるいい名前無いかな。)

こんなふうに ruby という言語の枠内で自在に配列の仕様を作れるのは
すごいと感心します。ちょっと表現法について妥協する必要はあります
が、あたかも自分で言語の仕様を拡大するノリでプログラミングできる
のは嬉しいです。

ちなみに NMDArray の仕様は以下のような感じです(ソースからの引用)。
こういうのって埋め込みドキュメント(=begin...=end)にするべきかな
あ。でも muleの ruby-mode は解釈せずに色つけちゃうしな...


# class methods
#
#   NMDArray.new(l1,l2,...)     l? is the lengths of ?-th dimension;
#                      The # of the arguments determines the # of dimensions
#
# methods
#
#   [],[]=     : subset making and subset alternation, respectively
#                Example 1 (when 3D): [1..2,2,-4] [10..-9]
#                    The # of arguments must be either equal to the rank of
#                    the array (the former case) or one (the latter case).
#                    If the former, the rank of the result of [] is the same
#                    as that of the original array. Use "trim" or "tirm!" to
#                    trim the dimensions of length 1.
#                    If the latter, the array is treated as if it were 1D.
#                    Then, the result of [] becomes 1D.
#                Example 2: [{0..-1,2},{-1..0,-1},0]
#                    A step can be specified by using a hash of length 1.
#                    Note that {0..-1,2} is equivalent to {0..-1=>2}.
#                    Specify a range as the key (here, 0..-1), and a step
#                    as the value (here, 2). Negative steps are accepted.
#                    In that case, range.first must be larger than range.last.
#
#   dup        : duplication (deep)
#   clone      : same as dup
#
#   trim trim!    :    eliminate the dimensions of length 1.
#                      trim creates another object; trim! transforms "self".
#                      (Example: a 3*1*2*1 4D array becomes 2D of 3*2)
#
#   length size       : total # of elements (length as a 1D array)
#   + - * / **        : numeric operators
#   abs               : absolute values
#   span_fill         : as in NArray (1D numeric array)
#
#   to_a       : into NArray (To get an Array, apply to_a again)
#
#   shape      : shape of the array (lengths of dimensions)
#
#   sin cos tan exp log log10 sqrt ldexp atan2   :  from Math module


堀之内 武                 horinout@xxxxxx
京都大学超高層電波研究センター    611-0011 宇治市五ヶ庄
phone:0774-38-3812                     fax:0774-31-8463