Exemplo n.º 1
0
// The product x := (y o x).  If diag is 'D', the 's' part of y is
// diagonal and only the diagonal is stored.
func sprod(x, y *matrix.FloatMatrix, dims *DimensionSet, mnl int, opts ...la_.Option) (err error) {

	err = nil
	diag := la_.GetStringOpt("diag", "N", opts...)
	// For the nonlinear and 'l' blocks:
	//
	//     yk o xk = yk .* xk.
	ind := mnl + dims.At("l")[0]
	err = blas.Tbmv(y, x, &la_.IOpt{"n", ind}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1})
	if err != nil {
		return
	}
	//fmt.Printf("Sprod l:x=\n%v\n", x)

	// For 'q' blocks:
	//
	//               [ l0   l1'  ]
	//     yk o xk = [           ] * xk
	//               [ l1   l0*I ]
	//
	// where yk = (l0, l1).
	for _, m := range dims.At("q") {
		dd := blas.DotFloat(x, y, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"offsety", ind},
			&la_.IOpt{"n", m})
		//fmt.Printf("dd=%v\n", dd)
		alpha := y.GetIndex(ind)
		//fmt.Printf("scal=%v\n", alpha)
		blas.ScalFloat(x, alpha, &la_.IOpt{"offset", ind + 1}, &la_.IOpt{"n", m - 1})
		alpha = x.GetIndex(ind)
		//fmt.Printf("axpy=%v\n", alpha)
		blas.AxpyFloat(y, x, alpha, &la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", ind + 1},
			&la_.IOpt{"n", m - 1})
		x.SetIndex(ind, dd)
		ind += m
	}
	//fmt.Printf("Sprod q :x=\n%v\n", x)

	// For the 's' blocks:
	//
	//    yk o sk = .5 * ( Yk * mat(xk) + mat(xk) * Yk )
	//
	// where Yk = mat(yk) if diag is 'N' and Yk = diag(yk) if diag is 'D'.

	if diag[0] == 'N' {
		// DEBUGGED
		maxm := maxdim(dims.At("s"))
		A := matrix.FloatZeros(maxm, maxm)
		for _, m := range dims.At("s") {
			blas.Copy(x, A, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"n", m * m})
			for i := 0; i < m-1; i++ { // i < m-1 --> i < m
				symm(A, m, 0)
				symm(y, m, ind)
			}
			err = blas.Syr2kFloat(A, y, x, 0.5, 0.0, &la_.IOpt{"n", m}, &la_.IOpt{"k", m},
				&la_.IOpt{"lda", m}, &la_.IOpt{"ldb", m}, &la_.IOpt{"ldc", m},
				&la_.IOpt{"offsetb", ind}, &la_.IOpt{"offsetc", ind})
			if err != nil {
				return
			}
			ind += m * m
		}
		//fmt.Printf("Sprod diag=N s:x=\n%v\n", x)

	} else {
		ind2 := ind
		for _, m := range dims.At("s") {
			for i := 0; i < m; i++ {
				// original: u = 0.5 * ( y[ind2+i:ind2+m] + y[ind2+i] )
				// creates matrix of elements: [ind2+i ... ind2+m] then
				// element wisely adds y[ind2+i] and scales by 0.5
				iset := matrix.MakeIndexSet(ind2+i, ind2+m, 1)
				u := matrix.FloatVector(y.GetIndexes(iset))
				u.Add(y.GetIndex(ind2 + i))
				u.Scale(0.5)
				err = blas.Tbmv(u, x, &la_.IOpt{"n", m - i}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1},
					&la_.IOpt{"offsetx", ind + i*(m+1)})
				if err != nil {
					return
				}
			}
			ind += m * m
			ind2 += m
		}
		//fmt.Printf("Sprod diag=T s:x=\n%v\n", x)
	}
	return
}