1 // Copyright ©2014 The Gonum Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 "gonum.org/v1/gonum/blas"
15 // throwPanic will throw unexpected panics if true, or will just report them as errors if false
16 const throwPanic = true
18 var znan = cmplx.NaN()
20 func dTolEqual(a, b float64) bool {
21 if math.IsNaN(a) && math.IsNaN(b) {
27 m := math.Max(math.Abs(a), math.Abs(b))
32 if math.Abs(a-b) < 1e-14 {
38 func dSliceTolEqual(a, b []float64) bool {
43 if !dTolEqual(a[i], b[i]) {
50 func dStridedSliceTolEqual(n int, a []float64, inca int, b []float64, incb int) bool {
59 for i := 0; i < n; i++ {
60 if !dTolEqual(a[ia], b[ib]) {
69 func dSliceEqual(a, b []float64) bool {
74 if !dTolEqual(a[i], b[i]) {
81 func dCopyTwoTmp(x, xTmp, y, yTmp []float64) {
82 if len(x) != len(xTmp) {
83 panic("x size mismatch")
85 if len(y) != len(yTmp) {
86 panic("y size mismatch")
92 // returns true if the function panics
93 func panics(f func()) (b bool) {
104 func testpanics(f func(), name string, t *testing.T) {
107 t.Errorf("%v should panic and does not", name)
111 func sliceOfSliceCopy(a [][]float64) [][]float64 {
112 n := make([][]float64, len(a))
114 n[i] = make([]float64, len(a[i]))
120 func sliceCopy(a []float64) []float64 {
121 n := make([]float64, len(a))
126 func flatten(a [][]float64) []float64 {
132 s := make([]float64, m*n)
133 for i := 0; i < m; i++ {
134 for j := 0; j < n; j++ {
141 func unflatten(a []float64, m, n int) [][]float64 {
142 s := make([][]float64, m)
143 for i := 0; i < m; i++ {
144 s[i] = make([]float64, n)
145 for j := 0; j < n; j++ {
152 // flattenTriangular turns the upper or lower triangle of a dense slice of slice
153 // into a single slice with packed storage. a must be a square matrix.
154 func flattenTriangular(a [][]float64, ul blas.Uplo) []float64 {
156 aFlat := make([]float64, m*(m+1)/2)
158 if ul == blas.Upper {
159 for i := 0; i < m; i++ {
160 k += copy(aFlat[k:], a[i][i:])
164 for i := 0; i < m; i++ {
165 k += copy(aFlat[k:], a[i][:i+1])
170 // flattenBanded turns a dense banded slice of slice into the compact banded matrix format
171 func flattenBanded(a [][]float64, ku, kl int) []float64 {
174 if ku < 0 || kl < 0 {
175 panic("testblas: negative band length")
178 nCols := (ku + kl + 1)
179 aflat := make([]float64, nRows*nCols)
180 for i := range aflat {
181 aflat[i] = math.NaN()
183 // loop over the rows, and then the bands
184 // elements in the ith row stay in the ith row
185 // order in bands is kept
186 for i := 0; i < nRows; i++ {
195 for j := min; j <= max; j++ {
197 aflat[i*nCols+col] = a[i][i+j]
203 // makeIncremented takes a slice with inc == 1 and makes an incremented version
204 // and adds extra values on the end
205 func makeIncremented(x []float64, inc int, extra int) []float64 {
213 xcopy := make([]float64, len(x))
217 for i := 0; i < len(x); i++ {
218 xcopy[i] = x[len(x)-i-1]
222 // don't use NaN because it makes comparison hard
223 // Do use a weird unique value for easier debugging
226 for i, v := range xcopy {
227 xnew = append(xnew, v)
229 for j := 0; j < absinc-1; j++ {
230 xnew = append(xnew, counter)
235 for i := 0; i < extra; i++ {
236 xnew = append(xnew, counter)
242 func abs(x int) int {
249 func allPairs(x, y []int) [][2]int {
251 for _, v0 := range x {
252 for _, v1 := range y {
253 p = append(p, [2]int{v0, v1})
259 func sameFloat64(a, b float64) bool {
260 return a == b || math.IsNaN(a) && math.IsNaN(b)
263 func sameComplex128(x, y complex128) bool {
264 return sameFloat64(real(x), real(y)) && sameFloat64(imag(x), imag(y))
267 func zsame(x, y []complex128) bool {
268 if len(x) != len(y) {
271 for i, v := range x {
273 if !sameComplex128(v, w) {
280 // zSameAtNonstrided returns whether elements at non-stride positions of vectors
282 func zSameAtNonstrided(x, y []complex128, inc int) bool {
283 if len(x) != len(y) {
289 for i, v := range x {
294 if !sameComplex128(v, w) {
301 // zEqualApproxAtStrided returns whether elements at stride positions of vectors
302 // x and y are approximately equal within tol.
303 func zEqualApproxAtStrided(x, y []complex128, inc int, tol float64) bool {
304 if len(x) != len(y) {
310 for i := 0; i < len(x); i += inc {
313 if !(cmplx.Abs(v-w) <= tol) {
320 func makeZVector(data []complex128, inc int) []complex128 {
328 x := make([]complex128, (len(data)-1)*inc+1)
332 for i, v := range data {
338 func makeZGeneral(data []complex128, m, n int, ld int) []complex128 {
342 if data != nil && len(data) != m*n {
348 if m == 0 || n == 0 {
351 a := make([]complex128, (m-1)*ld+n)
356 for i := 0; i < m; i++ {
357 copy(a[i*ld:i*ld+n], data[i*n:i*n+n])
363 func max(a, b int) int {
370 // zPack returns the uplo triangle of an n×n matrix A in packed format.
371 func zPack(uplo blas.Uplo, n int, a []complex128, lda int) []complex128 {
375 ap := make([]complex128, n*(n+1)/2)
377 if uplo == blas.Upper {
378 for i := 0; i < n; i++ {
379 for j := i; j < n; j++ {
385 for i := 0; i < n; i++ {
386 for j := 0; j <= i; j++ {
395 // zUnpackAsHermitian returns an n×n general Hermitian matrix (with stride n)
396 // whose packed uplo triangle is stored on entry in ap.
397 func zUnpackAsHermitian(uplo blas.Uplo, n int, ap []complex128) []complex128 {
401 a := make([]complex128, n*n)
404 if uplo == blas.Upper {
405 for i := 0; i < n; i++ {
406 for j := i; j < n; j++ {
409 a[j*lda+i] = cmplx.Conj(ap[ii])
415 for i := 0; i < n; i++ {
416 for j := 0; j <= i; j++ {
419 a[j*lda+i] = cmplx.Conj(ap[ii])