Full Code of skelterjohn/go.matrix for AI

go1 daa59528eefd cached
25 files
95.2 KB
37.1k tokens
247 symbols
1 requests
Download .txt
Repository: skelterjohn/go.matrix
Branch: go1
Commit: daa59528eefd
Files: 25
Total size: 95.2 KB

Directory structure:
gitextract_v_1rg_cr/

├── AUTHORS
├── LICENSE
├── README
├── arithmetic.go
├── dense.go
├── dense_arithmetic.go
├── dense_basic.go
├── dense_data.go
├── dense_decomp.go
├── dense_eigen.go
├── dense_svd.go
├── dense_test.go
├── densebench_test.go
├── error.go
├── matrix.go
├── matrix_test.go
├── pivot.go
├── pivot_arithmetic.go
├── pivot_basic.go
├── pivot_test.go
├── sparse.go
├── sparse_arithmetic.go
├── sparse_basic.go
├── sparse_test.go
└── util.go

================================================
FILE CONTENTS
================================================

================================================
FILE: AUTHORS
================================================
John Asmuth <jasmuth@gmail.com>
Ryanne Dolan


================================================
FILE: LICENSE
================================================

Copyright (c) 2013 the AUTHORS. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
   * The names in AUTHORs may not be used to endorse or promote
products derived from this software without specific prior written
permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: README
================================================


================================================
FILE: arithmetic.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "math"

/*
Finds the sum of two matrices.
*/
func Sum(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {
	C = MakeDenseCopy(A)
	var err error
	for _, B := range Bs {
		err = C.Add(MakeDenseCopy(B))
		if err != nil {
			break
		}
	}
	if err != nil {
		C = nil
	}
	return
}

/*
Finds the difference between two matrices.
*/
func Difference(A, B MatrixRO) (C *DenseMatrix) {
	C = MakeDenseCopy(A)
	err := C.Subtract(MakeDenseCopy(B))
	if err != nil {
		C = nil
	}
	return
}

/*
Finds the Product of two matrices.
*/
func Product(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {
	C = MakeDenseCopy(A)

	for _, B := range Bs {
		Cm, err := C.Times(B)
		if err != nil {
			return
		}
		C = Cm.(*DenseMatrix)
	}

	return
}

func Transpose(A MatrixRO) (B Matrix) {
	switch Am := A.(type) {
	case *DenseMatrix:
		B = Am.Transpose()
		return
	case *SparseMatrix:
		B = Am.Transpose()
		return
	}
	B = A.DenseMatrix().Transpose()
	return
}

func Inverse(A MatrixRO) (B Matrix) {
	var err error
	switch Am := A.(type) {
	case *DenseMatrix:
		B, err = Am.Inverse()
		if err != nil {
			panic(err)
		}
		return
	}
	B, err = A.DenseMatrix().Inverse()
	if err != nil {
		panic(err)
	}
	return
}

/*
The Kronecker product. (http://en.wikipedia.org/wiki/Kronecker_product)
*/
func Kronecker(A, B MatrixRO) (C *DenseMatrix) {
	ars, acs := A.Rows(), A.Cols()
	brs, bcs := B.Rows(), B.Cols()
	C = Zeros(ars*brs, acs*bcs)
	for i := 0; i < ars; i++ {
		for j := 0; j < acs; j++ {
			Cij := C.GetMatrix(i*brs, j*bcs, brs, bcs)
			Cij.SetMatrix(0, 0, Scaled(B, A.Get(i, j)))
		}
	}
	return
}

func Vectorize(Am MatrixRO) (V *DenseMatrix) {
	elems := Am.DenseMatrix().Transpose().Array()
	V = MakeDenseMatrix(elems, Am.Rows()*Am.Cols(), 1)
	return
}

func Unvectorize(V MatrixRO, rows, cols int) (A *DenseMatrix) {
	A = MakeDenseMatrix(V.DenseMatrix().Array(), cols, rows).Transpose()
	return
}

/*
Uses a number of goroutines to do the dot products necessary
for the matrix multiplication in parallel.
*/
func ParallelProduct(A, B MatrixRO) (C *DenseMatrix) {
	if A.Cols() != B.Rows() {
		return nil
	}

	C = Zeros(A.Rows(), B.Cols())

	in := make(chan int)
	quit := make(chan bool)

	dotRowCol := func() {
		for {
			select {
			case i := <-in:
				sums := make([]float64, B.Cols())
				for k := 0; k < A.Cols(); k++ {
					for j := 0; j < B.Cols(); j++ {
						sums[j] += A.Get(i, k) * B.Get(k, j)
					}
				}
				for j := 0; j < B.Cols(); j++ {
					C.Set(i, j, sums[j])
				}
			case <-quit:
				return
			}
		}
	}

	threads := 2

	for i := 0; i < threads; i++ {
		go dotRowCol()
	}

	for i := 0; i < A.Rows(); i++ {
		in <- i
	}

	for i := 0; i < threads; i++ {
		quit <- true
	}

	return
}

/*
Scales a matrix by a scalar.
*/
func Scaled(A MatrixRO, f float64) (B *DenseMatrix) {
	B = MakeDenseCopy(A)
	B.Scale(f)
	return
}

/*
Tests the element-wise equality of the two matrices.
*/
func Equals(A, B MatrixRO) bool {
	if A.Rows() != B.Rows() || A.Cols() != B.Cols() {
		return false
	}
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if A.Get(i, j) != B.Get(i, j) {
				return false
			}
		}
	}
	return true
}

/*
Tests to see if the difference between two matrices,
element-wise, exceeds ε.
*/
func ApproxEquals(A, B MatrixRO, ε float64) bool {
	if A.Rows() != B.Rows() || A.Cols() != B.Cols() {
		return false
	}
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if math.Abs(A.Get(i, j)-B.Get(i, j)) > ε {
				return false
			}
		}
	}
	return true
}


================================================
FILE: dense.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import (
	"math/rand"
)

/*
A matrix backed by a flat array of all elements.
*/
type DenseMatrix struct {
	matrix
	// flattened matrix data. elements[i*step+j] is row i, col j
	elements []float64
	// actual offset between rows
	step int
}

/*
Returns an array of slices referencing the matrix data. Changes to
the slices effect changes to the matrix.
*/
func (A *DenseMatrix) Arrays() [][]float64 {
	a := make([][]float64, A.rows)
	for i := 0; i < A.rows; i++ {
		a[i] = A.elements[i*A.step : i*A.step+A.cols]
	}
	return a
}

/*
Returns the contents of this matrix stored into a flat array (row-major).
*/
func (A *DenseMatrix) Array() []float64 {
	if A.step == A.rows {
		return A.elements[0 : A.rows*A.cols]
	}
	a := make([]float64, A.rows*A.cols)
	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			a[i*A.cols+j] = A.elements[i*A.step+j]
		}
	}
	return a
}

func (A *DenseMatrix) rowSlice(row int) []float64 {
	return A.elements[row*A.step : row*A.step+A.cols]
}

/*
Get the element in the ith row and jth column.
*/
func (A *DenseMatrix) Get(i int, j int) (v float64) {
	/*
		i = i % A.rows
		if i < 0 {
			i = A.rows - i
		}
		j = j % A.cols
		if j < 0 {
			j = A.cols - j
		}
	*/

	// reslicing like this does efficient range checks, perhaps
	v = A.elements[i*A.step : i*A.step+A.cols][j]
	//v = A.elements[i*A.step+j]
	return
}

/*
Set the element in the ith row and jth column to v.
*/
func (A *DenseMatrix) Set(i int, j int, v float64) {
	/*
		i = i % A.rows
		if i < 0 {
			i = A.rows - i
		}
		j = j % A.cols
		if j < 0 {
			j = A.cols - j
		}
	*/
	// reslicing like this does efficient range checks, perhaps
	A.elements[i*A.step : i*A.step+A.cols][j] = v
	//A.elements[i*A.step+j] = v
}

/*
Get a submatrix starting at i,j with rows rows and cols columns. Changes to
the returned matrix show up in the original.
*/
func (A *DenseMatrix) GetMatrix(i, j, rows, cols int) *DenseMatrix {
	B := new(DenseMatrix)
	B.elements = A.elements[i*A.step+j : i*A.step+j+(rows-1)*A.step+cols]
	B.rows = rows
	B.cols = cols
	B.step = A.step
	return B
}

/*
Copy B into A, with B's 0, 0 aligning with A's i, j
*/
func (A *DenseMatrix) SetMatrix(i, j int, B *DenseMatrix) {
	for r := 0; r < B.rows; r++ {
		for c := 0; c < B.cols; c++ {
			A.Set(i+r, j+c, B.Get(r, c))
		}
	}
}

func (A *DenseMatrix) GetColVector(j int) *DenseMatrix {
	return A.GetMatrix(0, j, A.rows, 1)
}

func (A *DenseMatrix) GetRowVector(i int) *DenseMatrix {
	return A.GetMatrix(i, 0, 1, A.cols)
}

/*
Get a copy of this matrix with 0s above the diagonal.
*/
func (A *DenseMatrix) L() *DenseMatrix {
	B := A.Copy()
	for i := 0; i < A.rows; i++ {
		for j := i + 1; j < A.cols; j++ {
			B.Set(i, j, 0)
		}
	}
	return B
}

/*
Get a copy of this matrix with 0s below the diagonal.
*/
func (A *DenseMatrix) U() *DenseMatrix {
	B := A.Copy()
	for i := 0; i < A.rows; i++ {
		for j := 0; j < i && j < A.cols; j++ {
			B.Set(i, j, 0)
		}
	}
	return B
}

func (A *DenseMatrix) Copy() *DenseMatrix {
	B := new(DenseMatrix)
	B.rows = A.rows
	B.cols = A.cols
	B.step = A.cols
	B.elements = make([]float64, B.rows*B.cols)
	for row := 0; row < B.rows; row++ {
		copy(B.rowSlice(row), A.rowSlice(row))
	}
	return B
}

/*
Get a new matrix [A B].
*/
func (A *DenseMatrix) Augment(B *DenseMatrix) (C *DenseMatrix, err error) {
	if A.rows != B.rows {
		err = ErrorDimensionMismatch
		return
	}
	C = Zeros(A.rows, A.cols+B.cols)
	err = A.AugmentFill(B, C)
	return
}
func (A *DenseMatrix) AugmentFill(B, C *DenseMatrix) (err error) {
	if A.rows != B.rows || C.rows != A.rows || C.cols != A.cols+B.cols {
		err = ErrorDimensionMismatch
		return
	}
	C.SetMatrix(0, 0, A)
	C.SetMatrix(0, A.cols, B)
	/*
		for i := 0; i < C.Rows(); i++ {
			for j := 0; j < A.Cols(); j++ {
				C.Set(i, j, A.Get(i, j))
			}
			for j := 0; j < B.Cols(); j++ {
				C.Set(i, j+A.Cols(), B.Get(i, j))
			}
		}*/
	return
}

/*
Get a new matrix [A; B], with A above B.
*/
func (A *DenseMatrix) Stack(B *DenseMatrix) (C *DenseMatrix, err error) {
	if A.cols != B.cols {
		err = ErrorDimensionMismatch
		return
	}
	C = Zeros(A.rows+B.rows, A.cols)
	err = A.StackFill(B, C)
	return
}
func (A *DenseMatrix) StackFill(B, C *DenseMatrix) (err error) {
	if A.cols != B.cols || C.cols != A.cols || C.rows != A.rows+B.rows {
		err = ErrorDimensionMismatch
		return
	}
	C.SetMatrix(0, 0, A)
	C.SetMatrix(A.rows, 0, B)
	/*
		for j := 0; j < A.cols; j++ {
			for i := 0; i < A.Rows(); i++ {
				C.Set(i, j, A.Get(i, j))
			}
			for i := 0; i < B.cols; i++ {
				C.Set(i+A.rows, j, B.Get(i, j))
			}
		}
	*/
	return
}

/*
Create a sparse matrix copy.
*/
func (A *DenseMatrix) SparseMatrix() *SparseMatrix {
	B := ZerosSparse(A.rows, A.cols)
	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			v := A.Get(i, j)
			if v != 0 {
				B.Set(i, j, v)
			}
		}
	}
	return B
}

func (A *DenseMatrix) DenseMatrix() *DenseMatrix {
	return A.Copy()
}

func Zeros(rows, cols int) *DenseMatrix {
	A := new(DenseMatrix)
	A.elements = make([]float64, rows*cols)
	A.rows = rows
	A.cols = cols
	A.step = cols
	return A
}

func Ones(rows, cols int) *DenseMatrix {
	A := new(DenseMatrix)
	A.elements = make([]float64, rows*cols)
	A.rows = rows
	A.cols = cols
	A.step = cols

	for i := 0; i < len(A.elements); i++ {
		A.elements[i] = 1
	}

	return A
}

func Numbers(rows, cols int, num float64) *DenseMatrix {
	A := Zeros(rows, cols)

	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			A.Set(i, j, num)
		}
	}

	return A
}

/*
Create an identity matrix with span rows and span columns.
*/
func Eye(span int) *DenseMatrix {
	A := Zeros(span, span)
	for i := 0; i < span; i++ {
		A.Set(i, i, 1)
	}
	return A
}

func Normals(rows, cols int) *DenseMatrix {
	A := Zeros(rows, cols)

	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			A.Set(i, j, rand.NormFloat64())
		}
	}

	return A
}

func Diagonal(d []float64) *DenseMatrix {
	n := len(d)
	A := Zeros(n, n)
	for i := 0; i < n; i++ {
		A.Set(i, i, d[i])
	}
	return A
}

func MakeDenseCopy(A MatrixRO) *DenseMatrix {
	B := Zeros(A.Rows(), A.Cols())
	for i := 0; i < B.rows; i++ {
		for j := 0; j < B.cols; j++ {
			B.Set(i, j, A.Get(i, j))
		}
	}
	return B
}

func MakeDenseMatrix(elements []float64, rows, cols int) *DenseMatrix {
	A := new(DenseMatrix)
	A.rows = rows
	A.cols = cols
	A.step = cols
	A.elements = elements
	return A
}

func MakeDenseMatrixStacked(data [][]float64) *DenseMatrix {
	rows := len(data)
	cols := len(data[0])
	elements := make([]float64, rows*cols)
	for i := 0; i < rows; i++ {
		for j := 0; j < cols; j++ {
			elements[i*cols+j] = data[i][j]
		}
	}
	return MakeDenseMatrix(elements, rows, cols)
}

func (A *DenseMatrix) String() string { return String(A) }


================================================
FILE: dense_arithmetic.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "runtime"

func (A *DenseMatrix) Plus(B MatrixRO) (Matrix, error) {
	C := A.Copy()
	err := C.Add(B)
	return C, err
}
func (A *DenseMatrix) PlusDense(B *DenseMatrix) (*DenseMatrix, error) {
	C := A.Copy()
	err := C.AddDense(B)
	return C, err
}

func (A *DenseMatrix) Minus(B MatrixRO) (Matrix, error) {
	C := A.Copy()
	err := C.Subtract(B)
	return C, err
}

func (A *DenseMatrix) MinusDense(B *DenseMatrix) (*DenseMatrix, error) {
	C := A.Copy()
	err := C.SubtractDense(B)
	return C, err
}

func (A *DenseMatrix) Add(B MatrixRO) error {
	if A.cols != B.Cols() || A.rows != B.Rows() {
		return ErrorDimensionMismatch
	}

	for i := 0; i < A.rows; i++ {
		index := i * A.step
		for j := 0; j < A.cols; j++ {
			A.elements[index] += B.Get(i, j)
			index++
		}
	}

	return nil
}

func (A *DenseMatrix) AddDense(B *DenseMatrix) error {
	if A.cols != B.cols || A.rows != B.rows {
		return ErrorDimensionMismatch
	}

	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			A.elements[i*A.step+j] += B.elements[i*B.step+j]
		}
	}

	return nil
}

func (A *DenseMatrix) Subtract(B MatrixRO) error {
	if Bd, ok := B.(*DenseMatrix); ok {
		return A.SubtractDense(Bd)
	}

	if A.cols != B.Cols() || A.rows != B.Rows() {
		return ErrorDimensionMismatch
	}

	for i := 0; i < A.rows; i++ {
		index := i * A.step
		for j := 0; j < A.cols; j++ {
			A.elements[index] -= B.Get(i, j)
			index++
		}
	}

	return nil
}

func (A *DenseMatrix) SubtractDense(B *DenseMatrix) error {

	if A.cols != B.cols || A.rows != B.rows {
		return ErrorDimensionMismatch
	}

	for i := 0; i < A.rows; i++ {
		indexA := i * A.step
		indexB := i * B.step

		for j := 0; j < A.cols; j++ {
			A.elements[indexA] -= B.elements[indexB]
			indexA++
			indexB++
		}
	}

	return nil
}

func (A *DenseMatrix) Times(B MatrixRO) (Matrix, error) {

	if Bd, ok := B.(*DenseMatrix); ok {
		return A.TimesDense(Bd)
	}

	if A.cols != B.Rows() {
		return nil, ErrorDimensionMismatch
	}
	C := Zeros(A.rows, B.Cols())

	for i := 0; i < A.rows; i++ {
		for j := 0; j < B.Cols(); j++ {
			sum := float64(0)
			for k := 0; k < A.cols; k++ {
				sum += A.elements[i*A.step+k] * B.Get(k, j)
			}
			C.elements[i*C.step+j] = sum
		}
	}

	return C, nil
}

type parJob struct {
	start, finish int
}

func parTimes1(A, B, C *DenseMatrix) {
	C = Zeros(A.rows, B.cols)

	mp := runtime.GOMAXPROCS(0)

	jobChan := make(chan box, 1+mp)

	go func() {
		rowCount := A.rows / mp
		for startRow := 0; startRow < A.rows; startRow += rowCount {
			start := startRow
			finish := startRow + rowCount
			if finish >= A.rows {
				finish = A.rows
			}
			jobChan <- parJob{start: start, finish: finish}
		}
		close(jobChan)
	}()

	wait := parFor(jobChan, func(iBox box) {
		job := iBox.(parJob)
		for i := job.start; i < job.finish; i++ {
			sums := C.elements[i*C.step : (i+1)*C.step]
			for k := 0; k < A.cols; k++ {
				for j := 0; j < B.cols; j++ {
					sums[j] += A.elements[i*A.step+k] * B.elements[k*B.step+j]
				}
			}
		}
	})
	wait()

	return
}

//this is an adaptation of code from a go-nuts post made by Dmitriy Vyukov
func parTimes2(A, B, C *DenseMatrix) {
	const threshold = 8

	currentGoroutineCount := 1
	maxGoroutines := runtime.GOMAXPROCS(0) + 2

	var aux func(sync chan bool, A, B, C *DenseMatrix, rs, re, cs, ce, ks, ke int)
	aux = func(sync chan bool, A, B, C *DenseMatrix, rs, re, cs, ce, ks, ke int) {
		dr := re - rs
		dc := ce - cs
		dk := ke - ks
		switch {
		case currentGoroutineCount < maxGoroutines && dr >= dc && dr >= dk && dr >= threshold:
			sync0 := make(chan bool, 1)
			rm := (rs + re) / 2
			currentGoroutineCount++
			go aux(sync0, A, B, C, rs, rm, cs, ce, ks, ke)
			aux(nil, A, B, C, rm, re, cs, ce, ks, ke)
			<-sync0
			currentGoroutineCount--
		case currentGoroutineCount < maxGoroutines && dc >= dk && dc >= dr && dc >= threshold:
			sync0 := make(chan bool, 1)
			cm := (cs + ce) / 2
			currentGoroutineCount++
			go aux(sync0, A, B, C, rs, re, cs, cm, ks, ke)
			aux(nil, A, B, C, rs, re, cm, ce, ks, ke)
			<-sync0
			currentGoroutineCount--
		case currentGoroutineCount < maxGoroutines && dk >= dc && dk >= dr && dk >= threshold:
			km := (ks + ke) / 2
			aux(nil, A, B, C, rs, re, cs, ce, ks, km)
			aux(nil, A, B, C, rs, re, cs, ce, km, ke)
		default:
			for row := rs; row < re; row++ {
				sums := C.elements[row*C.step : (row+1)*C.step]
				for k := ks; k < ke; k++ {
					for col := cs; col < ce; col++ {
						sums[col] += A.elements[row*A.step+k] * B.elements[k*B.step+col]
					}
				}
			}
		}
		if sync != nil {
			sync <- true
		}
	}

	aux(nil, A, B, C, 0, A.rows, 0, B.cols, 0, A.cols)

	return
}

var (
	WhichParMethod  = 2
	WhichSyncMethod = 1
)

func (A *DenseMatrix) TimesDense(B *DenseMatrix) (C *DenseMatrix, err error) {
	C = Zeros(A.rows, B.cols)
	err = A.TimesDenseFill(B, C)
	return
}
func (A *DenseMatrix) TimesDenseFill(B, C *DenseMatrix) (err error) {
	if C.rows != A.rows || C.cols != B.cols || A.cols != B.rows {
		err = ErrorDimensionMismatch
		return
	}
	if WhichParMethod > 0 && runtime.GOMAXPROCS(0) > 1 {
		switch WhichParMethod {
		case 1:
			parTimes1(A, B, C)
		case 2:
			parTimes2(A, B, C)
		}
	} else {
		switch {
		case A.cols > 100 && WhichSyncMethod == 2:
			transposeTimes(A, B, C)
		default:
			for i := 0; i < A.rows; i++ {
				sums := C.elements[i*C.step : (i+1)*C.step]
				for k, a := range A.elements[i*A.step : i*A.step + A.cols] {
					for j, b := range B.elements[k*B.step : k * B.step + B.cols] {
						sums[j] += a * b
					}
				}
			}
		}
	}

	return
}

func transposeTimes(A, B, C *DenseMatrix) {
	Bt := B.Transpose()

	Bcols := Bt.Arrays()

	for i := 0; i < A.rows; i++ {
		Arow := A.elements[i*A.step : i*A.step+A.cols]
		for j := 0; j < B.cols; j++ {
			Bcol := Bcols[j]
			for k := range Arow {
				C.elements[i*C.step+j] += Arow[k] * Bcol[k]
			}
		}
	}

	return
}

func (A *DenseMatrix) ElementMult(B MatrixRO) (Matrix, error) {
	C := A.Copy()
	err := C.ScaleMatrix(B)
	return C, err
}

func (A *DenseMatrix) ElementMultDense(B *DenseMatrix) (*DenseMatrix, error) {
	C := A.Copy()
	err := C.ScaleMatrixDense(B)
	return C, err
}

func (A *DenseMatrix) Scale(f float64) {
	for i := 0; i < A.rows; i++ {
		index := i * A.step
		for j := 0; j < A.cols; j++ {
			A.elements[index] *= f
			index++
		}
	}
}

func (A *DenseMatrix) ScaleMatrix(B MatrixRO) error {
	if Bd, ok := B.(*DenseMatrix); ok {
		return A.ScaleMatrixDense(Bd)
	}

	if A.rows != B.Rows() || A.cols != B.Cols() {
		return ErrorDimensionMismatch
	}
	for i := 0; i < A.rows; i++ {
		indexA := i * A.step
		for j := 0; j < A.cols; j++ {
			A.elements[indexA] *= B.Get(i, j)
			indexA++
		}
	}
	return nil
}

func (A *DenseMatrix) ScaleMatrixDense(B *DenseMatrix) error {
	if A.rows != B.rows || A.cols != B.cols {
		return ErrorDimensionMismatch
	}
	for i := 0; i < A.rows; i++ {
		indexA := i * A.step
		indexB := i * B.step
		for j := 0; j < A.cols; j++ {
			A.elements[indexA] *= B.elements[indexB]
			indexA++
			indexB++
		}
	}
	return nil
}


================================================
FILE: dense_basic.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import (
	"math"
	"errors"
)

func (A *DenseMatrix) Symmetric() bool {
	if A.rows != A.cols {
		return false
	}
	for i := 0; i < A.rows; i++ {
		for j := 0; j < i; j++ {
			if A.Get(i, j) != A.Get(j, i) {
				return false
			}
		}
	}
	return true
}

func (m *DenseMatrix) SwapRows(r1 int, r2 int) {
	index1 := r1 * m.step
	index2 := r2 * m.step
	for j := 0; j < m.cols; j++ {
		m.elements[index1], m.elements[index2] = m.elements[index2], m.elements[index1]
		index1++
		index2++
	}
}

func (m *DenseMatrix) ScaleRow(r int, f float64) {
	index := r * m.step
	for j := 0; j < m.cols; j++ {
		m.elements[index] *= f
		index++
	}
}

func (m *DenseMatrix) ScaleAddRow(rd int, rs int, f float64) {
	indexd := rd * m.step
	indexs := rs * m.step
	for j := 0; j < m.cols; j++ {
		m.elements[indexd] += f * m.elements[indexs]
		indexd++
		indexs++
	}
}

func (A *DenseMatrix) Inverse() (*DenseMatrix, error) {
	if A.Rows() != A.Cols() {
		return nil, ErrorDimensionMismatch
	}
	aug, _ := A.Augment(Eye(A.Rows()))
	for i := 0; i < aug.Rows(); i++ {
		j := i
		for k := i; k < aug.Rows(); k++ {
			if math.Abs(aug.Get(k, i)) > math.Abs(aug.Get(j, i)) {
				j = k
			}
		}
		if j != i {
			aug.SwapRows(i, j)
		}
		if aug.Get(i, i) == 0 {
			return nil, ExceptionSingular
		}
		aug.ScaleRow(i, 1.0/aug.Get(i, i))
		for k := 0; k < aug.Rows(); k++ {
			if k == i {
				continue
			}
			aug.ScaleAddRow(k, i, -aug.Get(k, i))
		}
	}
	inv := aug.GetMatrix(0, A.Cols(), A.Rows(), A.Cols())
	return inv, nil
}

func (A *DenseMatrix) Det() float64 {
	B := A.Copy()
	P := B.LUInPlace()
	return product(B.DiagonalCopy()) * P.Det()
}

func (A *DenseMatrix) Trace() float64 { return sum(A.DiagonalCopy()) }

func (A *DenseMatrix) OneNorm() (ε float64) {
	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			ε = max(ε, A.Get(i, j))
		}
	}
	return
}

func (A *DenseMatrix) TwoNorm() float64 {
	var sum float64 = 0
	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			v := A.elements[i*A.step+j]
			sum += v * v
		}
	}
	return math.Sqrt(sum)
}

func (A *DenseMatrix) InfinityNorm() (ε float64) {
	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			ε += A.Get(i, j)
		}
	}
	return
}

func (A *DenseMatrix) Transpose() *DenseMatrix {
	B := Zeros(A.Cols(), A.Rows())
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			B.Set(j, i, A.Get(i, j))
		}
	}
	return B
}

func (A *DenseMatrix) TransposeInPlace() (err error) {
	if A.rows != A.cols {
		err = errors.New("Can only transpose a square matrix in place")
		return
	}
	for i := 0; i < A.rows; i++ {
		for j := 0; j < i; j++ {
			tmp := A.Get(i, j)
			A.Set(i, j, A.Get(j, i))
			A.Set(j, i, tmp)
		}
	}
	return
}

func solveLower(A *DenseMatrix, b Matrix) *DenseMatrix {
	x := make([]float64, A.Cols())
	for i := 0; i < A.Rows(); i++ {
		x[i] = b.Get(i, 0)
		for j := 0; j < i; j++ {
			x[i] -= x[j] * A.Get(i, j)
		}
		//the diagonal defined to be ones
		//x[i] /= A.Get(i, i);
	}
	return MakeDenseMatrix(x, A.Cols(), 1)
}

func solveUpper(A *DenseMatrix, b Matrix) *DenseMatrix {
	x := make([]float64, A.Cols())
	for i := A.Rows() - 1; i >= 0; i-- {
		x[i] = b.Get(i, 0)
		for j := i + 1; j < A.Cols(); j++ {
			x[i] -= x[j] * A.Get(i, j)
		}
		x[i] /= A.Get(i, i)
	}
	return MakeDenseMatrix(x, A.Cols(), 1)
}

func (A *DenseMatrix) Solve(b MatrixRO) (*DenseMatrix, error) {
	Acopy := A.Copy()
	P := Acopy.LUInPlace()
	Pinv := P.Inverse()
	pb, err := Pinv.Times(b)

	if !(err == nil) {
		return nil, err
	}

	y := solveLower(Acopy, pb)
	x := solveUpper(Acopy, y)
	return x, nil
}

func (A *DenseMatrix) SolveDense(b *DenseMatrix) (*DenseMatrix, error) {
	return A.Solve(b)
}


================================================
FILE: dense_data.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

//returns a copy of the row (not a slice)
func (A *DenseMatrix) RowCopy(i int) []float64 {
	row := make([]float64, A.cols)
	for j := 0; j < A.cols; j++ {
		row[j] = A.Get(i, j)
	}
	return row
}

//returns a copy of the column (not a slice)
func (A *DenseMatrix) ColCopy(j int) []float64 {
	col := make([]float64, A.rows)
	for i := 0; i < A.rows; i++ {
		col[i] = A.Get(i, j)
	}
	return col
}

//returns a copy of the diagonal (not a slice)
func (A *DenseMatrix) DiagonalCopy() []float64 {
	span := A.rows
	if A.cols < span {
		span = A.cols
	}
	diag := make([]float64, span)
	for i := 0; i < span; i++ {
		diag[i] = A.Get(i, i)
	}
	return diag
}

func (A *DenseMatrix) BufferRow(i int, buf []float64) {
	for j := 0; j < A.cols; j++ {
		buf[j] = A.Get(i, j)
	}
}

func (A *DenseMatrix) BufferCol(j int, buf []float64) {
	for i := 0; i < A.rows; i++ {
		buf[i] = A.Get(i, j)
	}
}

func (A *DenseMatrix) BufferDiagonal(buf []float64) {
	for i := 0; i < A.rows && i < A.cols; i++ {
		buf[i] = A.Get(i, i)
	}
}

func (A *DenseMatrix) FillRow(i int, buf []float64) {
	for j := 0; j < A.cols; j++ {
		A.Set(i, j, buf[j])
	}
}

func (A *DenseMatrix) FillCol(j int, buf []float64) {
	for i := 0; i < A.rows; i++ {
		A.Set(i, j, buf[i])
	}
}

func (A *DenseMatrix) FillDiagonal(buf []float64) {
	for i := 0; i < A.rows && i < A.cols; i++ {
		A.Set(i, i, buf[i])
	}
}


================================================
FILE: dense_decomp.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "math"

/*
Returns the cholesky decomposition C of A, st CC'=A.
*/
func (A *DenseMatrix) Cholesky() (L *DenseMatrix, err error) {
	n := A.Rows()
	L = Zeros(n, n)
	isspd := A.Cols() == n

	for j := 0; j < n; j++ {
		Lrowj := L.RowCopy(j)
		d := float64(0)
		for k := 0; k < j; k++ {
			Lrowk := L.RowCopy(k)
			s := float64(0)
			for i := 0; i < k; i++ {
				s += Lrowk[i] * Lrowj[i]
			}
			s = (A.Get(j, k) - s) / Lrowk[k]
			Lrowj[k] = s
			L.Set(j, k, s)
			d += s * s
			isspd = isspd && (A.Get(k, j) == A.Get(j, k))
		}
		d = A.Get(j, j) - d
		isspd = isspd && (d > 0.0)
		L.Set(j, j, math.Sqrt(max(d, float64(0))))
		for k := j + 1; k < n; k++ {
			L.Set(j, k, 0)
		}
	}

	if !isspd {
		err = ExceptionNotSPD
	}

	return
}

/*
return L,U,P, st PLU=A.
*/
func (A *DenseMatrix) LU() (L, U *DenseMatrix, P *PivotMatrix) {
	m := A.Rows()
	n := A.Cols()
	C := A.Copy()

	P = C.LUInPlace()

	L = C.L()
	for i := 0; i < m && i < n; i++ {
		L.Set(i, i, 1)
	}
	U = C.U()

	return
}

/*
Overwrites A with [L\U] and returns P, st PLU=A. L is considered to
have 1s in the diagonal.
*/
func (A *DenseMatrix) LUInPlace() (P *PivotMatrix) {
	m := A.Rows()
	n := A.Cols()
	LUcolj := make([]float64, m)
	LUrowi := make([]float64, n)
	piv := make([]int, m)
	for i := 0; i < m; i++ {
		piv[i] = i
	}
	pivsign := float64(1.0)

	for j := 0; j < n; j++ {
		A.BufferCol(j, LUcolj)
		for i := 0; i < m; i++ {
			A.BufferRow(i, LUrowi)
			kmax := i
			if j < i {
				kmax = j
			}
			s := float64(0)
			for k := 0; k < kmax; k++ {
				s += LUrowi[k] * LUcolj[k]
			}
			LUcolj[i] -= s
			LUrowi[j] = LUcolj[i]
			A.Set(i, j, LUrowi[j])
		}

		p := j
		for i := j + 1; i < m; i++ {
			if math.Abs(LUcolj[i]) > math.Abs(LUcolj[p]) {
				p = i
			}
		}
		if p != j {
			A.SwapRows(p, j)
			k := piv[p]
			piv[p] = piv[j]
			piv[j] = k
			pivsign = -pivsign
		}

		if j < m && A.Get(j, j) != 0 {
			for i := j + 1; i < m; i++ {
				A.Set(i, j, A.Get(i, j)/A.Get(j, j))
			}
		}
	}

	P = MakePivotMatrix(piv, pivsign)

	return
}

func (A *DenseMatrix) QR() (Q, R *DenseMatrix) {
	m := A.Rows()
	n := A.Cols()
	QR := A.Copy()
	Q = Zeros(m, n)
	R = Zeros(m, n)
	i, j, k := 0, 0, 0
	norm := float64(0.0)
	s := float64(0.0)

	for k = 0; k < n; k++ {
		norm = 0
		for i = k; i < m; i++ {
			norm = math.Hypot(norm, QR.Get(i, k))
		}

		if norm != 0.0 {
			if QR.Get(k, k) < 0 {
				norm = -norm
			}

			for i = k; i < m; i++ {
				QR.Set(i, k, QR.Get(i, k)/norm)
			}
			QR.Set(k, k, QR.Get(k, k)+1.0)

			for j = k + 1; j < n; j++ {
				s = 0.0
				for i = k; i < m; i++ {
					s += QR.Get(i, k) * QR.Get(i, j)
				}
				s = -s / QR.Get(k, k)
				for i = k; i < m; i++ {
					QR.Set(i, j, QR.Get(i, j)+s*QR.Get(i, k))

					if i < j {
						R.Set(i, j, QR.Get(i, j))
					}
				}

			}
		}

		R.Set(k, k, -norm)

	}

	//Q Matrix:
	i, j, k = 0, 0, 0

	for k = n - 1; k >= 0; k-- {
		Q.Set(k, k, 1.0)
		for j = k; j < n; j++ {
			if QR.Get(k, k) != 0 {
				s = 0.0
				for i = k; i < m; i++ {
					s += QR.Get(i, k) * Q.Get(i, j)
				}
				s = -s / QR.Get(k, k)
				for i = k; i < m; i++ {
					Q.Set(i, j, Q.Get(i, j)+s*QR.Get(i, k))
				}
			}
		}
	}

	return
}


================================================
FILE: dense_eigen.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "math"

/*
Returns V,D st V*D*inv(V) = A and D is diagonal (or block diagonal).
*/
func (A *DenseMatrix) Eigen() (V, D *DenseMatrix, err error) {
	//code translated/ripped off from Jama
	if A.cols != A.rows {
		err = ErrorDimensionMismatch
		return
	}
	n := A.cols
	Va := A.Copy().Arrays()
	d := make([]float64, n)
	e := make([]float64, n)
	if A.Symmetric() {

		tred2(Va[0:n], d[0:n], e[0:n]) //pass slices so they're references

		tql2(Va[0:n], d[0:n], e[0:n])
	} else {
		H := A.GetMatrix(0, 0, n, n).Copy().Arrays()
		ort := make([]float64, n)

		// Reduce to Hessenberg form.
		orthes(Va[0:n], d[0:n], e[0:n], H[0:n], ort[0:n])

		// Reduce Hessenberg to real Schur form.
		hqr2(Va[0:n], d[0:n], e[0:n], H[0:n], ort[0:n])
	}
	V, D = MakeDenseMatrixStacked(Va), makeD(d, e)
	return
}

func makeD(d []float64, e []float64) *DenseMatrix {
	n := len(d)
	X := Zeros(n, n)
	D := X.Arrays()
	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			D[i][j] = 0.0
		}
		D[i][i] = d[i]
		if e[i] > 0 {
			D[i][i+1] = e[i]
		} else if e[i] < 0 {
			D[i][i-1] = e[i]
		}
	}
	return X
}

func tred2(V [][]float64, d []float64, e []float64) {
	n := len(V)

	//  This is derived from the Algol procedures tred2 by
	//  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
	//  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
	//  Fortran subroutine in EISPACK.

	for j := 0; j < n; j++ {
		d[j] = V[n-1][j]
	}

	// Householder reduction to tridiagonal form.

	for i := n - 1; i > 0; i-- {

		// Scale to avoid under/overflow.

		scale := float64(0)
		h := float64(0)
		for k := 0; k < i; k++ {
			scale = scale + math.Abs(d[k])
		}
		if scale == 0.0 {
			e[i] = d[i-1]
			for j := 0; j < i; j++ {
				d[j] = V[i-1][j]
				V[i][j] = 0.0
				V[j][i] = 0.0
			}
		} else {

			// Generate Householder vector.

			for k := 0; k < i; k++ {
				d[k] /= scale
				h += d[k] * d[k]
			}
			f := d[i-1]
			g := math.Sqrt(h)
			if f > 0 {
				g = -g
			}
			e[i] = scale * g
			h = h - f*g
			d[i-1] = f - g
			for j := 0; j < i; j++ {
				e[j] = 0.0
			}
			// Apply similarity transformation to remaining columns.

			for j := 0; j < i; j++ {
				f = d[j]
				V[j][i] = f
				g = e[j] + V[j][j]*f
				for k := j + 1; k <= i-1; k++ {
					g += V[k][j] * d[k]
					e[k] += V[k][j] * f
				}
				e[j] = g
			}

			f = 0.0
			for j := 0; j < i; j++ {
				e[j] /= h
				f += e[j] * d[j]
			}
			hh := f / (h + h)
			for j := 0; j < i; j++ {
				e[j] -= hh * d[j]
			}

			for j := 0; j < i; j++ {
				f = d[j]
				g = e[j]
				for k := j; k <= i-1; k++ {
					V[k][j] -= (f*e[k] + g*d[k])
				}
				d[j] = V[i-1][j]
				V[i][j] = 0.0
			}
		}
		d[i] = h
	}

	// Accumulate transformations.

	for i := 0; i < n-1; i++ {
		V[n-1][i] = V[i][i]
		V[i][i] = 1.0
		h := d[i+1]
		if h != 0.0 {
			for k := 0; k <= i; k++ {
				d[k] = V[k][i+1] / h
			}
			for j := 0; j <= i; j++ {
				g := float64(0)
				for k := 0; k <= i; k++ {
					g += V[k][i+1] * V[k][j]
				}
				for k := 0; k <= i; k++ {
					V[k][j] -= g * d[k]
				}
			}
		}
		for k := 0; k <= i; k++ {
			V[k][i+1] = 0.0
		}
	}
	for j := 0; j < n; j++ {
		d[j] = V[n-1][j]
		V[n-1][j] = 0.0
	}
	V[n-1][n-1] = 1.0
	e[0] = 0.0
}

func tql2(V [][]float64, d []float64, e []float64) {

	//  This is derived from the Algol procedures tql2, by
	//  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
	//  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
	//  Fortran subroutine in EISPACK.

	n := len(V)

	for i := 1; i < n; i++ {
		e[i-1] = e[i]
	}
	e[n-1] = 0.0

	f := float64(0)
	tst1 := float64(0)
	eps := math.Pow(2.0, -52.0)
	for l := 0; l < n; l++ {

		// Find small subdiagonal element

		tst1 = max(tst1, math.Abs(d[l])+math.Abs(e[l]))
		m := l
		for m < n {
			if math.Abs(e[m]) <= eps*tst1 {
				break
			}
			m++
		}

		// If m == l, d[l] is an eigenvalue,
		// otherwise, iterate.

		if m > l {
			iter := 0
			for true {
				iter = iter + 1 // (Could check iteration count here.)

				// Compute implicit shift

				g := d[l]
				p := (d[l+1] - g) / (2.0 * e[l])
				r := math.Sqrt(p*p + 1.0)
				if p < 0 {
					r = -r
				}
				d[l] = e[l] / (p + r)
				d[l+1] = e[l] * (p + r)
				dl1 := d[l+1]
				h := g - d[l]
				for i := l + 2; i < n; i++ {
					d[i] -= h
				}
				f = f + h

				// Implicit QL transformation.

				p = d[m]
				c := float64(1)
				c2 := c
				c3 := c
				el1 := e[l+1]
				s := float64(0)
				s2 := float64(0)
				for i := m - 1; i >= l; i-- {
					c3 = c2
					c2 = c
					s2 = s
					g = c * e[i]
					h = c * p
					r = math.Sqrt(p*p + e[i]*e[i])
					e[i+1] = s * r
					s = e[i] / r
					c = p / r
					p = c*d[i] - s*g
					d[i+1] = h + s*(c*g+s*d[i])

					// Accumulate transformation.

					for k := 0; k < n; k++ {
						h = V[k][i+1]
						V[k][i+1] = s*V[k][i] + c*h
						V[k][i] = c*V[k][i] - s*h
					}
				}
				p = -s * s2 * c3 * el1 * e[l] / dl1
				e[l] = s * p
				d[l] = c * p

				// Check for convergence.
				if !(math.Abs(e[l]) > eps*tst1) {
					break
				}
			}
		}
		d[l] = d[l] + f
		e[l] = 0.0
	}

	// Sort eigenvalues and corresponding vectors.

	for i := 0; i < n-1; i++ {
		k := i
		p := d[i]
		for j := i + 1; j < n; j++ {
			if d[j] < p {
				k = j
				p = d[j]
			}
		}
		if k != i {
			d[k] = d[i]
			d[i] = p
			for j := 0; j < n; j++ {
				p = V[j][i]
				V[j][i] = V[j][k]
				V[j][k] = p
			}
		}
	}
}

func orthes(V [][]float64, d []float64, e []float64, H [][]float64, ort []float64) {

	//  This is derived from the Algol procedures orthes and ortran,
	//  by Martin and Wilkinson, Handbook for Auto. Comp.,
	//  Vol.ii-Linear Algebra, and the corresponding
	//  Fortran subroutines in EISPACK.

	n := len(V)

	low := 0
	high := n - 1

	for m := low + 1; m <= high-1; m++ {

		// Scale column.

		scale := float64(0)
		for i := m; i <= high; i++ {
			scale = scale + math.Abs(H[i][m-1])
		}
		if scale != 0.0 {

			// Compute Householder transformation.

			h := float64(0)
			for i := high; i >= m; i-- {
				ort[i] = H[i][m-1] / scale
				h += ort[i] * ort[i]
			}
			g := math.Sqrt(h)
			if ort[m] > 0 {
				g = -g
			}
			h = h - ort[m]*g
			ort[m] = ort[m] - g

			// Apply Householder similarity transformation
			// H = (I-u*u'/h)*H*(I-u*u')/h)

			for j := m; j < n; j++ {
				f := float64(0)
				for i := high; i >= m; i-- {
					f += ort[i] * H[i][j]
				}
				f = f / h
				for i := m; i <= high; i++ {
					H[i][j] -= f * ort[i]
				}
			}

			for i := 0; i <= high; i++ {
				f := float64(0)
				for j := high; j >= m; j-- {
					f += ort[j] * H[i][j]
				}
				f = f / h
				for j := m; j <= high; j++ {
					H[i][j] -= f * ort[j]
				}
			}
			ort[m] = scale * ort[m]
			H[m][m-1] = scale * g
		}
	}

	// Accumulate transformations (Algol's ortran).

	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			if i == j {
				V[i][j] = 1
			} else {
				V[i][j] = 0
			}
		}
	}

	for m := high - 1; m >= low+1; m-- {
		if H[m][m-1] != 0.0 {
			for i := m + 1; i <= high; i++ {
				ort[i] = H[i][m-1]
			}
			for j := m; j <= high; j++ {
				g := float64(0)
				for i := m; i <= high; i++ {
					g += ort[i] * V[i][j]
				}
				// Double division avoids possible underflow
				g = (g / ort[m]) / H[m][m-1]
				for i := m; i <= high; i++ {
					V[i][j] += g * ort[i]
				}
			}
		}
	}
}

func hqr2(V [][]float64, d []float64, e []float64, H [][]float64, ort []float64) {

	//  This is derived from the Algol procedure hqr2,
	//  by Martin and Wilkinson, Handbook for Auto. Comp.,
	//  Vol.ii-Linear Algebra, and the corresponding
	//  Fortran subroutine in EISPACK.

	// Initialize

	n := len(V)

	nn := n
	n = nn - 1
	low := 0
	high := nn - 1
	eps := math.Pow(2.0, -52.0)
	exshift := float64(0)
	p := float64(0)
	q := float64(0)
	r := float64(0)
	s := float64(0)
	z := float64(0)
	var t, w, x, y float64

	// Store roots isolated by balanc and compute matrix norm

	norm := float64(0)
	for i := 0; i < nn; i++ {
		if i < low || i > high {
			d[i] = H[i][i]
			e[i] = 0.0
		}
		for j := int(max(float64(i)-1, 0)); j < nn; j++ {
			norm = norm + math.Abs(H[i][j])
		}
	}

	// Outer loop over eigenvalue index

	iter := 0
	for n >= low {

		// Look for single small sub-diagonal element

		l := n
		for l > low {
			s = math.Abs(H[l-1][l-1]) + math.Abs(H[l][l])
			if s == 0.0 {
				s = norm
			}
			if math.Abs(H[l][l-1]) < eps*s {
				break
			}
			l--
		}

		// Check for convergence
		// One root found

		if l == n {
			H[n][n] = H[n][n] + exshift
			d[n] = H[n][n]
			e[n] = 0.0
			n--
			iter = 0

			// Two roots found

		} else if l == n-1 {
			w = H[n][n-1] * H[n-1][n]
			p = (H[n-1][n-1] - H[n][n]) / 2.0
			q = p*p + w
			z = math.Sqrt(math.Abs(q))
			H[n][n] = H[n][n] + exshift
			H[n-1][n-1] = H[n-1][n-1] + exshift
			x = H[n][n]

			// Real pair

			if q >= 0 {
				if p >= 0 {
					z = p + z
				} else {
					z = p - z
				}
				d[n-1] = x + z
				d[n] = d[n-1]
				if z != 0.0 {
					d[n] = x - w/z
				}
				e[n-1] = 0.0
				e[n] = 0.0
				x = H[n][n-1]
				s = math.Abs(x) + math.Abs(z)
				p = x / s
				q = z / s
				r = math.Sqrt(p*p + q*q)
				p = p / r
				q = q / r

				// Row modification

				for j := n - 1; j < nn; j++ {
					z = H[n-1][j]
					H[n-1][j] = q*z + p*H[n][j]
					H[n][j] = q*H[n][j] - p*z
				}

				// Column modification

				for i := 0; i <= n; i++ {
					z = H[i][n-1]
					H[i][n-1] = q*z + p*H[i][n]
					H[i][n] = q*H[i][n] - p*z
				}

				// Accumulate transformations

				for i := low; i <= high; i++ {
					z = V[i][n-1]
					V[i][n-1] = q*z + p*V[i][n]
					V[i][n] = q*V[i][n] - p*z
				}

				// Complex pair

			} else {
				d[n-1] = x + p
				d[n] = x + p
				e[n-1] = z
				e[n] = -z
			}
			n = n - 2
			iter = 0

			// No convergence yet

		} else {

			// Form shift

			x = H[n][n]
			y = 0.0
			w = 0.0
			if l < n {
				y = H[n-1][n-1]
				w = H[n][n-1] * H[n-1][n]
			}

			// Wilkinson's original ad hoc shift

			if iter == 10 {
				exshift += x
				for i := low; i <= n; i++ {
					H[i][i] -= x
				}
				s = math.Abs(H[n][n-1]) + math.Abs(H[n-1][n-2])
				y = 0.75 * s
				x = y
				w = -0.4375 * s * s
			}

			// MATLAB's new ad hoc shift

			if iter == 30 {
				s = (y - x) / 2.0
				s = s*s + w
				if s > 0 {
					s = math.Sqrt(s)
					if y < x {
						s = -s
					}
					s = x - w/((y-x)/2.0+s)
					for i := low; i <= n; i++ {
						H[i][i] -= s
					}
					exshift += s
					w = 0.964
					y = w
					x = y
				}
			}

			iter = iter + 1 // (Could check iteration count here.)

			// Look for two consecutive small sub-diagonal elements

			m := n - 2
			for m >= l {
				z = H[m][m]
				r = x - z
				s = y - z
				p = (r*s-w)/H[m+1][m] + H[m][m+1]
				q = H[m+1][m+1] - z - r - s
				r = H[m+2][m+1]
				s = math.Abs(p) + math.Abs(q) + math.Abs(r)
				p = p / s
				q = q / s
				r = r / s
				if m == l {
					break
				}
				if math.Abs(H[m][m-1])*(math.Abs(q)+math.Abs(r)) <
					eps*(math.Abs(p)*(math.Abs(H[m-1][m-1])+math.Abs(z)+
						math.Abs(H[m+1][m+1]))) {
					break
				}
				m--
			}

			for i := m + 2; i <= n; i++ {
				H[i][i-2] = 0.0
				if i > m+2 {
					H[i][i-3] = 0.0
				}
			}

			// Double QR step involving rows l:n and columns m:n

			for k := m; k <= n-1; k++ {
				notlast := (k != n-1)
				if k != m {
					p = H[k][k-1]
					q = H[k+1][k-1]
					if notlast {
						r = H[k+2][k-1]
					} else {
						r = 0
					}

					x = math.Abs(p) + math.Abs(q) + math.Abs(r)
					if x != 0.0 {
						p = p / x
						q = q / x
						r = r / x
					}
				}
				if x == 0.0 {
					break
				}
				s = math.Sqrt(p*p + q*q + r*r)
				if p < 0 {
					s = -s
				}
				if s != 0 {
					if k != m {
						H[k][k-1] = -s * x
					} else if l != m {
						H[k][k-1] = -H[k][k-1]
					}
					p = p + s
					x = p / s
					y = q / s
					z = r / s
					q = q / p
					r = r / p

					// Row modification

					for j := k; j < nn; j++ {
						p = H[k][j] + q*H[k+1][j]
						if notlast {
							p = p + r*H[k+2][j]
							H[k+2][j] = H[k+2][j] - p*z
						}
						H[k][j] = H[k][j] - p*x
						H[k+1][j] = H[k+1][j] - p*y
					}

					// Column modification

					for i := 0; i <= int(min(float64(n), float64(k)+3)); i++ {
						p = x*H[i][k] + y*H[i][k+1]
						if notlast {
							p = p + z*H[i][k+2]
							H[i][k+2] = H[i][k+2] - p*r
						}
						H[i][k] = H[i][k] - p
						H[i][k+1] = H[i][k+1] - p*q
					}

					// Accumulate transformations

					for i := low; i <= high; i++ {
						p = x*V[i][k] + y*V[i][k+1]
						if notlast {
							p = p + z*V[i][k+2]
							V[i][k+2] = V[i][k+2] - p*r
						}
						V[i][k] = V[i][k] - p
						V[i][k+1] = V[i][k+1] - p*q
					}
				} // (s != 0)
			} // k loop
		} // check convergence
	} // while (n >= low)

	// Backsubstitute to find vectors of upper triangular form

	if norm == 0.0 {
		return
	}

	for n = nn - 1; n >= 0; n-- {
		p = d[n]
		q = e[n]

		// Real vector

		if q == 0 {
			l := n
			H[n][n] = 1.0
			for i := n - 1; i >= 0; i-- {
				w = H[i][i] - p
				r = 0.0
				for j := l; j <= n; j++ {
					r = r + H[i][j]*H[j][n]
				}
				if e[i] < 0.0 {
					z = w
					s = r
				} else {
					l = i
					if e[i] == 0.0 {
						if w != 0.0 {
							H[i][n] = -r / w
						} else {
							H[i][n] = -r / (eps * norm)
						}

						// Solve real equations

					} else {
						x = H[i][i+1]
						y = H[i+1][i]
						q = (d[i]-p)*(d[i]-p) + e[i]*e[i]
						t = (x*s - z*r) / q
						H[i][n] = t
						if math.Abs(x) > math.Abs(z) {
							H[i+1][n] = (-r - w*t) / x
						} else {
							H[i+1][n] = (-s - y*t) / z
						}
					}

					// Overflow control

					t = math.Abs(H[i][n])
					if (eps*t)*t > 1 {
						for j := i; j <= n; j++ {
							H[j][n] = H[j][n] / t
						}
					}
				}
			}

			// Complex vector

		} else if q < 0 {
			l := n - 1

			// Last vector component imaginary so matrix is triangular

			if math.Abs(H[n][n-1]) > math.Abs(H[n-1][n]) {
				H[n-1][n-1] = q / H[n][n-1]
				H[n-1][n] = -(H[n][n] - p) / H[n][n-1]
			} else {
				cdivr, cdivi := cdiv(0.0, -H[n-1][n], H[n-1][n-1]-p, q)
				H[n-1][n-1] = cdivr
				H[n-1][n] = cdivi
			}
			H[n][n-1] = 0.0
			H[n][n] = 1.0
			for i := n - 2; i >= 0; i-- {
				var ra, sa, vr, vi float64
				ra = 0.0
				sa = 0.0
				for j := l; j <= n; j++ {
					ra = ra + H[i][j]*H[j][n-1]
					sa = sa + H[i][j]*H[j][n]
				}
				w = H[i][i] - p

				if e[i] < 0.0 {
					z = w
					r = ra
					s = sa
				} else {
					l = i
					if e[i] == 0 {
						cdivr, cdivi := cdiv(-ra, -sa, w, q)
						H[i][n-1] = cdivr
						H[i][n] = cdivi
					} else {

						// Solve complex equations

						x = H[i][i+1]
						y = H[i+1][i]
						vr = (d[i]-p)*(d[i]-p) + e[i]*e[i] - q*q
						vi = (d[i] - p) * 2.0 * q
						if vr == 0.0 && vi == 0.0 {
							vr = eps * norm * (math.Abs(w) + math.Abs(q) +
								math.Abs(x) + math.Abs(y) + math.Abs(z))
						}
						cdivr, cdivi := cdiv(x*r-z*ra+q*sa, x*s-z*sa-q*ra, vr, vi)
						H[i][n-1] = cdivr
						H[i][n] = cdivi
						if math.Abs(x) > (math.Abs(z) + math.Abs(q)) {
							H[i+1][n-1] = (-ra - w*H[i][n-1] + q*H[i][n]) / x
							H[i+1][n] = (-sa - w*H[i][n] - q*H[i][n-1]) / x
						} else {
							cdiv(-r-y*H[i][n-1], -s-y*H[i][n], z, q)
							H[i+1][n-1] = cdivr
							H[i+1][n] = cdivi
						}
					}

					// Overflow control

					t = max(math.Abs(H[i][n-1]), math.Abs(H[i][n]))
					if (eps*t)*t > 1 {
						for j := i; j <= n; j++ {
							H[j][n-1] = H[j][n-1] / t
							H[j][n] = H[j][n] / t
						}
					}
				}
			}
		}
	}

	// Vectors of isolated roots

	for i := 0; i < nn; i++ {
		if i < low || i > high {
			for j := i; j < nn; j++ {
				V[i][j] = H[i][j]
			}
		}
	}

	// Back transformation to get eigenvectors of original matrix

	for j := nn - 1; j >= low; j-- {
		for i := low; i <= high; i++ {
			z = 0.0
			for k := low; k <= int(min(float64(j), float64(high))); k++ {
				z = z + V[i][k]*H[k][j]
			}
			V[i][j] = z
		}
	}
}

func cdiv(xr float64, xi float64, yr float64, yi float64) (cdivr float64, cdivi float64) {
	var r, d float64
	if math.Abs(yr) > math.Abs(yi) {
		r = yi / yr
		d = yr + r*yi
		cdivr = (xr + r*xi) / d
		cdivi = (xi - r*xr) / d
	} else {
		r = yr / yi
		d = yi + r*yr
		cdivr = (r*xr + xi) / d
		cdivi = (r*xi - xr) / d
	}
	return
}


================================================
FILE: dense_svd.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "math"

/*
Returns U, Σ, V st Σ is diagonal (or block diagonal) and UΣV'=Arg
*/
func (Arg *DenseMatrix) SVD() (theU, Σ, theV *DenseMatrix, err error) {
	//copied from Jama
	// Derived from LINPACK code.
	// Initialize.
	A := Arg.Copy().Arrays()
	m := Arg.rows
	n := Arg.cols

	/* Apparently the failing cases are only a proper subset of (m<n),
		 so let's not throw error.  Correct fix to come later?
	      if (m<n) {
		  throw new IllegalArgumentException("Jama SVD only works for m >= n"); }
	*/

	if m < n {
		err = ErrorDimensionMismatch
		return
	}

	nu := minInt(m, n)
	s := make([]float64, minInt(m+1, n))

	U := make([][]float64, m)
	for i := 0; i < m; i++ {
		U[i] = make([]float64, nu)
	}
	V := make([][]float64, n)
	for i := 0; i < n; i++ {
		V[i] = make([]float64, n)
	}

	e := make([]float64, n)
	work := make([]float64, m)
	wantu := true
	wantv := true

	// Reduce A to bidiagonal form, storing the diagonal elements
	// in s and the super-diagonal elements in e.

	nct := minInt(m-1, n)
	nrt := maxInt(0, minInt(n-2, m))
	for k := 0; k < maxInt(nct, nrt); k++ {
		if k < nct {

			// Compute the transformation for the k-th column and
			// place the k-th diagonal in s[k].
			// Compute 2-norm of k-th column without under/overflow.
			s[k] = 0
			for i := k; i < m; i++ {
				s[k] = math.Hypot(s[k], A[i][k])
			}
			if s[k] != 0.0 {
				if A[k][k] < 0.0 {
					s[k] = -s[k]
				}
				for i := k; i < m; i++ {
					A[i][k] /= s[k]
				}
				A[k][k] += 1.0
			}
			s[k] = -s[k]
		}
		for j := k + 1; j < n; j++ {
			if (k < nct) && (s[k] != 0.0) {

				// Apply the transformation.

				t := float64(0)
				for i := k; i < m; i++ {
					t += A[i][k] * A[i][j]
				}
				t = -t / A[k][k]
				for i := k; i < m; i++ {
					A[i][j] += t * A[i][k]
				}
			}

			// Place the k-th row of A into e for the
			// subsequent calculation of the row transformation.

			e[j] = A[k][j]
		}
		if wantu && (k < nct) {

			// Place the transformation in U for subsequent back
			// multiplication.

			for i := k; i < m; i++ {
				U[i][k] = A[i][k]
			}
		}
		if k < nrt {

			// Compute the k-th row transformation and place the
			// k-th super-diagonal in e[k].
			// Compute 2-norm without under/overflow.
			e[k] = 0
			for i := k + 1; i < n; i++ {
				e[k] = math.Hypot(e[k], e[i])
			}
			if e[k] != 0.0 {
				if e[k+1] < 0.0 {
					e[k] = -e[k]
				}
				for i := k + 1; i < n; i++ {
					e[i] /= e[k]
				}
				e[k+1] += 1.0
			}
			e[k] = -e[k]
			if (k+1 < m) && (e[k] != 0.0) {

				// Apply the transformation.

				for i := k + 1; i < m; i++ {
					work[i] = 0.0
				}
				for j := k + 1; j < n; j++ {
					for i := k + 1; i < m; i++ {
						work[i] += e[j] * A[i][j]
					}
				}
				for j := k + 1; j < n; j++ {
					t := -e[j] / e[k+1]
					for i := k + 1; i < m; i++ {
						A[i][j] += t * work[i]
					}
				}
			}
			if wantv {

				// Place the transformation in V for subsequent
				// back multiplication.

				for i := k + 1; i < n; i++ {
					V[i][k] = e[i]
				}
			}
		}
	}

	// Set up the final bidiagonal matrix or order p.

	p := minInt(n, m+1)
	if nct < n {
		s[nct] = A[nct][nct]
	}
	if m < p {
		s[p-1] = 0.0
	}
	if nrt+1 < p {
		e[nrt] = A[nrt][p-1]
	}
	e[p-1] = 0.0

	// If required, generate U.

	if wantu {
		for j := nct; j < nu; j++ {
			for i := 0; i < m; i++ {
				U[i][j] = 0.0
			}
			U[j][j] = 1.0
		}
		for k := nct - 1; k >= 0; k-- {
			if s[k] != 0.0 {
				for j := k + 1; j < nu; j++ {
					t := float64(0)
					for i := k; i < m; i++ {
						t += U[i][k] * U[i][j]
					}
					t = -t / U[k][k]
					for i := k; i < m; i++ {
						U[i][j] += t * U[i][k]
					}
				}
				for i := k; i < m; i++ {
					U[i][k] = -U[i][k]
				}
				U[k][k] = 1.0 + U[k][k]
				for i := 0; i < k-1; i++ {
					U[i][k] = 0.0
				}
			} else {
				for i := 0; i < m; i++ {
					U[i][k] = 0.0
				}
				U[k][k] = 1.0
			}
		}
	}

	// If required, generate V.

	if wantv {
		for k := n - 1; k >= 0; k-- {
			if (k < nrt) && (e[k] != 0.0) {
				for j := k + 1; j < nu; j++ {
					t := float64(0)
					for i := k + 1; i < n; i++ {
						t += V[i][k] * V[i][j]
					}
					t = -t / V[k+1][k]
					for i := k + 1; i < n; i++ {
						V[i][j] += t * V[i][k]
					}
				}
			}
			for i := 0; i < n; i++ {
				V[i][k] = 0.0
			}
			V[k][k] = 1.0
		}
	}

	// Main iteration loop for the singular values.

	pp := p - 1
	iter := 0
	eps := math.Pow(2.0, -52.0)
	tiny := math.Pow(2.0, -966.0)
	for p > 0 {
		var k, kase int

		// Here is where a test for too many iterations would go.

		// This section of the program inspects for
		// negligible elements in the s and e arrays.  On
		// completion the variables kase and k are set as follows.

		// kase = 1     if s(p) and e[k-1] are negligible and k<p
		// kase = 2     if s(k) is negligible and k<p
		// kase = 3     if e[k-1] is negligible, k<p, and
		//              s(k), ..., s(p) are not negligible (qr step).
		// kase = 4     if e(p-1) is negligible (convergence).

		for k = p - 2; k >= -1; k-- {
			if k == -1 {
				break
			}
			if math.Abs(e[k]) <=
				tiny+eps*(math.Abs(s[k])+math.Abs(s[k+1])) {
				e[k] = 0.0
				break
			}
		}
		if k == p-2 {
			kase = 4
		} else {
			var ks int
			for ks = p - 1; ks >= k; ks-- {
				if ks == k {
					break
				}
				t := float64(0)
				if ks != p {
					t = math.Abs(e[ks])
				}
				if ks != k+1 {
					t += math.Abs(e[ks-1])
				}
				//double t = (ks != p ? Math.abs(e[ks]) : 0.) +
				//           (ks != k+1 ? Math.abs(e[ks-1]) : 0.);
				if math.Abs(s[ks]) <= tiny+eps*t {
					s[ks] = 0.0
					break
				}
			}
			if ks == k {
				kase = 3
			} else if ks == p-1 {
				kase = 1
			} else {
				kase = 2
				k = ks
			}
		}
		k++

		// Perform the task indicated by kase.
		//fmt.Printf("kase = %d\n", kase);
		switch kase {

		// Deflate negligible s(p).

		case 1:
			{
				f := e[p-2]
				e[p-2] = 0.0
				for j := p - 2; j >= k; j-- {
					t := math.Hypot(s[j], f)
					cs := s[j] / t
					sn := f / t
					s[j] = t
					if j != k {
						f = -sn * e[j-1]
						e[j-1] = cs * e[j-1]
					}
					if wantv {
						for i := 0; i < n; i++ {
							t = cs*V[i][j] + sn*V[i][p-1]
							V[i][p-1] = -sn*V[i][j] + cs*V[i][p-1]
							V[i][j] = t
						}
					}
				}
			}
			break

		// Split at negligible s(k).

		case 2:
			{
				f := e[k-1]
				e[k-1] = 0.0
				for j := k; j < p; j++ {
					t := math.Hypot(s[j], f)
					cs := s[j] / t
					sn := f / t
					s[j] = t
					f = -sn * e[j]
					e[j] = cs * e[j]
					if wantu {
						for i := 0; i < m; i++ {
							t = cs*U[i][j] + sn*U[i][k-1]
							U[i][k-1] = -sn*U[i][j] + cs*U[i][k-1]
							U[i][j] = t
						}
					}
				}
			}
			break

		// Perform one qr step.

		case 3:
			{

				// Calculate the shift.

				scale := max(max(max(max(
					math.Abs(s[p-1]), math.Abs(s[p-2])),
					math.Abs(e[p-2])),
					math.Abs(s[k])),
					math.Abs(e[k]))
				sp := s[p-1] / scale
				spm1 := s[p-2] / scale
				epm1 := e[p-2] / scale
				sk := s[k] / scale
				ek := e[k] / scale
				b := ((spm1+sp)*(spm1-sp) + epm1*epm1) / 2.0
				c := (sp * epm1) * (sp * epm1)
				shift := float64(0)
				if (b != 0.0) || (c != 0.0) {
					shift = math.Sqrt(b*b + c)
					if b < 0.0 {
						shift = -shift
					}
					shift = c / (b + shift)
				}
				f := (sk+sp)*(sk-sp) + shift
				g := sk * ek

				// Chase zeros.

				for j := k; j < p-1; j++ {
					t := math.Hypot(f, g)
					cs := f / t
					sn := g / t
					if j != k {
						e[j-1] = t
					}
					f = cs*s[j] + sn*e[j]
					e[j] = cs*e[j] - sn*s[j]
					g = sn * s[j+1]
					s[j+1] = cs * s[j+1]
					if wantv {
						for i := 0; i < n; i++ {
							t = cs*V[i][j] + sn*V[i][j+1]
							V[i][j+1] = -sn*V[i][j] + cs*V[i][j+1]
							V[i][j] = t
						}
					}
					t = math.Hypot(f, g)
					cs = f / t
					sn = g / t
					s[j] = t
					f = cs*e[j] + sn*s[j+1]
					s[j+1] = -sn*e[j] + cs*s[j+1]
					g = sn * e[j+1]
					e[j+1] = cs * e[j+1]
					if wantu && (j < m-1) {
						for i := 0; i < m; i++ {
							t = cs*U[i][j] + sn*U[i][j+1]
							U[i][j+1] = -sn*U[i][j] + cs*U[i][j+1]
							U[i][j] = t
						}
					}
				}
				e[p-2] = f
				iter = iter + 1
			}
			break

		// Convergence.

		case 4:
			{

				// Make the singular values positive.

				if s[k] <= 0.0 {
					if s[k] < 0.0 {
						s[k] = -s[k]
					} else {
						s[k] = 0
					}
					if wantv {
						for i := 0; i <= pp; i++ {
							V[i][k] = -V[i][k]
						}
					}
				}

				// Order the singular values.

				for k < pp {
					if s[k] >= s[k+1] {
						break
					}
					t := s[k]
					s[k] = s[k+1]
					s[k+1] = t
					if wantv && (k < n-1) {
						for i := 0; i < n; i++ {
							t = V[i][k+1]
							V[i][k+1] = V[i][k]
							V[i][k] = t
						}
					}
					if wantu && (k < m-1) {
						for i := 0; i < m; i++ {
							t = U[i][k+1]
							U[i][k+1] = U[i][k]
							U[i][k] = t
						}
					}
					k++
				}
				iter = 0
				p--
			}
			break
		}
	}
	//fmt.Printf("testing\n%v\n%v\n%v\n%v\n%v\n", A, V, U, e, s);

	theU = MakeDenseMatrixStacked(U).GetMatrix(0, 0, m, minInt(m+1, n))
	Σ = Diagonal(s)
	theV = MakeDenseMatrixStacked(V)

	return
}


================================================
FILE: dense_test.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import (
	"fmt"
	"math/rand"
	"testing"
	"time"
)

const ε = 0.000001
const verbose = false
const speedTest = true

/* TEST: arithmetic.go */

func TestEquals(t *testing.T) {
	if !Equals(Ones(5, 3), Ones(5, 3)) {
		t.Fail()
	}
	if Equals(Ones(3, 5), Ones(5, 3)) {
		t.Fail()
	}
	if Equals(Zeros(3, 3), Ones(3, 3)) {
		t.Fail()
	}
}

func TestApproximates(t *testing.T) {
	A := Numbers(3, 3, 6)
	B := Numbers(3, 3, .1)
	C := Numbers(3, 3, .6)
	D, err := A.ElementMult(B)
	if !(err == nil) && !ApproxEquals(D, C, ε) {
		t.Fail()
	}
}

func TestAdd(t *testing.T) {
	A := Normals(3, 3)
	B := Normals(3, 3)
	C := Sum(A, B)
	if C.Nil() {
		t.Fail()
	}
	for i := 0; i < C.Rows(); i++ {
		for j := 0; j < C.Cols(); j++ {
			if A.Get(i, j)+B.Get(i, j) != C.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestSubtract(t *testing.T) {
	A := Normals(3, 3)
	B := Normals(3, 3)
	C := Difference(A, B)
	if C.Nil() {
		t.Fail()
	}
	for i := 0; i < C.Rows(); i++ {
		for j := 0; j < C.Cols(); j++ {
			if A.Get(i, j)-B.Get(i, j) != C.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestProduct(t *testing.T) {
	A := MakeDenseMatrix([]float64{6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	B := MakeDenseMatrix([]float64{1, 7, -4, 4,
		3, -2, -6, 1,
		-12, 8, 1, 20,
		0, 0, -10, 3,
	},
		4, 4)

	C, err := A.Times(B)

	if !(err == nil) {
		t.Fail()
	}

	var Ctrue Matrix
	Ctrue = MakeDenseMatrix([]float64{48, 14, -56, -46,
		66, -21, -10, -108,
		-240, 68, 101, 356,
		114, -122, -56, -203,
	},
		4, 4)

	if !Equals(C, Ctrue) {
		t.Fail()
	}

	P := MakePivotMatrix([]int{1, 3, 0, 2}, -1)
	C, err = P.Times(A)

	Ctrue, err = P.DenseMatrix().Times(A)
	if !Equals(C, Ctrue) {
		t.Fail()
	}
}

func TestParallelProduct(t *testing.T) {

	w := 100000
	h := 40

	if !verbose {
		w = 100
		h = 4
	}

	rand.Seed(time.Now().UnixNano())
	A := Normals(h, w)
	B := Normals(w, h)

	var C *DenseMatrix
	var start, end int64

	start = time.Now().UnixNano()
	Ctrue, err := A.Times(B)
	if !(err == nil) {
		t.Fail()
	}
	end = time.Now().UnixNano()
	if verbose {
		fmt.Printf("%fs for synchronous\n", float64(end-start)/1000000000)
	}

	start = time.Now().UnixNano()
	C = ParallelProduct(A, B)
	if !(err == nil) {
		t.Fail()
	}
	end = time.Now().UnixNano()
	if verbose {
		fmt.Printf("%fs for parallel\n", float64(end-start)/1000000000)
	}

	if !Equals(C, Ctrue) {
		t.Fail()
	}
}

var MaxProcs int = 1

func TestTimesDenseProcs(t *testing.T) {
	A := Normals(10, 10)
	B := Normals(10, 10)

	old := MaxProcs
	MaxProcs = 1
	C, _ := A.TimesDense(B)
	MaxProcs = 2
	Cp, _ := A.TimesDense(B)
	if !Equals(C, Cp) {
		t.Fail()
	}
	MaxProcs = old
}

func TestElementMult(t *testing.T) {

	A := MakeDenseMatrix([]float64{6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	T := MakeDenseMatrix([]float64{0.1, 0.1, 0.1, 0.1,
		10, 10, 10, 10,
		100, 100, 100, 100,
		1000, 1000, 1000, 1000,
	},
		4, 4)
	C, err := A.ElementMult(T)

	if !(err == nil) {
		t.Fail()
	}

	Ctrue := MakeDenseMatrix([]float64{0.6, -0.2, -0.4, 0.4,
		30, -30, -60, 10,
		-1200, 800, 2100, -800,
		-6000, 0, -10000, 7000,
	},
		4, 4)

	if !ApproxEquals(C, Ctrue, ε) {
		t.Fail()
	}
}

func TestScale(t *testing.T) {
	A := Normals(3, 3)
	f := float64(5.3)
	B := A.Copy()
	B.Scale(f)

	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if A.Get(i, j)*f != B.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestScaleMatrix(t *testing.T) {
	A := Normals(4, 4)
	B := Normals(4, 4)
	C := A.Copy()
	C.ScaleMatrix(B)

	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if A.Get(i, j)*B.Get(i, j) != C.Get(i, j) {
				t.Fail()
			}
		}
	}
}

/* TEST: basic.go */

func TestSymmetric(t *testing.T) {
	A := MakeDenseMatrix([]float64{
		6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	if A.Symmetric() {
		t.Fail()
	}
	B := MakeDenseMatrix([]float64{
		6, 3, -12, -6,
		3, -3, 8, 0,
		-12, 8, 21, -10,
		-6, 0, -10, 7,
	},
		4, 4)
	if !B.Symmetric() {
		t.Fail()
	}
}

func TestInverse(t *testing.T) {
	A := MakeDenseMatrix([]float64{6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	Ainv, err := A.Inverse()

	if !(err == nil) {
		t.Fail()
	}

	AAinv, err := A.Times(Ainv)

	if !(err == nil) {
		t.Fail()
	}

	if !ApproxEquals(Eye(A.Rows()), AAinv, ε) {
		if verbose {
			fmt.Printf("A\n%v\n\nAinv\n%v\n\nA*Ainv\n%v\n", A, Ainv, AAinv)
		}
		t.Fail()
	}
}

func TestDet(t *testing.T) {
	A := MakeDenseMatrix([]float64{4, -2, 5,
		-1, -7, 10,
		0, 1, -3,
	},
		3, 3)

	if A.Det() != 45 {
		if verbose {
			fmt.Printf("A\n%v\n\nA.Det()\n%v\n\n", A, A.Det())
		}
		t.Fail()
	}
}

func TestTrace(t *testing.T) {
	A := MakeDenseMatrix([]float64{4, -2, 5,
		-1, -7, 10,
		0, 1, -3,
	},
		3, 3)

	if A.Trace() != 4-7-3 {
		if verbose {
			fmt.Printf("A\n%v\n\nA.Trace()\n%v\n\n", A, A.Trace())
		}
		t.Fail()
	}
}

func TestTranspose(t *testing.T) {
	A := Normals(4, 4)
	B := A.Transpose()
	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			if A.Get(i, j) != B.Get(j, i) {
				t.Fail()
			}
		}
	}
}

func TestSolve(t *testing.T) {
	A := MakeDenseMatrix([]float64{6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	b := MakeDenseMatrix([]float64{1, 1, 1, 1}, 4, 1)
	x, err := A.Solve(b)

	if !(err == nil) {
		t.Fail()
	}

	xtrue := MakeDenseMatrix([]float64{-0.906250, -3.393750, 1.275000, 1.187500}, 4, 1)

	if !Equals(x, xtrue) {
		t.Fail()
	}
}

/* TEST: decomp.go */

func TestCholesky(t *testing.T) {
	A := MakeDenseMatrix([]float64{1, 0.2, 0,
		0.2, 1, 0.5,
		0, 0.5, 1,
	},
		3, 3)
	B, err := A.Cholesky()
	if !(err == nil) {
		t.Fail()
	}
	if !ApproxEquals(A, Product(B, B.Transpose()), ε) {
		t.Fail()
	}
}

func TestLU(t *testing.T) {

	A := MakeDenseMatrix([]float64{6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	L, U, P := A.LU()

	LU, err := L.Times(U)
	PLU, err := P.Times(LU)

	if !(err == nil) {
		if verbose {
			fmt.Printf("TestLU: %v\n", err)
		}
		t.Fail()
	}

	if !Equals(A, PLU) {
		if verbose {
			fmt.Printf("TestLU:\n%v\n!=\n%v\n", A, PLU)
		}
		t.Fail()
	}

	A = MakeDenseMatrix([]float64{6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	Ltrue, Utrue, Ptrue := A.LU()

	P = A.LUInPlace()
	L = A.L()
	U = A.U()

	for i := 0; i < L.Rows(); i++ {
		L.Set(i, i, 1)
	}

	PL := Product(P, L)
	PLU2 := Product(PL, U)
	PLtrue := Product(Ptrue, Ltrue)
	PLUtrue := Product(PLtrue, Utrue)

	if !Equals(PLU2, PLUtrue) {
		t.Fail()
	}

}

func TestQR(t *testing.T) {
	A := MakeDenseMatrix([]float64{6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	Q, R := A.QR()

	Qtrue := MakeDenseMatrix([]float64{-0.4, 0.278610, 0.543792, -0.683130,
		-0.2, -0.358213, -0.699161, -0.585540,
		0.8, 0.437816, -0.126237, -0.390360,
		0.4, -0.776129, 0.446686, -0.195180,
	},
		4, 4)

	Rtrue := MakeDenseMatrix([]float64{-15, 7.8, 15.6, -5.4,
		0, 4.019950, 17.990272, -8.179206,
		0, 0, -5.098049, 5.612709,
		0, 0, 0, -1.561440,
	},
		4, 4)

	QR := Product(Q, R)

	if !ApproxEquals(Q, Qtrue, ε) ||
		!ApproxEquals(R, Rtrue, ε) ||
		!ApproxEquals(A, QR, ε) {
		t.Fail()
	}
}

/* TEST: eigen.go */

func TestEigen(t *testing.T) {
	A := MakeDenseMatrix([]float64{
		2, 1,
		1, 2,
	},
		2, 2)
	V, D, _ := A.Eigen()

	Vinv, _ := V.Inverse()
	Aguess := Product(Product(V, D), Vinv)

	if !ApproxEquals(A, Aguess, ε) {
		t.Fail()
	}

	B := MakeDenseMatrix([]float64{
		6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)

	V, D, _ = B.Eigen()

	Vinv, _ = V.Inverse()

	if !ApproxEquals(B, Product(Product(V, D), Vinv), ε) {
		if verbose {
			fmt.Printf("B =\n%v\nV=\n%v\nD=\n%v\n", B, V, D)
		}
		t.Fail()
	}

	Bm, _ := B.Times(B.Transpose())
	B = Bm.DenseMatrix()
	V, D, _ = B.Eigen()
	Vinv, _ = V.Inverse()

	if !ApproxEquals(B, Product(Product(V, D), Vinv), ε) {
		if verbose {
			fmt.Printf("B =\n%v\nV=\n%v\nD=\n%v\n", B, V, D)
		}
		t.Fail()
	}
}

func TestSVD(t *testing.T) {
	A := MakeDenseMatrix([]float64{
		6, -2, -4, 4,
		3, -3, -6, 1,
		-12, 8, 21, -8,
		-6, 0, -10, 7,
	},
		4, 4)
	U, Σ, V, _ := A.SVD()
	Arecomp := Product(Product(U, Σ), V.Transpose())
	if !ApproxEquals(A, Arecomp, ε) {
		t.Fail()
	}
	A = Normals(5, 3)
	U, Σ, V, _ = A.SVD()
	Arecomp = Product(Product(U, Σ), V.Transpose())
	if !ApproxEquals(A, Arecomp, ε) {
		t.Fail()
	}
}

/* TEST: matrix.go */

func TestGetMatrix(t *testing.T) {
	A := Zeros(4, 4)
	B := A.GetMatrix(1, 1, 2, 2)
	B.Set(0, 1, 1)
	if A.Get(1, 2) != 1 {
		t.Fail()
	}
}

func TestL(t *testing.T) {
	A := Normals(4, 4)
	L := A.L()
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if j > i && L.Get(i, j) != 0 {
				t.Fail()
			} else if j <= i && L.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	A = Normals(4, 2)
	L = A.L()
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if j > i && L.Get(i, j) != 0 {
				t.Fail()
			} else if j <= i && L.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	A = Normals(2, 4)
	L = A.L()
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if j > i && L.Get(i, j) != 0 {
				t.Fail()
			} else if j <= i && L.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestU(t *testing.T) {
	A := Normals(4, 4)
	U := A.U()
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if j < i && U.Get(i, j) != 0 {
				t.Fail()
			} else if j >= i && U.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	A = Normals(2, 4)
	U = A.U()
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if j < i && U.Get(i, j) != 0 {
				t.Fail()
			} else if j >= i && U.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	A = Normals(4, 2)
	U = A.U()
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if j < i && U.Get(i, j) != 0 {
				t.Fail()
			} else if j >= i && U.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestAugment(t *testing.T) {
	var A, B, C *DenseMatrix
	A = Normals(4, 4)
	B = Normals(4, 4)
	C, _ = A.Augment(B)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i, j+A.Cols()) != B.Get(i, j) {
				t.Fail()
			}
		}
	}

	A = Normals(2, 2)
	B = Normals(4, 4)
	C, err := A.Augment(B)
	if err == nil {
		t.Fail()
	}

	A = Normals(4, 4)
	B = Normals(4, 2)
	C, _ = A.Augment(B)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i, j+A.Cols()) != B.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestStack(t *testing.T) {

	var A, B, C *DenseMatrix
	A = Normals(4, 4)
	B = Normals(4, 4)
	C, _ = A.Stack(B)

	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i+A.Rows(), j) != B.Get(i, j) {
				t.Fail()
			}
		}
	}

	A = Normals(4, 4)
	B = Normals(4, 2)
	C, err := A.Stack(B)
	if err == nil {
		t.Fail()
	}

	A = Normals(2, 4)
	B = Normals(4, 4)
	C, err = A.Stack(B)

	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i+A.Rows(), j) != B.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestZeros(t *testing.T) {
	A := Zeros(4, 5)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if A.Get(i, j) != 0 {
				t.Fail()
			}
		}
	}
}

func TestNumbers(t *testing.T) {
	n := float64(1.0)
	A := Numbers(3, 3, n)
	//	fmt.Printf("%v\n\n\n",A.String());

	Atrue := MakeDenseMatrix([]float64{n, n, n,
		n, n, n,
		n, n, n,
	},
		3, 3)
	if !Equals(A, Atrue) {
		t.Fail()
	}
}

func TestOnes(t *testing.T) {

	A := Ones(4, 5)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if A.Get(i, j) != 1 {
				t.Fail()
			}
		}
	}
}

func TestEye(t *testing.T) {

	A := Eye(4)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if (i != j && A.Get(i, j) != 0) || (i == j && A.Get(i, j) != 1) {
				t.Fail()
			}
		}
	}
}

func TestNormals(t *testing.T) {
	//test that it's filled with random data?
	A := Normals(3, 4)
	if A.Rows() != 3 || A.Cols() != 4 {
		t.Fail()
	}
}

func TestKronecker(t *testing.T) {
	A := MakeDenseMatrix([]float64{0, 1, 2, 3}, 2, 2)
	B := MakeDenseMatrix([]float64{5, 6, 7, 8, 9, 10}, 2, 3)
	C := Kronecker(A, B)
	Cp := MakeDenseMatrix([]float64{0, 0, 0, 5, 6, 7,
		0, 0, 0, 8, 9, 10,
		10, 12, 14, 15, 18, 21,
		16, 18, 20, 24, 27, 30}, 4, 6)
	if !Equals(C, Cp) {
		t.Fail()
	}
}

func TestVectorize(t *testing.T) {
	A := MakeDenseMatrix([]float64{0, 1, 2, 3, 4, 5}, 2, 3)
	V := Vectorize(A)
	Vp := MakeDenseMatrix([]float64{0, 3, 1, 4, 2, 5}, 6, 1)
	if !Equals(V, Vp) {
		t.Fail()
	}
}

func TestSubmatrix(t *testing.T) {
	Eye(3).GetMatrix(1, 1, 2, 2).GetColVector(0)
}

/* TEST: util.go */

/*
func TestMultipleProduct(t *testing.T) {
	A := Ones(3, 1)
	B := Ones(1, 3)
	C := MultipleProduct(A, B, A)
	D := Product(A, B)
	E := Product(D, A)

	if !Equals(E, C) {
		t.Fail()
	}
}
*/


================================================
FILE: densebench_test.go
================================================
package matrix

import (
	"fmt"
	"testing"
	"time"
)

func BenchmarkTransposeTimes(b *testing.B) {
	fmt.Println("benchmark")
	for s := 25; s <= 100; s += 25 {
		w, h := s/2, s*2

		A := Normals(h, w)
		B := Normals(w, h)

		var times [2]float64

		const Count = 500

		MaxProcs = 1
		WhichSyncMethod = 1
		start := time.Now()
		for i := 0; i < Count; i++ {
			A.Times(B)
		}
		end := time.Now()
		duration := end.Sub(start)
		times[0] = float64(duration) / 1e9

		WhichSyncMethod = 2
		start = time.Now()
		for i := 0; i < Count; i++ {
			A.Times(B)
		}
		end = time.Now()
		duration = end.Sub(start)
		times[1] = float64(duration) / 1e9
		fmt.Printf("%d: %.2f\n", h, times[1]/times[0])
	}
}


================================================
FILE: error.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "fmt"

const (
	//The matrix returned was nil.
	errorNilMatrix = iota + 1
	//The dimensions of the inputs do not make sense for this operation.
	errorDimensionMismatch
	//The indices provided are out of bounds.
	errorIllegalIndex
	//The matrix provided has a singularity.
	exceptionSingular
	//The matrix provided is not positive semi-definite.
	exceptionNotSPD
)

type error_ int

func (e error_) Error() string {
	switch e {
	case errorNilMatrix:
		return "Matrix is nil"
	case errorDimensionMismatch:
		return "Input dimensions do not match"
	case errorIllegalIndex:
		return "Index out of bounds"
	case exceptionSingular:
		return "Matrix is singular"
	case exceptionNotSPD:
		return "Matrix is not positive semidefinite"
	}
	return fmt.Sprintf("Unknown error code %d", e)
}
func (e error_) String() string {
	return e.Error()
}

var (
	//The matrix returned was nil.
	ErrorNilMatrix error_ = error_(errorNilMatrix)
	//The dimensions of the inputs do not make sense for this operation.
	ErrorDimensionMismatch error_ = error_(errorDimensionMismatch)
	//The indices provided are out of bounds.
	ErrorIllegalIndex error_ = error_(errorIllegalIndex)
	//The matrix provided has a singularity.
	ExceptionSingular error_ = error_(exceptionSingular)
	//The matrix provided is not positive semi-definite.
	ExceptionNotSPD error_ = error_(exceptionNotSPD)
)


================================================
FILE: matrix.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//target:gomatrix.googlecode.com/hg/matrix

//Linear algebra.
package matrix

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

//The MatrixRO interface defines matrix operations that do not change the
//underlying data, such as information requests or the creation of transforms
/*
Read-only matrix types (at the moment, PivotMatrix).
*/
type MatrixRO interface {
	//Returns true if the underlying object is nil.
	Nil() bool

	//The number of rows in this matrix.
	Rows() int
	//The number of columns in this matrix.
	Cols() int

	//The number of elements in this matrix.
	NumElements() int
	//The size pair, (Rows(), Cols())
	GetSize() (int, int)

	//The element in the ith row and jth column.
	Get(i, j int) float64

	Plus(MatrixRO) (Matrix, error)
	Minus(MatrixRO) (Matrix, error)
	Times(MatrixRO) (Matrix, error)

	//The determinant of this matrix.
	Det() float64
	//The trace of this matrix.
	Trace() float64

	//A pretty-print string.
	String() string

	DenseMatrix() *DenseMatrix
	SparseMatrix() *SparseMatrix
}

/*
A mutable matrix.
*/
type Matrix interface {
	MatrixRO

	//Set the element at the ith row and jth column to v.
	Set(i int, j int, v float64)

	Add(MatrixRO) error
	Subtract(MatrixRO) error
	Scale(float64)
}

type matrix struct {
	rows int
	cols int
}

func (A *matrix) Nil() bool { return A == nil }

func (A *matrix) Rows() int { return A.rows }

func (A *matrix) Cols() int { return A.cols }

func (A *matrix) NumElements() int { return A.rows * A.cols }

func (A *matrix) GetSize() (rows, cols int) {
	rows = A.rows
	cols = A.cols
	return
}

/*
	Take a matlab-style matrix representation

	eg [a b c; d e f]
*/
func ParseMatlab(txt string) (A *DenseMatrix, err error) {
	var arrays [][]float64

	spaceSep := strings.Fields(txt)

	tok := func() (t string, eos bool) {
		defer func() {
			for len(spaceSep) != 0 && len(spaceSep[0]) == 0 {
				spaceSep = spaceSep[1:]
			}
		}()

		isNotNumber := func(c byte) bool {
			return c != '[' || c != ']' || c == ';'
		}

		if len(spaceSep) == 0 {
			eos = true
			return
		}

		top := spaceSep[0]

		var lof int
		for ; lof < len(top) && !isNotNumber(top[lof]); lof++ {
		}

		if lof != 0 {
			t = top[:lof]
			spaceSep[0] = top[lof:]
			return
		} else {
			t = top[:1]
			spaceSep[0] = top[1:]
			return
		}

		panic("unreachable")
	}

	stack := func(row []float64) (err error) {
		if len(arrays) == 0 {
			arrays = [][]float64{row}
			return
		}
		if len(arrays[0]) != len(row) {
			err = errors.New("misaligned row")
		}
		arrays = append(arrays, row)
		return
	}

	var row []float64

loop:
	for {
		t, eos := tok()
		if eos {
			break loop
		}
		switch t {
		case "[":
		case ";":
			err = stack(row)
			if err != nil {
				return
			}
			row = []float64{}
		case "]":
			err = stack(row)
			if err != nil {
				return
			}
			break loop
		default:
			var v float64
			v, err = strconv.ParseFloat(t, 64)
			if err != nil {
				return
			}
			row = append(row, v)
		}
	}
	A = MakeDenseMatrixStacked(arrays)
	return
}

func String(A MatrixRO) string {
	condense := func(vs string) string {
		if strings.Index(vs, ".") != -1 {
			for vs[len(vs)-1] == '0' {
				vs = vs[0 : len(vs)-1]
			}
		}
		if vs[len(vs)-1] == '.' {
			vs = vs[0 : len(vs)-1]
		}
		return vs
	}

	if A == nil {
		return "{nil}"
	}
	s := "{"

	maxLen := 0
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			v := A.Get(i, j)
			vs := condense(fmt.Sprintf("%f", v))

			maxLen = maxInt(maxLen, len(vs))
		}
	}

	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			v := A.Get(i, j)

			vs := condense(fmt.Sprintf("%f", v))

			for len(vs) < maxLen {
				vs = " " + vs
			}
			s += vs
			if i != A.Rows()-1 || j != A.Cols()-1 {
				s += ","
			}
			if j != A.Cols()-1 {
				s += " "
			}
		}
		if i != A.Rows()-1 {
			s += "\n "
		}
	}
	s += "}"
	return s
}


================================================
FILE: matrix_test.go
================================================
package matrix

import (
	"testing"
)

func TestParse(t *testing.T) {
	s := `[1 2 3;4 5 6]`
	A, err := ParseMatlab(s)
	
	if err != nil {
		t.Fatal(err)
	}
	
	Ar := MakeDenseMatrix([]float64{1,2,3,4,5,6}, 2, 3)
	if !Equals(A, Ar) {
		t.Error()
	}
}


================================================
FILE: pivot.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

/*
A space-optimized structure for pivot matrices, ie a matrix with
exactly one 1 in each row and each column.
*/
type PivotMatrix struct {
	matrix
	pivots    []int
	pivotSign float64
}

func (P *PivotMatrix) Get(i, j int) float64 {
	i = i % P.rows
	if i < 0 {
		i = P.rows - i
	}
	j = j % P.cols
	if j < 0 {
		j = P.cols - j
	}
	if P.pivots[j] == i {
		return 1
	}
	return 0
}

/*
Convert this PivotMatrix into a DenseMatrix.
*/
func (P *PivotMatrix) DenseMatrix() *DenseMatrix {
	A := Zeros(P.rows, P.cols)
	for j := 0; j < P.rows; j++ {
		A.Set(P.pivots[j], j, 1)
	}
	return A
}

/*
Convert this PivotMatrix into a SparseMatrix.
*/
func (P *PivotMatrix) SparseMatrix() *SparseMatrix {
	A := ZerosSparse(P.rows, P.cols)
	for j := 0; j < P.rows; j++ {
		A.Set(P.pivots[j], j, 1)
	}
	return A
}

/*
Make a copy of this PivotMatrix.
*/
func (P *PivotMatrix) Copy() *PivotMatrix { return MakePivotMatrix(P.pivots, P.pivotSign) }

func MakePivotMatrix(pivots []int, pivotSign float64) *PivotMatrix {
	n := len(pivots)
	P := new(PivotMatrix)
	P.rows = n
	P.cols = n
	P.pivots = pivots
	P.pivotSign = pivotSign
	return P
}

func (A *PivotMatrix) String() string { return String(A) }


================================================
FILE: pivot_arithmetic.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

func (P *PivotMatrix) Minus(A MatrixRO) (Matrix, error) {
	if P.rows != A.Rows() || P.cols != A.Cols() {
		return nil, ErrorDimensionMismatch
	}
	B := P.DenseMatrix()
	B.Subtract(A)
	return B, nil
}

func (P *PivotMatrix) Plus(A MatrixRO) (Matrix, error) {
	if P.rows != A.Rows() || P.cols != A.Cols() {
		return nil, ErrorDimensionMismatch
	}
	B := P.DenseMatrix()
	B.Add(A)
	return B, nil
}

/*
Multiply this pivot matrix by another.
*/
func (P *PivotMatrix) Times(A MatrixRO) (Matrix, error) {
	if P.Cols() != A.Rows() {
		return nil, ErrorDimensionMismatch
	}
	B := Zeros(P.rows, A.Cols())
	for i := 0; i < P.rows; i++ {
		k := 0
		for ; i != P.pivots[k]; k++ {
		}
		for j := 0; j < A.Cols(); j++ {
			B.Set(i, j, A.Get(k, j))
		}
	}
	return B, nil
}

/*
Multiplication optimized for when two pivots are the operands.
*/
func (P *PivotMatrix) TimesPivot(A *PivotMatrix) (*PivotMatrix, error) {
	if P.rows != A.rows {
		return nil, ErrorDimensionMismatch
	}

	newPivots := make([]int, P.rows)
	newSign := P.pivotSign * A.pivotSign

	for i := 0; i < A.rows; i++ {
		newPivots[i] = P.pivots[A.pivots[i]]
	}

	return MakePivotMatrix(newPivots, newSign), nil
}

/*
Equivalent to PxA, but streamlined to take advantage of the datastructures.
*/
func (P *PivotMatrix) RowPivotDense(A *DenseMatrix) (*DenseMatrix, error) {
	if P.rows != A.rows {
		return nil, ErrorDimensionMismatch
	}
	B := Zeros(A.rows, A.cols)
	for si := 0; si < A.rows; si++ {
		di := P.pivots[si]
		Astart := si * A.step
		Bstart := di * B.step
		for j := 0; j < A.cols; j++ {
			B.elements[Bstart+j] = A.elements[Astart+j]
		}
	}
	return B, nil
}

/*
Equivalent to AxP, but streamlined to take advantage of the datastructures.
*/
func (P *PivotMatrix) ColPivotDense(A *DenseMatrix) (*DenseMatrix, error) {
	if P.rows != A.cols {
		return nil, ErrorDimensionMismatch
	}
	B := Zeros(A.rows, A.cols)
	for i := 0; i < B.rows; i++ {
		Astart := i * A.step
		Bstart := i * B.step
		for sj := 0; sj < B.cols; sj++ {
			dj := P.pivots[sj]
			B.elements[Bstart+dj] = A.elements[Astart+sj]
		}
	}
	return B, nil
}

/*
Equivalent to PxA, but streamlined to take advantage of the datastructures.
*/
func (P *PivotMatrix) RowPivotSparse(A *SparseMatrix) (*SparseMatrix, error) {
	if P.rows != A.rows {
		return nil, ErrorDimensionMismatch
	}
	B := ZerosSparse(A.rows, A.cols)
	for index, value := range A.elements {
		si, j := A.GetRowColIndex(index)
		di := P.pivots[si]
		B.Set(di, j, value)
	}

	return B, nil
}

/*
Equivalent to AxP, but streamlined to take advantage of the datastructures.
*/
func (P *PivotMatrix) ColPivotSparse(A *SparseMatrix) (*SparseMatrix, error) {
	if P.rows != A.cols {
		return nil, ErrorDimensionMismatch
	}
	B := ZerosSparse(A.rows, A.cols)
	for index, value := range A.elements {
		i, sj := A.GetRowColIndex(index)
		dj := P.pivots[sj]
		B.Set(i, dj, value)
	}

	return B, nil
}


================================================
FILE: pivot_basic.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "math"

/*
Swap two rows in this PivotMatrix.
*/
func (P *PivotMatrix) SwapRows(r1, r2 int) error {
	//	tmp := P.pivots[r1];
	//	P.pivots[r1] = P.pivots[r2];
	//	P.pivots[r2] = tmp;
	P.pivots[r1], P.pivots[r2] = P.pivots[r2], P.pivots[r1]
	P.pivotSign *= -1

	return nil
}

func (P *PivotMatrix) Symmetric() bool {
	for i := 0; i < P.rows; i++ {
		if P.pivots[P.pivots[i]] != i {
			return false
		}
	}
	return true
}

func (A *PivotMatrix) Inverse() *PivotMatrix { return A.Transpose() }

func (P *PivotMatrix) Transpose() *PivotMatrix {
	newPivots := make([]int, P.rows)
	for i := 0; i < P.rows; i++ {
		newPivots[P.pivots[i]] = i
	}
	return MakePivotMatrix(newPivots, P.pivotSign)
}

func (P *PivotMatrix) Det() float64 { return P.pivotSign }

func (P *PivotMatrix) Trace() (r float64) {
	for i := 0; i < len(P.pivots); i++ {
		if P.pivots[i] == i {
			r += 1
		}
	}
	return
}

/*
Returns x such that Px=b.
*/
func (P *PivotMatrix) Solve(b MatrixRO) (Matrix, error) {
	return P.Transpose().Times(b) //error comes from times
}

func (A *PivotMatrix) OneNorm() float64      { return float64(A.rows) }
func (A *PivotMatrix) TwoNorm() float64      { return math.Sqrt(float64(A.rows)) }
func (A *PivotMatrix) InfinityNorm() float64 { return 1 }


================================================
FILE: pivot_test.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "testing"
import "fmt"

func TestTimes_Pivot(t *testing.T) {
	P1 := MakePivotMatrix([]int{2, 1, 0}, -1)
	P2 := MakePivotMatrix([]int{2, 0, 1}, 1)
	P, _ := P1.TimesPivot(P2)
	if !Equals(P, Product(P1, P2)) {
		if verbose {
			fmt.Printf("%v\n%v\n%v\n", P1, P2, P)
		}
		t.Fail()
	}
}

func TestRowPivot(t *testing.T) {
	P := MakePivotMatrix([]int{2, 1, 0}, -1)
	A := Normals(3, 4)
	B, _ := P.RowPivotDense(A)
	Btrue := Product(P, A)
	if !Equals(B, Btrue) {
		t.Fail()
	}
	A = Normals(4, 3)
	_, err := P.RowPivotDense(A)
	if err == nil {
		t.Fail()
	}
	C := Normals(3, 4).SparseMatrix()
	D, _ := P.RowPivotSparse(C)
	Btrue = Product(P, C)
	if !Equals(D, Btrue) {
		t.Fail()
	}
}

func TestColPivot(t *testing.T) {
	P := MakePivotMatrix([]int{2, 1, 0}, -1)
	A := Normals(4, 3)
	B, _ := P.ColPivotDense(A)
	Btrue := Product(A, P)
	if !Equals(B, Btrue) {
		t.Fail()
	}
	A = Normals(3, 4)
	_, err := P.ColPivotDense(A)
	if err == nil {
		t.Fail()
	}
	C := Normals(4, 3).SparseMatrix()
	D, _ := P.ColPivotSparse(C)
	Btrue = Product(C, P)
	if !Equals(D, Btrue) {
		t.Fail()
	}
}


================================================
FILE: sparse.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "math/rand"

/*
A sparse matrix based on go's map datastructure.
*/
type SparseMatrix struct {
	matrix
	elements map[int]float64
	// offset to start of matrix s.t. idx = i*cols + j + offset
	// offset = starting row * step + starting col
	offset int
	// analogous to dense step
	step int
}

func (A *SparseMatrix) Get(i, j int) float64 {
	i = i % A.rows
	if i < 0 {
		i = A.rows - i
	}
	j = j % A.cols
	if j < 0 {
		j = A.cols - j
	}
	x, _ := A.elements[i*A.step+j+A.offset]
	return x
}

/*
Looks up an element given its element index.
*/
func (A *SparseMatrix) GetIndex(index int) float64 {
	x, ok := A.elements[index]
	if !ok {
		return 0
	}
	return x
}

/*
Turn an element index into a row number.
*/
func (A *SparseMatrix) GetRowIndex(index int) (i int) {
	i = (index - A.offset) / A.cols
	return
}

/*
Turn an element index into a column number.
*/
func (A *SparseMatrix) GetColIndex(index int) (j int) {
	j = (index - A.offset) % A.cols
	return
}

/*
Turn an element index into a row and column number.
*/
func (A *SparseMatrix) GetRowColIndex(index int) (i int, j int) {
	i = (index - A.offset) / A.step
	j = (index - A.offset) % A.step
	return
}

func (A *SparseMatrix) Set(i int, j int, v float64) {
	i = i % A.rows
	if i < 0 {
		i = A.rows - i
	}
	j = j % A.cols
	if j < 0 {
		j = A.cols - j
	}
	// v == 0 results in removal of key from underlying map
	if v == 0 {
		delete(A.elements, i*A.step+j+A.offset)
	} else {
		A.elements[i*A.step+j+A.offset] = v
	}
}

/*
Sets an element given its index.
*/
func (A *SparseMatrix) SetIndex(index int, v float64) {
	// v == 0 results in removal of key from underlying map
	if v == 0 {
		delete(A.elements, index)
	} else {
		A.elements[index] = v
	}
}

/*
A channel that will carry the indices of non-zero elements.
*/
func (A *SparseMatrix) Indices() (out chan int) {
	//maybe thread the populating?
	out = make(chan int)
	go func(o chan int) {
		for index := range A.elements {
			i, j := A.GetRowColIndex(index)
			if 0 <= i && i < A.rows && 0 <= j && j < A.cols {
				o <- index
			}
		}
		close(o)
	}(out)
	return
}

/*
Get a matrix representing a subportion of A. Changes to the new matrix will be
reflected in A.
*/
func (A *SparseMatrix) GetMatrix(i, j, rows, cols int) (subMatrix *SparseMatrix) {
	if i < 0 || j < 0 || i+rows > A.rows || j+cols > A.cols {
		i = maxInt(0, i)
		j = maxInt(0, j)
		rows = minInt(A.rows-i, rows)
		rows = minInt(A.cols-j, cols)
	}

	subMatrix = new(SparseMatrix)
	subMatrix.rows = rows
	subMatrix.cols = cols
	subMatrix.offset = (i+A.offset/A.step)*A.step + (j + A.offset%A.step)
	subMatrix.step = A.step
	subMatrix.elements = A.elements

	return
}

/*
Gets a reference to a column vector.
*/
func (A *SparseMatrix) GetColVector(j int) *SparseMatrix {
	return A.GetMatrix(0, j, A.rows, j+1)
}

/*
Gets a reference to a row vector.
*/
func (A *SparseMatrix) GetRowVector(i int) *SparseMatrix {
	return A.GetMatrix(i, 0, 1, A.cols)
}

/*
Creates a new matrix [A B].
*/
func (A *SparseMatrix) Augment(B *SparseMatrix) (*SparseMatrix, error) {
	if A.rows != B.rows {
		return nil, ErrorDimensionMismatch
	}
	C := ZerosSparse(A.rows, A.cols+B.cols)

	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		C.Set(i, j, value)
	}

	for index, value := range B.elements {
		i, j := B.GetRowColIndex(index)
		C.Set(i, j+A.cols, value)
	}

	return C, nil
}

/*
Creates a new matrix [A;B], where A is above B.
*/
func (A *SparseMatrix) Stack(B *SparseMatrix) (*SparseMatrix, error) {
	if A.cols != B.cols {
		return nil, ErrorDimensionMismatch
	}
	C := ZerosSparse(A.rows+B.rows, A.cols)

	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		C.Set(i, j, value)
	}

	for index, value := range B.elements {
		i, j := B.GetRowColIndex(index)
		C.Set(i+A.rows, j, value)
	}

	return C, nil
}

/*
Returns a copy with all zeros above the diagonal.
*/
func (A *SparseMatrix) L() *SparseMatrix {
	B := ZerosSparse(A.rows, A.cols)
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		if i >= j {
			B.Set(i, j, value)
		}
	}
	return B
}

/*
Returns a copy with all zeros below the diagonal.
*/
func (A *SparseMatrix) U() *SparseMatrix {
	B := ZerosSparse(A.rows, A.cols)
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		if i <= j {
			B.Set(i, j, value)
		}
	}
	return B
}

func (A *SparseMatrix) Copy() *SparseMatrix {
	B := ZerosSparse(A.rows, A.cols)
	for index, value := range A.elements {
		B.elements[index] = value
	}
	return B
}

func ZerosSparse(rows int, cols int) *SparseMatrix {
	A := new(SparseMatrix)
	A.rows = rows
	A.cols = cols
	A.offset = 0
	A.step = cols
	A.elements = map[int]float64{}
	return A
}

/*
Creates a matrix and puts a standard normal in n random elements, with replacement.
*/
func NormalsSparse(rows int, cols int, n int) *SparseMatrix {
	A := ZerosSparse(rows, cols)
	for k := 0; k < n; k++ {
		i := rand.Intn(rows)
		j := rand.Intn(cols)
		A.Set(i, j, rand.NormFloat64())
	}
	return A
}

/*
Create a sparse matrix using the provided map as its backing.
*/
func MakeSparseMatrix(elements map[int]float64, rows int, cols int) *SparseMatrix {
	A := ZerosSparse(rows, cols)
	A.elements = elements
	return A
}

/*
Convert this sparse matrix into a dense matrix.
*/
func (A *SparseMatrix) DenseMatrix() *DenseMatrix {
	B := Zeros(A.rows, A.cols)
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		B.Set(i, j, value)
	}
	return B
}

func (A *SparseMatrix) SparseMatrix() *SparseMatrix {
	return A.Copy()
}

func (A *SparseMatrix) String() string { return String(A) }


================================================
FILE: sparse_arithmetic.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

/*
The sum of this matrix and another.
*/
func (A *SparseMatrix) Plus(B MatrixRO) (Matrix, error) {
	C := A.Copy()
	err := C.Add(B)
	return C, err
}

/*
The sum of this matrix and another sparse matrix, optimized for sparsity.
*/
func (A *SparseMatrix) PlusSparse(B *SparseMatrix) (*SparseMatrix, error) {
	C := A.Copy()
	err := C.AddSparse(B)
	return C, err
}

/*
The difference between this matrix and another.
*/
func (A *SparseMatrix) Minus(B MatrixRO) (Matrix, error) {
	C := A.Copy()
	err := C.Subtract(B)
	return C, err
}

/*
The difference between this matrix and another sparse matrix, optimized for sparsity.
*/
func (A *SparseMatrix) MinusSparse(B *SparseMatrix) (*SparseMatrix, error) {
	C := A.Copy()
	err := C.SubtractSparse(B)
	return C, err
}

/*
Add another matrix to this one in place.
*/
func (A *SparseMatrix) Add(B MatrixRO) error {
	if Bs, ok := B.(*SparseMatrix); ok {
		return A.AddSparse(Bs)
	}

	if A.rows != B.Rows() || A.cols != B.Cols() {
		return ErrorDimensionMismatch
	}

	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			A.Set(i, j, A.Get(i, j)+B.Get(i, j))
		}
	}

	return nil
}

/*
Add another matrix to this one in place, optimized for sparsity.
*/
func (A *SparseMatrix) AddSparse(B *SparseMatrix) error {
	if A.rows != B.Rows() || A.cols != B.Cols() {
		return ErrorDimensionMismatch
	}

	for index, value := range B.elements {
		i, j := A.GetRowColIndex(index)
		A.Set(i, j, A.Get(i, j)+value)
	}

	return nil
}

/*
Subtract another matrix from this one in place.
*/
func (A *SparseMatrix) Subtract(B MatrixRO) error {
	if Bs, ok := B.(*SparseMatrix); ok {
		return A.SubtractSparse(Bs)
	}

	if A.rows != B.Rows() || A.cols != B.Cols() {
		return ErrorDimensionMismatch
	}

	for i := 0; i < A.rows; i++ {
		for j := 0; j < A.cols; j++ {
			A.Set(i, j, A.Get(i, j)-B.Get(i, j))
		}
	}

	return nil
}

/*
Subtract another matrix from this one in place, optimized for sparsity.
*/
func (A *SparseMatrix) SubtractSparse(B *SparseMatrix) error {
	if A.rows != B.Rows() || A.cols != B.Cols() {
		return ErrorDimensionMismatch
	}

	for index, value := range B.elements {
		i, j := A.GetRowColIndex(index)
		A.Set(i, j, A.Get(i, j)-value)
	}

	return nil
}

/*
Get the product of this matrix and another.
*/
func (A *SparseMatrix) Times(B MatrixRO) (Matrix, error) {
	/* uncomment this if an efficient version is written
	if Bs, ok := B.(*SparseMatrix); ok {
		return A.TimesSparse(Bs);
	}
	*/

	if A.cols != B.Rows() {
		return nil, ErrorDimensionMismatch
	}

	C := ZerosSparse(A.rows, B.Cols())

	for index, value := range A.elements {
		i, k := A.GetRowColIndex(index)
		//not sure if there is a more efficient way to do this without using
		//a different data structure
		for j := 0; j < B.Cols(); j++ {
			v := B.Get(k, j)
			if v != 0 {
				C.Set(i, j, C.Get(i, j)+value*v)
			}
		}
	}

	return C, nil
}

/*
Get the product of this matrix and another, optimized for sparsity.
*/
func (A *SparseMatrix) TimesSparse(B *SparseMatrix) (*SparseMatrix, error) {
	if A.cols != B.Rows() {
		return nil, ErrorDimensionMismatch
	}

	C := ZerosSparse(A.rows, B.Cols())

	for index, value := range A.elements {
		i, k := A.GetRowColIndex(index)
		//not sure if there is a more efficient way to do this without using
		//a different data structure
		for j := 0; j < B.Cols(); j++ {
			v := B.Get(k, j)
			if v != 0 {
				C.Set(i, j, C.Get(i, j)+value*v)
			}
		}
	}

	return C, nil
}

/*
Scale this matrix by f.
*/
func (A *SparseMatrix) Scale(f float64) {
	for index, value := range A.elements {
		A.elements[index] = value * f
	}
}

/*
Get the element-wise product of this matrix and another.
*/
func (A *SparseMatrix) ElementMult(B MatrixRO) (*SparseMatrix, error) {
	C := A.Copy()
	err := C.ScaleMatrix(B)
	return C, err
}

/*
Get the element-wise product of this matrix and another, optimized for sparsity.
*/
func (A *SparseMatrix) ElementMultSparse(B *SparseMatrix) (*SparseMatrix, error) {
	C := A.Copy()
	err := C.ScaleMatrixSparse(B)
	return C, err
}

/*
Scale this matrix by another, element-wise.
*/
func (A *SparseMatrix) ScaleMatrix(B MatrixRO) error {
	if A.rows != B.Rows() || A.cols != B.Cols() {
		return ErrorDimensionMismatch
	}

	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		A.Set(i, j, value*B.Get(i, j))
	}

	return nil
}

/*
Scale this matrix by another sparse matrix, element-wise. Optimized for sparsity.
*/
func (A *SparseMatrix) ScaleMatrixSparse(B *SparseMatrix) error {
	if len(B.elements) > len(A.elements) {
		if A.rows != B.rows || A.cols != B.cols {
			return ErrorDimensionMismatch
		}

		for index, value := range A.elements {
			i, j := A.GetRowColIndex(index)
			A.Set(i, j, value*B.Get(i, j))
		}
	}
	return A.ScaleMatrix(B)
}


================================================
FILE: sparse_basic.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "math"

/*
Swap two rows in this matrix.
*/
func (A *SparseMatrix) SwapRows(r1, r2 int) {
	js := map[int]bool{}
	for index := range A.elements {
		i, j := A.GetRowColIndex(index)
		if i == r1 || i == r2 {
			js[j] = true
		}
	}
	for j := range js {
		tmp := A.Get(r1, j)
		A.Set(r1, j, A.Get(r2, j))
		A.Set(r2, j, tmp)
	}
}

/*
Scale a row by a scalar.
*/
func (A *SparseMatrix) ScaleRow(r int, f float64) {
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		if i == r {
			A.Set(i, j, value*f)
		}
	}
}

/*
Add a multiple of row rs to row rd.
*/
func (A *SparseMatrix) ScaleAddRow(rd, rs int, f float64) {
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		if i == rs {
			A.Set(rd, j, A.Get(rd, j)+value*f)
		}
	}
}

func (A *SparseMatrix) Symmetric() bool {
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		if i != j && value != A.Get(j, i) {
			return false
		}
	}
	return true
}

func (A *SparseMatrix) Transpose() *SparseMatrix {
	B := ZerosSparse(A.cols, A.rows)
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		B.Set(j, i, value)
	}
	return B
}

func (A *SparseMatrix) Det() float64 {
	//TODO: obviously this is a horrible way to do it
	return A.DenseMatrix().Det()
}

func (A *SparseMatrix) Trace() (res float64) {
	for index, value := range A.elements {
		i, j := A.GetRowColIndex(index)
		if i == j {
			res += value
		}
	}
	return
}

func (A *SparseMatrix) OneNorm() (res float64) {
	for _, value := range A.elements {
		res += math.Abs(value)
	}
	return
}

func (A *SparseMatrix) TwoNorm() float64 {
	var sum float64 = 0
	for _, value := range A.elements {
		sum += value * value
	}
	return math.Sqrt(sum)
}

func (A *SparseMatrix) InfinityNorm() (res float64) {
	for _, value := range A.elements {
		res = max(res, math.Abs(value))
	}
	return
}


================================================
FILE: sparse_test.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import (
	"fmt"
	"math/rand"
	"testing"
)

func TestAdd_Sparse(t *testing.T) {
	A := NormalsSparse(3, 3, 9)
	B := NormalsSparse(3, 3, 9)
	C1, _ := A.Plus(B)
	C2, _ := A.PlusSparse(B)
	if !ApproxEquals(C1, Sum(A, B), ε) {
		t.Fail()
	}
	if !ApproxEquals(C2, Sum(A, B), ε) {
		t.Fail()
	}
}

func TestSubtract_Sparse(t *testing.T) {
	A := NormalsSparse(3, 3, 9)
	B := NormalsSparse(3, 3, 9)
	C1, _ := A.Minus(B)
	C2, _ := A.MinusSparse(B)
	if !ApproxEquals(C1, Difference(A, B), ε) {
		t.Fail()
	}
	if !ApproxEquals(C2, Difference(A, B), ε) {
		t.Fail()
	}
}

func TestTimes_Sparse(t *testing.T) {
	A := Normals(3, 3).SparseMatrix()
	B := Normals(3, 3).SparseMatrix()
	C1, _ := A.Times(B)
	C2, _ := A.TimesSparse(B)
	if !ApproxEquals(C1, Product(A, B), ε) {
		t.Fail()
	}
	if !ApproxEquals(C2, Product(A, B), ε) {
		t.Fail()
	}
}

func TestElementMult_Sparse(t *testing.T) {
	A := Normals(3, 3).SparseMatrix()
	B := Normals(3, 3).SparseMatrix()
	C1, _ := A.ElementMult(B)
	C2, _ := A.ElementMultSparse(B)
	D, _ := A.DenseMatrix().ElementMult(B)
	if !Equals(D, C1) {
		t.Fail()
	}
	if !Equals(D, C2) {
		t.Fail()
	}
}

func TestGetMatrix_Sparse(t *testing.T) {
	A := ZerosSparse(6, 6)
	for i := 0; i < 36; i++ {
		x := rand.Intn(6)
		y := rand.Intn(6)
		A.Set(y, x, 1)
	}
	B := A.GetMatrix(1, 1, 4, 4)

	for i := 0; i < 4; i++ {
		for j := 0; j < 4; j++ {
			if B.Get(i, j) != A.Get(i+1, j+1) {
				t.Fail()
			}
		}
	}

}

func TestAugment_Sparse(t *testing.T) {
	var A, B, C *SparseMatrix
	A = NormalsSparse(4, 4, 16)
	B = NormalsSparse(4, 4, 16)
	C, _ = A.Augment(B)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i, j+A.Cols()) != B.Get(i, j) {
				t.Fail()
			}
		}
	}

	A = NormalsSparse(2, 2, 4)
	B = NormalsSparse(4, 4, 16)
	C, err := A.Augment(B)
	if err == nil {
		t.Fail()
	}

	A = NormalsSparse(4, 4, 16)
	B = NormalsSparse(4, 2, 8)
	C, _ = A.Augment(B)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i, j+A.Cols()) != B.Get(i, j) {
				t.Fail()
			}
		}
	}
}

func TestStack_Sparse(t *testing.T) {
	var A, B, C *SparseMatrix
	A = NormalsSparse(4, 4, 16)
	B = NormalsSparse(4, 4, 16)
	C, _ = A.Stack(B)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i+A.Rows(), j) != B.Get(i, j) {
				t.Fail()
			}
		}
	}

	A = NormalsSparse(2, 2, 4)
	B = NormalsSparse(4, 4, 16)
	C, err := A.Stack(B)
	if err == nil {
		if verbose {
			fmt.Printf("%v\n", err)
		}
		t.Fail()
	}

	A = NormalsSparse(4, 4, 16)
	B = NormalsSparse(2, 4, 8)
	C, _ = A.Stack(B)
	for i := 0; i < A.Rows(); i++ {
		for j := 0; j < A.Cols(); j++ {
			if C.Get(i, j) != A.Get(i, j) {
				t.Fail()
			}
		}
	}
	for i := 0; i < B.Rows(); i++ {
		for j := 0; j < B.Cols(); j++ {
			if C.Get(i+A.Rows(), j) != B.Get(i, j) {
				t.Fail()
			}
		}
	}
}


================================================
FILE: util.go
================================================
// Copyright 2009 The GoMatrix Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package matrix

import "runtime"

func max(x, y float64) float64 {
	if x > y {
		return x
	}
	return y
}

func maxInt(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func min(x, y float64) float64 {
	if x < y {
		return x
	}
	return y
}

func minInt(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func sum(a []float64) (s float64) {
	for _, v := range a {
		s += v
	}
	return
}

func product(a []float64) float64 {
	p := float64(1)
	for _, v := range a {
		p *= v
	}
	return p
}

type box interface{}

func countBoxes(start, cap int) chan box {
	ints := make(chan box)
	go func() {
		for i := start; i < cap; i++ {
			ints <- i
		}
		close(ints)
	}()
	return ints
}

func parFor(inputs <-chan box, foo func(i box)) (wait func()) {
	n := runtime.GOMAXPROCS(0)
	block := make(chan bool, n)
	for j := 0; j < n; j++ {
		go func() {
			for {
				i, ok := <-inputs
				if !ok {
					break
				}
				foo(i)
			}
			block <- true
		}()
	}
	wait = func() {
		for i := 0; i < n; i++ {
			<-block
		}
	}
	return
}
Download .txt
gitextract_v_1rg_cr/

├── AUTHORS
├── LICENSE
├── README
├── arithmetic.go
├── dense.go
├── dense_arithmetic.go
├── dense_basic.go
├── dense_data.go
├── dense_decomp.go
├── dense_eigen.go
├── dense_svd.go
├── dense_test.go
├── densebench_test.go
├── error.go
├── matrix.go
├── matrix_test.go
├── pivot.go
├── pivot_arithmetic.go
├── pivot_basic.go
├── pivot_test.go
├── sparse.go
├── sparse_arithmetic.go
├── sparse_basic.go
├── sparse_test.go
└── util.go
Download .txt
SYMBOL INDEX (247 symbols across 22 files)

FILE: arithmetic.go
  function Sum (line 12) | func Sum(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {
  function Difference (line 30) | func Difference(A, B MatrixRO) (C *DenseMatrix) {
  function Product (line 42) | func Product(A MatrixRO, Bs ...MatrixRO) (C *DenseMatrix) {
  function Transpose (line 56) | func Transpose(A MatrixRO) (B Matrix) {
  function Inverse (line 69) | func Inverse(A MatrixRO) (B Matrix) {
  function Kronecker (line 89) | func Kronecker(A, B MatrixRO) (C *DenseMatrix) {
  function Vectorize (line 102) | func Vectorize(Am MatrixRO) (V *DenseMatrix) {
  function Unvectorize (line 108) | func Unvectorize(V MatrixRO, rows, cols int) (A *DenseMatrix) {
  function ParallelProduct (line 117) | func ParallelProduct(A, B MatrixRO) (C *DenseMatrix) {
  function Scaled (line 166) | func Scaled(A MatrixRO, f float64) (B *DenseMatrix) {
  function Equals (line 175) | func Equals(A, B MatrixRO) bool {
  function ApproxEquals (line 193) | func ApproxEquals(A, B MatrixRO, ε float64) bool {

FILE: dense.go
  type DenseMatrix (line 14) | type DenseMatrix struct
    method Arrays (line 26) | func (A *DenseMatrix) Arrays() [][]float64 {
    method Array (line 37) | func (A *DenseMatrix) Array() []float64 {
    method rowSlice (line 50) | func (A *DenseMatrix) rowSlice(row int) []float64 {
    method Get (line 57) | func (A *DenseMatrix) Get(i int, j int) (v float64) {
    method Set (line 78) | func (A *DenseMatrix) Set(i int, j int, v float64) {
    method GetMatrix (line 98) | func (A *DenseMatrix) GetMatrix(i, j, rows, cols int) *DenseMatrix {
    method SetMatrix (line 110) | func (A *DenseMatrix) SetMatrix(i, j int, B *DenseMatrix) {
    method GetColVector (line 118) | func (A *DenseMatrix) GetColVector(j int) *DenseMatrix {
    method GetRowVector (line 122) | func (A *DenseMatrix) GetRowVector(i int) *DenseMatrix {
    method L (line 129) | func (A *DenseMatrix) L() *DenseMatrix {
    method U (line 142) | func (A *DenseMatrix) U() *DenseMatrix {
    method Copy (line 152) | func (A *DenseMatrix) Copy() *DenseMatrix {
    method Augment (line 167) | func (A *DenseMatrix) Augment(B *DenseMatrix) (C *DenseMatrix, err err...
    method AugmentFill (line 176) | func (A *DenseMatrix) AugmentFill(B, C *DenseMatrix) (err error) {
    method Stack (line 198) | func (A *DenseMatrix) Stack(B *DenseMatrix) (C *DenseMatrix, err error) {
    method StackFill (line 207) | func (A *DenseMatrix) StackFill(B, C *DenseMatrix) (err error) {
    method SparseMatrix (line 230) | func (A *DenseMatrix) SparseMatrix() *SparseMatrix {
    method DenseMatrix (line 243) | func (A *DenseMatrix) DenseMatrix() *DenseMatrix {
    method String (line 345) | func (A *DenseMatrix) String() string { return String(A) }
  function Zeros (line 247) | func Zeros(rows, cols int) *DenseMatrix {
  function Ones (line 256) | func Ones(rows, cols int) *DenseMatrix {
  function Numbers (line 270) | func Numbers(rows, cols int, num float64) *DenseMatrix {
  function Eye (line 285) | func Eye(span int) *DenseMatrix {
  function Normals (line 293) | func Normals(rows, cols int) *DenseMatrix {
  function Diagonal (line 305) | func Diagonal(d []float64) *DenseMatrix {
  function MakeDenseCopy (line 314) | func MakeDenseCopy(A MatrixRO) *DenseMatrix {
  function MakeDenseMatrix (line 324) | func MakeDenseMatrix(elements []float64, rows, cols int) *DenseMatrix {
  function MakeDenseMatrixStacked (line 333) | func MakeDenseMatrixStacked(data [][]float64) *DenseMatrix {

FILE: dense_arithmetic.go
  method Plus (line 9) | func (A *DenseMatrix) Plus(B MatrixRO) (Matrix, error) {
  method PlusDense (line 14) | func (A *DenseMatrix) PlusDense(B *DenseMatrix) (*DenseMatrix, error) {
  method Minus (line 20) | func (A *DenseMatrix) Minus(B MatrixRO) (Matrix, error) {
  method MinusDense (line 26) | func (A *DenseMatrix) MinusDense(B *DenseMatrix) (*DenseMatrix, error) {
  method Add (line 32) | func (A *DenseMatrix) Add(B MatrixRO) error {
  method AddDense (line 48) | func (A *DenseMatrix) AddDense(B *DenseMatrix) error {
  method Subtract (line 62) | func (A *DenseMatrix) Subtract(B MatrixRO) error {
  method SubtractDense (line 82) | func (A *DenseMatrix) SubtractDense(B *DenseMatrix) error {
  method Times (line 102) | func (A *DenseMatrix) Times(B MatrixRO) (Matrix, error) {
  type parJob (line 126) | type parJob struct
  function parTimes1 (line 130) | func parTimes1(A, B, C *DenseMatrix) {
  function parTimes2 (line 167) | func parTimes2(A, B, C *DenseMatrix) {
  method TimesDense (line 224) | func (A *DenseMatrix) TimesDense(B *DenseMatrix) (C *DenseMatrix, err er...
  method TimesDenseFill (line 229) | func (A *DenseMatrix) TimesDenseFill(B, C *DenseMatrix) (err error) {
  function transposeTimes (line 260) | func transposeTimes(A, B, C *DenseMatrix) {
  method ElementMult (line 278) | func (A *DenseMatrix) ElementMult(B MatrixRO) (Matrix, error) {
  method ElementMultDense (line 284) | func (A *DenseMatrix) ElementMultDense(B *DenseMatrix) (*DenseMatrix, er...
  method Scale (line 290) | func (A *DenseMatrix) Scale(f float64) {
  method ScaleMatrix (line 300) | func (A *DenseMatrix) ScaleMatrix(B MatrixRO) error {
  method ScaleMatrixDense (line 318) | func (A *DenseMatrix) ScaleMatrixDense(B *DenseMatrix) error {

FILE: dense_basic.go
  method Symmetric (line 12) | func (A *DenseMatrix) Symmetric() bool {
  method SwapRows (line 26) | func (m *DenseMatrix) SwapRows(r1 int, r2 int) {
  method ScaleRow (line 36) | func (m *DenseMatrix) ScaleRow(r int, f float64) {
  method ScaleAddRow (line 44) | func (m *DenseMatrix) ScaleAddRow(rd int, rs int, f float64) {
  method Inverse (line 54) | func (A *DenseMatrix) Inverse() (*DenseMatrix, error) {
  method Det (line 84) | func (A *DenseMatrix) Det() float64 {
  method Trace (line 90) | func (A *DenseMatrix) Trace() float64 { return sum(A.DiagonalCopy()) }
  method OneNorm (line 92) | func (A *DenseMatrix) OneNorm() (ε float64) {
  method TwoNorm (line 101) | func (A *DenseMatrix) TwoNorm() float64 {
  method InfinityNorm (line 112) | func (A *DenseMatrix) InfinityNorm() (ε float64) {
  method Transpose (line 121) | func (A *DenseMatrix) Transpose() *DenseMatrix {
  method TransposeInPlace (line 131) | func (A *DenseMatrix) TransposeInPlace() (err error) {
  function solveLower (line 146) | func solveLower(A *DenseMatrix, b Matrix) *DenseMatrix {
  function solveUpper (line 159) | func solveUpper(A *DenseMatrix, b Matrix) *DenseMatrix {
  method Solve (line 171) | func (A *DenseMatrix) Solve(b MatrixRO) (*DenseMatrix, error) {
  method SolveDense (line 186) | func (A *DenseMatrix) SolveDense(b *DenseMatrix) (*DenseMatrix, error) {

FILE: dense_data.go
  method RowCopy (line 8) | func (A *DenseMatrix) RowCopy(i int) []float64 {
  method ColCopy (line 17) | func (A *DenseMatrix) ColCopy(j int) []float64 {
  method DiagonalCopy (line 26) | func (A *DenseMatrix) DiagonalCopy() []float64 {
  method BufferRow (line 38) | func (A *DenseMatrix) BufferRow(i int, buf []float64) {
  method BufferCol (line 44) | func (A *DenseMatrix) BufferCol(j int, buf []float64) {
  method BufferDiagonal (line 50) | func (A *DenseMatrix) BufferDiagonal(buf []float64) {
  method FillRow (line 56) | func (A *DenseMatrix) FillRow(i int, buf []float64) {
  method FillCol (line 62) | func (A *DenseMatrix) FillCol(j int, buf []float64) {
  method FillDiagonal (line 68) | func (A *DenseMatrix) FillDiagonal(buf []float64) {

FILE: dense_decomp.go
  method Cholesky (line 12) | func (A *DenseMatrix) Cholesky() (L *DenseMatrix, err error) {
  method LU (line 50) | func (A *DenseMatrix) LU() (L, U *DenseMatrix, P *PivotMatrix) {
  method LUInPlace (line 70) | func (A *DenseMatrix) LUInPlace() (P *PivotMatrix) {
  method QR (line 124) | func (A *DenseMatrix) QR() (Q, R *DenseMatrix) {

FILE: dense_eigen.go
  method Eigen (line 12) | func (A *DenseMatrix) Eigen() (V, D *DenseMatrix, err error) {
  function makeD (line 41) | func makeD(d []float64, e []float64) *DenseMatrix {
  function tred2 (line 59) | func tred2(V [][]float64, d []float64, e []float64) {
  function tql2 (line 176) | func tql2(V [][]float64, d []float64, e []float64) {
  function orthes (line 298) | func orthes(V [][]float64, d []float64, e []float64, H [][]float64, ort ...
  function hqr2 (line 395) | func hqr2(V [][]float64, d []float64, e []float64, H [][]float64, ort []...
  function cdiv (line 850) | func cdiv(xr float64, xi float64, yr float64, yi float64) (cdivr float64...

FILE: dense_svd.go
  method SVD (line 12) | func (Arg *DenseMatrix) SVD() (theU, Σ, theV *DenseMatrix, err error) {

FILE: dense_test.go
  constant ε (line 14) | ε = 0.000001
  constant verbose (line 15) | verbose = false
  constant speedTest (line 16) | speedTest = true
  function TestEquals (line 20) | func TestEquals(t *testing.T) {
  function TestApproximates (line 32) | func TestApproximates(t *testing.T) {
  function TestAdd (line 42) | func TestAdd(t *testing.T) {
  function TestSubtract (line 58) | func TestSubtract(t *testing.T) {
  function TestProduct (line 74) | func TestProduct(t *testing.T) {
  function TestParallelProduct (line 115) | func TestParallelProduct(t *testing.T) {
  function TestTimesDenseProcs (line 159) | func TestTimesDenseProcs(t *testing.T) {
  function TestElementMult (line 174) | func TestElementMult(t *testing.T) {
  function TestScale (line 206) | func TestScale(t *testing.T) {
  function TestScaleMatrix (line 221) | func TestScaleMatrix(t *testing.T) {
  function TestSymmetric (line 238) | func TestSymmetric(t *testing.T) {
  function TestInverse (line 261) | func TestInverse(t *testing.T) {
  function TestDet (line 288) | func TestDet(t *testing.T) {
  function TestTrace (line 303) | func TestTrace(t *testing.T) {
  function TestTranspose (line 318) | func TestTranspose(t *testing.T) {
  function TestSolve (line 330) | func TestSolve(t *testing.T) {
  function TestCholesky (line 353) | func TestCholesky(t *testing.T) {
  function TestLU (line 368) | func TestLU(t *testing.T) {
  function TestQR (line 422) | func TestQR(t *testing.T) {
  function TestEigen (line 456) | func TestEigen(t *testing.T) {
  function TestSVD (line 503) | func TestSVD(t *testing.T) {
  function TestGetMatrix (line 526) | func TestGetMatrix(t *testing.T) {
  function TestL (line 535) | func TestL(t *testing.T) {
  function TestU (line 571) | func TestU(t *testing.T) {
  function TestAugment (line 607) | func TestAugment(t *testing.T) {
  function TestStack (line 653) | func TestStack(t *testing.T) {
  function TestZeros (line 702) | func TestZeros(t *testing.T) {
  function TestNumbers (line 713) | func TestNumbers(t *testing.T) {
  function TestOnes (line 728) | func TestOnes(t *testing.T) {
  function TestEye (line 740) | func TestEye(t *testing.T) {
  function TestNormals (line 752) | func TestNormals(t *testing.T) {
  function TestKronecker (line 760) | func TestKronecker(t *testing.T) {
  function TestVectorize (line 773) | func TestVectorize(t *testing.T) {
  function TestSubmatrix (line 782) | func TestSubmatrix(t *testing.T) {

FILE: densebench_test.go
  function BenchmarkTransposeTimes (line 9) | func BenchmarkTransposeTimes(b *testing.B) {

FILE: error.go
  constant errorNilMatrix (line 11) | errorNilMatrix = iota + 1
  constant errorDimensionMismatch (line 13) | errorDimensionMismatch
  constant errorIllegalIndex (line 15) | errorIllegalIndex
  constant exceptionSingular (line 17) | exceptionSingular
  constant exceptionNotSPD (line 19) | exceptionNotSPD
  type error_ (line 22) | type error_
    method Error (line 24) | func (e error_) Error() string {
    method String (line 39) | func (e error_) String() string {

FILE: matrix.go
  type MatrixRO (line 22) | type MatrixRO interface
  type Matrix (line 58) | type Matrix interface
  type matrix (line 69) | type matrix struct
    method Nil (line 74) | func (A *matrix) Nil() bool { return A == nil }
    method Rows (line 76) | func (A *matrix) Rows() int { return A.rows }
    method Cols (line 78) | func (A *matrix) Cols() int { return A.cols }
    method NumElements (line 80) | func (A *matrix) NumElements() int { return A.rows * A.cols }
    method GetSize (line 82) | func (A *matrix) GetSize() (rows, cols int) {
  function ParseMatlab (line 93) | func ParseMatlab(txt string) (A *DenseMatrix, err error) {
  function String (line 180) | func String(A MatrixRO) string {

FILE: matrix_test.go
  function TestParse (line 7) | func TestParse(t *testing.T) {

FILE: pivot.go
  type PivotMatrix (line 11) | type PivotMatrix struct
    method Get (line 17) | func (P *PivotMatrix) Get(i, j int) float64 {
    method DenseMatrix (line 35) | func (P *PivotMatrix) DenseMatrix() *DenseMatrix {
    method SparseMatrix (line 46) | func (P *PivotMatrix) SparseMatrix() *SparseMatrix {
    method Copy (line 57) | func (P *PivotMatrix) Copy() *PivotMatrix { return MakePivotMatrix(P.p...
    method String (line 69) | func (A *PivotMatrix) String() string { return String(A) }
  function MakePivotMatrix (line 59) | func MakePivotMatrix(pivots []int, pivotSign float64) *PivotMatrix {

FILE: pivot_arithmetic.go
  method Minus (line 7) | func (P *PivotMatrix) Minus(A MatrixRO) (Matrix, error) {
  method Plus (line 16) | func (P *PivotMatrix) Plus(A MatrixRO) (Matrix, error) {
  method Times (line 28) | func (P *PivotMatrix) Times(A MatrixRO) (Matrix, error) {
  method TimesPivot (line 47) | func (P *PivotMatrix) TimesPivot(A *PivotMatrix) (*PivotMatrix, error) {
  method RowPivotDense (line 65) | func (P *PivotMatrix) RowPivotDense(A *DenseMatrix) (*DenseMatrix, error) {
  method ColPivotDense (line 84) | func (P *PivotMatrix) ColPivotDense(A *DenseMatrix) (*DenseMatrix, error) {
  method RowPivotSparse (line 103) | func (P *PivotMatrix) RowPivotSparse(A *SparseMatrix) (*SparseMatrix, er...
  method ColPivotSparse (line 120) | func (P *PivotMatrix) ColPivotSparse(A *SparseMatrix) (*SparseMatrix, er...

FILE: pivot_basic.go
  method SwapRows (line 12) | func (P *PivotMatrix) SwapRows(r1, r2 int) error {
  method Symmetric (line 22) | func (P *PivotMatrix) Symmetric() bool {
  method Inverse (line 31) | func (A *PivotMatrix) Inverse() *PivotMatrix { return A.Transpose() }
  method Transpose (line 33) | func (P *PivotMatrix) Transpose() *PivotMatrix {
  method Det (line 41) | func (P *PivotMatrix) Det() float64 { return P.pivotSign }
  method Trace (line 43) | func (P *PivotMatrix) Trace() (r float64) {
  method Solve (line 55) | func (P *PivotMatrix) Solve(b MatrixRO) (Matrix, error) {
  method OneNorm (line 59) | func (A *PivotMatrix) OneNorm() float64      { return float64(A.rows) }
  method TwoNorm (line 60) | func (A *PivotMatrix) TwoNorm() float64      { return math.Sqrt(float64(...
  method InfinityNorm (line 61) | func (A *PivotMatrix) InfinityNorm() float64 { return 1 }

FILE: pivot_test.go
  function TestTimes_Pivot (line 10) | func TestTimes_Pivot(t *testing.T) {
  function TestRowPivot (line 22) | func TestRowPivot(t *testing.T) {
  function TestColPivot (line 43) | func TestColPivot(t *testing.T) {

FILE: sparse.go
  type SparseMatrix (line 12) | type SparseMatrix struct
    method Get (line 22) | func (A *SparseMatrix) Get(i, j int) float64 {
    method GetIndex (line 38) | func (A *SparseMatrix) GetIndex(index int) float64 {
    method GetRowIndex (line 49) | func (A *SparseMatrix) GetRowIndex(index int) (i int) {
    method GetColIndex (line 57) | func (A *SparseMatrix) GetColIndex(index int) (j int) {
    method GetRowColIndex (line 65) | func (A *SparseMatrix) GetRowColIndex(index int) (i int, j int) {
    method Set (line 71) | func (A *SparseMatrix) Set(i int, j int, v float64) {
    method SetIndex (line 91) | func (A *SparseMatrix) SetIndex(index int, v float64) {
    method Indices (line 103) | func (A *SparseMatrix) Indices() (out chan int) {
    method GetMatrix (line 122) | func (A *SparseMatrix) GetMatrix(i, j, rows, cols int) (subMatrix *Spa...
    method GetColVector (line 143) | func (A *SparseMatrix) GetColVector(j int) *SparseMatrix {
    method GetRowVector (line 150) | func (A *SparseMatrix) GetRowVector(i int) *SparseMatrix {
    method Augment (line 157) | func (A *SparseMatrix) Augment(B *SparseMatrix) (*SparseMatrix, error) {
    method Stack (line 179) | func (A *SparseMatrix) Stack(B *SparseMatrix) (*SparseMatrix, error) {
    method L (line 201) | func (A *SparseMatrix) L() *SparseMatrix {
    method U (line 215) | func (A *SparseMatrix) U() *SparseMatrix {
    method Copy (line 226) | func (A *SparseMatrix) Copy() *SparseMatrix {
    method DenseMatrix (line 269) | func (A *SparseMatrix) DenseMatrix() *DenseMatrix {
    method SparseMatrix (line 278) | func (A *SparseMatrix) SparseMatrix() *SparseMatrix {
    method String (line 282) | func (A *SparseMatrix) String() string { return String(A) }
  function ZerosSparse (line 234) | func ZerosSparse(rows int, cols int) *SparseMatrix {
  function NormalsSparse (line 247) | func NormalsSparse(rows int, cols int, n int) *SparseMatrix {
  function MakeSparseMatrix (line 260) | func MakeSparseMatrix(elements map[int]float64, rows int, cols int) *Spa...

FILE: sparse_arithmetic.go
  method Plus (line 10) | func (A *SparseMatrix) Plus(B MatrixRO) (Matrix, error) {
  method PlusSparse (line 19) | func (A *SparseMatrix) PlusSparse(B *SparseMatrix) (*SparseMatrix, error) {
  method Minus (line 28) | func (A *SparseMatrix) Minus(B MatrixRO) (Matrix, error) {
  method MinusSparse (line 37) | func (A *SparseMatrix) MinusSparse(B *SparseMatrix) (*SparseMatrix, erro...
  method Add (line 46) | func (A *SparseMatrix) Add(B MatrixRO) error {
  method AddSparse (line 67) | func (A *SparseMatrix) AddSparse(B *SparseMatrix) error {
  method Subtract (line 83) | func (A *SparseMatrix) Subtract(B MatrixRO) error {
  method SubtractSparse (line 104) | func (A *SparseMatrix) SubtractSparse(B *SparseMatrix) error {
  method Times (line 120) | func (A *SparseMatrix) Times(B MatrixRO) (Matrix, error) {
  method TimesSparse (line 151) | func (A *SparseMatrix) TimesSparse(B *SparseMatrix) (*SparseMatrix, erro...
  method Scale (line 176) | func (A *SparseMatrix) Scale(f float64) {
  method ElementMult (line 185) | func (A *SparseMatrix) ElementMult(B MatrixRO) (*SparseMatrix, error) {
  method ElementMultSparse (line 194) | func (A *SparseMatrix) ElementMultSparse(B *SparseMatrix) (*SparseMatrix...
  method ScaleMatrix (line 203) | func (A *SparseMatrix) ScaleMatrix(B MatrixRO) error {
  method ScaleMatrixSparse (line 219) | func (A *SparseMatrix) ScaleMatrixSparse(B *SparseMatrix) error {

FILE: sparse_basic.go
  method SwapRows (line 12) | func (A *SparseMatrix) SwapRows(r1, r2 int) {
  method ScaleRow (line 30) | func (A *SparseMatrix) ScaleRow(r int, f float64) {
  method ScaleAddRow (line 42) | func (A *SparseMatrix) ScaleAddRow(rd, rs int, f float64) {
  method Symmetric (line 51) | func (A *SparseMatrix) Symmetric() bool {
  method Transpose (line 61) | func (A *SparseMatrix) Transpose() *SparseMatrix {
  method Det (line 70) | func (A *SparseMatrix) Det() float64 {
  method Trace (line 75) | func (A *SparseMatrix) Trace() (res float64) {
  method OneNorm (line 85) | func (A *SparseMatrix) OneNorm() (res float64) {
  method TwoNorm (line 92) | func (A *SparseMatrix) TwoNorm() float64 {
  method InfinityNorm (line 100) | func (A *SparseMatrix) InfinityNorm() (res float64) {

FILE: sparse_test.go
  function TestAdd_Sparse (line 13) | func TestAdd_Sparse(t *testing.T) {
  function TestSubtract_Sparse (line 26) | func TestSubtract_Sparse(t *testing.T) {
  function TestTimes_Sparse (line 39) | func TestTimes_Sparse(t *testing.T) {
  function TestElementMult_Sparse (line 52) | func TestElementMult_Sparse(t *testing.T) {
  function TestGetMatrix_Sparse (line 66) | func TestGetMatrix_Sparse(t *testing.T) {
  function TestAugment_Sparse (line 85) | func TestAugment_Sparse(t *testing.T) {
  function TestStack_Sparse (line 131) | func TestStack_Sparse(t *testing.T) {

FILE: util.go
  function max (line 9) | func max(x, y float64) float64 {
  function maxInt (line 16) | func maxInt(x, y int) int {
  function min (line 23) | func min(x, y float64) float64 {
  function minInt (line 30) | func minInt(x, y int) int {
  function sum (line 37) | func sum(a []float64) (s float64) {
  function product (line 44) | func product(a []float64) float64 {
  type box (line 52) | type box interface
  function countBoxes (line 54) | func countBoxes(start, cap int) chan box {
  function parFor (line 65) | func parFor(inputs <-chan box, foo func(i box)) (wait func()) {
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (112K chars).
[
  {
    "path": "AUTHORS",
    "chars": 45,
    "preview": "John Asmuth <jasmuth@gmail.com>\nRyanne Dolan\n"
  },
  {
    "path": "LICENSE",
    "chars": 1229,
    "preview": "\u0001\nCopyright (c) 2013 the AUTHORS. All rights reserved.\n\nRedistribution and use in source and binary forms, with or witho"
  },
  {
    "path": "README",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "arithmetic.go",
    "chars": 3660,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense.go",
    "chars": 6867,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense_arithmetic.go",
    "chars": 7134,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense_basic.go",
    "chars": 3840,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense_data.go",
    "chars": 1539,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense_decomp.go",
    "chars": 3324,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense_eigen.go",
    "chars": 16283,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense_svd.go",
    "chars": 9248,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "dense_test.go",
    "chars": 13461,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "densebench_test.go",
    "chars": 692,
    "preview": "package matrix\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc BenchmarkTransposeTimes(b *testing.B) {\n\tfmt.Println(\"benchma"
  },
  {
    "path": "error.go",
    "chars": 1542,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "matrix.go",
    "chars": 3997,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "matrix_test.go",
    "chars": 248,
    "preview": "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"
  },
  {
    "path": "pivot.go",
    "chars": 1360,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "pivot_arithmetic.go",
    "chars": 3052,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "pivot_basic.go",
    "chars": 1432,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "pivot_test.go",
    "chars": 1260,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "sparse.go",
    "chars": 5772,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "sparse_arithmetic.go",
    "chars": 4918,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "sparse_basic.go",
    "chars": 2053,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "sparse_test.go",
    "chars": 3374,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  },
  {
    "path": "util.go",
    "chars": 1184,
    "preview": "// Copyright 2009 The GoMatrix Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// li"
  }
]

About this extraction

This page contains the full source code of the skelterjohn/go.matrix GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (95.2 KB), approximately 37.1k tokens, and a symbol index with 247 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!