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 |
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 187 187: def Matrix.build(row_size, column_size = row_size) 188: row_size = CoercionHelper.coerce_to_int(row_size) 189: column_size = CoercionHelper.coerce_to_int(column_size) 190: raise ArgumentError if row_size < 0 || column_size < 0 191: return to_enum :build, row_size, column_size unless block_given? 192: rows = Array.new(row_size) do |i| 193: Array.new(column_size) do |j| 194: yield i, j 195: end 196: end 197: new rows, column_size 198: 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 207 207: def Matrix.diagonal(*values) 208: size = values.size 209: rows = Array.new(size) {|j| 210: row = Array.new(size, 0) 211: row[j] = values[j] 212: row 213: } 214: new rows 215: 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 290 290: def Matrix.empty(row_size = 0, column_size = 0) 291: Matrix.Raise ArgumentError, "One size must be 0" if column_size != 0 && row_size != 0 292: Matrix.Raise ArgumentError, "Negative size" if column_size < 0 || row_size < 0 293: 294: new([[]]*row_size, column_size) 295: end
Matrix.new is private; use Matrix.rows, columns, [], etc… to create.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 300 300: def initialize(rows, column_size = rows[0].size) 301: # No checking is done at this point. rows must be an Array of Arrays. 302: # column_size must be the size of the first row, if there is one, 303: # otherwise it *must* be specified and can be any integer >= 0 304: @rows = rows 305: @column_size = column_size 306: 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 154 154: def Matrix.rows(rows, copy = true) 155: rows = convert_to_array(rows) 156: rows.map! do |row| 157: convert_to_array(row, copy) 158: end 159: size = (rows[0] || []).size 160: rows.each do |row| 161: Matrix.Raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size 162: end 163: new rows, size 164: 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 808 808: def *(m) # m is matrix or vector or number 809: case(m) 810: when Numeric 811: rows = @rows.collect {|row| 812: row.collect {|e| e * m } 813: } 814: return new_matrix rows, column_size 815: when Vector 816: m = self.class.column_vector(m) 817: r = self * m 818: return r.column(0) 819: when Matrix 820: Matrix.Raise ErrDimensionMismatch if column_size != m.row_size 821: 822: rows = Array.new(row_size) {|i| 823: Array.new(m.column_size) {|j| 824: (0 ... column_size).inject(0) do |vij, k| 825: vij + self[i, k] * m[k, j] 826: end 827: } 828: } 829: return new_matrix rows, m.column_size 830: else 831: return apply_through_coercion(m, __method__) 832: end 833: 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 975 975: def ** (other) 976: case other 977: when Integer 978: x = self 979: if other <= 0 980: x = self.inverse 981: return self.class.identity(self.column_size) if other == 0 982: other = -other 983: end 984: z = nil 985: loop do 986: z = z ? z * x : x if other[0] == 1 987: return z if (other >>= 1).zero? 988: x *= x 989: end 990: when Numeric 991: v, d, v_inv = eigensystem 992: v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** other}) * v_inv 993: else 994: Matrix.Raise ErrOperationNotDefined, "**", self.class, other.class 995: end 996: 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 841 841: def +(m) 842: case m 843: when Numeric 844: Matrix.Raise ErrOperationNotDefined, "+", self.class, m.class 845: when Vector 846: m = self.class.column_vector(m) 847: when Matrix 848: else 849: return apply_through_coercion(m, __method__) 850: end 851: 852: Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size 853: 854: rows = Array.new(row_size) {|i| 855: Array.new(column_size) {|j| 856: self[i, j] + m[i, j] 857: } 858: } 859: new_matrix rows, column_size 860: 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 868 868: def -(m) 869: case m 870: when Numeric 871: Matrix.Raise ErrOperationNotDefined, "-", self.class, m.class 872: when Vector 873: m = self.class.column_vector(m) 874: when Matrix 875: else 876: return apply_through_coercion(m, __method__) 877: end 878: 879: Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size 880: 881: rows = Array.new(row_size) {|i| 882: Array.new(column_size) {|j| 883: self[i, j] - m[i, j] 884: } 885: } 886: new_matrix rows, column_size 887: 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 895 895: def /(other) 896: case other 897: when Numeric 898: rows = @rows.collect {|row| 899: row.collect {|e| e / other } 900: } 901: return new_matrix rows, column_size 902: when Matrix 903: return self * other.inverse 904: else 905: return apply_through_coercion(other, __method__) 906: end 907: end
Returns true if and only if the two matrices contain equal elements.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 770 770: def ==(other) 771: return false unless Matrix === other && 772: column_size == other.column_size # necessary for empty matrices 773: rows == other.rows 774: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 322 322: def []=(i, j, v) 323: @rows[i][j] = v 324: 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 1281 1281: def coerce(other) 1282: case other 1283: when Numeric 1284: return Scalar.new(other), self 1285: else 1286: raise TypeError, "#{self.class} can't be coerced into #{other.class}" 1287: end 1288: 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 382 382: def collect(&block) # :yield: e 383: return to_enum(:collect) unless block_given? 384: rows = @rows.collect{|row| row.collect(&block)} 385: new_matrix rows, column_size 386: 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 359 359: def column(j) # :yield: e 360: if block_given? 361: return self if j >= column_size || j < -column_size 362: row_size.times do |i| 363: yield @rows[i][j] 364: end 365: self 366: else 367: return nil if j >= column_size || j < -column_size 368: col = Array.new(row_size) {|i| 369: @rows[i][j] 370: } 371: Vector.elements(col, false) 372: end 373: 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 1227 1227: def conjugate 1228: collect(&:conjugate) 1229: 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 1012 1012: def determinant 1013: Matrix.Raise ErrDimensionMismatch unless square? 1014: m = @rows 1015: case row_size 1016: # Up to 4x4, give result using Laplacian expansion by minors. 1017: # This will typically be faster, as well as giving good results 1018: # in case of Floats 1019: when 0 1020: +1 1021: when 1 1022: + m[0][0] 1023: when 2 1024: + m[0][0] * m[1][1] - m[0][1] * m[1][0] 1025: when 3 1026: m0, m1, m2 = m 1027: + m0[0] * m1[1] * m2[2] - m0[0] * m1[2] * m2[1] \ 1028: - m0[1] * m1[0] * m2[2] + m0[1] * m1[2] * m2[0] \ 1029: + m0[2] * m1[0] * m2[1] - m0[2] * m1[1] * m2[0] 1030: when 4 1031: m0, m1, m2, m3 = m 1032: + m0[0] * m1[1] * m2[2] * m3[3] - m0[0] * m1[1] * m2[3] * m3[2] \ 1033: - m0[0] * m1[2] * m2[1] * m3[3] + m0[0] * m1[2] * m2[3] * m3[1] \ 1034: + m0[0] * m1[3] * m2[1] * m3[2] - m0[0] * m1[3] * m2[2] * m3[1] \ 1035: - m0[1] * m1[0] * m2[2] * m3[3] + m0[1] * m1[0] * m2[3] * m3[2] \ 1036: + m0[1] * m1[2] * m2[0] * m3[3] - m0[1] * m1[2] * m2[3] * m3[0] \ 1037: - m0[1] * m1[3] * m2[0] * m3[2] + m0[1] * m1[3] * m2[2] * m3[0] \ 1038: + m0[2] * m1[0] * m2[1] * m3[3] - m0[2] * m1[0] * m2[3] * m3[1] \ 1039: - m0[2] * m1[1] * m2[0] * m3[3] + m0[2] * m1[1] * m2[3] * m3[0] \ 1040: + m0[2] * m1[3] * m2[0] * m3[1] - m0[2] * m1[3] * m2[1] * m3[0] \ 1041: - m0[3] * m1[0] * m2[1] * m3[2] + m0[3] * m1[0] * m2[2] * m3[1] \ 1042: + m0[3] * m1[1] * m2[0] * m3[2] - m0[3] * m1[1] * m2[2] * m3[0] \ 1043: - m0[3] * m1[2] * m2[0] * m3[1] + m0[3] * m1[2] * m2[1] * m3[0] 1044: else 1045: # For bigger matrices, use an efficient and general algorithm. 1046: # Currently, we use the Gauss-Bareiss algorithm 1047: determinant_bareiss 1048: end 1049: end
deprecated; use Matrix#determinant
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1094 1094: def determinant_e 1095: warn "#{caller(1)[0]}: warning: Matrix#determinant_e is deprecated; use #determinant" 1096: rank 1097: 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 405 405: def each(which = :all) # :yield: e 406: return to_enum :each, which unless block_given? 407: last = column_size - 1 408: case which 409: when :all 410: block = Proc.new 411: @rows.each do |row| 412: row.each(&block) 413: end 414: when :diagonal 415: @rows.each_with_index do |row, row_index| 416: yield row.fetch(row_index){return self} 417: end 418: when :off_diagonal 419: @rows.each_with_index do |row, row_index| 420: column_size.times do |col_index| 421: yield row[col_index] unless row_index == col_index 422: end 423: end 424: when :lower 425: @rows.each_with_index do |row, row_index| 426: 0.upto([row_index, last].min) do |col_index| 427: yield row[col_index] 428: end 429: end 430: when :strict_lower 431: @rows.each_with_index do |row, row_index| 432: [row_index, column_size].min.times do |col_index| 433: yield row[col_index] 434: end 435: end 436: when :strict_upper 437: @rows.each_with_index do |row, row_index| 438: (row_index+1).upto(last) do |col_index| 439: yield row[col_index] 440: end 441: end 442: when :upper 443: @rows.each_with_index do |row, row_index| 444: row_index.upto(last) do |col_index| 445: yield row[col_index] 446: end 447: end 448: else 449: Matrix.Raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" 450: end 451: self 452: 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 466 466: def each_with_index(which = :all) # :yield: e, row, column 467: return to_enum :each_with_index, which unless block_given? 468: last = column_size - 1 469: case which 470: when :all 471: @rows.each_with_index do |row, row_index| 472: row.each_with_index do |e, col_index| 473: yield e, row_index, col_index 474: end 475: end 476: when :diagonal 477: @rows.each_with_index do |row, row_index| 478: yield row.fetch(row_index){return self}, row_index, row_index 479: end 480: when :off_diagonal 481: @rows.each_with_index do |row, row_index| 482: column_size.times do |col_index| 483: yield row[col_index], row_index, col_index unless row_index == col_index 484: end 485: end 486: when :lower 487: @rows.each_with_index do |row, row_index| 488: 0.upto([row_index, last].min) do |col_index| 489: yield row[col_index], row_index, col_index 490: end 491: end 492: when :strict_lower 493: @rows.each_with_index do |row, row_index| 494: [row_index, column_size].min.times do |col_index| 495: yield row[col_index], row_index, col_index 496: end 497: end 498: when :strict_upper 499: @rows.each_with_index do |row, row_index| 500: (row_index+1).upto(last) do |col_index| 501: yield row[col_index], row_index, col_index 502: end 503: end 504: when :upper 505: @rows.each_with_index do |row, row_index| 506: row_index.upto(last) do |col_index| 507: yield row[col_index], row_index, col_index 508: end 509: end 510: else 511: Matrix.Raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" 512: end 513: self 514: 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 1193 1193: def eigensystem 1194: EigenvalueDecomposition.new(self) 1195: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1315 1315: def elements_to_f 1316: warn "#{caller(1)[0]}: warning: Matrix#elements_to_f is deprecated, use map(&:to_f)" 1317: map(&:to_f) 1318: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1320 1320: def elements_to_i 1321: warn "#{caller(1)[0]}: warning: Matrix#elements_to_i is deprecated, use map(&:to_i)" 1322: map(&:to_i) 1323: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1325 1325: def elements_to_r 1326: warn "#{caller(1)[0]}: warning: Matrix#elements_to_r is deprecated, use map(&:to_r)" 1327: map(&:to_r) 1328: end
# File lib/backports/1.9.2/stdlib/matrix.rb, line 776 776: def eql?(other) 777: return false unless Matrix === other && 778: column_size == other.column_size # necessary for empty matrices 779: rows.eql? other.rows 780: 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 619 619: def hermitian? 620: Matrix.Raise ErrDimensionMismatch unless square? 621: each_with_index(:strict_upper).all? do |e, row, col| 622: e == rows[col][row].conj 623: end 624: 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 1241 1241: def imaginary 1242: collect(&:imaginary) 1243: 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 529 529: def index(*args) 530: raise ArgumentError, "wrong number of arguments(#{args.size} for 0-2)" if args.size > 2 531: which = (args.size == 2 || SELECTORS.include?(args.last)) ? args.pop : :all 532: return to_enum :find_index, which, *args unless block_given? || args.size == 1 533: if args.size == 1 534: value = args.first 535: each_with_index(which) do |e, row_index, col_index| 536: return row_index, col_index if e == value 537: end 538: else 539: each_with_index(which) do |e, row_index, col_index| 540: return row_index, col_index if yield e 541: end 542: end 543: nil 544: end
Overrides Object#inspect
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1350 1350: def inspect 1351: if empty? 1352: "#{self.class}.empty(#{row_size}, #{column_size})" 1353: else 1354: "#{self.class}#{@rows.inspect}" 1355: end 1356: end
Returns true is this is a lower triangular matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 629 629: def lower_triangular? 630: each(:strict_upper).all?(&:zero?) 631: 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 1208 1208: def lup 1209: LUPDecomposition.new(self) 1210: 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 559 559: def minor(*param) 560: case param.size 561: when 2 562: row_range, col_range = param 563: from_row = row_range.first 564: from_row += row_size if from_row < 0 565: to_row = row_range.end 566: to_row += row_size if to_row < 0 567: to_row += 1 unless row_range.exclude_end? 568: size_row = to_row - from_row 569: 570: from_col = col_range.first 571: from_col += column_size if from_col < 0 572: to_col = col_range.end 573: to_col += column_size if to_col < 0 574: to_col += 1 unless col_range.exclude_end? 575: size_col = to_col - from_col 576: when 4 577: from_row, size_row, from_col, size_col = param 578: return nil if size_row < 0 || size_col < 0 579: from_row += row_size if from_row < 0 580: from_col += column_size if from_col < 0 581: else 582: Matrix.Raise ArgumentError, param.inspect 583: end 584: 585: return nil if from_row > row_size || from_col > column_size || from_row < 0 || from_col < 0 586: rows = @rows[from_row, size_row].collect{|row| 587: row[from_col, size_col] 588: } 589: new_matrix rows, [column_size - from_col, size_col].min 590: 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 637 637: def normal? 638: Matrix.Raise ErrDimensionMismatch unless square? 639: rows.each_with_index do |row_i, i| 640: rows.each_with_index do |row_j, j| 641: s = 0 642: rows.each_with_index do |row_k, k| 643: s += row_i[k] * row_j[k].conj - row_k[i].conj * row_k[j] 644: end 645: return false unless s == 0 646: end 647: end 648: true 649: 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 655 655: def orthogonal? 656: Matrix.Raise ErrDimensionMismatch unless square? 657: rows.each_with_index do |row, i| 658: column_size.times do |j| 659: s = 0 660: row_size.times do |k| 661: s += row[k] * rows[k][j] 662: end 663: return false unless s == (i == j ? 1 : 0) 664: end 665: end 666: true 667: 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 673 673: def permutation? 674: Matrix.Raise ErrDimensionMismatch unless square? 675: cols = Array.new(column_size) 676: rows.each_with_index do |row, i| 677: found = false 678: row.each_with_index do |e, j| 679: if e == 1 680: return false if found || cols[j] 681: found = cols[j] = true 682: elsif e != 0 683: return false 684: end 685: end 686: return false unless found 687: end 688: true 689: 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 1109 1109: def rank 1110: # We currently use Bareiss' multistep integer-preserving gaussian elimination 1111: # (see comments on determinant) 1112: a = to_a 1113: last_column = column_size - 1 1114: last_row = row_size - 1 1115: pivot_row = 0 1116: previous_pivot = 1 1117: 0.upto(last_column) do |k| 1118: switch_row = (pivot_row .. last_row).find {|row| 1119: a[row][k] != 0 1120: } 1121: if switch_row 1122: a[switch_row], a[pivot_row] = a[pivot_row], a[switch_row] unless pivot_row == switch_row 1123: pivot = a[pivot_row][k] 1124: (pivot_row+1).upto(last_row) do |i| 1125: ai = a[i] 1126: (k+1).upto(last_column) do |j| 1127: ai[j] = (pivot * ai[j] - ai[k] * a[pivot_row][j]) / previous_pivot 1128: end 1129: end 1130: pivot_row += 1 1131: previous_pivot = pivot 1132: end 1133: end 1134: pivot_row 1135: end
deprecated; use Matrix#rank
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1140 1140: def rank_e 1141: warn "#{caller(1)[0]}: warning: Matrix#rank_e is deprecated; use #rank" 1142: rank 1143: end
Returns true if this is a regular (i.e. non-singular) matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 701 701: def regular? 702: not singular? 703: end
Returns a matrix with entries rounded to the given precision (see Float#round)
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1148 1148: def round(ndigits=0) 1149: map{|e| e.round(ndigits)} 1150: 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 345 345: def row(i, &block) # :yield: e 346: if block_given? 347: @rows.fetch(i){return self}.each(&block) 348: self 349: else 350: Vector.elements(@rows.fetch(i){return nil}) 351: end 352: end
Returns true is this is a singular matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 708 708: def singular? 709: determinant == 0 710: end
Returns true is this is a square matrix.
# File lib/backports/1.9.2/stdlib/matrix.rb, line 715 715: def square? 716: column_size == row_size 717: 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 723 723: def symmetric? 724: Matrix.Raise ErrDimensionMismatch unless square? 725: each_with_index(:strict_upper) do |e, row, col| 726: return false if e != rows[col][row] 727: end 728: true 729: end
Overrides Object#to_s
# File lib/backports/1.9.2/stdlib/matrix.rb, line 1337 1337: def to_s 1338: if empty? 1339: "#{self.class}.empty(#{row_size}, #{column_size})" 1340: else 1341: "#{self.class}[" + @rows.collect{|row| 1342: "[" + row.collect{|e| e.to_s}.join(", ") + "]" 1343: }.join(", ")+"]" 1344: end 1345: 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 1157 1157: def trace 1158: Matrix.Raise ErrDimensionMismatch unless square? 1159: (0...column_size).inject(0) do |tr, i| 1160: tr + @rows[i][i] 1161: end 1162: 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 1175 1175: def transpose 1176: return self.class.empty(column_size, 0) if row_size.zero? 1177: new_matrix @rows.transpose, row_size 1178: 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 735 735: def unitary? 736: Matrix.Raise ErrDimensionMismatch unless square? 737: rows.each_with_index do |row, i| 738: column_size.times do |j| 739: s = 0 740: row_size.times do |k| 741: s += row[k].conj * rows[k][j] 742: end 743: return false unless s == (i == j ? 1 : 0) 744: end 745: end 746: true 747: end