[
  {
    "path": "AUTHORS",
    "content": "John Asmuth <jasmuth@gmail.com>\nRyanne Dolan\n"
  },
  {
    "path": "LICENSE",
    "content": "\u0001\nCopyright (c) 2013 the AUTHORS. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * The names in AUTHORs may not be used to endorse or promote\nproducts derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README",
    "content": ""
  },
  {
    "path": "arithmetic.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"math\"\n\n/*\nFinds the sum of two matrices.\n*/\nfunc Sum(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {\n\tC = MakeDenseCopy(A)\n\tvar err error\n\tfor _, B := range Bs {\n\t\terr = C.Add(MakeDenseCopy(B))\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\tif err != nil {\n\t\tC = nil\n\t}\n\treturn\n}\n\n/*\nFinds the difference between two matrices.\n*/\nfunc Difference(A, B MatrixRO) (C *DenseMatrix) {\n\tC = MakeDenseCopy(A)\n\terr := C.Subtract(MakeDenseCopy(B))\n\tif err != nil {\n\t\tC = nil\n\t}\n\treturn\n}\n\n/*\nFinds the Product of two matrices.\n*/\nfunc Product(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {\n\tC = MakeDenseCopy(A)\n\n\tfor _, B := range Bs {\n\t\tCm, err := C.Times(B)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tC = Cm.(*DenseMatrix)\n\t}\n\n\treturn\n}\n\nfunc Transpose(A MatrixRO) (B Matrix) {\n\tswitch Am := A.(type) {\n\tcase *DenseMatrix:\n\t\tB = Am.Transpose()\n\t\treturn\n\tcase *SparseMatrix:\n\t\tB = Am.Transpose()\n\t\treturn\n\t}\n\tB = A.DenseMatrix().Transpose()\n\treturn\n}\n\nfunc Inverse(A MatrixRO) (B Matrix) {\n\tvar err error\n\tswitch Am := A.(type) {\n\tcase *DenseMatrix:\n\t\tB, err = Am.Inverse()\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn\n\t}\n\tB, err = A.DenseMatrix().Inverse()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn\n}\n\n/*\nThe Kronecker product. (http://en.wikipedia.org/wiki/Kronecker_product)\n*/\nfunc Kronecker(A, B MatrixRO) (C *DenseMatrix) {\n\tars, acs := A.Rows(), A.Cols()\n\tbrs, bcs := B.Rows(), B.Cols()\n\tC = Zeros(ars*brs, acs*bcs)\n\tfor i := 0; i < ars; i++ {\n\t\tfor j := 0; j < acs; j++ {\n\t\t\tCij := C.GetMatrix(i*brs, j*bcs, brs, bcs)\n\t\t\tCij.SetMatrix(0, 0, Scaled(B, A.Get(i, j)))\n\t\t}\n\t}\n\treturn\n}\n\nfunc Vectorize(Am MatrixRO) (V *DenseMatrix) {\n\telems := Am.DenseMatrix().Transpose().Array()\n\tV = MakeDenseMatrix(elems, Am.Rows()*Am.Cols(), 1)\n\treturn\n}\n\nfunc Unvectorize(V MatrixRO, rows, cols int) (A *DenseMatrix) {\n\tA = MakeDenseMatrix(V.DenseMatrix().Array(), cols, rows).Transpose()\n\treturn\n}\n\n/*\nUses a number of goroutines to do the dot products necessary\nfor the matrix multiplication in parallel.\n*/\nfunc ParallelProduct(A, B MatrixRO) (C *DenseMatrix) {\n\tif A.Cols() != B.Rows() {\n\t\treturn nil\n\t}\n\n\tC = Zeros(A.Rows(), B.Cols())\n\n\tin := make(chan int)\n\tquit := make(chan bool)\n\n\tdotRowCol := func() {\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase i := <-in:\n\t\t\t\tsums := make([]float64, B.Cols())\n\t\t\t\tfor k := 0; k < A.Cols(); k++ {\n\t\t\t\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\t\t\t\tsums[j] += A.Get(i, k) * B.Get(k, j)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\t\t\tC.Set(i, j, sums[j])\n\t\t\t\t}\n\t\t\tcase <-quit:\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tthreads := 2\n\n\tfor i := 0; i < threads; i++ {\n\t\tgo dotRowCol()\n\t}\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tin <- i\n\t}\n\n\tfor i := 0; i < threads; i++ {\n\t\tquit <- true\n\t}\n\n\treturn\n}\n\n/*\nScales a matrix by a scalar.\n*/\nfunc Scaled(A MatrixRO, f float64) (B *DenseMatrix) {\n\tB = MakeDenseCopy(A)\n\tB.Scale(f)\n\treturn\n}\n\n/*\nTests the element-wise equality of the two matrices.\n*/\nfunc Equals(A, B MatrixRO) bool {\n\tif A.Rows() != B.Rows() || A.Cols() != B.Cols() {\n\t\treturn false\n\t}\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif A.Get(i, j) != B.Get(i, j) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\n/*\nTests to see if the difference between two matrices,\nelement-wise, exceeds ε.\n*/\nfunc ApproxEquals(A, B MatrixRO, ε float64) bool {\n\tif A.Rows() != B.Rows() || A.Cols() != B.Cols() {\n\t\treturn false\n\t}\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif math.Abs(A.Get(i, j)-B.Get(i, j)) > ε {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "dense.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport (\n\t\"math/rand\"\n)\n\n/*\nA matrix backed by a flat array of all elements.\n*/\ntype DenseMatrix struct {\n\tmatrix\n\t// flattened matrix data. elements[i*step+j] is row i, col j\n\telements []float64\n\t// actual offset between rows\n\tstep int\n}\n\n/*\nReturns an array of slices referencing the matrix data. Changes to\nthe slices effect changes to the matrix.\n*/\nfunc (A *DenseMatrix) Arrays() [][]float64 {\n\ta := make([][]float64, A.rows)\n\tfor i := 0; i < A.rows; i++ {\n\t\ta[i] = A.elements[i*A.step : i*A.step+A.cols]\n\t}\n\treturn a\n}\n\n/*\nReturns the contents of this matrix stored into a flat array (row-major).\n*/\nfunc (A *DenseMatrix) Array() []float64 {\n\tif A.step == A.rows {\n\t\treturn A.elements[0 : A.rows*A.cols]\n\t}\n\ta := make([]float64, A.rows*A.cols)\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\ta[i*A.cols+j] = A.elements[i*A.step+j]\n\t\t}\n\t}\n\treturn a\n}\n\nfunc (A *DenseMatrix) rowSlice(row int) []float64 {\n\treturn A.elements[row*A.step : row*A.step+A.cols]\n}\n\n/*\nGet the element in the ith row and jth column.\n*/\nfunc (A *DenseMatrix) Get(i int, j int) (v float64) {\n\t/*\n\t\ti = i % A.rows\n\t\tif i < 0 {\n\t\t\ti = A.rows - i\n\t\t}\n\t\tj = j % A.cols\n\t\tif j < 0 {\n\t\t\tj = A.cols - j\n\t\t}\n\t*/\n\n\t// reslicing like this does efficient range checks, perhaps\n\tv = A.elements[i*A.step : i*A.step+A.cols][j]\n\t//v = A.elements[i*A.step+j]\n\treturn\n}\n\n/*\nSet the element in the ith row and jth column to v.\n*/\nfunc (A *DenseMatrix) Set(i int, j int, v float64) {\n\t/*\n\t\ti = i % A.rows\n\t\tif i < 0 {\n\t\t\ti = A.rows - i\n\t\t}\n\t\tj = j % A.cols\n\t\tif j < 0 {\n\t\t\tj = A.cols - j\n\t\t}\n\t*/\n\t// reslicing like this does efficient range checks, perhaps\n\tA.elements[i*A.step : i*A.step+A.cols][j] = v\n\t//A.elements[i*A.step+j] = v\n}\n\n/*\nGet a submatrix starting at i,j with rows rows and cols columns. Changes to\nthe returned matrix show up in the original.\n*/\nfunc (A *DenseMatrix) GetMatrix(i, j, rows, cols int) *DenseMatrix {\n\tB := new(DenseMatrix)\n\tB.elements = A.elements[i*A.step+j : i*A.step+j+(rows-1)*A.step+cols]\n\tB.rows = rows\n\tB.cols = cols\n\tB.step = A.step\n\treturn B\n}\n\n/*\nCopy B into A, with B's 0, 0 aligning with A's i, j\n*/\nfunc (A *DenseMatrix) SetMatrix(i, j int, B *DenseMatrix) {\n\tfor r := 0; r < B.rows; r++ {\n\t\tfor c := 0; c < B.cols; c++ {\n\t\t\tA.Set(i+r, j+c, B.Get(r, c))\n\t\t}\n\t}\n}\n\nfunc (A *DenseMatrix) GetColVector(j int) *DenseMatrix {\n\treturn A.GetMatrix(0, j, A.rows, 1)\n}\n\nfunc (A *DenseMatrix) GetRowVector(i int) *DenseMatrix {\n\treturn A.GetMatrix(i, 0, 1, A.cols)\n}\n\n/*\nGet a copy of this matrix with 0s above the diagonal.\n*/\nfunc (A *DenseMatrix) L() *DenseMatrix {\n\tB := A.Copy()\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := i + 1; j < A.cols; j++ {\n\t\t\tB.Set(i, j, 0)\n\t\t}\n\t}\n\treturn B\n}\n\n/*\nGet a copy of this matrix with 0s below the diagonal.\n*/\nfunc (A *DenseMatrix) U() *DenseMatrix {\n\tB := A.Copy()\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < i && j < A.cols; j++ {\n\t\t\tB.Set(i, j, 0)\n\t\t}\n\t}\n\treturn B\n}\n\nfunc (A *DenseMatrix) Copy() *DenseMatrix {\n\tB := new(DenseMatrix)\n\tB.rows = A.rows\n\tB.cols = A.cols\n\tB.step = A.cols\n\tB.elements = make([]float64, B.rows*B.cols)\n\tfor row := 0; row < B.rows; row++ {\n\t\tcopy(B.rowSlice(row), A.rowSlice(row))\n\t}\n\treturn B\n}\n\n/*\nGet a new matrix [A B].\n*/\nfunc (A *DenseMatrix) Augment(B *DenseMatrix) (C *DenseMatrix, err error) {\n\tif A.rows != B.rows {\n\t\terr = ErrorDimensionMismatch\n\t\treturn\n\t}\n\tC = Zeros(A.rows, A.cols+B.cols)\n\terr = A.AugmentFill(B, C)\n\treturn\n}\nfunc (A *DenseMatrix) AugmentFill(B, C *DenseMatrix) (err error) {\n\tif A.rows != B.rows || C.rows != A.rows || C.cols != A.cols+B.cols {\n\t\terr = ErrorDimensionMismatch\n\t\treturn\n\t}\n\tC.SetMatrix(0, 0, A)\n\tC.SetMatrix(0, A.cols, B)\n\t/*\n\t\tfor i := 0; i < C.Rows(); i++ {\n\t\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\t\tC.Set(i, j, A.Get(i, j))\n\t\t\t}\n\t\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\t\tC.Set(i, j+A.Cols(), B.Get(i, j))\n\t\t\t}\n\t\t}*/\n\treturn\n}\n\n/*\nGet a new matrix [A; B], with A above B.\n*/\nfunc (A *DenseMatrix) Stack(B *DenseMatrix) (C *DenseMatrix, err error) {\n\tif A.cols != B.cols {\n\t\terr = ErrorDimensionMismatch\n\t\treturn\n\t}\n\tC = Zeros(A.rows+B.rows, A.cols)\n\terr = A.StackFill(B, C)\n\treturn\n}\nfunc (A *DenseMatrix) StackFill(B, C *DenseMatrix) (err error) {\n\tif A.cols != B.cols || C.cols != A.cols || C.rows != A.rows+B.rows {\n\t\terr = ErrorDimensionMismatch\n\t\treturn\n\t}\n\tC.SetMatrix(0, 0, A)\n\tC.SetMatrix(A.rows, 0, B)\n\t/*\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tfor i := 0; i < A.Rows(); i++ {\n\t\t\t\tC.Set(i, j, A.Get(i, j))\n\t\t\t}\n\t\t\tfor i := 0; i < B.cols; i++ {\n\t\t\t\tC.Set(i+A.rows, j, B.Get(i, j))\n\t\t\t}\n\t\t}\n\t*/\n\treturn\n}\n\n/*\nCreate a sparse matrix copy.\n*/\nfunc (A *DenseMatrix) SparseMatrix() *SparseMatrix {\n\tB := ZerosSparse(A.rows, A.cols)\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tv := A.Get(i, j)\n\t\t\tif v != 0 {\n\t\t\t\tB.Set(i, j, v)\n\t\t\t}\n\t\t}\n\t}\n\treturn B\n}\n\nfunc (A *DenseMatrix) DenseMatrix() *DenseMatrix {\n\treturn A.Copy()\n}\n\nfunc Zeros(rows, cols int) *DenseMatrix {\n\tA := new(DenseMatrix)\n\tA.elements = make([]float64, rows*cols)\n\tA.rows = rows\n\tA.cols = cols\n\tA.step = cols\n\treturn A\n}\n\nfunc Ones(rows, cols int) *DenseMatrix {\n\tA := new(DenseMatrix)\n\tA.elements = make([]float64, rows*cols)\n\tA.rows = rows\n\tA.cols = cols\n\tA.step = cols\n\n\tfor i := 0; i < len(A.elements); i++ {\n\t\tA.elements[i] = 1\n\t}\n\n\treturn A\n}\n\nfunc Numbers(rows, cols int, num float64) *DenseMatrix {\n\tA := Zeros(rows, cols)\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tA.Set(i, j, num)\n\t\t}\n\t}\n\n\treturn A\n}\n\n/*\nCreate an identity matrix with span rows and span columns.\n*/\nfunc Eye(span int) *DenseMatrix {\n\tA := Zeros(span, span)\n\tfor i := 0; i < span; i++ {\n\t\tA.Set(i, i, 1)\n\t}\n\treturn A\n}\n\nfunc Normals(rows, cols int) *DenseMatrix {\n\tA := Zeros(rows, cols)\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tA.Set(i, j, rand.NormFloat64())\n\t\t}\n\t}\n\n\treturn A\n}\n\nfunc Diagonal(d []float64) *DenseMatrix {\n\tn := len(d)\n\tA := Zeros(n, n)\n\tfor i := 0; i < n; i++ {\n\t\tA.Set(i, i, d[i])\n\t}\n\treturn A\n}\n\nfunc MakeDenseCopy(A MatrixRO) *DenseMatrix {\n\tB := Zeros(A.Rows(), A.Cols())\n\tfor i := 0; i < B.rows; i++ {\n\t\tfor j := 0; j < B.cols; j++ {\n\t\t\tB.Set(i, j, A.Get(i, j))\n\t\t}\n\t}\n\treturn B\n}\n\nfunc MakeDenseMatrix(elements []float64, rows, cols int) *DenseMatrix {\n\tA := new(DenseMatrix)\n\tA.rows = rows\n\tA.cols = cols\n\tA.step = cols\n\tA.elements = elements\n\treturn A\n}\n\nfunc MakeDenseMatrixStacked(data [][]float64) *DenseMatrix {\n\trows := len(data)\n\tcols := len(data[0])\n\telements := make([]float64, rows*cols)\n\tfor i := 0; i < rows; i++ {\n\t\tfor j := 0; j < cols; j++ {\n\t\t\telements[i*cols+j] = data[i][j]\n\t\t}\n\t}\n\treturn MakeDenseMatrix(elements, rows, cols)\n}\n\nfunc (A *DenseMatrix) String() string { return String(A) }\n"
  },
  {
    "path": "dense_arithmetic.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"runtime\"\n\nfunc (A *DenseMatrix) Plus(B MatrixRO) (Matrix, error) {\n\tC := A.Copy()\n\terr := C.Add(B)\n\treturn C, err\n}\nfunc (A *DenseMatrix) PlusDense(B *DenseMatrix) (*DenseMatrix, error) {\n\tC := A.Copy()\n\terr := C.AddDense(B)\n\treturn C, err\n}\n\nfunc (A *DenseMatrix) Minus(B MatrixRO) (Matrix, error) {\n\tC := A.Copy()\n\terr := C.Subtract(B)\n\treturn C, err\n}\n\nfunc (A *DenseMatrix) MinusDense(B *DenseMatrix) (*DenseMatrix, error) {\n\tC := A.Copy()\n\terr := C.SubtractDense(B)\n\treturn C, err\n}\n\nfunc (A *DenseMatrix) Add(B MatrixRO) error {\n\tif A.cols != B.Cols() || A.rows != B.Rows() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tindex := i * A.step\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.elements[index] += B.Get(i, j)\n\t\t\tindex++\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (A *DenseMatrix) AddDense(B *DenseMatrix) error {\n\tif A.cols != B.cols || A.rows != B.rows {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.elements[i*A.step+j] += B.elements[i*B.step+j]\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (A *DenseMatrix) Subtract(B MatrixRO) error {\n\tif Bd, ok := B.(*DenseMatrix); ok {\n\t\treturn A.SubtractDense(Bd)\n\t}\n\n\tif A.cols != B.Cols() || A.rows != B.Rows() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tindex := i * A.step\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.elements[index] -= B.Get(i, j)\n\t\t\tindex++\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (A *DenseMatrix) SubtractDense(B *DenseMatrix) error {\n\n\tif A.cols != B.cols || A.rows != B.rows {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tindexA := i * A.step\n\t\tindexB := i * B.step\n\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.elements[indexA] -= B.elements[indexB]\n\t\t\tindexA++\n\t\t\tindexB++\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (A *DenseMatrix) Times(B MatrixRO) (Matrix, error) {\n\n\tif Bd, ok := B.(*DenseMatrix); ok {\n\t\treturn A.TimesDense(Bd)\n\t}\n\n\tif A.cols != B.Rows() {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tC := Zeros(A.rows, B.Cols())\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tsum := float64(0)\n\t\t\tfor k := 0; k < A.cols; k++ {\n\t\t\t\tsum += A.elements[i*A.step+k] * B.Get(k, j)\n\t\t\t}\n\t\t\tC.elements[i*C.step+j] = sum\n\t\t}\n\t}\n\n\treturn C, nil\n}\n\ntype parJob struct {\n\tstart, finish int\n}\n\nfunc parTimes1(A, B, C *DenseMatrix) {\n\tC = Zeros(A.rows, B.cols)\n\n\tmp := runtime.GOMAXPROCS(0)\n\n\tjobChan := make(chan box, 1+mp)\n\n\tgo func() {\n\t\trowCount := A.rows / mp\n\t\tfor startRow := 0; startRow < A.rows; startRow += rowCount {\n\t\t\tstart := startRow\n\t\t\tfinish := startRow + rowCount\n\t\t\tif finish >= A.rows {\n\t\t\t\tfinish = A.rows\n\t\t\t}\n\t\t\tjobChan <- parJob{start: start, finish: finish}\n\t\t}\n\t\tclose(jobChan)\n\t}()\n\n\twait := parFor(jobChan, func(iBox box) {\n\t\tjob := iBox.(parJob)\n\t\tfor i := job.start; i < job.finish; i++ {\n\t\t\tsums := C.elements[i*C.step : (i+1)*C.step]\n\t\t\tfor k := 0; k < A.cols; k++ {\n\t\t\t\tfor j := 0; j < B.cols; j++ {\n\t\t\t\t\tsums[j] += A.elements[i*A.step+k] * B.elements[k*B.step+j]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\twait()\n\n\treturn\n}\n\n//this is an adaptation of code from a go-nuts post made by Dmitriy Vyukov\nfunc parTimes2(A, B, C *DenseMatrix) {\n\tconst threshold = 8\n\n\tcurrentGoroutineCount := 1\n\tmaxGoroutines := runtime.GOMAXPROCS(0) + 2\n\n\tvar aux func(sync chan bool, A, B, C *DenseMatrix, rs, re, cs, ce, ks, ke int)\n\taux = func(sync chan bool, A, B, C *DenseMatrix, rs, re, cs, ce, ks, ke int) {\n\t\tdr := re - rs\n\t\tdc := ce - cs\n\t\tdk := ke - ks\n\t\tswitch {\n\t\tcase currentGoroutineCount < maxGoroutines && dr >= dc && dr >= dk && dr >= threshold:\n\t\t\tsync0 := make(chan bool, 1)\n\t\t\trm := (rs + re) / 2\n\t\t\tcurrentGoroutineCount++\n\t\t\tgo aux(sync0, A, B, C, rs, rm, cs, ce, ks, ke)\n\t\t\taux(nil, A, B, C, rm, re, cs, ce, ks, ke)\n\t\t\t<-sync0\n\t\t\tcurrentGoroutineCount--\n\t\tcase currentGoroutineCount < maxGoroutines && dc >= dk && dc >= dr && dc >= threshold:\n\t\t\tsync0 := make(chan bool, 1)\n\t\t\tcm := (cs + ce) / 2\n\t\t\tcurrentGoroutineCount++\n\t\t\tgo aux(sync0, A, B, C, rs, re, cs, cm, ks, ke)\n\t\t\taux(nil, A, B, C, rs, re, cm, ce, ks, ke)\n\t\t\t<-sync0\n\t\t\tcurrentGoroutineCount--\n\t\tcase currentGoroutineCount < maxGoroutines && dk >= dc && dk >= dr && dk >= threshold:\n\t\t\tkm := (ks + ke) / 2\n\t\t\taux(nil, A, B, C, rs, re, cs, ce, ks, km)\n\t\t\taux(nil, A, B, C, rs, re, cs, ce, km, ke)\n\t\tdefault:\n\t\t\tfor row := rs; row < re; row++ {\n\t\t\t\tsums := C.elements[row*C.step : (row+1)*C.step]\n\t\t\t\tfor k := ks; k < ke; k++ {\n\t\t\t\t\tfor col := cs; col < ce; col++ {\n\t\t\t\t\t\tsums[col] += A.elements[row*A.step+k] * B.elements[k*B.step+col]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif sync != nil {\n\t\t\tsync <- true\n\t\t}\n\t}\n\n\taux(nil, A, B, C, 0, A.rows, 0, B.cols, 0, A.cols)\n\n\treturn\n}\n\nvar (\n\tWhichParMethod  = 2\n\tWhichSyncMethod = 1\n)\n\nfunc (A *DenseMatrix) TimesDense(B *DenseMatrix) (C *DenseMatrix, err error) {\n\tC = Zeros(A.rows, B.cols)\n\terr = A.TimesDenseFill(B, C)\n\treturn\n}\nfunc (A *DenseMatrix) TimesDenseFill(B, C *DenseMatrix) (err error) {\n\tif C.rows != A.rows || C.cols != B.cols || A.cols != B.rows {\n\t\terr = ErrorDimensionMismatch\n\t\treturn\n\t}\n\tif WhichParMethod > 0 && runtime.GOMAXPROCS(0) > 1 {\n\t\tswitch WhichParMethod {\n\t\tcase 1:\n\t\t\tparTimes1(A, B, C)\n\t\tcase 2:\n\t\t\tparTimes2(A, B, C)\n\t\t}\n\t} else {\n\t\tswitch {\n\t\tcase A.cols > 100 && WhichSyncMethod == 2:\n\t\t\ttransposeTimes(A, B, C)\n\t\tdefault:\n\t\t\tfor i := 0; i < A.rows; i++ {\n\t\t\t\tsums := C.elements[i*C.step : (i+1)*C.step]\n\t\t\t\tfor k, a := range A.elements[i*A.step : i*A.step + A.cols] {\n\t\t\t\t\tfor j, b := range B.elements[k*B.step : k * B.step + B.cols] {\n\t\t\t\t\t\tsums[j] += a * b\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn\n}\n\nfunc transposeTimes(A, B, C *DenseMatrix) {\n\tBt := B.Transpose()\n\n\tBcols := Bt.Arrays()\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tArow := A.elements[i*A.step : i*A.step+A.cols]\n\t\tfor j := 0; j < B.cols; j++ {\n\t\t\tBcol := Bcols[j]\n\t\t\tfor k := range Arow {\n\t\t\t\tC.elements[i*C.step+j] += Arow[k] * Bcol[k]\n\t\t\t}\n\t\t}\n\t}\n\n\treturn\n}\n\nfunc (A *DenseMatrix) ElementMult(B MatrixRO) (Matrix, error) {\n\tC := A.Copy()\n\terr := C.ScaleMatrix(B)\n\treturn C, err\n}\n\nfunc (A *DenseMatrix) ElementMultDense(B *DenseMatrix) (*DenseMatrix, error) {\n\tC := A.Copy()\n\terr := C.ScaleMatrixDense(B)\n\treturn C, err\n}\n\nfunc (A *DenseMatrix) Scale(f float64) {\n\tfor i := 0; i < A.rows; i++ {\n\t\tindex := i * A.step\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.elements[index] *= f\n\t\t\tindex++\n\t\t}\n\t}\n}\n\nfunc (A *DenseMatrix) ScaleMatrix(B MatrixRO) error {\n\tif Bd, ok := B.(*DenseMatrix); ok {\n\t\treturn A.ScaleMatrixDense(Bd)\n\t}\n\n\tif A.rows != B.Rows() || A.cols != B.Cols() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\tfor i := 0; i < A.rows; i++ {\n\t\tindexA := i * A.step\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.elements[indexA] *= B.Get(i, j)\n\t\t\tindexA++\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (A *DenseMatrix) ScaleMatrixDense(B *DenseMatrix) error {\n\tif A.rows != B.rows || A.cols != B.cols {\n\t\treturn ErrorDimensionMismatch\n\t}\n\tfor i := 0; i < A.rows; i++ {\n\t\tindexA := i * A.step\n\t\tindexB := i * B.step\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.elements[indexA] *= B.elements[indexB]\n\t\t\tindexA++\n\t\t\tindexB++\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "dense_basic.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport (\n\t\"math\"\n\t\"errors\"\n)\n\nfunc (A *DenseMatrix) Symmetric() bool {\n\tif A.rows != A.cols {\n\t\treturn false\n\t}\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < i; j++ {\n\t\t\tif A.Get(i, j) != A.Get(j, i) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (m *DenseMatrix) SwapRows(r1 int, r2 int) {\n\tindex1 := r1 * m.step\n\tindex2 := r2 * m.step\n\tfor j := 0; j < m.cols; j++ {\n\t\tm.elements[index1], m.elements[index2] = m.elements[index2], m.elements[index1]\n\t\tindex1++\n\t\tindex2++\n\t}\n}\n\nfunc (m *DenseMatrix) ScaleRow(r int, f float64) {\n\tindex := r * m.step\n\tfor j := 0; j < m.cols; j++ {\n\t\tm.elements[index] *= f\n\t\tindex++\n\t}\n}\n\nfunc (m *DenseMatrix) ScaleAddRow(rd int, rs int, f float64) {\n\tindexd := rd * m.step\n\tindexs := rs * m.step\n\tfor j := 0; j < m.cols; j++ {\n\t\tm.elements[indexd] += f * m.elements[indexs]\n\t\tindexd++\n\t\tindexs++\n\t}\n}\n\nfunc (A *DenseMatrix) Inverse() (*DenseMatrix, error) {\n\tif A.Rows() != A.Cols() {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\taug, _ := A.Augment(Eye(A.Rows()))\n\tfor i := 0; i < aug.Rows(); i++ {\n\t\tj := i\n\t\tfor k := i; k < aug.Rows(); k++ {\n\t\t\tif math.Abs(aug.Get(k, i)) > math.Abs(aug.Get(j, i)) {\n\t\t\t\tj = k\n\t\t\t}\n\t\t}\n\t\tif j != i {\n\t\t\taug.SwapRows(i, j)\n\t\t}\n\t\tif aug.Get(i, i) == 0 {\n\t\t\treturn nil, ExceptionSingular\n\t\t}\n\t\taug.ScaleRow(i, 1.0/aug.Get(i, i))\n\t\tfor k := 0; k < aug.Rows(); k++ {\n\t\t\tif k == i {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\taug.ScaleAddRow(k, i, -aug.Get(k, i))\n\t\t}\n\t}\n\tinv := aug.GetMatrix(0, A.Cols(), A.Rows(), A.Cols())\n\treturn inv, nil\n}\n\nfunc (A *DenseMatrix) Det() float64 {\n\tB := A.Copy()\n\tP := B.LUInPlace()\n\treturn product(B.DiagonalCopy()) * P.Det()\n}\n\nfunc (A *DenseMatrix) Trace() float64 { return sum(A.DiagonalCopy()) }\n\nfunc (A *DenseMatrix) OneNorm() (ε float64) {\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tε = max(ε, A.Get(i, j))\n\t\t}\n\t}\n\treturn\n}\n\nfunc (A *DenseMatrix) TwoNorm() float64 {\n\tvar sum float64 = 0\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tv := A.elements[i*A.step+j]\n\t\t\tsum += v * v\n\t\t}\n\t}\n\treturn math.Sqrt(sum)\n}\n\nfunc (A *DenseMatrix) InfinityNorm() (ε float64) {\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tε += A.Get(i, j)\n\t\t}\n\t}\n\treturn\n}\n\nfunc (A *DenseMatrix) Transpose() *DenseMatrix {\n\tB := Zeros(A.Cols(), A.Rows())\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tB.Set(j, i, A.Get(i, j))\n\t\t}\n\t}\n\treturn B\n}\n\nfunc (A *DenseMatrix) TransposeInPlace() (err error) {\n\tif A.rows != A.cols {\n\t\terr = errors.New(\"Can only transpose a square matrix in place\")\n\t\treturn\n\t}\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < i; j++ {\n\t\t\ttmp := A.Get(i, j)\n\t\t\tA.Set(i, j, A.Get(j, i))\n\t\t\tA.Set(j, i, tmp)\n\t\t}\n\t}\n\treturn\n}\n\nfunc solveLower(A *DenseMatrix, b Matrix) *DenseMatrix {\n\tx := make([]float64, A.Cols())\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tx[i] = b.Get(i, 0)\n\t\tfor j := 0; j < i; j++ {\n\t\t\tx[i] -= x[j] * A.Get(i, j)\n\t\t}\n\t\t//the diagonal defined to be ones\n\t\t//x[i] /= A.Get(i, i);\n\t}\n\treturn MakeDenseMatrix(x, A.Cols(), 1)\n}\n\nfunc solveUpper(A *DenseMatrix, b Matrix) *DenseMatrix {\n\tx := make([]float64, A.Cols())\n\tfor i := A.Rows() - 1; i >= 0; i-- {\n\t\tx[i] = b.Get(i, 0)\n\t\tfor j := i + 1; j < A.Cols(); j++ {\n\t\t\tx[i] -= x[j] * A.Get(i, j)\n\t\t}\n\t\tx[i] /= A.Get(i, i)\n\t}\n\treturn MakeDenseMatrix(x, A.Cols(), 1)\n}\n\nfunc (A *DenseMatrix) Solve(b MatrixRO) (*DenseMatrix, error) {\n\tAcopy := A.Copy()\n\tP := Acopy.LUInPlace()\n\tPinv := P.Inverse()\n\tpb, err := Pinv.Times(b)\n\n\tif !(err == nil) {\n\t\treturn nil, err\n\t}\n\n\ty := solveLower(Acopy, pb)\n\tx := solveUpper(Acopy, y)\n\treturn x, nil\n}\n\nfunc (A *DenseMatrix) SolveDense(b *DenseMatrix) (*DenseMatrix, error) {\n\treturn A.Solve(b)\n}\n"
  },
  {
    "path": "dense_data.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\n//returns a copy of the row (not a slice)\nfunc (A *DenseMatrix) RowCopy(i int) []float64 {\n\trow := make([]float64, A.cols)\n\tfor j := 0; j < A.cols; j++ {\n\t\trow[j] = A.Get(i, j)\n\t}\n\treturn row\n}\n\n//returns a copy of the column (not a slice)\nfunc (A *DenseMatrix) ColCopy(j int) []float64 {\n\tcol := make([]float64, A.rows)\n\tfor i := 0; i < A.rows; i++ {\n\t\tcol[i] = A.Get(i, j)\n\t}\n\treturn col\n}\n\n//returns a copy of the diagonal (not a slice)\nfunc (A *DenseMatrix) DiagonalCopy() []float64 {\n\tspan := A.rows\n\tif A.cols < span {\n\t\tspan = A.cols\n\t}\n\tdiag := make([]float64, span)\n\tfor i := 0; i < span; i++ {\n\t\tdiag[i] = A.Get(i, i)\n\t}\n\treturn diag\n}\n\nfunc (A *DenseMatrix) BufferRow(i int, buf []float64) {\n\tfor j := 0; j < A.cols; j++ {\n\t\tbuf[j] = A.Get(i, j)\n\t}\n}\n\nfunc (A *DenseMatrix) BufferCol(j int, buf []float64) {\n\tfor i := 0; i < A.rows; i++ {\n\t\tbuf[i] = A.Get(i, j)\n\t}\n}\n\nfunc (A *DenseMatrix) BufferDiagonal(buf []float64) {\n\tfor i := 0; i < A.rows && i < A.cols; i++ {\n\t\tbuf[i] = A.Get(i, i)\n\t}\n}\n\nfunc (A *DenseMatrix) FillRow(i int, buf []float64) {\n\tfor j := 0; j < A.cols; j++ {\n\t\tA.Set(i, j, buf[j])\n\t}\n}\n\nfunc (A *DenseMatrix) FillCol(j int, buf []float64) {\n\tfor i := 0; i < A.rows; i++ {\n\t\tA.Set(i, j, buf[i])\n\t}\n}\n\nfunc (A *DenseMatrix) FillDiagonal(buf []float64) {\n\tfor i := 0; i < A.rows && i < A.cols; i++ {\n\t\tA.Set(i, i, buf[i])\n\t}\n}\n"
  },
  {
    "path": "dense_decomp.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"math\"\n\n/*\nReturns the cholesky decomposition C of A, st CC'=A.\n*/\nfunc (A *DenseMatrix) Cholesky() (L *DenseMatrix, err error) {\n\tn := A.Rows()\n\tL = Zeros(n, n)\n\tisspd := A.Cols() == n\n\n\tfor j := 0; j < n; j++ {\n\t\tLrowj := L.RowCopy(j)\n\t\td := float64(0)\n\t\tfor k := 0; k < j; k++ {\n\t\t\tLrowk := L.RowCopy(k)\n\t\t\ts := float64(0)\n\t\t\tfor i := 0; i < k; i++ {\n\t\t\t\ts += Lrowk[i] * Lrowj[i]\n\t\t\t}\n\t\t\ts = (A.Get(j, k) - s) / Lrowk[k]\n\t\t\tLrowj[k] = s\n\t\t\tL.Set(j, k, s)\n\t\t\td += s * s\n\t\t\tisspd = isspd && (A.Get(k, j) == A.Get(j, k))\n\t\t}\n\t\td = A.Get(j, j) - d\n\t\tisspd = isspd && (d > 0.0)\n\t\tL.Set(j, j, math.Sqrt(max(d, float64(0))))\n\t\tfor k := j + 1; k < n; k++ {\n\t\t\tL.Set(j, k, 0)\n\t\t}\n\t}\n\n\tif !isspd {\n\t\terr = ExceptionNotSPD\n\t}\n\n\treturn\n}\n\n/*\nreturn L,U,P, st PLU=A.\n*/\nfunc (A *DenseMatrix) LU() (L, U *DenseMatrix, P *PivotMatrix) {\n\tm := A.Rows()\n\tn := A.Cols()\n\tC := A.Copy()\n\n\tP = C.LUInPlace()\n\n\tL = C.L()\n\tfor i := 0; i < m && i < n; i++ {\n\t\tL.Set(i, i, 1)\n\t}\n\tU = C.U()\n\n\treturn\n}\n\n/*\nOverwrites A with [L\\U] and returns P, st PLU=A. L is considered to\nhave 1s in the diagonal.\n*/\nfunc (A *DenseMatrix) LUInPlace() (P *PivotMatrix) {\n\tm := A.Rows()\n\tn := A.Cols()\n\tLUcolj := make([]float64, m)\n\tLUrowi := make([]float64, n)\n\tpiv := make([]int, m)\n\tfor i := 0; i < m; i++ {\n\t\tpiv[i] = i\n\t}\n\tpivsign := float64(1.0)\n\n\tfor j := 0; j < n; j++ {\n\t\tA.BufferCol(j, LUcolj)\n\t\tfor i := 0; i < m; i++ {\n\t\t\tA.BufferRow(i, LUrowi)\n\t\t\tkmax := i\n\t\t\tif j < i {\n\t\t\t\tkmax = j\n\t\t\t}\n\t\t\ts := float64(0)\n\t\t\tfor k := 0; k < kmax; k++ {\n\t\t\t\ts += LUrowi[k] * LUcolj[k]\n\t\t\t}\n\t\t\tLUcolj[i] -= s\n\t\t\tLUrowi[j] = LUcolj[i]\n\t\t\tA.Set(i, j, LUrowi[j])\n\t\t}\n\n\t\tp := j\n\t\tfor i := j + 1; i < m; i++ {\n\t\t\tif math.Abs(LUcolj[i]) > math.Abs(LUcolj[p]) {\n\t\t\t\tp = i\n\t\t\t}\n\t\t}\n\t\tif p != j {\n\t\t\tA.SwapRows(p, j)\n\t\t\tk := piv[p]\n\t\t\tpiv[p] = piv[j]\n\t\t\tpiv[j] = k\n\t\t\tpivsign = -pivsign\n\t\t}\n\n\t\tif j < m && A.Get(j, j) != 0 {\n\t\t\tfor i := j + 1; i < m; i++ {\n\t\t\t\tA.Set(i, j, A.Get(i, j)/A.Get(j, j))\n\t\t\t}\n\t\t}\n\t}\n\n\tP = MakePivotMatrix(piv, pivsign)\n\n\treturn\n}\n\nfunc (A *DenseMatrix) QR() (Q, R *DenseMatrix) {\n\tm := A.Rows()\n\tn := A.Cols()\n\tQR := A.Copy()\n\tQ = Zeros(m, n)\n\tR = Zeros(m, n)\n\ti, j, k := 0, 0, 0\n\tnorm := float64(0.0)\n\ts := float64(0.0)\n\n\tfor k = 0; k < n; k++ {\n\t\tnorm = 0\n\t\tfor i = k; i < m; i++ {\n\t\t\tnorm = math.Hypot(norm, QR.Get(i, k))\n\t\t}\n\n\t\tif norm != 0.0 {\n\t\t\tif QR.Get(k, k) < 0 {\n\t\t\t\tnorm = -norm\n\t\t\t}\n\n\t\t\tfor i = k; i < m; i++ {\n\t\t\t\tQR.Set(i, k, QR.Get(i, k)/norm)\n\t\t\t}\n\t\t\tQR.Set(k, k, QR.Get(k, k)+1.0)\n\n\t\t\tfor j = k + 1; j < n; j++ {\n\t\t\t\ts = 0.0\n\t\t\t\tfor i = k; i < m; i++ {\n\t\t\t\t\ts += QR.Get(i, k) * QR.Get(i, j)\n\t\t\t\t}\n\t\t\t\ts = -s / QR.Get(k, k)\n\t\t\t\tfor i = k; i < m; i++ {\n\t\t\t\t\tQR.Set(i, j, QR.Get(i, j)+s*QR.Get(i, k))\n\n\t\t\t\t\tif i < j {\n\t\t\t\t\t\tR.Set(i, j, QR.Get(i, j))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tR.Set(k, k, -norm)\n\n\t}\n\n\t//Q Matrix:\n\ti, j, k = 0, 0, 0\n\n\tfor k = n - 1; k >= 0; k-- {\n\t\tQ.Set(k, k, 1.0)\n\t\tfor j = k; j < n; j++ {\n\t\t\tif QR.Get(k, k) != 0 {\n\t\t\t\ts = 0.0\n\t\t\t\tfor i = k; i < m; i++ {\n\t\t\t\t\ts += QR.Get(i, k) * Q.Get(i, j)\n\t\t\t\t}\n\t\t\t\ts = -s / QR.Get(k, k)\n\t\t\t\tfor i = k; i < m; i++ {\n\t\t\t\t\tQ.Set(i, j, Q.Get(i, j)+s*QR.Get(i, k))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn\n}\n"
  },
  {
    "path": "dense_eigen.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"math\"\n\n/*\nReturns V,D st V*D*inv(V) = A and D is diagonal (or block diagonal).\n*/\nfunc (A *DenseMatrix) Eigen() (V, D *DenseMatrix, err error) {\n\t//code translated/ripped off from Jama\n\tif A.cols != A.rows {\n\t\terr = ErrorDimensionMismatch\n\t\treturn\n\t}\n\tn := A.cols\n\tVa := A.Copy().Arrays()\n\td := make([]float64, n)\n\te := make([]float64, n)\n\tif A.Symmetric() {\n\n\t\ttred2(Va[0:n], d[0:n], e[0:n]) //pass slices so they're references\n\n\t\ttql2(Va[0:n], d[0:n], e[0:n])\n\t} else {\n\t\tH := A.GetMatrix(0, 0, n, n).Copy().Arrays()\n\t\tort := make([]float64, n)\n\n\t\t// Reduce to Hessenberg form.\n\t\torthes(Va[0:n], d[0:n], e[0:n], H[0:n], ort[0:n])\n\n\t\t// Reduce Hessenberg to real Schur form.\n\t\thqr2(Va[0:n], d[0:n], e[0:n], H[0:n], ort[0:n])\n\t}\n\tV, D = MakeDenseMatrixStacked(Va), makeD(d, e)\n\treturn\n}\n\nfunc makeD(d []float64, e []float64) *DenseMatrix {\n\tn := len(d)\n\tX := Zeros(n, n)\n\tD := X.Arrays()\n\tfor i := 0; i < n; i++ {\n\t\tfor j := 0; j < n; j++ {\n\t\t\tD[i][j] = 0.0\n\t\t}\n\t\tD[i][i] = d[i]\n\t\tif e[i] > 0 {\n\t\t\tD[i][i+1] = e[i]\n\t\t} else if e[i] < 0 {\n\t\t\tD[i][i-1] = e[i]\n\t\t}\n\t}\n\treturn X\n}\n\nfunc tred2(V [][]float64, d []float64, e []float64) {\n\tn := len(V)\n\n\t//  This is derived from the Algol procedures tred2 by\n\t//  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for\n\t//  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding\n\t//  Fortran subroutine in EISPACK.\n\n\tfor j := 0; j < n; j++ {\n\t\td[j] = V[n-1][j]\n\t}\n\n\t// Householder reduction to tridiagonal form.\n\n\tfor i := n - 1; i > 0; i-- {\n\n\t\t// Scale to avoid under/overflow.\n\n\t\tscale := float64(0)\n\t\th := float64(0)\n\t\tfor k := 0; k < i; k++ {\n\t\t\tscale = scale + math.Abs(d[k])\n\t\t}\n\t\tif scale == 0.0 {\n\t\t\te[i] = d[i-1]\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\td[j] = V[i-1][j]\n\t\t\t\tV[i][j] = 0.0\n\t\t\t\tV[j][i] = 0.0\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Generate Householder vector.\n\n\t\t\tfor k := 0; k < i; k++ {\n\t\t\t\td[k] /= scale\n\t\t\t\th += d[k] * d[k]\n\t\t\t}\n\t\t\tf := d[i-1]\n\t\t\tg := math.Sqrt(h)\n\t\t\tif f > 0 {\n\t\t\t\tg = -g\n\t\t\t}\n\t\t\te[i] = scale * g\n\t\t\th = h - f*g\n\t\t\td[i-1] = f - g\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\te[j] = 0.0\n\t\t\t}\n\t\t\t// Apply similarity transformation to remaining columns.\n\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\tf = d[j]\n\t\t\t\tV[j][i] = f\n\t\t\t\tg = e[j] + V[j][j]*f\n\t\t\t\tfor k := j + 1; k <= i-1; k++ {\n\t\t\t\t\tg += V[k][j] * d[k]\n\t\t\t\t\te[k] += V[k][j] * f\n\t\t\t\t}\n\t\t\t\te[j] = g\n\t\t\t}\n\n\t\t\tf = 0.0\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\te[j] /= h\n\t\t\t\tf += e[j] * d[j]\n\t\t\t}\n\t\t\thh := f / (h + h)\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\te[j] -= hh * d[j]\n\t\t\t}\n\n\t\t\tfor j := 0; j < i; j++ {\n\t\t\t\tf = d[j]\n\t\t\t\tg = e[j]\n\t\t\t\tfor k := j; k <= i-1; k++ {\n\t\t\t\t\tV[k][j] -= (f*e[k] + g*d[k])\n\t\t\t\t}\n\t\t\t\td[j] = V[i-1][j]\n\t\t\t\tV[i][j] = 0.0\n\t\t\t}\n\t\t}\n\t\td[i] = h\n\t}\n\n\t// Accumulate transformations.\n\n\tfor i := 0; i < n-1; i++ {\n\t\tV[n-1][i] = V[i][i]\n\t\tV[i][i] = 1.0\n\t\th := d[i+1]\n\t\tif h != 0.0 {\n\t\t\tfor k := 0; k <= i; k++ {\n\t\t\t\td[k] = V[k][i+1] / h\n\t\t\t}\n\t\t\tfor j := 0; j <= i; j++ {\n\t\t\t\tg := float64(0)\n\t\t\t\tfor k := 0; k <= i; k++ {\n\t\t\t\t\tg += V[k][i+1] * V[k][j]\n\t\t\t\t}\n\t\t\t\tfor k := 0; k <= i; k++ {\n\t\t\t\t\tV[k][j] -= g * d[k]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor k := 0; k <= i; k++ {\n\t\t\tV[k][i+1] = 0.0\n\t\t}\n\t}\n\tfor j := 0; j < n; j++ {\n\t\td[j] = V[n-1][j]\n\t\tV[n-1][j] = 0.0\n\t}\n\tV[n-1][n-1] = 1.0\n\te[0] = 0.0\n}\n\nfunc tql2(V [][]float64, d []float64, e []float64) {\n\n\t//  This is derived from the Algol procedures tql2, by\n\t//  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for\n\t//  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding\n\t//  Fortran subroutine in EISPACK.\n\n\tn := len(V)\n\n\tfor i := 1; i < n; i++ {\n\t\te[i-1] = e[i]\n\t}\n\te[n-1] = 0.0\n\n\tf := float64(0)\n\ttst1 := float64(0)\n\teps := math.Pow(2.0, -52.0)\n\tfor l := 0; l < n; l++ {\n\n\t\t// Find small subdiagonal element\n\n\t\ttst1 = max(tst1, math.Abs(d[l])+math.Abs(e[l]))\n\t\tm := l\n\t\tfor m < n {\n\t\t\tif math.Abs(e[m]) <= eps*tst1 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tm++\n\t\t}\n\n\t\t// If m == l, d[l] is an eigenvalue,\n\t\t// otherwise, iterate.\n\n\t\tif m > l {\n\t\t\titer := 0\n\t\t\tfor true {\n\t\t\t\titer = iter + 1 // (Could check iteration count here.)\n\n\t\t\t\t// Compute implicit shift\n\n\t\t\t\tg := d[l]\n\t\t\t\tp := (d[l+1] - g) / (2.0 * e[l])\n\t\t\t\tr := math.Sqrt(p*p + 1.0)\n\t\t\t\tif p < 0 {\n\t\t\t\t\tr = -r\n\t\t\t\t}\n\t\t\t\td[l] = e[l] / (p + r)\n\t\t\t\td[l+1] = e[l] * (p + r)\n\t\t\t\tdl1 := d[l+1]\n\t\t\t\th := g - d[l]\n\t\t\t\tfor i := l + 2; i < n; i++ {\n\t\t\t\t\td[i] -= h\n\t\t\t\t}\n\t\t\t\tf = f + h\n\n\t\t\t\t// Implicit QL transformation.\n\n\t\t\t\tp = d[m]\n\t\t\t\tc := float64(1)\n\t\t\t\tc2 := c\n\t\t\t\tc3 := c\n\t\t\t\tel1 := e[l+1]\n\t\t\t\ts := float64(0)\n\t\t\t\ts2 := float64(0)\n\t\t\t\tfor i := m - 1; i >= l; i-- {\n\t\t\t\t\tc3 = c2\n\t\t\t\t\tc2 = c\n\t\t\t\t\ts2 = s\n\t\t\t\t\tg = c * e[i]\n\t\t\t\t\th = c * p\n\t\t\t\t\tr = math.Sqrt(p*p + e[i]*e[i])\n\t\t\t\t\te[i+1] = s * r\n\t\t\t\t\ts = e[i] / r\n\t\t\t\t\tc = p / r\n\t\t\t\t\tp = c*d[i] - s*g\n\t\t\t\t\td[i+1] = h + s*(c*g+s*d[i])\n\n\t\t\t\t\t// Accumulate transformation.\n\n\t\t\t\t\tfor k := 0; k < n; k++ {\n\t\t\t\t\t\th = V[k][i+1]\n\t\t\t\t\t\tV[k][i+1] = s*V[k][i] + c*h\n\t\t\t\t\t\tV[k][i] = c*V[k][i] - s*h\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tp = -s * s2 * c3 * el1 * e[l] / dl1\n\t\t\t\te[l] = s * p\n\t\t\t\td[l] = c * p\n\n\t\t\t\t// Check for convergence.\n\t\t\t\tif !(math.Abs(e[l]) > eps*tst1) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\td[l] = d[l] + f\n\t\te[l] = 0.0\n\t}\n\n\t// Sort eigenvalues and corresponding vectors.\n\n\tfor i := 0; i < n-1; i++ {\n\t\tk := i\n\t\tp := d[i]\n\t\tfor j := i + 1; j < n; j++ {\n\t\t\tif d[j] < p {\n\t\t\t\tk = j\n\t\t\t\tp = d[j]\n\t\t\t}\n\t\t}\n\t\tif k != i {\n\t\t\td[k] = d[i]\n\t\t\td[i] = p\n\t\t\tfor j := 0; j < n; j++ {\n\t\t\t\tp = V[j][i]\n\t\t\t\tV[j][i] = V[j][k]\n\t\t\t\tV[j][k] = p\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc orthes(V [][]float64, d []float64, e []float64, H [][]float64, ort []float64) {\n\n\t//  This is derived from the Algol procedures orthes and ortran,\n\t//  by Martin and Wilkinson, Handbook for Auto. Comp.,\n\t//  Vol.ii-Linear Algebra, and the corresponding\n\t//  Fortran subroutines in EISPACK.\n\n\tn := len(V)\n\n\tlow := 0\n\thigh := n - 1\n\n\tfor m := low + 1; m <= high-1; m++ {\n\n\t\t// Scale column.\n\n\t\tscale := float64(0)\n\t\tfor i := m; i <= high; i++ {\n\t\t\tscale = scale + math.Abs(H[i][m-1])\n\t\t}\n\t\tif scale != 0.0 {\n\n\t\t\t// Compute Householder transformation.\n\n\t\t\th := float64(0)\n\t\t\tfor i := high; i >= m; i-- {\n\t\t\t\tort[i] = H[i][m-1] / scale\n\t\t\t\th += ort[i] * ort[i]\n\t\t\t}\n\t\t\tg := math.Sqrt(h)\n\t\t\tif ort[m] > 0 {\n\t\t\t\tg = -g\n\t\t\t}\n\t\t\th = h - ort[m]*g\n\t\t\tort[m] = ort[m] - g\n\n\t\t\t// Apply Householder similarity transformation\n\t\t\t// H = (I-u*u'/h)*H*(I-u*u')/h)\n\n\t\t\tfor j := m; j < n; j++ {\n\t\t\t\tf := float64(0)\n\t\t\t\tfor i := high; i >= m; i-- {\n\t\t\t\t\tf += ort[i] * H[i][j]\n\t\t\t\t}\n\t\t\t\tf = f / h\n\t\t\t\tfor i := m; i <= high; i++ {\n\t\t\t\t\tH[i][j] -= f * ort[i]\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor i := 0; i <= high; i++ {\n\t\t\t\tf := float64(0)\n\t\t\t\tfor j := high; j >= m; j-- {\n\t\t\t\t\tf += ort[j] * H[i][j]\n\t\t\t\t}\n\t\t\t\tf = f / h\n\t\t\t\tfor j := m; j <= high; j++ {\n\t\t\t\t\tH[i][j] -= f * ort[j]\n\t\t\t\t}\n\t\t\t}\n\t\t\tort[m] = scale * ort[m]\n\t\t\tH[m][m-1] = scale * g\n\t\t}\n\t}\n\n\t// Accumulate transformations (Algol's ortran).\n\n\tfor i := 0; i < n; i++ {\n\t\tfor j := 0; j < n; j++ {\n\t\t\tif i == j {\n\t\t\t\tV[i][j] = 1\n\t\t\t} else {\n\t\t\t\tV[i][j] = 0\n\t\t\t}\n\t\t}\n\t}\n\n\tfor m := high - 1; m >= low+1; m-- {\n\t\tif H[m][m-1] != 0.0 {\n\t\t\tfor i := m + 1; i <= high; i++ {\n\t\t\t\tort[i] = H[i][m-1]\n\t\t\t}\n\t\t\tfor j := m; j <= high; j++ {\n\t\t\t\tg := float64(0)\n\t\t\t\tfor i := m; i <= high; i++ {\n\t\t\t\t\tg += ort[i] * V[i][j]\n\t\t\t\t}\n\t\t\t\t// Double division avoids possible underflow\n\t\t\t\tg = (g / ort[m]) / H[m][m-1]\n\t\t\t\tfor i := m; i <= high; i++ {\n\t\t\t\t\tV[i][j] += g * ort[i]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc hqr2(V [][]float64, d []float64, e []float64, H [][]float64, ort []float64) {\n\n\t//  This is derived from the Algol procedure hqr2,\n\t//  by Martin and Wilkinson, Handbook for Auto. Comp.,\n\t//  Vol.ii-Linear Algebra, and the corresponding\n\t//  Fortran subroutine in EISPACK.\n\n\t// Initialize\n\n\tn := len(V)\n\n\tnn := n\n\tn = nn - 1\n\tlow := 0\n\thigh := nn - 1\n\teps := math.Pow(2.0, -52.0)\n\texshift := float64(0)\n\tp := float64(0)\n\tq := float64(0)\n\tr := float64(0)\n\ts := float64(0)\n\tz := float64(0)\n\tvar t, w, x, y float64\n\n\t// Store roots isolated by balanc and compute matrix norm\n\n\tnorm := float64(0)\n\tfor i := 0; i < nn; i++ {\n\t\tif i < low || i > high {\n\t\t\td[i] = H[i][i]\n\t\t\te[i] = 0.0\n\t\t}\n\t\tfor j := int(max(float64(i)-1, 0)); j < nn; j++ {\n\t\t\tnorm = norm + math.Abs(H[i][j])\n\t\t}\n\t}\n\n\t// Outer loop over eigenvalue index\n\n\titer := 0\n\tfor n >= low {\n\n\t\t// Look for single small sub-diagonal element\n\n\t\tl := n\n\t\tfor l > low {\n\t\t\ts = math.Abs(H[l-1][l-1]) + math.Abs(H[l][l])\n\t\t\tif s == 0.0 {\n\t\t\t\ts = norm\n\t\t\t}\n\t\t\tif math.Abs(H[l][l-1]) < eps*s {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tl--\n\t\t}\n\n\t\t// Check for convergence\n\t\t// One root found\n\n\t\tif l == n {\n\t\t\tH[n][n] = H[n][n] + exshift\n\t\t\td[n] = H[n][n]\n\t\t\te[n] = 0.0\n\t\t\tn--\n\t\t\titer = 0\n\n\t\t\t// Two roots found\n\n\t\t} else if l == n-1 {\n\t\t\tw = H[n][n-1] * H[n-1][n]\n\t\t\tp = (H[n-1][n-1] - H[n][n]) / 2.0\n\t\t\tq = p*p + w\n\t\t\tz = math.Sqrt(math.Abs(q))\n\t\t\tH[n][n] = H[n][n] + exshift\n\t\t\tH[n-1][n-1] = H[n-1][n-1] + exshift\n\t\t\tx = H[n][n]\n\n\t\t\t// Real pair\n\n\t\t\tif q >= 0 {\n\t\t\t\tif p >= 0 {\n\t\t\t\t\tz = p + z\n\t\t\t\t} else {\n\t\t\t\t\tz = p - z\n\t\t\t\t}\n\t\t\t\td[n-1] = x + z\n\t\t\t\td[n] = d[n-1]\n\t\t\t\tif z != 0.0 {\n\t\t\t\t\td[n] = x - w/z\n\t\t\t\t}\n\t\t\t\te[n-1] = 0.0\n\t\t\t\te[n] = 0.0\n\t\t\t\tx = H[n][n-1]\n\t\t\t\ts = math.Abs(x) + math.Abs(z)\n\t\t\t\tp = x / s\n\t\t\t\tq = z / s\n\t\t\t\tr = math.Sqrt(p*p + q*q)\n\t\t\t\tp = p / r\n\t\t\t\tq = q / r\n\n\t\t\t\t// Row modification\n\n\t\t\t\tfor j := n - 1; j < nn; j++ {\n\t\t\t\t\tz = H[n-1][j]\n\t\t\t\t\tH[n-1][j] = q*z + p*H[n][j]\n\t\t\t\t\tH[n][j] = q*H[n][j] - p*z\n\t\t\t\t}\n\n\t\t\t\t// Column modification\n\n\t\t\t\tfor i := 0; i <= n; i++ {\n\t\t\t\t\tz = H[i][n-1]\n\t\t\t\t\tH[i][n-1] = q*z + p*H[i][n]\n\t\t\t\t\tH[i][n] = q*H[i][n] - p*z\n\t\t\t\t}\n\n\t\t\t\t// Accumulate transformations\n\n\t\t\t\tfor i := low; i <= high; i++ {\n\t\t\t\t\tz = V[i][n-1]\n\t\t\t\t\tV[i][n-1] = q*z + p*V[i][n]\n\t\t\t\t\tV[i][n] = q*V[i][n] - p*z\n\t\t\t\t}\n\n\t\t\t\t// Complex pair\n\n\t\t\t} else {\n\t\t\t\td[n-1] = x + p\n\t\t\t\td[n] = x + p\n\t\t\t\te[n-1] = z\n\t\t\t\te[n] = -z\n\t\t\t}\n\t\t\tn = n - 2\n\t\t\titer = 0\n\n\t\t\t// No convergence yet\n\n\t\t} else {\n\n\t\t\t// Form shift\n\n\t\t\tx = H[n][n]\n\t\t\ty = 0.0\n\t\t\tw = 0.0\n\t\t\tif l < n {\n\t\t\t\ty = H[n-1][n-1]\n\t\t\t\tw = H[n][n-1] * H[n-1][n]\n\t\t\t}\n\n\t\t\t// Wilkinson's original ad hoc shift\n\n\t\t\tif iter == 10 {\n\t\t\t\texshift += x\n\t\t\t\tfor i := low; i <= n; i++ {\n\t\t\t\t\tH[i][i] -= x\n\t\t\t\t}\n\t\t\t\ts = math.Abs(H[n][n-1]) + math.Abs(H[n-1][n-2])\n\t\t\t\ty = 0.75 * s\n\t\t\t\tx = y\n\t\t\t\tw = -0.4375 * s * s\n\t\t\t}\n\n\t\t\t// MATLAB's new ad hoc shift\n\n\t\t\tif iter == 30 {\n\t\t\t\ts = (y - x) / 2.0\n\t\t\t\ts = s*s + w\n\t\t\t\tif s > 0 {\n\t\t\t\t\ts = math.Sqrt(s)\n\t\t\t\t\tif y < x {\n\t\t\t\t\t\ts = -s\n\t\t\t\t\t}\n\t\t\t\t\ts = x - w/((y-x)/2.0+s)\n\t\t\t\t\tfor i := low; i <= n; i++ {\n\t\t\t\t\t\tH[i][i] -= s\n\t\t\t\t\t}\n\t\t\t\t\texshift += s\n\t\t\t\t\tw = 0.964\n\t\t\t\t\ty = w\n\t\t\t\t\tx = y\n\t\t\t\t}\n\t\t\t}\n\n\t\t\titer = iter + 1 // (Could check iteration count here.)\n\n\t\t\t// Look for two consecutive small sub-diagonal elements\n\n\t\t\tm := n - 2\n\t\t\tfor m >= l {\n\t\t\t\tz = H[m][m]\n\t\t\t\tr = x - z\n\t\t\t\ts = y - z\n\t\t\t\tp = (r*s-w)/H[m+1][m] + H[m][m+1]\n\t\t\t\tq = H[m+1][m+1] - z - r - s\n\t\t\t\tr = H[m+2][m+1]\n\t\t\t\ts = math.Abs(p) + math.Abs(q) + math.Abs(r)\n\t\t\t\tp = p / s\n\t\t\t\tq = q / s\n\t\t\t\tr = r / s\n\t\t\t\tif m == l {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif math.Abs(H[m][m-1])*(math.Abs(q)+math.Abs(r)) <\n\t\t\t\t\teps*(math.Abs(p)*(math.Abs(H[m-1][m-1])+math.Abs(z)+\n\t\t\t\t\t\tmath.Abs(H[m+1][m+1]))) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tm--\n\t\t\t}\n\n\t\t\tfor i := m + 2; i <= n; i++ {\n\t\t\t\tH[i][i-2] = 0.0\n\t\t\t\tif i > m+2 {\n\t\t\t\t\tH[i][i-3] = 0.0\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Double QR step involving rows l:n and columns m:n\n\n\t\t\tfor k := m; k <= n-1; k++ {\n\t\t\t\tnotlast := (k != n-1)\n\t\t\t\tif k != m {\n\t\t\t\t\tp = H[k][k-1]\n\t\t\t\t\tq = H[k+1][k-1]\n\t\t\t\t\tif notlast {\n\t\t\t\t\t\tr = H[k+2][k-1]\n\t\t\t\t\t} else {\n\t\t\t\t\t\tr = 0\n\t\t\t\t\t}\n\n\t\t\t\t\tx = math.Abs(p) + math.Abs(q) + math.Abs(r)\n\t\t\t\t\tif x != 0.0 {\n\t\t\t\t\t\tp = p / x\n\t\t\t\t\t\tq = q / x\n\t\t\t\t\t\tr = r / x\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif x == 0.0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\ts = math.Sqrt(p*p + q*q + r*r)\n\t\t\t\tif p < 0 {\n\t\t\t\t\ts = -s\n\t\t\t\t}\n\t\t\t\tif s != 0 {\n\t\t\t\t\tif k != m {\n\t\t\t\t\t\tH[k][k-1] = -s * x\n\t\t\t\t\t} else if l != m {\n\t\t\t\t\t\tH[k][k-1] = -H[k][k-1]\n\t\t\t\t\t}\n\t\t\t\t\tp = p + s\n\t\t\t\t\tx = p / s\n\t\t\t\t\ty = q / s\n\t\t\t\t\tz = r / s\n\t\t\t\t\tq = q / p\n\t\t\t\t\tr = r / p\n\n\t\t\t\t\t// Row modification\n\n\t\t\t\t\tfor j := k; j < nn; j++ {\n\t\t\t\t\t\tp = H[k][j] + q*H[k+1][j]\n\t\t\t\t\t\tif notlast {\n\t\t\t\t\t\t\tp = p + r*H[k+2][j]\n\t\t\t\t\t\t\tH[k+2][j] = H[k+2][j] - p*z\n\t\t\t\t\t\t}\n\t\t\t\t\t\tH[k][j] = H[k][j] - p*x\n\t\t\t\t\t\tH[k+1][j] = H[k+1][j] - p*y\n\t\t\t\t\t}\n\n\t\t\t\t\t// Column modification\n\n\t\t\t\t\tfor i := 0; i <= int(min(float64(n), float64(k)+3)); i++ {\n\t\t\t\t\t\tp = x*H[i][k] + y*H[i][k+1]\n\t\t\t\t\t\tif notlast {\n\t\t\t\t\t\t\tp = p + z*H[i][k+2]\n\t\t\t\t\t\t\tH[i][k+2] = H[i][k+2] - p*r\n\t\t\t\t\t\t}\n\t\t\t\t\t\tH[i][k] = H[i][k] - p\n\t\t\t\t\t\tH[i][k+1] = H[i][k+1] - p*q\n\t\t\t\t\t}\n\n\t\t\t\t\t// Accumulate transformations\n\n\t\t\t\t\tfor i := low; i <= high; i++ {\n\t\t\t\t\t\tp = x*V[i][k] + y*V[i][k+1]\n\t\t\t\t\t\tif notlast {\n\t\t\t\t\t\t\tp = p + z*V[i][k+2]\n\t\t\t\t\t\t\tV[i][k+2] = V[i][k+2] - p*r\n\t\t\t\t\t\t}\n\t\t\t\t\t\tV[i][k] = V[i][k] - p\n\t\t\t\t\t\tV[i][k+1] = V[i][k+1] - p*q\n\t\t\t\t\t}\n\t\t\t\t} // (s != 0)\n\t\t\t} // k loop\n\t\t} // check convergence\n\t} // while (n >= low)\n\n\t// Backsubstitute to find vectors of upper triangular form\n\n\tif norm == 0.0 {\n\t\treturn\n\t}\n\n\tfor n = nn - 1; n >= 0; n-- {\n\t\tp = d[n]\n\t\tq = e[n]\n\n\t\t// Real vector\n\n\t\tif q == 0 {\n\t\t\tl := n\n\t\t\tH[n][n] = 1.0\n\t\t\tfor i := n - 1; i >= 0; i-- {\n\t\t\t\tw = H[i][i] - p\n\t\t\t\tr = 0.0\n\t\t\t\tfor j := l; j <= n; j++ {\n\t\t\t\t\tr = r + H[i][j]*H[j][n]\n\t\t\t\t}\n\t\t\t\tif e[i] < 0.0 {\n\t\t\t\t\tz = w\n\t\t\t\t\ts = r\n\t\t\t\t} else {\n\t\t\t\t\tl = i\n\t\t\t\t\tif e[i] == 0.0 {\n\t\t\t\t\t\tif w != 0.0 {\n\t\t\t\t\t\t\tH[i][n] = -r / w\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tH[i][n] = -r / (eps * norm)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Solve real equations\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tx = H[i][i+1]\n\t\t\t\t\t\ty = H[i+1][i]\n\t\t\t\t\t\tq = (d[i]-p)*(d[i]-p) + e[i]*e[i]\n\t\t\t\t\t\tt = (x*s - z*r) / q\n\t\t\t\t\t\tH[i][n] = t\n\t\t\t\t\t\tif math.Abs(x) > math.Abs(z) {\n\t\t\t\t\t\t\tH[i+1][n] = (-r - w*t) / x\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tH[i+1][n] = (-s - y*t) / z\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Overflow control\n\n\t\t\t\t\tt = math.Abs(H[i][n])\n\t\t\t\t\tif (eps*t)*t > 1 {\n\t\t\t\t\t\tfor j := i; j <= n; j++ {\n\t\t\t\t\t\t\tH[j][n] = H[j][n] / t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Complex vector\n\n\t\t} else if q < 0 {\n\t\t\tl := n - 1\n\n\t\t\t// Last vector component imaginary so matrix is triangular\n\n\t\t\tif math.Abs(H[n][n-1]) > math.Abs(H[n-1][n]) {\n\t\t\t\tH[n-1][n-1] = q / H[n][n-1]\n\t\t\t\tH[n-1][n] = -(H[n][n] - p) / H[n][n-1]\n\t\t\t} else {\n\t\t\t\tcdivr, cdivi := cdiv(0.0, -H[n-1][n], H[n-1][n-1]-p, q)\n\t\t\t\tH[n-1][n-1] = cdivr\n\t\t\t\tH[n-1][n] = cdivi\n\t\t\t}\n\t\t\tH[n][n-1] = 0.0\n\t\t\tH[n][n] = 1.0\n\t\t\tfor i := n - 2; i >= 0; i-- {\n\t\t\t\tvar ra, sa, vr, vi float64\n\t\t\t\tra = 0.0\n\t\t\t\tsa = 0.0\n\t\t\t\tfor j := l; j <= n; j++ {\n\t\t\t\t\tra = ra + H[i][j]*H[j][n-1]\n\t\t\t\t\tsa = sa + H[i][j]*H[j][n]\n\t\t\t\t}\n\t\t\t\tw = H[i][i] - p\n\n\t\t\t\tif e[i] < 0.0 {\n\t\t\t\t\tz = w\n\t\t\t\t\tr = ra\n\t\t\t\t\ts = sa\n\t\t\t\t} else {\n\t\t\t\t\tl = i\n\t\t\t\t\tif e[i] == 0 {\n\t\t\t\t\t\tcdivr, cdivi := cdiv(-ra, -sa, w, q)\n\t\t\t\t\t\tH[i][n-1] = cdivr\n\t\t\t\t\t\tH[i][n] = cdivi\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Solve complex equations\n\n\t\t\t\t\t\tx = H[i][i+1]\n\t\t\t\t\t\ty = H[i+1][i]\n\t\t\t\t\t\tvr = (d[i]-p)*(d[i]-p) + e[i]*e[i] - q*q\n\t\t\t\t\t\tvi = (d[i] - p) * 2.0 * q\n\t\t\t\t\t\tif vr == 0.0 && vi == 0.0 {\n\t\t\t\t\t\t\tvr = eps * norm * (math.Abs(w) + math.Abs(q) +\n\t\t\t\t\t\t\t\tmath.Abs(x) + math.Abs(y) + math.Abs(z))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcdivr, cdivi := cdiv(x*r-z*ra+q*sa, x*s-z*sa-q*ra, vr, vi)\n\t\t\t\t\t\tH[i][n-1] = cdivr\n\t\t\t\t\t\tH[i][n] = cdivi\n\t\t\t\t\t\tif math.Abs(x) > (math.Abs(z) + math.Abs(q)) {\n\t\t\t\t\t\t\tH[i+1][n-1] = (-ra - w*H[i][n-1] + q*H[i][n]) / x\n\t\t\t\t\t\t\tH[i+1][n] = (-sa - w*H[i][n] - q*H[i][n-1]) / x\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcdiv(-r-y*H[i][n-1], -s-y*H[i][n], z, q)\n\t\t\t\t\t\t\tH[i+1][n-1] = cdivr\n\t\t\t\t\t\t\tH[i+1][n] = cdivi\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Overflow control\n\n\t\t\t\t\tt = max(math.Abs(H[i][n-1]), math.Abs(H[i][n]))\n\t\t\t\t\tif (eps*t)*t > 1 {\n\t\t\t\t\t\tfor j := i; j <= n; j++ {\n\t\t\t\t\t\t\tH[j][n-1] = H[j][n-1] / t\n\t\t\t\t\t\t\tH[j][n] = H[j][n] / t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Vectors of isolated roots\n\n\tfor i := 0; i < nn; i++ {\n\t\tif i < low || i > high {\n\t\t\tfor j := i; j < nn; j++ {\n\t\t\t\tV[i][j] = H[i][j]\n\t\t\t}\n\t\t}\n\t}\n\n\t// Back transformation to get eigenvectors of original matrix\n\n\tfor j := nn - 1; j >= low; j-- {\n\t\tfor i := low; i <= high; i++ {\n\t\t\tz = 0.0\n\t\t\tfor k := low; k <= int(min(float64(j), float64(high))); k++ {\n\t\t\t\tz = z + V[i][k]*H[k][j]\n\t\t\t}\n\t\t\tV[i][j] = z\n\t\t}\n\t}\n}\n\nfunc cdiv(xr float64, xi float64, yr float64, yi float64) (cdivr float64, cdivi float64) {\n\tvar r, d float64\n\tif math.Abs(yr) > math.Abs(yi) {\n\t\tr = yi / yr\n\t\td = yr + r*yi\n\t\tcdivr = (xr + r*xi) / d\n\t\tcdivi = (xi - r*xr) / d\n\t} else {\n\t\tr = yr / yi\n\t\td = yi + r*yr\n\t\tcdivr = (r*xr + xi) / d\n\t\tcdivi = (r*xi - xr) / d\n\t}\n\treturn\n}\n"
  },
  {
    "path": "dense_svd.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"math\"\n\n/*\nReturns U, Σ, V st Σ is diagonal (or block diagonal) and UΣV'=Arg\n*/\nfunc (Arg *DenseMatrix) SVD() (theU, Σ, theV *DenseMatrix, err error) {\n\t//copied from Jama\n\t// Derived from LINPACK code.\n\t// Initialize.\n\tA := Arg.Copy().Arrays()\n\tm := Arg.rows\n\tn := Arg.cols\n\n\t/* Apparently the failing cases are only a proper subset of (m<n),\n\t\t so let's not throw error.  Correct fix to come later?\n\t      if (m<n) {\n\t\t  throw new IllegalArgumentException(\"Jama SVD only works for m >= n\"); }\n\t*/\n\n\tif m < n {\n\t\terr = ErrorDimensionMismatch\n\t\treturn\n\t}\n\n\tnu := minInt(m, n)\n\ts := make([]float64, minInt(m+1, n))\n\n\tU := make([][]float64, m)\n\tfor i := 0; i < m; i++ {\n\t\tU[i] = make([]float64, nu)\n\t}\n\tV := make([][]float64, n)\n\tfor i := 0; i < n; i++ {\n\t\tV[i] = make([]float64, n)\n\t}\n\n\te := make([]float64, n)\n\twork := make([]float64, m)\n\twantu := true\n\twantv := true\n\n\t// Reduce A to bidiagonal form, storing the diagonal elements\n\t// in s and the super-diagonal elements in e.\n\n\tnct := minInt(m-1, n)\n\tnrt := maxInt(0, minInt(n-2, m))\n\tfor k := 0; k < maxInt(nct, nrt); k++ {\n\t\tif k < nct {\n\n\t\t\t// Compute the transformation for the k-th column and\n\t\t\t// place the k-th diagonal in s[k].\n\t\t\t// Compute 2-norm of k-th column without under/overflow.\n\t\t\ts[k] = 0\n\t\t\tfor i := k; i < m; i++ {\n\t\t\t\ts[k] = math.Hypot(s[k], A[i][k])\n\t\t\t}\n\t\t\tif s[k] != 0.0 {\n\t\t\t\tif A[k][k] < 0.0 {\n\t\t\t\t\ts[k] = -s[k]\n\t\t\t\t}\n\t\t\t\tfor i := k; i < m; i++ {\n\t\t\t\t\tA[i][k] /= s[k]\n\t\t\t\t}\n\t\t\t\tA[k][k] += 1.0\n\t\t\t}\n\t\t\ts[k] = -s[k]\n\t\t}\n\t\tfor j := k + 1; j < n; j++ {\n\t\t\tif (k < nct) && (s[k] != 0.0) {\n\n\t\t\t\t// Apply the transformation.\n\n\t\t\t\tt := float64(0)\n\t\t\t\tfor i := k; i < m; i++ {\n\t\t\t\t\tt += A[i][k] * A[i][j]\n\t\t\t\t}\n\t\t\t\tt = -t / A[k][k]\n\t\t\t\tfor i := k; i < m; i++ {\n\t\t\t\t\tA[i][j] += t * A[i][k]\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Place the k-th row of A into e for the\n\t\t\t// subsequent calculation of the row transformation.\n\n\t\t\te[j] = A[k][j]\n\t\t}\n\t\tif wantu && (k < nct) {\n\n\t\t\t// Place the transformation in U for subsequent back\n\t\t\t// multiplication.\n\n\t\t\tfor i := k; i < m; i++ {\n\t\t\t\tU[i][k] = A[i][k]\n\t\t\t}\n\t\t}\n\t\tif k < nrt {\n\n\t\t\t// Compute the k-th row transformation and place the\n\t\t\t// k-th super-diagonal in e[k].\n\t\t\t// Compute 2-norm without under/overflow.\n\t\t\te[k] = 0\n\t\t\tfor i := k + 1; i < n; i++ {\n\t\t\t\te[k] = math.Hypot(e[k], e[i])\n\t\t\t}\n\t\t\tif e[k] != 0.0 {\n\t\t\t\tif e[k+1] < 0.0 {\n\t\t\t\t\te[k] = -e[k]\n\t\t\t\t}\n\t\t\t\tfor i := k + 1; i < n; i++ {\n\t\t\t\t\te[i] /= e[k]\n\t\t\t\t}\n\t\t\t\te[k+1] += 1.0\n\t\t\t}\n\t\t\te[k] = -e[k]\n\t\t\tif (k+1 < m) && (e[k] != 0.0) {\n\n\t\t\t\t// Apply the transformation.\n\n\t\t\t\tfor i := k + 1; i < m; i++ {\n\t\t\t\t\twork[i] = 0.0\n\t\t\t\t}\n\t\t\t\tfor j := k + 1; j < n; j++ {\n\t\t\t\t\tfor i := k + 1; i < m; i++ {\n\t\t\t\t\t\twork[i] += e[j] * A[i][j]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor j := k + 1; j < n; j++ {\n\t\t\t\t\tt := -e[j] / e[k+1]\n\t\t\t\t\tfor i := k + 1; i < m; i++ {\n\t\t\t\t\t\tA[i][j] += t * work[i]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif wantv {\n\n\t\t\t\t// Place the transformation in V for subsequent\n\t\t\t\t// back multiplication.\n\n\t\t\t\tfor i := k + 1; i < n; i++ {\n\t\t\t\t\tV[i][k] = e[i]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set up the final bidiagonal matrix or order p.\n\n\tp := minInt(n, m+1)\n\tif nct < n {\n\t\ts[nct] = A[nct][nct]\n\t}\n\tif m < p {\n\t\ts[p-1] = 0.0\n\t}\n\tif nrt+1 < p {\n\t\te[nrt] = A[nrt][p-1]\n\t}\n\te[p-1] = 0.0\n\n\t// If required, generate U.\n\n\tif wantu {\n\t\tfor j := nct; j < nu; j++ {\n\t\t\tfor i := 0; i < m; i++ {\n\t\t\t\tU[i][j] = 0.0\n\t\t\t}\n\t\t\tU[j][j] = 1.0\n\t\t}\n\t\tfor k := nct - 1; k >= 0; k-- {\n\t\t\tif s[k] != 0.0 {\n\t\t\t\tfor j := k + 1; j < nu; j++ {\n\t\t\t\t\tt := float64(0)\n\t\t\t\t\tfor i := k; i < m; i++ {\n\t\t\t\t\t\tt += U[i][k] * U[i][j]\n\t\t\t\t\t}\n\t\t\t\t\tt = -t / U[k][k]\n\t\t\t\t\tfor i := k; i < m; i++ {\n\t\t\t\t\t\tU[i][j] += t * U[i][k]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor i := k; i < m; i++ {\n\t\t\t\t\tU[i][k] = -U[i][k]\n\t\t\t\t}\n\t\t\t\tU[k][k] = 1.0 + U[k][k]\n\t\t\t\tfor i := 0; i < k-1; i++ {\n\t\t\t\t\tU[i][k] = 0.0\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor i := 0; i < m; i++ {\n\t\t\t\t\tU[i][k] = 0.0\n\t\t\t\t}\n\t\t\t\tU[k][k] = 1.0\n\t\t\t}\n\t\t}\n\t}\n\n\t// If required, generate V.\n\n\tif wantv {\n\t\tfor k := n - 1; k >= 0; k-- {\n\t\t\tif (k < nrt) && (e[k] != 0.0) {\n\t\t\t\tfor j := k + 1; j < nu; j++ {\n\t\t\t\t\tt := float64(0)\n\t\t\t\t\tfor i := k + 1; i < n; i++ {\n\t\t\t\t\t\tt += V[i][k] * V[i][j]\n\t\t\t\t\t}\n\t\t\t\t\tt = -t / V[k+1][k]\n\t\t\t\t\tfor i := k + 1; i < n; i++ {\n\t\t\t\t\t\tV[i][j] += t * V[i][k]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor i := 0; i < n; i++ {\n\t\t\t\tV[i][k] = 0.0\n\t\t\t}\n\t\t\tV[k][k] = 1.0\n\t\t}\n\t}\n\n\t// Main iteration loop for the singular values.\n\n\tpp := p - 1\n\titer := 0\n\teps := math.Pow(2.0, -52.0)\n\ttiny := math.Pow(2.0, -966.0)\n\tfor p > 0 {\n\t\tvar k, kase int\n\n\t\t// Here is where a test for too many iterations would go.\n\n\t\t// This section of the program inspects for\n\t\t// negligible elements in the s and e arrays.  On\n\t\t// completion the variables kase and k are set as follows.\n\n\t\t// kase = 1     if s(p) and e[k-1] are negligible and k<p\n\t\t// kase = 2     if s(k) is negligible and k<p\n\t\t// kase = 3     if e[k-1] is negligible, k<p, and\n\t\t//              s(k), ..., s(p) are not negligible (qr step).\n\t\t// kase = 4     if e(p-1) is negligible (convergence).\n\n\t\tfor k = p - 2; k >= -1; k-- {\n\t\t\tif k == -1 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif math.Abs(e[k]) <=\n\t\t\t\ttiny+eps*(math.Abs(s[k])+math.Abs(s[k+1])) {\n\t\t\t\te[k] = 0.0\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif k == p-2 {\n\t\t\tkase = 4\n\t\t} else {\n\t\t\tvar ks int\n\t\t\tfor ks = p - 1; ks >= k; ks-- {\n\t\t\t\tif ks == k {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tt := float64(0)\n\t\t\t\tif ks != p {\n\t\t\t\t\tt = math.Abs(e[ks])\n\t\t\t\t}\n\t\t\t\tif ks != k+1 {\n\t\t\t\t\tt += math.Abs(e[ks-1])\n\t\t\t\t}\n\t\t\t\t//double t = (ks != p ? Math.abs(e[ks]) : 0.) +\n\t\t\t\t//           (ks != k+1 ? Math.abs(e[ks-1]) : 0.);\n\t\t\t\tif math.Abs(s[ks]) <= tiny+eps*t {\n\t\t\t\t\ts[ks] = 0.0\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ks == k {\n\t\t\t\tkase = 3\n\t\t\t} else if ks == p-1 {\n\t\t\t\tkase = 1\n\t\t\t} else {\n\t\t\t\tkase = 2\n\t\t\t\tk = ks\n\t\t\t}\n\t\t}\n\t\tk++\n\n\t\t// Perform the task indicated by kase.\n\t\t//fmt.Printf(\"kase = %d\\n\", kase);\n\t\tswitch kase {\n\n\t\t// Deflate negligible s(p).\n\n\t\tcase 1:\n\t\t\t{\n\t\t\t\tf := e[p-2]\n\t\t\t\te[p-2] = 0.0\n\t\t\t\tfor j := p - 2; j >= k; j-- {\n\t\t\t\t\tt := math.Hypot(s[j], f)\n\t\t\t\t\tcs := s[j] / t\n\t\t\t\t\tsn := f / t\n\t\t\t\t\ts[j] = t\n\t\t\t\t\tif j != k {\n\t\t\t\t\t\tf = -sn * e[j-1]\n\t\t\t\t\t\te[j-1] = cs * e[j-1]\n\t\t\t\t\t}\n\t\t\t\t\tif wantv {\n\t\t\t\t\t\tfor i := 0; i < n; i++ {\n\t\t\t\t\t\t\tt = cs*V[i][j] + sn*V[i][p-1]\n\t\t\t\t\t\t\tV[i][p-1] = -sn*V[i][j] + cs*V[i][p-1]\n\t\t\t\t\t\t\tV[i][j] = t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\n\t\t// Split at negligible s(k).\n\n\t\tcase 2:\n\t\t\t{\n\t\t\t\tf := e[k-1]\n\t\t\t\te[k-1] = 0.0\n\t\t\t\tfor j := k; j < p; j++ {\n\t\t\t\t\tt := math.Hypot(s[j], f)\n\t\t\t\t\tcs := s[j] / t\n\t\t\t\t\tsn := f / t\n\t\t\t\t\ts[j] = t\n\t\t\t\t\tf = -sn * e[j]\n\t\t\t\t\te[j] = cs * e[j]\n\t\t\t\t\tif wantu {\n\t\t\t\t\t\tfor i := 0; i < m; i++ {\n\t\t\t\t\t\t\tt = cs*U[i][j] + sn*U[i][k-1]\n\t\t\t\t\t\t\tU[i][k-1] = -sn*U[i][j] + cs*U[i][k-1]\n\t\t\t\t\t\t\tU[i][j] = t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\n\t\t// Perform one qr step.\n\n\t\tcase 3:\n\t\t\t{\n\n\t\t\t\t// Calculate the shift.\n\n\t\t\t\tscale := max(max(max(max(\n\t\t\t\t\tmath.Abs(s[p-1]), math.Abs(s[p-2])),\n\t\t\t\t\tmath.Abs(e[p-2])),\n\t\t\t\t\tmath.Abs(s[k])),\n\t\t\t\t\tmath.Abs(e[k]))\n\t\t\t\tsp := s[p-1] / scale\n\t\t\t\tspm1 := s[p-2] / scale\n\t\t\t\tepm1 := e[p-2] / scale\n\t\t\t\tsk := s[k] / scale\n\t\t\t\tek := e[k] / scale\n\t\t\t\tb := ((spm1+sp)*(spm1-sp) + epm1*epm1) / 2.0\n\t\t\t\tc := (sp * epm1) * (sp * epm1)\n\t\t\t\tshift := float64(0)\n\t\t\t\tif (b != 0.0) || (c != 0.0) {\n\t\t\t\t\tshift = math.Sqrt(b*b + c)\n\t\t\t\t\tif b < 0.0 {\n\t\t\t\t\t\tshift = -shift\n\t\t\t\t\t}\n\t\t\t\t\tshift = c / (b + shift)\n\t\t\t\t}\n\t\t\t\tf := (sk+sp)*(sk-sp) + shift\n\t\t\t\tg := sk * ek\n\n\t\t\t\t// Chase zeros.\n\n\t\t\t\tfor j := k; j < p-1; j++ {\n\t\t\t\t\tt := math.Hypot(f, g)\n\t\t\t\t\tcs := f / t\n\t\t\t\t\tsn := g / t\n\t\t\t\t\tif j != k {\n\t\t\t\t\t\te[j-1] = t\n\t\t\t\t\t}\n\t\t\t\t\tf = cs*s[j] + sn*e[j]\n\t\t\t\t\te[j] = cs*e[j] - sn*s[j]\n\t\t\t\t\tg = sn * s[j+1]\n\t\t\t\t\ts[j+1] = cs * s[j+1]\n\t\t\t\t\tif wantv {\n\t\t\t\t\t\tfor i := 0; i < n; i++ {\n\t\t\t\t\t\t\tt = cs*V[i][j] + sn*V[i][j+1]\n\t\t\t\t\t\t\tV[i][j+1] = -sn*V[i][j] + cs*V[i][j+1]\n\t\t\t\t\t\t\tV[i][j] = t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tt = math.Hypot(f, g)\n\t\t\t\t\tcs = f / t\n\t\t\t\t\tsn = g / t\n\t\t\t\t\ts[j] = t\n\t\t\t\t\tf = cs*e[j] + sn*s[j+1]\n\t\t\t\t\ts[j+1] = -sn*e[j] + cs*s[j+1]\n\t\t\t\t\tg = sn * e[j+1]\n\t\t\t\t\te[j+1] = cs * e[j+1]\n\t\t\t\t\tif wantu && (j < m-1) {\n\t\t\t\t\t\tfor i := 0; i < m; i++ {\n\t\t\t\t\t\t\tt = cs*U[i][j] + sn*U[i][j+1]\n\t\t\t\t\t\t\tU[i][j+1] = -sn*U[i][j] + cs*U[i][j+1]\n\t\t\t\t\t\t\tU[i][j] = t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\te[p-2] = f\n\t\t\t\titer = iter + 1\n\t\t\t}\n\t\t\tbreak\n\n\t\t// Convergence.\n\n\t\tcase 4:\n\t\t\t{\n\n\t\t\t\t// Make the singular values positive.\n\n\t\t\t\tif s[k] <= 0.0 {\n\t\t\t\t\tif s[k] < 0.0 {\n\t\t\t\t\t\ts[k] = -s[k]\n\t\t\t\t\t} else {\n\t\t\t\t\t\ts[k] = 0\n\t\t\t\t\t}\n\t\t\t\t\tif wantv {\n\t\t\t\t\t\tfor i := 0; i <= pp; i++ {\n\t\t\t\t\t\t\tV[i][k] = -V[i][k]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Order the singular values.\n\n\t\t\t\tfor k < pp {\n\t\t\t\t\tif s[k] >= s[k+1] {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tt := s[k]\n\t\t\t\t\ts[k] = s[k+1]\n\t\t\t\t\ts[k+1] = t\n\t\t\t\t\tif wantv && (k < n-1) {\n\t\t\t\t\t\tfor i := 0; i < n; i++ {\n\t\t\t\t\t\t\tt = V[i][k+1]\n\t\t\t\t\t\t\tV[i][k+1] = V[i][k]\n\t\t\t\t\t\t\tV[i][k] = t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif wantu && (k < m-1) {\n\t\t\t\t\t\tfor i := 0; i < m; i++ {\n\t\t\t\t\t\t\tt = U[i][k+1]\n\t\t\t\t\t\t\tU[i][k+1] = U[i][k]\n\t\t\t\t\t\t\tU[i][k] = t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tk++\n\t\t\t\t}\n\t\t\t\titer = 0\n\t\t\t\tp--\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\t//fmt.Printf(\"testing\\n%v\\n%v\\n%v\\n%v\\n%v\\n\", A, V, U, e, s);\n\n\ttheU = MakeDenseMatrixStacked(U).GetMatrix(0, 0, m, minInt(m+1, n))\n\tΣ = Diagonal(s)\n\ttheV = MakeDenseMatrixStacked(V)\n\n\treturn\n}\n"
  },
  {
    "path": "dense_test.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"testing\"\n\t\"time\"\n)\n\nconst ε = 0.000001\nconst verbose = false\nconst speedTest = true\n\n/* TEST: arithmetic.go */\n\nfunc TestEquals(t *testing.T) {\n\tif !Equals(Ones(5, 3), Ones(5, 3)) {\n\t\tt.Fail()\n\t}\n\tif Equals(Ones(3, 5), Ones(5, 3)) {\n\t\tt.Fail()\n\t}\n\tif Equals(Zeros(3, 3), Ones(3, 3)) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestApproximates(t *testing.T) {\n\tA := Numbers(3, 3, 6)\n\tB := Numbers(3, 3, .1)\n\tC := Numbers(3, 3, .6)\n\tD, err := A.ElementMult(B)\n\tif !(err == nil) && !ApproxEquals(D, C, ε) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestAdd(t *testing.T) {\n\tA := Normals(3, 3)\n\tB := Normals(3, 3)\n\tC := Sum(A, B)\n\tif C.Nil() {\n\t\tt.Fail()\n\t}\n\tfor i := 0; i < C.Rows(); i++ {\n\t\tfor j := 0; j < C.Cols(); j++ {\n\t\t\tif A.Get(i, j)+B.Get(i, j) != C.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestSubtract(t *testing.T) {\n\tA := Normals(3, 3)\n\tB := Normals(3, 3)\n\tC := Difference(A, B)\n\tif C.Nil() {\n\t\tt.Fail()\n\t}\n\tfor i := 0; i < C.Rows(); i++ {\n\t\tfor j := 0; j < C.Cols(); j++ {\n\t\t\tif A.Get(i, j)-B.Get(i, j) != C.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestProduct(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tB := MakeDenseMatrix([]float64{1, 7, -4, 4,\n\t\t3, -2, -6, 1,\n\t\t-12, 8, 1, 20,\n\t\t0, 0, -10, 3,\n\t},\n\t\t4, 4)\n\n\tC, err := A.Times(B)\n\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\n\tvar Ctrue Matrix\n\tCtrue = MakeDenseMatrix([]float64{48, 14, -56, -46,\n\t\t66, -21, -10, -108,\n\t\t-240, 68, 101, 356,\n\t\t114, -122, -56, -203,\n\t},\n\t\t4, 4)\n\n\tif !Equals(C, Ctrue) {\n\t\tt.Fail()\n\t}\n\n\tP := MakePivotMatrix([]int{1, 3, 0, 2}, -1)\n\tC, err = P.Times(A)\n\n\tCtrue, err = P.DenseMatrix().Times(A)\n\tif !Equals(C, Ctrue) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestParallelProduct(t *testing.T) {\n\n\tw := 100000\n\th := 40\n\n\tif !verbose {\n\t\tw = 100\n\t\th = 4\n\t}\n\n\trand.Seed(time.Now().UnixNano())\n\tA := Normals(h, w)\n\tB := Normals(w, h)\n\n\tvar C *DenseMatrix\n\tvar start, end int64\n\n\tstart = time.Now().UnixNano()\n\tCtrue, err := A.Times(B)\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\tend = time.Now().UnixNano()\n\tif verbose {\n\t\tfmt.Printf(\"%fs for synchronous\\n\", float64(end-start)/1000000000)\n\t}\n\n\tstart = time.Now().UnixNano()\n\tC = ParallelProduct(A, B)\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\tend = time.Now().UnixNano()\n\tif verbose {\n\t\tfmt.Printf(\"%fs for parallel\\n\", float64(end-start)/1000000000)\n\t}\n\n\tif !Equals(C, Ctrue) {\n\t\tt.Fail()\n\t}\n}\n\nvar MaxProcs int = 1\n\nfunc TestTimesDenseProcs(t *testing.T) {\n\tA := Normals(10, 10)\n\tB := Normals(10, 10)\n\n\told := MaxProcs\n\tMaxProcs = 1\n\tC, _ := A.TimesDense(B)\n\tMaxProcs = 2\n\tCp, _ := A.TimesDense(B)\n\tif !Equals(C, Cp) {\n\t\tt.Fail()\n\t}\n\tMaxProcs = old\n}\n\nfunc TestElementMult(t *testing.T) {\n\n\tA := MakeDenseMatrix([]float64{6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tT := MakeDenseMatrix([]float64{0.1, 0.1, 0.1, 0.1,\n\t\t10, 10, 10, 10,\n\t\t100, 100, 100, 100,\n\t\t1000, 1000, 1000, 1000,\n\t},\n\t\t4, 4)\n\tC, err := A.ElementMult(T)\n\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\n\tCtrue := MakeDenseMatrix([]float64{0.6, -0.2, -0.4, 0.4,\n\t\t30, -30, -60, 10,\n\t\t-1200, 800, 2100, -800,\n\t\t-6000, 0, -10000, 7000,\n\t},\n\t\t4, 4)\n\n\tif !ApproxEquals(C, Ctrue, ε) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestScale(t *testing.T) {\n\tA := Normals(3, 3)\n\tf := float64(5.3)\n\tB := A.Copy()\n\tB.Scale(f)\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif A.Get(i, j)*f != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestScaleMatrix(t *testing.T) {\n\tA := Normals(4, 4)\n\tB := Normals(4, 4)\n\tC := A.Copy()\n\tC.ScaleMatrix(B)\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif A.Get(i, j)*B.Get(i, j) != C.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\n/* TEST: basic.go */\n\nfunc TestSymmetric(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{\n\t\t6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tif A.Symmetric() {\n\t\tt.Fail()\n\t}\n\tB := MakeDenseMatrix([]float64{\n\t\t6, 3, -12, -6,\n\t\t3, -3, 8, 0,\n\t\t-12, 8, 21, -10,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tif !B.Symmetric() {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestInverse(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tAinv, err := A.Inverse()\n\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\n\tAAinv, err := A.Times(Ainv)\n\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\n\tif !ApproxEquals(Eye(A.Rows()), AAinv, ε) {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"A\\n%v\\n\\nAinv\\n%v\\n\\nA*Ainv\\n%v\\n\", A, Ainv, AAinv)\n\t\t}\n\t\tt.Fail()\n\t}\n}\n\nfunc TestDet(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{4, -2, 5,\n\t\t-1, -7, 10,\n\t\t0, 1, -3,\n\t},\n\t\t3, 3)\n\n\tif A.Det() != 45 {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"A\\n%v\\n\\nA.Det()\\n%v\\n\\n\", A, A.Det())\n\t\t}\n\t\tt.Fail()\n\t}\n}\n\nfunc TestTrace(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{4, -2, 5,\n\t\t-1, -7, 10,\n\t\t0, 1, -3,\n\t},\n\t\t3, 3)\n\n\tif A.Trace() != 4-7-3 {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"A\\n%v\\n\\nA.Trace()\\n%v\\n\\n\", A, A.Trace())\n\t\t}\n\t\tt.Fail()\n\t}\n}\n\nfunc TestTranspose(t *testing.T) {\n\tA := Normals(4, 4)\n\tB := A.Transpose()\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tif A.Get(i, j) != B.Get(j, i) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestSolve(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tb := MakeDenseMatrix([]float64{1, 1, 1, 1}, 4, 1)\n\tx, err := A.Solve(b)\n\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\n\txtrue := MakeDenseMatrix([]float64{-0.906250, -3.393750, 1.275000, 1.187500}, 4, 1)\n\n\tif !Equals(x, xtrue) {\n\t\tt.Fail()\n\t}\n}\n\n/* TEST: decomp.go */\n\nfunc TestCholesky(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{1, 0.2, 0,\n\t\t0.2, 1, 0.5,\n\t\t0, 0.5, 1,\n\t},\n\t\t3, 3)\n\tB, err := A.Cholesky()\n\tif !(err == nil) {\n\t\tt.Fail()\n\t}\n\tif !ApproxEquals(A, Product(B, B.Transpose()), ε) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestLU(t *testing.T) {\n\n\tA := MakeDenseMatrix([]float64{6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tL, U, P := A.LU()\n\n\tLU, err := L.Times(U)\n\tPLU, err := P.Times(LU)\n\n\tif !(err == nil) {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"TestLU: %v\\n\", err)\n\t\t}\n\t\tt.Fail()\n\t}\n\n\tif !Equals(A, PLU) {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"TestLU:\\n%v\\n!=\\n%v\\n\", A, PLU)\n\t\t}\n\t\tt.Fail()\n\t}\n\n\tA = MakeDenseMatrix([]float64{6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tLtrue, Utrue, Ptrue := A.LU()\n\n\tP = A.LUInPlace()\n\tL = A.L()\n\tU = A.U()\n\n\tfor i := 0; i < L.Rows(); i++ {\n\t\tL.Set(i, i, 1)\n\t}\n\n\tPL := Product(P, L)\n\tPLU2 := Product(PL, U)\n\tPLtrue := Product(Ptrue, Ltrue)\n\tPLUtrue := Product(PLtrue, Utrue)\n\n\tif !Equals(PLU2, PLUtrue) {\n\t\tt.Fail()\n\t}\n\n}\n\nfunc TestQR(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tQ, R := A.QR()\n\n\tQtrue := MakeDenseMatrix([]float64{-0.4, 0.278610, 0.543792, -0.683130,\n\t\t-0.2, -0.358213, -0.699161, -0.585540,\n\t\t0.8, 0.437816, -0.126237, -0.390360,\n\t\t0.4, -0.776129, 0.446686, -0.195180,\n\t},\n\t\t4, 4)\n\n\tRtrue := MakeDenseMatrix([]float64{-15, 7.8, 15.6, -5.4,\n\t\t0, 4.019950, 17.990272, -8.179206,\n\t\t0, 0, -5.098049, 5.612709,\n\t\t0, 0, 0, -1.561440,\n\t},\n\t\t4, 4)\n\n\tQR := Product(Q, R)\n\n\tif !ApproxEquals(Q, Qtrue, ε) ||\n\t\t!ApproxEquals(R, Rtrue, ε) ||\n\t\t!ApproxEquals(A, QR, ε) {\n\t\tt.Fail()\n\t}\n}\n\n/* TEST: eigen.go */\n\nfunc TestEigen(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{\n\t\t2, 1,\n\t\t1, 2,\n\t},\n\t\t2, 2)\n\tV, D, _ := A.Eigen()\n\n\tVinv, _ := V.Inverse()\n\tAguess := Product(Product(V, D), Vinv)\n\n\tif !ApproxEquals(A, Aguess, ε) {\n\t\tt.Fail()\n\t}\n\n\tB := MakeDenseMatrix([]float64{\n\t\t6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\n\tV, D, _ = B.Eigen()\n\n\tVinv, _ = V.Inverse()\n\n\tif !ApproxEquals(B, Product(Product(V, D), Vinv), ε) {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"B =\\n%v\\nV=\\n%v\\nD=\\n%v\\n\", B, V, D)\n\t\t}\n\t\tt.Fail()\n\t}\n\n\tBm, _ := B.Times(B.Transpose())\n\tB = Bm.DenseMatrix()\n\tV, D, _ = B.Eigen()\n\tVinv, _ = V.Inverse()\n\n\tif !ApproxEquals(B, Product(Product(V, D), Vinv), ε) {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"B =\\n%v\\nV=\\n%v\\nD=\\n%v\\n\", B, V, D)\n\t\t}\n\t\tt.Fail()\n\t}\n}\n\nfunc TestSVD(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{\n\t\t6, -2, -4, 4,\n\t\t3, -3, -6, 1,\n\t\t-12, 8, 21, -8,\n\t\t-6, 0, -10, 7,\n\t},\n\t\t4, 4)\n\tU, Σ, V, _ := A.SVD()\n\tArecomp := Product(Product(U, Σ), V.Transpose())\n\tif !ApproxEquals(A, Arecomp, ε) {\n\t\tt.Fail()\n\t}\n\tA = Normals(5, 3)\n\tU, Σ, V, _ = A.SVD()\n\tArecomp = Product(Product(U, Σ), V.Transpose())\n\tif !ApproxEquals(A, Arecomp, ε) {\n\t\tt.Fail()\n\t}\n}\n\n/* TEST: matrix.go */\n\nfunc TestGetMatrix(t *testing.T) {\n\tA := Zeros(4, 4)\n\tB := A.GetMatrix(1, 1, 2, 2)\n\tB.Set(0, 1, 1)\n\tif A.Get(1, 2) != 1 {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestL(t *testing.T) {\n\tA := Normals(4, 4)\n\tL := A.L()\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif j > i && L.Get(i, j) != 0 {\n\t\t\t\tt.Fail()\n\t\t\t} else if j <= i && L.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tA = Normals(4, 2)\n\tL = A.L()\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif j > i && L.Get(i, j) != 0 {\n\t\t\t\tt.Fail()\n\t\t\t} else if j <= i && L.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tA = Normals(2, 4)\n\tL = A.L()\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif j > i && L.Get(i, j) != 0 {\n\t\t\t\tt.Fail()\n\t\t\t} else if j <= i && L.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestU(t *testing.T) {\n\tA := Normals(4, 4)\n\tU := A.U()\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif j < i && U.Get(i, j) != 0 {\n\t\t\t\tt.Fail()\n\t\t\t} else if j >= i && U.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tA = Normals(2, 4)\n\tU = A.U()\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif j < i && U.Get(i, j) != 0 {\n\t\t\t\tt.Fail()\n\t\t\t} else if j >= i && U.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tA = Normals(4, 2)\n\tU = A.U()\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif j < i && U.Get(i, j) != 0 {\n\t\t\t\tt.Fail()\n\t\t\t} else if j >= i && U.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestAugment(t *testing.T) {\n\tvar A, B, C *DenseMatrix\n\tA = Normals(4, 4)\n\tB = Normals(4, 4)\n\tC, _ = A.Augment(B)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i, j+A.Cols()) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\n\tA = Normals(2, 2)\n\tB = Normals(4, 4)\n\tC, err := A.Augment(B)\n\tif err == nil {\n\t\tt.Fail()\n\t}\n\n\tA = Normals(4, 4)\n\tB = Normals(4, 2)\n\tC, _ = A.Augment(B)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i, j+A.Cols()) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestStack(t *testing.T) {\n\n\tvar A, B, C *DenseMatrix\n\tA = Normals(4, 4)\n\tB = Normals(4, 4)\n\tC, _ = A.Stack(B)\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i+A.Rows(), j) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\n\tA = Normals(4, 4)\n\tB = Normals(4, 2)\n\tC, err := A.Stack(B)\n\tif err == nil {\n\t\tt.Fail()\n\t}\n\n\tA = Normals(2, 4)\n\tB = Normals(4, 4)\n\tC, err = A.Stack(B)\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i+A.Rows(), j) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestZeros(t *testing.T) {\n\tA := Zeros(4, 5)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif A.Get(i, j) != 0 {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestNumbers(t *testing.T) {\n\tn := float64(1.0)\n\tA := Numbers(3, 3, n)\n\t//\tfmt.Printf(\"%v\\n\\n\\n\",A.String());\n\n\tAtrue := MakeDenseMatrix([]float64{n, n, n,\n\t\tn, n, n,\n\t\tn, n, n,\n\t},\n\t\t3, 3)\n\tif !Equals(A, Atrue) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestOnes(t *testing.T) {\n\n\tA := Ones(4, 5)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif A.Get(i, j) != 1 {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestEye(t *testing.T) {\n\n\tA := Eye(4)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif (i != j && A.Get(i, j) != 0) || (i == j && A.Get(i, j) != 1) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestNormals(t *testing.T) {\n\t//test that it's filled with random data?\n\tA := Normals(3, 4)\n\tif A.Rows() != 3 || A.Cols() != 4 {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestKronecker(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{0, 1, 2, 3}, 2, 2)\n\tB := MakeDenseMatrix([]float64{5, 6, 7, 8, 9, 10}, 2, 3)\n\tC := Kronecker(A, B)\n\tCp := MakeDenseMatrix([]float64{0, 0, 0, 5, 6, 7,\n\t\t0, 0, 0, 8, 9, 10,\n\t\t10, 12, 14, 15, 18, 21,\n\t\t16, 18, 20, 24, 27, 30}, 4, 6)\n\tif !Equals(C, Cp) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestVectorize(t *testing.T) {\n\tA := MakeDenseMatrix([]float64{0, 1, 2, 3, 4, 5}, 2, 3)\n\tV := Vectorize(A)\n\tVp := MakeDenseMatrix([]float64{0, 3, 1, 4, 2, 5}, 6, 1)\n\tif !Equals(V, Vp) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestSubmatrix(t *testing.T) {\n\tEye(3).GetMatrix(1, 1, 2, 2).GetColVector(0)\n}\n\n/* TEST: util.go */\n\n/*\nfunc TestMultipleProduct(t *testing.T) {\n\tA := Ones(3, 1)\n\tB := Ones(1, 3)\n\tC := MultipleProduct(A, B, A)\n\tD := Product(A, B)\n\tE := Product(D, A)\n\n\tif !Equals(E, C) {\n\t\tt.Fail()\n\t}\n}\n*/\n"
  },
  {
    "path": "densebench_test.go",
    "content": "package matrix\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc BenchmarkTransposeTimes(b *testing.B) {\n\tfmt.Println(\"benchmark\")\n\tfor s := 25; s <= 100; s += 25 {\n\t\tw, h := s/2, s*2\n\n\t\tA := Normals(h, w)\n\t\tB := Normals(w, h)\n\n\t\tvar times [2]float64\n\n\t\tconst Count = 500\n\n\t\tMaxProcs = 1\n\t\tWhichSyncMethod = 1\n\t\tstart := time.Now()\n\t\tfor i := 0; i < Count; i++ {\n\t\t\tA.Times(B)\n\t\t}\n\t\tend := time.Now()\n\t\tduration := end.Sub(start)\n\t\ttimes[0] = float64(duration) / 1e9\n\n\t\tWhichSyncMethod = 2\n\t\tstart = time.Now()\n\t\tfor i := 0; i < Count; i++ {\n\t\t\tA.Times(B)\n\t\t}\n\t\tend = time.Now()\n\t\tduration = end.Sub(start)\n\t\ttimes[1] = float64(duration) / 1e9\n\t\tfmt.Printf(\"%d: %.2f\\n\", h, times[1]/times[0])\n\t}\n}\n"
  },
  {
    "path": "error.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"fmt\"\n\nconst (\n\t//The matrix returned was nil.\n\terrorNilMatrix = iota + 1\n\t//The dimensions of the inputs do not make sense for this operation.\n\terrorDimensionMismatch\n\t//The indices provided are out of bounds.\n\terrorIllegalIndex\n\t//The matrix provided has a singularity.\n\texceptionSingular\n\t//The matrix provided is not positive semi-definite.\n\texceptionNotSPD\n)\n\ntype error_ int\n\nfunc (e error_) Error() string {\n\tswitch e {\n\tcase errorNilMatrix:\n\t\treturn \"Matrix is nil\"\n\tcase errorDimensionMismatch:\n\t\treturn \"Input dimensions do not match\"\n\tcase errorIllegalIndex:\n\t\treturn \"Index out of bounds\"\n\tcase exceptionSingular:\n\t\treturn \"Matrix is singular\"\n\tcase exceptionNotSPD:\n\t\treturn \"Matrix is not positive semidefinite\"\n\t}\n\treturn fmt.Sprintf(\"Unknown error code %d\", e)\n}\nfunc (e error_) String() string {\n\treturn e.Error()\n}\n\nvar (\n\t//The matrix returned was nil.\n\tErrorNilMatrix error_ = error_(errorNilMatrix)\n\t//The dimensions of the inputs do not make sense for this operation.\n\tErrorDimensionMismatch error_ = error_(errorDimensionMismatch)\n\t//The indices provided are out of bounds.\n\tErrorIllegalIndex error_ = error_(errorIllegalIndex)\n\t//The matrix provided has a singularity.\n\tExceptionSingular error_ = error_(exceptionSingular)\n\t//The matrix provided is not positive semi-definite.\n\tExceptionNotSPD error_ = error_(exceptionNotSPD)\n)\n"
  },
  {
    "path": "matrix.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//target:gomatrix.googlecode.com/hg/matrix\n\n//Linear algebra.\npackage matrix\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n//The MatrixRO interface defines matrix operations that do not change the\n//underlying data, such as information requests or the creation of transforms\n/*\nRead-only matrix types (at the moment, PivotMatrix).\n*/\ntype MatrixRO interface {\n\t//Returns true if the underlying object is nil.\n\tNil() bool\n\n\t//The number of rows in this matrix.\n\tRows() int\n\t//The number of columns in this matrix.\n\tCols() int\n\n\t//The number of elements in this matrix.\n\tNumElements() int\n\t//The size pair, (Rows(), Cols())\n\tGetSize() (int, int)\n\n\t//The element in the ith row and jth column.\n\tGet(i, j int) float64\n\n\tPlus(MatrixRO) (Matrix, error)\n\tMinus(MatrixRO) (Matrix, error)\n\tTimes(MatrixRO) (Matrix, error)\n\n\t//The determinant of this matrix.\n\tDet() float64\n\t//The trace of this matrix.\n\tTrace() float64\n\n\t//A pretty-print string.\n\tString() string\n\n\tDenseMatrix() *DenseMatrix\n\tSparseMatrix() *SparseMatrix\n}\n\n/*\nA mutable matrix.\n*/\ntype Matrix interface {\n\tMatrixRO\n\n\t//Set the element at the ith row and jth column to v.\n\tSet(i int, j int, v float64)\n\n\tAdd(MatrixRO) error\n\tSubtract(MatrixRO) error\n\tScale(float64)\n}\n\ntype matrix struct {\n\trows int\n\tcols int\n}\n\nfunc (A *matrix) Nil() bool { return A == nil }\n\nfunc (A *matrix) Rows() int { return A.rows }\n\nfunc (A *matrix) Cols() int { return A.cols }\n\nfunc (A *matrix) NumElements() int { return A.rows * A.cols }\n\nfunc (A *matrix) GetSize() (rows, cols int) {\n\trows = A.rows\n\tcols = A.cols\n\treturn\n}\n\n/*\n\tTake a matlab-style matrix representation\n\n\teg [a b c; d e f]\n*/\nfunc ParseMatlab(txt string) (A *DenseMatrix, err error) {\n\tvar arrays [][]float64\n\n\tspaceSep := strings.Fields(txt)\n\n\ttok := func() (t string, eos bool) {\n\t\tdefer func() {\n\t\t\tfor len(spaceSep) != 0 && len(spaceSep[0]) == 0 {\n\t\t\t\tspaceSep = spaceSep[1:]\n\t\t\t}\n\t\t}()\n\n\t\tisNotNumber := func(c byte) bool {\n\t\t\treturn c != '[' || c != ']' || c == ';'\n\t\t}\n\n\t\tif len(spaceSep) == 0 {\n\t\t\teos = true\n\t\t\treturn\n\t\t}\n\n\t\ttop := spaceSep[0]\n\n\t\tvar lof int\n\t\tfor ; lof < len(top) && !isNotNumber(top[lof]); lof++ {\n\t\t}\n\n\t\tif lof != 0 {\n\t\t\tt = top[:lof]\n\t\t\tspaceSep[0] = top[lof:]\n\t\t\treturn\n\t\t} else {\n\t\t\tt = top[:1]\n\t\t\tspaceSep[0] = top[1:]\n\t\t\treturn\n\t\t}\n\n\t\tpanic(\"unreachable\")\n\t}\n\n\tstack := func(row []float64) (err error) {\n\t\tif len(arrays) == 0 {\n\t\t\tarrays = [][]float64{row}\n\t\t\treturn\n\t\t}\n\t\tif len(arrays[0]) != len(row) {\n\t\t\terr = errors.New(\"misaligned row\")\n\t\t}\n\t\tarrays = append(arrays, row)\n\t\treturn\n\t}\n\n\tvar row []float64\n\nloop:\n\tfor {\n\t\tt, eos := tok()\n\t\tif eos {\n\t\t\tbreak loop\n\t\t}\n\t\tswitch t {\n\t\tcase \"[\":\n\t\tcase \";\":\n\t\t\terr = stack(row)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\trow = []float64{}\n\t\tcase \"]\":\n\t\t\terr = stack(row)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tbreak loop\n\t\tdefault:\n\t\t\tvar v float64\n\t\t\tv, err = strconv.ParseFloat(t, 64)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\trow = append(row, v)\n\t\t}\n\t}\n\tA = MakeDenseMatrixStacked(arrays)\n\treturn\n}\n\nfunc String(A MatrixRO) string {\n\tcondense := func(vs string) string {\n\t\tif strings.Index(vs, \".\") != -1 {\n\t\t\tfor vs[len(vs)-1] == '0' {\n\t\t\t\tvs = vs[0 : len(vs)-1]\n\t\t\t}\n\t\t}\n\t\tif vs[len(vs)-1] == '.' {\n\t\t\tvs = vs[0 : len(vs)-1]\n\t\t}\n\t\treturn vs\n\t}\n\n\tif A == nil {\n\t\treturn \"{nil}\"\n\t}\n\ts := \"{\"\n\n\tmaxLen := 0\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tv := A.Get(i, j)\n\t\t\tvs := condense(fmt.Sprintf(\"%f\", v))\n\n\t\t\tmaxLen = maxInt(maxLen, len(vs))\n\t\t}\n\t}\n\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tv := A.Get(i, j)\n\n\t\t\tvs := condense(fmt.Sprintf(\"%f\", v))\n\n\t\t\tfor len(vs) < maxLen {\n\t\t\t\tvs = \" \" + vs\n\t\t\t}\n\t\t\ts += vs\n\t\t\tif i != A.Rows()-1 || j != A.Cols()-1 {\n\t\t\t\ts += \",\"\n\t\t\t}\n\t\t\tif j != A.Cols()-1 {\n\t\t\t\ts += \" \"\n\t\t\t}\n\t\t}\n\t\tif i != A.Rows()-1 {\n\t\t\ts += \"\\n \"\n\t\t}\n\t}\n\ts += \"}\"\n\treturn s\n}\n"
  },
  {
    "path": "matrix_test.go",
    "content": "package matrix\n\nimport (\n\t\"testing\"\n)\n\nfunc TestParse(t *testing.T) {\n\ts := `[1 2 3;4 5 6]`\n\tA, err := ParseMatlab(s)\n\t\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t\n\tAr := MakeDenseMatrix([]float64{1,2,3,4,5,6}, 2, 3)\n\tif !Equals(A, Ar) {\n\t\tt.Error()\n\t}\n}\n"
  },
  {
    "path": "pivot.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\n/*\nA space-optimized structure for pivot matrices, ie a matrix with\nexactly one 1 in each row and each column.\n*/\ntype PivotMatrix struct {\n\tmatrix\n\tpivots    []int\n\tpivotSign float64\n}\n\nfunc (P *PivotMatrix) Get(i, j int) float64 {\n\ti = i % P.rows\n\tif i < 0 {\n\t\ti = P.rows - i\n\t}\n\tj = j % P.cols\n\tif j < 0 {\n\t\tj = P.cols - j\n\t}\n\tif P.pivots[j] == i {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n/*\nConvert this PivotMatrix into a DenseMatrix.\n*/\nfunc (P *PivotMatrix) DenseMatrix() *DenseMatrix {\n\tA := Zeros(P.rows, P.cols)\n\tfor j := 0; j < P.rows; j++ {\n\t\tA.Set(P.pivots[j], j, 1)\n\t}\n\treturn A\n}\n\n/*\nConvert this PivotMatrix into a SparseMatrix.\n*/\nfunc (P *PivotMatrix) SparseMatrix() *SparseMatrix {\n\tA := ZerosSparse(P.rows, P.cols)\n\tfor j := 0; j < P.rows; j++ {\n\t\tA.Set(P.pivots[j], j, 1)\n\t}\n\treturn A\n}\n\n/*\nMake a copy of this PivotMatrix.\n*/\nfunc (P *PivotMatrix) Copy() *PivotMatrix { return MakePivotMatrix(P.pivots, P.pivotSign) }\n\nfunc MakePivotMatrix(pivots []int, pivotSign float64) *PivotMatrix {\n\tn := len(pivots)\n\tP := new(PivotMatrix)\n\tP.rows = n\n\tP.cols = n\n\tP.pivots = pivots\n\tP.pivotSign = pivotSign\n\treturn P\n}\n\nfunc (A *PivotMatrix) String() string { return String(A) }\n"
  },
  {
    "path": "pivot_arithmetic.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nfunc (P *PivotMatrix) Minus(A MatrixRO) (Matrix, error) {\n\tif P.rows != A.Rows() || P.cols != A.Cols() {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tB := P.DenseMatrix()\n\tB.Subtract(A)\n\treturn B, nil\n}\n\nfunc (P *PivotMatrix) Plus(A MatrixRO) (Matrix, error) {\n\tif P.rows != A.Rows() || P.cols != A.Cols() {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tB := P.DenseMatrix()\n\tB.Add(A)\n\treturn B, nil\n}\n\n/*\nMultiply this pivot matrix by another.\n*/\nfunc (P *PivotMatrix) Times(A MatrixRO) (Matrix, error) {\n\tif P.Cols() != A.Rows() {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tB := Zeros(P.rows, A.Cols())\n\tfor i := 0; i < P.rows; i++ {\n\t\tk := 0\n\t\tfor ; i != P.pivots[k]; k++ {\n\t\t}\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tB.Set(i, j, A.Get(k, j))\n\t\t}\n\t}\n\treturn B, nil\n}\n\n/*\nMultiplication optimized for when two pivots are the operands.\n*/\nfunc (P *PivotMatrix) TimesPivot(A *PivotMatrix) (*PivotMatrix, error) {\n\tif P.rows != A.rows {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\n\tnewPivots := make([]int, P.rows)\n\tnewSign := P.pivotSign * A.pivotSign\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tnewPivots[i] = P.pivots[A.pivots[i]]\n\t}\n\n\treturn MakePivotMatrix(newPivots, newSign), nil\n}\n\n/*\nEquivalent to PxA, but streamlined to take advantage of the datastructures.\n*/\nfunc (P *PivotMatrix) RowPivotDense(A *DenseMatrix) (*DenseMatrix, error) {\n\tif P.rows != A.rows {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tB := Zeros(A.rows, A.cols)\n\tfor si := 0; si < A.rows; si++ {\n\t\tdi := P.pivots[si]\n\t\tAstart := si * A.step\n\t\tBstart := di * B.step\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tB.elements[Bstart+j] = A.elements[Astart+j]\n\t\t}\n\t}\n\treturn B, nil\n}\n\n/*\nEquivalent to AxP, but streamlined to take advantage of the datastructures.\n*/\nfunc (P *PivotMatrix) ColPivotDense(A *DenseMatrix) (*DenseMatrix, error) {\n\tif P.rows != A.cols {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tB := Zeros(A.rows, A.cols)\n\tfor i := 0; i < B.rows; i++ {\n\t\tAstart := i * A.step\n\t\tBstart := i * B.step\n\t\tfor sj := 0; sj < B.cols; sj++ {\n\t\t\tdj := P.pivots[sj]\n\t\t\tB.elements[Bstart+dj] = A.elements[Astart+sj]\n\t\t}\n\t}\n\treturn B, nil\n}\n\n/*\nEquivalent to PxA, but streamlined to take advantage of the datastructures.\n*/\nfunc (P *PivotMatrix) RowPivotSparse(A *SparseMatrix) (*SparseMatrix, error) {\n\tif P.rows != A.rows {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tB := ZerosSparse(A.rows, A.cols)\n\tfor index, value := range A.elements {\n\t\tsi, j := A.GetRowColIndex(index)\n\t\tdi := P.pivots[si]\n\t\tB.Set(di, j, value)\n\t}\n\n\treturn B, nil\n}\n\n/*\nEquivalent to AxP, but streamlined to take advantage of the datastructures.\n*/\nfunc (P *PivotMatrix) ColPivotSparse(A *SparseMatrix) (*SparseMatrix, error) {\n\tif P.rows != A.cols {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tB := ZerosSparse(A.rows, A.cols)\n\tfor index, value := range A.elements {\n\t\ti, sj := A.GetRowColIndex(index)\n\t\tdj := P.pivots[sj]\n\t\tB.Set(i, dj, value)\n\t}\n\n\treturn B, nil\n}\n"
  },
  {
    "path": "pivot_basic.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"math\"\n\n/*\nSwap two rows in this PivotMatrix.\n*/\nfunc (P *PivotMatrix) SwapRows(r1, r2 int) error {\n\t//\ttmp := P.pivots[r1];\n\t//\tP.pivots[r1] = P.pivots[r2];\n\t//\tP.pivots[r2] = tmp;\n\tP.pivots[r1], P.pivots[r2] = P.pivots[r2], P.pivots[r1]\n\tP.pivotSign *= -1\n\n\treturn nil\n}\n\nfunc (P *PivotMatrix) Symmetric() bool {\n\tfor i := 0; i < P.rows; i++ {\n\t\tif P.pivots[P.pivots[i]] != i {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (A *PivotMatrix) Inverse() *PivotMatrix { return A.Transpose() }\n\nfunc (P *PivotMatrix) Transpose() *PivotMatrix {\n\tnewPivots := make([]int, P.rows)\n\tfor i := 0; i < P.rows; i++ {\n\t\tnewPivots[P.pivots[i]] = i\n\t}\n\treturn MakePivotMatrix(newPivots, P.pivotSign)\n}\n\nfunc (P *PivotMatrix) Det() float64 { return P.pivotSign }\n\nfunc (P *PivotMatrix) Trace() (r float64) {\n\tfor i := 0; i < len(P.pivots); i++ {\n\t\tif P.pivots[i] == i {\n\t\t\tr += 1\n\t\t}\n\t}\n\treturn\n}\n\n/*\nReturns x such that Px=b.\n*/\nfunc (P *PivotMatrix) Solve(b MatrixRO) (Matrix, error) {\n\treturn P.Transpose().Times(b) //error comes from times\n}\n\nfunc (A *PivotMatrix) OneNorm() float64      { return float64(A.rows) }\nfunc (A *PivotMatrix) TwoNorm() float64      { return math.Sqrt(float64(A.rows)) }\nfunc (A *PivotMatrix) InfinityNorm() float64 { return 1 }\n"
  },
  {
    "path": "pivot_test.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"testing\"\nimport \"fmt\"\n\nfunc TestTimes_Pivot(t *testing.T) {\n\tP1 := MakePivotMatrix([]int{2, 1, 0}, -1)\n\tP2 := MakePivotMatrix([]int{2, 0, 1}, 1)\n\tP, _ := P1.TimesPivot(P2)\n\tif !Equals(P, Product(P1, P2)) {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"%v\\n%v\\n%v\\n\", P1, P2, P)\n\t\t}\n\t\tt.Fail()\n\t}\n}\n\nfunc TestRowPivot(t *testing.T) {\n\tP := MakePivotMatrix([]int{2, 1, 0}, -1)\n\tA := Normals(3, 4)\n\tB, _ := P.RowPivotDense(A)\n\tBtrue := Product(P, A)\n\tif !Equals(B, Btrue) {\n\t\tt.Fail()\n\t}\n\tA = Normals(4, 3)\n\t_, err := P.RowPivotDense(A)\n\tif err == nil {\n\t\tt.Fail()\n\t}\n\tC := Normals(3, 4).SparseMatrix()\n\tD, _ := P.RowPivotSparse(C)\n\tBtrue = Product(P, C)\n\tif !Equals(D, Btrue) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestColPivot(t *testing.T) {\n\tP := MakePivotMatrix([]int{2, 1, 0}, -1)\n\tA := Normals(4, 3)\n\tB, _ := P.ColPivotDense(A)\n\tBtrue := Product(A, P)\n\tif !Equals(B, Btrue) {\n\t\tt.Fail()\n\t}\n\tA = Normals(3, 4)\n\t_, err := P.ColPivotDense(A)\n\tif err == nil {\n\t\tt.Fail()\n\t}\n\tC := Normals(4, 3).SparseMatrix()\n\tD, _ := P.ColPivotSparse(C)\n\tBtrue = Product(C, P)\n\tif !Equals(D, Btrue) {\n\t\tt.Fail()\n\t}\n}\n"
  },
  {
    "path": "sparse.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"math/rand\"\n\n/*\nA sparse matrix based on go's map datastructure.\n*/\ntype SparseMatrix struct {\n\tmatrix\n\telements map[int]float64\n\t// offset to start of matrix s.t. idx = i*cols + j + offset\n\t// offset = starting row * step + starting col\n\toffset int\n\t// analogous to dense step\n\tstep int\n}\n\nfunc (A *SparseMatrix) Get(i, j int) float64 {\n\ti = i % A.rows\n\tif i < 0 {\n\t\ti = A.rows - i\n\t}\n\tj = j % A.cols\n\tif j < 0 {\n\t\tj = A.cols - j\n\t}\n\tx, _ := A.elements[i*A.step+j+A.offset]\n\treturn x\n}\n\n/*\nLooks up an element given its element index.\n*/\nfunc (A *SparseMatrix) GetIndex(index int) float64 {\n\tx, ok := A.elements[index]\n\tif !ok {\n\t\treturn 0\n\t}\n\treturn x\n}\n\n/*\nTurn an element index into a row number.\n*/\nfunc (A *SparseMatrix) GetRowIndex(index int) (i int) {\n\ti = (index - A.offset) / A.cols\n\treturn\n}\n\n/*\nTurn an element index into a column number.\n*/\nfunc (A *SparseMatrix) GetColIndex(index int) (j int) {\n\tj = (index - A.offset) % A.cols\n\treturn\n}\n\n/*\nTurn an element index into a row and column number.\n*/\nfunc (A *SparseMatrix) GetRowColIndex(index int) (i int, j int) {\n\ti = (index - A.offset) / A.step\n\tj = (index - A.offset) % A.step\n\treturn\n}\n\nfunc (A *SparseMatrix) Set(i int, j int, v float64) {\n\ti = i % A.rows\n\tif i < 0 {\n\t\ti = A.rows - i\n\t}\n\tj = j % A.cols\n\tif j < 0 {\n\t\tj = A.cols - j\n\t}\n\t// v == 0 results in removal of key from underlying map\n\tif v == 0 {\n\t\tdelete(A.elements, i*A.step+j+A.offset)\n\t} else {\n\t\tA.elements[i*A.step+j+A.offset] = v\n\t}\n}\n\n/*\nSets an element given its index.\n*/\nfunc (A *SparseMatrix) SetIndex(index int, v float64) {\n\t// v == 0 results in removal of key from underlying map\n\tif v == 0 {\n\t\tdelete(A.elements, index)\n\t} else {\n\t\tA.elements[index] = v\n\t}\n}\n\n/*\nA channel that will carry the indices of non-zero elements.\n*/\nfunc (A *SparseMatrix) Indices() (out chan int) {\n\t//maybe thread the populating?\n\tout = make(chan int)\n\tgo func(o chan int) {\n\t\tfor index := range A.elements {\n\t\t\ti, j := A.GetRowColIndex(index)\n\t\t\tif 0 <= i && i < A.rows && 0 <= j && j < A.cols {\n\t\t\t\to <- index\n\t\t\t}\n\t\t}\n\t\tclose(o)\n\t}(out)\n\treturn\n}\n\n/*\nGet a matrix representing a subportion of A. Changes to the new matrix will be\nreflected in A.\n*/\nfunc (A *SparseMatrix) GetMatrix(i, j, rows, cols int) (subMatrix *SparseMatrix) {\n\tif i < 0 || j < 0 || i+rows > A.rows || j+cols > A.cols {\n\t\ti = maxInt(0, i)\n\t\tj = maxInt(0, j)\n\t\trows = minInt(A.rows-i, rows)\n\t\trows = minInt(A.cols-j, cols)\n\t}\n\n\tsubMatrix = new(SparseMatrix)\n\tsubMatrix.rows = rows\n\tsubMatrix.cols = cols\n\tsubMatrix.offset = (i+A.offset/A.step)*A.step + (j + A.offset%A.step)\n\tsubMatrix.step = A.step\n\tsubMatrix.elements = A.elements\n\n\treturn\n}\n\n/*\nGets a reference to a column vector.\n*/\nfunc (A *SparseMatrix) GetColVector(j int) *SparseMatrix {\n\treturn A.GetMatrix(0, j, A.rows, j+1)\n}\n\n/*\nGets a reference to a row vector.\n*/\nfunc (A *SparseMatrix) GetRowVector(i int) *SparseMatrix {\n\treturn A.GetMatrix(i, 0, 1, A.cols)\n}\n\n/*\nCreates a new matrix [A B].\n*/\nfunc (A *SparseMatrix) Augment(B *SparseMatrix) (*SparseMatrix, error) {\n\tif A.rows != B.rows {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tC := ZerosSparse(A.rows, A.cols+B.cols)\n\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tC.Set(i, j, value)\n\t}\n\n\tfor index, value := range B.elements {\n\t\ti, j := B.GetRowColIndex(index)\n\t\tC.Set(i, j+A.cols, value)\n\t}\n\n\treturn C, nil\n}\n\n/*\nCreates a new matrix [A;B], where A is above B.\n*/\nfunc (A *SparseMatrix) Stack(B *SparseMatrix) (*SparseMatrix, error) {\n\tif A.cols != B.cols {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\tC := ZerosSparse(A.rows+B.rows, A.cols)\n\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tC.Set(i, j, value)\n\t}\n\n\tfor index, value := range B.elements {\n\t\ti, j := B.GetRowColIndex(index)\n\t\tC.Set(i+A.rows, j, value)\n\t}\n\n\treturn C, nil\n}\n\n/*\nReturns a copy with all zeros above the diagonal.\n*/\nfunc (A *SparseMatrix) L() *SparseMatrix {\n\tB := ZerosSparse(A.rows, A.cols)\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tif i >= j {\n\t\t\tB.Set(i, j, value)\n\t\t}\n\t}\n\treturn B\n}\n\n/*\nReturns a copy with all zeros below the diagonal.\n*/\nfunc (A *SparseMatrix) U() *SparseMatrix {\n\tB := ZerosSparse(A.rows, A.cols)\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tif i <= j {\n\t\t\tB.Set(i, j, value)\n\t\t}\n\t}\n\treturn B\n}\n\nfunc (A *SparseMatrix) Copy() *SparseMatrix {\n\tB := ZerosSparse(A.rows, A.cols)\n\tfor index, value := range A.elements {\n\t\tB.elements[index] = value\n\t}\n\treturn B\n}\n\nfunc ZerosSparse(rows int, cols int) *SparseMatrix {\n\tA := new(SparseMatrix)\n\tA.rows = rows\n\tA.cols = cols\n\tA.offset = 0\n\tA.step = cols\n\tA.elements = map[int]float64{}\n\treturn A\n}\n\n/*\nCreates a matrix and puts a standard normal in n random elements, with replacement.\n*/\nfunc NormalsSparse(rows int, cols int, n int) *SparseMatrix {\n\tA := ZerosSparse(rows, cols)\n\tfor k := 0; k < n; k++ {\n\t\ti := rand.Intn(rows)\n\t\tj := rand.Intn(cols)\n\t\tA.Set(i, j, rand.NormFloat64())\n\t}\n\treturn A\n}\n\n/*\nCreate a sparse matrix using the provided map as its backing.\n*/\nfunc MakeSparseMatrix(elements map[int]float64, rows int, cols int) *SparseMatrix {\n\tA := ZerosSparse(rows, cols)\n\tA.elements = elements\n\treturn A\n}\n\n/*\nConvert this sparse matrix into a dense matrix.\n*/\nfunc (A *SparseMatrix) DenseMatrix() *DenseMatrix {\n\tB := Zeros(A.rows, A.cols)\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tB.Set(i, j, value)\n\t}\n\treturn B\n}\n\nfunc (A *SparseMatrix) SparseMatrix() *SparseMatrix {\n\treturn A.Copy()\n}\n\nfunc (A *SparseMatrix) String() string { return String(A) }\n"
  },
  {
    "path": "sparse_arithmetic.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\n/*\nThe sum of this matrix and another.\n*/\nfunc (A *SparseMatrix) Plus(B MatrixRO) (Matrix, error) {\n\tC := A.Copy()\n\terr := C.Add(B)\n\treturn C, err\n}\n\n/*\nThe sum of this matrix and another sparse matrix, optimized for sparsity.\n*/\nfunc (A *SparseMatrix) PlusSparse(B *SparseMatrix) (*SparseMatrix, error) {\n\tC := A.Copy()\n\terr := C.AddSparse(B)\n\treturn C, err\n}\n\n/*\nThe difference between this matrix and another.\n*/\nfunc (A *SparseMatrix) Minus(B MatrixRO) (Matrix, error) {\n\tC := A.Copy()\n\terr := C.Subtract(B)\n\treturn C, err\n}\n\n/*\nThe difference between this matrix and another sparse matrix, optimized for sparsity.\n*/\nfunc (A *SparseMatrix) MinusSparse(B *SparseMatrix) (*SparseMatrix, error) {\n\tC := A.Copy()\n\terr := C.SubtractSparse(B)\n\treturn C, err\n}\n\n/*\nAdd another matrix to this one in place.\n*/\nfunc (A *SparseMatrix) Add(B MatrixRO) error {\n\tif Bs, ok := B.(*SparseMatrix); ok {\n\t\treturn A.AddSparse(Bs)\n\t}\n\n\tif A.rows != B.Rows() || A.cols != B.Cols() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.Set(i, j, A.Get(i, j)+B.Get(i, j))\n\t\t}\n\t}\n\n\treturn nil\n}\n\n/*\nAdd another matrix to this one in place, optimized for sparsity.\n*/\nfunc (A *SparseMatrix) AddSparse(B *SparseMatrix) error {\n\tif A.rows != B.Rows() || A.cols != B.Cols() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor index, value := range B.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tA.Set(i, j, A.Get(i, j)+value)\n\t}\n\n\treturn nil\n}\n\n/*\nSubtract another matrix from this one in place.\n*/\nfunc (A *SparseMatrix) Subtract(B MatrixRO) error {\n\tif Bs, ok := B.(*SparseMatrix); ok {\n\t\treturn A.SubtractSparse(Bs)\n\t}\n\n\tif A.rows != B.Rows() || A.cols != B.Cols() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor i := 0; i < A.rows; i++ {\n\t\tfor j := 0; j < A.cols; j++ {\n\t\t\tA.Set(i, j, A.Get(i, j)-B.Get(i, j))\n\t\t}\n\t}\n\n\treturn nil\n}\n\n/*\nSubtract another matrix from this one in place, optimized for sparsity.\n*/\nfunc (A *SparseMatrix) SubtractSparse(B *SparseMatrix) error {\n\tif A.rows != B.Rows() || A.cols != B.Cols() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor index, value := range B.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tA.Set(i, j, A.Get(i, j)-value)\n\t}\n\n\treturn nil\n}\n\n/*\nGet the product of this matrix and another.\n*/\nfunc (A *SparseMatrix) Times(B MatrixRO) (Matrix, error) {\n\t/* uncomment this if an efficient version is written\n\tif Bs, ok := B.(*SparseMatrix); ok {\n\t\treturn A.TimesSparse(Bs);\n\t}\n\t*/\n\n\tif A.cols != B.Rows() {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\n\tC := ZerosSparse(A.rows, B.Cols())\n\n\tfor index, value := range A.elements {\n\t\ti, k := A.GetRowColIndex(index)\n\t\t//not sure if there is a more efficient way to do this without using\n\t\t//a different data structure\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tv := B.Get(k, j)\n\t\t\tif v != 0 {\n\t\t\t\tC.Set(i, j, C.Get(i, j)+value*v)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn C, nil\n}\n\n/*\nGet the product of this matrix and another, optimized for sparsity.\n*/\nfunc (A *SparseMatrix) TimesSparse(B *SparseMatrix) (*SparseMatrix, error) {\n\tif A.cols != B.Rows() {\n\t\treturn nil, ErrorDimensionMismatch\n\t}\n\n\tC := ZerosSparse(A.rows, B.Cols())\n\n\tfor index, value := range A.elements {\n\t\ti, k := A.GetRowColIndex(index)\n\t\t//not sure if there is a more efficient way to do this without using\n\t\t//a different data structure\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tv := B.Get(k, j)\n\t\t\tif v != 0 {\n\t\t\t\tC.Set(i, j, C.Get(i, j)+value*v)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn C, nil\n}\n\n/*\nScale this matrix by f.\n*/\nfunc (A *SparseMatrix) Scale(f float64) {\n\tfor index, value := range A.elements {\n\t\tA.elements[index] = value * f\n\t}\n}\n\n/*\nGet the element-wise product of this matrix and another.\n*/\nfunc (A *SparseMatrix) ElementMult(B MatrixRO) (*SparseMatrix, error) {\n\tC := A.Copy()\n\terr := C.ScaleMatrix(B)\n\treturn C, err\n}\n\n/*\nGet the element-wise product of this matrix and another, optimized for sparsity.\n*/\nfunc (A *SparseMatrix) ElementMultSparse(B *SparseMatrix) (*SparseMatrix, error) {\n\tC := A.Copy()\n\terr := C.ScaleMatrixSparse(B)\n\treturn C, err\n}\n\n/*\nScale this matrix by another, element-wise.\n*/\nfunc (A *SparseMatrix) ScaleMatrix(B MatrixRO) error {\n\tif A.rows != B.Rows() || A.cols != B.Cols() {\n\t\treturn ErrorDimensionMismatch\n\t}\n\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tA.Set(i, j, value*B.Get(i, j))\n\t}\n\n\treturn nil\n}\n\n/*\nScale this matrix by another sparse matrix, element-wise. Optimized for sparsity.\n*/\nfunc (A *SparseMatrix) ScaleMatrixSparse(B *SparseMatrix) error {\n\tif len(B.elements) > len(A.elements) {\n\t\tif A.rows != B.rows || A.cols != B.cols {\n\t\t\treturn ErrorDimensionMismatch\n\t\t}\n\n\t\tfor index, value := range A.elements {\n\t\t\ti, j := A.GetRowColIndex(index)\n\t\t\tA.Set(i, j, value*B.Get(i, j))\n\t\t}\n\t}\n\treturn A.ScaleMatrix(B)\n}\n"
  },
  {
    "path": "sparse_basic.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"math\"\n\n/*\nSwap two rows in this matrix.\n*/\nfunc (A *SparseMatrix) SwapRows(r1, r2 int) {\n\tjs := map[int]bool{}\n\tfor index := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tif i == r1 || i == r2 {\n\t\t\tjs[j] = true\n\t\t}\n\t}\n\tfor j := range js {\n\t\ttmp := A.Get(r1, j)\n\t\tA.Set(r1, j, A.Get(r2, j))\n\t\tA.Set(r2, j, tmp)\n\t}\n}\n\n/*\nScale a row by a scalar.\n*/\nfunc (A *SparseMatrix) ScaleRow(r int, f float64) {\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tif i == r {\n\t\t\tA.Set(i, j, value*f)\n\t\t}\n\t}\n}\n\n/*\nAdd a multiple of row rs to row rd.\n*/\nfunc (A *SparseMatrix) ScaleAddRow(rd, rs int, f float64) {\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tif i == rs {\n\t\t\tA.Set(rd, j, A.Get(rd, j)+value*f)\n\t\t}\n\t}\n}\n\nfunc (A *SparseMatrix) Symmetric() bool {\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tif i != j && value != A.Get(j, i) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (A *SparseMatrix) Transpose() *SparseMatrix {\n\tB := ZerosSparse(A.cols, A.rows)\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tB.Set(j, i, value)\n\t}\n\treturn B\n}\n\nfunc (A *SparseMatrix) Det() float64 {\n\t//TODO: obviously this is a horrible way to do it\n\treturn A.DenseMatrix().Det()\n}\n\nfunc (A *SparseMatrix) Trace() (res float64) {\n\tfor index, value := range A.elements {\n\t\ti, j := A.GetRowColIndex(index)\n\t\tif i == j {\n\t\t\tres += value\n\t\t}\n\t}\n\treturn\n}\n\nfunc (A *SparseMatrix) OneNorm() (res float64) {\n\tfor _, value := range A.elements {\n\t\tres += math.Abs(value)\n\t}\n\treturn\n}\n\nfunc (A *SparseMatrix) TwoNorm() float64 {\n\tvar sum float64 = 0\n\tfor _, value := range A.elements {\n\t\tsum += value * value\n\t}\n\treturn math.Sqrt(sum)\n}\n\nfunc (A *SparseMatrix) InfinityNorm() (res float64) {\n\tfor _, value := range A.elements {\n\t\tres = max(res, math.Abs(value))\n\t}\n\treturn\n}\n"
  },
  {
    "path": "sparse_test.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"testing\"\n)\n\nfunc TestAdd_Sparse(t *testing.T) {\n\tA := NormalsSparse(3, 3, 9)\n\tB := NormalsSparse(3, 3, 9)\n\tC1, _ := A.Plus(B)\n\tC2, _ := A.PlusSparse(B)\n\tif !ApproxEquals(C1, Sum(A, B), ε) {\n\t\tt.Fail()\n\t}\n\tif !ApproxEquals(C2, Sum(A, B), ε) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestSubtract_Sparse(t *testing.T) {\n\tA := NormalsSparse(3, 3, 9)\n\tB := NormalsSparse(3, 3, 9)\n\tC1, _ := A.Minus(B)\n\tC2, _ := A.MinusSparse(B)\n\tif !ApproxEquals(C1, Difference(A, B), ε) {\n\t\tt.Fail()\n\t}\n\tif !ApproxEquals(C2, Difference(A, B), ε) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestTimes_Sparse(t *testing.T) {\n\tA := Normals(3, 3).SparseMatrix()\n\tB := Normals(3, 3).SparseMatrix()\n\tC1, _ := A.Times(B)\n\tC2, _ := A.TimesSparse(B)\n\tif !ApproxEquals(C1, Product(A, B), ε) {\n\t\tt.Fail()\n\t}\n\tif !ApproxEquals(C2, Product(A, B), ε) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestElementMult_Sparse(t *testing.T) {\n\tA := Normals(3, 3).SparseMatrix()\n\tB := Normals(3, 3).SparseMatrix()\n\tC1, _ := A.ElementMult(B)\n\tC2, _ := A.ElementMultSparse(B)\n\tD, _ := A.DenseMatrix().ElementMult(B)\n\tif !Equals(D, C1) {\n\t\tt.Fail()\n\t}\n\tif !Equals(D, C2) {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestGetMatrix_Sparse(t *testing.T) {\n\tA := ZerosSparse(6, 6)\n\tfor i := 0; i < 36; i++ {\n\t\tx := rand.Intn(6)\n\t\ty := rand.Intn(6)\n\t\tA.Set(y, x, 1)\n\t}\n\tB := A.GetMatrix(1, 1, 4, 4)\n\n\tfor i := 0; i < 4; i++ {\n\t\tfor j := 0; j < 4; j++ {\n\t\t\tif B.Get(i, j) != A.Get(i+1, j+1) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\n}\n\nfunc TestAugment_Sparse(t *testing.T) {\n\tvar A, B, C *SparseMatrix\n\tA = NormalsSparse(4, 4, 16)\n\tB = NormalsSparse(4, 4, 16)\n\tC, _ = A.Augment(B)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i, j+A.Cols()) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\n\tA = NormalsSparse(2, 2, 4)\n\tB = NormalsSparse(4, 4, 16)\n\tC, err := A.Augment(B)\n\tif err == nil {\n\t\tt.Fail()\n\t}\n\n\tA = NormalsSparse(4, 4, 16)\n\tB = NormalsSparse(4, 2, 8)\n\tC, _ = A.Augment(B)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i, j+A.Cols()) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestStack_Sparse(t *testing.T) {\n\tvar A, B, C *SparseMatrix\n\tA = NormalsSparse(4, 4, 16)\n\tB = NormalsSparse(4, 4, 16)\n\tC, _ = A.Stack(B)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i+A.Rows(), j) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\n\tA = NormalsSparse(2, 2, 4)\n\tB = NormalsSparse(4, 4, 16)\n\tC, err := A.Stack(B)\n\tif err == nil {\n\t\tif verbose {\n\t\t\tfmt.Printf(\"%v\\n\", err)\n\t\t}\n\t\tt.Fail()\n\t}\n\n\tA = NormalsSparse(4, 4, 16)\n\tB = NormalsSparse(2, 4, 8)\n\tC, _ = A.Stack(B)\n\tfor i := 0; i < A.Rows(); i++ {\n\t\tfor j := 0; j < A.Cols(); j++ {\n\t\t\tif C.Get(i, j) != A.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n\tfor i := 0; i < B.Rows(); i++ {\n\t\tfor j := 0; j < B.Cols(); j++ {\n\t\t\tif C.Get(i+A.Rows(), j) != B.Get(i, j) {\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "util.go",
    "content": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage matrix\n\nimport \"runtime\"\n\nfunc max(x, y float64) float64 {\n\tif x > y {\n\t\treturn x\n\t}\n\treturn y\n}\n\nfunc maxInt(x, y int) int {\n\tif x > y {\n\t\treturn x\n\t}\n\treturn y\n}\n\nfunc min(x, y float64) float64 {\n\tif x < y {\n\t\treturn x\n\t}\n\treturn y\n}\n\nfunc minInt(x, y int) int {\n\tif x < y {\n\t\treturn x\n\t}\n\treturn y\n}\n\nfunc sum(a []float64) (s float64) {\n\tfor _, v := range a {\n\t\ts += v\n\t}\n\treturn\n}\n\nfunc product(a []float64) float64 {\n\tp := float64(1)\n\tfor _, v := range a {\n\t\tp *= v\n\t}\n\treturn p\n}\n\ntype box interface{}\n\nfunc countBoxes(start, cap int) chan box {\n\tints := make(chan box)\n\tgo func() {\n\t\tfor i := start; i < cap; i++ {\n\t\t\tints <- i\n\t\t}\n\t\tclose(ints)\n\t}()\n\treturn ints\n}\n\nfunc parFor(inputs <-chan box, foo func(i box)) (wait func()) {\n\tn := runtime.GOMAXPROCS(0)\n\tblock := make(chan bool, n)\n\tfor j := 0; j < n; j++ {\n\t\tgo func() {\n\t\t\tfor {\n\t\t\t\ti, ok := <-inputs\n\t\t\t\tif !ok {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tfoo(i)\n\t\t\t}\n\t\t\tblock <- true\n\t\t}()\n\t}\n\twait = func() {\n\t\tfor i := 0; i < n; i++ {\n\t\t\t<-block\n\t\t}\n\t}\n\treturn\n}\n"
  }
]