Class | Matrix |
In: |
lib/backports/1.9.2/stdlib/matrix.rb
lib/backports/1.9.2/stdlib/matrix/eigenvalue_decomposition.rb lib/backports/1.9.2/stdlib/matrix/lup_decomposition.rb |
Parent: | Object |
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).
To create a matrix:
To access Matrix elements/columns/rows/submatrices/properties:
Properties of a matrix:
Matrix arithmetic:
Matrix functions:
Matrix decompositions:
Complex arithmetic:
Conversion to other data types:
String representations:
SELECTORS | = | {:all => true, :diagonal => true, :off_diagonal => true, :lower => true, :strict_lower => true, :strict_upper => true, :upper => true}.freeze unless const_defined?(:SELECTORS) |
identity | -> | unit |
identity | -> | I |
column_size | [R] | Returns the number of columns. |
rows | [R] | instance creations |
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 185 185: def Matrix.build(row_size, column_size = row_size) 186: row_size = CoercionHelper.coerce_to_int(row_size) 187: column_size = CoercionHelper.coerce_to_int(column_size) 188: raise ArgumentError if row_size < 0 || column_size < 0 189: return to_enum :build, row_size, column_size unless block_given? 190: rows = Array.new(row_size) do |i| 191: Array.new(column_size) do |j| 192: yield i, j 193: end 194: end 195: new rows, column_size 196: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 205 205: def Matrix.diagonal(*values) 206: size = values.size 207: rows = Array.new(size) {|j| 208: row = Array.new(size, 0) 209: row[j] = values[j] 210: row 211: } 212: new rows 213: end
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]]
# File lib/backports/1.9.2/stdlib/matrix.rb, line 288 288: def Matrix.empty(row_size = 0, column_size = 0) 289: Matrix.Raise ArgumentError, "One size must be 0" if column_size != 0 && row_size != 0 290: Matrix.Raise ArgumentError, "Negative size" if column_size < 0 || row_size < 0 291: 292: new([[]]*row_size, column_size) 293: end
Matrix.new is private; use Matrix.rows, columns, [], etc… to create.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 298 298: def initialize(rows, column_size = rows[0].size) 299: # No checking is done at this point. rows must be an Array of Arrays. 300: # column_size must be the size of the first row, if there is one, 301: # otherwise it *must* be specified and can be any integer >= 0 302: @rows = rows 303: @column_size = column_size 304: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 152 152: def Matrix.rows(rows, copy = true) 153: rows = convert_to_array(rows) 154: rows.map! do |row| 155: convert_to_array(row, copy) 156: end 157: size = (rows[0] || []).size 158: rows.each do |row| 159: Matrix.Raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size 160: end 161: new rows, size 162: end
Matrix multiplication.
Matrix[[2,4], [6,8]] * Matrix.identity(2) => 2 4 6 8
# File lib/backports/1.9.2/stdlib/matrix.rb, line 806 806: def *(m) # m is matrix or vector or number 807: case(m) 808: when Numeric 809: rows = @rows.collect {|row| 810: row.collect {|e| e * m } 811: } 812: return new_matrix rows, column_size 813: when Vector 814: m = self.class.column_vector(m) 815: r = self * m 816: return r.column(0) 817: when Matrix 818: Matrix.Raise ErrDimensionMismatch if column_size != m.row_size 819: 820: rows = Array.new(row_size) {|i| 821: Array.new(m.column_size) {|j| 822: (0 ... column_size).inject(0) do |vij, k| 823: vij + self[i, k] * m[k, j] 824: end 825: } 826: } 827: return new_matrix rows, m.column_size 828: else 829: return apply_through_coercion(m, __method__) 830: end 831: end
Matrix exponentiation. Equivalent to multiplying the matrix by itself N times. Non integer exponents will be handled by diagonalizing the matrix.
Matrix[[7,6], [3,9]] ** 2 => 67 96 48 99
# File lib/backports/1.9.2/stdlib/matrix.rb, line 973 973: def ** (other) 974: case other 975: when Integer 976: x = self 977: if other <= 0 978: x = self.inverse 979: return self.class.identity(self.column_size) if other == 0 980: other = -other 981: end 982: z = nil 983: loop do 984: z = z ? z * x : x if other[0] == 1 985: return z if (other >>= 1).zero? 986: x *= x 987: end 988: when Numeric 989: v, d, v_inv = eigensystem 990: v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** other}) * v_inv 991: else 992: Matrix.Raise ErrOperationNotDefined, "**", self.class, other.class 993: end 994: end
Matrix addition.
Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]] => 6 0 -4 12
# File lib/backports/1.9.2/stdlib/matrix.rb, line 839 839: def +(m) 840: case m 841: when Numeric 842: Matrix.Raise ErrOperationNotDefined, "+", self.class, m.class 843: when Vector 844: m = self.class.column_vector(m) 845: when Matrix 846: else 847: return apply_through_coercion(m, __method__) 848: end 849: 850: Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size 851: 852: rows = Array.new(row_size) {|i| 853: Array.new(column_size) {|j| 854: self[i, j] + m[i, j] 855: } 856: } 857: new_matrix rows, column_size 858: end
Matrix subtraction.
Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]] => -8 2 8 1
# File lib/backports/1.9.2/stdlib/matrix.rb, line 866 866: def -(m) 867: case m 868: when Numeric 869: Matrix.Raise ErrOperationNotDefined, "-", self.class, m.class 870: when Vector 871: m = self.class.column_vector(m) 872: when Matrix 873: else 874: return apply_through_coercion(m, __method__) 875: end 876: 877: Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size 878: 879: rows = Array.new(row_size) {|i| 880: Array.new(column_size) {|j| 881: self[i, j] - m[i, j] 882: } 883: } 884: new_matrix rows, column_size 885: end
Matrix division (multiplication by the inverse).
Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]] => -7 1 -3 -6
# File lib/backports/1.9.2/stdlib/matrix.rb, line 893 893: def /(other) 894: case other 895: when Numeric 896: rows = @rows.collect {|row| 897: row.collect {|e| e / other } 898: } 899: return new_matrix rows, column_size 900: when Matrix 901: return self * other.inverse 902: else 903: return apply_through_coercion(other, __method__) 904: end 905: end
Returns true if and only if the two matrices contain equal elements.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 768 768: def ==(other) 769: return false unless Matrix === other && 770: column_size == other.column_size # necessary for empty matrices 771: rows == other.rows 772: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 320 320: def []=(i, j, v) 321: @rows[i][j] = v 322: end
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.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1279 1279: def coerce(other) 1280: case other 1281: when Numeric 1282: return Scalar.new(other), self 1283: else 1284: raise TypeError, "#{self.class} can't be coerced into #{other.class}" 1285: end 1286: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 380 380: def collect(&block) # :yield: e 381: return to_enum(:collect) unless block_given? 382: rows = @rows.collect{|row| row.collect(&block)} 383: new_matrix rows, column_size 384: end
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.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 357 357: def column(j) # :yield: e 358: if block_given? 359: return self if j >= column_size || j < -column_size 360: row_size.times do |i| 361: yield @rows[i][j] 362: end 363: self 364: else 365: return nil if j >= column_size || j < -column_size 366: col = Array.new(row_size) {|i| 367: @rows[i][j] 368: } 369: Vector.elements(col, false) 370: end 371: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1225 1225: def conjugate 1226: collect(&:conjugate) 1227: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1010 1010: def determinant 1011: Matrix.Raise ErrDimensionMismatch unless square? 1012: m = @rows 1013: case row_size 1014: # Up to 4x4, give result using Laplacian expansion by minors. 1015: # This will typically be faster, as well as giving good results 1016: # in case of Floats 1017: when 0 1018: +1 1019: when 1 1020: + m[0][0] 1021: when 2 1022: + m[0][0] * m[1][1] - m[0][1] * m[1][0] 1023: when 3 1024: m0, m1, m2 = m 1025: + m0[0] * m1[1] * m2[2] - m0[0] * m1[2] * m2[1] \ 1026: - m0[1] * m1[0] * m2[2] + m0[1] * m1[2] * m2[0] \ 1027: + m0[2] * m1[0] * m2[1] - m0[2] * m1[1] * m2[0] 1028: when 4 1029: m0, m1, m2, m3 = m 1030: + m0[0] * m1[1] * m2[2] * m3[3] - m0[0] * m1[1] * m2[3] * m3[2] \ 1031: - m0[0] * m1[2] * m2[1] * m3[3] + m0[0] * m1[2] * m2[3] * m3[1] \ 1032: + m0[0] * m1[3] * m2[1] * m3[2] - m0[0] * m1[3] * m2[2] * m3[1] \ 1033: - m0[1] * m1[0] * m2[2] * m3[3] + m0[1] * m1[0] * m2[3] * m3[2] \ 1034: + m0[1] * m1[2] * m2[0] * m3[3] - m0[1] * m1[2] * m2[3] * m3[0] \ 1035: - m0[1] * m1[3] * m2[0] * m3[2] + m0[1] * m1[3] * m2[2] * m3[0] \ 1036: + m0[2] * m1[0] * m2[1] * m3[3] - m0[2] * m1[0] * m2[3] * m3[1] \ 1037: - m0[2] * m1[1] * m2[0] * m3[3] + m0[2] * m1[1] * m2[3] * m3[0] \ 1038: + m0[2] * m1[3] * m2[0] * m3[1] - m0[2] * m1[3] * m2[1] * m3[0] \ 1039: - m0[3] * m1[0] * m2[1] * m3[2] + m0[3] * m1[0] * m2[2] * m3[1] \ 1040: + m0[3] * m1[1] * m2[0] * m3[2] - m0[3] * m1[1] * m2[2] * m3[0] \ 1041: - m0[3] * m1[2] * m2[0] * m3[1] + m0[3] * m1[2] * m2[1] * m3[0] 1042: else 1043: # For bigger matrices, use an efficient and general algorithm. 1044: # Currently, we use the Gauss-Bareiss algorithm 1045: determinant_bareiss 1046: end 1047: end
deprecated; use Matrix#determinant
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1092 1092: def determinant_e 1093: warn "#{caller(1)[0]}: warning: Matrix#determinant_e is deprecated; use #determinant" 1094: rank 1095: end
Yields all elements of the matrix, starting with those of the first row, or returns an Enumerator is no block given. Elements can be restricted by passing an argument:
Matrix[ [1,2], [3,4] ].each { |e| puts e }
# => prints the numbers 1 to 4
# File lib/backports/1.9.2/stdlib/matrix.rb, line 403 403: def each(which = :all) # :yield: e 404: return to_enum :each, which unless block_given? 405: last = column_size - 1 406: case which 407: when :all 408: block = Proc.new 409: @rows.each do |row| 410: row.each(&block) 411: end 412: when :diagonal 413: @rows.each_with_index do |row, row_index| 414: yield row.fetch(row_index){return self} 415: end 416: when :off_diagonal 417: @rows.each_with_index do |row, row_index| 418: column_size.times do |col_index| 419: yield row[col_index] unless row_index == col_index 420: end 421: end 422: when :lower 423: @rows.each_with_index do |row, row_index| 424: 0.upto([row_index, last].min) do |col_index| 425: yield row[col_index] 426: end 427: end 428: when :strict_lower 429: @rows.each_with_index do |row, row_index| 430: [row_index, column_size].min.times do |col_index| 431: yield row[col_index] 432: end 433: end 434: when :strict_upper 435: @rows.each_with_index do |row, row_index| 436: (row_index+1).upto(last) do |col_index| 437: yield row[col_index] 438: end 439: end 440: when :upper 441: @rows.each_with_index do |row, row_index| 442: row_index.upto(last) do |col_index| 443: yield row[col_index] 444: end 445: end 446: else 447: Matrix.Raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" 448: end 449: self 450: end
Same as each, but the row index and column index in addition to the element
Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col| puts "#{e} at #{row}, #{col}" end # => Prints: # 1 at 0, 0 # 2 at 0, 1 # 3 at 1, 0 # 4 at 1, 1
# File lib/backports/1.9.2/stdlib/matrix.rb, line 464 464: def each_with_index(which = :all) # :yield: e, row, column 465: return to_enum :each_with_index, which unless block_given? 466: last = column_size - 1 467: case which 468: when :all 469: @rows.each_with_index do |row, row_index| 470: row.each_with_index do |e, col_index| 471: yield e, row_index, col_index 472: end 473: end 474: when :diagonal 475: @rows.each_with_index do |row, row_index| 476: yield row.fetch(row_index){return self}, row_index, row_index 477: end 478: when :off_diagonal 479: @rows.each_with_index do |row, row_index| 480: column_size.times do |col_index| 481: yield row[col_index], row_index, col_index unless row_index == col_index 482: end 483: end 484: when :lower 485: @rows.each_with_index do |row, row_index| 486: 0.upto([row_index, last].min) do |col_index| 487: yield row[col_index], row_index, col_index 488: end 489: end 490: when :strict_lower 491: @rows.each_with_index do |row, row_index| 492: [row_index, column_size].min.times do |col_index| 493: yield row[col_index], row_index, col_index 494: end 495: end 496: when :strict_upper 497: @rows.each_with_index do |row, row_index| 498: (row_index+1).upto(last) do |col_index| 499: yield row[col_index], row_index, col_index 500: end 501: end 502: when :upper 503: @rows.each_with_index do |row, row_index| 504: row_index.upto(last) do |col_index| 505: yield row[col_index], row_index, col_index 506: end 507: end 508: else 509: Matrix.Raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" 510: end 511: self 512: end
Returns the Eigensystem of the matrix; see EigenvalueDecomposition.
m = Matrix[[1, 2], [3, 4]] v, d, v_inv = m.eigensystem d.diagonal? # => true v.inv == v_inv # => true (v * d * v_inv).round(5) == m # => true
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1191 1191: def eigensystem 1192: EigenvalueDecomposition.new(self) 1193: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1313 1313: def elements_to_f 1314: warn "#{caller(1)[0]}: warning: Matrix#elements_to_f is deprecated, use map(&:to_f)" 1315: map(&:to_f) 1316: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1318 1318: def elements_to_i 1319: warn "#{caller(1)[0]}: warning: Matrix#elements_to_i is deprecated, use map(&:to_i)" 1320: map(&:to_i) 1321: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1323 1323: def elements_to_r 1324: warn "#{caller(1)[0]}: warning: Matrix#elements_to_r is deprecated, use map(&:to_r)" 1325: map(&:to_r) 1326: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 774 774: def eql?(other) 775: return false unless Matrix === other && 776: column_size == other.column_size # necessary for empty matrices 777: rows.eql? other.rows 778: end
Returns true is this is an hermitian matrix. Raises an error if matrix is not square.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 617 617: def hermitian? 618: Matrix.Raise ErrDimensionMismatch unless square? 619: each_with_index(:strict_upper).all? do |e, row, col| 620: e == rows[col][row].conj 621: end 622: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1239 1239: def imaginary 1240: collect(&:imaginary) 1241: end
The index method is specialized to return the index as [row, column] It also accepts an optional selector argument, see each for details.
Matrix[ [1,2], [3,4] ].index(&:even?) # => [0, 1] Matrix[ [1,1], [1,1] ].index(1, :strict_lower) # => [1, 0]
# File lib/backports/1.9.2/stdlib/matrix.rb, line 527 527: def index(*args) 528: raise ArgumentError, "wrong number of arguments(#{args.size} for 0-2)" if args.size > 2 529: which = (args.size == 2 || SELECTORS.include?(args.last)) ? args.pop : :all 530: return to_enum :find_index, which, *args unless block_given? || args.size == 1 531: if args.size == 1 532: value = args.first 533: each_with_index(which) do |e, row_index, col_index| 534: return row_index, col_index if e == value 535: end 536: else 537: each_with_index(which) do |e, row_index, col_index| 538: return row_index, col_index if yield e 539: end 540: end 541: nil 542: end
Overrides Object#inspect
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1348 1348: def inspect 1349: if empty? 1350: "#{self.class}.empty(#{row_size}, #{column_size})" 1351: else 1352: "#{self.class}#{@rows.inspect}" 1353: end 1354: end
Returns true is this is a lower triangular matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 627 627: def lower_triangular? 628: each(:strict_upper).all?(&:zero?) 629: end
Returns the LUP decomposition of the matrix; see LUPDecomposition.
a = Matrix[[1, 2], [3, 4]] l, u, p = a.lup l.lower_triangular? # => true u.upper_triangular? # => true p.permutation? # => true l * u == a * p # => true a.lup.solve([2, 5]) # => Vector[(1/1), (1/2)]
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1206 1206: def lup 1207: LUPDecomposition.new(self) 1208: end
Returns a section of the matrix. The parameters are either:
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.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 557 557: def minor(*param) 558: case param.size 559: when 2 560: row_range, col_range = param 561: from_row = row_range.first 562: from_row += row_size if from_row < 0 563: to_row = row_range.end 564: to_row += row_size if to_row < 0 565: to_row += 1 unless row_range.exclude_end? 566: size_row = to_row - from_row 567: 568: from_col = col_range.first 569: from_col += column_size if from_col < 0 570: to_col = col_range.end 571: to_col += column_size if to_col < 0 572: to_col += 1 unless col_range.exclude_end? 573: size_col = to_col - from_col 574: when 4 575: from_row, size_row, from_col, size_col = param 576: return nil if size_row < 0 || size_col < 0 577: from_row += row_size if from_row < 0 578: from_col += column_size if from_col < 0 579: else 580: Matrix.Raise ArgumentError, param.inspect 581: end 582: 583: return nil if from_row > row_size || from_col > column_size || from_row < 0 || from_col < 0 584: rows = @rows[from_row, size_row].collect{|row| 585: row[from_col, size_col] 586: } 587: new_matrix rows, [column_size - from_col, size_col].min 588: end
Returns true is this is a normal matrix. Raises an error if matrix is not square.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 635 635: def normal? 636: Matrix.Raise ErrDimensionMismatch unless square? 637: rows.each_with_index do |row_i, i| 638: rows.each_with_index do |row_j, j| 639: s = 0 640: rows.each_with_index do |row_k, k| 641: s += row_i[k] * row_j[k].conj - row_k[i].conj * row_k[j] 642: end 643: return false unless s == 0 644: end 645: end 646: true 647: end
Returns true is this is an orthogonal matrix Raises an error if matrix is not square.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 653 653: def orthogonal? 654: Matrix.Raise ErrDimensionMismatch unless square? 655: rows.each_with_index do |row, i| 656: column_size.times do |j| 657: s = 0 658: row_size.times do |k| 659: s += row[k] * rows[k][j] 660: end 661: return false unless s == (i == j ? 1 : 0) 662: end 663: end 664: true 665: end
Returns true is this is a permutation matrix Raises an error if matrix is not square.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 671 671: def permutation? 672: Matrix.Raise ErrDimensionMismatch unless square? 673: cols = Array.new(column_size) 674: rows.each_with_index do |row, i| 675: found = false 676: row.each_with_index do |e, j| 677: if e == 1 678: return false if found || cols[j] 679: found = cols[j] = true 680: elsif e != 0 681: return false 682: end 683: end 684: return false unless found 685: end 686: true 687: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1107 1107: def rank 1108: # We currently use Bareiss' multistep integer-preserving gaussian elimination 1109: # (see comments on determinant) 1110: a = to_a 1111: last_column = column_size - 1 1112: last_row = row_size - 1 1113: pivot_row = 0 1114: previous_pivot = 1 1115: 0.upto(last_column) do |k| 1116: switch_row = (pivot_row .. last_row).find {|row| 1117: a[row][k] != 0 1118: } 1119: if switch_row 1120: a[switch_row], a[pivot_row] = a[pivot_row], a[switch_row] unless pivot_row == switch_row 1121: pivot = a[pivot_row][k] 1122: (pivot_row+1).upto(last_row) do |i| 1123: ai = a[i] 1124: (k+1).upto(last_column) do |j| 1125: ai[j] = (pivot * ai[j] - ai[k] * a[pivot_row][j]) / previous_pivot 1126: end 1127: end 1128: pivot_row += 1 1129: previous_pivot = pivot 1130: end 1131: end 1132: pivot_row 1133: end
deprecated; use Matrix#rank
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1138 1138: def rank_e 1139: warn "#{caller(1)[0]}: warning: Matrix#rank_e is deprecated; use #rank" 1140: rank 1141: end
Returns true if this is a regular (i.e. non-singular) matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 699 699: def regular? 700: not singular? 701: end
Returns a matrix with entries rounded to the given precision (see Float#round)
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1146 1146: def round(ndigits=0) 1147: map{|e| e.round(ndigits)} 1148: end
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.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 343 343: def row(i, &block) # :yield: e 344: if block_given? 345: @rows.fetch(i){return self}.each(&block) 346: self 347: else 348: Vector.elements(@rows.fetch(i){return nil}) 349: end 350: end
Returns true is this is a singular matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 706 706: def singular? 707: determinant == 0 708: end
Returns true is this is a square matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 713 713: def square? 714: column_size == row_size 715: end
Returns true is this is a symmetric matrix. Raises an error if matrix is not square.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 721 721: def symmetric? 722: Matrix.Raise ErrDimensionMismatch unless square? 723: each_with_index(:strict_upper) do |e, row, col| 724: return false if e != rows[col][row] 725: end 726: true 727: end
Overrides Object#to_s
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1335 1335: def to_s 1336: if empty? 1337: "#{self.class}.empty(#{row_size}, #{column_size})" 1338: else 1339: "#{self.class}[" + @rows.collect{|row| 1340: "[" + row.collect{|e| e.to_s}.join(", ") + "]" 1341: }.join(", ")+"]" 1342: end 1343: end
Returns the trace (sum of diagonal elements) of the matrix.
Matrix[[7,6], [3,9]].trace => 16
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1155 1155: def trace 1156: Matrix.Raise ErrDimensionMismatch unless square? 1157: (0...column_size).inject(0) do |tr, i| 1158: tr + @rows[i][i] 1159: end 1160: end
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
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1173 1173: def transpose 1174: return self.class.empty(column_size, 0) if row_size.zero? 1175: new_matrix @rows.transpose, row_size 1176: end
Returns true is this is a unitary matrix Raises an error if matrix is not square.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 733 733: def unitary? 734: Matrix.Raise ErrDimensionMismatch unless square? 735: rows.each_with_index do |row, i| 736: column_size.times do |j| 737: s = 0 738: row_size.times do |k| 739: s += row[k].conj * rows[k][j] 740: end 741: return false unless s == (i == j ? 1 : 0) 742: end 743: end 744: true 745: end