--- /dev/null
+// Copyright ©2017 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 gonum
+
+import (
+ "math/cmplx"
+
+ "gonum.org/v1/gonum/blas"
+ "gonum.org/v1/gonum/internal/asm/c128"
+)
+
+// Zgemv performs one of the matrix-vector operations
+// y = alpha * A * x + beta * y if trans = blas.NoTrans
+// y = alpha * A^T * x + beta * y if trans = blas.Trans
+// y = alpha * A^H * x + beta * y if trans = blas.ConjTrans
+// where alpha and beta are scalars, x and y are vectors, and A is an m×n dense matrix.
+func (Implementation) Zgemv(trans blas.Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) {
+ checkZMatrix('A', m, n, a, lda)
+ switch trans {
+ default:
+ panic(badTranspose)
+ case blas.NoTrans:
+ checkZVector('x', n, x, incX)
+ checkZVector('y', m, y, incY)
+ case blas.Trans, blas.ConjTrans:
+ checkZVector('x', m, x, incX)
+ checkZVector('y', n, y, incY)
+ }
+
+ if m == 0 || n == 0 || (alpha == 0 && beta == 1) {
+ return
+ }
+
+ var lenX, lenY int
+ if trans == blas.NoTrans {
+ lenX = n
+ lenY = m
+ } else {
+ lenX = m
+ lenY = n
+ }
+ var kx int
+ if incX < 0 {
+ kx = (1 - lenX) * incX
+ }
+ var ky int
+ if incY < 0 {
+ ky = (1 - lenY) * incY
+ }
+
+ // Form y = beta*y.
+ if beta != 1 {
+ if incY == 1 {
+ if beta == 0 {
+ for i := range y[:lenY] {
+ y[i] = 0
+ }
+ } else {
+ c128.ScalUnitary(beta, y[:lenY])
+ }
+ } else {
+ iy := ky
+ if beta == 0 {
+ for i := 0; i < lenY; i++ {
+ y[iy] = 0
+ iy += incY
+ }
+ } else {
+ if incY > 0 {
+ c128.ScalInc(beta, y, uintptr(lenY), uintptr(incY))
+ } else {
+ c128.ScalInc(beta, y, uintptr(lenY), uintptr(-incY))
+ }
+ }
+ }
+ }
+
+ if alpha == 0 {
+ return
+ }
+
+ switch trans {
+ default:
+ // Form y = alpha*A*x + y.
+ iy := ky
+ if incX == 1 {
+ for i := 0; i < m; i++ {
+ y[iy] += alpha * c128.DotuUnitary(a[i*lda:i*lda+n], x[:n])
+ iy += incY
+ }
+ return
+ }
+ for i := 0; i < m; i++ {
+ y[iy] += alpha * c128.DotuInc(a[i*lda:i*lda+n], x, uintptr(n), 1, uintptr(incX), 0, uintptr(kx))
+ iy += incY
+ }
+ return
+
+ case blas.Trans:
+ // Form y = alpha*A^T*x + y.
+ ix := kx
+ if incY == 1 {
+ for i := 0; i < m; i++ {
+ c128.AxpyUnitary(alpha*x[ix], a[i*lda:i*lda+n], y[:n])
+ ix += incX
+ }
+ return
+ }
+ for i := 0; i < m; i++ {
+ c128.AxpyInc(alpha*x[ix], a[i*lda:i*lda+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky))
+ ix += incX
+ }
+ return
+
+ case blas.ConjTrans:
+ // Form y = alpha*A^H*x + y.
+ ix := kx
+ if incY == 1 {
+ for i := 0; i < m; i++ {
+ tmp := alpha * x[ix]
+ for j := 0; j < n; j++ {
+ y[j] += tmp * cmplx.Conj(a[i*lda+j])
+ }
+ ix += incX
+ }
+ return
+ }
+ for i := 0; i < m; i++ {
+ tmp := alpha * x[ix]
+ jy := ky
+ for j := 0; j < n; j++ {
+ y[jy] += tmp * cmplx.Conj(a[i*lda+j])
+ jy += incY
+ }
+ ix += incX
+ }
+ return
+ }
+}
+
+// Zgerc performs the rank-one operation
+// A += alpha * x * y^H
+// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector,
+// and y is an n element vector.
+func (Implementation) Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) {
+ checkZMatrix('A', m, n, a, lda)
+ checkZVector('x', m, x, incX)
+ checkZVector('y', n, y, incY)
+
+ if m == 0 || n == 0 || alpha == 0 {
+ return
+ }
+
+ var kx, jy int
+ if incX < 0 {
+ kx = (1 - m) * incX
+ }
+ if incY < 0 {
+ jy = (1 - n) * incY
+ }
+ for j := 0; j < n; j++ {
+ if y[jy] != 0 {
+ tmp := alpha * cmplx.Conj(y[jy])
+ c128.AxpyInc(tmp, x, a[j:], uintptr(m), uintptr(incX), uintptr(lda), uintptr(kx), 0)
+ }
+ jy += incY
+ }
+}
+
+// Zgeru performs the rank-one operation
+// A += alpha * x * y^T
+// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector,
+// and y is an n element vector.
+func (Implementation) Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) {
+ checkZMatrix('A', m, n, a, lda)
+ checkZVector('x', m, x, incX)
+ checkZVector('y', n, y, incY)
+
+ if m == 0 || n == 0 || alpha == 0 {
+ return
+ }
+
+ var kx int
+ if incX < 0 {
+ kx = (1 - m) * incX
+ }
+ if incY == 1 {
+ for i := 0; i < m; i++ {
+ if x[kx] != 0 {
+ tmp := alpha * x[kx]
+ c128.AxpyUnitary(tmp, y[:n], a[i*lda:i*lda+n])
+ }
+ kx += incX
+ }
+ return
+ }
+ var jy int
+ if incY < 0 {
+ jy = (1 - n) * incY
+ }
+ for i := 0; i < m; i++ {
+ if x[kx] != 0 {
+ tmp := alpha * x[kx]
+ c128.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(jy), 0)
+ }
+ kx += incX
+ }
+}
+
+// Zhemv performs the matrix-vector operation
+// y = alpha * A * x + beta * y
+// where alpha and beta are scalars, x and y are vectors, and A is an n×n
+// Hermitian matrix. The imaginary parts of the diagonal elements of A are
+// ignored and assumed to be zero.
+func (Implementation) Zhemv(uplo blas.Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ checkZMatrix('A', n, n, a, lda)
+ checkZVector('x', n, x, incX)
+ checkZVector('y', n, y, incY)
+
+ if n == 0 || (alpha == 0 && beta == 1) {
+ return
+ }
+
+ // Set up the start indices in X and Y.
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+ var ky int
+ if incY < 0 {
+ ky = (1 - n) * incY
+ }
+
+ // Form y = beta*y.
+ if beta != 1 {
+ if incY == 1 {
+ if beta == 0 {
+ for i := range y[:n] {
+ y[i] = 0
+ }
+ } else {
+ for i, v := range y[:n] {
+ y[i] = beta * v
+ }
+ }
+ } else {
+ iy := ky
+ if beta == 0 {
+ for i := 0; i < n; i++ {
+ y[iy] = 0
+ iy += incY
+ }
+ } else {
+ for i := 0; i < n; i++ {
+ y[iy] = beta * y[iy]
+ iy += incY
+ }
+ }
+ }
+ }
+
+ if alpha == 0 {
+ return
+ }
+
+ // The elements of A are accessed sequentially with one pass through
+ // the triangular part of A.
+
+ if uplo == blas.Upper {
+ // Form y when A is stored in upper triangle.
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[i]
+ var tmp2 complex128
+ for j := i + 1; j < n; j++ {
+ y[j] += tmp1 * cmplx.Conj(a[i*lda+j])
+ tmp2 += a[i*lda+j] * x[j]
+ }
+ aii := complex(real(a[i*lda+i]), 0)
+ y[i] += tmp1*aii + alpha*tmp2
+ }
+ } else {
+ ix := kx
+ iy := ky
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[ix]
+ var tmp2 complex128
+ jx := ix
+ jy := iy
+ for j := i + 1; j < n; j++ {
+ jx += incX
+ jy += incY
+ y[jy] += tmp1 * cmplx.Conj(a[i*lda+j])
+ tmp2 += a[i*lda+j] * x[jx]
+ }
+ aii := complex(real(a[i*lda+i]), 0)
+ y[iy] += tmp1*aii + alpha*tmp2
+ ix += incX
+ iy += incY
+ }
+ }
+ return
+ }
+
+ // Form y when A is stored in lower triangle.
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[i]
+ var tmp2 complex128
+ for j := 0; j < i; j++ {
+ y[j] += tmp1 * cmplx.Conj(a[i*lda+j])
+ tmp2 += a[i*lda+j] * x[j]
+ }
+ aii := complex(real(a[i*lda+i]), 0)
+ y[i] += tmp1*aii + alpha*tmp2
+ }
+ } else {
+ ix := kx
+ iy := ky
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[ix]
+ var tmp2 complex128
+ jx := kx
+ jy := ky
+ for j := 0; j < i; j++ {
+ y[jy] += tmp1 * cmplx.Conj(a[i*lda+j])
+ tmp2 += a[i*lda+j] * x[jx]
+ jx += incX
+ jy += incY
+ }
+ aii := complex(real(a[i*lda+i]), 0)
+ y[iy] += tmp1*aii + alpha*tmp2
+ ix += incX
+ iy += incY
+ }
+ }
+}
+
+// Zher performs the Hermitian rank-one operation
+// A += alpha * x * x^H
+// where A is an n×n Hermitian matrix, alpha is a real scalar, and x is an n
+// element vector. On entry, the imaginary parts of the diagonal elements of A
+// are ignored and assumed to be zero, on return they will be set to zero.
+func (Implementation) Zher(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ checkZMatrix('A', n, n, a, lda)
+ checkZVector('x', n, x, incX)
+
+ if n == 0 || alpha == 0 {
+ return
+ }
+
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+ if uplo == blas.Upper {
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ if x[i] != 0 {
+ tmp := complex(alpha*real(x[i]), alpha*imag(x[i]))
+ aii := real(a[i*lda+i])
+ xtmp := real(tmp * cmplx.Conj(x[i]))
+ a[i*lda+i] = complex(aii+xtmp, 0)
+ for j := i + 1; j < n; j++ {
+ a[i*lda+j] += tmp * cmplx.Conj(x[j])
+ }
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ }
+ return
+ }
+
+ ix := kx
+ for i := 0; i < n; i++ {
+ if x[ix] != 0 {
+ tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix]))
+ aii := real(a[i*lda+i])
+ xtmp := real(tmp * cmplx.Conj(x[ix]))
+ a[i*lda+i] = complex(aii+xtmp, 0)
+ jx := ix + incX
+ for j := i + 1; j < n; j++ {
+ a[i*lda+j] += tmp * cmplx.Conj(x[jx])
+ jx += incX
+ }
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ ix += incX
+ }
+ return
+ }
+
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ if x[i] != 0 {
+ tmp := complex(alpha*real(x[i]), alpha*imag(x[i]))
+ for j := 0; j < i; j++ {
+ a[i*lda+j] += tmp * cmplx.Conj(x[j])
+ }
+ aii := real(a[i*lda+i])
+ xtmp := real(tmp * cmplx.Conj(x[i]))
+ a[i*lda+i] = complex(aii+xtmp, 0)
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ }
+ return
+ }
+
+ ix := kx
+ for i := 0; i < n; i++ {
+ if x[ix] != 0 {
+ tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix]))
+ jx := kx
+ for j := 0; j < i; j++ {
+ a[i*lda+j] += tmp * cmplx.Conj(x[jx])
+ jx += incX
+ }
+ aii := real(a[i*lda+i])
+ xtmp := real(tmp * cmplx.Conj(x[ix]))
+ a[i*lda+i] = complex(aii+xtmp, 0)
+
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ ix += incX
+ }
+}
+
+// Zher2 performs the Hermitian rank-two operation
+// A += alpha*x*y^H + conj(alpha)*y*x^H
+// where alpha is a scalar, x and y are n element vectors and A is an n×n
+// Hermitian matrix. On entry, the imaginary parts of the diagonal elements are
+// ignored and assumed to be zero. On return they will be set to zero.
+func (Implementation) Zher2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ checkZMatrix('A', n, n, a, lda)
+ checkZVector('x', n, x, incX)
+ checkZVector('y', n, y, incY)
+
+ if n == 0 || alpha == 0 {
+ return
+ }
+
+ var kx, ky int
+ var ix, iy int
+ if incX != 1 || incY != 1 {
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+ if incY < 0 {
+ ky = (1 - n) * incY
+ }
+ ix = kx
+ iy = ky
+ }
+ if uplo == blas.Upper {
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ if x[i] != 0 || y[i] != 0 {
+ tmp1 := alpha * x[i]
+ tmp2 := cmplx.Conj(alpha) * y[i]
+ aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i]))
+ a[i*lda+i] = complex(aii, 0)
+ for j := i + 1; j < n; j++ {
+ a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j])
+ }
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ }
+ return
+ }
+ for i := 0; i < n; i++ {
+ if x[ix] != 0 || y[iy] != 0 {
+ tmp1 := alpha * x[ix]
+ tmp2 := cmplx.Conj(alpha) * y[iy]
+ aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix]))
+ a[i*lda+i] = complex(aii, 0)
+ jx := ix + incX
+ jy := iy + incY
+ for j := i + 1; j < n; j++ {
+ a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx])
+ jx += incX
+ jy += incY
+ }
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ ix += incX
+ iy += incY
+ }
+ return
+ }
+
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ if x[i] != 0 || y[i] != 0 {
+ tmp1 := alpha * x[i]
+ tmp2 := cmplx.Conj(alpha) * y[i]
+ for j := 0; j < i; j++ {
+ a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j])
+ }
+ aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i]))
+ a[i*lda+i] = complex(aii, 0)
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ }
+ return
+ }
+ for i := 0; i < n; i++ {
+ if x[ix] != 0 || y[iy] != 0 {
+ tmp1 := alpha * x[ix]
+ tmp2 := cmplx.Conj(alpha) * y[iy]
+ jx := kx
+ jy := ky
+ for j := 0; j < i; j++ {
+ a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx])
+ jx += incX
+ jy += incY
+ }
+ aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix]))
+ a[i*lda+i] = complex(aii, 0)
+ } else {
+ aii := real(a[i*lda+i])
+ a[i*lda+i] = complex(aii, 0)
+ }
+ ix += incX
+ iy += incY
+ }
+}
+
+// Zhpmv performs the matrix-vector operation
+// y = alpha * A * x + beta * y
+// where alpha and beta are scalars, x and y are vectors, and A is an n×n
+// Hermitian matrix in packed form. The imaginary parts of the diagonal
+// elements of A are ignored and assumed to be zero.
+func (Implementation) Zhpmv(uplo blas.Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ checkZVector('x', n, x, incX)
+ checkZVector('y', n, y, incY)
+ if len(ap) < n*(n+1)/2 {
+ panic("blas: insufficient A packed matrix slice length")
+ }
+
+ if n == 0 || (alpha == 0 && beta == 1) {
+ return
+ }
+
+ // Set up the start indices in X and Y.
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+ var ky int
+ if incY < 0 {
+ ky = (1 - n) * incY
+ }
+
+ // Form y = beta*y.
+ if beta != 1 {
+ if incY == 1 {
+ if beta == 0 {
+ for i := range y[:n] {
+ y[i] = 0
+ }
+ } else {
+ for i, v := range y[:n] {
+ y[i] = beta * v
+ }
+ }
+ } else {
+ iy := ky
+ if beta == 0 {
+ for i := 0; i < n; i++ {
+ y[iy] = 0
+ iy += incY
+ }
+ } else {
+ for i := 0; i < n; i++ {
+ y[iy] *= beta
+ iy += incY
+ }
+ }
+ }
+ }
+
+ if alpha == 0 {
+ return
+ }
+
+ // The elements of A are accessed sequentially with one pass through ap.
+
+ var kk int
+ if uplo == blas.Upper {
+ // Form y when ap contains the upper triangle.
+ // Here, kk points to the current diagonal element in ap.
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[i]
+ y[i] += tmp1 * complex(real(ap[kk]), 0)
+ var tmp2 complex128
+ k := kk + 1
+ for j := i + 1; j < n; j++ {
+ y[j] += tmp1 * cmplx.Conj(ap[k])
+ tmp2 += ap[k] * x[j]
+ k++
+ }
+ y[i] += alpha * tmp2
+ kk += n - i
+ }
+ } else {
+ ix := kx
+ iy := ky
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[ix]
+ y[iy] += tmp1 * complex(real(ap[kk]), 0)
+ var tmp2 complex128
+ jx := ix
+ jy := iy
+ for k := kk + 1; k < kk+n-i; k++ {
+ jx += incX
+ jy += incY
+ y[jy] += tmp1 * cmplx.Conj(ap[k])
+ tmp2 += ap[k] * x[jx]
+ }
+ y[iy] += alpha * tmp2
+ ix += incX
+ iy += incY
+ kk += n - i
+ }
+ }
+ return
+ }
+
+ // Form y when ap contains the lower triangle.
+ // Here, kk points to the beginning of current row in ap.
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[i]
+ var tmp2 complex128
+ k := kk
+ for j := 0; j < i; j++ {
+ y[j] += tmp1 * cmplx.Conj(ap[k])
+ tmp2 += ap[k] * x[j]
+ k++
+ }
+ aii := complex(real(ap[kk+i]), 0)
+ y[i] += tmp1*aii + alpha*tmp2
+ kk += i + 1
+ }
+ } else {
+ ix := kx
+ iy := ky
+ for i := 0; i < n; i++ {
+ tmp1 := alpha * x[ix]
+ var tmp2 complex128
+ jx := kx
+ jy := ky
+ for k := kk; k < kk+i; k++ {
+ y[jy] += tmp1 * cmplx.Conj(ap[k])
+ tmp2 += ap[k] * x[jx]
+ jx += incX
+ jy += incY
+ }
+ aii := complex(real(ap[kk+i]), 0)
+ y[iy] += tmp1*aii + alpha*tmp2
+ ix += incX
+ iy += incY
+ kk += i + 1
+ }
+ }
+}
+
+// Zhpr performs the Hermitian rank-1 operation
+// A += alpha * x * x^H,
+// where alpha is a real scalar, x is a vector, and A is an n×n hermitian matrix
+// in packed form. On entry, the imaginary parts of the diagonal elements are
+// assumed to be zero, and on return they are set to zero.
+func (Implementation) Zhpr(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, ap []complex128) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ if n < 0 {
+ panic(nLT0)
+ }
+ checkZVector('x', n, x, incX)
+ if len(ap) < n*(n+1)/2 {
+ panic("blas: insufficient A packed matrix slice length")
+ }
+
+ if n == 0 || alpha == 0 {
+ return
+ }
+
+ // Set up start index in X.
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+
+ // The elements of A are accessed sequentially with one pass through ap.
+
+ var kk int
+ if uplo == blas.Upper {
+ // Form A when upper triangle is stored in AP.
+ // Here, kk points to the current diagonal element in ap.
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ xi := x[i]
+ if xi != 0 {
+ aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi)
+ ap[kk] = complex(aii, 0)
+
+ tmp := complex(alpha, 0) * xi
+ a := ap[kk+1 : kk+n-i]
+ x := x[i+1 : n]
+ for j, v := range x {
+ a[j] += tmp * cmplx.Conj(v)
+ }
+ } else {
+ ap[kk] = complex(real(ap[kk]), 0)
+ }
+ kk += n - i
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ xi := x[ix]
+ if xi != 0 {
+ aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi)
+ ap[kk] = complex(aii, 0)
+
+ tmp := complex(alpha, 0) * xi
+ jx := ix + incX
+ a := ap[kk+1 : kk+n-i]
+ for k := range a {
+ a[k] += tmp * cmplx.Conj(x[jx])
+ jx += incX
+ }
+ } else {
+ ap[kk] = complex(real(ap[kk]), 0)
+ }
+ ix += incX
+ kk += n - i
+ }
+ }
+ return
+ }
+
+ // Form A when lower triangle is stored in AP.
+ // Here, kk points to the beginning of current row in ap.
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ xi := x[i]
+ if xi != 0 {
+ tmp := complex(alpha, 0) * xi
+ a := ap[kk : kk+i]
+ for j, v := range x[:i] {
+ a[j] += tmp * cmplx.Conj(v)
+ }
+
+ aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi)
+ ap[kk+i] = complex(aii, 0)
+ } else {
+ ap[kk+i] = complex(real(ap[kk+i]), 0)
+ }
+ kk += i + 1
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ xi := x[ix]
+ if xi != 0 {
+ tmp := complex(alpha, 0) * xi
+ a := ap[kk : kk+i]
+ jx := kx
+ for k := range a {
+ a[k] += tmp * cmplx.Conj(x[jx])
+ jx += incX
+ }
+
+ aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi)
+ ap[kk+i] = complex(aii, 0)
+ } else {
+ ap[kk+i] = complex(real(ap[kk+i]), 0)
+ }
+ ix += incX
+ kk += i + 1
+ }
+ }
+}
+
+// Zhpr2 performs the Hermitian rank-2 operation
+// A += alpha*x*y^H + conj(alpha)*y*x^H,
+// where alpha is a complex scalar, x and y are n element vectors, and A is an
+// n×n Hermitian matrix, supplied in packed form. On entry, the imaginary parts
+// of the diagonal elements are assumed to be zero, and on return they are set to zero.
+func (Implementation) Zhpr2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ if n < 0 {
+ panic(nLT0)
+ }
+ checkZVector('x', n, x, incX)
+ checkZVector('y', n, y, incY)
+ if len(ap) < n*(n+1)/2 {
+ panic("blas: insufficient A packed matrix slice length")
+ }
+
+ if n == 0 || alpha == 0 {
+ return
+ }
+
+ // Set up start indices in X and Y.
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+ var ky int
+ if incY < 0 {
+ ky = (1 - n) * incY
+ }
+
+ // The elements of A are accessed sequentially with one pass through ap.
+
+ var kk int
+ if uplo == blas.Upper {
+ // Form A when upper triangle is stored in AP.
+ // Here, kk points to the current diagonal element in ap.
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ if x[i] != 0 || y[i] != 0 {
+ tmp1 := alpha * x[i]
+ tmp2 := cmplx.Conj(alpha) * y[i]
+ aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i]))
+ ap[kk] = complex(aii, 0)
+ k := kk + 1
+ for j := i + 1; j < n; j++ {
+ ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j])
+ k++
+ }
+ } else {
+ ap[kk] = complex(real(ap[kk]), 0)
+ }
+ kk += n - i
+ }
+ } else {
+ ix := kx
+ iy := ky
+ for i := 0; i < n; i++ {
+ if x[ix] != 0 || y[iy] != 0 {
+ tmp1 := alpha * x[ix]
+ tmp2 := cmplx.Conj(alpha) * y[iy]
+ aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix]))
+ ap[kk] = complex(aii, 0)
+ jx := ix + incX
+ jy := iy + incY
+ for k := kk + 1; k < kk+n-i; k++ {
+ ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx])
+ jx += incX
+ jy += incY
+ }
+ } else {
+ ap[kk] = complex(real(ap[kk]), 0)
+ }
+ ix += incX
+ iy += incY
+ kk += n - i
+ }
+ }
+ return
+ }
+
+ // Form A when lower triangle is stored in AP.
+ // Here, kk points to the beginning of current row in ap.
+ if incX == 1 && incY == 1 {
+ for i := 0; i < n; i++ {
+ if x[i] != 0 || y[i] != 0 {
+ tmp1 := alpha * x[i]
+ tmp2 := cmplx.Conj(alpha) * y[i]
+ k := kk
+ for j := 0; j < i; j++ {
+ ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j])
+ k++
+ }
+ aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i]))
+ ap[kk+i] = complex(aii, 0)
+ } else {
+ ap[kk+i] = complex(real(ap[kk+i]), 0)
+ }
+ kk += i + 1
+ }
+ } else {
+ ix := kx
+ iy := ky
+ for i := 0; i < n; i++ {
+ if x[ix] != 0 || y[iy] != 0 {
+ tmp1 := alpha * x[ix]
+ tmp2 := cmplx.Conj(alpha) * y[iy]
+ jx := kx
+ jy := ky
+ for k := kk; k < kk+i; k++ {
+ ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx])
+ jx += incX
+ jy += incY
+ }
+ aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix]))
+ ap[kk+i] = complex(aii, 0)
+ } else {
+ ap[kk+i] = complex(real(ap[kk+i]), 0)
+ }
+ ix += incX
+ iy += incY
+ kk += i + 1
+ }
+ }
+}
+
+// Ztpmv performs one of the matrix-vector operations
+// x = A * x if trans = blas.NoTrans
+// x = A^T * x if trans = blas.Trans
+// x = A^H * x if trans = blas.ConjTrans
+// where x is an n element vector and A is an n×n triangular matrix, supplied in
+// packed form.
+func (Implementation) Ztpmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex128, x []complex128, incX int) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans {
+ panic(badTranspose)
+ }
+ if diag != blas.Unit && diag != blas.NonUnit {
+ panic(badDiag)
+ }
+ checkZVector('x', n, x, incX)
+ if len(ap) < n*(n+1)/2 {
+ panic("blas: insufficient A packed matrix slice length")
+ }
+
+ if n == 0 {
+ return
+ }
+
+ // Set up start index in X.
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+
+ // The elements of A are accessed sequentially with one pass through A.
+
+ if trans == blas.NoTrans {
+ // Form x = A*x.
+ if uplo == blas.Upper {
+ // kk points to the current diagonal element in ap.
+ kk := 0
+ if incX == 1 {
+ x = x[:n]
+ for i := range x {
+ if diag == blas.NonUnit {
+ x[i] *= ap[kk]
+ }
+ if n-i-1 > 0 {
+ x[i] += c128.DotuUnitary(ap[kk+1:kk+n-i], x[i+1:])
+ }
+ kk += n - i
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ if diag == blas.NonUnit {
+ x[ix] *= ap[kk]
+ }
+ if n-i-1 > 0 {
+ x[ix] += c128.DotuInc(ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX))
+ }
+ ix += incX
+ kk += n - i
+ }
+ }
+ } else {
+ // kk points to the beginning of current row in ap.
+ kk := n*(n+1)/2 - n
+ if incX == 1 {
+ for i := n - 1; i >= 0; i-- {
+ if diag == blas.NonUnit {
+ x[i] *= ap[kk+i]
+ }
+ if i > 0 {
+ x[i] += c128.DotuUnitary(ap[kk:kk+i], x[:i])
+ }
+ kk -= i
+ }
+ } else {
+ ix := kx + (n-1)*incX
+ for i := n - 1; i >= 0; i-- {
+ if diag == blas.NonUnit {
+ x[ix] *= ap[kk+i]
+ }
+ if i > 0 {
+ x[ix] += c128.DotuInc(ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx))
+ }
+ ix -= incX
+ kk -= i
+ }
+ }
+ }
+ return
+ }
+
+ if trans == blas.Trans {
+ // Form x = A^T*x.
+ if uplo == blas.Upper {
+ // kk points to the current diagonal element in ap.
+ kk := n*(n+1)/2 - 1
+ if incX == 1 {
+ for i := n - 1; i >= 0; i-- {
+ xi := x[i]
+ if diag == blas.NonUnit {
+ x[i] *= ap[kk]
+ }
+ if n-i-1 > 0 {
+ c128.AxpyUnitary(xi, ap[kk+1:kk+n-i], x[i+1:n])
+ }
+ kk -= n - i + 1
+ }
+ } else {
+ ix := kx + (n-1)*incX
+ for i := n - 1; i >= 0; i-- {
+ xi := x[ix]
+ if diag == blas.NonUnit {
+ x[ix] *= ap[kk]
+ }
+ if n-i-1 > 0 {
+ c128.AxpyInc(xi, ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX))
+ }
+ ix -= incX
+ kk -= n - i + 1
+ }
+ }
+ } else {
+ // kk points to the beginning of current row in ap.
+ kk := 0
+ if incX == 1 {
+ x = x[:n]
+ for i := range x {
+ if i > 0 {
+ c128.AxpyUnitary(x[i], ap[kk:kk+i], x[:i])
+ }
+ if diag == blas.NonUnit {
+ x[i] *= ap[kk+i]
+ }
+ kk += i + 1
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ c128.AxpyInc(x[ix], ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx))
+ }
+ if diag == blas.NonUnit {
+ x[ix] *= ap[kk+i]
+ }
+ ix += incX
+ kk += i + 1
+ }
+ }
+ }
+ return
+ }
+
+ // Form x = A^H*x.
+ if uplo == blas.Upper {
+ // kk points to the current diagonal element in ap.
+ kk := n*(n+1)/2 - 1
+ if incX == 1 {
+ for i := n - 1; i >= 0; i-- {
+ xi := x[i]
+ if diag == blas.NonUnit {
+ x[i] *= cmplx.Conj(ap[kk])
+ }
+ k := kk + 1
+ for j := i + 1; j < n; j++ {
+ x[j] += xi * cmplx.Conj(ap[k])
+ k++
+ }
+ kk -= n - i + 1
+ }
+ } else {
+ ix := kx + (n-1)*incX
+ for i := n - 1; i >= 0; i-- {
+ xi := x[ix]
+ if diag == blas.NonUnit {
+ x[ix] *= cmplx.Conj(ap[kk])
+ }
+ jx := ix + incX
+ k := kk + 1
+ for j := i + 1; j < n; j++ {
+ x[jx] += xi * cmplx.Conj(ap[k])
+ jx += incX
+ k++
+ }
+ ix -= incX
+ kk -= n - i + 1
+ }
+ }
+ } else {
+ // kk points to the beginning of current row in ap.
+ kk := 0
+ if incX == 1 {
+ x = x[:n]
+ for i, xi := range x {
+ for j := 0; j < i; j++ {
+ x[j] += xi * cmplx.Conj(ap[kk+j])
+ }
+ if diag == blas.NonUnit {
+ x[i] *= cmplx.Conj(ap[kk+i])
+ }
+ kk += i + 1
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ xi := x[ix]
+ jx := kx
+ for j := 0; j < i; j++ {
+ x[jx] += xi * cmplx.Conj(ap[kk+j])
+ jx += incX
+ }
+ if diag == blas.NonUnit {
+ x[ix] *= cmplx.Conj(ap[kk+i])
+ }
+ ix += incX
+ kk += i + 1
+ }
+ }
+ }
+}
+
+// Ztrmv performs one of the matrix-vector operations
+// x = A * x if trans = blas.NoTrans
+// x = A^T * x if trans = blas.Trans
+// x = A^H * x if trans = blas.ConjTrans
+// where x is a vector, and A is an n×n triangular matrix.
+func (Implementation) Ztrmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans {
+ panic(badTranspose)
+ }
+ if diag != blas.Unit && diag != blas.NonUnit {
+ panic(badDiag)
+ }
+ checkZMatrix('A', n, n, a, lda)
+ checkZVector('x', n, x, incX)
+
+ if n == 0 {
+ return
+ }
+
+ // Set up start index in X.
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+
+ // The elements of A are accessed sequentially with one pass through A.
+
+ if trans == blas.NoTrans {
+ // Form x = A*x.
+ if uplo == blas.Upper {
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ if diag == blas.NonUnit {
+ x[i] *= a[i*lda+i]
+ }
+ if n-i-1 > 0 {
+ x[i] += c128.DotuUnitary(a[i*lda+i+1:i*lda+n], x[i+1:n])
+ }
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ if diag == blas.NonUnit {
+ x[ix] *= a[i*lda+i]
+ }
+ if n-i-1 > 0 {
+ x[ix] += c128.DotuInc(a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX))
+ }
+ ix += incX
+ }
+ }
+ } else {
+ if incX == 1 {
+ for i := n - 1; i >= 0; i-- {
+ if diag == blas.NonUnit {
+ x[i] *= a[i*lda+i]
+ }
+ if i > 0 {
+ x[i] += c128.DotuUnitary(a[i*lda:i*lda+i], x[:i])
+ }
+ }
+ } else {
+ ix := kx + (n-1)*incX
+ for i := n - 1; i >= 0; i-- {
+ if diag == blas.NonUnit {
+ x[ix] *= a[i*lda+i]
+ }
+ if i > 0 {
+ x[ix] += c128.DotuInc(a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx))
+ }
+ ix -= incX
+ }
+ }
+ }
+ return
+ }
+
+ if trans == blas.Trans {
+ // Form x = A^T*x.
+ if uplo == blas.Upper {
+ if incX == 1 {
+ for i := n - 1; i >= 0; i-- {
+ xi := x[i]
+ if diag == blas.NonUnit {
+ x[i] *= a[i*lda+i]
+ }
+ if n-i-1 > 0 {
+ c128.AxpyUnitary(xi, a[i*lda+i+1:i*lda+n], x[i+1:n])
+ }
+ }
+ } else {
+ ix := kx + (n-1)*incX
+ for i := n - 1; i >= 0; i-- {
+ xi := x[ix]
+ if diag == blas.NonUnit {
+ x[ix] *= a[i*lda+i]
+ }
+ if n-i-1 > 0 {
+ c128.AxpyInc(xi, a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX))
+ }
+ ix -= incX
+ }
+ }
+ } else {
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ c128.AxpyUnitary(x[i], a[i*lda:i*lda+i], x[:i])
+ }
+ if diag == blas.NonUnit {
+ x[i] *= a[i*lda+i]
+ }
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ c128.AxpyInc(x[ix], a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx))
+ }
+ if diag == blas.NonUnit {
+ x[ix] *= a[i*lda+i]
+ }
+ ix += incX
+ }
+ }
+ }
+ return
+ }
+
+ // Form x = A^H*x.
+ if uplo == blas.Upper {
+ if incX == 1 {
+ for i := n - 1; i >= 0; i-- {
+ xi := x[i]
+ if diag == blas.NonUnit {
+ x[i] *= cmplx.Conj(a[i*lda+i])
+ }
+ for j := i + 1; j < n; j++ {
+ x[j] += xi * cmplx.Conj(a[i*lda+j])
+ }
+ }
+ } else {
+ ix := kx + (n-1)*incX
+ for i := n - 1; i >= 0; i-- {
+ xi := x[ix]
+ if diag == blas.NonUnit {
+ x[ix] *= cmplx.Conj(a[i*lda+i])
+ }
+ jx := ix + incX
+ for j := i + 1; j < n; j++ {
+ x[jx] += xi * cmplx.Conj(a[i*lda+j])
+ jx += incX
+ }
+ ix -= incX
+ }
+ }
+ } else {
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ for j := 0; j < i; j++ {
+ x[j] += x[i] * cmplx.Conj(a[i*lda+j])
+ }
+ if diag == blas.NonUnit {
+ x[i] *= cmplx.Conj(a[i*lda+i])
+ }
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ jx := kx
+ for j := 0; j < i; j++ {
+ x[jx] += x[ix] * cmplx.Conj(a[i*lda+j])
+ jx += incX
+ }
+ if diag == blas.NonUnit {
+ x[ix] *= cmplx.Conj(a[i*lda+i])
+ }
+ ix += incX
+ }
+ }
+ }
+}
+
+// Ztrsv solves one of the systems of equations
+// A*x = b if trans == blas.NoTrans,
+// A^T*x = b, if trans == blas.Trans,
+// A^H*x = b, if trans == blas.ConjTrans,
+// where b and x are n element vectors and A is an n×n triangular matrix.
+//
+// On entry, x contains the values of b, and the solution is
+// stored in-place into x.
+//
+// No test for singularity or near-singularity is included in this
+// routine. Such tests must be performed before calling this routine.
+func (Implementation) Ztrsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) {
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans {
+ panic(badTranspose)
+ }
+ if diag != blas.Unit && diag != blas.NonUnit {
+ panic(badDiag)
+ }
+ checkZMatrix('A', n, n, a, lda)
+ checkZVector('x', n, x, incX)
+
+ if n == 0 {
+ return
+ }
+
+ // Set up start index in X.
+ var kx int
+ if incX < 0 {
+ kx = (1 - n) * incX
+ }
+
+ // The elements of A are accessed sequentially with one pass through A.
+
+ if trans == blas.NoTrans {
+ // Form x = inv(A)*x.
+ if uplo == blas.Upper {
+ if incX == 1 {
+ for i := n - 1; i >= 0; i-- {
+ aii := a[i*lda+i]
+ if n-i-1 > 0 {
+ x[i] -= c128.DotuUnitary(x[i+1:n], a[i*lda+i+1:i*lda+n])
+ }
+ if diag == blas.NonUnit {
+ x[i] /= aii
+ }
+ }
+ } else {
+ ix := kx + (n-1)*incX
+ for i := n - 1; i >= 0; i-- {
+ aii := a[i*lda+i]
+ if n-i-1 > 0 {
+ x[ix] -= c128.DotuInc(x, a[i*lda+i+1:i*lda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0)
+ }
+ if diag == blas.NonUnit {
+ x[ix] /= aii
+ }
+ ix -= incX
+ }
+ }
+ } else {
+ if incX == 1 {
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ x[i] -= c128.DotuUnitary(x[:i], a[i*lda:i*lda+i])
+ }
+ if diag == blas.NonUnit {
+ x[i] /= a[i*lda+i]
+ }
+ }
+ } else {
+ ix := kx
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ x[ix] -= c128.DotuInc(x, a[i*lda:i*lda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0)
+ }
+ if diag == blas.NonUnit {
+ x[ix] /= a[i*lda+i]
+ }
+ ix += incX
+ }
+ }
+ }
+ return
+ }
+
+ if trans == blas.Trans {
+ // Form x = inv(A^T)*x.
+ if uplo == blas.Upper {
+ if incX == 1 {
+ for j := 0; j < n; j++ {
+ if diag == blas.NonUnit {
+ x[j] /= a[j*lda+j]
+ }
+ if n-j-1 > 0 {
+ c128.AxpyUnitary(-x[j], a[j*lda+j+1:j*lda+n], x[j+1:n])
+ }
+ }
+ } else {
+ jx := kx
+ for j := 0; j < n; j++ {
+ if diag == blas.NonUnit {
+ x[jx] /= a[j*lda+j]
+ }
+ if n-j-1 > 0 {
+ c128.AxpyInc(-x[jx], a[j*lda+j+1:j*lda+n], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX))
+ }
+ jx += incX
+ }
+ }
+ } else {
+ if incX == 1 {
+ for j := n - 1; j >= 0; j-- {
+ if diag == blas.NonUnit {
+ x[j] /= a[j*lda+j]
+ }
+ xj := x[j]
+ if j > 0 {
+ c128.AxpyUnitary(-xj, a[j*lda:j*lda+j], x[:j])
+ }
+ }
+ } else {
+ jx := kx + (n-1)*incX
+ for j := n - 1; j >= 0; j-- {
+ if diag == blas.NonUnit {
+ x[jx] /= a[j*lda+j]
+ }
+ if j > 0 {
+ c128.AxpyInc(-x[jx], a[j*lda:j*lda+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx))
+ }
+ jx -= incX
+ }
+ }
+ }
+ return
+ }
+
+ // Form x = inv(A^H)*x.
+ if uplo == blas.Upper {
+ if incX == 1 {
+ for j := 0; j < n; j++ {
+ if diag == blas.NonUnit {
+ x[j] /= cmplx.Conj(a[j*lda+j])
+ }
+ xj := x[j]
+ for i := j + 1; i < n; i++ {
+ x[i] -= xj * cmplx.Conj(a[j*lda+i])
+ }
+ }
+ } else {
+ jx := kx
+ for j := 0; j < n; j++ {
+ if diag == blas.NonUnit {
+ x[jx] /= cmplx.Conj(a[j*lda+j])
+ }
+ xj := x[jx]
+ ix := jx + incX
+ for i := j + 1; i < n; i++ {
+ x[ix] -= xj * cmplx.Conj(a[j*lda+i])
+ ix += incX
+ }
+ jx += incX
+ }
+ }
+ } else {
+ if incX == 1 {
+ for j := n - 1; j >= 0; j-- {
+ if diag == blas.NonUnit {
+ x[j] /= cmplx.Conj(a[j*lda+j])
+ }
+ xj := x[j]
+ for i := 0; i < j; i++ {
+ x[i] -= xj * cmplx.Conj(a[j*lda+i])
+ }
+ }
+ } else {
+ jx := kx + (n-1)*incX
+ for j := n - 1; j >= 0; j-- {
+ if diag == blas.NonUnit {
+ x[jx] /= cmplx.Conj(a[j*lda+j])
+ }
+ xj := x[jx]
+ ix := kx
+ for i := 0; i < j; i++ {
+ x[ix] -= xj * cmplx.Conj(a[j*lda+i])
+ ix += incX
+ }
+ jx -= incX
+ }
+ }
+ }
+}