mmcs-ruby/silicium

View on GitHub
lib/silicium/multi.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
module Silicium
  module Sparse
    # here goes tha addition to SparseMatrix class
    class SparseMatrix
      ##
      # @param [Integer] pos - Position of a row to return
      # @raise [ArgumentError] if position was less or bigger than count of cols
      # @return [Array] The array contains elements of row
      #
      # Returns a row of sparse matrix by its position
      def get_row(pos)
        get_dimension({dimension: 0, position: 1}, pos)
      end

      ##
      # @param [Integer] pos - Position of a column to return
      # @raise [ArgumentError] if position was less or bigger than count of rows
      # @return [Array] The array that contains elements of column
      #
      # Returns a column of sparse matrix by its position
      def get_col(pos)
        get_dimension({dimension: 1, position: 0}, pos)
      end

      ##
      # @return [Array] The array that contains rows of matrix
      # Returns sparse matrix in its regular view
      def regular_view
        Array.new(@n) { |i| get_row(i) }
      end

      ##
      # @param [SparseMatrix::Object] matrix - A matrix to multiply to
      # @raise [ArgumentError] if count of columns of right matrix
      # doesn't match count of rows of left matrix
      #
      # Returns a matrix in its regular view but multiplied by other matrix
      def multiply(matrix)
        raise 'wrong argument' if @n != matrix.m

        rows = regular_view
        result = Array.new(@n) { Array.new }
        (0...@n).each { |i|
          (0...matrix.m).each { |j|
            result[i] << matrix
                             .get_col(j)
                             .zip(rows[i])
                             .inject(0) { |acc, current| acc + current[0] * current[1] }
          }
        }
        result
      end

      ##
      # @param [Integer] num - A number to multiply to
      #
      # Multiplies matrix by a number
      def mult_by_num(num)
        return SparseMatrix.new(@n, @m) if num.zero?

        res = copy
        res.triplets.each do |triplet|
          triplet[2] *= num
        end
        res
      end

      private

      def get_dimension(selector, pos)
        raise 'wrong argument' if pos.negative? || pos > @m

        result = Array.new(@m, 0)
        @triplets
            .select { |triplet| triplet[selector[:dimension]] == pos }
            .each { |triplet| result[triplet[selector[:position]]] = triplet[2] }
        result
      end

    end
  end
end