Files
gonum/lapack/native/dlacn2.go
2017-05-23 00:03:03 -06:00

135 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright ©2015 The gonum 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 native
import (
"math"
"gonum.org/v1/gonum/blas/blas64"
)
// Dlacn2 estimates the 1-norm of an n×n matrix A using sequential updates with
// matrix-vector products provided externally.
//
// Dlacn2 is called sequentially and it returns the value of est and kase to be
// used on the next call.
// On the initial call, kase must be 0.
// In between calls, x must be overwritten by
// A * X if kase was returned as 1,
// A^T * X if kase was returned as 2,
// and all other parameters must not be changed.
// On the final return, kase is returned as 0, v contains A*W where W is a
// vector, and est = norm(V)/norm(W) is a lower bound for 1-norm of A.
//
// v, x, and isgn must all have length n and n must be at least 1, otherwise
// Dlacn2 will panic. isave is used for temporary storage.
//
// Dlacn2 is an internal routine. It is exported for testing purposes.
func (impl Implementation) Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) {
if n < 1 {
panic("lapack: non-positive n")
}
checkVector(n, x, 1)
checkVector(n, v, 1)
if len(isgn) < n {
panic("lapack: insufficient isgn length")
}
if isave[0] < 0 || isave[0] > 5 {
panic("lapack: bad isave value")
}
if isave[0] == 0 && kase != 0 {
panic("lapack: bad isave value")
}
itmax := 5
bi := blas64.Implementation()
if kase == 0 {
for i := 0; i < n; i++ {
x[i] = 1 / float64(n)
}
kase = 1
isave[0] = 1
return est, kase
}
switch isave[0] {
default:
panic("unreachable")
case 1:
if n == 1 {
v[0] = x[0]
est = math.Abs(v[0])
kase = 0
return est, kase
}
est = bi.Dasum(n, x, 1)
for i := 0; i < n; i++ {
x[i] = math.Copysign(1, x[i])
isgn[i] = int(x[i])
}
kase = 2
isave[0] = 2
return est, kase
case 2:
isave[1] = bi.Idamax(n, x, 1)
isave[2] = 2
for i := 0; i < n; i++ {
x[i] = 0
}
x[isave[1]] = 1
kase = 1
isave[0] = 3
return est, kase
case 3:
bi.Dcopy(n, x, 1, v, 1)
estold := est
est = bi.Dasum(n, v, 1)
sameSigns := true
for i := 0; i < n; i++ {
if int(math.Copysign(1, x[i])) != isgn[i] {
sameSigns = false
break
}
}
if !sameSigns && est > estold {
for i := 0; i < n; i++ {
x[i] = math.Copysign(1, x[i])
isgn[i] = int(x[i])
}
kase = 2
isave[0] = 4
return est, kase
}
case 4:
jlast := isave[1]
isave[1] = bi.Idamax(n, x, 1)
if x[jlast] != math.Abs(x[isave[1]]) && isave[2] < itmax {
isave[2] += 1
for i := 0; i < n; i++ {
x[i] = 0
}
x[isave[1]] = 1
kase = 1
isave[0] = 3
return est, kase
}
case 5:
tmp := 2 * (bi.Dasum(n, x, 1)) / float64(3*n)
if tmp > est {
bi.Dcopy(n, x, 1, v, 1)
est = tmp
}
kase = 0
return est, kase
}
// Iteration complete. Final stage
altsgn := 1.0
for i := 0; i < n; i++ {
x[i] = altsgn * (1 + float64(i)/float64(n-1))
altsgn *= -1
}
kase = 1
isave[0] = 5
return est, kase
}