mirror of
				https://github.com/gonum/gonum.git
				synced 2025-11-01 02:52:49 +08:00 
			
		
		
		
	matrix/mat64: use pools for []float64 and []int where possible
This commit is contained in:
		| @@ -39,7 +39,8 @@ type Cholesky struct { | |||||||
| // the norm is estimated from the decomposition. | // the norm is estimated from the decomposition. | ||||||
| func (c *Cholesky) updateCond(norm float64) { | func (c *Cholesky) updateCond(norm float64) { | ||||||
| 	n := c.chol.mat.N | 	n := c.chol.mat.N | ||||||
| 	work := make([]float64, 3*n) | 	work := getFloats(3*n, false) | ||||||
|  | 	defer putFloats(work) | ||||||
| 	if norm < 0 { | 	if norm < 0 { | ||||||
| 		// This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||. | 		// This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||. | ||||||
| 		// Here, A = U^T * U. | 		// Here, A = U^T * U. | ||||||
| @@ -52,8 +53,9 @@ func (c *Cholesky) updateCond(norm float64) { | |||||||
| 		norm = unorm * lnorm | 		norm = unorm * lnorm | ||||||
| 	} | 	} | ||||||
| 	sym := c.chol.asSymBlas() | 	sym := c.chol.asSymBlas() | ||||||
| 	iwork := make([]int, n) | 	iwork := getInts(n, false) | ||||||
| 	v := lapack64.Pocon(sym, norm, work, iwork) | 	v := lapack64.Pocon(sym, norm, work, iwork) | ||||||
|  | 	putInts(iwork) | ||||||
| 	c.cond = 1 / v | 	c.cond = 1 / v | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -70,8 +72,9 @@ func (c *Cholesky) Factorize(a Symmetric) (ok bool) { | |||||||
| 	copySymIntoTriangle(c.chol, a) | 	copySymIntoTriangle(c.chol, a) | ||||||
|  |  | ||||||
| 	sym := c.chol.asSymBlas() | 	sym := c.chol.asSymBlas() | ||||||
| 	work := make([]float64, c.chol.mat.N) | 	work := getFloats(c.chol.mat.N, false) | ||||||
| 	norm := lapack64.Lansy(matrix.CondNorm, sym, work) | 	norm := lapack64.Lansy(matrix.CondNorm, sym, work) | ||||||
|  | 	putFloats(work) | ||||||
| 	_, ok = lapack64.Potrf(sym) | 	_, ok = lapack64.Potrf(sym) | ||||||
| 	if ok { | 	if ok { | ||||||
| 		c.updateCond(norm) | 		c.updateCond(norm) | ||||||
| @@ -345,7 +348,8 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x *Vector) (ok bool | |||||||
| 	//   EPFL Technical Report 161468 (2004) | 	//   EPFL Technical Report 161468 (2004) | ||||||
| 	//   http://infoscience.epfl.ch/record/161468 | 	//   http://infoscience.epfl.ch/record/161468 | ||||||
|  |  | ||||||
| 	work := make([]float64, n) | 	work := getFloats(n, false) | ||||||
|  | 	defer putFloats(work) | ||||||
| 	blas64.Copy(n, x.RawVector(), blas64.Vector{1, work}) | 	blas64.Copy(n, x.RawVector(), blas64.Vector{1, work}) | ||||||
|  |  | ||||||
| 	if alpha > 0 { | 	if alpha > 0 { | ||||||
| @@ -404,8 +408,10 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x *Vector) (ok bool | |||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
| 	norm = math.Sqrt((1 + norm) * (1 - norm)) | 	norm = math.Sqrt((1 + norm) * (1 - norm)) | ||||||
| 	cos := make([]float64, n) | 	cos := getFloats(n, false) | ||||||
| 	sin := make([]float64, n) | 	defer putFloats(cos) | ||||||
|  | 	sin := getFloats(n, false) | ||||||
|  | 	defer putFloats(sin) | ||||||
| 	for i := n - 1; i >= 0; i-- { | 	for i := n - 1; i >= 0; i-- { | ||||||
| 		// Compute parameters of Givens matrices that zero elements of p | 		// Compute parameters of Givens matrices that zero elements of p | ||||||
| 		// backwards. | 		// backwards. | ||||||
|   | |||||||
| @@ -230,18 +230,22 @@ func (m *Dense) Inverse(a Matrix) error { | |||||||
| 	default: | 	default: | ||||||
| 		m.Copy(a) | 		m.Copy(a) | ||||||
| 	} | 	} | ||||||
| 	ipiv := make([]int, r) | 	ipiv := getInts(r, false) | ||||||
|  | 	defer putInts(ipiv) | ||||||
| 	ok := lapack64.Getrf(m.mat, ipiv) | 	ok := lapack64.Getrf(m.mat, ipiv) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return matrix.Condition(math.Inf(1)) | 		return matrix.Condition(math.Inf(1)) | ||||||
| 	} | 	} | ||||||
| 	work := make([]float64, 1, 4*r) // must be at least 4*r for cond. | 	work := getFloats(4*r, false) // must be at least 4*r for cond. | ||||||
| 	lapack64.Getri(m.mat, ipiv, work, -1) | 	lapack64.Getri(m.mat, ipiv, work, -1) | ||||||
| 	if int(work[0]) > 4*r { | 	if int(work[0]) > 4*r { | ||||||
| 		work = make([]float64, int(work[0])) | 		l := int(work[0]) | ||||||
|  | 		putFloats(work) | ||||||
|  | 		work = getFloats(l, false) | ||||||
| 	} else { | 	} else { | ||||||
| 		work = work[:4*r] | 		work = work[:4*r] | ||||||
| 	} | 	} | ||||||
|  | 	defer putFloats(work) | ||||||
| 	lapack64.Getri(m.mat, ipiv, work, len(work)) | 	lapack64.Getri(m.mat, ipiv, work, len(work)) | ||||||
| 	norm := lapack64.Lange(matrix.CondNorm, m.mat, work) | 	norm := lapack64.Lange(matrix.CondNorm, m.mat, work) | ||||||
| 	rcond := lapack64.Gecon(matrix.CondNorm, m.mat, norm, work, ipiv) // reuse ipiv | 	rcond := lapack64.Gecon(matrix.CondNorm, m.mat, norm, work, ipiv) // reuse ipiv | ||||||
| @@ -426,7 +430,8 @@ func (m *Dense) Mul(a, b Matrix) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	row := make([]float64, ac) | 	row := getFloats(ac, false) | ||||||
|  | 	defer putFloats(row) | ||||||
| 	for r := 0; r < ar; r++ { | 	for r := 0; r < ar; r++ { | ||||||
| 		for i := range row { | 		for i := range row { | ||||||
| 			row[i] = a.At(r, i) | 			row[i] = a.At(r, i) | ||||||
|   | |||||||
| @@ -44,11 +44,12 @@ func (e *EigenSym) Factorize(a Symmetric, vectors bool) (ok bool) { | |||||||
| 		jobz = lapack.ComputeEV | 		jobz = lapack.ComputeEV | ||||||
| 	} | 	} | ||||||
| 	w := make([]float64, n) | 	w := make([]float64, n) | ||||||
| 	work := make([]float64, 1) | 	work := []float64{0} | ||||||
| 	lapack64.Syev(jobz, sd.mat, w, work, -1) | 	lapack64.Syev(jobz, sd.mat, w, work, -1) | ||||||
|  |  | ||||||
| 	work = make([]float64, int(work[0])) | 	work = getFloats(int(work[0]), false) | ||||||
| 	ok = lapack64.Syev(jobz, sd.mat, w, work, len(work)) | 	ok = lapack64.Syev(jobz, sd.mat, w, work, len(work)) | ||||||
|  | 	putFloats(work) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		e.vectorsComputed = false | 		e.vectorsComputed = false | ||||||
| 		e.values = nil | 		e.values = nil | ||||||
| @@ -165,13 +166,16 @@ func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) { | |||||||
| 		jobvr = lapack.ComputeRightEV | 		jobvr = lapack.ComputeRightEV | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	wr := make([]float64, c) | 	wr := getFloats(c, false) | ||||||
| 	wi := make([]float64, c) | 	defer putFloats(wr) | ||||||
|  | 	wi := getFloats(c, false) | ||||||
|  | 	defer putFloats(wi) | ||||||
|  |  | ||||||
| 	work := make([]float64, 1) | 	work := []float64{0} | ||||||
| 	lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, -1) | 	lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, -1) | ||||||
| 	work = make([]float64, int(work[0])) | 	work = getFloats(int(work[0]), false) | ||||||
| 	first := lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, len(work)) | 	first := lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, len(work)) | ||||||
|  | 	putFloats(work) | ||||||
|  |  | ||||||
| 	if first != 0 { | 	if first != 0 { | ||||||
| 		e.values = nil | 		e.values = nil | ||||||
|   | |||||||
| @@ -24,11 +24,13 @@ func (lq *LQ) updateCond() { | |||||||
| 	// A = LQ, where Q is orthonormal. Orthonormal multiplications do not change | 	// A = LQ, where Q is orthonormal. Orthonormal multiplications do not change | ||||||
| 	// the condition number. Thus, ||A|| = ||L|| ||Q|| = ||Q||. | 	// the condition number. Thus, ||A|| = ||L|| ||Q|| = ||Q||. | ||||||
| 	m := lq.lq.mat.Rows | 	m := lq.lq.mat.Rows | ||||||
| 	work := make([]float64, 3*m) | 	work := getFloats(3*m, false) | ||||||
| 	iwork := make([]int, m) | 	iwork := getInts(m, false) | ||||||
| 	l := lq.lq.asTriDense(m, blas.NonUnit, blas.Lower) | 	l := lq.lq.asTriDense(m, blas.NonUnit, blas.Lower) | ||||||
| 	v := lapack64.Trcon(matrix.CondNorm, l.mat, work, iwork) | 	v := lapack64.Trcon(matrix.CondNorm, l.mat, work, iwork) | ||||||
| 	lq.cond = 1 / v | 	lq.cond = 1 / v | ||||||
|  | 	putFloats(work) | ||||||
|  | 	putInts(iwork) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Factorize computes the LQ factorization of an m×n matrix a where n <= m. The LQ | // Factorize computes the LQ factorization of an m×n matrix a where n <= m. The LQ | ||||||
| @@ -47,11 +49,12 @@ func (lq *LQ) Factorize(a Matrix) { | |||||||
| 		lq.lq = &Dense{} | 		lq.lq = &Dense{} | ||||||
| 	} | 	} | ||||||
| 	lq.lq.Clone(a) | 	lq.lq.Clone(a) | ||||||
| 	work := make([]float64, 1) | 	work := []float64{0} | ||||||
| 	lq.tau = make([]float64, k) | 	lq.tau = make([]float64, k) | ||||||
| 	lapack64.Gelqf(lq.lq.mat, lq.tau, work, -1) | 	lapack64.Gelqf(lq.lq.mat, lq.tau, work, -1) | ||||||
| 	work = make([]float64, int(work[0])) | 	work = getFloats(int(work[0]), false) | ||||||
| 	lapack64.Gelqf(lq.lq.mat, lq.tau, work, len(work)) | 	lapack64.Gelqf(lq.lq.mat, lq.tau, work, len(work)) | ||||||
|  | 	putFloats(work) | ||||||
| 	lq.updateCond() | 	lq.updateCond() | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -110,10 +113,11 @@ func (lq *LQ) QTo(dst *Dense) *Dense { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Construct Q from the elementary reflectors. | 	// Construct Q from the elementary reflectors. | ||||||
| 	work := make([]float64, 1) | 	work := []float64{0} | ||||||
| 	lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, q, work, -1) | 	lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, q, work, -1) | ||||||
| 	work = make([]float64, int(work[0])) | 	work = getFloats(int(work[0]), false) | ||||||
| 	lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, q, work, len(work)) | 	lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, q, work, len(work)) | ||||||
|  | 	putFloats(work) | ||||||
|  |  | ||||||
| 	return dst | 	return dst | ||||||
| } | } | ||||||
| @@ -152,10 +156,11 @@ func (m *Dense) SolveLQ(lq *LQ, trans bool, b Matrix) error { | |||||||
| 	x.Copy(b) | 	x.Copy(b) | ||||||
| 	t := lq.lq.asTriDense(lq.lq.mat.Rows, blas.NonUnit, blas.Lower).mat | 	t := lq.lq.asTriDense(lq.lq.mat.Rows, blas.NonUnit, blas.Lower).mat | ||||||
| 	if trans { | 	if trans { | ||||||
| 		work := make([]float64, 1) | 		work := []float64{0} | ||||||
| 		lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, -1) | 		lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, -1) | ||||||
| 		work = make([]float64, int(work[0])) | 		work = getFloats(int(work[0]), false) | ||||||
| 		lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, len(work)) | 		lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, len(work)) | ||||||
|  | 		putFloats(work) | ||||||
|  |  | ||||||
| 		ok := lapack64.Trtrs(blas.Trans, t, x.mat) | 		ok := lapack64.Trtrs(blas.Trans, t, x.mat) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| @@ -169,10 +174,11 @@ func (m *Dense) SolveLQ(lq *LQ, trans bool, b Matrix) error { | |||||||
| 		for i := r; i < c; i++ { | 		for i := r; i < c; i++ { | ||||||
| 			zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) | 			zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) | ||||||
| 		} | 		} | ||||||
| 		work := make([]float64, 1) | 		work := []float64{0} | ||||||
| 		lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, -1) | 		lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, -1) | ||||||
| 		work = make([]float64, int(work[0])) | 		work = getFloats(int(work[0]), false) | ||||||
| 		lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, len(work)) | 		lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, len(work)) | ||||||
|  | 		putFloats(work) | ||||||
| 	} | 	} | ||||||
| 	// M was set above to be the correct size for the result. | 	// M was set above to be the correct size for the result. | ||||||
| 	m.Copy(x) | 	m.Copy(x) | ||||||
|   | |||||||
| @@ -27,8 +27,10 @@ type LU struct { | |||||||
| // norm of the original matrix. If norm is negative it will be estimated. | // norm of the original matrix. If norm is negative it will be estimated. | ||||||
| func (lu *LU) updateCond(norm float64) { | func (lu *LU) updateCond(norm float64) { | ||||||
| 	n := lu.lu.mat.Cols | 	n := lu.lu.mat.Cols | ||||||
| 	work := make([]float64, 4*n) | 	work := getFloats(4*n, false) | ||||||
| 	iwork := make([]int, n) | 	defer putFloats(work) | ||||||
|  | 	iwork := getInts(n, false) | ||||||
|  | 	defer putInts(iwork) | ||||||
| 	if norm < 0 { | 	if norm < 0 { | ||||||
| 		// This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||. | 		// This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||. | ||||||
| 		// The condition number is ||A|| || A^-1||, so this will underestimate | 		// The condition number is ||A|| || A^-1||, so this will underestimate | ||||||
| @@ -68,8 +70,9 @@ func (lu *LU) Factorize(a Matrix) { | |||||||
| 		lu.pivot = make([]int, r) | 		lu.pivot = make([]int, r) | ||||||
| 	} | 	} | ||||||
| 	lu.pivot = lu.pivot[:r] | 	lu.pivot = lu.pivot[:r] | ||||||
| 	work := make([]float64, r) | 	work := getFloats(r, false) | ||||||
| 	anorm := lapack64.Lange(matrix.CondNorm, lu.lu.mat, work) | 	anorm := lapack64.Lange(matrix.CondNorm, lu.lu.mat, work) | ||||||
|  | 	putFloats(work) | ||||||
| 	lapack64.Getrf(lu.lu.mat, lu.pivot) | 	lapack64.Getrf(lu.lu.mat, lu.pivot) | ||||||
| 	lu.updateCond(anorm) | 	lu.updateCond(anorm) | ||||||
| } | } | ||||||
| @@ -99,7 +102,8 @@ func (lu *LU) Det() float64 { | |||||||
| // division expressions is generally improved by working in log space. | // division expressions is generally improved by working in log space. | ||||||
| func (lu *LU) LogDet() (det float64, sign float64) { | func (lu *LU) LogDet() (det float64, sign float64) { | ||||||
| 	_, n := lu.lu.Dims() | 	_, n := lu.lu.Dims() | ||||||
| 	logDiag := make([]float64, n) | 	logDiag := getFloats(n, false) | ||||||
|  | 	defer putFloats(logDiag) | ||||||
| 	sign = 1.0 | 	sign = 1.0 | ||||||
| 	for i := 0; i < n; i++ { | 	for i := 0; i < n; i++ { | ||||||
| 		v := lu.lu.at(i, i) | 		v := lu.lu.at(i, i) | ||||||
| @@ -171,8 +175,10 @@ func (lu *LU) RankOne(orig *LU, alpha float64, x, y *Vector) { | |||||||
| 		lu.lu.Copy(orig.lu) | 		lu.lu.Copy(orig.lu) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	xs := make([]float64, n) | 	xs := getFloats(n, false) | ||||||
| 	ys := make([]float64, n) | 	defer putFloats(xs) | ||||||
|  | 	ys := getFloats(n, false) | ||||||
|  | 	defer putFloats(ys) | ||||||
| 	for i := 0; i < n; i++ { | 	for i := 0; i < n; i++ { | ||||||
| 		xs[i] = x.at(i) | 		xs[i] = x.at(i) | ||||||
| 		ys[i] = y.at(i) | 		ys[i] = y.at(i) | ||||||
|   | |||||||
| @@ -292,48 +292,58 @@ func Cond(a Matrix, norm float64) float64 { | |||||||
| 		// Use the LU decomposition to compute the condition number. | 		// Use the LU decomposition to compute the condition number. | ||||||
| 		tmp := getWorkspace(m, n, false) | 		tmp := getWorkspace(m, n, false) | ||||||
| 		tmp.Copy(a) | 		tmp.Copy(a) | ||||||
| 		work := make([]float64, 4*n) | 		work := getFloats(4*n, false) | ||||||
| 		aNorm := lapack64.Lange(lnorm, tmp.mat, work) | 		aNorm := lapack64.Lange(lnorm, tmp.mat, work) | ||||||
| 		pivot := make([]int, m) | 		pivot := getInts(m, false) | ||||||
| 		lapack64.Getrf(tmp.mat, pivot) | 		lapack64.Getrf(tmp.mat, pivot) | ||||||
| 		iwork := make([]int, n) | 		iwork := make([]int, n) | ||||||
| 		v := lapack64.Gecon(lnorm, tmp.mat, aNorm, work, iwork) | 		v := lapack64.Gecon(lnorm, tmp.mat, aNorm, work, iwork) | ||||||
| 		putWorkspace(tmp) | 		putWorkspace(tmp) | ||||||
|  | 		putFloats(work) | ||||||
|  | 		putInts(pivot) | ||||||
| 		return 1 / v | 		return 1 / v | ||||||
| 	} | 	} | ||||||
| 	if m > n { | 	if m > n { | ||||||
| 		// Use the QR factorization to compute the condition number. | 		// Use the QR factorization to compute the condition number. | ||||||
| 		tmp := getWorkspace(m, n, false) | 		tmp := getWorkspace(m, n, false) | ||||||
| 		tmp.Copy(a) | 		tmp.Copy(a) | ||||||
| 		work := make([]float64, 3*n) | 		work := getFloats(3*n, false) | ||||||
| 		tau := make([]float64, min(m, n)) | 		tau := getFloats(min(m, n), false) | ||||||
| 		lapack64.Geqrf(tmp.mat, tau, work, -1) | 		lapack64.Geqrf(tmp.mat, tau, work, -1) | ||||||
| 		if int(work[0]) > len(work) { | 		if l := int(work[0]); l > len(work) { | ||||||
| 			work = make([]float64, int(work[0])) | 			putFloats(work) | ||||||
|  | 			work = getFloats(l, false) | ||||||
| 		} | 		} | ||||||
| 		lapack64.Geqrf(tmp.mat, tau, work, len(work)) | 		lapack64.Geqrf(tmp.mat, tau, work, len(work)) | ||||||
|  |  | ||||||
| 		iwork := make([]int, n) | 		iwork := getInts(n, false) | ||||||
| 		r := tmp.asTriDense(n, blas.NonUnit, blas.Upper) | 		r := tmp.asTriDense(n, blas.NonUnit, blas.Upper) | ||||||
| 		v := lapack64.Trcon(lnorm, r.mat, work, iwork) | 		v := lapack64.Trcon(lnorm, r.mat, work, iwork) | ||||||
| 		putWorkspace(tmp) | 		putWorkspace(tmp) | ||||||
|  | 		putFloats(work) | ||||||
|  | 		putFloats(tau) | ||||||
|  | 		putInts(iwork) | ||||||
| 		return 1 / v | 		return 1 / v | ||||||
| 	} | 	} | ||||||
| 	// Use the LQ factorization to compute the condition number. | 	// Use the LQ factorization to compute the condition number. | ||||||
| 	tmp := getWorkspace(m, n, false) | 	tmp := getWorkspace(m, n, false) | ||||||
| 	tmp.Copy(a) | 	tmp.Copy(a) | ||||||
| 	work := make([]float64, 3*m) | 	work := getFloats(3*m, false) | ||||||
| 	tau := make([]float64, min(m, n)) | 	tau := getFloats(min(m, n), false) | ||||||
| 	lapack64.Gelqf(tmp.mat, tau, work, -1) | 	lapack64.Gelqf(tmp.mat, tau, work, -1) | ||||||
| 	if int(work[0]) > len(work) { | 	if l := int(work[0]); l > len(work) { | ||||||
| 		work = make([]float64, int(work[0])) | 		putFloats(work) | ||||||
|  | 		work = getFloats(l, false) | ||||||
| 	} | 	} | ||||||
| 	lapack64.Gelqf(tmp.mat, tau, work, len(work)) | 	lapack64.Gelqf(tmp.mat, tau, work, len(work)) | ||||||
|  |  | ||||||
| 	iwork := make([]int, m) | 	iwork := getInts(m, false) | ||||||
| 	l := tmp.asTriDense(m, blas.NonUnit, blas.Lower) | 	l := tmp.asTriDense(m, blas.NonUnit, blas.Lower) | ||||||
| 	v := lapack64.Trcon(lnorm, l.mat, work, iwork) | 	v := lapack64.Trcon(lnorm, l.mat, work, iwork) | ||||||
| 	putWorkspace(tmp) | 	putWorkspace(tmp) | ||||||
|  | 	putFloats(work) | ||||||
|  | 	putFloats(tau) | ||||||
|  | 	putInts(iwork) | ||||||
| 	return 1 / v | 	return 1 / v | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -679,21 +689,24 @@ func Norm(a Matrix, norm float64) float64 { | |||||||
| 		rm := rma.RawMatrix() | 		rm := rma.RawMatrix() | ||||||
| 		n := normLapack(norm, aTrans) | 		n := normLapack(norm, aTrans) | ||||||
| 		if n == lapack.MaxColumnSum { | 		if n == lapack.MaxColumnSum { | ||||||
| 			work = make([]float64, rm.Cols) | 			work = getFloats(rm.Cols, false) | ||||||
|  | 			defer putFloats(work) | ||||||
| 		} | 		} | ||||||
| 		return lapack64.Lange(n, rm, work) | 		return lapack64.Lange(n, rm, work) | ||||||
| 	case RawTriangular: | 	case RawTriangular: | ||||||
| 		rm := rma.RawTriangular() | 		rm := rma.RawTriangular() | ||||||
| 		n := normLapack(norm, aTrans) | 		n := normLapack(norm, aTrans) | ||||||
| 		if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { | 		if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { | ||||||
| 			work = make([]float64, rm.N) | 			work = getFloats(rm.N, false) | ||||||
|  | 			defer putFloats(work) | ||||||
| 		} | 		} | ||||||
| 		return lapack64.Lantr(n, rm, work) | 		return lapack64.Lantr(n, rm, work) | ||||||
| 	case RawSymmetricer: | 	case RawSymmetricer: | ||||||
| 		rm := rma.RawSymmetric() | 		rm := rma.RawSymmetric() | ||||||
| 		n := normLapack(norm, aTrans) | 		n := normLapack(norm, aTrans) | ||||||
| 		if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { | 		if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { | ||||||
| 			work = make([]float64, rm.N) | 			work = getFloats(rm.N, false) | ||||||
|  | 			defer putFloats(work) | ||||||
| 		} | 		} | ||||||
| 		return lapack64.Lansy(n, rm, work) | 		return lapack64.Lansy(n, rm, work) | ||||||
| 	case *Vector: | 	case *Vector: | ||||||
|   | |||||||
| @@ -54,6 +54,12 @@ var ( | |||||||
|  |  | ||||||
| 	// poolVec is the Vector equivalent of pool. | 	// poolVec is the Vector equivalent of pool. | ||||||
| 	poolVec [63]sync.Pool | 	poolVec [63]sync.Pool | ||||||
|  |  | ||||||
|  | 	// poolFloats is the []float64 equivalent of pool. | ||||||
|  | 	poolFloats [63]sync.Pool | ||||||
|  |  | ||||||
|  | 	// poolInts is the []int equivalent of pool. | ||||||
|  | 	poolInts [63]sync.Pool | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| @@ -81,6 +87,12 @@ func init() { | |||||||
| 				Data: make([]float64, l), | 				Data: make([]float64, l), | ||||||
| 			}} | 			}} | ||||||
| 		} | 		} | ||||||
|  | 		poolFloats[i].New = func() interface{} { | ||||||
|  | 			return make([]float64, l) | ||||||
|  | 		} | ||||||
|  | 		poolInts[i].New = func() interface{} { | ||||||
|  | 			return make([]int, l) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -182,3 +194,41 @@ func getWorkspaceVec(n int, clear bool) *Vector { | |||||||
| func putWorkspaceVec(v *Vector) { | func putWorkspaceVec(v *Vector) { | ||||||
| 	poolVec[bits(uint64(cap(v.mat.Data)))].Put(v) | 	poolVec[bits(uint64(cap(v.mat.Data)))].Put(v) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // getFloats returns a []float64 of length l and a cap that is | ||||||
|  | // less than 2*l. If clear is true, the slice visible is zeroed. | ||||||
|  | func getFloats(l int, clear bool) []float64 { | ||||||
|  | 	w := poolFloats[bits(uint64(l))].Get().([]float64) | ||||||
|  | 	w = w[:l] | ||||||
|  | 	if clear { | ||||||
|  | 		zero(w) | ||||||
|  | 	} | ||||||
|  | 	return w | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // putFloats replaces a used []float64 into the appropriate size | ||||||
|  | // workspace pool. putFloats must not be called with a slice | ||||||
|  | // where references to the underlying data have been kept. | ||||||
|  | func putFloats(w []float64) { | ||||||
|  | 	poolFloats[bits(uint64(cap(w)))].Put(w) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // getInts returns a []ints of length l and a cap that is | ||||||
|  | // less than 2*l. If clear is true, the slice visible is zeroed. | ||||||
|  | func getInts(l int, clear bool) []int { | ||||||
|  | 	w := poolInts[bits(uint64(l))].Get().([]int) | ||||||
|  | 	w = w[:l] | ||||||
|  | 	if clear { | ||||||
|  | 		for i := range w { | ||||||
|  | 			w[i] = 0 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return w | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // putInts replaces a used []int into the appropriate size | ||||||
|  | // workspace pool. putInts must not be called with a slice | ||||||
|  | // where references to the underlying data have been kept. | ||||||
|  | func putInts(w []int) { | ||||||
|  | 	poolInts[bits(uint64(cap(w)))].Put(w) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -25,10 +25,12 @@ func (qr *QR) updateCond() { | |||||||
| 	// A = QR, where Q is orthonormal. Orthonormal multiplications do not change | 	// A = QR, where Q is orthonormal. Orthonormal multiplications do not change | ||||||
| 	// the condition number. Thus, ||A|| = ||Q|| ||R|| = ||R||. | 	// the condition number. Thus, ||A|| = ||Q|| ||R|| = ||R||. | ||||||
| 	n := qr.qr.mat.Cols | 	n := qr.qr.mat.Cols | ||||||
| 	work := make([]float64, 3*n) | 	work := getFloats(3*n, false) | ||||||
| 	iwork := make([]int, n) | 	iwork := getInts(n, false) | ||||||
| 	r := qr.qr.asTriDense(n, blas.NonUnit, blas.Upper) | 	r := qr.qr.asTriDense(n, blas.NonUnit, blas.Upper) | ||||||
| 	v := lapack64.Trcon(matrix.CondNorm, r.mat, work, iwork) | 	v := lapack64.Trcon(matrix.CondNorm, r.mat, work, iwork) | ||||||
|  | 	putFloats(work) | ||||||
|  | 	putInts(iwork) | ||||||
| 	qr.cond = 1 / v | 	qr.cond = 1 / v | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -48,12 +50,13 @@ func (qr *QR) Factorize(a Matrix) { | |||||||
| 		qr.qr = &Dense{} | 		qr.qr = &Dense{} | ||||||
| 	} | 	} | ||||||
| 	qr.qr.Clone(a) | 	qr.qr.Clone(a) | ||||||
| 	work := make([]float64, 1) | 	work := []float64{0} | ||||||
| 	qr.tau = make([]float64, k) | 	qr.tau = make([]float64, k) | ||||||
| 	lapack64.Geqrf(qr.qr.mat, qr.tau, work, -1) | 	lapack64.Geqrf(qr.qr.mat, qr.tau, work, -1) | ||||||
|  |  | ||||||
| 	work = make([]float64, int(work[0])) | 	work = getFloats(int(work[0]), false) | ||||||
| 	lapack64.Geqrf(qr.qr.mat, qr.tau, work, len(work)) | 	lapack64.Geqrf(qr.qr.mat, qr.tau, work, len(work)) | ||||||
|  | 	putFloats(work) | ||||||
| 	qr.updateCond() | 	qr.updateCond() | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -107,10 +110,11 @@ func (qr *QR) QTo(dst *Dense) *Dense { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Construct Q from the elementary reflectors. | 	// Construct Q from the elementary reflectors. | ||||||
| 	work := make([]float64, 1) | 	work := []float64{0} | ||||||
| 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, -1) | 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, -1) | ||||||
| 	work = make([]float64, int(work[0])) | 	work = getFloats(int(work[0]), false) | ||||||
| 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, len(work)) | 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, len(work)) | ||||||
|  | 	putFloats(work) | ||||||
|  |  | ||||||
| 	return dst | 	return dst | ||||||
| } | } | ||||||
| @@ -156,15 +160,17 @@ func (m *Dense) SolveQR(qr *QR, trans bool, b Matrix) error { | |||||||
| 		for i := c; i < r; i++ { | 		for i := c; i < r; i++ { | ||||||
| 			zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) | 			zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) | ||||||
| 		} | 		} | ||||||
| 		work := make([]float64, 1) | 		work := []float64{0} | ||||||
| 		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, -1) | 		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, -1) | ||||||
| 		work = make([]float64, int(work[0])) | 		work = getFloats(int(work[0]), false) | ||||||
| 		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, len(work)) | 		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, len(work)) | ||||||
|  | 		putFloats(work) | ||||||
| 	} else { | 	} else { | ||||||
| 		work := make([]float64, 1) | 		work := []float64{0} | ||||||
| 		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, -1) | 		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, -1) | ||||||
| 		work = make([]float64, int(work[0])) | 		work = getFloats(int(work[0]), false) | ||||||
| 		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, len(work)) | 		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, len(work)) | ||||||
|  | 		putFloats(work) | ||||||
|  |  | ||||||
| 		ok := lapack64.Trtrs(blas.NoTrans, t, x.mat) | 		ok := lapack64.Trtrs(blas.NoTrans, t, x.mat) | ||||||
| 		if !ok { | 		if !ok { | ||||||
|   | |||||||
| @@ -64,9 +64,11 @@ func (m *Dense) Solve(a, b Matrix) error { | |||||||
|  |  | ||||||
| 		rm := rma.RawTriangular() | 		rm := rma.RawTriangular() | ||||||
| 		blas64.Trsm(side, tA, 1, rm, m.mat) | 		blas64.Trsm(side, tA, 1, rm, m.mat) | ||||||
| 		work := make([]float64, 3*rm.N) | 		work := getFloats(3*rm.N, false) | ||||||
| 		iwork := make([]int, rm.N) | 		iwork := getInts(rm.N, false) | ||||||
| 		cond := lapack64.Trcon(matrix.CondNorm, rm, work, iwork) | 		cond := lapack64.Trcon(matrix.CondNorm, rm, work, iwork) | ||||||
|  | 		putFloats(work) | ||||||
|  | 		putInts(iwork) | ||||||
| 		if cond > matrix.ConditionTolerance { | 		if cond > matrix.ConditionTolerance { | ||||||
| 			return matrix.Condition(cond) | 			return matrix.Condition(cond) | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -92,10 +92,11 @@ func (svd *SVD) Factorize(a Matrix, kind matrix.SVDKind) (ok bool) { | |||||||
| 	svd.kind = kind | 	svd.kind = kind | ||||||
| 	svd.s = use(svd.s, min(m, n)) | 	svd.s = use(svd.s, min(m, n)) | ||||||
|  |  | ||||||
| 	work := make([]float64, 1) | 	work := []float64{0} | ||||||
| 	lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, -1) | 	lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, -1) | ||||||
| 	work = make([]float64, int(work[0])) | 	work = getFloats(int(work[0]), false) | ||||||
| 	ok = lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, len(work)) | 	ok = lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, len(work)) | ||||||
|  | 	putFloats(work) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		svd.kind = 0 | 		svd.kind = 0 | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -331,9 +331,11 @@ func (t *TriDense) InverseTri(a Triangular) error { | |||||||
| 	n, _ := a.Triangle() | 	n, _ := a.Triangle() | ||||||
| 	t.reuseAs(a.Triangle()) | 	t.reuseAs(a.Triangle()) | ||||||
| 	t.Copy(a) | 	t.Copy(a) | ||||||
| 	work := make([]float64, 3*n) | 	work := getFloats(3*n, false) | ||||||
| 	iwork := make([]int, n) | 	iwork := getInts(n, false) | ||||||
| 	cond := lapack64.Trcon(matrix.CondNorm, t.mat, work, iwork) | 	cond := lapack64.Trcon(matrix.CondNorm, t.mat, work, iwork) | ||||||
|  | 	putFloats(work) | ||||||
|  | 	putInts(iwork) | ||||||
| 	if math.IsInf(cond, 1) { | 	if math.IsInf(cond, 1) { | ||||||
| 		return matrix.Condition(cond) | 		return matrix.Condition(cond) | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 kortschak
					kortschak