gonum.org/v1/gonum@v0.14.0/blas/testblas/dgemv.go (about) 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. 4 5 package testblas 6 7 import ( 8 "testing" 9 10 "gonum.org/v1/gonum/blas" 11 ) 12 13 type DgemvCase struct { 14 Name string 15 m int 16 n int 17 A [][]float64 18 tA blas.Transpose 19 x []float64 20 incX int 21 y []float64 22 incY int 23 24 Subcases []DgemvSubcase 25 } 26 27 type DgemvSubcase struct { 28 mulXNeg1 bool 29 mulYNeg1 bool 30 alpha float64 31 beta float64 32 ans []float64 33 } 34 35 var DgemvCases = []DgemvCase{ 36 { 37 Name: "M_gt_N_Inc1_NoTrans", 38 tA: blas.NoTrans, 39 m: 5, 40 n: 3, 41 A: [][]float64{ 42 {4.1, 6.2, 8.1}, 43 {9.6, 3.5, 9.1}, 44 {10, 7, 3}, 45 {1, 1, 2}, 46 {9, 2, 5}, 47 }, 48 incX: 1, 49 incY: 1, 50 x: []float64{1, 2, 3}, 51 y: []float64{7, 8, 9, 10, 11}, 52 53 Subcases: []DgemvSubcase{ 54 { 55 alpha: 0, 56 beta: 0, 57 ans: []float64{0, 0, 0, 0, 0}, 58 }, 59 { 60 alpha: 0, 61 beta: 1, 62 ans: []float64{7, 8, 9, 10, 11}, 63 }, 64 { 65 alpha: 1, 66 beta: 0, 67 ans: []float64{40.8, 43.9, 33, 9, 28}, 68 }, 69 { 70 alpha: 8, 71 beta: -6, 72 ans: []float64{284.4, 303.2, 210, 12, 158}, 73 }, 74 }, 75 }, 76 { 77 Name: "M_gt_N_Inc1_Trans", 78 tA: blas.Trans, 79 m: 5, 80 n: 3, 81 A: [][]float64{ 82 {4.1, 6.2, 8.1}, 83 {9.6, 3.5, 9.1}, 84 {10, 7, 3}, 85 {1, 1, 2}, 86 {9, 2, 5}, 87 }, 88 incX: 1, 89 incY: 1, 90 x: []float64{1, 2, 3, -4, 5}, 91 y: []float64{7, 8, 9}, 92 93 Subcases: []DgemvSubcase{ 94 { 95 alpha: 0, 96 beta: 0, 97 ans: []float64{0, 0, 0}, 98 }, 99 { 100 alpha: 0, 101 beta: 1, 102 ans: []float64{7, 8, 9}, 103 }, 104 { 105 alpha: 1, 106 beta: 0, 107 ans: []float64{94.3, 40.2, 52.3}, 108 }, 109 { 110 alpha: 8, 111 beta: -6, 112 ans: []float64{712.4, 273.6, 364.4}, 113 }, 114 }, 115 }, 116 { 117 Name: "M_eq_N_Inc1_NoTrans", 118 tA: blas.NoTrans, 119 m: 3, 120 n: 3, 121 A: [][]float64{ 122 {4.1, 6.2, 8.1}, 123 {9.6, 3.5, 9.1}, 124 {10, 7, 3}, 125 }, 126 incX: 1, 127 incY: 1, 128 x: []float64{1, 2, 3}, 129 y: []float64{7, 2, 2}, 130 131 Subcases: []DgemvSubcase{ 132 { 133 alpha: 0, 134 beta: 0, 135 ans: []float64{0, 0, 0}, 136 }, 137 { 138 alpha: 0, 139 beta: 1, 140 ans: []float64{7, 2, 2}, 141 }, 142 { 143 alpha: 1, 144 beta: 0, 145 ans: []float64{40.8, 43.9, 33}, 146 }, 147 { 148 alpha: 8, 149 beta: -6, 150 ans: []float64{40.8*8 - 6*7, 43.9*8 - 6*2, 33*8 - 6*2}, 151 }, 152 }, 153 }, 154 { 155 Name: "M_eq_N_Inc1_Trans", 156 tA: blas.Trans, 157 m: 3, 158 n: 3, 159 A: [][]float64{ 160 {4.1, 6.2, 8.1}, 161 {9.6, 3.5, 9.1}, 162 {10, 7, 3}, 163 }, 164 incX: 1, 165 incY: 1, 166 x: []float64{1, 2, 3}, 167 y: []float64{7, 2, 2}, 168 169 Subcases: []DgemvSubcase{ 170 { 171 alpha: 8, 172 beta: -6, 173 ans: []float64{384.4, 261.6, 270.4}, 174 }, 175 }, 176 }, 177 { 178 Name: "M_lt_N_Inc1_NoTrans", 179 tA: blas.NoTrans, 180 m: 3, 181 n: 5, 182 A: [][]float64{ 183 {4.1, 6.2, 8.1, 10, 7}, 184 {9.6, 3.5, 9.1, -2, 9}, 185 {10, 7, 3, 1, -5}, 186 }, 187 incX: 1, 188 incY: 1, 189 x: []float64{1, 2, 3, -7.6, 8.1}, 190 y: []float64{7, 2, 2}, 191 192 Subcases: []DgemvSubcase{ 193 { 194 alpha: 0, 195 beta: 0, 196 ans: []float64{0, 0, 0}, 197 }, 198 { 199 alpha: 0, 200 beta: 1, 201 ans: []float64{7, 2, 2}, 202 }, 203 { 204 alpha: 1, 205 beta: 0, 206 ans: []float64{21.5, 132, -15.1}, 207 }, 208 209 { 210 alpha: 8, 211 beta: -6, 212 ans: []float64{21.5*8 - 6*7, 132*8 - 6*2, -15.1*8 - 6*2}, 213 }, 214 }, 215 }, 216 { 217 Name: "M_lt_N_Inc1_Trans", 218 tA: blas.Trans, 219 m: 3, 220 n: 5, 221 A: [][]float64{ 222 {4.1, 6.2, 8.1, 10, 7}, 223 {9.6, 3.5, 9.1, -2, 9}, 224 {10, 7, 3, 1, -5}, 225 }, 226 incX: 1, 227 incY: 1, 228 x: []float64{1, 2, 3}, 229 y: []float64{7, 2, 2, -3, 5}, 230 231 Subcases: []DgemvSubcase{ 232 { 233 alpha: 8, 234 beta: -6, 235 ans: []float64{384.4, 261.6, 270.4, 90, 50}, 236 }, 237 }, 238 }, 239 { 240 Name: "M_gt_N_Part1_NoTrans", 241 tA: blas.NoTrans, 242 m: 5, 243 n: 3, 244 A: [][]float64{ 245 {4.1, 6.2, 8.1}, 246 {9.6, 3.5, 9.1}, 247 {10, 7, 3}, 248 {1, 1, 2}, 249 {9, 2, 5}, 250 }, 251 incX: 1, 252 incY: 2, 253 x: []float64{1, 2, 3}, 254 y: []float64{7, 100, 8, 101, 9, 102, 10, 103, 11}, 255 256 Subcases: []DgemvSubcase{ 257 { 258 alpha: 0, 259 beta: 0, 260 ans: []float64{0, 100, 0, 101, 0, 102, 0, 103, 0}, 261 }, 262 { 263 alpha: 0, 264 beta: 1, 265 ans: []float64{7, 100, 8, 101, 9, 102, 10, 103, 11}, 266 }, 267 { 268 alpha: 1, 269 beta: 0, 270 ans: []float64{40.8, 100, 43.9, 101, 33, 102, 9, 103, 28}, 271 }, 272 { 273 alpha: 8, 274 beta: -6, 275 ans: []float64{284.4, 100, 303.2, 101, 210, 102, 12, 103, 158}, 276 }, 277 }, 278 }, 279 { 280 Name: "M_gt_N_Part1_Trans", 281 tA: blas.Trans, 282 m: 5, 283 n: 3, 284 A: [][]float64{ 285 {4.1, 6.2, 8.1}, 286 {9.6, 3.5, 9.1}, 287 {10, 7, 3}, 288 {1, 1, 2}, 289 {9, 2, 5}, 290 }, 291 incX: 1, 292 incY: 2, 293 x: []float64{1, 2, 3, -4, 5}, 294 y: []float64{7, 100, 8, 101, 9}, 295 296 Subcases: []DgemvSubcase{ 297 { 298 alpha: 0, 299 beta: 0, 300 ans: []float64{0, 100, 0, 101, 0}, 301 }, 302 { 303 alpha: 0, 304 beta: 1, 305 ans: []float64{7, 100, 8, 101, 9}, 306 }, 307 { 308 alpha: 1, 309 beta: 0, 310 ans: []float64{94.3, 100, 40.2, 101, 52.3}, 311 }, 312 { 313 alpha: 8, 314 beta: -6, 315 ans: []float64{712.4, 100, 273.6, 101, 364.4}, 316 }, 317 }, 318 }, 319 { 320 Name: "M_gt_N_IncNot1_NoTrans", 321 tA: blas.NoTrans, 322 m: 5, 323 n: 3, 324 325 A: [][]float64{ 326 {4.1, 6.2, 8.1}, 327 {9.6, 3.5, 9.1}, 328 {10, 7, 3}, 329 {1, 1, 2}, 330 {9, 2, 5}, 331 }, 332 incX: 2, 333 incY: 3, 334 x: []float64{1, 15, 2, 150, 3}, 335 y: []float64{7, 2, 6, 8, -4, -5, 9, 1, 1, 10, 19, 22, 11}, 336 Subcases: []DgemvSubcase{ 337 { 338 alpha: 8, 339 beta: -6, 340 ans: []float64{284.4, 2, 6, 303.2, -4, -5, 210, 1, 1, 12, 19, 22, 158}, 341 }, 342 { 343 mulXNeg1: true, 344 alpha: 8, 345 beta: -6, 346 ans: []float64{220.4, 2, 6, 311.2, -4, -5, 322, 1, 1, -4, 19, 22, 222}, 347 }, 348 { 349 mulYNeg1: true, 350 alpha: 8, 351 beta: -6, 352 ans: []float64{182, 2, 6, 24, -4, -5, 210, 1, 1, 291.2, 19, 22, 260.4}, 353 }, 354 { 355 mulXNeg1: true, 356 mulYNeg1: true, 357 alpha: 8, 358 beta: -6, 359 ans: []float64{246, 2, 6, 8, -4, -5, 322, 1, 1, 299.2, 19, 22, 196.4}, 360 }, 361 }, 362 }, 363 { 364 Name: "M_gt_N_IncNot1_Trans", 365 tA: blas.Trans, 366 m: 5, 367 n: 3, 368 369 A: [][]float64{ 370 {4.1, 6.2, 8.1}, 371 {9.6, 3.5, 9.1}, 372 {10, 7, 3}, 373 {1, 1, 2}, 374 {9, 2, 5}, 375 }, 376 incX: 2, 377 incY: 3, 378 x: []float64{1, 15, 2, 150, 3, 8, -3, 6, 5}, 379 y: []float64{7, 2, 6, 8, -4, -5, 9}, 380 Subcases: []DgemvSubcase{ 381 { 382 alpha: 8, 383 beta: -6, 384 ans: []float64{720.4, 2, 6, 281.6, -4, -5, 380.4}, 385 }, 386 { 387 mulXNeg1: true, 388 alpha: 8, 389 beta: -6, 390 ans: []float64{219.6, 2, 6, 316, -4, -5, 195.6}, 391 }, 392 { 393 mulYNeg1: true, 394 alpha: 8, 395 beta: -6, 396 ans: []float64{392.4, 2, 6, 281.6, -4, -5, 708.4}, 397 }, 398 { 399 mulXNeg1: true, 400 mulYNeg1: true, 401 alpha: 8, 402 beta: -6, 403 ans: []float64{207.6, 2, 6, 316, -4, -5, 207.6}, 404 }, 405 }, 406 }, 407 { 408 Name: "M_eq_N_IncNot1_NoTrans", 409 tA: blas.NoTrans, 410 m: 3, 411 n: 3, 412 A: [][]float64{ 413 {4.1, 6.2, 8.1}, 414 {9.6, 3.5, 9.1}, 415 {10, 7, 3}, 416 }, 417 incX: 2, 418 incY: 3, 419 x: []float64{1, 15, 2, 150, 3}, 420 y: []float64{7, 2, 6, 8, -4, -5, 9}, 421 Subcases: []DgemvSubcase{ 422 { 423 alpha: 8, 424 beta: -6, 425 ans: []float64{284.4, 2, 6, 303.2, -4, -5, 210}, 426 }, 427 { 428 mulXNeg1: true, 429 alpha: 8, 430 beta: -6, 431 ans: []float64{220.4, 2, 6, 311.2, -4, -5, 322}, 432 }, 433 { 434 mulYNeg1: true, 435 alpha: 8, 436 beta: -6, 437 ans: []float64{222, 2, 6, 303.2, -4, -5, 272.4}, 438 }, 439 { 440 mulXNeg1: true, 441 mulYNeg1: true, 442 alpha: 8, 443 beta: -6, 444 ans: []float64{334, 2, 6, 311.2, -4, -5, 208.4}, 445 }, 446 }, 447 }, 448 { 449 Name: "M_eq_N_IncNot1_Trans", 450 tA: blas.Trans, 451 m: 3, 452 n: 3, 453 A: [][]float64{ 454 {4.1, 6.2, 8.1}, 455 {9.6, 3.5, 9.1}, 456 {10, 7, 3}, 457 }, 458 incX: 2, 459 incY: 3, 460 x: []float64{1, 15, 2, 150, 3}, 461 y: []float64{7, 2, 6, 8, -4, -5, 9}, 462 463 Subcases: []DgemvSubcase{ 464 { 465 alpha: 8, 466 beta: -6, 467 ans: []float64{384.4, 2, 6, 225.6, -4, -5, 228.4}, 468 }, 469 { 470 mulXNeg1: true, 471 alpha: 8, 472 beta: -6, 473 ans: []float64{290, 2, 6, 212.8, -4, -5, 310}, 474 }, 475 { 476 mulYNeg1: true, 477 alpha: 8, 478 beta: -6, 479 ans: []float64{240.4, 2, 6, 225.6, -4, -5, 372.4}, 480 }, 481 { 482 mulXNeg1: true, 483 mulYNeg1: true, 484 alpha: 8, 485 beta: -6, 486 ans: []float64{322, 2, 6, 212.8, -4, -5, 278}, 487 }, 488 }, 489 }, 490 { 491 Name: "M_lt_N_IncNot1_NoTrans", 492 tA: blas.NoTrans, 493 m: 3, 494 n: 5, 495 A: [][]float64{ 496 {4.1, 6.2, 8.1, 10, 11}, 497 {9.6, 3.5, 9.1, -3, -2}, 498 {10, 7, 3, -7, -4}, 499 }, 500 incX: 2, 501 incY: 3, 502 x: []float64{1, 15, 2, 150, 3, -2, -4, 8, -9}, 503 y: []float64{7, 2, 6, 8, -4, -5, 9}, 504 505 Subcases: []DgemvSubcase{ 506 { 507 alpha: 8, 508 beta: -6, 509 ans: []float64{-827.6, 2, 6, 543.2, -4, -5, 722}, 510 }, 511 { 512 mulXNeg1: true, 513 alpha: 8, 514 beta: -6, 515 ans: []float64{-93.2, 2, 6, -696.8, -4, -5, -1070}, 516 }, 517 { 518 mulYNeg1: true, 519 alpha: 8, 520 beta: -6, 521 ans: []float64{734, 2, 6, 543.2, -4, -5, -839.6}, 522 }, 523 { 524 mulXNeg1: true, 525 mulYNeg1: true, 526 alpha: 8, 527 beta: -6, 528 ans: []float64{-1058, 2, 6, -696.8, -4, -5, -105.2}, 529 }, 530 }, 531 }, 532 { 533 Name: "M_lt_N_IncNot1_Trans", 534 tA: blas.Trans, 535 m: 3, 536 n: 5, 537 A: [][]float64{ 538 {4.1, 6.2, 8.1, 10, 11}, 539 {9.6, 3.5, 9.1, -3, -2}, 540 {10, 7, 3, -7, -4}, 541 }, 542 incX: 2, 543 incY: 3, 544 x: []float64{1, 15, 2, 150, 3}, 545 y: []float64{7, 2, 6, 8, -4, -5, 9, -4, -1, -9, 1, 1, 2}, 546 547 Subcases: []DgemvSubcase{ 548 { 549 alpha: 8, 550 beta: -6, 551 ans: []float64{384.4, 2, 6, 225.6, -4, -5, 228.4, -4, -1, -82, 1, 1, -52}, 552 }, 553 { 554 mulXNeg1: true, 555 alpha: 8, 556 beta: -6, 557 ans: []float64{290, 2, 6, 212.8, -4, -5, 310, -4, -1, 190, 1, 1, 188}, 558 }, 559 { 560 mulYNeg1: true, 561 alpha: 8, 562 beta: -6, 563 ans: []float64{-82, 2, 6, -184, -4, -5, 228.4, -4, -1, 327.6, 1, 1, 414.4}, 564 }, 565 { 566 mulXNeg1: true, 567 mulYNeg1: true, 568 alpha: 8, 569 beta: -6, 570 ans: []float64{158, 2, 6, 88, -4, -5, 310, -4, -1, 314.8, 1, 1, 320}, 571 }, 572 }, 573 }, 574 { 575 Name: "M_eq_N_Lg_IncNot1_Trans", 576 tA: blas.Trans, 577 m: 7, 578 n: 7, 579 A: [][]float64{ 580 {4.1, 6.2, 8.1, 2.5, 3.3, 7.4, 9.3}, 581 {9.6, 3.5, 9.1, 1.2, 5.4, 4.8, 8.7}, 582 {10, 7, 3, 2, 4, 1, 12}, 583 {9.6, 3.5, 9.1, 1.2, 5.4, 4.8, 8.7}, 584 {4.1, 6.2, 8.1, 2.5, 3.3, 7.4, 9.3}, 585 {10, 7, 3, 2, 4, 1, 12}, 586 {9.6, 3.5, 9.1, 1.2, 5.4, 4.8, 8.7}, 587 }, 588 incX: 2, 589 incY: 3, 590 x: []float64{1, 105, 2, 150, 3, 200, 4, 300, 5, 600, 6, 700, 7}, 591 y: []float64{7, 200, 600, 8, -400, -500, 9, 600, 700, 10, 500, 400, 11, 200, 300, 12, 100, 200, 13, 300, 400, 14}, 592 593 Subcases: []DgemvSubcase{ 594 { 595 alpha: 8, 596 beta: -6, 597 ans: []float64{1873.1999999999998, 200, 600, 1117.6, -400, -500, 1497.1999999999998, 600, 700, 328.8, 500, 400, 942, 200, 300, 854.4000000000001, 100, 200, 2137.2, 300, 400, 14}, 598 }, 599 { 600 mulXNeg1: true, 601 alpha: 8, 602 beta: -6, 603 ans: []float64{1690.8, 200, 600, 1148, -400, -500, 1562.8, 600, 700, 357.6, 500, 400, 897.2, 200, 300, 998.4, 100, 200, 2103.6000000000004, 300, 400, 14}, 604 }, 605 { 606 mulYNeg1: true, 607 alpha: 8, 608 beta: -6, 609 ans: []float64{2173.2, 200, 600, 878.4000000000001, -400, -500, 954, 600, 700, 328.8, 500, 400, 1485.1999999999998, 200, 300, 1093.6, 100, 200, 1837.1999999999998, 300, 400, 14}, 610 }, 611 { 612 mulXNeg1: true, 613 mulYNeg1: true, 614 alpha: 8, 615 beta: -6, 616 ans: []float64{2139.6, 200, 600, 1022.4, -400, -500, 909.2, 600, 700, 357.6, 500, 400, 1550.8, 200, 300, 1124, 100, 200, 1654.8, 300, 400, 14}, 617 }, 618 }, 619 }, 620 621 // TODO: A can be longer than mxn. Add cases where it is longer 622 // TODO: x and y can also be longer. Add tests for these 623 // TODO: Add tests for dimension mismatch 624 // TODO: Add places with a "submatrix view", where lda != m 625 } 626 627 type Dgemver interface { 628 Dgemv(tA blas.Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) 629 } 630 631 func DgemvTest(t *testing.T, blasser Dgemver) { 632 for _, test := range DgemvCases { 633 for i, cas := range test.Subcases { 634 // Test that it passes with row-major 635 dgemvcomp(t, test, cas, i, blasser) 636 637 // Test the bad inputs 638 dgemvbad(t, test, cas, i, blasser) 639 } 640 } 641 } 642 643 func dgemvcomp(t *testing.T, test DgemvCase, cas DgemvSubcase, i int, blasser Dgemver) { 644 x := sliceCopy(test.x) 645 y := sliceCopy(test.y) 646 a := sliceOfSliceCopy(test.A) 647 aFlat := flatten(a) 648 649 lda := test.n 650 651 incX := test.incX 652 if cas.mulXNeg1 { 653 incX *= -1 654 } 655 incY := test.incY 656 if cas.mulYNeg1 { 657 incY *= -1 658 } 659 660 f := func() { 661 blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlat, lda, x, incX, cas.beta, y, incY) 662 } 663 if panics(f) { 664 t.Errorf("Test %v case %v: unexpected panic", test.Name, i) 665 if throwPanic { 666 blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlat, lda, x, incX, cas.beta, y, incY) 667 } 668 return 669 } 670 // Check that x and a are unchanged 671 if !dSliceEqual(x, test.x) { 672 t.Errorf("Test %v, case %v: x modified during call", test.Name, i) 673 } 674 aFlat2 := flatten(sliceOfSliceCopy(test.A)) 675 if !dSliceEqual(aFlat2, aFlat) { 676 t.Errorf("Test %v, case %v: a modified during call", test.Name, i) 677 } 678 679 // Check that the answer matches 680 if !dSliceTolEqual(cas.ans, y) { 681 t.Errorf("Test %v, case %v: answer mismatch: Expected %v, Found %v", test.Name, i, cas.ans, y) 682 } 683 } 684 685 func dgemvbad(t *testing.T, test DgemvCase, cas DgemvSubcase, i int, blasser Dgemver) { 686 x := sliceCopy(test.x) 687 y := sliceCopy(test.y) 688 a := sliceOfSliceCopy(test.A) 689 aFlatRow := flatten(a) 690 ldaRow := test.n 691 692 f := func() { 693 blasser.Dgemv('X', test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) 694 } 695 if !panics(f) { 696 t.Errorf("Test %v case %v: no panic for bad transpose", test.Name, i) 697 } 698 f = func() { 699 blasser.Dgemv(test.tA, -2, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) 700 } 701 if !panics(f) { 702 t.Errorf("Test %v case %v: no panic for m negative", test.Name, i) 703 } 704 f = func() { 705 blasser.Dgemv(test.tA, test.m, -4, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) 706 } 707 if !panics(f) { 708 t.Errorf("Test %v case %v: no panic for n negative", test.Name, i) 709 } 710 f = func() { 711 blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, 0, cas.beta, y, test.incY) 712 } 713 if !panics(f) { 714 t.Errorf("Test %v case %v: no panic for incX zero", test.Name, i) 715 } 716 f = func() { 717 blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, 0) 718 } 719 if !panics(f) { 720 t.Errorf("Test %v case %v: no panic for incY zero", test.Name, i) 721 } 722 f = func() { 723 blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow-1, x, test.incX, cas.beta, y, test.incY) 724 } 725 if !panics(f) { 726 t.Errorf("Test %v case %v: no panic for lda too small row major", test.Name, i) 727 } 728 }