class KXI::Math::Matrix

Represents a matrix

Public Class Methods

identity(n) click to toggle source

Returns a square identity matrix @param [Integer] n Dimension of matrix @return [KXI::Math::Matrix] Square identity matrix of given dimension

# 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
new(cols, rows = nil) { |i, j| ... } click to toggle source

Instantiates the {KXI::Math::Matrix} class @overload initialize(cols)

Creates a square matrix
@param [Integer] cols Dimension of matrix

@overload initialize(cols, rows)

Creates a matrix
@param [Integer] cols Number of columns in the matrix
@param [Integer] rows Number of rows in the matrix
# 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

Public Instance Methods

*(other) click to toggle source

Multiplies matrix @overload *(other)

Scales matrix
@param [Numeric] other Scalar to multiply with
@raise [KXI::Exceptions::InvalidTypeException] When value is of invalid type
@return [KXI::Math::Matrix] Scaled matrix

@overload *(other)

Multiplies matrix by another matrix
@param [KXI::Math::Matrix] other Right-side matrix to multiply with
@raise [KXI::Exceptions::InvalidTypeException] When value is of invalid type
@return [KXI::Math::Matrix] Multiplied matrix

@overload *(other)

Multiplies matrix by vector
@param [KXI::Math::Vector] other Vector to multiply with
@raise [KXI::Exceptions::InvalidTypeException] When value is of invalid type
@return [KXI::Math::Vector] Result of multiplication
# 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) click to toggle source

Compares matrix @param [void] other Value to compare to @return [Boolean] True if matrix is equivalent to given value; false otherwise

# 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
columns() click to toggle source

Returns the number of columns @return [Integer] Number of columns

# File lib/kxi/math/matrix.rb, line 22
def columns
        @cols
end
determinant() click to toggle source

Computes the determinant of matrix @return [Numeric] Determinant of matrix

# 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, data[row]| ... } click to toggle source

Iterates over each element of matrix @yield [col, row, val] Iterator function @yieldparam [Integer] col Column passed to iterator @yieldparam [Integer] row Row passed to iterator @yieldparam [Numeric] val Value of matrix at given column and row

# 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) click to toggle source

Gets the value of matrix at given column and row @param [Integer] col Column to get @param [Integer] row Row to get @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range @return [Numeric] Value of matrix at given column and row

# 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
inverse() click to toggle source

Computes the inverse of matrix @return [KXI::Math::Matrix] Inverse matrix

# 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, dst = nil) click to toggle source

Multiplies a row of matrix with specific coefficient @overload row_mult(src, cof)

Multiplies a row by coefficient and adds that to the row
@param [Integer] src Row to multiply
@param [Numeric] cof Coefficient to multiply with
        @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
@return [Matrix] New matrix with multiplied row

@overload row_mult(src, cof, dst)

Multiplies a row by coefficient and adds that to other row
@param [Integer] src Row to multiply
@param [Numeric] cof Coefficient to multiply with
@param [Numeric] dst Row to write the results of multiplication
        @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
@return [Matrix] New matrix with multiplied row
# 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, dst = nil) click to toggle source

Multiplies a row of matrix with specific coefficient @overload row_mult(src, cof)

Multiplies a row by coefficient into that row
@param [Integer] src Row to multiply
@param [Numeric] cof Coefficient to multiply with
        @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
@return [Matrix] New matrix with multiplied row

@overload row_mult(src, cof, dst)

Multiplies a row by coefficient into other row
@param [Integer] src Row to multiply
@param [Numeric] cof Coefficient to multiply with
@param [Numeric] dst Row to write the results of multiplication
        @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
@return [Matrix] New matrix with multiplied row
# 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) click to toggle source

Swaps two rows of the matrix @param [Integer] a First row to swap @param [Integer] b Second row to swap with @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range @return [KXI::Math::Matrix] New matrix with swapped rows

# 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
rows() click to toggle source

Returns the number of rows @return [Integer] Number of rows

# File lib/kxi/math/matrix.rb, line 16
def rows
        @rows
end
set(col, row, value) click to toggle source

Sets the value of vector at specific dimension @overload set(col, row, val)

Sets the value of vector at specific dimension
@param [Integer] col Column to set
@param [Integer] row Row to set
@param [Integer] val Value to set the matrix to
@raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
@raise [KXI::Exceptions::InvalidTypeException] When value has invalid type
@return [Numeric] Value passed to function

@overload set(col, row, val)

Sets the values of vector to range of values starting from specific dimension
@param [Integer] col Column to set
@param [Integer] row Row to set
@param [Array] val Values to set the matrix to
@raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
@raise [KXI::Exceptions::InvalidTypeException] When value has invalid type
@return [Numeric] Value passed to function
# 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) click to toggle source

Converts matrix to string @param [Boolean] d Determines whether string should be decorated @return [String] String representation of matrix

# 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
transpose() click to toggle source

Returns the transpose of matrix @return [KXI::Math::Matrix] Transposed matrix

# 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

Private Instance Methods

sign(col, row) click to toggle source
# File lib/kxi/math/matrix.rb, line 114
def sign(col, row)
        return ((col % 2 == 0) == (row % 2 == 0)) ? 1 : -1
end
str(num) click to toggle source
# File lib/kxi/math/matrix.rb, line 276
def str(num)
        return (num == num.to_i ? num.to_i : num).to_s
end
sub(col, row) click to toggle source
# File lib/kxi/math/matrix.rb, line 147
def sub(col, row)
        return KXI::Math::Matrix.new(@cols - 1, @rows - 1) do |c, r|
                c = c + 1 if c >= col
                r = r + 1 if r >= row
                next get(c, r)
        end
end