Example #1
0
// Inverse computes the inverse of the matrix a, storing the result into the
// receiver. If a is ill-conditioned, a Condition error will be returned.
// Note that matrix inversion is numerically unstable, and should generally
// be avoided where possible, for example by using the Solve routines.
func (m *Dense) Inverse(a Matrix) error {
	// TODO(btracey): Special case for RawTriangular, etc.
	r, c := a.Dims()
	if r != c {
		panic(ErrSquare)
	}
	m.reuseAs(a.Dims())
	aMat, aTrans := untranspose(a)
	if m != aMat {
		m.Copy(a)
	} else if aTrans {
		tmp := getWorkspace(r, c, false)
		tmp.Copy(a)
		m.Copy(tmp)
		putWorkspace(tmp)
	}
	ipiv := make([]int, r)
	lapack64.Getrf(m.mat, ipiv)
	work := make([]float64, 1, 4*r) // must be at least 4*r for cond.
	lapack64.Getri(m.mat, ipiv, work, -1)
	if int(work[0]) > 4*r {
		work = make([]float64, int(work[0]))
	} else {
		work = work[:4*r]
	}
	lapack64.Getri(m.mat, ipiv, work, len(work))
	norm := lapack64.Lange(condNorm, m.mat, work)
	cond := lapack64.Gecon(condNorm, m.mat, norm, work, ipiv) // reuse ipiv
	if cond > condTol {
		return Condition(cond)
	}
	return nil
}
Example #2
0
// Inverse computes the inverse of the matrix a, storing the result into the
// receiver. If a is ill-conditioned, a Condition error will be returned.
// Note that matrix inversion is numerically unstable, and should generally
// be avoided where possible, for example by using the Solve routines.
func (m *Dense) Inverse(a Matrix) error {
	// TODO(btracey): Special case for RawTriangular, etc.
	r, c := a.Dims()
	if r != c {
		panic(matrix.ErrSquare)
	}
	m.reuseAs(a.Dims())
	aU, aTrans := untranspose(a)
	switch rm := aU.(type) {
	case RawMatrixer:
		if m != aU || aTrans {
			if m == aU || m.checkOverlap(rm.RawMatrix()) {
				tmp := getWorkspace(r, c, false)
				tmp.Copy(a)
				m.Copy(tmp)
				putWorkspace(tmp)
				break
			}
			m.Copy(a)
		}
	default:
		if m != aU {
			m.Copy(a)
		} else if aTrans {
			// m and a share data so Copy cannot be used directly.
			tmp := getWorkspace(r, c, false)
			tmp.Copy(a)
			m.Copy(tmp)
			putWorkspace(tmp)
		}
	}
	ipiv := make([]int, r)
	lapack64.Getrf(m.mat, ipiv)
	work := make([]float64, 1, 4*r) // must be at least 4*r for cond.
	lapack64.Getri(m.mat, ipiv, work, -1)
	if int(work[0]) > 4*r {
		work = make([]float64, int(work[0]))
	} else {
		work = work[:4*r]
	}
	lapack64.Getri(m.mat, ipiv, work, len(work))
	norm := lapack64.Lange(matrix.CondNorm, m.mat, work)
	cond := lapack64.Gecon(matrix.CondNorm, m.mat, norm, work, ipiv) // reuse ipiv
	if cond > matrix.ConditionTolerance {
		return matrix.Condition(cond)
	}
	return nil
}