rmds 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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