matrix 0.1.0 → 0.4.3

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.
data/lib/matrix.rb CHANGED
@@ -12,17 +12,44 @@
12
12
  # Original Documentation:: Gavin Sinclair (sourced from <i>Ruby in a Nutshell</i> (Matsumoto, O'Reilly))
13
13
  ##
14
14
 
15
- require "e2mmap"
15
+ require_relative "matrix/version"
16
16
 
17
17
  module ExceptionForMatrix # :nodoc:
18
- extend Exception2MessageMapper
19
- def_e2message(TypeError, "wrong argument type %s (expected %s)")
20
- def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)")
21
-
22
- def_exception("ErrDimensionMismatch", "\#{self.name} dimension mismatch")
23
- def_exception("ErrNotRegular", "Not Regular Matrix")
24
- def_exception("ErrOperationNotDefined", "Operation(%s) can\\'t be defined: %s op %s")
25
- def_exception("ErrOperationNotImplemented", "Sorry, Operation(%s) not implemented: %s op %s")
18
+ class ErrDimensionMismatch < StandardError
19
+ def initialize(val = nil)
20
+ if val
21
+ super(val)
22
+ else
23
+ super("Dimension mismatch")
24
+ end
25
+ end
26
+ end
27
+
28
+ class ErrNotRegular < StandardError
29
+ def initialize(val = nil)
30
+ if val
31
+ super(val)
32
+ else
33
+ super("Not Regular Matrix")
34
+ end
35
+ end
36
+ end
37
+
38
+ class ErrOperationNotDefined < StandardError
39
+ def initialize(vals)
40
+ if vals.is_a?(Array)
41
+ super("Operation(#{vals[0]}) can't be defined: #{vals[1]} op #{vals[2]}")
42
+ else
43
+ super(vals)
44
+ end
45
+ end
46
+ end
47
+
48
+ class ErrOperationNotImplemented < StandardError
49
+ def initialize(vals)
50
+ super("Sorry, Operation(#{vals[0]}) not implemented: #{vals[1]} op #{vals[2]}")
51
+ end
52
+ end
26
53
  end
27
54
 
28
55
  #
@@ -45,8 +72,8 @@ class Matrix
45
72
  #
46
73
  # Creates a matrix where each argument is a row.
47
74
  # Matrix[ [25, 93], [-1, 66] ]
48
- # => 25 93
49
- # -1 66
75
+ # # => 25 93
76
+ # # -1 66
50
77
  #
51
78
  def Matrix.[](*rows)
52
79
  rows(rows, false)
@@ -57,8 +84,8 @@ class Matrix
57
84
  # of the matrix. If the optional argument +copy+ is false, use the given
58
85
  # arrays as the internal structure of the matrix without copying.
59
86
  # Matrix.rows([[25, 93], [-1, 66]])
60
- # => 25 93
61
- # -1 66
87
+ # # => 25 93
88
+ # # -1 66
62
89
  #
63
90
  def Matrix.rows(rows, copy = true)
64
91
  rows = convert_to_array(rows, copy)
@@ -75,8 +102,8 @@ class Matrix
75
102
  #
76
103
  # Creates a matrix using +columns+ as an array of column vectors.
77
104
  # Matrix.columns([[25, 93], [-1, 66]])
78
- # => 25 -1
79
- # 93 66
105
+ # # => 25 -1
106
+ # # 93 66
80
107
  #
81
108
  def Matrix.columns(columns)
82
109
  rows(columns, false).transpose
@@ -89,9 +116,9 @@ class Matrix
89
116
  # Returns an enumerator if no block is given.
90
117
  #
91
118
  # m = Matrix.build(2, 4) {|row, col| col - row }
92
- # => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
119
+ # # => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
93
120
  # m = Matrix.build(3) { rand }
94
- # => a 3x3 matrix with random elements
121
+ # # => a 3x3 matrix with random elements
95
122
  #
96
123
  def Matrix.build(row_count, column_count = row_count)
97
124
  row_count = CoercionHelper.coerce_to_int(row_count)
@@ -109,9 +136,9 @@ class Matrix
109
136
  #
110
137
  # Creates a matrix where the diagonal elements are composed of +values+.
111
138
  # Matrix.diagonal(9, 5, -3)
112
- # => 9 0 0
113
- # 0 5 0
114
- # 0 0 -3
139
+ # # => 9 0 0
140
+ # # 0 5 0
141
+ # # 0 0 -3
115
142
  #
116
143
  def Matrix.diagonal(*values)
117
144
  size = values.size
@@ -128,8 +155,8 @@ class Matrix
128
155
  # Creates an +n+ by +n+ diagonal matrix where each diagonal element is
129
156
  # +value+.
130
157
  # Matrix.scalar(2, 5)
131
- # => 5 0
132
- # 0 5
158
+ # # => 5 0
159
+ # # 0 5
133
160
  #
134
161
  def Matrix.scalar(n, value)
135
162
  diagonal(*Array.new(n, value))
@@ -138,8 +165,8 @@ class Matrix
138
165
  #
139
166
  # Creates an +n+ by +n+ identity matrix.
140
167
  # Matrix.identity(2)
141
- # => 1 0
142
- # 0 1
168
+ # # => 1 0
169
+ # # 0 1
143
170
  #
144
171
  def Matrix.identity(n)
145
172
  scalar(n, 1)
@@ -152,8 +179,8 @@ class Matrix
152
179
  #
153
180
  # Creates a zero matrix.
154
181
  # Matrix.zero(2)
155
- # => 0 0
156
- # 0 0
182
+ # # => 0 0
183
+ # # 0 0
157
184
  #
158
185
  def Matrix.zero(row_count, column_count = row_count)
159
186
  rows = Array.new(row_count){Array.new(column_count, 0)}
@@ -164,7 +191,7 @@ class Matrix
164
191
  # Creates a single-row matrix where the values of that row are as given in
165
192
  # +row+.
166
193
  # Matrix.row_vector([4,5,6])
167
- # => 4 5 6
194
+ # # => 4 5 6
168
195
  #
169
196
  def Matrix.row_vector(row)
170
197
  row = convert_to_array(row)
@@ -175,9 +202,9 @@ class Matrix
175
202
  # Creates a single-column matrix where the values of that column are as given
176
203
  # in +column+.
177
204
  # Matrix.column_vector([4,5,6])
178
- # => 4
179
- # 5
180
- # 6
205
+ # # => 4
206
+ # # 5
207
+ # # 6
181
208
  #
182
209
  def Matrix.column_vector(column)
183
210
  column = convert_to_array(column)
@@ -190,12 +217,12 @@ class Matrix
190
217
  #
191
218
  # m = Matrix.empty(2, 0)
192
219
  # m == Matrix[ [], [] ]
193
- # => true
220
+ # # => true
194
221
  # n = Matrix.empty(0, 3)
195
222
  # n == Matrix.columns([ [], [], [] ])
196
- # => true
223
+ # # => true
197
224
  # m * n
198
- # => Matrix[[0, 0, 0], [0, 0, 0]]
225
+ # # => Matrix[[0, 0, 0], [0, 0, 0]]
199
226
  #
200
227
  def Matrix.empty(row_count = 0, column_count = 0)
201
228
  raise ArgumentError, "One size must be 0" if column_count != 0 && row_count != 0
@@ -249,6 +276,8 @@ class Matrix
249
276
  new result, total_column_count
250
277
  end
251
278
 
279
+ # :call-seq:
280
+ # Matrix.combine(*matrices) { |*elements| ... }
252
281
  #
253
282
  # Create a matrix by combining matrices entrywise, using the given block
254
283
  #
@@ -263,7 +292,7 @@ class Matrix
263
292
  matrices.map!(&CoercionHelper.method(:coerce_to_matrix))
264
293
  x = matrices.first
265
294
  matrices.each do |m|
266
- Matrix.Raise ErrDimensionMismatch unless x.row_count == m.row_count && x.column_count == m.column_count
295
+ raise ErrDimensionMismatch unless x.row_count == m.row_count && x.column_count == m.column_count
267
296
  end
268
297
 
269
298
  rows = Array.new(x.row_count) do |i|
@@ -274,12 +303,21 @@ class Matrix
274
303
  new rows, x.column_count
275
304
  end
276
305
 
306
+ # :call-seq:
307
+ # combine(*other_matrices) { |*elements| ... }
308
+ #
309
+ # Creates new matrix by combining with <i>other_matrices</i> entrywise,
310
+ # using the given block.
311
+ #
312
+ # x = Matrix[[6, 6], [4, 4]]
313
+ # y = Matrix[[1, 2], [3, 4]]
314
+ # x.combine(y) {|a, b| a - b} # => Matrix[[5, 4], [1, 0]]
277
315
  def combine(*matrices, &block)
278
316
  Matrix.combine(self, *matrices, &block)
279
317
  end
280
318
 
281
319
  #
282
- # Matrix.new is private; use Matrix.rows, columns, [], etc... to create.
320
+ # Matrix.new is private; use ::rows, ::columns, ::[], etc... to create.
283
321
  #
284
322
  def initialize(rows, column_count = rows[0].size)
285
323
  # No checking is done at this point. rows must be an Array of Arrays.
@@ -341,7 +379,7 @@ class Matrix
341
379
  end
342
380
 
343
381
  private def set_value(row, col, value)
344
- raise ErrDimensionMismatch, "Expected a a value, got a #{value.class}" if value.respond_to?(:to_matrix)
382
+ raise ErrDimensionMismatch, "Expected a value, got a #{value.class}" if value.respond_to?(:to_matrix)
345
383
 
346
384
  @rows[row][col] = value
347
385
  end
@@ -372,12 +410,12 @@ class Matrix
372
410
 
373
411
  private def set_row_range(row_range, col, value)
374
412
  if value.is_a?(Vector)
375
- Matrix.Raise ErrDimensionMismatch unless row_range.size == value.size
413
+ raise ErrDimensionMismatch unless row_range.size == value.size
376
414
  set_column_vector(row_range, col, value)
377
415
  elsif value.is_a?(Matrix)
378
- Matrix.Raise ErrDimensionMismatch unless value.column_count == 1
416
+ raise ErrDimensionMismatch unless value.column_count == 1
379
417
  value = value.column(0)
380
- Matrix.Raise ErrDimensionMismatch unless row_range.size == value.size
418
+ raise ErrDimensionMismatch unless row_range.size == value.size
381
419
  set_column_vector(row_range, col, value)
382
420
  else
383
421
  @rows[row_range].each{|e| e[col] = value }
@@ -395,12 +433,12 @@ class Matrix
395
433
  value = if value.is_a?(Vector)
396
434
  value.to_a
397
435
  elsif value.is_a?(Matrix)
398
- Matrix.Raise ErrDimensionMismatch unless value.row_count == 1
436
+ raise ErrDimensionMismatch unless value.row_count == 1
399
437
  value.row(0).to_a
400
438
  else
401
439
  Array.new(col_range.size, value)
402
440
  end
403
- Matrix.Raise ErrDimensionMismatch unless col_range.size == value.size
441
+ raise ErrDimensionMismatch unless col_range.size == value.size
404
442
  @rows[row][col_range] = value
405
443
  end
406
444
 
@@ -464,8 +502,8 @@ class Matrix
464
502
  # * :strict_upper: yields only elements above the diagonal
465
503
  # * :upper: yields only elements on or above the diagonal
466
504
  # Matrix[ [1,2], [3,4] ].collect { |e| e**2 }
467
- # => 1 4
468
- # 9 16
505
+ # # => 1 4
506
+ # # 9 16
469
507
  #
470
508
  def collect(which = :all, &block) # :yield: e
471
509
  return to_enum(:collect, which) unless block_given?
@@ -494,7 +532,8 @@ class Matrix
494
532
  alias map! collect!
495
533
 
496
534
  def freeze
497
- @rows.freeze
535
+ @rows.each(&:freeze).freeze
536
+
498
537
  super
499
538
  end
500
539
 
@@ -510,16 +549,15 @@ class Matrix
510
549
  # * :strict_upper: yields only elements above the diagonal
511
550
  # * :upper: yields only elements on or above the diagonal
512
551
  #
513
- # Matrix[ [1,2], [3,4] ].each { |e| puts e }
514
- # # => prints the numbers 1 to 4
515
- # Matrix[ [1,2], [3,4] ].each(:strict_lower).to_a # => [3]
552
+ # Matrix[ [1,2], [3,4] ].each { |e| puts e }
553
+ # # => prints the numbers 1 to 4
554
+ # Matrix[ [1,2], [3,4] ].each(:strict_lower).to_a # => [3]
516
555
  #
517
- def each(which = :all) # :yield: e
556
+ def each(which = :all, &block) # :yield: e
518
557
  return to_enum :each, which unless block_given?
519
558
  last = column_count - 1
520
559
  case which
521
560
  when :all
522
- block = Proc.new
523
561
  @rows.each do |row|
524
562
  row.each(&block)
525
563
  end
@@ -662,8 +700,8 @@ class Matrix
662
700
  # * row_range, col_range
663
701
  #
664
702
  # Matrix.diagonal(9, 5, -3).minor(0..1, 0..2)
665
- # => 9 0 0
666
- # 0 5 0
703
+ # # => 9 0 0
704
+ # # 0 5 0
667
705
  #
668
706
  # Like Array#[], negative indices count backward from the end of the
669
707
  # row or column (-1 is the last element). Returns nil if the starting
@@ -706,9 +744,9 @@ class Matrix
706
744
  # Returns the submatrix obtained by deleting the specified row and column.
707
745
  #
708
746
  # Matrix.diagonal(9, 5, -3, 4).first_minor(1, 2)
709
- # => 9 0 0
710
- # 0 0 0
711
- # 0 0 4
747
+ # # => 9 0 0
748
+ # # 0 0 0
749
+ # # 0 0 4
712
750
  #
713
751
  def first_minor(row, column)
714
752
  raise RuntimeError, "first_minor of empty matrix is not defined" if empty?
@@ -735,11 +773,11 @@ class Matrix
735
773
  # the first minor by (-1)**(row + column).
736
774
  #
737
775
  # Matrix.diagonal(9, 5, -3, 4).cofactor(1, 1)
738
- # => -108
776
+ # # => -108
739
777
  #
740
778
  def cofactor(row, column)
741
779
  raise RuntimeError, "cofactor of empty matrix is not defined" if empty?
742
- Matrix.Raise ErrDimensionMismatch unless square?
780
+ raise ErrDimensionMismatch unless square?
743
781
 
744
782
  det_of_minor = first_minor(row, column).determinant
745
783
  det_of_minor * (-1) ** (row + column)
@@ -749,11 +787,11 @@ class Matrix
749
787
  # Returns the adjugate of the matrix.
750
788
  #
751
789
  # Matrix[ [7,6],[3,9] ].adjugate
752
- # => 9 -6
753
- # -3 7
790
+ # # => 9 -6
791
+ # # -3 7
754
792
  #
755
793
  def adjugate
756
- Matrix.Raise ErrDimensionMismatch unless square?
794
+ raise ErrDimensionMismatch unless square?
757
795
  Matrix.build(row_count, column_count) do |row, column|
758
796
  cofactor(column, row)
759
797
  end
@@ -763,10 +801,10 @@ class Matrix
763
801
  # Returns the Laplace expansion along given row or column.
764
802
  #
765
803
  # Matrix[[7,6], [3,9]].laplace_expansion(column: 1)
766
- # => 45
804
+ # # => 45
767
805
  #
768
806
  # Matrix[[Vector[1, 0], Vector[0, 1]], [2, 3]].laplace_expansion(row: 0)
769
- # => Vector[3, -2]
807
+ # # => Vector[3, -2]
770
808
  #
771
809
  #
772
810
  def laplace_expansion(row: nil, column: nil)
@@ -776,7 +814,7 @@ class Matrix
776
814
  raise ArgumentError, "exactly one the row or column arguments must be specified"
777
815
  end
778
816
 
779
- Matrix.Raise ErrDimensionMismatch unless square?
817
+ raise ErrDimensionMismatch unless square?
780
818
  raise RuntimeError, "laplace_expansion of empty matrix is not defined" if empty?
781
819
 
782
820
  unless 0 <= num && num < row_count
@@ -799,7 +837,7 @@ class Matrix
799
837
  # Raises an error if matrix is not square.
800
838
  #
801
839
  def diagonal?
802
- Matrix.Raise ErrDimensionMismatch unless square?
840
+ raise ErrDimensionMismatch unless square?
803
841
  each(:off_diagonal).all?(&:zero?)
804
842
  end
805
843
 
@@ -816,7 +854,7 @@ class Matrix
816
854
  # Raises an error if matrix is not square.
817
855
  #
818
856
  def hermitian?
819
- Matrix.Raise ErrDimensionMismatch unless square?
857
+ raise ErrDimensionMismatch unless square?
820
858
  each_with_index(:upper).all? do |e, row, col|
821
859
  e == rows[col][row].conj
822
860
  end
@@ -834,7 +872,7 @@ class Matrix
834
872
  # Raises an error if matrix is not square.
835
873
  #
836
874
  def normal?
837
- Matrix.Raise ErrDimensionMismatch unless square?
875
+ raise ErrDimensionMismatch unless square?
838
876
  rows.each_with_index do |row_i, i|
839
877
  rows.each_with_index do |row_j, j|
840
878
  s = 0
@@ -852,12 +890,13 @@ class Matrix
852
890
  # Raises an error if matrix is not square.
853
891
  #
854
892
  def orthogonal?
855
- Matrix.Raise ErrDimensionMismatch unless square?
856
- rows.each_with_index do |row, i|
857
- column_count.times do |j|
893
+ raise ErrDimensionMismatch unless square?
894
+
895
+ rows.each_with_index do |row_i, i|
896
+ rows.each_with_index do |row_j, j|
858
897
  s = 0
859
898
  row_count.times do |k|
860
- s += row[k] * rows[k][j]
899
+ s += row_i[k] * row_j[k]
861
900
  end
862
901
  return false unless s == (i == j ? 1 : 0)
863
902
  end
@@ -870,7 +909,7 @@ class Matrix
870
909
  # Raises an error if matrix is not square.
871
910
  #
872
911
  def permutation?
873
- Matrix.Raise ErrDimensionMismatch unless square?
912
+ raise ErrDimensionMismatch unless square?
874
913
  cols = Array.new(column_count)
875
914
  rows.each_with_index do |row, i|
876
915
  found = false
@@ -920,7 +959,7 @@ class Matrix
920
959
  # Raises an error if matrix is not square.
921
960
  #
922
961
  def symmetric?
923
- Matrix.Raise ErrDimensionMismatch unless square?
962
+ raise ErrDimensionMismatch unless square?
924
963
  each_with_index(:strict_upper) do |e, row, col|
925
964
  return false if e != rows[col][row]
926
965
  end
@@ -932,7 +971,7 @@ class Matrix
932
971
  # Raises an error if matrix is not square.
933
972
  #
934
973
  def antisymmetric?
935
- Matrix.Raise ErrDimensionMismatch unless square?
974
+ raise ErrDimensionMismatch unless square?
936
975
  each_with_index(:upper) do |e, row, col|
937
976
  return false unless e == -rows[col][row]
938
977
  end
@@ -945,12 +984,12 @@ class Matrix
945
984
  # Raises an error if matrix is not square.
946
985
  #
947
986
  def unitary?
948
- Matrix.Raise ErrDimensionMismatch unless square?
949
- rows.each_with_index do |row, i|
950
- column_count.times do |j|
987
+ raise ErrDimensionMismatch unless square?
988
+ rows.each_with_index do |row_i, i|
989
+ rows.each_with_index do |row_j, j|
951
990
  s = 0
952
991
  row_count.times do |k|
953
- s += row[k].conj * rows[k][j]
992
+ s += row_i[k].conj * row_j[k]
954
993
  end
955
994
  return false unless s == (i == j ? 1 : 0)
956
995
  end
@@ -977,7 +1016,7 @@ class Matrix
977
1016
  #++
978
1017
 
979
1018
  #
980
- # Returns +true+ if and only if the two matrices contain equal elements.
1019
+ # Returns whether the two matrices contain equal elements.
981
1020
  #
982
1021
  def ==(other)
983
1022
  return false unless Matrix === other &&
@@ -1013,31 +1052,33 @@ class Matrix
1013
1052
  #
1014
1053
  # Matrix multiplication.
1015
1054
  # Matrix[[2,4], [6,8]] * Matrix.identity(2)
1016
- # => 2 4
1017
- # 6 8
1055
+ # # => 2 4
1056
+ # # 6 8
1018
1057
  #
1019
1058
  def *(m) # m is matrix or vector or number
1020
1059
  case(m)
1021
1060
  when Numeric
1022
- rows = @rows.collect {|row|
1061
+ new_rows = @rows.collect {|row|
1023
1062
  row.collect {|e| e * m }
1024
1063
  }
1025
- return new_matrix rows, column_count
1064
+ return new_matrix new_rows, column_count
1026
1065
  when Vector
1027
1066
  m = self.class.column_vector(m)
1028
1067
  r = self * m
1029
1068
  return r.column(0)
1030
1069
  when Matrix
1031
- Matrix.Raise ErrDimensionMismatch if column_count != m.row_count
1032
-
1033
- rows = Array.new(row_count) {|i|
1034
- Array.new(m.column_count) {|j|
1035
- (0 ... column_count).inject(0) do |vij, k|
1036
- vij + self[i, k] * m[k, j]
1070
+ raise ErrDimensionMismatch if column_count != m.row_count
1071
+ m_rows = m.rows
1072
+ new_rows = rows.map do |row_i|
1073
+ Array.new(m.column_count) do |j|
1074
+ vij = 0
1075
+ column_count.times do |k|
1076
+ vij += row_i[k] * m_rows[k][j]
1037
1077
  end
1038
- }
1039
- }
1040
- return new_matrix rows, m.column_count
1078
+ vij
1079
+ end
1080
+ end
1081
+ return new_matrix new_rows, m.column_count
1041
1082
  else
1042
1083
  return apply_through_coercion(m, __method__)
1043
1084
  end
@@ -1046,13 +1087,13 @@ class Matrix
1046
1087
  #
1047
1088
  # Matrix addition.
1048
1089
  # Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]]
1049
- # => 6 0
1050
- # -4 12
1090
+ # # => 6 0
1091
+ # # -4 12
1051
1092
  #
1052
1093
  def +(m)
1053
1094
  case m
1054
1095
  when Numeric
1055
- Matrix.Raise ErrOperationNotDefined, "+", self.class, m.class
1096
+ raise ErrOperationNotDefined, ["+", self.class, m.class]
1056
1097
  when Vector
1057
1098
  m = self.class.column_vector(m)
1058
1099
  when Matrix
@@ -1060,7 +1101,7 @@ class Matrix
1060
1101
  return apply_through_coercion(m, __method__)
1061
1102
  end
1062
1103
 
1063
- Matrix.Raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count
1104
+ raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count
1064
1105
 
1065
1106
  rows = Array.new(row_count) {|i|
1066
1107
  Array.new(column_count) {|j|
@@ -1073,13 +1114,13 @@ class Matrix
1073
1114
  #
1074
1115
  # Matrix subtraction.
1075
1116
  # Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]]
1076
- # => -8 2
1077
- # 8 1
1117
+ # # => -8 2
1118
+ # # 8 1
1078
1119
  #
1079
1120
  def -(m)
1080
1121
  case m
1081
1122
  when Numeric
1082
- Matrix.Raise ErrOperationNotDefined, "-", self.class, m.class
1123
+ raise ErrOperationNotDefined, ["-", self.class, m.class]
1083
1124
  when Vector
1084
1125
  m = self.class.column_vector(m)
1085
1126
  when Matrix
@@ -1087,7 +1128,7 @@ class Matrix
1087
1128
  return apply_through_coercion(m, __method__)
1088
1129
  end
1089
1130
 
1090
- Matrix.Raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count
1131
+ raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count
1091
1132
 
1092
1133
  rows = Array.new(row_count) {|i|
1093
1134
  Array.new(column_count) {|j|
@@ -1100,8 +1141,8 @@ class Matrix
1100
1141
  #
1101
1142
  # Matrix division (multiplication by the inverse).
1102
1143
  # Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]]
1103
- # => -7 1
1104
- # -3 -6
1144
+ # # => -7 1
1145
+ # # -3 -6
1105
1146
  #
1106
1147
  def /(other)
1107
1148
  case other
@@ -1120,8 +1161,8 @@ class Matrix
1120
1161
  #
1121
1162
  # Hadamard product
1122
1163
  # Matrix[[1,2], [3,4]].hadamard_product(Matrix[[1,2], [3,2]])
1123
- # => 1 4
1124
- # 9 8
1164
+ # # => 1 4
1165
+ # # 9 8
1125
1166
  #
1126
1167
  def hadamard_product(m)
1127
1168
  combine(m){|a, b| a * b}
@@ -1131,11 +1172,11 @@ class Matrix
1131
1172
  #
1132
1173
  # Returns the inverse of the matrix.
1133
1174
  # Matrix[[-1, -1], [0, -1]].inverse
1134
- # => -1 1
1135
- # 0 -1
1175
+ # # => -1 1
1176
+ # # 0 -1
1136
1177
  #
1137
1178
  def inverse
1138
- Matrix.Raise ErrDimensionMismatch unless square?
1179
+ raise ErrDimensionMismatch unless square?
1139
1180
  self.class.I(row_count).send(:inverse_from, self)
1140
1181
  end
1141
1182
  alias_method :inv, :inverse
@@ -1154,7 +1195,7 @@ class Matrix
1154
1195
  akk = v
1155
1196
  end
1156
1197
  end
1157
- Matrix.Raise ErrNotRegular if akk == 0
1198
+ raise ErrNotRegular if akk == 0
1158
1199
  if i != k
1159
1200
  a[i], a[k] = a[k], a[i]
1160
1201
  @rows[i], @rows[k] = @rows[k], @rows[i]
@@ -1187,32 +1228,56 @@ class Matrix
1187
1228
  #
1188
1229
  # Matrix exponentiation.
1189
1230
  # Equivalent to multiplying the matrix by itself N times.
1190
- # Non integer exponents will be handled by diagonalizing the matrix.
1231
+ # Non-integer exponents will be handled by diagonalizing the matrix;
1232
+ # this is not supported for Complex matrices.
1191
1233
  #
1192
1234
  # Matrix[[7,6], [3,9]] ** 2
1193
- # => 67 96
1194
- # 48 99
1235
+ # # => 67 96
1236
+ # # 48 99
1195
1237
  #
1196
- def **(other)
1197
- case other
1238
+ def **(exp)
1239
+ case exp
1198
1240
  when Integer
1199
- x = self
1200
- if other <= 0
1201
- x = self.inverse
1202
- return self.class.identity(self.column_count) if other == 0
1203
- other = -other
1204
- end
1205
- z = nil
1206
- loop do
1207
- z = z ? z * x : x if other[0] == 1
1208
- return z if (other >>= 1).zero?
1209
- x *= x
1241
+ case
1242
+ when exp == 0
1243
+ raise ErrDimensionMismatch unless square?
1244
+ self.class.identity(column_count)
1245
+ when exp < 0
1246
+ inverse.power_int(-exp)
1247
+ else
1248
+ power_int(exp)
1210
1249
  end
1211
1250
  when Numeric
1212
1251
  v, d, v_inv = eigensystem
1213
- v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** other}) * v_inv
1252
+ v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** exp}) * v_inv
1253
+ else
1254
+ raise ErrOperationNotDefined, ["**", self.class, exp.class]
1255
+ end
1256
+ end
1257
+
1258
+ protected def power_int(exp)
1259
+ # assumes `exp` is an Integer > 0
1260
+ #
1261
+ # Previous algorithm:
1262
+ # build M**2, M**4 = (M**2)**2, M**8, ... and multiplying those you need
1263
+ # e.g. M**0b1011 = M**11 = M * M**2 * M**8
1264
+ # ^ ^
1265
+ # (highlighted the 2 out of 5 multiplications involving `M * x`)
1266
+ #
1267
+ # Current algorithm has same number of multiplications but with lower exponents:
1268
+ # M**11 = M * (M * M**4)**2
1269
+ # ^ ^ ^
1270
+ # (highlighted the 3 out of 5 multiplications involving `M * x`)
1271
+ #
1272
+ # This should be faster for all (non nil-potent) matrices.
1273
+ case
1274
+ when exp == 1
1275
+ self
1276
+ when exp.odd?
1277
+ self * power_int(exp - 1)
1214
1278
  else
1215
- Matrix.Raise ErrOperationNotDefined, "**", self.class, other.class
1279
+ sqrt = power_int(exp / 2)
1280
+ sqrt * sqrt
1216
1281
  end
1217
1282
  end
1218
1283
 
@@ -1220,10 +1285,22 @@ class Matrix
1220
1285
  self
1221
1286
  end
1222
1287
 
1288
+ # Unary matrix negation.
1289
+ #
1290
+ # -Matrix[[1,5], [4,2]]
1291
+ # # => -1 -5
1292
+ # # -4 -2
1223
1293
  def -@
1224
1294
  collect {|e| -e }
1225
1295
  end
1226
1296
 
1297
+ #
1298
+ # Returns the absolute value elementwise
1299
+ #
1300
+ def abs
1301
+ collect(&:abs)
1302
+ end
1303
+
1227
1304
  #--
1228
1305
  # MATRIX FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
1229
1306
  #++
@@ -1236,10 +1313,10 @@ class Matrix
1236
1313
  # Consider using exact types like Rational or BigDecimal instead.
1237
1314
  #
1238
1315
  # Matrix[[7,6], [3,9]].determinant
1239
- # => 45
1316
+ # # => 45
1240
1317
  #
1241
1318
  def determinant
1242
- Matrix.Raise ErrDimensionMismatch unless square?
1319
+ raise ErrDimensionMismatch unless square?
1243
1320
  m = @rows
1244
1321
  case row_count
1245
1322
  # Up to 4x4, give result using Laplacian expansion by minors.
@@ -1344,7 +1421,7 @@ class Matrix
1344
1421
  # Consider using exact types like Rational or BigDecimal instead.
1345
1422
  #
1346
1423
  # Matrix[[7,6], [3,9]].rank
1347
- # => 2
1424
+ # # => 2
1348
1425
  #
1349
1426
  def rank
1350
1427
  # We currently use Bareiss' multistep integer-preserving gaussian elimination
@@ -1382,6 +1459,35 @@ class Matrix
1382
1459
  rank
1383
1460
  end
1384
1461
 
1462
+ #
1463
+ # Returns a new matrix with rotated elements.
1464
+ # The argument specifies the rotation (defaults to `:clockwise`):
1465
+ # * :clockwise, 1, -3, etc.: "turn right" - first row becomes last column
1466
+ # * :half_turn, 2, -2, etc.: first row becomes last row, elements in reverse order
1467
+ # * :counter_clockwise, -1, 3: "turn left" - first row becomes first column
1468
+ # (but with elements in reverse order)
1469
+ #
1470
+ # m = Matrix[ [1, 2], [3, 4] ]
1471
+ # r = m.rotate_entries(:clockwise)
1472
+ # # => Matrix[[3, 1], [4, 2]]
1473
+ #
1474
+ def rotate_entries(rotation = :clockwise)
1475
+ rotation %= 4 if rotation.respond_to? :to_int
1476
+
1477
+ case rotation
1478
+ when 0
1479
+ dup
1480
+ when 1, :clockwise
1481
+ new_matrix @rows.transpose.each(&:reverse!), row_count
1482
+ when 2, :half_turn
1483
+ new_matrix @rows.map(&:reverse).reverse!, column_count
1484
+ when 3, :counter_clockwise
1485
+ new_matrix @rows.transpose.reverse!, row_count
1486
+ else
1487
+ raise ArgumentError, "expected #{rotation.inspect} to be one of :clockwise, :counter_clockwise, :half_turn or an integer"
1488
+ end
1489
+ end
1490
+
1385
1491
  # Returns a matrix with entries rounded to the given precision
1386
1492
  # (see Float#round)
1387
1493
  #
@@ -1392,10 +1498,10 @@ class Matrix
1392
1498
  #
1393
1499
  # Returns the trace (sum of diagonal elements) of the matrix.
1394
1500
  # Matrix[[7,6], [3,9]].trace
1395
- # => 16
1501
+ # # => 16
1396
1502
  #
1397
1503
  def trace
1398
- Matrix.Raise ErrDimensionMismatch unless square?
1504
+ raise ErrDimensionMismatch unless square?
1399
1505
  (0...column_count).inject(0) do |tr, i|
1400
1506
  tr + @rows[i][i]
1401
1507
  end
@@ -1405,12 +1511,12 @@ class Matrix
1405
1511
  #
1406
1512
  # Returns the transpose of the matrix.
1407
1513
  # Matrix[[1,2], [3,4], [5,6]]
1408
- # => 1 2
1409
- # 3 4
1410
- # 5 6
1514
+ # # => 1 2
1515
+ # # 3 4
1516
+ # # 5 6
1411
1517
  # Matrix[[1,2], [3,4], [5,6]].transpose
1412
- # => 1 3 5
1413
- # 2 4 6
1518
+ # # => 1 3 5
1519
+ # # 2 4 6
1414
1520
  #
1415
1521
  def transpose
1416
1522
  return self.class.empty(column_count, 0) if row_count.zero?
@@ -1442,6 +1548,7 @@ class Matrix
1442
1548
  # v.inv == v_inv # => true
1443
1549
  # (v * d * v_inv).round(5) == m # => true
1444
1550
  #
1551
+ # This is not supported for Complex matrices
1445
1552
  def eigensystem
1446
1553
  EigenvalueDecomposition.new(self)
1447
1554
  end
@@ -1469,25 +1576,36 @@ class Matrix
1469
1576
  #
1470
1577
  # Returns the conjugate of the matrix.
1471
1578
  # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
1472
- # => 1+2i i 0
1473
- # 1 2 3
1579
+ # # => 1+2i i 0
1580
+ # # 1 2 3
1474
1581
  # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].conjugate
1475
- # => 1-2i -i 0
1476
- # 1 2 3
1582
+ # # => 1-2i -i 0
1583
+ # # 1 2 3
1477
1584
  #
1478
1585
  def conjugate
1479
1586
  collect(&:conjugate)
1480
1587
  end
1481
1588
  alias_method :conj, :conjugate
1482
1589
 
1590
+ #
1591
+ # Returns the adjoint of the matrix.
1592
+ #
1593
+ # Matrix[ [i,1],[2,-i] ].adjoint
1594
+ # # => -i 2
1595
+ # # 1 i
1596
+ #
1597
+ def adjoint
1598
+ conjugate.transpose
1599
+ end
1600
+
1483
1601
  #
1484
1602
  # Returns the imaginary part of the matrix.
1485
1603
  # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
1486
- # => 1+2i i 0
1487
- # 1 2 3
1604
+ # # => 1+2i i 0
1605
+ # # 1 2 3
1488
1606
  # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].imaginary
1489
- # => 2i i 0
1490
- # 0 0 0
1607
+ # # => 2i i 0
1608
+ # # 0 0 0
1491
1609
  #
1492
1610
  def imaginary
1493
1611
  collect(&:imaginary)
@@ -1497,11 +1615,11 @@ class Matrix
1497
1615
  #
1498
1616
  # Returns the real part of the matrix.
1499
1617
  # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
1500
- # => 1+2i i 0
1501
- # 1 2 3
1618
+ # # => 1+2i i 0
1619
+ # # 1 2 3
1502
1620
  # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].real
1503
- # => 1 0 0
1504
- # 1 2 3
1621
+ # # => 1 0 0
1622
+ # # 1 2 3
1505
1623
  #
1506
1624
  def real
1507
1625
  collect(&:real)
@@ -1511,7 +1629,7 @@ class Matrix
1511
1629
  # Returns an array containing matrices corresponding to the real and imaginary
1512
1630
  # parts of the matrix
1513
1631
  #
1514
- # m.rect == [m.real, m.imag] # ==> true for all matrices m
1632
+ # m.rect == [m.real, m.imag] # ==> true for all matrices m
1515
1633
  #
1516
1634
  def rect
1517
1635
  [real, imag]
@@ -1572,7 +1690,7 @@ class Matrix
1572
1690
 
1573
1691
  # Deprecated.
1574
1692
  #
1575
- # Use map(&:to_f)
1693
+ # Use <code>map(&:to_f)</code>
1576
1694
  def elements_to_f
1577
1695
  warn "Matrix#elements_to_f is deprecated, use map(&:to_f)", uplevel: 1
1578
1696
  map(&:to_f)
@@ -1580,7 +1698,7 @@ class Matrix
1580
1698
 
1581
1699
  # Deprecated.
1582
1700
  #
1583
- # Use map(&:to_i)
1701
+ # Use <code>map(&:to_i)</code>
1584
1702
  def elements_to_i
1585
1703
  warn "Matrix#elements_to_i is deprecated, use map(&:to_i)", uplevel: 1
1586
1704
  map(&:to_i)
@@ -1588,7 +1706,7 @@ class Matrix
1588
1706
 
1589
1707
  # Deprecated.
1590
1708
  #
1591
- # Use map(&:to_r)
1709
+ # Use <code>map(&:to_r)</code>
1592
1710
  def elements_to_r
1593
1711
  warn "Matrix#elements_to_r is deprecated, use map(&:to_r)", uplevel: 1
1594
1712
  map(&:to_r)
@@ -1728,7 +1846,7 @@ class Matrix
1728
1846
  when Numeric
1729
1847
  Scalar.new(@value + other)
1730
1848
  when Vector, Matrix
1731
- Scalar.Raise ErrOperationNotDefined, "+", @value.class, other.class
1849
+ raise ErrOperationNotDefined, ["+", @value.class, other.class]
1732
1850
  else
1733
1851
  apply_through_coercion(other, __method__)
1734
1852
  end
@@ -1739,7 +1857,7 @@ class Matrix
1739
1857
  when Numeric
1740
1858
  Scalar.new(@value - other)
1741
1859
  when Vector, Matrix
1742
- Scalar.Raise ErrOperationNotDefined, "-", @value.class, other.class
1860
+ raise ErrOperationNotDefined, ["-", @value.class, other.class]
1743
1861
  else
1744
1862
  apply_through_coercion(other, __method__)
1745
1863
  end
@@ -1761,7 +1879,7 @@ class Matrix
1761
1879
  when Numeric
1762
1880
  Scalar.new(@value / other)
1763
1881
  when Vector
1764
- Scalar.Raise ErrOperationNotDefined, "/", @value.class, other.class
1882
+ raise ErrOperationNotDefined, ["/", @value.class, other.class]
1765
1883
  when Matrix
1766
1884
  self * other.inverse
1767
1885
  else
@@ -1774,10 +1892,10 @@ class Matrix
1774
1892
  when Numeric
1775
1893
  Scalar.new(@value ** other)
1776
1894
  when Vector
1777
- Scalar.Raise ErrOperationNotDefined, "**", @value.class, other.class
1895
+ raise ErrOperationNotDefined, ["**", @value.class, other.class]
1778
1896
  when Matrix
1779
1897
  #other.powered_by(self)
1780
- Scalar.Raise ErrOperationNotImplemented, "**", @value.class, other.class
1898
+ raise ErrOperationNotImplemented, ["**", @value.class, other.class]
1781
1899
  else
1782
1900
  apply_through_coercion(other, __method__)
1783
1901
  end
@@ -1824,8 +1942,8 @@ end
1824
1942
  # * #-@
1825
1943
  #
1826
1944
  # Vector functions:
1827
- # * #inner_product(v), dot(v)
1828
- # * #cross_product(v), cross(v)
1945
+ # * #inner_product(v), #dot(v)
1946
+ # * #cross_product(v), #cross(v)
1829
1947
  # * #collect
1830
1948
  # * #collect!
1831
1949
  # * #magnitude
@@ -1890,7 +2008,7 @@ class Vector
1890
2008
  #
1891
2009
  # Return a zero vector.
1892
2010
  #
1893
- # Vector.zero(3) => Vector[0, 0, 0]
2011
+ # Vector.zero(3) # => Vector[0, 0, 0]
1894
2012
  #
1895
2013
  def Vector.zero(size)
1896
2014
  raise ArgumentError, "invalid size (#{size} for 0..)" if size < 0
@@ -1953,7 +2071,7 @@ class Vector
1953
2071
  raise ArgumentError, "vector to be set has wrong size" unless range.size == value.size
1954
2072
  @elements[range] = value.elements
1955
2073
  elsif value.is_a?(Matrix)
1956
- Matrix.Raise ErrDimensionMismatch unless value.row_count == 1
2074
+ raise ErrDimensionMismatch unless value.row_count == 1
1957
2075
  @elements[range] = value.row(0).elements
1958
2076
  else
1959
2077
  @elements[range] = Array.new(range.size, value)
@@ -1992,7 +2110,7 @@ class Vector
1992
2110
  #
1993
2111
  def each2(v) # :yield: e1, e2
1994
2112
  raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer)
1995
- Vector.Raise ErrDimensionMismatch if size != v.size
2113
+ raise ErrDimensionMismatch if size != v.size
1996
2114
  return to_enum(:each2, v) unless block_given?
1997
2115
  size.times do |i|
1998
2116
  yield @elements[i], v[i]
@@ -2006,7 +2124,7 @@ class Vector
2006
2124
  #
2007
2125
  def collect2(v) # :yield: e1, e2
2008
2126
  raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer)
2009
- Vector.Raise ErrDimensionMismatch if size != v.size
2127
+ raise ErrDimensionMismatch if size != v.size
2010
2128
  return to_enum(:collect2, v) unless block_given?
2011
2129
  Array.new(size) do |i|
2012
2130
  yield @elements[i], v[i]
@@ -2018,43 +2136,46 @@ class Vector
2018
2136
  #++
2019
2137
 
2020
2138
  #
2021
- # Returns +true+ iff all of vectors are linearly independent.
2139
+ # Returns whether all of vectors are linearly independent.
2022
2140
  #
2023
2141
  # Vector.independent?(Vector[1,0], Vector[0,1])
2024
- # => true
2142
+ # # => true
2025
2143
  #
2026
2144
  # Vector.independent?(Vector[1,2], Vector[2,4])
2027
- # => false
2145
+ # # => false
2028
2146
  #
2029
2147
  def Vector.independent?(*vs)
2030
2148
  vs.each do |v|
2031
2149
  raise TypeError, "expected Vector, got #{v.class}" unless v.is_a?(Vector)
2032
- Vector.Raise ErrDimensionMismatch unless v.size == vs.first.size
2150
+ raise ErrDimensionMismatch unless v.size == vs.first.size
2033
2151
  end
2034
2152
  return false if vs.count > vs.first.size
2035
2153
  Matrix[*vs].rank.eql?(vs.count)
2036
2154
  end
2037
2155
 
2038
2156
  #
2039
- # Returns +true+ iff all of vectors are linearly independent.
2157
+ # Returns whether all of vectors are linearly independent.
2040
2158
  #
2041
2159
  # Vector[1,0].independent?(Vector[0,1])
2042
- # => true
2160
+ # # => true
2043
2161
  #
2044
2162
  # Vector[1,2].independent?(Vector[2,4])
2045
- # => false
2163
+ # # => false
2046
2164
  #
2047
2165
  def independent?(*vs)
2048
2166
  self.class.independent?(self, *vs)
2049
2167
  end
2050
2168
 
2051
2169
  #
2052
- # Returns +true+ iff all elements are zero.
2170
+ # Returns whether all elements are zero.
2053
2171
  #
2054
2172
  def zero?
2055
2173
  all?(&:zero?)
2056
2174
  end
2057
2175
 
2176
+ #
2177
+ # Makes the matrix frozen and Ractor-shareable
2178
+ #
2058
2179
  def freeze
2059
2180
  @elements.freeze
2060
2181
  super
@@ -2074,7 +2195,7 @@ class Vector
2074
2195
  #++
2075
2196
 
2076
2197
  #
2077
- # Returns +true+ iff the two vectors have the same elements in the same order.
2198
+ # Returns whether the two vectors have the same elements in the same order.
2078
2199
  #
2079
2200
  def ==(other)
2080
2201
  return false unless Vector === other
@@ -2108,7 +2229,7 @@ class Vector
2108
2229
  when Matrix
2109
2230
  Matrix.column_vector(self) * x
2110
2231
  when Vector
2111
- Vector.Raise ErrOperationNotDefined, "*", self.class, x.class
2232
+ raise ErrOperationNotDefined, ["*", self.class, x.class]
2112
2233
  else
2113
2234
  apply_through_coercion(x, __method__)
2114
2235
  end
@@ -2120,7 +2241,7 @@ class Vector
2120
2241
  def +(v)
2121
2242
  case v
2122
2243
  when Vector
2123
- Vector.Raise ErrDimensionMismatch if size != v.size
2244
+ raise ErrDimensionMismatch if size != v.size
2124
2245
  els = collect2(v) {|v1, v2|
2125
2246
  v1 + v2
2126
2247
  }
@@ -2138,7 +2259,7 @@ class Vector
2138
2259
  def -(v)
2139
2260
  case v
2140
2261
  when Vector
2141
- Vector.Raise ErrDimensionMismatch if size != v.size
2262
+ raise ErrDimensionMismatch if size != v.size
2142
2263
  els = collect2(v) {|v1, v2|
2143
2264
  v1 - v2
2144
2265
  }
@@ -2159,7 +2280,7 @@ class Vector
2159
2280
  els = @elements.collect{|e| e / x}
2160
2281
  self.class.elements(els, false)
2161
2282
  when Matrix, Vector
2162
- Vector.Raise ErrOperationNotDefined, "/", self.class, x.class
2283
+ raise ErrOperationNotDefined, ["/", self.class, x.class]
2163
2284
  else
2164
2285
  apply_through_coercion(x, __method__)
2165
2286
  end
@@ -2179,10 +2300,10 @@ class Vector
2179
2300
 
2180
2301
  #
2181
2302
  # Returns the inner product of this vector with the other.
2182
- # Vector[4,7].inner_product Vector[10,1] => 47
2303
+ # Vector[4,7].inner_product Vector[10,1] # => 47
2183
2304
  #
2184
2305
  def inner_product(v)
2185
- Vector.Raise ErrDimensionMismatch if size != v.size
2306
+ raise ErrDimensionMismatch if size != v.size
2186
2307
 
2187
2308
  p = 0
2188
2309
  each2(v) {|v1, v2|
@@ -2194,7 +2315,7 @@ class Vector
2194
2315
 
2195
2316
  #
2196
2317
  # Returns the cross product of this vector with the others.
2197
- # Vector[1, 0, 0].cross_product Vector[0, 1, 0] => Vector[0, 0, 1]
2318
+ # Vector[1, 0, 0].cross_product Vector[0, 1, 0] # => Vector[0, 0, 1]
2198
2319
  #
2199
2320
  # It is generalized to other dimensions to return a vector perpendicular
2200
2321
  # to the arguments.
@@ -2209,7 +2330,7 @@ class Vector
2209
2330
  raise ArgumentError, "wrong number of arguments (#{vs.size} for #{size - 2})" unless vs.size == size - 2
2210
2331
  vs.each do |v|
2211
2332
  raise TypeError, "expected Vector, got #{v.class}" unless v.is_a? Vector
2212
- Vector.Raise ErrDimensionMismatch unless v.size == size
2333
+ raise ErrDimensionMismatch unless v.size == size
2213
2334
  end
2214
2335
  case size
2215
2336
  when 2
@@ -2249,7 +2370,7 @@ class Vector
2249
2370
 
2250
2371
  #
2251
2372
  # Returns the modulus (Pythagorean distance) of the vector.
2252
- # Vector[5,8,2].r => 9.643650761
2373
+ # Vector[5,8,2].r # => 9.643650761
2253
2374
  #
2254
2375
  def magnitude
2255
2376
  Math.sqrt(@elements.inject(0) {|v, e| v + e.abs2})
@@ -2272,7 +2393,7 @@ class Vector
2272
2393
  # Returns a new vector with the same direction but with norm 1.
2273
2394
  # v = Vector[5,8,2].normalize
2274
2395
  # # => Vector[0.5184758473652127, 0.8295613557843402, 0.20739033894608505]
2275
- # v.norm => 1.0
2396
+ # v.norm # => 1.0
2276
2397
  #
2277
2398
  def normalize
2278
2399
  n = magnitude
@@ -2287,7 +2408,7 @@ class Vector
2287
2408
  #
2288
2409
  def angle_with(v)
2289
2410
  raise TypeError, "Expected a Vector, got a #{v.class}" unless v.is_a?(Vector)
2290
- Vector.Raise ErrDimensionMismatch if size != v.size
2411
+ raise ErrDimensionMismatch if size != v.size
2291
2412
  prod = magnitude * v.magnitude
2292
2413
  raise ZeroVectorError, "Can't get angle of zero vector" if prod == 0
2293
2414
  dot = inner_product(v)