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