# vector.rb version 0.1, 2002/4/21 # simple vector caliculator # by Tomokiyo Nomura # # Usage: this program is supposed to be used on the irb with --noinspect option. # after irb prompt appeared, type 'require "vector.rb"'. To create a Matrix, # type as follows. # irb> a = Matrix[[1,2],[3,4]] # or to create a vector, # irb> b = Vector[[1,2]] # in this case, try 'a + a', 'a * a', 'a * 2', 'b + b', 'b * 2', 'a * b' # on the irb prompt. To calculate inner_product, use Vector.inner_product # class method. ex, # irb> Vector.inner_product( b, b ) # To transpose matrix or vector, use transpose method. # irb> a.transpose # To convert a vector to the matrix, use to_matrix method. # irb> b.to_matrix # # Each row or column of the matrix can be processed, to exchange rows, # irb> a.row.exchange(1,2) # The following methods are usable for row or column calculation. # row_exchange!(i, j) has 'ce!' shortcut # row_add!( i, j, scalar ) has 'ca!' shortcut # row_subtract!( i, j, scalar ) has 'cs!' shortcut # row_multiply!( i, scalar ) has 'cm!' shortcut # row_divide!( i, scalar ) has 'cd!' shortcut # column_exchange! has 'ce!' shortcut # column_add!( i, j, scalar ) has 'ca!' shortcut # column_subtract!( i, j, scalar ) has 'cs!' shortcut # column_multiply!( i, scalar ) has 'cm!' shortcut # column_divide!( i, scalar ) has 'cd!' shortcut class Matrix def initialize( a ) @a = a end attr_reader :a def to_s b = "[" @a.each {|c| b += c.inspect + "\n"} b.chop + "]" end def Matrix.[]( *a ) Matrix.new( a ) end def Matrix.dim( row, column ) (0...row).collect { Array.new(column).fill(0) } end def Matrix.add( x, y ) row, column = x.size, x[0].size c = Matrix.dim(row, column) for i in 0...row for j in 0...column c[i][j] = x[i][j] + y[i][j] end end c end def Matrix.sub( x, y ) row, column = x.size, x[0].size c = Matrix.dim(row, column) for i in 0...row for j in 0...column c[i][j] = x[i][j] - y[i][j] end end c end def Matrix.multiply( x, y ) x_row, x_column = x.size, x[0].size y_column = y[0].size c = Matrix.dim(x_row, y_column) for i in 0...x_row for j in 0...y_column for k in 0...x_column c[i][j] += x[i][k] * y[k][j] end end end c end def Matrix.multiply_by_scalar( x, a ) x_row, x_column = x.size, x[0].size c = Matrix.dim(x_row, x_column) for i in 0...x_row for j in 0...x_column c[i][j] = x[i][j] * a end end c end def Matrix.transpose( arry ) row, column = arry.size, arry[0].size c = Matrix.dim( column, row ) for i in 0...row for j in 0...column c[j][i] = arry[i][j] end end c end def +( other ) Matrix.new( Matrix.add( self.a, other.a ) ) end def -( other ) Matrix.new( Matrix.sub( self.a, other.a ) ) end def *( other ) if other.kind_of?( Numeric ) Matrix.new( Matrix.multiply_by_scalar( self.a, other ) ) elsif other.type == Vector Vector.new( Matrix.multiply( self.a, other.a ) ) else Matrix.new( Matrix.multiply( self.a, other.a ) ) end end def row_exchange!( i, j ) i -= 1; j -= 1 @a[i], @a[j] = @a[j], @a[i] self end def row_add!( i, j, c = 1 ) i -=1; j -= 1 @a[i].each_index {|k| @a[i][k] += @a[j][k] * c} self end def row_subtract!( i, j, c = 1 ) i -=1; j -= 1 @a[i].each_index {|k| @a[i][k] -= @a[j][k] * c} self end def row_multiply!( i, c ) i -=1; column = @a.size (0...column).each {|k| @a[i][k] *= c} self end def row_divide!( i, c ) i -=1; column = @a[0].size (0...column).each {|k| @a[i][k] /= c.to_f} self end def transpose Matrix.new( Matrix.transpose( @a ) ) end alias re! row_exchange! alias ra! row_add! alias rs! row_subtract! alias rm! row_multiply! alias rd! row_divide! def column_exchange!( i, j ) row = @a.size i -= 1; j -= 1 for k in 0...row @a[k][i], @a[k][j] = @a[k][j], @a[k][i] end self end def column_add!( i, j, c = 1 ) row = @a.size i -= 1; j -= 1 for k in 0...row @a[k][i] += @a[k][j] * c end self end def column_subtract!( i, j, c = 1) row = @a.size i -= 1; j -= 1 for k in 0...row @a[k][i] -= @a[k][j] * c end self end def column_multiply!( i, c ) row = @a.size i -= 1 for k in 0...row @a[k][i] *= c end self end def column_divide!( i, c ) row = @a.size i -= 1 for k in 0...row @a[k][i] /= c.to_f end self end alias ce! column_exchange! alias ca! column_add! alias cs! column_subtract! alias cm! column_multiply! alias cd! column_divide! end class Vector def initialize( a ) @a = a end attr_reader :a def to_s @a.collect {|c| c[0]}.inspect end def Vector.[]( *a ) Vector.new( a.collect{|c| c.to_a} ) end def +( other ) Vector.new( Matrix.add( self.a, other.a ) ) end def -( other ) Vector.new( Matrix.sub( self.a, other.a ) ) end def *( other ) if other.kind_of?( Numeric ) Vector.new( Matrix.multiply_by_scalar( self.a, other ) ) else Vector.new( Matrix.multiply( self.a, other.a ) ) end end def to_matrix Matrix.new( @a ) end def Vector.inner_product( x, y ) p = 0 x.a.each_index {|i| p += x.a[i][0] * y.a[i][0]} p end end