# Class: Matrix

Inherits:
Object
show all
Extended by:
ConversionHelper
Includes:
Enumerable, ExceptionForMatrix, CoercionHelper
Defined in:
lib/matrix.rb

## Overview

The Matrix class represents a mathematical matrix. It provides methods for creating matrices, operating on them arithmetically and algebraically, and determining their mathematical properties (trace, rank, inverse, determinant).

## Method Catalogue

To create a matrix:

• Matrix[*rows]

• Matrix.[](*rows)

• Matrix.rows(rows, copy = true)

• Matrix.columns(columns)

• Matrix.build(row_size, column_size, &block)

• Matrix.diagonal(*values)

• Matrix.scalar(n, value)

• Matrix.identity(n)

• Matrix.unit(n)

• Matrix.I(n)

• Matrix.zero(n)

• Matrix.row_vector(row)

• Matrix.column_vector(column)

To access Matrix elements/columns/rows/submatrices/properties:

• [](i, j)

• #row_size

• #column_size

• #row(i)

• #column(j)

• #collect

• #map

• #each

• #each_with_index

• #minor(*param)

Properties of a matrix:

• #empty?

• #real?

• #regular?

• #singular?

• #square?

Matrix arithmetic:

• *(m)

• +(m)

• -(m)

• #/(m)

• #inverse

• #inv

• **

Matrix functions:

• #determinant

• #det

• #rank

• #trace

• #tr

• #transpose

• #t

Complex arithmetic:

• conj

• conjugate

• imag

• imaginary

• real

• rect

• rectangular

Conversion to other data types:

• #coerce(other)

• #row_vectors

• #column_vectors

• #to_a

String representations:

• #to_s

• #inspect

## Defined Under Namespace

Modules: CoercionHelper, ConversionHelper Classes: Scalar

## Constant Summary

### Constants included from Exception2MessageMapper

Exception2MessageMapper::E2MM

## Instance Attribute Summary (collapse)

Returns the number of columns.

## Class Method Summary (collapse)

• Creates a matrix where each argument is a row.

• Creates a matrix of size row_size x column_size.

• Creates a single-column matrix where the values of that column are as given in column.

• Creates a matrix using columns as an array of column vectors.

• Creates a matrix where the diagonal elements are composed of values.

• Creates a empty matrix of row_size x column_size.

• + (Object) identity(n) (also: unit, I)

Creates an n by n identity matrix.

• Creates a single-row matrix where the values of that row are as given in row.

• Creates a matrix where rows is an array of arrays, each of which is a row of the matrix.

• Creates an n by n diagonal matrix where each diagonal element is value.

• Creates an n by n zero matrix.

## Instance Method Summary (collapse)

• Matrix multiplication.

• Matrix exponentiation.

• Matrix subtraction.

• Matrix division (multiplication by the inverse).

• Returns true if and only if the two matrices contain equal elements.

• - (Object) [](i, j) (also: #element, #component)

Returns element (i,j) of the matrix.

• Returns a clone of the matrix, so that the contents of each do not reference identical objects.

• The coerce method provides support for Ruby type coercion.

• - (Object) collect(&block) (also: #map)

Returns a matrix that is the result of iteration of the given block over all elements of the matrix.

• Returns column vector number j of the matrix as a Vector (starting at 0 like an array).

• Returns an array of the column vectors of the matrix.

• - (Object) conjugate (also: #conj)

Returns the conjugate of the matrix.

• - (Object) determinant (also: #det)

Returns the determinant of the matrix.

• - (Object) determinant_e (also: #det_e)

deprecated; use Matrix#determinant.

• Yields all elements of the matrix, starting with those of the first row, or returns an Enumerator is no block given Matrix[ [1,2], [3,4] ].each { |e| puts e } # => prints the numbers 1 to 4.

• Yields all elements of the matrix, starting with those of the first row, along with the row index and column index, or returns an Enumerator is no block given Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col| puts "#e at #row, #col" end # => 1 at 0, 0 # => 2 at 0, 1 # => 3 at 1, 0 # => 4 at 1, 1.

• Returns true if this is an empty matrix, i.e.

• Returns a hash-code for the matrix.

• - (Object) imaginary (also: #imag)

Returns the imaginary part of the matrix.

• constructor

Matrix.new is private; use Matrix.rows, columns, [], etc...

• Overrides Object#inspect.

• - (Object) inverse (also: #inv)

Returns the inverse of the matrix.

• Returns a section of the matrix.

• Returns the rank of the matrix.

• deprecated; use Matrix#rank.

• Returns the real part of the matrix.

• Returns true if all entries of the matrix are real.

• - (Object) rect (also: #rectangular)

Returns an array containing matrices corresponding to the real and imaginary parts of the matrix.

• Returns true if this is a regular (i.e. non-singular) matrix.

• Returns row vector number i of the matrix as a Vector (starting at 0 like an array).

• Returns the number of rows.

• Returns an array of the row vectors of the matrix.

• Returns true is this is a singular matrix.

• Returns true is this is a square matrix.

• Returns an array of arrays that describe the rows of the matrix.

• Overrides Object#to_s.

• - (Object) trace (also: #tr)

Returns the trace (sum of diagonal elements) of the matrix.

• - (Object) transpose (also: #t)

Returns the transpose of the matrix.

#to_set

## Constructor Details

### - (Matrix) initialize(rows, column_size = rows[0].size)

Matrix.new is private; use Matrix.rows, columns, [], etc... to create.

 277 278 279 280 281 282 283 # File 'lib/matrix.rb', line 277 def initialize(rows, column_size = rows[0].size) # No checking is done at this point. rows must be an Array of Arrays. # column_size must be the size of the first row, if there is one, # otherwise it *must* be specified and can be any integer >= 0 @rows = rows @column_size = column_size end

## Instance Attribute Details

### - (Object) column_size(readonly)

Returns the number of columns.

 316 317 318 # File 'lib/matrix.rb', line 316 def column_size @column_size end

## Class Method Details

### + (Object) [](*rows)

Creates a matrix where each argument is a row.

Matrix[ [25, 93], [-1, 66] ]
=>  25 93
-1 66
 120 121 122 # File 'lib/matrix.rb', line 120 def Matrix.[](*rows) Matrix.rows(rows, false) end

### + (Object) build(row_size, column_size = row_size)

Creates a matrix of size row_size x column_size. It fills the values by calling the given block, passing the current row and column. Returns an enumerator if no block is given.

m = Matrix.build(2, 4) {|row, col| col - row }
=> Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
m = Matrix.build(3) { rand }
=> a 3x3 matrix with random elements

Raises:

• (ArgumentError)
 165 166 167 168 169 170 171 172 173 174 175 176 # File 'lib/matrix.rb', line 165 def Matrix.build(row_size, column_size = row_size) row_size = CoercionHelper.coerce_to_int(row_size) column_size = CoercionHelper.coerce_to_int(column_size) raise ArgumentError if row_size < 0 || column_size < 0 return to_enum :build, row_size, column_size unless block_given? rows = row_size.times.map do |i| column_size.times.map do |j| yield i, j end end new rows, column_size end

### + (Object) column_vector(column)

Creates a single-column matrix where the values of that column are as given in column.

Matrix.column_vector([4,5,6])
=> 4
5
6
 249 250 251 252 # File 'lib/matrix.rb', line 249 def Matrix.column_vector(column) column = convert_to_array(column) new [column].transpose, 1 end

### + (Object) columns(columns)

Creates a matrix using columns as an array of column vectors.

Matrix.columns([[25, 93], [-1, 66]])
=>  25 -1
93 66
 150 151 152 # File 'lib/matrix.rb', line 150 def Matrix.columns(columns) Matrix.rows(columns, false).transpose end

### + (Object) diagonal(*values)

Creates a matrix where the diagonal elements are composed of values.

Matrix.diagonal(9, 5, -3)
=>  9  0  0
0  5  0
0  0 -3
 185 186 187 188 189 190 191 192 193 # File 'lib/matrix.rb', line 185 def Matrix.diagonal(*values) size = values.size rows = (0 ... size).collect {|j| row = Array.new(size, 0) row[j] = values[j] row } new rows end

### + (Object) empty(row_size = 0, column_size = 0)

Creates a empty matrix of row_size x column_size. At least one of row_size or column_size must be 0.

m = Matrix.empty(2, 0)
m == Matrix[ [], [] ]
=> true
n = Matrix.empty(0, 3)
n == Matrix.columns([ [], [], [] ])
=> true
m * n
=> Matrix[[0, 0, 0], [0, 0, 0]]
 267 268 269 270 271 272 # File 'lib/matrix.rb', line 267 def Matrix.empty(row_size = 0, column_size = 0) Matrix.Raise ArgumentError, "One size must be 0" if column_size != 0 && row_size != 0 Matrix.Raise ArgumentError, "Negative size" if column_size < 0 || row_size < 0 new([[]]*row_size, column_size) end

### + (Object) identity(n) Also known as: unit, I

Creates an n by n identity matrix.

Matrix.identity(2)
=> 1 0
0 1
 212 213 214 # File 'lib/matrix.rb', line 212 def Matrix.identity(n) Matrix.scalar(n, 1) end

### + (Object) row_vector(row)

Creates a single-row matrix where the values of that row are as given in row.

Matrix.row_vector([4,5,6])
=> 4 5 6
 236 237 238 239 # File 'lib/matrix.rb', line 236 def Matrix.row_vector(row) row = convert_to_array(row) new [row] end

### + (Object) rows(rows, copy = true)

Creates a matrix where rows is an array of arrays, each of which is a row of the matrix. If the optional argument copy is false, use the given arrays as the internal structure of the matrix without copying.

Matrix.rows([[25, 93], [-1, 66]])
=>  25 93
-1 66
 132 133 134 135 136 137 138 139 140 141 142 # File 'lib/matrix.rb', line 132 def Matrix.rows(rows, copy = true) rows = convert_to_array(rows) rows.map! do |row| convert_to_array(row, copy) end size = (rows[0] || []).size rows.each do |row| Matrix.Raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size end new rows, size end

### + (Object) scalar(n, value)

Creates an n by n diagonal matrix where each diagonal element is value.

Matrix.scalar(2, 5)
=> 5 0
0 5
 202 203 204 # File 'lib/matrix.rb', line 202 def Matrix.scalar(n, value) Matrix.diagonal(*Array.new(n, value)) end

### + (Object) zero(n)

Creates an n by n zero matrix.

Matrix.zero(2)
=> 0 0
0 0
 226 227 228 # File 'lib/matrix.rb', line 226 def Matrix.zero(n) Matrix.scalar(n, 0) end

## Instance Method Details

### - (Object) *(m)

Matrix multiplication.

Matrix[[2,4], [6,8]] * Matrix.identity(2)
=> 2 4
6 8
 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 # File 'lib/matrix.rb', line 531 def *(m) # m is matrix or vector or number case(m) when Numeric rows = @rows.collect {|row| row.collect {|e| e * m } } return new_matrix rows, column_size when Vector m = Matrix.column_vector(m) r = self * m return r.column(0) when Matrix Matrix.Raise ErrDimensionMismatch if column_size != m.row_size rows = (0 ... row_size).collect {|i| (0 ... m.column_size).collect {|j| (0 ... column_size).inject(0) do |vij, k| vij + self[i, k] * m[k, j] end } } return new_matrix rows, m.column_size else return apply_through_coercion(m, __method__) end end

### - (Object) **(other)

Matrix exponentiation. Currently implemented for integer powers only. Equivalent to multiplying the matrix by itself N times.

Matrix[[7,6], [3,9]] ** 2
=> 67 96
48 99
 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 # File 'lib/matrix.rb', line 700 def ** (other) case other when Integer x = self if other <= 0 x = self.inverse return Matrix.identity(self.column_size) if other == 0 other = -other end z = nil loop do z = z ? z * x : x if other[0] == 1 return z if (other >>= 1).zero? x *= x end when Float, Rational Matrix.Raise ErrOperationNotImplemented, "**", self.class, other.class else Matrix.Raise ErrOperationNotDefined, "**", self.class, other.class end end

### - (Object) +(m)

Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]]
=>  6  0
-4 12
 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 # File 'lib/matrix.rb', line 566 def +(m) case m when Numeric Matrix.Raise ErrOperationNotDefined, "+", self.class, m.class when Vector m = Matrix.column_vector(m) when Matrix else return apply_through_coercion(m, __method__) end Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size rows = (0 ... row_size).collect {|i| (0 ... column_size).collect {|j| self[i, j] + m[i, j] } } new_matrix rows, column_size end

### - (Object) -(m)

Matrix subtraction.

Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]]
=> -8  2
8  1
 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 # File 'lib/matrix.rb', line 593 def -(m) case m when Numeric Matrix.Raise ErrOperationNotDefined, "-", self.class, m.class when Vector m = Matrix.column_vector(m) when Matrix else return apply_through_coercion(m, __method__) end Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size rows = (0 ... row_size).collect {|i| (0 ... column_size).collect {|j| self[i, j] - m[i, j] } } new_matrix rows, column_size end

### - (Object) /(other)

Matrix division (multiplication by the inverse).

Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]]
=> -7  1
-3 -6
 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 # File 'lib/matrix.rb', line 620 def /(other) case other when Numeric rows = @rows.collect {|row| row.collect {|e| e / other } } return new_matrix rows, column_size when Matrix return self * other.inverse else return apply_through_coercion(other, __method__) end end

### - (Object) ==(other)

Returns true if and only if the two matrices contain equal elements.

 495 496 497 498 # File 'lib/matrix.rb', line 495 def ==(other) return false unless Matrix === other rows == other.rows end

### - (Object) [](i, j) Also known as: element, component

Returns element (i,j) of the matrix. That is: row i, column j.

 293 294 295 # File 'lib/matrix.rb', line 293 def [](i, j) @rows.fetch(i){return nil}[j] end

### - (Object) clone

Returns a clone of the matrix, so that the contents of each do not reference identical objects. There should be no good reason to do this since Matrices are immutable.

 510 511 512 # File 'lib/matrix.rb', line 510 def clone new_matrix @rows.map(&:dup), column_size end

### - (Object) coerce(other)

The coerce method provides support for Ruby type coercion. This coercion mechanism is used by Ruby to handle mixed-type numeric operations: it is intended to find a compatible common type between the two operands of the operator. See also Numeric#coerce.

 967 968 969 970 971 972 973 974 # File 'lib/matrix.rb', line 967 def coerce(other) case other when Numeric return Scalar.new(other), self else raise TypeError, "#{self.class} can't be coerced into #{other.class}" end end

### - (Object) collect(&block) Also known as: map

Returns a matrix that is the result of iteration of the given block over all elements of the matrix.

Matrix[ [1,2], [3,4] ].collect { |e| e**2 }
=> 1  4
9 16
 359 360 361 362 363 # File 'lib/matrix.rb', line 359 def collect(&block) # :yield: e return to_enum(:collect) unless block_given? rows = @rows.collect{|row| row.collect(&block)} new_matrix rows, column_size end

### - (Object) column(j)

Returns column vector number j of the matrix as a Vector (starting at 0 like an array). When a block is given, the elements of that vector are iterated.

 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 # File 'lib/matrix.rb', line 336 def column(j) # :yield: e if block_given? return self if j >= column_size || j < -column_size row_size.times do |i| yield @rows[i][j] end self else return nil if j >= column_size || j < -column_size col = (0 ... row_size).collect {|i| @rows[i][j] } Vector.elements(col, false) end end

### - (Object) column_vectors

Returns an array of the column vectors of the matrix. See Vector.

 988 989 990 991 992 # File 'lib/matrix.rb', line 988 def column_vectors (0 ... column_size).collect {|i| column(i) } end

### - (Object) conjugateAlso known as: conj

Returns the conjugate of the matrix.

Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
=> 1+2i   i  0
1   2  3
Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].conjugate
=> 1-2i  -i  0
1   2  3
 913 914 915 # File 'lib/matrix.rb', line 913 def conjugate collect(&:conjugate) end

### - (Object) determinantAlso known as: det

Returns the determinant of the matrix.

Beware that using Float values can yield erroneous results because of their lack of precision. Consider using exact types like Rational or BigDecimal instead.

Matrix[[7,6], [3,9]].determinant
=> 45
 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 # File 'lib/matrix.rb', line 736 def determinant Matrix.Raise ErrDimensionMismatch unless square? m = @rows case row_size # Up to 4x4, give result using Laplacian expansion by minors. # This will typically be faster, as well as giving good results # in case of Floats when 0 +1 when 1 + m[0][0] when 2 + m[0][0] * m[1][1] - m[0][1] * m[1][0] when 3 m0 = m[0]; m1 = m[1]; m2 = m[2] + m0[0] * m1[1] * m2[2] - m0[0] * m1[2] * m2[1] \ - m0[1] * m1[0] * m2[2] + m0[1] * m1[2] * m2[0] \ + m0[2] * m1[0] * m2[1] - m0[2] * m1[1] * m2[0] when 4 m0 = m[0]; m1 = m[1]; m2 = m[2]; m3 = m[3] + m0[0] * m1[1] * m2[2] * m3[3] - m0[0] * m1[1] * m2[3] * m3[2] \ - m0[0] * m1[2] * m2[1] * m3[3] + m0[0] * m1[2] * m2[3] * m3[1] \ + m0[0] * m1[3] * m2[1] * m3[2] - m0[0] * m1[3] * m2[2] * m3[1] \ - m0[1] * m1[0] * m2[2] * m3[3] + m0[1] * m1[0] * m2[3] * m3[2] \ + m0[1] * m1[2] * m2[0] * m3[3] - m0[1] * m1[2] * m2[3] * m3[0] \ - m0[1] * m1[3] * m2[0] * m3[2] + m0[1] * m1[3] * m2[2] * m3[0] \ + m0[2] * m1[0] * m2[1] * m3[3] - m0[2] * m1[0] * m2[3] * m3[1] \ - m0[2] * m1[1] * m2[0] * m3[3] + m0[2] * m1[1] * m2[3] * m3[0] \ + m0[2] * m1[3] * m2[0] * m3[1] - m0[2] * m1[3] * m2[1] * m3[0] \ - m0[3] * m1[0] * m2[1] * m3[2] + m0[3] * m1[0] * m2[2] * m3[1] \ + m0[3] * m1[1] * m2[0] * m3[2] - m0[3] * m1[1] * m2[2] * m3[0] \ - m0[3] * m1[2] * m2[0] * m3[1] + m0[3] * m1[2] * m2[1] * m3[0] else # For bigger matrices, use an efficient and general algorithm. # Currently, we use the Gauss-Bareiss algorithm determinant_bareiss end end

### - (Object) determinant_eAlso known as: det_e

deprecated; use Matrix#determinant

 818 819 820 821 # File 'lib/matrix.rb', line 818 def determinant_e warn "#{caller(1)[0]}: warning: Matrix#determinant_e is deprecated; use #determinant" rank end

### - (Object) each(&block)

Yields all elements of the matrix, starting with those of the first row, or returns an Enumerator is no block given

Matrix[ [1,2], [3,4] ].each { |e| puts e }
# => prints the numbers 1 to 4
 372 373 374 375 376 377 378 # File 'lib/matrix.rb', line 372 def each(&block) # :yield: e return to_enum(:each) unless block_given? @rows.each do |row| row.each(&block) end self end

### - (Object) each_with_index(&block)

Yields all elements of the matrix, starting with those of the first row, along with the row index and column index, or returns an Enumerator is no block given

Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col|
puts "#{e} at #{row}, #{col}"
end
# => 1 at 0, 0
# => 2 at 0, 1
# => 3 at 1, 0
# => 4 at 1, 1
 392 393 394 395 396 397 398 399 400 # File 'lib/matrix.rb', line 392 def each_with_index(&block) # :yield: e, row, column return to_enum(:each_with_index) unless block_given? @rows.each_with_index do |row, row_index| row.each_with_index do |e, col_index| yield e, row_index, col_index end end self end

### - (Object) elements_to_f

 1001 1002 1003 1004 # File 'lib/matrix.rb', line 1001 def elements_to_f warn "#{caller(1)[0]}: warning: Matrix#elements_to_f is deprecated, use map(&:to_f)" map(&:to_f) end

### - (Object) elements_to_i

 1006 1007 1008 1009 # File 'lib/matrix.rb', line 1006 def elements_to_i warn "#{caller(1)[0]}: warning: Matrix#elements_to_i is deprecated, use map(&:to_i)" map(&:to_i) end

### - (Object) elements_to_r

 1011 1012 1013 1014 # File 'lib/matrix.rb', line 1011 def elements_to_r warn "#{caller(1)[0]}: warning: Matrix#elements_to_r is deprecated, use map(&:to_r)" map(&:to_r) end

### - (Boolean) empty?

Returns true if this is an empty matrix, i.e. if the number of rows or the number of columns is 0.

Returns:

• (Boolean)
 456 457 458 # File 'lib/matrix.rb', line 456 def empty? column_size == 0 || row_size == 0 end

### - (Boolean) eql?(other)

Returns:

• (Boolean)
 500 501 502 503 # File 'lib/matrix.rb', line 500 def eql?(other) return false unless Matrix === other rows.eql? other.rows end

### - (Object) hash

Returns a hash-code for the matrix.

 517 518 519 # File 'lib/matrix.rb', line 517 def hash @rows.hash end

### - (Object) imaginaryAlso known as: imag

Returns the imaginary part of the matrix.

Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
=> 1+2i  i  0
1  2  3
Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].imaginary
=>   2i  i  0
0  0  0
 927 928 929 # File 'lib/matrix.rb', line 927 def imaginary collect(&:imaginary) end

### - (Object) inspect

Overrides Object#inspect

 1036 1037 1038 1039 1040 1041 1042 # File 'lib/matrix.rb', line 1036 def inspect if empty? "Matrix.empty(#{row_size}, #{column_size})" else "Matrix#{@rows.inspect}" end end

### - (Object) inverseAlso known as: inv

Returns the inverse of the matrix.

Matrix[[-1, -1], [0, -1]].inverse
=> -1  1
0 -1
 642 643 644 645 # File 'lib/matrix.rb', line 642 def inverse Matrix.Raise ErrDimensionMismatch unless square? Matrix.I(row_size).send(:inverse_from, self) end

### - (Object) minor(*param)

Returns a section of the matrix. The parameters are either:

• start_row, nrows, start_col, ncols; OR

• row_range, col_range

Matrix.diagonal(9, 5, -3).minor(0..1, 0..2)
=> 9 0 0
0 5 0

Like Array#[], negative indices count backward from the end of the row or column (-1 is the last element). Returns nil if the starting row or column is greater than row_size or column_size respectively.

 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 # File 'lib/matrix.rb', line 415 def minor(*param) case param.size when 2 row_range, col_range = param from_row = row_range.first from_row += row_size if from_row < 0 to_row = row_range.end to_row += row_size if to_row < 0 to_row += 1 unless row_range.exclude_end? size_row = to_row - from_row from_col = col_range.first from_col += column_size if from_col < 0 to_col = col_range.end to_col += column_size if to_col < 0 to_col += 1 unless col_range.exclude_end? size_col = to_col - from_col when 4 from_row, size_row, from_col, size_col = param return nil if size_row < 0 || size_col < 0 from_row += row_size if from_row < 0 from_col += column_size if from_col < 0 else Matrix.Raise ArgumentError, param.inspect end return nil if from_row > row_size || from_col > column_size || from_row < 0 || from_col < 0 rows = @rows[from_row, size_row].collect{|row| row[from_col, size_col] } new_matrix rows, column_size - from_col end

### - (Object) rank

Returns the rank of the matrix. Beware that using Float values can yield erroneous results because of their lack of precision. Consider using exact types like Rational or BigDecimal instead.

Matrix[[7,6], [3,9]].rank
=> 2
 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 # File 'lib/matrix.rb', line 833 def rank # We currently use Bareiss' multistep integer-preserving gaussian elimination # (see comments on determinant) a = to_a last_column = column_size - 1 last_row = row_size - 1 rank = 0 pivot_row = 0 previous_pivot = 1 0.upto(last_column) do |k| switch_row = (pivot_row .. last_row).find {|row| a[row][k] != 0 } if switch_row a[switch_row], a[pivot_row] = a[pivot_row], a[switch_row] unless pivot_row == switch_row pivot = a[pivot_row][k] (pivot_row+1).upto(last_row) do |i| ai = a[i] (k+1).upto(last_column) do |j| ai[j] = (pivot * ai[j] - ai[k] * a[pivot_row][j]) / previous_pivot end end pivot_row += 1 previous_pivot = pivot end end pivot_row end

### - (Object) rank_e

deprecated; use Matrix#rank

 865 866 867 868 # File 'lib/matrix.rb', line 865 def rank_e warn "#{caller(1)[0]}: warning: Matrix#rank_e is deprecated; use #rank" rank end

### - (Object) real

Returns the real part of the matrix.

Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
=> 1+2i  i  0
1  2  3
Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].real
=>    1  0  0
1  2  3
 941 942 943 # File 'lib/matrix.rb', line 941 def real collect(&:real) end

### - (Boolean) real?

Returns true if all entries of the matrix are real.

Returns:

• (Boolean)
 463 464 465 # File 'lib/matrix.rb', line 463 def real? all?(&:real?) end

### - (Object) rectAlso known as: rectangular

Returns an array containing matrices corresponding to the real and imaginary parts of the matrix

m.rect == [m.real, m.imag] # ==> true for all matrices m

 951 952 953 # File 'lib/matrix.rb', line 951 def rect [real, imag] end

### - (Boolean) regular?

Returns true if this is a regular (i.e. non-singular) matrix.

Returns:

• (Boolean)
 470 471 472 # File 'lib/matrix.rb', line 470 def regular? not singular? end

### - (Object) row(i, &block)

Returns row vector number i of the matrix as a Vector (starting at 0 like an array). When a block is given, the elements of that vector are iterated.

 322 323 324 325 326 327 328 329 # File 'lib/matrix.rb', line 322 def row(i, &block) # :yield: e if block_given? @rows.fetch(i){return self}.each(&block) self else Vector.elements(@rows.fetch(i){return nil}) end end

### - (Object) row_size

Returns the number of rows.

 309 310 311 # File 'lib/matrix.rb', line 309 def row_size @rows.size end

### - (Object) row_vectors

Returns an array of the row vectors of the matrix. See Vector.

 979 980 981 982 983 # File 'lib/matrix.rb', line 979 def row_vectors (0 ... row_size).collect {|i| row(i) } end

### - (Boolean) singular?

Returns true is this is a singular matrix.

Returns:

• (Boolean)
 477 478 479 # File 'lib/matrix.rb', line 477 def singular? determinant == 0 end

### - (Boolean) square?

Returns true is this is a square matrix.

Returns:

• (Boolean)
 484 485 486 # File 'lib/matrix.rb', line 484 def square? column_size == row_size end

### - (Object) to_a

Returns an array of arrays that describe the rows of the matrix.

 997 998 999 # File 'lib/matrix.rb', line 997 def to_a @rows.collect{|row| row.dup} end

### - (Object) to_s

Overrides Object#to_s

 1023 1024 1025 1026 1027 1028 1029 1030 1031 # File 'lib/matrix.rb', line 1023 def to_s if empty? "Matrix.empty(#{row_size}, #{column_size})" else "Matrix[" + @rows.collect{|row| "[" + row.collect{|e| e.to_s}.join(", ") + "]" }.join(", ")+"]" end end

### - (Object) traceAlso known as: tr

Returns the trace (sum of diagonal elements) of the matrix.

Matrix[[7,6], [3,9]].trace
=> 16
 876 877 878 879 880 881 # File 'lib/matrix.rb', line 876 def trace Matrix.Raise ErrDimensionMismatch unless square? (0...column_size).inject(0) do |tr, i| tr + @rows[i][i] end end

### - (Object) transposeAlso known as: t

Returns the transpose of the matrix.

Matrix[[1,2], [3,4], [5,6]]
=> 1 2
3 4
5 6
Matrix[[1,2], [3,4], [5,6]].transpose
=> 1 3 5
2 4 6
 894 895 896 897 # File 'lib/matrix.rb', line 894 def transpose return Matrix.empty(column_size, 0) if row_size.zero? new_matrix @rows.transpose, row_size end