matrix_gem 0.1.0 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dead9ede19c10d0e07aab6515af1c7b9beb37a03
4
- data.tar.gz: 8982a7fb48c26c4ce88891d3c6308fd0d265b05a
3
+ metadata.gz: bc7ba70b852af0c334f8206cd216b1ff2dbf4d33
4
+ data.tar.gz: 8ce5d4a3281b74f3920886c427c6d9a22791fea4
5
5
  SHA512:
6
- metadata.gz: 2b5630df3882796c82788bdcb787938a6a121d2222ee81228deba8494bcda0267d380bc1aa662d31b5905a49d95147a975c5864107ed84767e075273e1b90d4a
7
- data.tar.gz: f956702d425022d394d4597437bcf6ddc2f53e375261c4b3eb91415b6f0daf4f7ccfdace759660e24cabbe916b7d780c73704d2212d4baf58f63968e36f5eb89
6
+ metadata.gz: bc66b52f0908a2c87e4e15492cddd2ddc3648bbd2bee0907785a2c2730d0bca7b429e7eefef20ee901dcdd90d109a5e2d7df7244cb805237f6e6ec1b35a2921e
7
+ data.tar.gz: 0071e0d34d392db460c59645dd49f7b23b6ed6e556f78258ee3d1403d126ad8562b9a53e50f1e869b9d51f761badc1698a74badf9d0b852b462761947f6adb32
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+ Bundler.setup
4
+
5
+ require 'rake/testtask'
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs << 'test'
9
+ end
10
+
11
+ desc "Run tests"
12
+ task :default => :test
@@ -0,0 +1,109 @@
1
+
2
+
3
+ class Diagonal_Matrix < Matrix
4
+
5
+ # Creates a matrix by given rows, columns, and nums where the diagonal elements are composed of nums.
6
+ # With given only rows create identity matrix.
7
+ def initialize(rows, cols = nil, *nums)
8
+ if cols == nil
9
+ @matrix = identity rows
10
+ elsif nums.length != [rows, cols].min
11
+ raise MatrixArgumentError,
12
+ "Wrong number of arguments (#{2 + nums.length} for #{2 + [rows, cols].min})"
13
+ else
14
+ @matrix = []
15
+ rows.times do |row|
16
+ @matrix[row] = []
17
+ cols.times do |col|
18
+ if row == col
19
+ @matrix[row][col] = nums[row]
20
+ else
21
+ @matrix[row][col] = 0
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ class << self
29
+ # Creates a matrix where the diagonal elements are composed of nums.
30
+ def diagonal(*nums)
31
+ size = nums.length
32
+ Diagonal_Matrix.new size, size, *(nums)
33
+ end
34
+
35
+ # Creates a zero matrix with dimension equal to n.
36
+ def zero(n)
37
+ Diagonal_Matrix.diagonal(*(Array.new(n, 0)))
38
+ end
39
+
40
+ def identity(n)
41
+ Diagonal_Matrix.new n
42
+ end
43
+ end
44
+
45
+ # Set element on main diagonal
46
+ def []=(i, j = nil, value)
47
+ if j != nil && i != j
48
+ raise MatrixIndexOutOfRange,
49
+ "You can set only elements on main diagonal in a diagonal matrix."
50
+ elsif @matrix.size <= i
51
+ raise MatrixIndexOutOfRange
52
+ end
53
+ @matrix[i][i] = value
54
+ end
55
+
56
+ # Sum values on main diagonal of two matrices.
57
+ # Raises error if 'matrix' is not a Matrix or if matrices dimensions mismatch.
58
+ def +(matrix)
59
+ sum_validation(self, matrix)
60
+ values = self.diagonal_values.zip(matrix.diagonal_values).map{ |i| i.inject(:+) }
61
+ Diagonal_Matrix.new self.m, self.n, *(values)
62
+ end
63
+
64
+ # Returns the difference of values on main diagonal of two matrices in new matrix.
65
+ # Raises error if 'matrix' is not a Matrix or if matrices dimensions mismatch.
66
+ def -(matrix)
67
+ sum_validation(self, matrix)
68
+ values = self.diagonal_values.zip(matrix.diagonal_values).map{ |i| i.inject(:-) }
69
+
70
+ Diagonal_Matrix.new self.m, self.n, *(values)
71
+ end
72
+
73
+ # Matrix multiplication. Returns new instance of Diagonal_Matrix.
74
+ # Raises error if product can't be instance of Diagonal_Matrix.
75
+ def *(matrix)
76
+ product = super(matrix)
77
+ raise MatrixInvalidValue, "Product of multiplication is not diagonal matrix." if product.diagonal?
78
+
79
+ Diagonal_Matrix.new(product.m, product.n, *(product.diagonal_values))
80
+ end
81
+
82
+ # Matrix division (multiplication by the inverse).
83
+ # Raises error if difference can't be instance of Diagonal_Matrix.
84
+ # Raises error if matrix is not invertible.
85
+ def /(matrix)
86
+ diff = super(matrix)
87
+ raise MatrixInvalidValue, "Difference of matrices in not a diagonal matrix." if diff.diagonal?
88
+
89
+ Diagonal_Matrix.new(diff.m, diff.n, *(diff.diagonal_values))
90
+ end
91
+
92
+ # Returns the determinant of the matrix.
93
+ def det
94
+ is_square_validation self
95
+ self.diagonal_values.reduce(:*)
96
+ end
97
+
98
+ private
99
+
100
+ def non_main_diagonal_elements?(matrix)
101
+ matrix.m.times do |i|
102
+ matrix.n.times do |j|
103
+ return true if ((i != j) && (matrix[i,j] != 0))
104
+ end
105
+ end
106
+ false
107
+ end
108
+ end
109
+
@@ -0,0 +1,371 @@
1
+ class Matrix
2
+ include MatrixErr
3
+ include Properties
4
+ include Enumerable
5
+
6
+ #---------Initialize the matrix--------
7
+ # 1. Matrix with values
8
+ # Matrix.new(rows, cols, numbers) // numbers = rows*cols
9
+ # 2. Matrix only with dimension(rows and cols) make Identity matrix with dimension
10
+ # equal to rows
11
+ # Matrix.new(rows, cols)
12
+ def initialize(rows, cols, *nums)
13
+ if rows < 1 || cols < 1
14
+ raise MatrixArgumentError, "Rows and Columns should be positive numbers!"
15
+ elsif ((cols.is_a? Float) || (rows.is_a? Float))
16
+ raise MatrixArgumentError, "Dimension of matrix can't be floating point number"
17
+ elsif nums.length == 0
18
+ @matrix = identity rows
19
+ elsif rows * cols == nums.length
20
+ @matrix = matrix_with_values nums, cols
21
+ else
22
+ raise MatrixArgumentError,
23
+ "Wrong number of arguments (#{2 + nums.length} for #{2 + rows * cols})"
24
+ end
25
+ @matrix
26
+ end
27
+
28
+ class << self
29
+
30
+ # Creates an n by n zero matrix.
31
+ def zero(n)
32
+ values = Array.new(n*n, 0)
33
+ Matrix.new n, n, *(values)
34
+ end
35
+
36
+ # Creates a matrix where the diagonal elements are composed of values.
37
+ def diagonal(*nums)
38
+ raise ArgumentError, "Matrix values can't be nil" if nums.include? nil
39
+ size = nums.length
40
+ matrix_values = []
41
+ Array.new(size) { |i| Array.new(size) do |j|
42
+ if i == j
43
+ matrix_values << nums[i]
44
+ else
45
+ matrix_values << 0
46
+ end
47
+ end
48
+ }
49
+ Matrix.new(size, size, *(matrix_values))
50
+ end
51
+
52
+ # Creates an n by n identity matrix.
53
+ def identity(n)
54
+ Matrix.new n, n
55
+ end
56
+ end
57
+
58
+ # Return the sum of two matrices in new matrix
59
+ # Raises an error if matrices dimension mismatch.
60
+ def +(matrix)
61
+ sum_validation(self, matrix)
62
+ values = self.zip(matrix).map{ |i| i.inject(:+) }
63
+
64
+ Matrix.new self.m, self.n, *(values)
65
+ end
66
+
67
+ # Return the difference of two matrices in new matrix.
68
+ # Raises an error if matrices dimension mismatch.
69
+ def -(matrix)
70
+ sum_validation(self, matrix)
71
+ values = self.zip(matrix).map{|i| i.inject(:-)}
72
+
73
+ Matrix.new self.m, self.n, *(values)
74
+ end
75
+
76
+ # Matrix multiplication.
77
+ def *(matrix)
78
+ case(matrix)
79
+ when Numeric
80
+ new_matrix_values = []
81
+ self.each { |x| new_matrix_values << x * matrix }
82
+ Matrix.new self.m, self.n, *(new_matrix_values)
83
+ when Matrix
84
+ multiply_validation self, matrix
85
+ rows = Array.new(self.m) { |i|
86
+ Array.new(matrix.n) { |j|
87
+ (0 ... self.n).inject(0) do |vij, k|
88
+ vij + self[i, k] * matrix[k, j]
89
+ end
90
+ }
91
+ }
92
+ values = []
93
+ rows.each{ |x| x.each { |y| values << y} }
94
+ Matrix.new self.m, matrix.n, *(values)
95
+ end
96
+ end
97
+
98
+ # Matrix division (multiplication by the inverse).
99
+ def /(matrix)
100
+ case matrix
101
+ when Numeric
102
+ new_matrix_values = []
103
+ self.each { |x| new_matrix_values << x / matrix.to_f }
104
+ Matrix.new self.m, self.n, *(new_matrix_values)
105
+ when Matrix
106
+ self * matrix.inversed
107
+ end
108
+ end
109
+
110
+ # Returns element (i,j) of the matrix. That is: row i, column j.
111
+ # If only i is given return row[i]. That is: row with index i.
112
+ def [](i, j = nil)
113
+ if j == nil
114
+ @matrix[i]
115
+ else
116
+ @matrix[i][j]
117
+ end
118
+ end
119
+
120
+ # Set element (i,j) of the matrix. That is: row i, column j.
121
+ # Set row i of the matrix if j is not given. That is: column j.
122
+ # Also aliased as set_element
123
+ def []=(i, j = nil, val)
124
+ if j == nil
125
+ raise ErrDimensionMismatch if val.length != self.m
126
+ @matrix[i] = val
127
+ elsif (i < self.m && j < self.n)
128
+ @matrix[i][j] = val
129
+ end
130
+ end
131
+ alias set_element []=
132
+
133
+ # Return a new matrix which is the transposition of the given one.
134
+ def transposed
135
+ elements = []
136
+ @matrix.to_a.transpose.map{ |x| x.map{ |y| elements << y } }
137
+ Matrix.new self.m, self.n, *(elements)
138
+ end
139
+
140
+ # Transpose the matrix.
141
+ # Also aliased as t().
142
+ def transpose
143
+ elements = []
144
+ @matrix.to_a.transpose.map{ |x| x.map{ |y| elements << y } }
145
+ @matrix = elements.each_slice(@matrix[0].length).to_a
146
+ self
147
+ end
148
+ alias t transpose
149
+
150
+ #Each method.
151
+ def each
152
+ @matrix.each do |sub_arr|
153
+ sub_arr.each do |value|
154
+ yield value
155
+ end
156
+ end
157
+ end
158
+
159
+ # Returns true if and only if the two matrices contain equal elements.
160
+ def ==(matrix)
161
+ (0..self.m-1).each do |i|
162
+ (0..self.n-1).each do |j|
163
+ return false if self[i][j] != matrix[i][j]
164
+ end
165
+ end
166
+ true
167
+ end
168
+
169
+ # Returns the determinant of the matrix.
170
+ # Also alised as determinant()
171
+ def det
172
+ is_square_validation self
173
+
174
+ _this = copy(self)
175
+ c = 1
176
+ new_matrix = nil
177
+ size = _this.n
178
+
179
+ (0..size - 2).each do |i|
180
+ (i + 1..size -1).each do |j|
181
+ if _this[i][i] == 0
182
+ (i+1..size-1).each do |k|
183
+ if _this[k,i] != 0
184
+ swap_rows(_this, k, i)
185
+ c *= -1
186
+ end
187
+ end
188
+ end
189
+ if _this[i,i] == 0
190
+ return 0
191
+ end
192
+
193
+ new_matrix = cauchy_method(_this, i, j, -_this[j,i]/_this[i,i].to_f)
194
+ end
195
+ end
196
+
197
+ det = 1
198
+
199
+ (0..size-1).each do |i|
200
+ det *= new_matrix[i][i]
201
+ end
202
+
203
+ det *= c
204
+ det.round
205
+ end
206
+ alias determinant det
207
+
208
+ # Returns new matrix witch is the inverse of the matrix.
209
+ def inversed
210
+ is_square_validation self
211
+ raise ErrZeroDeterminant if self.det == 0
212
+
213
+ _this = copy(self)
214
+ c = 1
215
+ e = Matrix.new _this.m, _this.n
216
+ size = _this.m
217
+
218
+ (0..size-2).each do |i|
219
+ (i+1..size-1).each do |j|
220
+ if _this[i, i] == 0
221
+ (i..size-2).each do |k|
222
+ if _this[k, i] != 0
223
+ swap_rows(_this, k, i)
224
+ swap_rows(e, k, i)
225
+ c *= -1
226
+ end
227
+ end
228
+ end
229
+
230
+ return 0 if _this[i, i] == 0
231
+
232
+ cauchy_method(e, i, j, -_this[j, i]/_this[i, i].to_f)
233
+ cauchy_method(_this, i, j, -_this[j, i]/_this[i, i].to_f)
234
+ end
235
+ end
236
+
237
+ (0..size-2).each do |i|
238
+ (i+1..size-1).each do |j|
239
+
240
+ cauchy_method(e, size-i-1, size-j-1, -_this[size-j-1, size-i-1]/_this[size-i-1, size-i-1])
241
+
242
+ cauchy_method(_this, size-i-1, size-j-1, -_this[size-j-1, size-i-1]/_this[size-i-1, size-i-1])
243
+ end
244
+ end
245
+
246
+ (0..size-1).each do |i|
247
+ e.set_row i, multiply_row(e, i, 1/_this[i,i])
248
+ _this.set_row i, multiply_row(_this, i, 1/_this[i,i])
249
+ end
250
+ Matrix.new self.m, self.m, *(e)
251
+ end
252
+
253
+ # Chanege matrix to its inversed.
254
+ def inverse
255
+ elements = []
256
+ self.inversed.each{ |x| elements << x}
257
+ @matrix = elements.each_slice(@matrix[0].length).to_a
258
+ self
259
+ end
260
+
261
+ # To stirng method.
262
+ def to_str
263
+ a = "Matrix\n" + @matrix.map do |row|
264
+ "[" + row.map do |e|
265
+ e.to_s
266
+ end.join(" ") + "]"
267
+ end.join(",\n")
268
+ puts a
269
+ end
270
+
271
+ # Matrix exponentiation. Equivalent to multiplying the matrix by itself N times.
272
+ def **(n)
273
+ raise MatrixArgumentError if !(n.is_a? Integer)
274
+ matrix = Matrix.identity(self.m)
275
+ n.times { |_| matrix *= self } if self.square?
276
+ matrix
277
+ end
278
+
279
+ def minor(*param)
280
+ row_range, col_range = param
281
+
282
+ from_row = row_range.first
283
+ form_row += self.m if from_row < 0
284
+ to_row = row_range.end
285
+ to_row += self.m if to_row < 0
286
+ to_row += 1 unless row_range.exclude_end?
287
+ size_row = to_row - from_row
288
+
289
+ from_col = col_range.first
290
+ from_col += self.n if from_col < 0
291
+ to_col = col_range.end
292
+ to_col += self.n if from_col < 0
293
+ to_col += 1 unless col_range.exclude_end?
294
+ size_col = to_col - from_col
295
+ return nil if from_row > row_count || from_col > column_count ||
296
+ from_row < 0 || from_col < 0
297
+ rows = @matrix[from_row, size_row].collect{ |row| row[from_col, size_col] }
298
+ values = []
299
+ rows.each{ |row| row.each {|val| values << val } }
300
+ Matrix.new [self.m - from_row, size_row].min, [self.n - from_col, size_col].min, *(values)
301
+ end
302
+
303
+ private
304
+
305
+ # Swap to matrix rows.
306
+ def swap_rows(_this, row1_index, row2_index)
307
+ _this[row1_index], _this[row2_index] = _this[row2_index], _this[row1_index]
308
+ end
309
+
310
+ # Return new instance of Matrix with same values.
311
+ def copy(_this)
312
+ values = []
313
+ _this.each{ |row| values << row }
314
+ copy = Matrix.new _this.m, _this.n, *(values)
315
+ end
316
+
317
+ # Multiply the first row elements with multiplier and sum it with second row
318
+ # elements.
319
+ # Used to make matrix in triangular form.
320
+ def cauchy_method(_this, row1_index, row2_index, multiplier)
321
+ _this.row(row2_index).each_with_index do |row_element, i|
322
+ _this.row(row2_index)[i] += _this[row1_index][i] * multiplier
323
+ end
324
+ _this
325
+ end
326
+
327
+ # Check if caller matrix columns are equal to other matrix rows.
328
+ def multiply_validation(_this, matrix)
329
+ raise ErrDimensionMismatch if _this.col_size != matrix.row_size
330
+ end
331
+
332
+ # Check if matrix rows are equals to its columns.
333
+ def is_square_validation(_this)
334
+ raise NoSquareMatrix if _this.m != _this.n
335
+ end
336
+
337
+ # Check if matrices have same dimensions.
338
+ def sum_validation(_this, matrix)
339
+ raise ErrOperationNotDefine if !matrix.is_a? Matrix
340
+ raise ErrDimensionMismatch if matrix.m != _this.m || matrix.n != _this.n
341
+ end
342
+
343
+ # Make Identity matrix.
344
+ def identity(dimension)
345
+ id_matrix = []
346
+ dimension.times do |x|
347
+ id_matrix[x] = []
348
+ dimension.times do |y|
349
+ if x == y
350
+ id_matrix[x][y] = 1
351
+ else
352
+ id_matrix[x][y] = 0
353
+ end
354
+ end
355
+ end
356
+ return id_matrix
357
+ end
358
+
359
+ # Multiplication of matrix row with number.
360
+ def multiply_row(matrix, index, number)
361
+ matrix = matrix.row(index).map{ |n| n * number }
362
+ end
363
+
364
+ # Format values.
365
+ def matrix_with_values(values, col_length)
366
+ matrixNums = values.each_slice(col_length).to_a
367
+ end
368
+
369
+ end
370
+
371
+
@@ -3,9 +3,15 @@ module MatrixErr
3
3
  class Matrix_Error < StandardError
4
4
  end
5
5
 
6
+ class MatrixInvalidValue < StandardError
7
+ end
8
+
6
9
  class MatrixArgumentError < Matrix_Error
7
10
  end
8
11
 
12
+ class MatrixIndexOutOfRange < Matrix_Error
13
+ end
14
+
9
15
  class ErrOperationNotDefine < Matrix_Error
10
16
  def message
11
17
  "Operation is not define!"
@@ -29,5 +35,4 @@ module MatrixErr
29
35
  "Matrix determinant should be not equal to zero!"
30
36
  end
31
37
  end
32
-
33
38
  end
@@ -0,0 +1,26 @@
1
+ class Orthogonal_Matrix < Matrix
2
+
3
+ # Initialize orthogonal matrix (square matrix and its transpose is equal to its inverse).
4
+ def initialize(rows, cols, *nums)
5
+ if !(Matrix.new rows, cols, *(nums)).orthogonal?
6
+ raise MatrixArgumentError,
7
+ "Can't initialize orthogonal matrix with this values."
8
+ elsif nums.length == 0
9
+ @matrix = identity rows
10
+ else
11
+ @matrix = matrix_with_values nums, cols
12
+ end
13
+ end
14
+
15
+ # Set element.
16
+ # Raise error if the matrix with new value is not orthogonal.
17
+ def []=(i, j, value)
18
+ b = copy(self)
19
+ b[i,j] = value
20
+ if b.orthogonal?
21
+ @matrix[i][j] = value
22
+ else
23
+ raise MatrixIndexOutOfRange, 'The matrix must be orthogonal.'
24
+ end
25
+ end
26
+ end
@@ -1,9 +1,44 @@
1
1
  module Properties
2
+
3
+ include MatrixErr
4
+
2
5
  # Returns an array of arrays that describe the rows of the matrix.
3
6
  def to_a
4
7
  self
5
8
  end
6
9
 
10
+ # Make all values floating point.
11
+ def to_f
12
+ (0..self.n - 1).each{ |i| (0..self.m - 1).each do
13
+ |j| self[i,j] = self[i,j].to_f
14
+ end }
15
+ self
16
+ end
17
+
18
+ # Return array with values on main diagonal.
19
+ def diagonal_values
20
+ size = ([self.m, self.n].min) -1
21
+ values = []
22
+
23
+ (0..size).each do |i|
24
+ values << self[i][i]
25
+ end
26
+ values
27
+ end
28
+
29
+ # Set values on main diagonal.
30
+ # Raise error if nums are less than matrix main diagonal length
31
+ # Also aliased as set_diagonal_values
32
+ def set_diagonal(*nums)
33
+ size = ([self.m, self.n].min) -1
34
+ raise MatrixArgumentError, 'Wrong number of arguments.' if nums.length < size + 1
35
+ (0..size).each do |i|
36
+ self[i,i] = nums[i]
37
+ end
38
+ self
39
+ end
40
+ alias set_diagonal_values set_diagonal
41
+
7
42
  # Returns the number of columns.
8
43
  # Also aliased as n(), col_size(), column_count()
9
44
  def col_length
@@ -27,21 +62,70 @@ module Properties
27
62
  alias col_size col_length
28
63
  alias column_count n
29
64
 
30
- # Retun row on index.
65
+ # Retuns array with row on index as values.
31
66
  def row(index)
32
67
  self[index]
33
68
  end
34
69
 
35
- # Set value of matrix row.
36
- def row_change(index, elements)
70
+ # Returns array with column on index as values.
71
+ # Also aliased as column()
72
+ def col(index)
73
+ column = []
74
+ (0..self.m-1).each{ |x| column << self[x, index] }
75
+ column
76
+ end
77
+ alias column col
78
+
79
+ # Set values of matrix row. Elements shoud be an array of values
80
+ # Raise error if length of elements is not equal to matrix row length.
81
+ def set_row(index, elements)
82
+ raise MatrixArgumentError, 'Different length of elements and row length' if
83
+ elements.length != self.row_length
37
84
  self[index] = elements
85
+ self
38
86
  end
39
87
 
40
- # Return col on index
41
- # Also aliased as column()
42
- def col(index)
43
- self.each { |a| p a[index] }
88
+ # Set values of matrix column. Elements shoud be an array of values.
89
+ # Raise error if length of elements is not equal to matrix column length.
90
+ def set_col(index, elements)
91
+ raise MatrixArgumentError, 'Different length of elements and column length' if elements.length != self.col_length
92
+ (0..self.m-1).each{ |x| self[x, index] = elements[x] }
93
+ self
44
94
  end
45
95
 
46
- alias column col
96
+ # Returns true if there is values not equal to 0 only on main diagonal.
97
+ # Also aliased as diagonal?
98
+ def is_diagonal
99
+ (0..self.m-1).each do |i|
100
+ (0..self.m-1).each do |j|
101
+ return false if ((self[i,j] != 0 && i != j))
102
+ end
103
+ end
104
+ true
105
+ end
106
+ alias diagonal? is_diagonal
107
+
108
+ # Returns true if this is a matrix with only zero elements.
109
+ # Also aliased as is_zero
110
+ def zero?
111
+ self.map{ |x| return false if x != 0 }
112
+ true
113
+ end
114
+ alias is_zero zero?
115
+
116
+ # Returns true if this is a matrix with equal rows and columns.
117
+ # Also aliased as square?
118
+ def is_square
119
+ return false if self.m != self.n
120
+ true
121
+ end
122
+ alias square? is_square
123
+
124
+ # Returns true if this is square matrix and its transpose is equal to its inverse.
125
+ # Also aliased as is_zero
126
+ def orthogonal?
127
+ return true if ((self.is_square) && (self.transposed == self.inversed))
128
+ false
129
+ end
130
+ alias is_orthogonal orthogonal?
47
131
  end
data/lib/matrix_gem.rb CHANGED
@@ -1,305 +1,6 @@
1
- require 'matrix_gem/matrix_err'
2
- require 'matrix_gem/properties_module'
3
-
4
-
5
- class Matrix
6
- include MatrixErr
7
- include Properties
8
- include Enumerable
9
-
10
- #---------Initialize the matrix------
11
- # 1. Matrix with values
12
- # Matrix.new(rows, cols, numbers) // numbers = rows*cols
13
- # 2. Matrix only with dimention(rows and cols) make Identity matrix
14
- # Matrix.new(rows, cols)
15
- def initialize(rows, cols, *nums)
16
- if rows < 1 || cols < 1
17
- raise MatrixArgumentError, "Rows and Columns should be positive numbers!"
18
- elsif nums.length == 0
19
- @matrix = identity cols
20
- elsif rows * cols == nums.length
21
- @matrix = matrix_with_values nums, cols
22
- else
23
- raise MatrixArgumentError,
24
- "Wrong number of arguments (#{2 + nums.length} for #{2 + rows * cols})"
25
- end
26
- @matrix
27
- end
28
-
29
- #Return the sum of two matrices in new matrix
30
- def +(matrix)
31
- sum_validation(matrix, self)
32
- values = self.zip(matrix).map{|i| i.inject(:+)}
33
-
34
- Matrix.new self.m, self.n, *(values)
35
- end
36
-
37
- #Return the difference of two matrices in new matrix
38
- def -(matrix)
39
- sum_validation(matrix, self)
40
- values = self.zip(matrix).map{|i| i.inject(:-)}
41
-
42
- Matrix.new self.m, self.n, *(values)
43
- end
44
-
45
- # Returns element (i,j) of the matrix. That is: row i, column j.
46
- # If only i is given return row[i]. That is: row with index i.
47
- def [](i, j = nil)
48
- if j == nil
49
- @matrix[i]
50
- else
51
- @matrix[i][j]
52
- end
53
- end
54
-
55
- # Set element (i,j) of the matrix. That is: row i, column j.
56
- # Set row i of the matrix if j is not given. That is: column j.
57
- # Also aliased as set_element
58
- def []=(i, j = nil, val)
59
- if j == nil
60
- raise ErrDimensionMismatch if val.length != self.m
61
- @matrix[i] = val
62
- else
63
- @matrix[i][j] = val
64
- end
65
- end
66
- alias set_element []=
67
-
68
- # Return a new matrix which is the transposition of the given one.
69
- def transposed
70
- elements = []
71
- @matrix.to_a.transpose.map{ |x| x.map{ |y| elements << y } }
72
- Matrix.new self.m, self.n, *(elements)
73
- end
74
-
75
- # Transpose the matrix.
76
- # Also aliased as t().
77
- def transpose
78
- elements = []
79
- @matrix.to_a.transpose.map{ |x| x.map{ |y| elements << y } }
80
- @matrix = elements.each_slice(@matrix[0].length).to_a
81
- end
82
- alias t transpose
83
-
84
- #Each method.
85
- def each
86
- @matrix.each do |sub_arr|
87
- sub_arr.each do |value|
88
- yield value
89
- end
90
- end
91
- end
92
-
93
- # Returns true if and only if the two matrices contain equal elements.
94
- def ==(matrix)
95
- matrix.to_a == self.to_a
96
- end
97
-
98
- # Matrix multiplication.
99
- def *(m)
100
- case(m)
101
- when Numeric
102
- new_matrix_values = []
103
- self.each { |x| new_matrix_values << x * m }
104
- Matrix.new self.m, self.n, *(new_matrix_values)
105
- when Matrix
106
- multiply_validation self, m
107
- rows = Array.new(self.m) { |i|
108
- Array.new(m.n) { |j|
109
- (0 ... m.n ).inject(0) do |vij, k|
110
- vij + self[i, k] * m[k, j]
111
- end
112
- }
113
- }
114
- end
115
- end
116
-
117
- # Returns the determinant of the matrix.
118
- # Also alised as determinant()
119
- def det
120
- is_square_validation self
121
-
122
- _this = copy(self)
123
- c = 1
124
- new_matrix = nil
125
- size = _this.n
126
-
127
- (0..size - 2).each do |i|
128
- (i + 1..size -1).each do |j|
129
- if _this[i][i] == 0
130
- (i+1..size-1).each do |k|
131
- if _this[k,i] != 0
132
- swap_rows(_this, k, i)
133
- c *= -1
134
- end
135
- end
136
- end
137
- if _this[i,i] == 0
138
- p _this
139
- return 0
140
- end
141
-
142
- new_matrix = cauchy_method(_this, i, j, -_this[j,i]/_this[i,i].to_f)
143
- end
144
- end
145
-
146
- det = 1
147
-
148
- (0..size-1).each do |i|
149
- det *= new_matrix[i][i]
150
- end
151
-
152
- det *= c
153
- det.round
154
- end
155
- alias determinant det
156
-
157
- # Multiplication of matrix row with number.
158
- def multiply_row(matrix, index, number)
159
- matrix = matrix.row(index).map{ |n| n*number }
160
- end
161
-
162
- # Returns the inverse of the matrix.
163
- def inverse
164
- is_square_validation self
165
- raise ErrZeroDeterminant if self.det == 0
166
-
167
- _this = copy(self)
168
- c = 1
169
- e = Matrix.new _this.m, _this.n
170
- size = _this.m
171
-
172
- (0..size-2).each do |i|
173
- (i+1..size-1).each do |j|
174
- if _this[i, i] == 0
175
- (i..size-2).each do |k|
176
- if _this[k, i] != 0
177
- swap_rows(_this, k, i)
178
- swap_rows(e, k, i)
179
- c *= -1
180
- end
181
- end
182
- end
183
-
184
- return 0 if _this[i, i] == 0
185
-
186
- cauchy_method(e, i, j, -_this[j, i]/_this[i, i].to_f)
187
- cauchy_method(_this, i, j, -_this[j, i]/_this[i, i].to_f)
188
- end
189
- end
190
-
191
- (0..size-2).each do |i|
192
- (i+1..size-1).each do |j|
193
-
194
- cauchy_method(e, size-i-1, size-j-1, -_this[size-j-1, size-i-1]/_this[size-i-1, size-i-1])
195
-
196
- cauchy_method(_this, size-i-1, size-j-1, -_this[size-j-1, size-i-1]/_this[size-i-1, size-i-1])
197
- end
198
- end
199
-
200
- (0..size-1).each do |i|
201
- e.row_change i, multiply_row(e, i, 1/_this[i,i])
202
- _this.row_change i, multiply_row(_this, i, 1/_this[i,i])
203
- end
204
- e
205
- end
206
-
207
- # Chanege matrix to its inversed.
208
- def inversed
209
- elements = []
210
- self.inverse.each{ |x| elements << x}
211
- @matrix = elements.each_slice(@matrix[0].length).to_a
212
- end
213
-
214
- # def to_s
215
- # "Matrix[" + @matrix.map{|row|
216
- # "[" + row.map{|e| e.to_s}.join("\t") + "]"
217
- # }.join(", ") + "]"
218
- # end
219
-
220
- private
221
-
222
- # Swap to matrix rows.
223
- def swap_rows(_this, row1_index, row2_index)
224
- _this[row1_index], _this[row2_index] = _this[row2_index], _this[row1_index]
225
- end
226
-
227
- # Return new instance of Matrix with same values.
228
- def copy(_this)
229
- values = []
230
- _this.each{ |row| values << row }
231
- copy = Matrix.new _this.m, _this.n, *(values)
232
- end
233
-
234
- # Multiply the first row elements with multiplier and sum it with second row
235
- # elements.
236
- # Used to make matrix in triangular form.
237
- def cauchy_method(_this, row1_index, row2_index, multiplier)
238
- _this.row(row2_index).each_with_index do |row_element, i|
239
- _this.row(row2_index)[i] += _this[row1_index][i] * multiplier
240
- end
241
- _this
242
- end
243
-
244
- # Check if caller matrix columns are equal to other matrix rows.
245
- def multiply_validation(_this, matrix)
246
- raise ErrDimensionMismatch if _this.n != matrix.m
247
- end
248
-
249
- # Check if matrix rows are equals to its columns.
250
- def is_square_validation(_this)
251
- raise NoSquareMatrix if _this.m != _this.n
252
- end
253
-
254
- # Check if matrices have same dimentions.
255
- def sum_validation(_this, matrix)
256
- raise ErrOperationNotDefine if matrix.is_a? Numeric
257
- raise ErrDimensionMismatch if matrix.m != _this.m || matrix.n != _this.n
258
- end
259
-
260
- # Make Identity matrix.
261
- def identity(dimension)
262
- id_matrix = []
263
- dimension.times do |x|
264
- id_matrix[x] = []
265
- dimension.times do |y|
266
- if x == y
267
- id_matrix[x][y] = 1
268
- else
269
- id_matrix[x][y] = 0
270
- end
271
- end
272
- end
273
- return id_matrix
274
- end
275
-
276
- # Format values.
277
- def matrix_with_values(values, col_length)
278
- matrixNums = values.each_slice(col_length).to_a
279
- end
280
- end
281
-
282
-
283
- a = Matrix.new 3,3,1,2,57,1,3,43,5,6,70
284
- # p a
285
- c = Matrix.new 2,2,4,3,3,2
286
- d = Matrix.new 3,3,2,3,1,1,2,1,3,5,3
287
- # d = Matrix.new 2,2,0,1,3,0
288
- # d = Matrix.new 2,2,0,9,5,2
289
-
290
-
291
- d = Matrix.new 3,3
292
-
293
- #
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
1
+ require_relative './matrix_gem/matrix_err'
2
+ require_relative './matrix_gem/properties_module'
3
+ require_relative './matrix_gem/matrix'
4
+ require_relative './matrix_gem/diagonal_matrix'
5
+ require_relative './matrix_gem/orthogonal_matrix'
305
6
 
metadata CHANGED
@@ -1,23 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matrix_gem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Grigorov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-11 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2015-02-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.4'
13
55
  description: Gem for work with matrices
14
56
  email: bojko002@gmail.com
15
57
  executables: []
16
58
  extensions: []
17
59
  extra_rdoc_files: []
18
60
  files:
61
+ - Rakefile
19
62
  - lib/matrix_gem.rb
63
+ - lib/matrix_gem/diagonal_matrix.rb
64
+ - lib/matrix_gem/matrix.rb
20
65
  - lib/matrix_gem/matrix_err.rb
66
+ - lib/matrix_gem/orthogonal_matrix.rb
21
67
  - lib/matrix_gem/properties_module.rb
22
68
  homepage: http://rubygems.org/gems/matrix_gem
23
69
  licenses: