예제 #1
0
파일: trdsec.go 프로젝트: hrautila/gomas
// Solve secular function arising in symmetric eigenproblems. On exit 'Y' contains new
// eigenvalues and 'V' the rank-one update vector corresponding new eigenvalues.
// The matrix Qd holds for each eigenvalue then computed deltas as row vectors.
// On entry 'D' holds original eigenvalues and 'Z' is the rank-one update vector.
func TRDSecularSolveAll(y, v, Qd, d, z *cmat.FloatMatrix, rho float64, confs ...*gomas.Config) (err *gomas.Error) {
	var delta cmat.FloatMatrix
	var lmbda float64
	var e, ei int

	ei = 0
	err = nil
	if y.Len() != d.Len() || z.Len() != d.Len() || m(Qd) != n(Qd) || m(Qd) != d.Len() {
		err = gomas.NewError(gomas.ESIZE, "TRDSecularSolveAll")
		return
	}
	for i := 0; i < d.Len(); i++ {
		delta.Row(Qd, i)
		lmbda, e = trdsecRoot(d, z, &delta, i, rho)
		if e < 0 && ei == 0 {
			ei = -(i + 1)
		}
		y.SetAt(i, lmbda)
	}
	if ei == 0 {
		trdsecUpdateVecDelta(v, Qd, d, rho)
	} else {
		err = gomas.NewError(gomas.ECONVERGE, "TRDSecularSolveAll", ei)
	}
	return
}
예제 #2
0
파일: sort.go 프로젝트: hrautila/gomas
func sortEigenVec(D, U, V, C *cmat.FloatMatrix, updown int) {
	var sD, m0, m1 cmat.FloatMatrix

	N := D.Len()
	for k := 0; k < N-1; k++ {
		sD.SubVector(D, k, N-k)
		pk := vecMinMax(&sD, -updown)
		if pk != 0 {
			t0 := D.GetAt(k)
			D.SetAt(k, D.GetAt(pk+k))
			D.SetAt(k+pk, t0)
			if U != nil {
				m0.Column(U, k)
				m1.Column(U, k+pk)
				blasd.Swap(&m1, &m0)
			}
			if V != nil {
				m0.Row(V, k)
				m1.Row(V, k+pk)
				blasd.Swap(&m1, &m0)
			}
			if C != nil {
				m0.Column(C, k)
				m1.Column(C, k+pk)
				blasd.Swap(&m1, &m0)
			}
		}
	}
}
예제 #3
0
파일: diag.go 프로젝트: hrautila/gomas
/*
 * Compute
 *   B = B*diag(D).-1      flags & RIGHT == true
 *   B = diag(D).-1*B      flags & LEFT  == true
 *
 * If flags is LEFT (RIGHT) then element-wise divides columns (rows) of B with vector D.
 *
 * Arguments:
 *   B     M-by-N matrix if flags&RIGHT == true or N-by-M matrix if flags&LEFT == true
 *
 *   D     N element column or row vector or N-by-N matrix
 *
 *   flags Indicator bits, LEFT or RIGHT
 */
func SolveDiag(B, D *cmat.FloatMatrix, flags int, confs ...*gomas.Config) *gomas.Error {
	var c, d0 cmat.FloatMatrix
	var d *cmat.FloatMatrix

	conf := gomas.CurrentConf(confs...)
	d = D
	if !D.IsVector() {
		d0.Diag(D)
		d = &d0
	}
	dn := d0.Len()
	br, bc := B.Size()
	switch flags & (gomas.LEFT | gomas.RIGHT) {
	case gomas.LEFT:
		if br != dn {
			return gomas.NewError(gomas.ESIZE, "SolveDiag")
		}
		// scale rows;
		for k := 0; k < dn; k++ {
			c.Row(B, k)
			blasd.InvScale(&c, d.GetAt(k), conf)
		}
	case gomas.RIGHT:
		if bc != dn {
			return gomas.NewError(gomas.ESIZE, "SolveDiag")
		}
		// scale columns
		for k := 0; k < dn; k++ {
			c.Column(B, k)
			blasd.InvScale(&c, d.GetAt(k), conf)
		}
	}
	return nil
}
예제 #4
0
파일: trdsec.go 프로젝트: hrautila/gomas
// Compute eigenmatrix Q for updated eigenvalues in 'dl'.
func trdsecEigenBuild(Q, z, Q2 *cmat.FloatMatrix) {
	var qi, delta cmat.FloatMatrix

	for k := 0; k < z.Len(); k++ {
		qi.Column(Q, k)
		delta.Row(Q2, k)
		trdsecEigenVecDelta(&qi, &delta, z)
	}
}
예제 #5
0
파일: norm.go 프로젝트: hrautila/gomas
func mNormInf(A *cmat.FloatMatrix) float64 {
	var amax float64 = 0.0
	var row cmat.FloatMatrix
	arows, _ := A.Size()
	for k := 0; k < arows; k++ {
		row.Row(A, k)
		rmax := blasd.ASum(&row)
		if rmax > amax {
			amax = rmax
		}
	}
	return amax
}
예제 #6
0
파일: bired.go 프로젝트: hrautila/gomas
/*
 * Generate one of the orthogonal matrices Q or P.T determined by BDReduce() when
 * reducing a real matrix A to bidiagonal form. Q and P.T are defined as products
 * elementary reflectors H(i) or G(i) respectively.
 *
 * Orthogonal matrix Q is generated if flag WANTQ is set. And matrix P respectively
 * if flag WANTP is set.
 */
func BDBuild(A, tau, W *cmat.FloatMatrix, K, flags int, confs ...*gomas.Config) *gomas.Error {
	var Qh, Ph, tauh, d, s cmat.FloatMatrix
	var err *gomas.Error = nil

	if m(A) == 0 || n(A) == 0 {
		return nil
	}

	if m(A) > n(A) || (m(A) == n(A) && flags&gomas.LOWER == 0) {
		switch flags & (gomas.WANTQ | gomas.WANTP) {
		case gomas.WANTQ:
			tauh.SubMatrix(tau, 0, 0, n(A), 1)
			err = QRBuild(A, &tauh, W, K, confs...)

		case gomas.WANTP:
			// Shift P matrix embedded in A down and fill first column and row
			// to unit vector
			for j := n(A) - 1; j > 0; j-- {
				s.SubMatrix(A, j-1, j, 1, n(A)-j)
				d.SubMatrix(A, j, j, 1, n(A)-j)
				blasd.Copy(&d, &s)
				A.Set(j, 0, 0.0)
			}
			// zero  first row and set first entry to one
			d.Row(A, 0)
			blasd.Scale(&d, 0.0)
			d.Set(0, 0, 1.0)

			Ph.SubMatrix(A, 1, 1, n(A)-1, n(A)-1)
			tauh.SubMatrix(tau, 0, 0, n(A)-1, 1)
			if K > n(A)-1 {
				K = n(A) - 1
			}
			err = LQBuild(&Ph, &tauh, W, K, confs...)
		}
	} else {
		switch flags & (gomas.WANTQ | gomas.WANTP) {
		case gomas.WANTQ:
			// Shift Q matrix embedded in A right and fill first column and row
			// to unit vector
			for j := m(A) - 1; j > 0; j-- {
				s.SubMatrix(A, j, j-1, m(A)-j, 1)
				d.SubMatrix(A, j, j, m(A)-j, 1)
				blasd.Copy(&d, &s)
				A.Set(0, j, 0.0)
			}
			// zero first column and set first entry to one
			d.Column(A, 0)
			blasd.Scale(&d, 0.0)
			d.Set(0, 0, 1.0)

			Qh.SubMatrix(A, 1, 1, m(A)-1, m(A)-1)
			tauh.SubMatrix(tau, 0, 0, m(A)-1, 1)
			if K > m(A)-1 {
				K = m(A) - 1
			}
			err = QRBuild(&Qh, &tauh, W, K, confs...)

		case gomas.WANTP:
			tauh.SubMatrix(tau, 0, 0, m(A), 1)
			err = LQBuild(A, &tauh, W, K, confs...)
		}
	}
	if err != nil {
		err.Update("BDBuild")
	}
	return err
}
예제 #7
0
파일: svd.go 프로젝트: hrautila/gomas
func svdSmall(S, U, V, A, W *cmat.FloatMatrix, bits int, conf *gomas.Config) (err *gomas.Error) {
	var r cmat.FloatMatrix
	var d0, d1, e0 float64

	err = nil
	K := m(A)
	if n(A) < K {
		K = n(A)
	}
	tau := cmat.NewMatrix(K, 1)
	if m(A) >= n(A) {
		if err = QRFactor(A, tau, W, conf); err != nil {
			return
		}
	} else {
		if err = LQFactor(A, tau, W, conf); err != nil {
			return
		}
	}
	if m(A) == 1 || n(A) == 1 {
		// either tall M-by-1 or wide 1-by-N
		S.SetAt(0, math.Abs(A.Get(0, 0)))

		if bits&gomas.WANTU != 0 {
			if n(A) == 1 {
				if n(U) == n(A) {
					// U is M-by-1
					U.Copy(A)
					QRBuild(U, tau, W, n(A), conf)
				} else {
					// U is M-by-M
					eye := cmat.FloatDiagonalSource{1.0}
					U.SetFrom(&eye, cmat.SYMM)
					if err = QRMult(U, A, tau, W, gomas.RIGHT, conf); err != nil {
						return
					}
				}
			} else {
				U.Set(0, 0, -1.0)
			}
		}
		if bits&gomas.WANTV != 0 {
			if m(A) == 1 {
				if m(V) == m(A) {
					// V is 1-by-N
					V.Copy(A)
					LQBuild(V, tau, W, m(A), conf)
				} else {
					// V is N-by-N
					eye := cmat.FloatDiagonalSource{1.0}
					V.SetFrom(&eye, cmat.SYMM)
					if err = LQMult(V, A, tau, W, gomas.RIGHT, conf); err != nil {
						return
					}
				}
			} else {
				// V is 1-by-1
				V.Set(0, 0, -1.0)
			}
		}
		return
	}

	// Use bdSvd2x2 functions
	d0 = A.Get(0, 0)
	d1 = A.Get(1, 1)
	if m(A) >= n(A) {
		e0 = A.Get(0, 1)
	} else {
		e0 = A.Get(1, 0)
	}

	if bits&(gomas.WANTU|gomas.WANTV) == 0 {
		// no vectors
		smin, smax := bdSvd2x2(d0, e0, d1)
		S.SetAt(0, math.Abs(smax))
		S.SetAt(1, math.Abs(smin))
		return
	}

	// at least left or right eigenvector wanted
	smin, smax, cosl, sinl, cosr, sinr := bdSvd2x2Vec(d0, e0, d1)
	if bits&gomas.WANTU != 0 {
		// left eigenvectors
		if m(A) >= n(A) {
			if n(U) == n(A) {
				U.Copy(A)
				if err = QRBuild(U, tau, W, n(A), conf); err != nil {
					return
				}
			} else {
				// U is M-by-M
				eye := cmat.FloatDiagonalSource{1.0}
				U.SetFrom(&eye, cmat.SYMM)
				if err = QRMult(U, A, tau, W, gomas.RIGHT, conf); err != nil {
					return
				}
			}
			ApplyGivensRight(U, 0, 1, 0, m(A), cosl, sinl)
		} else {
			// U is 2-by-2
			eye := cmat.FloatDiagonalSource{1.0}
			U.SetFrom(&eye, cmat.SYMM)
			ApplyGivensRight(U, 0, 1, 0, m(A), cosr, sinr)
		}
	}

	if bits&gomas.WANTV != 0 {
		if n(A) > m(A) {
			if m(V) == m(A) {
				V.Copy(A)
				if err = LQBuild(V, tau, W, m(A), conf); err != nil {
					return
				}
			} else {
				eye := cmat.FloatDiagonalSource{1.0}
				V.SetFrom(&eye, cmat.SYMM)
				if err = LQMult(V, A, tau, W, gomas.RIGHT, conf); err != nil {
					return
				}
			}
			ApplyGivensLeft(V, 0, 1, 0, n(A), cosl, sinl)
		} else {
			// V is 2-by-2
			eye := cmat.FloatDiagonalSource{1.0}
			V.SetFrom(&eye, cmat.SYMM)
			ApplyGivensLeft(V, 0, 1, 0, n(A), cosr, sinr)
		}
		if smax < 0.0 {
			r.Row(V, 0)
			blasd.Scale(&r, -1.0)
		}
		if smin < 0.0 {
			r.Row(V, 1)
			blasd.Scale(&r, -1.0)
		}
	}
	S.SetAt(0, math.Abs(smax))
	S.SetAt(1, math.Abs(smin))
	return
}