Class: KXI::Math::Matrix

Inherits:
Object
  • Object
show all
Defined in:
lib/kxi/math/matrix.rb

Overview

Represents a matrix

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cols) ⇒ Matrix #initialize(cols, rows) ⇒ Matrix

Instantiates the KXI::Math::Matrix class

Overloads:

  • #initialize(cols) ⇒ Matrix

    Creates a square matrix

  • #initialize(cols, rows) ⇒ Matrix

    Creates a matrix



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/kxi/math/matrix.rb', line 34

def initialize(cols, rows = nil)
  rows  = cols if rows == nil
  @data = []
  cols.times do |i|
    if block_given?
      @data[i] = []
      rows.times do |j|
        v = yield(i, j)
        raise(KXI::Exceptions::InvalidTypeException.new(v.type, Numeric)) unless v.is_a?(Numeric)
        @data[i].push(v)
      end
    else
      @data[i] = [0.0] * rows
    end
  end
  @cols = cols
  @rows = rows
end

Class Method Details

.identity(n) ⇒ KXI::Math::Matrix

Returns a square identity matrix



10
11
12
# File 'lib/kxi/math/matrix.rb', line 10

def self.identity(n)
  return KXI::Math::Matrix.new(n, n) { |c, r| c == r ? 1 : 0 }
end

Instance Method Details

#*(other) ⇒ KXI::Math::Matrix #*(other) ⇒ KXI::Math::Matrix #*(other) ⇒ KXI::Math::Vector

Multiplies matrix

Overloads:



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/kxi/math/matrix.rb', line 243

def *(other)
  if other.is_a?(Numeric)
    return KXI::Math::Matrix.new(@cols, @rows) { |c, r| other * get(c, r) }
  elsif other.is_a?(KXI::Math::Matrix)
    return KXI::Math::Matrix.new(other.columns, @rows) do |c, r|
      sum = 0
      @cols.times { |i| sum += get(i, r) * other.get(c, i) }
      next sum
    end
  elsif other.is_a?(KXI::Math::Vector)
    return KXI::Math::Vector.new(@rows) do |d|
      sum = 0
      @cols.times { |c| sum += get(c, d) * other[c] }
      next sum
    end
  else
    raise(KXI::Exceptions::InvalidTypeException.new(other.class, Numeric, KXI::Math::Matrix, KXI::Math::Vector))
  end
end

#==(other) ⇒ Boolean

Compares matrix



266
267
268
269
270
271
272
273
274
# File 'lib/kxi/math/matrix.rb', line 266

def ==(other)
  return false unless other.is_a?(KXI::Math::Matrix)
  return false if @cols != other.columns or @row != other.rows
  @cols.times do |col|
    @rows.times do |row|
      return false if get(col, row) != other.get(col, row)
    end
  end
end

#columnsInteger

Returns the number of columns



22
23
24
# File 'lib/kxi/math/matrix.rb', line 22

def columns
  @cols
end

#determinantNumeric

Computes the determinant of matrix



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/kxi/math/matrix.rb', line 120

def determinant
  return get(0, 0) * get(1, 1) - get(1, 0) * get(0, 1) if @cols == 2
  ci = 0
  cz = 0
  @cols.times do |col|
    zeros = 0
    @rows.times { |row| zeros += 1 if get(col, row) == 0 }
    if zeros > cz
      ci = col
      cz = zeros
    end
  end
  ret = 0
  @rows.times do |row|
    if get(ci, row) != 0
      ret += sign(ci, row) * get(ci, row) * sub(ci, row).determinant
    end
  end
  return ret
end

#each {|col, row, val| ... } ⇒ Object

Iterates over each element of matrix

Yields:

  • (col, row, val)

    Iterator function

Yield Parameters:

  • col (Integer)

    Column passed to iterator

  • row (Integer)

    Row passed to iterator

  • val (Numeric)

    Value of matrix at given column and row



209
210
211
212
213
214
215
# File 'lib/kxi/math/matrix.rb', line 209

def each
  @cols.times do |col|
    @rows.times do |row|
      yield(col, row, @data[col][row])
    end
  end
end

#get(col, row) ⇒ Numeric

Gets the value of matrix at given column and row

Raises:



160
161
162
163
164
# File 'lib/kxi/math/matrix.rb', line 160

def get(col, row)
  raise(KXI::Exceptions::OutOfRangeException.new(col, 0, @cols - 1)) if col < 0 or col >= @cols
  raise(KXI::Exceptions::OutOfRangeException.new(row, 0, @rows - 1)) if row < 0 or row >= @rows
  return @data[col][row]
end

#inverseKXI::Math::Matrix

Computes the inverse of matrix



143
144
145
# File 'lib/kxi/math/matrix.rb', line 143

def inverse
  return (KXI::Math::Matrix.new(@cols, @rows) { |c, r| sign(c, r) * sub(c, r).determinant }).transpose * (1 / determinant)
end

#row_mult(src, cof) ⇒ Matrix #row_mult(src, cof, dst) ⇒ Matrix

Multiplies a row of matrix with specific coefficient

Overloads:



106
107
108
109
110
111
112
# File 'lib/kxi/math/matrix.rb', line 106

def row_mult(src, cof, dst = nil)
  dst = src if dst == nil
  return KXI::Math::Matrix.new(@cols, @rows) do |c, r|
    next get(c, r) + cof * get(c, src) if r == dst
    get(c, r)
  end
end

#row_mult(src, cof) ⇒ Matrix #row_mult(src, cof, dst) ⇒ Matrix

Multiplies a row of matrix with specific coefficient

Overloads:

Raises:



82
83
84
85
86
87
88
89
90
# File 'lib/kxi/math/matrix.rb', line 82

def row_mult!(src, cof, dst = nil)
  dst = src if dst == nil
  raise(KXI::Exceptions::OutOfRangeException.new(src, 0, @rows - 1)) if src < 0 or src >= @rows
  raise(KXI::Exceptions::OutOfRangeException.new(dst, 0, @rows - 1)) if dst < 0 or dst >= @rows
  return KXI::Math::Matrix.new(@cols, @rows) do |c, r|
    next cof * get(c, src) if r == dst
    get(c, r)
  end
end

#row_swap(a, b) ⇒ KXI::Math::Matrix

Swaps two rows of the matrix

Raises:



58
59
60
61
62
63
64
65
66
# File 'lib/kxi/math/matrix.rb', line 58

def row_swap(a, b)
  raise(KXI::Exceptions::OutOfRangeException.new(a, 0, @rows - 1)) if a < 0 or a >= @rows
  raise(KXI::Exceptions::OutOfRangeException.new(b, 0, @rows - 1)) if b < 0 or b >= @rows
  return KXI::Math::Matrix.new(@cols, @rows) do |c, r|
    next get(c, b) if r == a
    next get(c, a) if r == b
    get(c, r)
  end
end

#rowsInteger

Returns the number of rows



16
17
18
# File 'lib/kxi/math/matrix.rb', line 16

def rows
  @rows
end

#set(col, row, val) ⇒ Numeric #set(col, row, val) ⇒ Numeric

Sets the value of vector at specific dimension

Overloads:

Raises:



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/kxi/math/matrix.rb', line 183

def set(col, row, value)
  raise(KXI::Exceptions::OutOfRangeException.new(col, 0, @cols - 1)) if col < 0 or col >= @cols
  raise(KXI::Exceptions::OutOfRangeException.new(row, 0, @rows - 1)) if row < 0 or row >= @rows
  if value.is_a?(Array)
    i = 0
    while i + col < @cols and i < value.length
      j = 0
      while j + row < @rows and j < value[i].length
        @data[col + i][row + j] = value[i][j].to_f
        j                       += 1
      end
      i += 1
    end
  elsif value.is_a?(Numeric)
    @data[col][row] = value.to_f
  else
    raise(KXI::Exceptions::InvalidTypeException.new(value.type, Numeric, Array))
  end
  return value
end

#to_s(d = true) ⇒ String

Converts matrix to string



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/kxi/math/matrix.rb', line 283

def to_s(d = true)
  ret  = ''
  just = [0] * @cols
  each { |c, r, v| d = str(v).length; just[c] = d if d > just[c] }
  @rows.times do |row|
    ret += $/ unless row == 0
    ret += '|' if d
    @cols.times do |col|
      ret += ' ' unless col == 0
      ret += str(get(col, row)).rjust(just[col], ' ')
    end
    ret += '|' if d
  end
  
  return ret
end

#transposeKXI::Math::Matrix

Returns the transpose of matrix



219
220
221
222
223
224
225
# File 'lib/kxi/math/matrix.rb', line 219

def transpose
  ret = KXI::Math::Matrix.new(@rows, @cols)
  each do |col, row, value|
    ret.set(row, col, value)
  end
  return ret
end