Class: FastMatrix::Matrix
- Inherits:
-
Data
- Object
- Data
- FastMatrix::Matrix
- Defined in:
- lib/matrix/matrix.rb,
lib/scalar.rb,
lib/matrix/constructors.rb,
ext/fast_matrix/matrix.c
Overview
Constructors as in the standard matrix
Class Method Summary collapse
-
.[](*rows) ⇒ Object
Creates a matrix where each argument is a row.
-
.build(row_count, column_count = row_count, &block) ⇒ Object
Creates a matrix of size
row_countxcolumn_count. -
.column_vector(column) ⇒ Object
Creates a single-column matrix where the values of that column are as given in
column. -
.columns(columns) ⇒ Object
Creates a matrix using
columnsas an array of column vectors. -
.combine(*matrices) ⇒ Object
Create a matrix by combining matrices entrywise, using the given block.
-
.convert(matrix) ⇒ Object
Create fast matrix from standard matrix.
-
.diagonal(*values) ⇒ Object
Creates a matrix where the diagonal elements are composed of
values. -
.empty(_ = 0, _ = 0) ⇒ Object
Empty matrices does not supported.
-
.fill(value, row_count, column_count = row_count) ⇒ Object
Creates a filled matrix Matrix.fill(42, 2, 4) => 42 42 42 42 42 42 42 42.
-
.hstack(x, *matrices) ⇒ Object
Create a matrix by stacking matrices horizontally.
-
.identity(n) ⇒ Object
(also: unit, I)
Creates an
nbynidentity matrix. -
.row_vector(row) ⇒ Object
Creates a single-row matrix where the values of that row are as given in
row. -
.rows(rows, copy = true) ⇒ Object
Creates a matrix where
rowsis an array of arrays, each of which is a row of the matrix. -
.scalar(n, value) ⇒ Object
Creates an
nbyndiagonal matrix where each diagonal element isvalue. -
.vstack(x, *matrices) ⇒ Object
Create a matrix by stacking matrices vertically.
-
.zero(row_count, column_count = row_count) ⇒ Object
Creates a zero matrix
row_countbycolumn_count.
Instance Method Summary collapse
- #*(v) ⇒ Object
- #+(value) ⇒ Object
- #+=(value) ⇒ Object
- #-(value) ⇒ Object
- #-=(value) ⇒ Object
-
#==(other) ⇒ Object
FIXME: for compare with standard matrix.
- #>=(value) ⇒ Object
-
#[](row, column) ⇒ Object
[].
-
#[]=(row, column, v) ⇒ Object
[]=.
-
#abs ⇒ Object
rb_define_method(cMatrix, “strassen”, strassen, 1);.
- #clone ⇒ Object
-
#coerce(other) ⇒ Object
The coerce method provides support for Ruby type coercion.
- #collect ⇒ Object
- #column_count ⇒ Object (also: #column_size)
- #component ⇒ Object
-
#convert ⇒ Object
Convert to standard ruby matrix.
- #determinant ⇒ Object
-
#each(&block) ⇒ Object
Yields all elements of the matrix, starting with those of the first row.
-
#each_with_index ⇒ Object
Same as #each, but the row index and column index in addition to the element.
-
#each_with_index! ⇒ Object
don’t use (Issue#1).
-
#element ⇒ Object
Returns element (
i,j) of the matrix. - #eql?(value) ⇒ Boolean
- #fill!(value) ⇒ Object
- #initialize(rows_count, columns_count) ⇒ Object constructor
- #row_count ⇒ Object (also: #row_size)
-
#to_s ⇒ Object
(also: #to_str)
Overrides Object#to_s.
- #transpose ⇒ Object
Constructor Details
#initialize(rows_count, columns_count) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'ext/fast_matrix/matrix.c', line 49 VALUE matrix_initialize(VALUE self, VALUE rows_count, VALUE columns_count) { struct matrix* data; int m = raise_rb_value_to_int(columns_count); int n = raise_rb_value_to_int(rows_count); if(m <= 0 || n <= 0) rb_raise(fm_eIndexError, "Size cannot be negative or zero"); TypedData_Get_Struct(self, struct matrix, &matrix_type, data); c_matrix_init(data, m, n); return self; } |
Class Method Details
.[](*rows) ⇒ Object
Creates a matrix where each argument is a row.
Matrix[ [25, 93], [-1, 66] ]
=> 25 93
-1 66
57 58 59 |
# File 'lib/matrix/constructors.rb', line 57 def self.[](*rows) self.rows(rows) end |
.build(row_count, column_count = row_count, &block) ⇒ Object
Creates a matrix of size row_count x column_count. It fills the values by calling the given block, passing the current row and column. Returns random matrix 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
20 21 22 23 24 25 |
# File 'lib/matrix/constructors.rb', line 20 def self.build(row_count, column_count = row_count, &block) matrix = create_with_check(row_count, column_count) raise NotImplementedError, 'Issue#17' unless block_given? matrix.each_with_index! { |_, i, j| block.call(i, j) } end |
.column_vector(column) ⇒ Object
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
69 70 71 72 73 |
# File 'lib/matrix/constructors.rb', line 69 def self.column_vector(column) matrix = create_with_check(column.size, 1) column.each_with_index { |elem, i| matrix[i, 0] = elem } matrix end |
.columns(columns) ⇒ Object
Creates a matrix using columns as an array of column vectors.
Matrix.columns([[25, 93], [-1, 66]])
=> 25 -1
93 66
47 48 49 |
# File 'lib/matrix/constructors.rb', line 47 def self.columns(columns) lines(columns, false) end |
.combine(*matrices) ⇒ Object
Create a matrix by combining matrices entrywise, using the given block
x = Matrix[[6, 6], [4, 4]]
y = Matrix[[1, 2], [3, 4]]
Matrix.combine(x, y) {|a, b| a - b} # => Matrix[[5, 4], [1, 0]]
TODO: optimize in C
209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/matrix/constructors.rb', line 209 def self.combine(*matrices) return empty if matrices.empty? result = convert(matrices.first) matrices[1..matrices.size].each do |m| raise IndexError unless result.row_count == m.row_count && result.column_count == m.column_count result.each_with_index! { |elem, i, j| yield elem, m[i, j] } end result end |
.convert(matrix) ⇒ Object
Create fast matrix from standard matrix
45 46 47 48 49 50 51 52 53 |
# File 'lib/matrix/matrix.rb', line 45 def self.convert(matrix) fast_matrix = Matrix.new(matrix.row_count, matrix.column_count) (0...matrix.row_count).each do |i| (0...matrix.column_count).each do |j| fast_matrix[i, j] = matrix[i, j] end end fast_matrix end |
.diagonal(*values) ⇒ Object
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
94 95 96 |
# File 'lib/matrix/constructors.rb', line 94 def self.diagonal(*values) build(values.size, values.size) { |i, j| i == j ? values[i] : 0 } end |
.empty(_ = 0, _ = 0) ⇒ Object
Empty matrices does not supported
146 147 148 |
# File 'lib/matrix/constructors.rb', line 146 def self.empty(_ = 0, _ = 0) raise NotSupportedError, 'Empty matrices does not supported' end |
.fill(value, row_count, column_count = row_count) ⇒ Object
Creates a filled matrix Matrix.fill(42, 2, 4)
=> 42 42 42 42
42 42 42 42
129 130 131 |
# File 'lib/matrix/constructors.rb', line 129 def self.fill(value, row_count, column_count = row_count) create_with_check(row_count, column_count).fill!(value) end |
.hstack(x, *matrices) ⇒ Object
Create a matrix by stacking matrices horizontally
x = Matrix[[1, 2], [3, 4]]
y = Matrix[[5, 6], [7, 8]]
Matrix.hstack(x, y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]]
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/matrix/constructors.rb', line 183 def self.hstack(x, *matrices) column_count = x.column_count row_count = x.row_count matrices.each do |matrix| raise IndexError unless matrix.row_count == row_count column_count += matrix.column_count end result = new(row_count, column_count) m_j = 0 [x, *matrices].each do |matrix| matrix.each_with_index do |elem, i, j| result[i, m_j + j] = elem end m_j += matrix.column_count end result end |
.identity(n) ⇒ Object Also known as: unit, I
Creates an n by n identity matrix.
Matrix.identity(2)
=> 1 0
0 1
115 116 117 |
# File 'lib/matrix/constructors.rb', line 115 def self.identity(n) scalar(n, 1) end |
.row_vector(row) ⇒ Object
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
81 82 83 84 85 |
# File 'lib/matrix/constructors.rb', line 81 def self.row_vector(row) matrix = create_with_check(1, row.size) row.each_with_index { |elem, j| matrix[0, j] = elem } matrix end |
.rows(rows, copy = true) ⇒ Object
Creates a matrix where rows is an array of arrays, each of which is a row of the matrix. The optional argument copy exists only for compatibility with standard. The optional argument copy cannot be false, unlike standard.
Matrix.rows([[25, 93], [-1, 66]])
=> 25 93
-1 66
36 37 38 39 |
# File 'lib/matrix/constructors.rb', line 36 def self.rows(rows, copy = true) check_flag_copy(copy) lines(rows, true) end |
.scalar(n, value) ⇒ Object
Creates an n by n diagonal matrix where each diagonal element is value.
Matrix.scalar(2, 5)
=> 5 0
0 5
105 106 107 |
# File 'lib/matrix/constructors.rb', line 105 def self.scalar(n, value) build(n, n) { |i, j| i == j ? value : 0 } end |
.vstack(x, *matrices) ⇒ Object
Create a matrix by stacking matrices vertically
x = Matrix[[1, 2], [3, 4]]
y = Matrix[[5, 6], [7, 8]]
Matrix.vstack(x, y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]]
TODO: optimize (maybe in C)
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/matrix/constructors.rb', line 157 def self.vstack(x, *matrices) column_count = x.column_count row_count = x.row_count matrices.each do |matrix| raise IndexError unless matrix.column_count == column_count row_count += matrix.row_count end result = new(row_count, column_count) m_i = 0 [x, *matrices].each do |matrix| matrix.each_with_index do |elem, i, j| result[m_i + i, j] = elem end m_i += matrix.row_count end result end |
.zero(row_count, column_count = row_count) ⇒ Object
Creates a zero matrix row_count by column_count.
Matrix.zero(2, 3)
=> 0 0 0
0 0 0
139 140 141 |
# File 'lib/matrix/constructors.rb', line 139 def self.zero(row_count, column_count = row_count) fill(0, row_count, column_count) end |
Instance Method Details
#*(v) ⇒ Object
438 439 440 441 442 443 444 445 446 447 448 |
# File 'ext/fast_matrix/matrix.c', line 438 VALUE matrix_multiply(VALUE self, VALUE v) { if(RB_FLOAT_TYPE_P(v) || FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM)) return matrix_multiply_mn(self, v); if(RBASIC_CLASS(v) == cMatrix) return strassen(self, v); if(RBASIC_CLASS(v) == cVector); return matrix_multiply_mv(self, v); rb_raise(fm_eTypeError, "Invalid klass for multiply"); } |
#+(value) ⇒ Object
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 |
# File 'ext/fast_matrix/matrix.c', line 492 VALUE matrix_add_with(VALUE self, VALUE value) { raise_check_rbasic(value, cMatrix, "matrix"); struct matrix* A; struct matrix* B; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); TypedData_Get_Struct(value, struct matrix, &matrix_type, B); if(A->m != B->m && A->n != B->n) rb_raise(fm_eIndexError, "Different sizes matrices"); int m = B->m; int n = A->n; struct matrix* C; VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C); c_matrix_init(C, m, n); add_d_arrays_to_result(n * m, A->data, B->data, C->data); return result; } |
#+=(value) ⇒ Object
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
# File 'ext/fast_matrix/matrix.c', line 515 VALUE matrix_add_from(VALUE self, VALUE value) { raise_check_rbasic(value, cMatrix, "matrix"); struct matrix* A; struct matrix* B; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); TypedData_Get_Struct(value, struct matrix, &matrix_type, B); if(A->m != B->m && A->n != B->n) rb_raise(fm_eIndexError, "Different sizes matrices"); int m = B->m; int n = A->n; add_d_arrays_to_first(n * m, A->data, B->data); return self; } |
#-(value) ⇒ Object
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
# File 'ext/fast_matrix/matrix.c', line 534 VALUE matrix_sub_with(VALUE self, VALUE value) { raise_check_rbasic(value, cMatrix, "matrix"); struct matrix* A; struct matrix* B; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); TypedData_Get_Struct(value, struct matrix, &matrix_type, B); if(A->m != B->m && A->n != B->n) rb_raise(fm_eIndexError, "Different sizes matrices"); int m = B->m; int n = A->n; struct matrix* C; VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C); c_matrix_init(C, m, n); sub_d_arrays_to_result(n * m, A->data, B->data, C->data); return result; } |
#-=(value) ⇒ Object
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
# File 'ext/fast_matrix/matrix.c', line 557 VALUE matrix_sub_from(VALUE self, VALUE value) { raise_check_rbasic(value, cMatrix, "matrix"); struct matrix* A; struct matrix* B; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); TypedData_Get_Struct(value, struct matrix, &matrix_type, B); if(A->m != B->m && A->n != B->n) rb_raise(fm_eIndexError, "Different sizes matrices"); int m = B->m; int n = A->n; sub_d_arrays_to_first(n * m, A->data, B->data); return self; } |
#==(other) ⇒ Object
FIXME: for compare with standard matrix
108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/matrix/matrix.rb', line 108 def ==(other) return eql?(other) if other.class == Matrix return false unless i[row_size column_size \[\]].all? { |x| other.respond_to? x } return false unless self.row_size == other.row_size && self.column_size == other.column_size result = true each_with_index do |elem, i, j| result &&= elem == other[i, j].to_f end result end |
#>=(value) ⇒ Object
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
# File 'ext/fast_matrix/matrix.c', line 668 VALUE matrix_greater_or_equal(VALUE self, VALUE value) { if(RBASIC_CLASS(value) != cMatrix) rb_raise(fm_eTypeError, "Expected class matrix"); struct matrix* A; struct matrix* B; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); TypedData_Get_Struct(value, struct matrix, &matrix_type, B); if(A->m != B->m && A->n != B->n) rb_raise(fm_eIndexError, "Different sizes matrices"); int m = B->m; int n = A->n; if(greater_or_equal_d_array(n * m, A->data, B->data)) return Qtrue; return Qfalse; } |
#[](row, column) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'ext/fast_matrix/matrix.c', line 86 VALUE matrix_get(VALUE self, VALUE row, VALUE column) { int m = raise_rb_value_to_int(column); int n = raise_rb_value_to_int(row); struct matrix* data; TypedData_Get_Struct(self, struct matrix, &matrix_type, data); m = (m < 0) ? data->m + m : m; n = (n < 0) ? data->n + n : n; if(m < 0 || n < 0 || n >= data->n || m >= data->m) return Qnil; return DBL2NUM(data->data[m + data->m * n]); } |
#[]=(row, column, v) ⇒ Object
[]=
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'ext/fast_matrix/matrix.c', line 66 VALUE matrix_set(VALUE self, VALUE row, VALUE column, VALUE v) { int m = raise_rb_value_to_int(column); int n = raise_rb_value_to_int(row); double x = raise_rb_value_to_double(v); struct matrix* data; TypedData_Get_Struct(self, struct matrix, &matrix_type, data); m = (m < 0) ? data->m + m : m; n = (n < 0) ? data->n + n : n; raise_check_range(m, 0, data->m); raise_check_range(n, 0, data->n); data->data[m + data->m * n] = x; return v; } |
#abs ⇒ Object
rb_define_method(cMatrix, “strassen”, strassen, 1);
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 |
# File 'ext/fast_matrix/matrix.c', line 651 VALUE matrix_abs(VALUE self) { struct matrix* A; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); int m = A->m; int n = A->n; struct matrix* B; VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, B); c_matrix_init(B, m, n); abs_d_array(n * m, A->data, B->data); return result; } |
#clone ⇒ Object
450 451 452 453 454 455 456 457 458 459 460 461 462 |
# File 'ext/fast_matrix/matrix.c', line 450 VALUE matrix_copy(VALUE mtrx) { struct matrix* M; TypedData_Get_Struct(mtrx, struct matrix, &matrix_type, M); struct matrix* R; VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, R); c_matrix_init(R, M->m, M->n); copy_d_array(M->m * M->n, M->data, R->data); return result; } |
#coerce(other) ⇒ Object
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.
13 14 15 16 17 18 19 20 |
# File 'lib/scalar.rb', line 13 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 |
#collect ⇒ Object
22 23 24 25 26 27 28 |
# File 'lib/matrix/matrix.rb', line 22 def collect collected_rows = [] rows.each do |i| collected_rows.push(yield i) end collected_rows end |
#column_count ⇒ Object Also known as: column_size
464 465 466 467 468 469 |
# File 'ext/fast_matrix/matrix.c', line 464 VALUE row_size(VALUE self) { struct matrix* data; TypedData_Get_Struct(self, struct matrix, &matrix_type, data); return INT2NUM(data->m); } |
#component ⇒ Object
20 |
# File 'lib/matrix/matrix.rb', line 20 alias component [] |
#convert ⇒ Object
Convert to standard ruby matrix.
103 104 105 |
# File 'lib/matrix/matrix.rb', line 103 def convert ::Matrix.build(row_size, column_size) { |i, j| self[i, j] } end |
#determinant ⇒ Object
607 608 609 610 611 612 613 614 615 616 617 618 |
# File 'ext/fast_matrix/matrix.c', line 607 VALUE matrix_determinant(VALUE self) { struct matrix* A; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); int m = A->m; int n = A->n; if(m != n) rb_raise(fm_eIndexError, "Not a square matrix"); return DBL2NUM(determinant(n, A->data)); } |
#each(&block) ⇒ Object
Yields all elements of the matrix, starting with those of the first row
Matrix[ [1,2], [3,4] ].each { |e| puts e }
# => prints the numbers 1 to 4
60 61 62 63 64 65 |
# File 'lib/matrix/matrix.rb', line 60 def each(&block) raise NotSupportedError unless block_given? each_with_index { |elem, _, _| block.call(elem) } self end |
#each_with_index ⇒ Object
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
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/matrix/matrix.rb', line 79 def each_with_index raise NotSupportedError unless block_given? (0...row_count).each do |i| (0...column_count).each do |j| yield self[i, j], i, j end end self end |
#each_with_index! ⇒ Object
don’t use (Issue#1)
91 92 93 94 95 96 97 98 |
# File 'lib/matrix/matrix.rb', line 91 def each_with_index! (0...row_count).each do |i| (0...column_count).each do |j| self[i, j] = yield self[i, j], i, j end end self end |
#element ⇒ Object
Returns element (i,j) of the matrix. That is: row i, column j.
19 |
# File 'lib/matrix/matrix.rb', line 19 alias element [] |
#eql?(value) ⇒ Boolean
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
# File 'ext/fast_matrix/matrix.c', line 631 VALUE matrix_equal(VALUE self, VALUE value) { if(RBASIC_CLASS(value) != cMatrix) return Qfalse; struct matrix* A; struct matrix* B; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); TypedData_Get_Struct(value, struct matrix, &matrix_type, B); if(A->n != B->n || A->m != B->m) return Qfalse; int n = A->n; int m = B->m; if(equal_d_arrays(n * m, A->data, B->data)) return Qtrue; return Qfalse; } |
#fill!(value) ⇒ Object
620 621 622 623 624 625 626 627 628 629 |
# File 'ext/fast_matrix/matrix.c', line 620 VALUE matrix_fill(VALUE self, VALUE value) { double d = raise_rb_value_to_double(value); struct matrix* A; TypedData_Get_Struct(self, struct matrix, &matrix_type, A); fill_d_array(A->m * A->n, A->data, d); return self; } |
#row_count ⇒ Object Also known as: row_size
471 472 473 474 475 476 |
# File 'ext/fast_matrix/matrix.c', line 471 VALUE column_size(VALUE self) { struct matrix* data; TypedData_Get_Struct(self, struct matrix, &matrix_type, data); return INT2NUM(data->n); } |
#to_s ⇒ Object Also known as: to_str
Overrides Object#to_s
33 34 35 36 37 |
# File 'lib/matrix/matrix.rb', line 33 def to_s "#{self.class}[#{collect do |row| '[' + row.join(', ') + ']' end.join(', ')}]" end |
#transpose ⇒ Object
478 479 480 481 482 483 484 485 486 487 488 489 490 |
# File 'ext/fast_matrix/matrix.c', line 478 VALUE transpose(VALUE self) { struct matrix* M; TypedData_Get_Struct(self, struct matrix, &matrix_type, M); struct matrix* R; VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, R); c_matrix_init(R, M->n, M->m); matrix_transpose(M->m, M->n, M->data, R->data); return result; } |