RubyのMatrix

ruby の Matrix#determinant の実装が間違ってる 経由。

[ruby-dev:27548] の問題、

Matrix[Float]

とか

 Matrix[Rational]

とか書いて新しいClassオブジェクトを返すようにして、係数体(or 環)を指定するようにしたら解決しないのかな。

require 'matrix'

class << Matrix
  alias :"[]_orig" []
  def [](*args)
    if args.length == 1 and args[0].kind_of? Class
      ring = args[0]
      name = ring.name
      return const_get(name) if const_defined? name
      normalizer = Kernel.instance_method(name).bind(self)
      klass = Class.new(Matrix)
      (class << klass; self end).class_eval do
        define_method(:[]) do |*args|
          args = args.map { |row|
            row.map{|element| normalizer[element]}
          }
          __send__(:"[]_orig", *args)
        end
      end
      klass.const_set(:COEFF_RING, ring)
      self.const_set(name, klass)
      klass
    else
      Matrix[Float][*args]
    end
  end
end

p Matrix[Integer][[1.0, 2.0], [3.0, 4.0]]

やっぱり整除演算子はあったほうがいい気がするが、今は/が除算と整除で混ざって使われてるので互換性維持が難しいし、整除演算子は昔Matzが蹴ってたよなぁ。まあ、数学の人以外は現状で不便がないだろうから、divとquoで我慢するか。逆元が無いとき用に環でundefinedな除算メソッドが欲しいところだが。

Pythonは整除の導入はよくやったよなぁ。やっぱり段階的にfeatureを移行させていく例のシステム(なんつったか)が有効に働いてる。