しおりの日記 このページをアンテナに追加 RSSフィード

2007-10-09 [Ruby][数学]

[][]matrix ライブラリーの使い方

question:1191841779

matrix ライブラリーの使い方が少しわかったので、それを使って書き直してみた。

require 'matrix'

class Vector2 < Vector
  DIMENSION = 2

  def self.[](*array)
    self.Raise ErrDimensionMismatch if array.size != DIMENSION
    super
  end

  def self.elements(array, copy = true)
    self.Raise ErrDimensionMismatch if array.size != DIMENSION
    super
  end

  def rotate(angle)
    cos = Math.cos(angle)
    sin = Math.sin(angle)
    mat = Matrix[[cos, -sin],
                 [sin,  cos]]
    mat * self # .class == Vector...orz
  end
end

x = 13.0
y = 6.0
angle_degree = 47.0

angle = angle_degree * Math::PI / 180.0 # convert degrees into radians
p Vector2[x, y].rotate(angle)           # => Vector[4.47785647109746, 13.5995882814242]
p Vector2.elements([x, y]).rotate(angle)# => Vector[4.47785647109746, 13.5995882814242]

復帰値が Vector クラスのインスタンスになってしまうのが痛い(ノ∀`)……*1

*1:クラス名を決め打ちにするのは止めて欲しい。

2007-04-02 [Ruby][定数][列挙]

[][][]C/C++enum 相当の機能

question:1175229198

使い易いようにメソッドにしてみた。また、C/C++ 相当の機能と、C/C++ にも無い機能を追加してみた。*1

constant.rb
#!ruby

module Constant
  def self.enum_set(klass, names, init_val = 0)
    value = init_val.to_int
    names.each do |name|
      klass.const_set(name, value)
      value += 1
    end
  end

  def self.enum_set_ex(klass, exprs, init_val = 0)
    value = init_val.to_int
    exprs.each do |expr|
      case expr
      when /\A([^=]+)\s*=\s*(.+)\Z/
	value = klass.module_eval($2).to_int
	klass.const_set($1, value)
      else
	klass.const_set(expr, value)
      end
      value += 1
    end
  end

  def self.enum_set_bit(klass, names, init_val = 1)
    value = init_val.to_int
    names.each do |name|
      klass.const_set(name, value)
      value <<= 1
    end
  end
end

class Module
  def enum_const_set(names, init_val = 0)
    Constant.enum_set(self, names, init_val)
  end

  def enum_const_set_ex(exprs, init_val = 0)
    Constant.enum_set_ex(self, exprs, init_val)
  end

  def enum_const_set_bit(names, init_val = 1)
    Constant.enum_set_bit(self, names, init_val)
  end
end

次のような感じで使える。

enum_const_set
require 'constant'

class Foo
  enum_const_set %w[
    XX_A
    XX_B
    XX_C
  ]
end

p Foo::XX_A	# => 0
p Foo::XX_B	# => 1
p Foo::XX_C	# => 2
enum_const_set_ex
require 'constant'

class Foo
  enum_const_set_ex %w[
    XX_A
    XX_B
    XX_C=-2
    XX_D
    XX_E=XX_B
  ]
end

p Foo::XX_A	# => 0
p Foo::XX_B	# => 1
p Foo::XX_C	# => -2
p Foo::XX_D	# => -1
p Foo::XX_E	# => 1
enum_const_set_bit
require 'constant'

class Foo
  enum_const_set_bit %w[
    XX_A
    XX_B
    XX_C
  ]
end

p Foo::XX_A	# => 1 = 0b0001
p Foo::XX_B	# => 2 = 0b0010
p Foo::XX_C	# => 4 = 0b0100

*1:私自身も昔作ろうとしたけど、当時はできなかった。