/matrix/arithmetic.go

https://code.google.com/p/gomatrix/ · Go · 205 lines · 152 code · 24 blank · 29 comment · 44 complexity · 3c60dab8ef2063c122dad789d006c667 MD5 · raw file

  1. // Copyright 2009 The GoMatrix Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package matrix
  5. import "math"
  6. /*
  7. Finds the sum of two matrices.
  8. */
  9. func Sum(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {
  10. C = MakeDenseCopy(A)
  11. var err error
  12. for _, B := range Bs {
  13. err = C.Add(MakeDenseCopy(B))
  14. if err != nil {
  15. break
  16. }
  17. }
  18. if err != nil {
  19. C = nil
  20. }
  21. return
  22. }
  23. /*
  24. Finds the difference between two matrices.
  25. */
  26. func Difference(A, B MatrixRO) (C *DenseMatrix) {
  27. C = MakeDenseCopy(A)
  28. err := C.Subtract(MakeDenseCopy(B))
  29. if err != nil {
  30. C = nil
  31. }
  32. return
  33. }
  34. /*
  35. Finds the Product of two matrices.
  36. */
  37. func Product(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {
  38. C = MakeDenseCopy(A)
  39. for _, B := range Bs {
  40. Cm, err := C.Times(B)
  41. if err != nil {
  42. return
  43. }
  44. C = Cm.(*DenseMatrix)
  45. }
  46. return
  47. }
  48. func Transpose(A MatrixRO) (B Matrix) {
  49. switch Am := A.(type) {
  50. case *DenseMatrix:
  51. B = Am.Transpose()
  52. return
  53. case *SparseMatrix:
  54. B = Am.Transpose()
  55. return
  56. }
  57. B = A.DenseMatrix().Transpose()
  58. return
  59. }
  60. func Inverse(A MatrixRO) (B Matrix) {
  61. var err error
  62. switch Am := A.(type) {
  63. case *DenseMatrix:
  64. B, err = Am.Inverse()
  65. if err != nil {
  66. panic(err)
  67. }
  68. return
  69. }
  70. B, err = A.DenseMatrix().Inverse()
  71. if err != nil {
  72. panic(err)
  73. }
  74. return
  75. }
  76. /*
  77. The Kronecker product. (http://en.wikipedia.org/wiki/Kronecker_product)
  78. */
  79. func Kronecker(A, B MatrixRO) (C *DenseMatrix) {
  80. ars, acs := A.Rows(), A.Cols()
  81. brs, bcs := B.Rows(), B.Cols()
  82. C = Zeros(ars*brs, acs*bcs)
  83. for i := 0; i < ars; i++ {
  84. for j := 0; j < acs; j++ {
  85. Cij := C.GetMatrix(i*brs, j*bcs, brs, bcs)
  86. Cij.SetMatrix(0, 0, Scaled(B, A.Get(i, j)))
  87. }
  88. }
  89. return
  90. }
  91. func Vectorize(Am MatrixRO) (V *DenseMatrix) {
  92. elems := Am.DenseMatrix().Transpose().Array()
  93. V = MakeDenseMatrix(elems, Am.Rows()*Am.Cols(), 1)
  94. return
  95. }
  96. func Unvectorize(V MatrixRO, rows, cols int) (A *DenseMatrix) {
  97. A = MakeDenseMatrix(V.DenseMatrix().Array(), cols, rows).Transpose()
  98. return
  99. }
  100. /*
  101. Uses a number of goroutines to do the dot products necessary
  102. for the matrix multiplication in parallel.
  103. */
  104. func ParallelProduct(A, B MatrixRO) (C *DenseMatrix) {
  105. if A.Cols() != B.Rows() {
  106. return nil
  107. }
  108. C = Zeros(A.Rows(), B.Cols())
  109. in := make(chan int)
  110. quit := make(chan bool)
  111. dotRowCol := func() {
  112. for {
  113. select {
  114. case i := <-in:
  115. sums := make([]float64, B.Cols())
  116. for k := 0; k < A.Cols(); k++ {
  117. for j := 0; j < B.Cols(); j++ {
  118. sums[j] += A.Get(i, k) * B.Get(k, j)
  119. }
  120. }
  121. for j := 0; j < B.Cols(); j++ {
  122. C.Set(i, j, sums[j])
  123. }
  124. case <-quit:
  125. return
  126. }
  127. }
  128. }
  129. threads := 2
  130. for i := 0; i < threads; i++ {
  131. go dotRowCol()
  132. }
  133. for i := 0; i < A.Rows(); i++ {
  134. in <- i
  135. }
  136. for i := 0; i < threads; i++ {
  137. quit <- true
  138. }
  139. return
  140. }
  141. /*
  142. Scales a matrix by a scalar.
  143. */
  144. func Scaled(A MatrixRO, f float64) (B *DenseMatrix) {
  145. B = MakeDenseCopy(A)
  146. B.Scale(f)
  147. return
  148. }
  149. /*
  150. Tests the element-wise equality of the two matrices.
  151. */
  152. func Equals(A, B MatrixRO) bool {
  153. if A.Rows() != B.Rows() || A.Cols() != B.Cols() {
  154. return false
  155. }
  156. for i := 0; i < A.Rows(); i++ {
  157. for j := 0; j < A.Cols(); j++ {
  158. if A.Get(i, j) != B.Get(i, j) {
  159. return false
  160. }
  161. }
  162. }
  163. return true
  164. }
  165. /*
  166. Tests to see if the difference between two matrices,
  167. element-wise, exceeds ε.
  168. */
  169. func ApproxEquals(A, B MatrixRO, ε float64) bool {
  170. if A.Rows() != B.Rows() || A.Cols() != B.Cols() {
  171. return false
  172. }
  173. for i := 0; i < A.Rows(); i++ {
  174. for j := 0; j < A.Cols(); j++ {
  175. if math.Abs(A.Get(i, j)-B.Get(i, j)) > ε {
  176. return false
  177. }
  178. }
  179. }
  180. return true
  181. }