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

[dennou-ruby:000104] NMDArray revised



堀之内です。

9月末のワークショップ後に ftp サイトに置きました ruby による多
次元配列ライブラリーを更新しました。置場は前回と同じ

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

で、ファイル名は

  nmd_array-19991004.tgz

です。

# このディレクトリーのネーミングシステムでは、新しいものを置く度
   にその日の日付で切り直すことが期待されているような気がするな...

前回からの変化といえば、多次元配列クラス NMDArray に新メソッド
each_set! と each_set (non-destructive version) が加わっただけで
すが、これは以前話題になった各要素毎の操作の実装例ですので、報告し
ておきます。今は ruby だけで閉じてますが、これをそっくり C の関
数で置き換えられれば、要素毎にオブジェクトを作ることなしにユーザー
が指定したきめ細かな要素毎演算を行えるということになるかもしれま
せん --- って辛いですか?(ブロックを自前パースしない限り無理?)
なお、組込みの配列 Array に実装されている each と同様、ブロック
を使いますので、複数行にわたる演算が出来る、if文が使えるので演算
対象を選択できる(fortran90のwhere構文みたいに)、といったメリット
があります。

中身は簡単なので最後に引用します。もっといい方法あるよ、といった
指摘をよろしくお願いします。

未解決の問題は複数のオブジェクトに演算を適用することです。どいう
いうことか例をあげると、fortran90 で a, b という同じ形の配列があっ
たとして

   where(a>0)
     a=a*b
   endwhere

などと、whereの判断の対象(a)以外の配列(b)を取り込んだ演算をする
ようなことです。each_setのブロックの前に()で引数を取らせることは
出来るので、他のオブジェクトをメソッドに引数として与えられますが、
例えそうしてもその要素をどうブロックに組み込んだらいいかわかりま
せん。これ(他のオブジェクト取り込み)も出来たらいいんですが。

---
  def each_set!(&block)
    # Elementwise operation. Each element is replaced with the value
    # evaluated by the last statement in the block. The data substitution
    # is suppressed when the value is nil.
    # Note that the operation can be applied to selected elements by using
    # if conditioning (see examples).
    # This is a destructive method (with "!"); the object is modified
    # directly. Use each_set (without "!") to create another object to
    # return the result, leaving the original one intact.
    #
    # Usage: array.each_set!{block}
    # Example: array.each_set!{|x| x*3}     # multiply 3 to all elements
    #          array.each_set!{|x| x*3 if x>0}    #same but only when positive
    #          array.each_set!{|x| s=sin(x); x+s if(cos(x)>0.0)}
    #                       # last value (x+s) is substituted if the condition
    #                       # is satisfied. Here, s is a local variable
    #                       # only in the block ({} introduces a new scope).

    @xxxxxx do
      |i|
      eval = block.call(@xxxxxx[i])
      @xxxxxx[i]=eval if (eval != nil)
    end
  end

  def each_set(&block)
    out=self.dclone         # deep clone
    out.each_set!(&block)
    return out
  end
---
使用例:

% irb
irb(main):001:0> require "NMDArray"
nil
irb(main):002:0> a=NMDArray.indgen(3,2)
#<NMDArray: @xxxxxx=[3, 2], @xxxxxx=[0.0, 1.0, 2.0, 3.0, 4.0, 5.0], @xxxxxx=6, @xxxxxx=2>
irb(main):003:0> b=a.each_set{|x| x*3 if x>3}
#<NMDArray: @xxxxxx=[3, 2], @xxxxxx=[0.0, 1.0, 2.0, 3.0, 12.0, 15.0], @xxxxxx=6, @xxxxxx=2>
irb(main):004:0> a.prt
[0.0, 1.0, 2.0,
3.0, 4.0, 5.0]
nil
irb(main):005:0> b.prt
[0.0, 1.0, 2.0,
3.0, 12.0, 15.0]
nil

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