This documentation is automatically generated by online-judge-tools/verification-helper
class Matrix(T)
include Indexable(Array(T))
def Matrix.identity(size : Int32) : self
result = Matrix(T).new(size, size, T.zero)
(0...size).each do |i|
result[i][i] = T.new(1)
end
result
end
macro [](*rows)
Matrix.new [{{rows.splat}}]
end
getter height : Int32, width : Int32, data : Array(Array(T))
def initialize
@height = 0
@width = 0
@data = Array(Array(T)).new
end
def initialize(@height, @width, value : T)
raise ArgumentError.new("Negative matrix height: #{@height}") unless @height >= 0
raise ArgumentError.new("Negative matrix width: #{@width}") unless @width >= 0
@data = Array.new(height) { Array(T).new(width, value) }
end
def initialize(@height, @width, &block : Int32, Int32 -> T)
raise ArgumentError.new("Negative matrix height: #{@height}") unless @height >= 0
raise ArgumentError.new("Negative matrix width: #{@width}") unless @width >= 0
@data = Array.new(height) { |i| Array.new(width) { |j| yield i, j } }
end
def initialize(@data : Array(Array(T)))
@height = @data.size
@width = @data[0].size
raise ArgumentError.new unless @data.all? { |a| a.size == width }
end
def self.from(*rows) : self
Matrix(T).new rows.map { |row|
row.map { |value| T.new(value) }.to_a
}.to_a
end
def size : Int32
@data.size
end
def unsafe_fetch(index : Int) : Array(T)
@data.unsafe_fetch(index)
end
private def check_index_out_of_bounds(i, j)
check_index_out_of_bounds(i, j) { raise IndexError.new }
end
private def check_index_out_of_bounds(i, j)
i += height if i < 0
j += width if j < 0
if 0 <= i < height && 0 <= j < width
{i, j}
else
yield
end
end
def fetch(i : Int, j : Int, &)
i, j = check_index_out_of_bounds(i, j) { return yield i, j }
unsafe_fetch(i, j)
end
def fetch(i : Int, j : Int, default)
fetch(i, j) { default }
end
def [](i : Int, j : Int) : T
fetch(i, j) { raise IndexError.new }
end
def []?(i : Int, j : Int) : T?
fetch(i, j, nil)
end
def unsafe_fetch(i : Int, j : Int) : T
@data.unsafe_fetch(i).unsafe_fetch(j)
end
def +(other : self) : self
raise IndexError.new unless height == other.height && width == other.width
Matrix(T).new(height, width) { |i, j|
unsafe_fetch(i, j) + other.unsafe_fetch(i, j)
}
end
def -(other : self) : self
raise IndexError.new unless height == other.height && width == other.width
Matrix(T).new(height, width) { |i, j|
unsafe_fetch(i, j) - other.unsafe_fetch(i, j)
}
end
def *(other : self) : self
raise IndexError.new unless width == other.height
Matrix(T).new(height, other.width) { |i, j|
(0...width).sum { |k| unsafe_fetch(i, k) * other.unsafe_fetch(k, j) }
}
end
def **(k : Int) : self
result = Matrix(T).identity(height)
memo = Matrix.new(data)
while k > 0
result *= memo if k.odd?
memo *= memo
k >>= 1
end
result
end
def ==(other : Matrix) : Bool
return false unless height == other.height && width == other.width
data == other.data
end
def to_s(io) : Nil
io << data
end
def inspect(io) : Nil
io << "Matrix" << data
end
end
class Matrix(T)
include Indexable(Array(T))
def Matrix.identity(size : Int32) : self
result = Matrix(T).new(size, size, T.zero)
(0...size).each do |i|
result[i][i] = T.new(1)
end
result
end
macro [](*rows)
Matrix.new [{{rows.splat}}]
end
getter height : Int32, width : Int32, data : Array(Array(T))
def initialize
@height = 0
@width = 0
@data = Array(Array(T)).new
end
def initialize(@height, @width, value : T)
raise ArgumentError.new("Negative matrix height: #{@height}") unless @height >= 0
raise ArgumentError.new("Negative matrix width: #{@width}") unless @width >= 0
@data = Array.new(height) { Array(T).new(width, value) }
end
def initialize(@height, @width, &block : Int32, Int32 -> T)
raise ArgumentError.new("Negative matrix height: #{@height}") unless @height >= 0
raise ArgumentError.new("Negative matrix width: #{@width}") unless @width >= 0
@data = Array.new(height) { |i| Array.new(width) { |j| yield i, j } }
end
def initialize(@data : Array(Array(T)))
@height = @data.size
@width = @data[0].size
raise ArgumentError.new unless @data.all? { |a| a.size == width }
end
def self.from(*rows) : self
Matrix(T).new rows.map { |row|
row.map { |value| T.new(value) }.to_a
}.to_a
end
def size : Int32
@data.size
end
def unsafe_fetch(index : Int) : Array(T)
@data.unsafe_fetch(index)
end
private def check_index_out_of_bounds(i, j)
check_index_out_of_bounds(i, j) { raise IndexError.new }
end
private def check_index_out_of_bounds(i, j)
i += height if i < 0
j += width if j < 0
if 0 <= i < height && 0 <= j < width
{i, j}
else
yield
end
end
def fetch(i : Int, j : Int, &)
i, j = check_index_out_of_bounds(i, j) { return yield i, j }
unsafe_fetch(i, j)
end
def fetch(i : Int, j : Int, default)
fetch(i, j) { default }
end
def [](i : Int, j : Int) : T
fetch(i, j) { raise IndexError.new }
end
def []?(i : Int, j : Int) : T?
fetch(i, j, nil)
end
def unsafe_fetch(i : Int, j : Int) : T
@data.unsafe_fetch(i).unsafe_fetch(j)
end
def +(other : self) : self
raise IndexError.new unless height == other.height && width == other.width
Matrix(T).new(height, width) { |i, j|
unsafe_fetch(i, j) + other.unsafe_fetch(i, j)
}
end
def -(other : self) : self
raise IndexError.new unless height == other.height && width == other.width
Matrix(T).new(height, width) { |i, j|
unsafe_fetch(i, j) - other.unsafe_fetch(i, j)
}
end
def *(other : self) : self
raise IndexError.new unless width == other.height
Matrix(T).new(height, other.width) { |i, j|
(0...width).sum { |k| unsafe_fetch(i, k) * other.unsafe_fetch(k, j) }
}
end
def **(k : Int) : self
result = Matrix(T).identity(height)
memo = Matrix.new(data)
while k > 0
result *= memo if k.odd?
memo *= memo
k >>= 1
end
result
end
def ==(other : Matrix) : Bool
return false unless height == other.height && width == other.width
data == other.data
end
def to_s(io) : Nil
io << data
end
def inspect(io) : Nil
io << "Matrix" << data
end
end