PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/test/matrix/test_matrix.rb

http://github.com/ruby/ruby
Ruby | 815 lines | 709 code | 95 blank | 11 comment | 4 complexity | 8f05973b6776153ebbaf2b632d9fa0fc MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: false
  2. require 'test/unit'
  3. require 'matrix'
  4. class SubMatrix < Matrix
  5. end
  6. class TestMatrix < Test::Unit::TestCase
  7. def setup
  8. @m1 = Matrix[[1,2,3], [4,5,6]]
  9. @m2 = Matrix[[1,2,3], [4,5,6]]
  10. @m3 = @m1.clone
  11. @m4 = Matrix[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
  12. @n1 = Matrix[[2,3,4], [5,6,7]]
  13. @c1 = Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
  14. @e1 = Matrix.empty(2,0)
  15. @e2 = Matrix.empty(0,3)
  16. @a3 = Matrix[[4, 1, -3], [0, 3, 7], [11, -4, 2]]
  17. @a5 = Matrix[[2, 0, 9, 3, 9], [8, 7, 0, 1, 9], [7, 5, 6, 6, 5], [0, 7, 8, 3, 0], [7, 8, 2, 3, 1]]
  18. @b3 = Matrix[[-7, 7, -10], [9, -3, -2], [-1, 3, 9]]
  19. @rot = Matrix[[0, -1, 0], [1, 0, 0], [0, 0, -1]]
  20. end
  21. def test_matrix
  22. assert_equal(1, @m1[0, 0])
  23. assert_equal(2, @m1[0, 1])
  24. assert_equal(3, @m1[0, 2])
  25. assert_equal(4, @m1[1, 0])
  26. assert_equal(5, @m1[1, 1])
  27. assert_equal(6, @m1[1, 2])
  28. end
  29. def test_identity
  30. assert_same @m1, @m1
  31. assert_not_same @m1, @m2
  32. assert_not_same @m1, @m3
  33. assert_not_same @m1, @m4
  34. assert_not_same @m1, @n1
  35. end
  36. def test_equality
  37. assert_equal @m1, @m1
  38. assert_equal @m1, @m2
  39. assert_equal @m1, @m3
  40. assert_equal @m1, @m4
  41. assert_not_equal @m1, @n1
  42. end
  43. def test_hash_equality
  44. assert @m1.eql?(@m1)
  45. assert @m1.eql?(@m2)
  46. assert @m1.eql?(@m3)
  47. assert !@m1.eql?(@m4)
  48. assert !@m1.eql?(@n1)
  49. hash = { @m1 => :value }
  50. assert hash.key?(@m1)
  51. assert hash.key?(@m2)
  52. assert hash.key?(@m3)
  53. assert !hash.key?(@m4)
  54. assert !hash.key?(@n1)
  55. end
  56. def test_hash
  57. assert_equal @m1.hash, @m1.hash
  58. assert_equal @m1.hash, @m2.hash
  59. assert_equal @m1.hash, @m3.hash
  60. end
  61. def test_uplus
  62. assert_equal(@m1, +@m1)
  63. end
  64. def test_negate
  65. assert_equal(Matrix[[-1, -2, -3], [-4, -5, -6]], -@m1)
  66. assert_equal(@m1, -(-@m1))
  67. end
  68. def test_rank
  69. [
  70. [[0]],
  71. [[0], [0]],
  72. [[0, 0], [0, 0]],
  73. [[0, 0], [0, 0], [0, 0]],
  74. [[0, 0, 0]],
  75. [[0, 0, 0], [0, 0, 0]],
  76. [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
  77. [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
  78. ].each do |rows|
  79. assert_equal 0, Matrix[*rows].rank
  80. end
  81. [
  82. [[1], [0]],
  83. [[1, 0], [0, 0]],
  84. [[1, 0], [1, 0]],
  85. [[0, 0], [1, 0]],
  86. [[1, 0], [0, 0], [0, 0]],
  87. [[0, 0], [1, 0], [0, 0]],
  88. [[0, 0], [0, 0], [1, 0]],
  89. [[1, 0], [1, 0], [0, 0]],
  90. [[0, 0], [1, 0], [1, 0]],
  91. [[1, 0], [1, 0], [1, 0]],
  92. [[1, 0, 0]],
  93. [[1, 0, 0], [0, 0, 0]],
  94. [[0, 0, 0], [1, 0, 0]],
  95. [[1, 0, 0], [1, 0, 0]],
  96. [[1, 0, 0], [1, 0, 0]],
  97. [[1, 0, 0], [0, 0, 0], [0, 0, 0]],
  98. [[0, 0, 0], [1, 0, 0], [0, 0, 0]],
  99. [[0, 0, 0], [0, 0, 0], [1, 0, 0]],
  100. [[1, 0, 0], [1, 0, 0], [0, 0, 0]],
  101. [[0, 0, 0], [1, 0, 0], [1, 0, 0]],
  102. [[1, 0, 0], [0, 0, 0], [1, 0, 0]],
  103. [[1, 0, 0], [1, 0, 0], [1, 0, 0]],
  104. [[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
  105. [[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
  106. [[1, 0, 0], [1, 0, 0], [0, 0, 0], [0, 0, 0]],
  107. [[1, 0, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0]],
  108. [[1, 0, 0], [0, 0, 0], [0, 0, 0], [1, 0, 0]],
  109. [[1, 0, 0], [1, 0, 0], [1, 0, 0], [0, 0, 0]],
  110. [[1, 0, 0], [0, 0, 0], [1, 0, 0], [1, 0, 0]],
  111. [[1, 0, 0], [1, 0, 0], [0, 0, 0], [1, 0, 0]],
  112. [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]],
  113. [[1]],
  114. [[1], [1]],
  115. [[1, 1]],
  116. [[1, 1], [1, 1]],
  117. [[1, 1], [1, 1], [1, 1]],
  118. [[1, 1, 1]],
  119. [[1, 1, 1], [1, 1, 1]],
  120. [[1, 1, 1], [1, 1, 1], [1, 1, 1]],
  121. [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
  122. ].each do |rows|
  123. matrix = Matrix[*rows]
  124. assert_equal 1, matrix.rank
  125. assert_equal 1, matrix.transpose.rank
  126. end
  127. [
  128. [[1, 0], [0, 1]],
  129. [[1, 0], [0, 1], [0, 0]],
  130. [[1, 0], [0, 1], [0, 1]],
  131. [[1, 0], [0, 1], [1, 1]],
  132. [[1, 0, 0], [0, 1, 0]],
  133. [[1, 0, 0], [0, 0, 1]],
  134. [[1, 0, 0], [0, 1, 0], [0, 0, 0]],
  135. [[1, 0, 0], [0, 0, 1], [0, 0, 0]],
  136. [[1, 0, 0], [0, 0, 0], [0, 1, 0]],
  137. [[1, 0, 0], [0, 0, 0], [0, 0, 1]],
  138. [[1, 0], [1, 1]],
  139. [[1, 2], [1, 1]],
  140. [[1, 2], [0, 1], [1, 1]],
  141. ].each do |rows|
  142. m = Matrix[*rows]
  143. assert_equal 2, m.rank
  144. assert_equal 2, m.transpose.rank
  145. end
  146. [
  147. [[1, 0, 0], [0, 1, 0], [0, 0, 1]],
  148. [[1, 1, 0], [0, 1, 1], [1, 0, 1]],
  149. [[1, 1, 0], [0, 1, 1], [1, 0, 1]],
  150. [[1, 1, 0], [0, 1, 1], [1, 0, 1], [0, 0, 0]],
  151. [[1, 1, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]],
  152. [[1, 1, 1], [1, 1, 2], [1, 3, 1], [4, 1, 1]],
  153. ].each do |rows|
  154. m = Matrix[*rows]
  155. assert_equal 3, m.rank
  156. assert_equal 3, m.transpose.rank
  157. end
  158. end
  159. def test_inverse
  160. assert_equal(Matrix.empty(0, 0), Matrix.empty.inverse)
  161. assert_equal(Matrix[[-1, 1], [0, -1]], Matrix[[-1, -1], [0, -1]].inverse)
  162. assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { @m1.inverse }
  163. end
  164. def test_determinant
  165. assert_equal(0, Matrix[[0,0],[0,0]].determinant)
  166. assert_equal(45, Matrix[[7,6], [3,9]].determinant)
  167. assert_equal(-18, Matrix[[2,0,1],[0,-2,2],[1,2,3]].determinant)
  168. assert_equal(-7, Matrix[[0,0,1],[0,7,6],[1,3,9]].determinant)
  169. assert_equal(42, Matrix[[7,0,1,0,12],[8,1,1,9,1],[4,0,0,-7,17],[-1,0,0,-4,8],[10,1,1,8,6]].determinant)
  170. end
  171. def test_new_matrix
  172. assert_raise(TypeError) { Matrix[Object.new] }
  173. o = Object.new
  174. def o.to_ary; [1,2,3]; end
  175. assert_equal(@m1, Matrix[o, [4,5,6]])
  176. end
  177. def test_round
  178. a = Matrix[[1.0111, 2.32320, 3.04343], [4.81, 5.0, 6.997]]
  179. b = Matrix[[1.01, 2.32, 3.04], [4.81, 5.0, 7.0]]
  180. assert_equal(a.round(2), b)
  181. end
  182. def test_rows
  183. assert_equal(@m1, Matrix.rows([[1, 2, 3], [4, 5, 6]]))
  184. end
  185. def test_rows_copy
  186. rows1 = [[1], [1]]
  187. rows2 = [[1], [1]]
  188. m1 = Matrix.rows(rows1, copy = false)
  189. m2 = Matrix.rows(rows2, copy = true)
  190. rows1.uniq!
  191. rows2.uniq!
  192. assert_equal([[1]], m1.to_a)
  193. assert_equal([[1], [1]], m2.to_a)
  194. end
  195. def test_to_matrix
  196. assert @m1.equal? @m1.to_matrix
  197. end
  198. def test_columns
  199. assert_equal(@m1, Matrix.columns([[1, 4], [2, 5], [3, 6]]))
  200. end
  201. def test_diagonal
  202. assert_equal(Matrix.empty(0, 0), Matrix.diagonal( ))
  203. assert_equal(Matrix[[3,0,0],[0,2,0],[0,0,1]], Matrix.diagonal(3, 2, 1))
  204. assert_equal(Matrix[[4,0,0,0],[0,3,0,0],[0,0,2,0],[0,0,0,1]], Matrix.diagonal(4, 3, 2, 1))
  205. end
  206. def test_scalar
  207. assert_equal(Matrix.empty(0, 0), Matrix.scalar(0, 1))
  208. assert_equal(Matrix[[2,0,0],[0,2,0],[0,0,2]], Matrix.scalar(3, 2))
  209. assert_equal(Matrix[[2,0,0,0],[0,2,0,0],[0,0,2,0],[0,0,0,2]], Matrix.scalar(4, 2))
  210. end
  211. def test_identity2
  212. assert_equal(Matrix[[1,0,0],[0,1,0],[0,0,1]], Matrix.identity(3))
  213. assert_equal(Matrix[[1,0,0],[0,1,0],[0,0,1]], Matrix.unit(3))
  214. assert_equal(Matrix[[1,0,0],[0,1,0],[0,0,1]], Matrix.I(3))
  215. assert_equal(Matrix[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]], Matrix.identity(4))
  216. end
  217. def test_zero
  218. assert_equal(Matrix[[0,0,0],[0,0,0],[0,0,0]], Matrix.zero(3))
  219. assert_equal(Matrix[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]], Matrix.zero(4))
  220. assert_equal(Matrix[[0]], Matrix.zero(1))
  221. end
  222. def test_row_vector
  223. assert_equal(Matrix[[1,2,3,4]], Matrix.row_vector([1,2,3,4]))
  224. end
  225. def test_column_vector
  226. assert_equal(Matrix[[1],[2],[3],[4]], Matrix.column_vector([1,2,3,4]))
  227. end
  228. def test_empty
  229. m = Matrix.empty(2, 0)
  230. assert_equal(Matrix[ [], [] ], m)
  231. n = Matrix.empty(0, 3)
  232. assert_equal(Matrix.columns([ [], [], [] ]), n)
  233. assert_equal(Matrix[[0, 0, 0], [0, 0, 0]], m * n)
  234. end
  235. def test_row
  236. assert_equal(Vector[1, 2, 3], @m1.row(0))
  237. assert_equal(Vector[4, 5, 6], @m1.row(1))
  238. a = []; @m1.row(0) {|x| a << x }
  239. assert_equal([1, 2, 3], a)
  240. end
  241. def test_column
  242. assert_equal(Vector[1, 4], @m1.column(0))
  243. assert_equal(Vector[2, 5], @m1.column(1))
  244. assert_equal(Vector[3, 6], @m1.column(2))
  245. a = []; @m1.column(0) {|x| a << x }
  246. assert_equal([1, 4], a)
  247. end
  248. def test_collect
  249. m1 = Matrix.zero(2,2)
  250. m2 = Matrix.build(3,4){|row, col| 1}
  251. assert_equal(Matrix[[5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5]], m2.collect{|e| e * 5})
  252. assert_equal(Matrix[[7, 0],[0, 7]], m1.collect(:diagonal){|e| e + 7})
  253. assert_equal(Matrix[[0, 5],[5, 0]], m1.collect(:off_diagonal){|e| e + 5})
  254. assert_equal(Matrix[[8, 1, 1, 1], [8, 8, 1, 1], [8, 8, 8, 1]], m2.collect(:lower){|e| e + 7})
  255. assert_equal(Matrix[[1, 1, 1, 1], [-11, 1, 1, 1], [-11, -11, 1, 1]], m2.collect(:strict_lower){|e| e - 12})
  256. assert_equal(Matrix[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], m2.collect(:strict_upper){|e| e ** 2})
  257. assert_equal(Matrix[[-1, -1, -1, -1], [1, -1, -1, -1], [1, 1, -1, -1]], m2.collect(:upper){|e| -e})
  258. assert_raise(ArgumentError) {m1.collect(:test){|e| e + 7}}
  259. assert_not_equal(m2, m2.collect {|e| e * 2 })
  260. end
  261. def test_minor
  262. assert_equal(Matrix[[1, 2], [4, 5]], @m1.minor(0..1, 0..1))
  263. assert_equal(Matrix[[2], [5]], @m1.minor(0..1, 1..1))
  264. assert_equal(Matrix[[4, 5]], @m1.minor(1..1, 0..1))
  265. assert_equal(Matrix[[1, 2], [4, 5]], @m1.minor(0, 2, 0, 2))
  266. assert_equal(Matrix[[4, 5]], @m1.minor(1, 1, 0, 2))
  267. assert_equal(Matrix[[2], [5]], @m1.minor(0, 2, 1, 1))
  268. assert_raise(ArgumentError) { @m1.minor(0) }
  269. end
  270. def test_first_minor
  271. assert_equal(Matrix.empty(0, 0), Matrix[[1]].first_minor(0, 0))
  272. assert_equal(Matrix.empty(0, 2), Matrix[[1, 4, 2]].first_minor(0, 1))
  273. assert_equal(Matrix[[1, 3]], @m1.first_minor(1, 1))
  274. assert_equal(Matrix[[4, 6]], @m1.first_minor(0, 1))
  275. assert_equal(Matrix[[1, 2]], @m1.first_minor(1, 2))
  276. assert_raise(RuntimeError) { Matrix.empty(0, 0).first_minor(0, 0) }
  277. assert_raise(ArgumentError) { @m1.first_minor(4, 0) }
  278. assert_raise(ArgumentError) { @m1.first_minor(0, -1) }
  279. assert_raise(ArgumentError) { @m1.first_minor(-1, 4) }
  280. end
  281. def test_cofactor
  282. assert_equal(1, Matrix[[1]].cofactor(0, 0))
  283. assert_equal(9, Matrix[[7,6],[3,9]].cofactor(0, 0))
  284. assert_equal(0, Matrix[[0,0],[0,0]].cofactor(0, 0))
  285. assert_equal(3, Matrix[[0,0,1],[0,7,6],[1,3,9]].cofactor(1, 0))
  286. assert_equal(-21, Matrix[[7,0,1,0,12],[8,1,1,9,1],[4,0,0,-7,17],[-1,0,0,-4,8],[10,1,1,8,6]].cofactor(2, 3))
  287. assert_raise(RuntimeError) { Matrix.empty(0, 0).cofactor(0, 0) }
  288. assert_raise(ArgumentError) { Matrix[[0,0],[0,0]].cofactor(-1, 4) }
  289. assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { Matrix[[2,0,1],[0,-2,2]].cofactor(0, 0) }
  290. end
  291. def test_adjugate
  292. assert_equal(Matrix.empty, Matrix.empty.adjugate)
  293. assert_equal(Matrix[[1]], Matrix[[5]].adjugate)
  294. assert_equal(Matrix[[9,-6],[-3,7]], Matrix[[7,6],[3,9]].adjugate)
  295. assert_equal(Matrix[[45,3,-7],[6,-1,0],[-7,0,0]], Matrix[[0,0,1],[0,7,6],[1,3,9]].adjugate)
  296. assert_equal(Matrix.identity(5), (@a5.adjugate * @a5) / @a5.det)
  297. assert_equal(Matrix.I(3), Matrix.I(3).adjugate)
  298. assert_equal((@a3 * @b3).adjugate, @b3.adjugate * @a3.adjugate)
  299. assert_equal(4**(@a3.row_count-1) * @a3.adjugate, (4 * @a3).adjugate)
  300. assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { @m1.adjugate }
  301. end
  302. def test_laplace_expansion
  303. assert_equal(1, Matrix[[1]].laplace_expansion(row: 0))
  304. assert_equal(45, Matrix[[7,6], [3,9]].laplace_expansion(row: 1))
  305. assert_equal(0, Matrix[[0,0],[0,0]].laplace_expansion(column: 0))
  306. assert_equal(-7, Matrix[[0,0,1],[0,7,6],[1,3,9]].laplace_expansion(column: 2))
  307. assert_equal(Vector[3, -2], Matrix[[Vector[1, 0], Vector[0, 1]], [2, 3]].laplace_expansion(row: 0))
  308. assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { @m1.laplace_expansion(row: 1) }
  309. assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion() }
  310. assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion(foo: 1) }
  311. assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion(row: 1, column: 1) }
  312. assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion(row: 2) }
  313. assert_raise(ArgumentError) { Matrix[[0,0,1],[0,7,6],[1,3,9]].laplace_expansion(column: -1) }
  314. assert_raise(RuntimeError) { Matrix.empty(0, 0).laplace_expansion(row: 0) }
  315. end
  316. def test_regular?
  317. assert(Matrix[[1, 0], [0, 1]].regular?)
  318. assert(Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]].regular?)
  319. assert(!Matrix[[1, 0, 0], [0, 0, 1], [0, 0, 1]].regular?)
  320. end
  321. def test_singular?
  322. assert(!Matrix[[1, 0], [0, 1]].singular?)
  323. assert(!Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]].singular?)
  324. assert(Matrix[[1, 0, 0], [0, 0, 1], [0, 0, 1]].singular?)
  325. end
  326. def test_square?
  327. assert(Matrix[[1, 0], [0, 1]].square?)
  328. assert(Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]].square?)
  329. assert(Matrix[[1, 0, 0], [0, 0, 1], [0, 0, 1]].square?)
  330. assert(!Matrix[[1, 0, 0], [0, 1, 0]].square?)
  331. end
  332. def test_mul
  333. assert_equal(Matrix[[2,4],[6,8]], Matrix[[2,4],[6,8]] * Matrix.I(2))
  334. assert_equal(Matrix[[4,8],[12,16]], Matrix[[2,4],[6,8]] * 2)
  335. assert_equal(Matrix[[4,8],[12,16]], 2 * Matrix[[2,4],[6,8]])
  336. assert_equal(Matrix[[14,32],[32,77]], @m1 * @m1.transpose)
  337. assert_equal(Matrix[[17,22,27],[22,29,36],[27,36,45]], @m1.transpose * @m1)
  338. assert_equal(Vector[14,32], @m1 * Vector[1,2,3])
  339. o = Object.new
  340. def o.coerce(m)
  341. [m, m.transpose]
  342. end
  343. assert_equal(Matrix[[14,32],[32,77]], @m1 * o)
  344. end
  345. def test_add
  346. assert_equal(Matrix[[6,0],[-4,12]], Matrix.scalar(2,5) + Matrix[[1,0],[-4,7]])
  347. assert_equal(Matrix[[3,5,7],[9,11,13]], @m1 + @n1)
  348. assert_equal(Matrix[[3,5,7],[9,11,13]], @n1 + @m1)
  349. assert_equal(Matrix[[2],[4],[6]], Matrix[[1],[2],[3]] + Vector[1,2,3])
  350. assert_raise(Matrix::ErrOperationNotDefined) { @m1 + 1 }
  351. o = Object.new
  352. def o.coerce(m)
  353. [m, m]
  354. end
  355. assert_equal(Matrix[[2,4,6],[8,10,12]], @m1 + o)
  356. end
  357. def test_sub
  358. assert_equal(Matrix[[4,0],[4,-2]], Matrix.scalar(2,5) - Matrix[[1,0],[-4,7]])
  359. assert_equal(Matrix[[-1,-1,-1],[-1,-1,-1]], @m1 - @n1)
  360. assert_equal(Matrix[[1,1,1],[1,1,1]], @n1 - @m1)
  361. assert_equal(Matrix[[0],[0],[0]], Matrix[[1],[2],[3]] - Vector[1,2,3])
  362. assert_raise(Matrix::ErrOperationNotDefined) { @m1 - 1 }
  363. o = Object.new
  364. def o.coerce(m)
  365. [m, m]
  366. end
  367. assert_equal(Matrix[[0,0,0],[0,0,0]], @m1 - o)
  368. end
  369. def test_div
  370. assert_equal(Matrix[[0,1,1],[2,2,3]], @m1 / 2)
  371. assert_equal(Matrix[[1,1],[1,1]], Matrix[[2,2],[2,2]] / Matrix.scalar(2,2))
  372. o = Object.new
  373. def o.coerce(m)
  374. [m, Matrix.scalar(2,2)]
  375. end
  376. assert_equal(Matrix[[1,1],[1,1]], Matrix[[2,2],[2,2]] / o)
  377. end
  378. def test_hadamard_product
  379. assert_equal(Matrix[[1,4], [9,16]], Matrix[[1,2], [3,4]].hadamard_product(Matrix[[1,2], [3,4]]))
  380. assert_equal(Matrix[[2, 6, 12], [20, 30, 42]], @m1.hadamard_product(@n1))
  381. o = Object.new
  382. def o.to_matrix
  383. Matrix[[1, 2, 3], [-1, 0, 1]]
  384. end
  385. assert_equal(Matrix[[1, 4, 9], [-4, 0, 6]], @m1.hadamard_product(o))
  386. e = Matrix.empty(3, 0)
  387. assert_equal(e, e.hadamard_product(e))
  388. e = Matrix.empty(0, 3)
  389. assert_equal(e, e.hadamard_product(e))
  390. end
  391. def test_exp
  392. assert_equal(Matrix[[67,96],[48,99]], Matrix[[7,6],[3,9]] ** 2)
  393. assert_equal(Matrix.I(5), Matrix.I(5) ** -1)
  394. assert_raise(Matrix::ErrOperationNotDefined) { Matrix.I(5) ** Object.new }
  395. end
  396. def test_det
  397. assert_equal(Matrix.instance_method(:determinant), Matrix.instance_method(:det))
  398. end
  399. def test_rank2
  400. assert_equal(2, Matrix[[7,6],[3,9]].rank)
  401. assert_equal(0, Matrix[[0,0],[0,0]].rank)
  402. assert_equal(3, Matrix[[0,0,1],[0,7,6],[1,3,9]].rank)
  403. assert_equal(1, Matrix[[0,1],[0,1],[0,1]].rank)
  404. assert_equal(2, @m1.rank)
  405. end
  406. def test_trace
  407. assert_equal(1+5+9, Matrix[[1,2,3],[4,5,6],[7,8,9]].trace)
  408. end
  409. def test_transpose
  410. assert_equal(Matrix[[1,4],[2,5],[3,6]], @m1.transpose)
  411. end
  412. def test_conjugate
  413. assert_equal(Matrix[[Complex(1,-2), Complex(0,-1), 0], [1, 2, 3]], @c1.conjugate)
  414. end
  415. def test_eigensystem
  416. m = Matrix[[1, 2], [3, 4]]
  417. v, d, v_inv = m.eigensystem
  418. assert(d.diagonal?)
  419. assert_equal(v.inv, v_inv)
  420. assert_equal((v * d * v_inv).round(5), m)
  421. end
  422. def test_imaginary
  423. assert_equal(Matrix[[2, 1, 0], [0, 0, 0]], @c1.imaginary)
  424. end
  425. def test_lup
  426. m = Matrix[[1, 2], [3, 4]]
  427. l, u, p = m.lup
  428. assert(l.lower_triangular?)
  429. assert(u.upper_triangular?)
  430. assert(p.permutation?)
  431. assert(l * u == p * m)
  432. assert_equal(m.lup.solve([2, 5]), Vector[1, Rational(1,2)])
  433. end
  434. def test_real
  435. assert_equal(Matrix[[1, 0, 0], [1, 2, 3]], @c1.real)
  436. end
  437. def test_rect
  438. assert_equal([Matrix[[1, 0, 0], [1, 2, 3]], Matrix[[2, 1, 0], [0, 0, 0]]], @c1.rect)
  439. end
  440. def test_row_vectors
  441. assert_equal([Vector[1,2,3], Vector[4,5,6]], @m1.row_vectors)
  442. end
  443. def test_column_vectors
  444. assert_equal([Vector[1,4], Vector[2,5], Vector[3,6]], @m1.column_vectors)
  445. end
  446. def test_to_s
  447. assert_equal("Matrix[[1, 2, 3], [4, 5, 6]]", @m1.to_s)
  448. assert_equal("Matrix.empty(0, 0)", Matrix[].to_s)
  449. assert_equal("Matrix.empty(1, 0)", Matrix[[]].to_s)
  450. end
  451. def test_inspect
  452. assert_equal("Matrix[[1, 2, 3], [4, 5, 6]]", @m1.inspect)
  453. assert_equal("Matrix.empty(0, 0)", Matrix[].inspect)
  454. assert_equal("Matrix.empty(1, 0)", Matrix[[]].inspect)
  455. end
  456. def test_scalar_add
  457. s1 = @m1.coerce(1).first
  458. assert_equal(Matrix[[1]], (s1 + 0) * Matrix[[1]])
  459. assert_raise(Matrix::ErrOperationNotDefined) { s1 + Vector[0] }
  460. assert_raise(Matrix::ErrOperationNotDefined) { s1 + Matrix[[0]] }
  461. o = Object.new
  462. def o.coerce(x)
  463. [1, 1]
  464. end
  465. assert_equal(2, s1 + o)
  466. end
  467. def test_scalar_sub
  468. s1 = @m1.coerce(1).first
  469. assert_equal(Matrix[[1]], (s1 - 0) * Matrix[[1]])
  470. assert_raise(Matrix::ErrOperationNotDefined) { s1 - Vector[0] }
  471. assert_raise(Matrix::ErrOperationNotDefined) { s1 - Matrix[[0]] }
  472. o = Object.new
  473. def o.coerce(x)
  474. [1, 1]
  475. end
  476. assert_equal(0, s1 - o)
  477. end
  478. def test_scalar_mul
  479. s1 = @m1.coerce(1).first
  480. assert_equal(Matrix[[1]], (s1 * 1) * Matrix[[1]])
  481. assert_equal(Vector[2], s1 * Vector[2])
  482. assert_equal(Matrix[[2]], s1 * Matrix[[2]])
  483. o = Object.new
  484. def o.coerce(x)
  485. [1, 1]
  486. end
  487. assert_equal(1, s1 * o)
  488. end
  489. def test_scalar_div
  490. s1 = @m1.coerce(1).first
  491. assert_equal(Matrix[[1]], (s1 / 1) * Matrix[[1]])
  492. assert_raise(Matrix::ErrOperationNotDefined) { s1 / Vector[0] }
  493. assert_equal(Matrix[[Rational(1,2)]], s1 / Matrix[[2]])
  494. o = Object.new
  495. def o.coerce(x)
  496. [1, 1]
  497. end
  498. assert_equal(1, s1 / o)
  499. end
  500. def test_scalar_pow
  501. s1 = @m1.coerce(1).first
  502. assert_equal(Matrix[[1]], (s1 ** 1) * Matrix[[1]])
  503. assert_raise(Matrix::ErrOperationNotDefined) { s1 ** Vector[0] }
  504. assert_raise(Matrix::ErrOperationNotImplemented) { s1 ** Matrix[[1]] }
  505. o = Object.new
  506. def o.coerce(x)
  507. [1, 1]
  508. end
  509. assert_equal(1, s1 ** o)
  510. end
  511. def test_abs
  512. s1 = @a3.abs
  513. assert_equal(s1, Matrix[[4, 1, 3], [0, 3, 7], [11, 4, 2]])
  514. end
  515. def test_hstack
  516. assert_equal Matrix[[1,2,3,2,3,4,1,2,3], [4,5,6,5,6,7,4,5,6]],
  517. @m1.hstack(@n1, @m1)
  518. # Error checking:
  519. assert_raise(TypeError) { @m1.hstack(42) }
  520. assert_raise(TypeError) { Matrix.hstack(42, @m1) }
  521. assert_raise(Matrix::ErrDimensionMismatch) { @m1.hstack(Matrix.identity(3)) }
  522. assert_raise(Matrix::ErrDimensionMismatch) { @e1.hstack(@e2) }
  523. # Corner cases:
  524. assert_equal @m1, @m1.hstack
  525. assert_equal @e1, @e1.hstack(@e1)
  526. assert_equal Matrix.empty(0,6), @e2.hstack(@e2)
  527. assert_equal SubMatrix, SubMatrix.hstack(@e1).class
  528. # From Vectors:
  529. assert_equal Matrix[[1, 3],[2, 4]], Matrix.hstack(Vector[1,2], Vector[3, 4])
  530. end
  531. def test_vstack
  532. assert_equal Matrix[[1,2,3], [4,5,6], [2,3,4], [5,6,7], [1,2,3], [4,5,6]],
  533. @m1.vstack(@n1, @m1)
  534. # Error checking:
  535. assert_raise(TypeError) { @m1.vstack(42) }
  536. assert_raise(TypeError) { Matrix.vstack(42, @m1) }
  537. assert_raise(Matrix::ErrDimensionMismatch) { @m1.vstack(Matrix.identity(2)) }
  538. assert_raise(Matrix::ErrDimensionMismatch) { @e1.vstack(@e2) }
  539. # Corner cases:
  540. assert_equal @m1, @m1.vstack
  541. assert_equal Matrix.empty(4,0), @e1.vstack(@e1)
  542. assert_equal @e2, @e2.vstack(@e2)
  543. assert_equal SubMatrix, SubMatrix.vstack(@e1).class
  544. # From Vectors:
  545. assert_equal Matrix[[1],[2],[3]], Matrix.vstack(Vector[1,2], Vector[3])
  546. end
  547. def test_combine
  548. x = Matrix[[6, 6], [4, 4]]
  549. y = Matrix[[1, 2], [3, 4]]
  550. assert_equal Matrix[[5, 4], [1, 0]], Matrix.combine(x, y) {|a, b| a - b}
  551. assert_equal Matrix[[5, 4], [1, 0]], x.combine(y) {|a, b| a - b}
  552. # Without block
  553. assert_equal Matrix[[5, 4], [1, 0]], Matrix.combine(x, y).each {|a, b| a - b}
  554. # With vectors
  555. assert_equal Matrix[[111], [222]], Matrix.combine(Matrix[[1], [2]], Vector[10,20], Vector[100,200], &:sum)
  556. # Basic checks
  557. assert_raise(Matrix::ErrDimensionMismatch) { @m1.combine(x) { raise } }
  558. # Edge cases
  559. assert_equal Matrix.empty, Matrix.combine{ raise }
  560. assert_equal Matrix.empty(3,0), Matrix.combine(Matrix.empty(3,0), Matrix.empty(3,0)) { raise }
  561. assert_equal Matrix.empty(0,3), Matrix.combine(Matrix.empty(0,3), Matrix.empty(0,3)) { raise }
  562. end
  563. def test_set_element
  564. src = Matrix[
  565. [1, 2, 3, 4],
  566. [5, 6, 7, 8],
  567. [9, 10, 11, 12],
  568. ]
  569. rows = {
  570. range: [1..2, 1...3, 1..-1, -2..2, 1.., 1..., -2.., -2...],
  571. int: [2, -1],
  572. invalid: [-4, 4, -4..2, 2..-4, 0...0, 2..0, -4..],
  573. }
  574. columns = {
  575. range: [2..3, 2...4, 2..-1, -2..3, 2.., 2..., -2..., -2..],
  576. int: [3, -1],
  577. invalid: [-5, 5, -5..2, 2..-5, 0...0, -5..],
  578. }
  579. values = {
  580. element: 42,
  581. matrix: Matrix[[20, 21], [22, 23]],
  582. vector: Vector[30, 31],
  583. row: Matrix[[60, 61]],
  584. column: Matrix[[50], [51]],
  585. mismatched_matrix: Matrix.identity(3),
  586. mismatched_vector: Vector[0, 1, 2, 3],
  587. }
  588. solutions = {
  589. [:int, :int] => {
  590. element: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 42]],
  591. },
  592. [:range , :int] => {
  593. element: Matrix[[1, 2, 3, 4], [5, 6, 7, 42], [9, 10, 11, 42]],
  594. column: Matrix[[1, 2, 3, 4], [5, 6, 7, 50], [9, 10, 11, 51]],
  595. vector: Matrix[[1, 2, 3, 4], [5, 6, 7, 30], [9, 10, 11, 31]],
  596. },
  597. [:int, :range] => {
  598. element: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 42, 42]],
  599. row: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 60, 61]],
  600. vector: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 30, 31]],
  601. },
  602. [:range , :range] => {
  603. element: Matrix[[1, 2, 3, 4], [5, 6, 42, 42], [9, 10, 42, 42]],
  604. matrix: Matrix[[1, 2, 3, 4], [5, 6, 20, 21], [9, 10, 22, 23]],
  605. },
  606. }
  607. solutions.default = Hash.new(IndexError)
  608. rows.each do |row_style, row_arguments|
  609. row_arguments.each do |row_argument|
  610. columns.each do |column_style, column_arguments|
  611. column_arguments.each do |column_argument|
  612. values.each do |value_type, value|
  613. expected = solutions[[row_style, column_style]][value_type] || Matrix::ErrDimensionMismatch
  614. result = src.clone
  615. begin
  616. result[row_argument, column_argument] = value
  617. assert_equal expected, result,
  618. "m[#{row_argument.inspect}][#{column_argument.inspect}] = #{value.inspect} failed"
  619. rescue Exception => e
  620. raise if e.class != expected
  621. end
  622. end
  623. end
  624. end
  625. end
  626. end
  627. end
  628. def test_map!
  629. m1 = Matrix.zero(2,2)
  630. m2 = Matrix.build(3,4){|row, col| 1}
  631. m3 = Matrix.zero(3,5).freeze
  632. m4 = Matrix.empty.freeze
  633. assert_equal Matrix[[5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5]], m2.map!{|e| e * 5}
  634. assert_equal Matrix[[7, 0],[0, 7]], m1.map!(:diagonal){|e| e + 7}
  635. assert_equal Matrix[[7, 5],[5, 7]], m1.map!(:off_diagonal){|e| e + 5}
  636. assert_equal Matrix[[12, 5, 5, 5], [12, 12, 5, 5], [12, 12, 12, 5]], m2.map!(:lower){|e| e + 7}
  637. assert_equal Matrix[[12, 5, 5, 5], [0, 12, 5, 5], [0, 0, 12, 5]], m2.map!(:strict_lower){|e| e - 12}
  638. assert_equal Matrix[[12, 25, 25, 25], [0, 12, 25, 25], [0, 0, 12, 25]], m2.map!(:strict_upper){|e| e ** 2}
  639. assert_equal Matrix[[-12, -25, -25, -25], [0, -12, -25, -25], [0, 0, -12, -25]], m2.map!(:upper){|e| -e}
  640. assert_equal m1, m1.map!{|e| e ** 2 }
  641. assert_equal m2, m2.map!(:lower){ |e| e - 3 }
  642. assert_raise(ArgumentError) {m1.map!(:test){|e| e + 7}}
  643. assert_raise(FrozenError) { m3.map!{|e| e * 2} }
  644. assert_raise(FrozenError) { m4.map!{} }
  645. end
  646. def test_freeze
  647. m = Matrix[[1, 2, 3],[4, 5, 6]]
  648. f = m.freeze
  649. assert_equal true, f.frozen?
  650. assert m.equal?(f)
  651. assert m.equal?(f.freeze)
  652. assert_raise(FrozenError){ m[0, 1] = 56 }
  653. assert_equal m.dup, m
  654. end
  655. def test_clone
  656. a = Matrix[[4]]
  657. def a.foo
  658. 42
  659. end
  660. m = a.clone
  661. m[0, 0] = 2
  662. assert_equal a, m * 2
  663. assert_equal 42, m.foo
  664. a.freeze
  665. m = a.clone
  666. assert m.frozen?
  667. assert_equal 42, m.foo
  668. end
  669. def test_dup
  670. a = Matrix[[4]]
  671. def a.foo
  672. 42
  673. end
  674. a.freeze
  675. m = a.dup
  676. m[0, 0] = 2
  677. assert_equal a, m * 2
  678. assert !m.respond_to?(:foo)
  679. end
  680. def test_eigenvalues_and_eigenvectors_symmetric
  681. m = Matrix[
  682. [8, 1],
  683. [1, 8]
  684. ]
  685. values = m.eigensystem.eigenvalues
  686. assert_in_epsilon(7.0, values[0])
  687. assert_in_epsilon(9.0, values[1])
  688. vectors = m.eigensystem.eigenvectors
  689. assert_in_epsilon(-vectors[0][0], vectors[0][1])
  690. assert_in_epsilon(vectors[1][0], vectors[1][1])
  691. end
  692. def test_eigenvalues_and_eigenvectors_nonsymmetric
  693. m = Matrix[
  694. [8, 1],
  695. [4, 5]
  696. ]
  697. values = m.eigensystem.eigenvalues
  698. assert_in_epsilon(9.0, values[0])
  699. assert_in_epsilon(4.0, values[1])
  700. vectors = m.eigensystem.eigenvectors
  701. assert_in_epsilon(vectors[0][0], vectors[0][1])
  702. assert_in_epsilon(-4 * vectors[1][0], vectors[1][1])
  703. end
  704. def test_unitary?
  705. assert_equal true, @rot.unitary?
  706. assert_equal true, ((0+1i) * @rot).unitary?
  707. assert_equal false, @a3.unitary?
  708. assert_raise(Matrix::ErrDimensionMismatch) { @m1.unitary? }
  709. end
  710. def test_orthogonal
  711. assert_equal true, @rot.orthogonal?
  712. assert_equal false, ((0+1i) * @rot).orthogonal?
  713. assert_equal false, @a3.orthogonal?
  714. assert_raise(Matrix::ErrDimensionMismatch) { @m1.orthogonal? }
  715. end
  716. def test_adjoint
  717. assert_equal(Matrix[[(1-2i), 1], [(0-1i), 2], [0, 3]], @c1.adjoint)
  718. assert_equal(Matrix.empty(0,2), @e1.adjoint)
  719. end
  720. end