github.com/gopherd/gonum@v0.0.4/lapack/testlapack/test_matrices.go (about) 1 // Copyright ©2016 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. 4 5 package testlapack 6 7 import ( 8 "math" 9 10 "math/rand" 11 12 "github.com/gopherd/gonum/blas/blas64" 13 ) 14 15 // A123 is the non-symmetric singular matrix 16 // [ 1 2 3 ] 17 // A = [ 4 5 6 ] 18 // [ 7 8 9 ] 19 // It has three distinct real eigenvalues. 20 type A123 struct{} 21 22 func (A123) Matrix() blas64.General { 23 return blas64.General{ 24 Rows: 3, 25 Cols: 3, 26 Stride: 3, 27 Data: []float64{ 28 1, 2, 3, 29 4, 5, 6, 30 7, 8, 9, 31 }, 32 } 33 } 34 35 func (A123) Eigenvalues() []complex128 { 36 return []complex128{16.116843969807043, -1.116843969807043, 0} 37 } 38 39 func (A123) LeftEV() blas64.General { 40 return blas64.General{ 41 Rows: 3, 42 Cols: 3, 43 Stride: 3, 44 Data: []float64{ 45 -0.464547273387671, -0.570795531228578, -0.677043789069485, 46 -0.882905959653586, -0.239520420054206, 0.403865119545174, 47 0.408248290463862, -0.816496580927726, 0.408248290463863, 48 }, 49 } 50 } 51 52 func (A123) RightEV() blas64.General { 53 return blas64.General{ 54 Rows: 3, 55 Cols: 3, 56 Stride: 3, 57 Data: []float64{ 58 -0.231970687246286, -0.785830238742067, 0.408248290463864, 59 -0.525322093301234, -0.086751339256628, -0.816496580927726, 60 -0.818673499356181, 0.612327560228810, 0.408248290463863, 61 }, 62 } 63 } 64 65 // AntisymRandom is a anti-symmetric random matrix. All its eigenvalues are 66 // imaginary with one zero if the order is odd. 67 type AntisymRandom struct { 68 mat blas64.General 69 } 70 71 func NewAntisymRandom(n int, rnd *rand.Rand) AntisymRandom { 72 a := zeros(n, n, n) 73 for i := 0; i < n; i++ { 74 for j := i + 1; j < n; j++ { 75 r := rnd.NormFloat64() 76 a.Data[i*a.Stride+j] = r 77 a.Data[j*a.Stride+i] = -r 78 } 79 } 80 return AntisymRandom{a} 81 } 82 83 func (a AntisymRandom) Matrix() blas64.General { 84 return cloneGeneral(a.mat) 85 } 86 87 func (AntisymRandom) Eigenvalues() []complex128 { 88 return nil 89 } 90 91 // Circulant is a generally non-symmetric matrix given by 92 // A[i,j] = 1 + (j-i+n)%n. 93 // For example, for n=5, 94 // [ 1 2 3 4 5 ] 95 // [ 5 1 2 3 4 ] 96 // A = [ 4 5 1 2 3 ] 97 // [ 3 4 5 1 2 ] 98 // [ 2 3 4 5 1 ] 99 // It has real and complex eigenvalues, some possibly repeated. 100 type Circulant int 101 102 func (c Circulant) Matrix() blas64.General { 103 n := int(c) 104 a := zeros(n, n, n) 105 for i := 0; i < n; i++ { 106 for j := 0; j < n; j++ { 107 a.Data[i*a.Stride+j] = float64(1 + (j-i+n)%n) 108 } 109 } 110 return a 111 } 112 113 func (c Circulant) Eigenvalues() []complex128 { 114 n := int(c) 115 w := rootsOfUnity(n) 116 ev := make([]complex128, n) 117 for k := 0; k < n; k++ { 118 ev[k] = complex(float64(n), 0) 119 } 120 for i := n - 1; i > 0; i-- { 121 for k := 0; k < n; k++ { 122 ev[k] = ev[k]*w[k] + complex(float64(i), 0) 123 } 124 } 125 return ev 126 } 127 128 // Clement is a generally non-symmetric matrix given by 129 // A[i,j] = i+1 if j == i+1, 130 // = n-i if j == i-1, 131 // = 0 otherwise. 132 // For example, for n=5, 133 // [ . 1 . . . ] 134 // [ 4 . 2 . . ] 135 // A = [ . 3 . 3 . ] 136 // [ . . 2 . 4 ] 137 // [ . . . 1 . ] 138 // It has n distinct real eigenvalues. 139 type Clement int 140 141 func (c Clement) Matrix() blas64.General { 142 n := int(c) 143 a := zeros(n, n, n) 144 for i := 0; i < n; i++ { 145 if i < n-1 { 146 a.Data[i*a.Stride+i+1] = float64(i + 1) 147 } 148 if i > 0 { 149 a.Data[i*a.Stride+i-1] = float64(n - i) 150 } 151 } 152 return a 153 } 154 155 func (c Clement) Eigenvalues() []complex128 { 156 n := int(c) 157 ev := make([]complex128, n) 158 for i := range ev { 159 ev[i] = complex(float64(-n+2*i+1), 0) 160 } 161 return ev 162 } 163 164 // Creation is a singular non-symmetric matrix given by 165 // A[i,j] = i if j == i-1, 166 // = 0 otherwise. 167 // For example, for n=5, 168 // [ . . . . . ] 169 // [ 1 . . . . ] 170 // A = [ . 2 . . . ] 171 // [ . . 3 . . ] 172 // [ . . . 4 . ] 173 // Zero is its only eigenvalue. 174 type Creation int 175 176 func (c Creation) Matrix() blas64.General { 177 n := int(c) 178 a := zeros(n, n, n) 179 for i := 1; i < n; i++ { 180 a.Data[i*a.Stride+i-1] = float64(i) 181 } 182 return a 183 } 184 185 func (c Creation) Eigenvalues() []complex128 { 186 return make([]complex128, int(c)) 187 } 188 189 // Diagonal is a diagonal matrix given by 190 // A[i,j] = i+1 if i == j, 191 // = 0 otherwise. 192 // For example, for n=5, 193 // [ 1 . . . . ] 194 // [ . 2 . . . ] 195 // A = [ . . 3 . . ] 196 // [ . . . 4 . ] 197 // [ . . . . 5 ] 198 // It has n real eigenvalues {1,...,n}. 199 type Diagonal int 200 201 func (d Diagonal) Matrix() blas64.General { 202 n := int(d) 203 a := zeros(n, n, n) 204 for i := 0; i < n; i++ { 205 a.Data[i*a.Stride+i] = float64(i) 206 } 207 return a 208 } 209 210 func (d Diagonal) Eigenvalues() []complex128 { 211 n := int(d) 212 ev := make([]complex128, n) 213 for i := range ev { 214 ev[i] = complex(float64(i), 0) 215 } 216 return ev 217 } 218 219 // Downshift is a non-singular upper Hessenberg matrix given by 220 // A[i,j] = 1 if (i-j+n)%n == 1, 221 // = 0 otherwise. 222 // For example, for n=5, 223 // [ . . . . 1 ] 224 // [ 1 . . . . ] 225 // A = [ . 1 . . . ] 226 // [ . . 1 . . ] 227 // [ . . . 1 . ] 228 // Its eigenvalues are the complex roots of unity. 229 type Downshift int 230 231 func (d Downshift) Matrix() blas64.General { 232 n := int(d) 233 a := zeros(n, n, n) 234 a.Data[n-1] = 1 235 for i := 1; i < n; i++ { 236 a.Data[i*a.Stride+i-1] = 1 237 } 238 return a 239 } 240 241 func (d Downshift) Eigenvalues() []complex128 { 242 return rootsOfUnity(int(d)) 243 } 244 245 // Fibonacci is an upper Hessenberg matrix with 3 distinct real eigenvalues. For 246 // example, for n=5, 247 // [ . 1 . . . ] 248 // [ 1 1 . . . ] 249 // A = [ . 1 1 . . ] 250 // [ . . 1 1 . ] 251 // [ . . . 1 1 ] 252 type Fibonacci int 253 254 func (f Fibonacci) Matrix() blas64.General { 255 n := int(f) 256 a := zeros(n, n, n) 257 if n > 1 { 258 a.Data[1] = 1 259 } 260 for i := 1; i < n; i++ { 261 a.Data[i*a.Stride+i-1] = 1 262 a.Data[i*a.Stride+i] = 1 263 } 264 return a 265 } 266 267 func (f Fibonacci) Eigenvalues() []complex128 { 268 n := int(f) 269 ev := make([]complex128, n) 270 if n == 0 || n == 1 { 271 return ev 272 } 273 phi := 0.5 * (1 + math.Sqrt(5)) 274 ev[0] = complex(phi, 0) 275 for i := 1; i < n-1; i++ { 276 ev[i] = 1 + 0i 277 } 278 ev[n-1] = complex(1-phi, 0) 279 return ev 280 } 281 282 // Gear is a singular non-symmetric matrix with real eigenvalues. For example, 283 // for n=5, 284 // [ . 1 . . 1 ] 285 // [ 1 . 1 . . ] 286 // A = [ . 1 . 1 . ] 287 // [ . . 1 . 1 ] 288 // [-1 . . 1 . ] 289 type Gear int 290 291 func (g Gear) Matrix() blas64.General { 292 n := int(g) 293 a := zeros(n, n, n) 294 if n == 1 { 295 return a 296 } 297 for i := 0; i < n-1; i++ { 298 a.Data[i*a.Stride+i+1] = 1 299 } 300 for i := 1; i < n; i++ { 301 a.Data[i*a.Stride+i-1] = 1 302 } 303 a.Data[n-1] = 1 304 a.Data[(n-1)*a.Stride] = -1 305 return a 306 } 307 308 func (g Gear) Eigenvalues() []complex128 { 309 n := int(g) 310 ev := make([]complex128, n) 311 if n == 0 || n == 1 { 312 return ev 313 } 314 if n == 2 { 315 ev[0] = complex(0, 1) 316 ev[1] = complex(0, -1) 317 return ev 318 } 319 w := 0 320 ev[w] = math.Pi / 2 321 w++ 322 phi := (n - 1) / 2 323 for p := 1; p <= phi; p++ { 324 ev[w] = complex(float64(2*p)*math.Pi/float64(n), 0) 325 w++ 326 } 327 phi = n / 2 328 for p := 1; p <= phi; p++ { 329 ev[w] = complex(float64(2*p-1)*math.Pi/float64(n), 0) 330 w++ 331 } 332 for i, v := range ev { 333 ev[i] = complex(2*math.Cos(real(v)), 0) 334 } 335 return ev 336 } 337 338 // Grcar is an upper Hessenberg matrix given by 339 // A[i,j] = -1 if i == j+1, 340 // = 1 if i <= j and j <= i+k, 341 // = 0 otherwise. 342 // For example, for n=5 and k=2, 343 // [ 1 1 1 . . ] 344 // [ -1 1 1 1 . ] 345 // A = [ . -1 1 1 1 ] 346 // [ . . -1 1 1 ] 347 // [ . . . -1 1 ] 348 // The matrix has sensitive eigenvalues but they are not given explicitly. 349 type Grcar struct { 350 N int 351 K int 352 } 353 354 func (g Grcar) Matrix() blas64.General { 355 n := g.N 356 a := zeros(n, n, n) 357 for k := 0; k <= g.K; k++ { 358 for i := 0; i < n-k; i++ { 359 a.Data[i*a.Stride+i+k] = 1 360 } 361 } 362 for i := 1; i < n; i++ { 363 a.Data[i*a.Stride+i-1] = -1 364 } 365 return a 366 } 367 368 func (Grcar) Eigenvalues() []complex128 { 369 return nil 370 } 371 372 // Hanowa is a non-symmetric non-singular matrix of even order given by 373 // A[i,j] = alpha if i == j, 374 // = -i-1 if i < n/2 and j == i + n/2, 375 // = i+1-n/2 if i >= n/2 and j == i - n/2, 376 // = 0 otherwise. 377 // The matrix has complex eigenvalues. 378 type Hanowa struct { 379 N int // Order of the matrix, must be even. 380 Alpha float64 381 } 382 383 func (h Hanowa) Matrix() blas64.General { 384 if h.N&0x1 != 0 { 385 panic("lapack: matrix order must be even") 386 } 387 n := h.N 388 a := zeros(n, n, n) 389 for i := 0; i < n; i++ { 390 a.Data[i*a.Stride+i] = h.Alpha 391 } 392 for i := 0; i < n/2; i++ { 393 a.Data[i*a.Stride+i+n/2] = float64(-i - 1) 394 } 395 for i := n / 2; i < n; i++ { 396 a.Data[i*a.Stride+i-n/2] = float64(i + 1 - n/2) 397 } 398 return a 399 } 400 401 func (h Hanowa) Eigenvalues() []complex128 { 402 if h.N&0x1 != 0 { 403 panic("lapack: matrix order must be even") 404 } 405 n := h.N 406 ev := make([]complex128, n) 407 for i := 0; i < n/2; i++ { 408 ev[2*i] = complex(h.Alpha, float64(-i-1)) 409 ev[2*i+1] = complex(h.Alpha, float64(i+1)) 410 } 411 return ev 412 } 413 414 // Lesp is a tridiagonal, generally non-symmetric matrix given by 415 // A[i,j] = -2*i-5 if i == j, 416 // = 1/(i+1) if i == j-1, 417 // = j+1 if i == j+1. 418 // For example, for n=5, 419 // [ -5 2 . . . ] 420 // [ 1/2 -7 3 . . ] 421 // A = [ . 1/3 -9 4 . ] 422 // [ . . 1/4 -11 5 ] 423 // [ . . . 1/5 -13 ]. 424 // The matrix has sensitive eigenvalues but they are not given explicitly. 425 type Lesp int 426 427 func (l Lesp) Matrix() blas64.General { 428 n := int(l) 429 a := zeros(n, n, n) 430 for i := 0; i < n; i++ { 431 a.Data[i*a.Stride+i] = float64(-2*i - 5) 432 } 433 for i := 0; i < n-1; i++ { 434 a.Data[i*a.Stride+i+1] = float64(i + 2) 435 } 436 for i := 1; i < n; i++ { 437 a.Data[i*a.Stride+i-1] = 1 / float64(i+1) 438 } 439 return a 440 } 441 442 func (Lesp) Eigenvalues() []complex128 { 443 return nil 444 } 445 446 // Rutis is the 4×4 non-symmetric matrix 447 // [ 4 -5 0 3 ] 448 // A = [ 0 4 -3 -5 ] 449 // [ 5 -3 4 0 ] 450 // [ 3 0 5 4 ] 451 // It has two distinct real eigenvalues and a pair of complex eigenvalues. 452 type Rutis struct{} 453 454 func (Rutis) Matrix() blas64.General { 455 return blas64.General{ 456 Rows: 4, 457 Cols: 4, 458 Stride: 4, 459 Data: []float64{ 460 4, -5, 0, 3, 461 0, 4, -3, -5, 462 5, -3, 4, 0, 463 3, 0, 5, 4, 464 }, 465 } 466 } 467 468 func (Rutis) Eigenvalues() []complex128 { 469 return []complex128{12, 1 + 5i, 1 - 5i, 2} 470 } 471 472 // Tris is a tridiagonal matrix given by 473 // A[i,j] = x if i == j-1, 474 // = y if i == j, 475 // = z if i == j+1. 476 // If x*z is negative, the matrix has complex eigenvalues. 477 type Tris struct { 478 N int 479 X, Y, Z float64 480 } 481 482 func (t Tris) Matrix() blas64.General { 483 n := t.N 484 a := zeros(n, n, n) 485 for i := 1; i < n; i++ { 486 a.Data[i*a.Stride+i-1] = t.X 487 } 488 for i := 0; i < n; i++ { 489 a.Data[i*a.Stride+i] = t.Y 490 } 491 for i := 0; i < n-1; i++ { 492 a.Data[i*a.Stride+i+1] = t.Z 493 } 494 return a 495 } 496 497 func (t Tris) Eigenvalues() []complex128 { 498 n := t.N 499 ev := make([]complex128, n) 500 for i := range ev { 501 angle := float64(i+1) * math.Pi / float64(n+1) 502 arg := t.X * t.Z 503 if arg >= 0 { 504 ev[i] = complex(t.Y+2*math.Sqrt(arg)*math.Cos(angle), 0) 505 } else { 506 ev[i] = complex(t.Y, 2*math.Sqrt(-arg)*math.Cos(angle)) 507 } 508 } 509 return ev 510 } 511 512 // Wilk4 is a 4×4 lower triangular matrix with 4 distinct real eigenvalues. 513 type Wilk4 struct{} 514 515 func (Wilk4) Matrix() blas64.General { 516 return blas64.General{ 517 Rows: 4, 518 Cols: 4, 519 Stride: 4, 520 Data: []float64{ 521 0.9143e-4, 0.0, 0.0, 0.0, 522 0.8762, 0.7156e-4, 0.0, 0.0, 523 0.7943, 0.8143, 0.9504e-4, 0.0, 524 0.8017, 0.6123, 0.7165, 0.7123e-4, 525 }, 526 } 527 } 528 529 func (Wilk4) Eigenvalues() []complex128 { 530 return []complex128{ 531 0.9504e-4, 0.9143e-4, 0.7156e-4, 0.7123e-4, 532 } 533 } 534 535 // Wilk12 is a 12×12 lower Hessenberg matrix with 12 distinct real eigenvalues. 536 type Wilk12 struct{} 537 538 func (Wilk12) Matrix() blas64.General { 539 return blas64.General{ 540 Rows: 12, 541 Cols: 12, 542 Stride: 12, 543 Data: []float64{ 544 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 545 11, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 546 10, 10, 10, 9, 0, 0, 0, 0, 0, 0, 0, 0, 547 9, 9, 9, 9, 8, 0, 0, 0, 0, 0, 0, 0, 548 8, 8, 8, 8, 8, 7, 0, 0, 0, 0, 0, 0, 549 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, 550 6, 6, 6, 6, 6, 6, 6, 5, 0, 0, 0, 0, 551 5, 5, 5, 5, 5, 5, 5, 5, 4, 0, 0, 0, 552 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 0, 0, 553 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 554 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 555 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 556 }, 557 } 558 } 559 560 func (Wilk12) Eigenvalues() []complex128 { 561 return []complex128{ 562 32.2288915015722210, 563 20.1989886458770691, 564 12.3110774008685340, 565 6.9615330855671154, 566 3.5118559485807528, 567 1.5539887091319704, 568 0.6435053190136506, 569 0.2847497205488856, 570 0.1436465181918488, 571 0.0812276683076552, 572 0.0495074140194613, 573 0.0310280683208907, 574 } 575 } 576 577 // Wilk20 is a 20×20 lower Hessenberg matrix. If the parameter is 0, the matrix 578 // has 20 distinct real eigenvalues. If the parameter is 1e-10, the matrix has 6 579 // real eigenvalues and 7 pairs of complex eigenvalues. 580 type Wilk20 float64 581 582 func (w Wilk20) Matrix() blas64.General { 583 a := zeros(20, 20, 20) 584 for i := 0; i < 20; i++ { 585 a.Data[i*a.Stride+i] = float64(i + 1) 586 } 587 for i := 0; i < 19; i++ { 588 a.Data[i*a.Stride+i+1] = 20 589 } 590 a.Data[19*a.Stride] = float64(w) 591 return a 592 } 593 594 func (w Wilk20) Eigenvalues() []complex128 { 595 if float64(w) == 0 { 596 ev := make([]complex128, 20) 597 for i := range ev { 598 ev[i] = complex(float64(i+1), 0) 599 } 600 return ev 601 } 602 return nil 603 } 604 605 // Zero is a matrix with all elements equal to zero. 606 type Zero int 607 608 func (z Zero) Matrix() blas64.General { 609 n := int(z) 610 return zeros(n, n, n) 611 } 612 613 func (z Zero) Eigenvalues() []complex128 { 614 n := int(z) 615 return make([]complex128, n) 616 }