rmds 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,155 @@
1
+ #
2
+ # RMDS - Ruby Multidimensional Scaling Library
3
+ # Copyright (c) Christoph Heindl, 2010
4
+ # http://github.com/cheind/rmds
5
+ #
6
+
7
+ require 'mds/matrix_interface'
8
+
9
+ begin
10
+ require 'rubygems'
11
+ require 'extendmatrix'
12
+ rescue LoadError
13
+ warn "\n**Notice: RubyAdapter requires \'extendmatrix\' which was not found."
14
+ warn "You can install the extension as follows: \n gem install extendmatrix \n"
15
+ raise $!
16
+ end
17
+
18
+ module MDS
19
+
20
+ #
21
+ # Matrix interface for Ruby's standard library Matrix class.
22
+ #
23
+ # To succesfully use this interface 'extendmatrix' is required.
24
+ # For more information and installation instructions see
25
+ # http://github.com/clbustos/extendmatrix
26
+ #
27
+ # The algorithm/implementation of the eigen-decomposition is
28
+ # sub-optimal. It is therefore suitable only for small-scale problems.
29
+ # Timings are illustrated in the benchmark section of the {file:README}.
30
+ #
31
+ # The reason this interface is still included in RMDS is the fact
32
+ # that it only depends on Ruby code and no native extensions.
33
+ #
34
+ # Compatible with 'extendmatrix >= 0.3.1'
35
+ #
36
+ class StdlibInterface < MatrixInterface
37
+
38
+ #
39
+ # Create a new matrix with equal elements.
40
+ #
41
+ # @param (see MatrixInterface#create)
42
+ # @return (see MatrixInterface#create)
43
+ #
44
+ def StdlibInterface.create(n, m, s)
45
+ ::Matrix.build(n, m, s)
46
+ end
47
+
48
+ #
49
+ # Return the number of matrix rows
50
+ #
51
+ # @param (see MatrixInterface#nrows)
52
+ # @return (see MatrixInterface#nrows)
53
+ #
54
+ def StdlibInterface.nrows(m)
55
+ m.row_size
56
+ end
57
+
58
+ #
59
+ # Return the number of matrix columns
60
+ #
61
+ # @param (see MatrixInterface#ncols)
62
+ # @return (see MatrixInterface#ncols)
63
+ #
64
+ def StdlibInterface.ncols(m)
65
+ m.column_size
66
+ end
67
+
68
+ #
69
+ # Set matrix element.
70
+ #
71
+ # @param (see MatrixInterface#set)
72
+ #
73
+ def StdlibInterface.set(m, i, j, s)
74
+ m[i,j] = s
75
+ end
76
+
77
+ #
78
+ # Get matrix element.
79
+ #
80
+ # @param (see MatrixInterface#get)
81
+ # @return (see MatrixInterface#get)
82
+ #
83
+ def StdlibInterface.get(m, i, j)
84
+ m[i,j]
85
+ end
86
+
87
+ #
88
+ # Calculate the product of two matrices or
89
+ # the product of a matrix and a scalar.
90
+ #
91
+ # @param (see MatrixInterface#prod)
92
+ # @return (see MatrixInterface#prod)
93
+ #
94
+ def StdlibInterface.prod(m, n)
95
+ m * n
96
+ end
97
+
98
+ #
99
+ # Transpose a matrix.
100
+ #
101
+ # @param (see MatrixInterface#t)
102
+ # @return (see MatrixInterface#t)
103
+ #
104
+ def StdlibInterface.t(m)
105
+ m.t
106
+ end
107
+
108
+ #
109
+ # Componentwise addition of two matrices.
110
+ #
111
+ # @param (see MatrixInterface#add)
112
+ # @return (see MatrixInterface#add)
113
+ #
114
+ def StdlibInterface.add(m, n)
115
+ m + n
116
+ end
117
+
118
+ #
119
+ # Componentwise subtraction of two matrices.
120
+ #
121
+ # @param (see MatrixAdapter#sub)
122
+ # @return (see MatrixAdapter#sub)
123
+ #
124
+ def StdlibInterface.sub(m, n)
125
+ m - n
126
+ end
127
+
128
+ #
129
+ # Compute the eigen-decomposition of a real symmetric matrix.
130
+ #
131
+ # The Ruby version uses Jacobi iterations to calculate the
132
+ # eigen-decomposition of a matrix. Although comfortable as all
133
+ # third-party dependencies can be installed via gem, the method is
134
+ # not suited for matrices bigger than 10x10.
135
+ #
136
+ # @param (see MatrixInterface#ed)
137
+ # @return (see MatrixInterface#ed)
138
+ #
139
+ def StdlibInterface.ed(m)
140
+ eigen_values = m.cJacobiA
141
+ eigen_vectors = m.cJacobiV
142
+
143
+ ranks = (0..(m.row_size-1)).sort{|i,j| eigen_values[j,j] <=> eigen_values[i,i]}
144
+
145
+ s_eigen_values = []
146
+ s_eigen_vectors = []
147
+ ranks.each do |r|
148
+ s_eigen_values << eigen_values[r,r]
149
+ s_eigen_vectors << eigen_vectors.column(r)
150
+ end
151
+ [::Matrix.diagonal(*s_eigen_values), ::Matrix.columns(s_eigen_vectors)]
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,29 @@
1
+ #
2
+ # RMDS - Ruby Multidimensional Scaling Library
3
+ # Copyright (c) Christoph Heindl, 2010
4
+ # http://github.com/cheind/rmds
5
+ #
6
+
7
+ module MDS
8
+ module IO
9
+
10
+ #
11
+ # Read matrix from CSV file
12
+ # Each feature corresponds to a single row.
13
+ # All rows are assumed to have an equal column count.
14
+ #
15
+ def IO.read_csv(path, sep = ' ')
16
+ rows = []
17
+ File.foreach(path) do |line|
18
+ cells = line.chop.split(sep)
19
+ if block_given?
20
+ rows << cells.map{|c| yield c}.compact
21
+ else
22
+ rows << cells
23
+ end
24
+ end
25
+ rows
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,258 @@
1
+ #
2
+ # RMDS - Ruby Multidimensional Scaling Library
3
+ # Copyright (c) Christoph Heindl, 2010
4
+ # http://github.com/cheind/rmds
5
+ #
6
+
7
+ module MDS
8
+
9
+ #
10
+ # A matrix adapter.
11
+ #
12
+ # RMDS does not implement matrices or linear algebra routines itself,
13
+ # instead RMDS offers a non-intrusive adapter architecture to interop
14
+ # with third party linear algebra packages.
15
+ #
16
+ # The RMDS adapter architecture consists of two layers
17
+ #
18
+ # * {MDS::MatrixInterface} defines a minimal common interface of
19
+ # required interop methods.
20
+ # * {MDS::Matrix} is a matrix adapter that binds to data provided by
21
+ # a specialized {MDS::MatrixInterface} class and carries out all
22
+ # computations through methods defined in {MDS::MatrixInterface}.
23
+ #
24
+ # @see MDS::MatrixInterface
25
+ #
26
+ class Matrix
27
+ # Wrapped matrix
28
+ attr_reader :m
29
+ alias :matrix :m
30
+
31
+ #
32
+ # Initialize from matrix instance and interface class.
33
+ #
34
+ # @param matrix the matrix to be wrapped
35
+ #
36
+ def initialize(matrix)
37
+ @m = matrix
38
+ end
39
+
40
+ #
41
+ # Create a new matrix setting all elements to equal values.
42
+ #
43
+ # @param (see MatrixInterface#create)
44
+ # @return [Matrix] the newly created matrix.
45
+ #
46
+ def Matrix.create(n, m, s)
47
+ Matrix.new(Backend.active.create(n, m, s))
48
+ end
49
+
50
+ #
51
+ # Create a new matrix and assign each element as the
52
+ # result of invoking the given block.
53
+ #
54
+ # @param (see MatrixInterface#create_block)
55
+ # @return [Matrix] the newly created matrix.
56
+ #
57
+ def Matrix.create_block(n, m, &block)
58
+ Matrix.new(Backend.active.create_block(n, m, &block))
59
+ end
60
+
61
+ #
62
+ # Create a new matrix from uniform random distribution.
63
+ #
64
+ # @param (see MatrixInterface#create_random)
65
+ # @return [Matrix] the newly created matrix.
66
+ #
67
+ def Matrix.create_random(n, m, smin = -1.0, smax = 1.0)
68
+ Matrix.new(Backend.active.create_random(n, m, smin, smax))
69
+ end
70
+
71
+ #
72
+ # Create a new identity matrix.
73
+ #
74
+ # @param (see MatrixInterface#create_identity)
75
+ # @return [Matrix] the newly created matrix.
76
+ #
77
+ def Matrix.create_identity(n)
78
+ Matrix.new(Backend.active.create_identity(n))
79
+ end
80
+
81
+ #
82
+ # Create a new diagonal matrix.
83
+ #
84
+ # @param (see MatrixInterface#create_diagonal)
85
+ # @return [Matrix] the newly created matrix.
86
+ #
87
+ def Matrix.create_diagonal(*elements)
88
+ Matrix.new(Backend.active.create_diagonal(*elements))
89
+ end
90
+
91
+ #
92
+ # Create matrix from rows.
93
+ #
94
+ # @param (see MatrixInterface#create_rows)
95
+ # @return [Matrix] the newly created matrix.
96
+ #
97
+ def Matrix.create_rows(*rows)
98
+ Matrix.new(Backend.active.create_rows(*rows))
99
+ end
100
+
101
+ #
102
+ # Return the number of matrix rows
103
+ #
104
+ # @return number of rows in matrix
105
+ #
106
+ def nrows
107
+ Backend.active.nrows(@m)
108
+ end
109
+
110
+ #
111
+ # Return the number of matrix columns
112
+ #
113
+ # @return number of columns in matrix
114
+ #
115
+ def ncols
116
+ Backend.active.ncols(@m)
117
+ end
118
+
119
+ #
120
+ # Set value of matrix element.
121
+ #
122
+ # @param [Integer] i the i-th row, zero-based indexing
123
+ # @param [Integer] j the j-th column, zero-based indexing
124
+ # @param [Float] s scalar value to set
125
+ #
126
+ def []=(i, j, s)
127
+ Backend.active.set(@m, i, j, s)
128
+ end
129
+
130
+ #
131
+ # Get value of matrix element.
132
+ #
133
+ # @param [Integer] i the i-th row, zero-based indexing
134
+ # @param [Integer] j the j-th column, zero-based indexing
135
+ # @return [Float] value of element
136
+ #
137
+ def [](i,j)
138
+ Backend.active.get(@m, i, j)
139
+ end
140
+
141
+ #
142
+ # Calculate the product of two matrices or
143
+ # the product of a matrix and a scalar.
144
+ #
145
+ # @param [Matrix, Float] other matrix to multiply with, or scalar
146
+ # @return [Matrix] the matrix.
147
+ #
148
+ def *(other)
149
+ is_ma = other.instance_of?(Matrix)
150
+ Matrix.new(
151
+ Backend.active.prod(@m, is_ma ? other.matrix : other)
152
+ )
153
+ end
154
+
155
+ #
156
+ # Componentwise addition of two matrices.
157
+ #
158
+ # @param [Matrix] other matrix to add to this matrix
159
+ # @return [Matrix] the matrix.
160
+ #
161
+ def +(other)
162
+ Matrix.new(Backend.active.add(@m, other.m))
163
+ end
164
+
165
+ #
166
+ # Componentwise subtraction of two matrices.
167
+ #
168
+ # @param [Matrix] other matrix to subtract from this matrix.
169
+ # @return [Matrix] the matrix.
170
+ #
171
+ def -(other)
172
+ Matrix.new(Backend.active.sub(@m, other.m))
173
+ end
174
+
175
+ #
176
+ # Transpose a matrix.
177
+ #
178
+ # @return [Matrix] the transposed matrix.
179
+ #
180
+ def t
181
+ Matrix.new(Backend.active.t(@m))
182
+ end
183
+
184
+ #
185
+ # Compute the eigen-decomposition of a real symmetric matrix.
186
+ #
187
+ # The eigen-decomposition consists of a diagonal matrix +D+ containing
188
+ # the eigen values and a square matrix +N+ having the normalized eigenvectors
189
+ # in columns.
190
+ #
191
+ # @return [Array] the array containing the matrix of eigen-values and eigen-vector
192
+ #
193
+ def ed
194
+ Backend.active.ed(@m).map {|m| Matrix.new(m) }
195
+ end
196
+
197
+ #
198
+ # Retrieve the diagonal elements as an array.
199
+ #
200
+ # @return [Array] diagonal elements as array.
201
+ #
202
+ def diagonals
203
+ Backend.active.diagonals(@m)
204
+ end
205
+
206
+ #
207
+ # Calculate the sum of diagonal matrix elements.
208
+ #
209
+ # @return [Float] trace of matrix
210
+ #
211
+ def trace
212
+ Backend.active.trace(@m)
213
+ end
214
+
215
+ #
216
+ # Calculate minor matrix.
217
+ #
218
+ # @param [Range] row_range row range
219
+ # @param [Range] col_range column range
220
+ # @return [Matrix] minor matrix
221
+ #
222
+ def minor(row_range, col_range)
223
+ Matrix.new(
224
+ Backend.active.minor(@m, row_range, col_range)
225
+ )
226
+ end
227
+
228
+ #
229
+ # Returns matrix as array of columns.
230
+ #
231
+ # @return [Array<Array>] the array of columns where each column is an array
232
+ #
233
+ def columns
234
+ Backend.active.columns(@m)
235
+ end
236
+
237
+ #
238
+ # Returns matrix as array of rows.
239
+ #
240
+ # @return [Array<Array>] the array of rows where each row is an array
241
+ #
242
+ def rows
243
+ Backend.active.rows(@m)
244
+ end
245
+
246
+ #
247
+ # Convert to string.
248
+ #
249
+ # Invokes #to_s from wrapped matrix.
250
+ #
251
+ # @return wrapped matrix as string.
252
+ #
253
+ def to_s
254
+ Backend.active.to_s(@m)
255
+ end
256
+
257
+ end
258
+ end
@@ -0,0 +1,358 @@
1
+ #
2
+ # RMDS - Ruby Multidimensional Scaling Library
3
+ # Copyright (c) Christoph Heindl, 2010
4
+ # http://github.com/cheind/rmds
5
+ #
6
+
7
+ module MDS
8
+
9
+ #
10
+ # Provides a common interface to matrix operations.
11
+ #
12
+ # RMDS does not implement any linear algebra routine itself,
13
+ # but rather provides a non intrusive mechanism to plugin third party
14
+ # linear algebra packages. {MDS::MatrixInterface} defines a minimal
15
+ # set of required methods to be implemented for any linear algebra packages
16
+ # which are to be used with RMDS.
17
+ #
18
+ # Making linear algebra backends compatible with RMDS is easy:
19
+ # simply subclass from {MDS::MatrixInterface} and implement all abstract
20
+ # methods. Not all of {MDS::MatrixInterface} methods are abstract, some
21
+ # come with a default implementation. If your linear algebra package
22
+ # does better at some of those methods, you should override them in your
23
+ # interface subclass.
24
+ #
25
+ # RMDS helps you in testing your matrix interfaces through test bundles
26
+ # that ship with RMDS. Each test bundle contains a set of tests that work
27
+ # independently of the matrix interface chosen. The following file unit
28
+ # tests a matrix interface.
29
+ #
30
+ # require 'test/unit'
31
+ # require 'mds/test/bundles/bundle_matrix_interface.rb'
32
+ # require 'mds/interfaces/linalg_interface'
33
+ #
34
+ # class TestLinalgInteface < Test::Unit::TestCase
35
+ # include MDS::Test::BundleMatrixInterface
36
+ #
37
+ # def setup
38
+ # MDS::Backend.push_active(MDS::LinalgInterface)
39
+ # end
40
+ #
41
+ # def teardown
42
+ # MDS::Backend.pop_active
43
+ # end
44
+ #
45
+ # end
46
+ #
47
+ # Finally, tell RMDS to use your matrix interface by setting the
48
+ # default matrix interface, like so
49
+ #
50
+ # # Set active interface
51
+ # MDS::Backend.active = YourMatrixInterface
52
+ #
53
+ # # Push onto interface stack and set active interface
54
+ # MDS::Backend.push_active(YourMatrixInterface)
55
+ #
56
+ # # Restore the previously active interface
57
+ # MDS::Backend.pop_active
58
+ #
59
+ # @see MDS::Matrix, MDS::Backend
60
+ class MatrixInterface
61
+
62
+ #
63
+ # Record creation of a subclass of this class at the MDS::Backend
64
+ #
65
+ def MatrixInterface.inherited(subclass)
66
+ MDS::Backend.add(subclass)
67
+ end
68
+
69
+ #---------------------------------------
70
+ # Required
71
+ # Abstract methods
72
+ #---------------------------------------
73
+
74
+ #
75
+ # Create a new matrix having all elements equal values.
76
+ #
77
+ # @param [Integer] n the number of rows
78
+ # @param [Integer] m the number of columns
79
+ # @param [Float] s the scalar value of each matrix component
80
+ # @return the newly created matrix.
81
+ # @abstract
82
+ #
83
+ def MatrixInterface.create(n, m, s)
84
+ raise NotImplementedError
85
+ end
86
+
87
+ #
88
+ # Return the number of matrix rows
89
+ #
90
+ # @param m the matrix
91
+ # @return number of rows in matrix
92
+ # @abstract
93
+ #
94
+ def MatrixInterface.nrows(m)
95
+ raise NotImplementedError
96
+ end
97
+
98
+ #
99
+ # Return the number of matrix columns
100
+ #
101
+ # @param m the matrix
102
+ # @return number of columns in matrix
103
+ # @abstract
104
+ #
105
+ def MatrixInterface.ncols(m)
106
+ raise NotImplementedError
107
+ end
108
+
109
+ #
110
+ # Set value of matrix element.
111
+ #
112
+ # @param m the matrix
113
+ # @param [Integer] i the i-th row, zero-based indexing
114
+ # @param [Integer] j the j-th column, zero-based indexing
115
+ # @param [Float] s scalar value to set
116
+ # @abstract
117
+ def MatrixInterface.set(m, i, j, s)
118
+ raise NotImplementedError
119
+ end
120
+
121
+ #
122
+ # Get value of matrix element.
123
+ #
124
+ # @param m the matrix
125
+ # @param [Integer] i the i-th row, zero-based indexing
126
+ # @param [Integer] j the j-th column, zero-based indexing
127
+ # @return [Float] value of element
128
+ # @abstract
129
+ #
130
+ def MatrixInterface.get(m, i, j)
131
+ raise NotImplementedError
132
+ end
133
+
134
+ #
135
+ # Calculate the product of two matrices or
136
+ # the product of a matrix and a scalar.
137
+ #
138
+ # @param m first matrix
139
+ # @param n second matrix or scalar
140
+ # @return the matrix product as newly allocated matrix
141
+ # @abstract
142
+ #
143
+ def MatrixInterface.prod(m, n)
144
+ raise NotImplementedError
145
+ end
146
+
147
+ #
148
+ # Componentwise addition of two matrices.
149
+ #
150
+ # @param m first matrix
151
+ # @param n second matrix
152
+ # @return the matrix addition as newly allocated matrix
153
+ # @abstract
154
+ def MatrixInterface.add(m, n)
155
+ raise NotImplementedError
156
+ end
157
+
158
+ #
159
+ # Componentwise subtraction of two matrices.
160
+ #
161
+ # @param m first matrix
162
+ # @param n second matrix
163
+ # @return the matrix subtraction as newly allocated matrix
164
+ # @abstract
165
+ #
166
+ def MatrixInterface.sub(m, n)
167
+ raise NotImplementedError
168
+ end
169
+
170
+ #
171
+ # Transpose a matrix.
172
+ #
173
+ # @param m the matrix to transpose
174
+ # @return the transposed matrix as newly allocated matrix
175
+ # @abstract
176
+ #
177
+ def MatrixInterface.t(m)
178
+ raise NotImplementedError
179
+ end
180
+
181
+ #
182
+ # Compute the eigen-decomposition of a real symmetric matrix.
183
+ #
184
+ # The eigen-decomposition consists of a diagonal matrix +D+ containing
185
+ # the eigen values and a square matrix +N+ having the normalized eigenvectors
186
+ # in columns. It is assumed that the result of MatrixInterface#ed yields the
187
+ # matrices as an array and that the eigen-vectors and values are sorted in
188
+ # descending order of importance.
189
+ #
190
+ # @param m the matrix to decompose
191
+ # @return [Array] the array containing the matrix of eigen-values and eigen-vector
192
+ # @abstract
193
+ #
194
+ def MatrixInterface.ed(m)
195
+ raise NotImplementedError
196
+ end
197
+
198
+ #---------------------------------------
199
+ # Optional
200
+ # Methods having default implementations.
201
+ #---------------------------------------
202
+
203
+ #
204
+ # Create a new matrix and assign each element as the
205
+ # result of invoking the given block.
206
+ #
207
+ # @param [Integer] n the number of rows
208
+ # @param [Integer] m the number of columns.
209
+ # @return the newly created matrix.
210
+ #
211
+ def MatrixInterface.create_block(n, m, &block)
212
+ mat = self.create(n, m, 0.0)
213
+ for i in 0..self.nrows(mat)-1
214
+ for j in 0..self.ncols(mat)-1
215
+ self.set(mat, i, j, block.call(i,j))
216
+ end
217
+ end
218
+ mat
219
+ end
220
+
221
+ #
222
+ # Create a new matrix with uniform random elements.
223
+ #
224
+ # @param [Integer] n the number of rows
225
+ # @param [Integer] m the number of columns
226
+ # @param [Float] smin the minimum element value (inclusive).
227
+ # @param [Float] smax the maximum element value (inclusive).
228
+ # @return the newly created matrix.
229
+ #
230
+ def MatrixInterface.create_random(n, m, smin = -1.0, smax = 1.0)
231
+ range = smax - smin
232
+ self.create_block(n, m) do |i,j|
233
+ smin + range*rand()
234
+ end
235
+ end
236
+
237
+ #
238
+ # Create a new identity matrix.
239
+ #
240
+ # @param [Integer] n matrix dimension
241
+ # @return the newly created matrix.
242
+ #
243
+ def MatrixInterface.create_identity(n)
244
+ self.create_diagonal(*[1.0]*n)
245
+ end
246
+
247
+ #
248
+ # Create a new diagonal matrix.
249
+ #
250
+ # @param *elements the diagonal elements
251
+ # @return the newly created matrix
252
+ #
253
+ def MatrixInterface.create_diagonal(*elements)
254
+ n = elements.length
255
+ m = self.create(n, n, 0.0)
256
+ for i in 0..self.nrows(m)-1
257
+ self.set(m, i, i, elements[i])
258
+ end
259
+ m
260
+ end
261
+
262
+ #
263
+ # Create matrix from rows.
264
+ #
265
+ # @param [Array] rows the rows
266
+ # @return the newly created matrix
267
+ #
268
+ def MatrixInterface.create_rows(*rows)
269
+ nrows = rows.length
270
+
271
+ ncols = rows.first.length
272
+ self.create_block(nrows, ncols) do |i,j|
273
+ rows[i][j]
274
+ end
275
+ end
276
+
277
+ #
278
+ # Retrieve the diagonal elements as an array.
279
+ #
280
+ # The number of diagonals of an NxM matrix is
281
+ # defined as min(N,M).
282
+ #
283
+ # @param m the matrix
284
+ # @return diagonals of matrix as array.
285
+ #
286
+ def MatrixInterface.diagonals(m)
287
+ size = [self.nrows(m), self.ncols(m)].min
288
+ (0..size-1).map{|i| self.get(m,i,i)}
289
+ end
290
+
291
+ #
292
+ # Calculate the sum of diagonal matrix elements.
293
+ #
294
+ # @param m the matrix
295
+ # @return trace of matrix
296
+ #
297
+ def MatrixInterface.trace(m)
298
+ self.diagonals(m).inject(0) {|sum,e| sum += e}
299
+ end
300
+
301
+ #
302
+ # Returns matrix as array of columns.
303
+ #
304
+ # @return [Array<Array>] the array of columns where each column is an array
305
+ #
306
+ def MatrixInterface.columns(m)
307
+ a = Array.new(self.ncols(m)) {Array.new(self.nrows(m))}
308
+ for i in 0..self.nrows(m)-1 do
309
+ for j in 0..self.ncols(m)-1 do
310
+ a[j][i] = self.get(m, i, j)
311
+ end
312
+ end
313
+ a
314
+ end
315
+
316
+ #
317
+ # Returns matrix as array of rows.
318
+ #
319
+ # @return [Array<Array>] the array of rows where each rows is an array
320
+ #
321
+ def MatrixInterface.rows(m)
322
+ a = Array.new(self.nrows(m)) {Array.new(self.ncols(m))}
323
+ for i in 0..self.nrows(m)-1 do
324
+ for j in 0..self.ncols(m)-1 do
325
+ a[i][j] = self.get(m, i, j)
326
+ end
327
+ end
328
+ a
329
+ end
330
+
331
+ #
332
+ # Calculate minor matrix.
333
+ #
334
+ # @param m matrix to calculate minor from
335
+ # @param [Range] row_range linear row range with step size equal to one.
336
+ # @param [Range] col_range linear column range with step size equal to one.
337
+ #
338
+ def MatrixInterface.minor(m, row_range, col_range)
339
+ nrows = (row_range.last - row_range.first) + 1
340
+ ncols = (col_range.last - col_range.first) + 1
341
+ self.create_block(nrows, ncols) do |i,j|
342
+ self.get(m, i + row_range.first, j + col_range.first)
343
+ end
344
+ end
345
+
346
+ #
347
+ # Convert to string.
348
+ #
349
+ # Invokes #to_s from wrapped matrix.
350
+ #
351
+ # @return wrapped matrix as string.
352
+ #
353
+ def to_s(m)
354
+ m.to_s
355
+ end
356
+
357
+ end
358
+ end