gonum.org/v1/gonum@v0.14.0/blas/gonum/level2cmplx128.go (about) 1 // Copyright ©2017 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 gonum 6 7 import ( 8 "math/cmplx" 9 10 "gonum.org/v1/gonum/blas" 11 "gonum.org/v1/gonum/internal/asm/c128" 12 ) 13 14 var _ blas.Complex128Level2 = Implementation{} 15 16 // Zgbmv performs one of the matrix-vector operations 17 // 18 // y = alpha * A * x + beta * y if trans = blas.NoTrans 19 // y = alpha * Aᵀ * x + beta * y if trans = blas.Trans 20 // y = alpha * Aᴴ * x + beta * y if trans = blas.ConjTrans 21 // 22 // where alpha and beta are scalars, x and y are vectors, and A is an m×n band matrix 23 // with kL sub-diagonals and kU super-diagonals. 24 func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { 25 switch trans { 26 default: 27 panic(badTranspose) 28 case blas.NoTrans, blas.Trans, blas.ConjTrans: 29 } 30 if m < 0 { 31 panic(mLT0) 32 } 33 if n < 0 { 34 panic(nLT0) 35 } 36 if kL < 0 { 37 panic(kLLT0) 38 } 39 if kU < 0 { 40 panic(kULT0) 41 } 42 if lda < kL+kU+1 { 43 panic(badLdA) 44 } 45 if incX == 0 { 46 panic(zeroIncX) 47 } 48 if incY == 0 { 49 panic(zeroIncY) 50 } 51 52 // Quick return if possible. 53 if m == 0 || n == 0 { 54 return 55 } 56 57 // For zero matrix size the following slice length checks are trivially satisfied. 58 if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { 59 panic(shortA) 60 } 61 var lenX, lenY int 62 if trans == blas.NoTrans { 63 lenX, lenY = n, m 64 } else { 65 lenX, lenY = m, n 66 } 67 if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { 68 panic(shortX) 69 } 70 if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { 71 panic(shortY) 72 } 73 74 // Quick return if possible. 75 if alpha == 0 && beta == 1 { 76 return 77 } 78 79 var kx int 80 if incX < 0 { 81 kx = (1 - lenX) * incX 82 } 83 var ky int 84 if incY < 0 { 85 ky = (1 - lenY) * incY 86 } 87 88 // Form y = beta*y. 89 if beta != 1 { 90 if incY == 1 { 91 if beta == 0 { 92 for i := range y[:lenY] { 93 y[i] = 0 94 } 95 } else { 96 c128.ScalUnitary(beta, y[:lenY]) 97 } 98 } else { 99 iy := ky 100 if beta == 0 { 101 for i := 0; i < lenY; i++ { 102 y[iy] = 0 103 iy += incY 104 } 105 } else { 106 if incY > 0 { 107 c128.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) 108 } else { 109 c128.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) 110 } 111 } 112 } 113 } 114 115 nRow := min(m, n+kL) 116 nCol := kL + 1 + kU 117 switch trans { 118 case blas.NoTrans: 119 iy := ky 120 if incX == 1 { 121 for i := 0; i < nRow; i++ { 122 l := max(0, kL-i) 123 u := min(nCol, n+kL-i) 124 aRow := a[i*lda+l : i*lda+u] 125 off := max(0, i-kL) 126 xtmp := x[off : off+u-l] 127 var sum complex128 128 for j, v := range aRow { 129 sum += xtmp[j] * v 130 } 131 y[iy] += alpha * sum 132 iy += incY 133 } 134 } else { 135 for i := 0; i < nRow; i++ { 136 l := max(0, kL-i) 137 u := min(nCol, n+kL-i) 138 aRow := a[i*lda+l : i*lda+u] 139 off := max(0, i-kL) * incX 140 jx := kx 141 var sum complex128 142 for _, v := range aRow { 143 sum += x[off+jx] * v 144 jx += incX 145 } 146 y[iy] += alpha * sum 147 iy += incY 148 } 149 } 150 case blas.Trans: 151 if incX == 1 { 152 for i := 0; i < nRow; i++ { 153 l := max(0, kL-i) 154 u := min(nCol, n+kL-i) 155 aRow := a[i*lda+l : i*lda+u] 156 off := max(0, i-kL) * incY 157 alphaxi := alpha * x[i] 158 jy := ky 159 for _, v := range aRow { 160 y[off+jy] += alphaxi * v 161 jy += incY 162 } 163 } 164 } else { 165 ix := kx 166 for i := 0; i < nRow; i++ { 167 l := max(0, kL-i) 168 u := min(nCol, n+kL-i) 169 aRow := a[i*lda+l : i*lda+u] 170 off := max(0, i-kL) * incY 171 alphaxi := alpha * x[ix] 172 jy := ky 173 for _, v := range aRow { 174 y[off+jy] += alphaxi * v 175 jy += incY 176 } 177 ix += incX 178 } 179 } 180 case blas.ConjTrans: 181 if incX == 1 { 182 for i := 0; i < nRow; i++ { 183 l := max(0, kL-i) 184 u := min(nCol, n+kL-i) 185 aRow := a[i*lda+l : i*lda+u] 186 off := max(0, i-kL) * incY 187 alphaxi := alpha * x[i] 188 jy := ky 189 for _, v := range aRow { 190 y[off+jy] += alphaxi * cmplx.Conj(v) 191 jy += incY 192 } 193 } 194 } else { 195 ix := kx 196 for i := 0; i < nRow; i++ { 197 l := max(0, kL-i) 198 u := min(nCol, n+kL-i) 199 aRow := a[i*lda+l : i*lda+u] 200 off := max(0, i-kL) * incY 201 alphaxi := alpha * x[ix] 202 jy := ky 203 for _, v := range aRow { 204 y[off+jy] += alphaxi * cmplx.Conj(v) 205 jy += incY 206 } 207 ix += incX 208 } 209 } 210 } 211 } 212 213 // Zgemv performs one of the matrix-vector operations 214 // 215 // y = alpha * A * x + beta * y if trans = blas.NoTrans 216 // y = alpha * Aᵀ * x + beta * y if trans = blas.Trans 217 // y = alpha * Aᴴ * x + beta * y if trans = blas.ConjTrans 218 // 219 // where alpha and beta are scalars, x and y are vectors, and A is an m×n dense matrix. 220 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) { 221 switch trans { 222 default: 223 panic(badTranspose) 224 case blas.NoTrans, blas.Trans, blas.ConjTrans: 225 } 226 if m < 0 { 227 panic(mLT0) 228 } 229 if n < 0 { 230 panic(nLT0) 231 } 232 if lda < max(1, n) { 233 panic(badLdA) 234 } 235 if incX == 0 { 236 panic(zeroIncX) 237 } 238 if incY == 0 { 239 panic(zeroIncY) 240 } 241 242 // Quick return if possible. 243 if m == 0 || n == 0 { 244 return 245 } 246 247 // For zero matrix size the following slice length checks are trivially satisfied. 248 var lenX, lenY int 249 if trans == blas.NoTrans { 250 lenX = n 251 lenY = m 252 } else { 253 lenX = m 254 lenY = n 255 } 256 if len(a) < lda*(m-1)+n { 257 panic(shortA) 258 } 259 if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { 260 panic(shortX) 261 } 262 if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { 263 panic(shortY) 264 } 265 266 // Quick return if possible. 267 if alpha == 0 && beta == 1 { 268 return 269 } 270 271 var kx int 272 if incX < 0 { 273 kx = (1 - lenX) * incX 274 } 275 var ky int 276 if incY < 0 { 277 ky = (1 - lenY) * incY 278 } 279 280 // Form y = beta*y. 281 if beta != 1 { 282 if incY == 1 { 283 if beta == 0 { 284 for i := range y[:lenY] { 285 y[i] = 0 286 } 287 } else { 288 c128.ScalUnitary(beta, y[:lenY]) 289 } 290 } else { 291 iy := ky 292 if beta == 0 { 293 for i := 0; i < lenY; i++ { 294 y[iy] = 0 295 iy += incY 296 } 297 } else { 298 if incY > 0 { 299 c128.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) 300 } else { 301 c128.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) 302 } 303 } 304 } 305 } 306 307 if alpha == 0 { 308 return 309 } 310 311 switch trans { 312 default: 313 // Form y = alpha*A*x + y. 314 iy := ky 315 if incX == 1 { 316 for i := 0; i < m; i++ { 317 y[iy] += alpha * c128.DotuUnitary(a[i*lda:i*lda+n], x[:n]) 318 iy += incY 319 } 320 return 321 } 322 for i := 0; i < m; i++ { 323 y[iy] += alpha * c128.DotuInc(a[i*lda:i*lda+n], x, uintptr(n), 1, uintptr(incX), 0, uintptr(kx)) 324 iy += incY 325 } 326 return 327 328 case blas.Trans: 329 // Form y = alpha*Aᵀ*x + y. 330 ix := kx 331 if incY == 1 { 332 for i := 0; i < m; i++ { 333 c128.AxpyUnitary(alpha*x[ix], a[i*lda:i*lda+n], y[:n]) 334 ix += incX 335 } 336 return 337 } 338 for i := 0; i < m; i++ { 339 c128.AxpyInc(alpha*x[ix], a[i*lda:i*lda+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) 340 ix += incX 341 } 342 return 343 344 case blas.ConjTrans: 345 // Form y = alpha*Aᴴ*x + y. 346 ix := kx 347 if incY == 1 { 348 for i := 0; i < m; i++ { 349 tmp := alpha * x[ix] 350 for j := 0; j < n; j++ { 351 y[j] += tmp * cmplx.Conj(a[i*lda+j]) 352 } 353 ix += incX 354 } 355 return 356 } 357 for i := 0; i < m; i++ { 358 tmp := alpha * x[ix] 359 jy := ky 360 for j := 0; j < n; j++ { 361 y[jy] += tmp * cmplx.Conj(a[i*lda+j]) 362 jy += incY 363 } 364 ix += incX 365 } 366 return 367 } 368 } 369 370 // Zgerc performs the rank-one operation 371 // 372 // A += alpha * x * yᴴ 373 // 374 // where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, 375 // and y is an n element vector. 376 func (Implementation) Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { 377 if m < 0 { 378 panic(mLT0) 379 } 380 if n < 0 { 381 panic(nLT0) 382 } 383 if lda < max(1, n) { 384 panic(badLdA) 385 } 386 if incX == 0 { 387 panic(zeroIncX) 388 } 389 if incY == 0 { 390 panic(zeroIncY) 391 } 392 393 // Quick return if possible. 394 if m == 0 || n == 0 { 395 return 396 } 397 398 // For zero matrix size the following slice length checks are trivially satisfied. 399 if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { 400 panic(shortX) 401 } 402 if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { 403 panic(shortY) 404 } 405 if len(a) < lda*(m-1)+n { 406 panic(shortA) 407 } 408 409 // Quick return if possible. 410 if alpha == 0 { 411 return 412 } 413 414 var kx, jy int 415 if incX < 0 { 416 kx = (1 - m) * incX 417 } 418 if incY < 0 { 419 jy = (1 - n) * incY 420 } 421 for j := 0; j < n; j++ { 422 if y[jy] != 0 { 423 tmp := alpha * cmplx.Conj(y[jy]) 424 c128.AxpyInc(tmp, x, a[j:], uintptr(m), uintptr(incX), uintptr(lda), uintptr(kx), 0) 425 } 426 jy += incY 427 } 428 } 429 430 // Zgeru performs the rank-one operation 431 // 432 // A += alpha * x * yᵀ 433 // 434 // where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, 435 // and y is an n element vector. 436 func (Implementation) Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { 437 if m < 0 { 438 panic(mLT0) 439 } 440 if n < 0 { 441 panic(nLT0) 442 } 443 if lda < max(1, n) { 444 panic(badLdA) 445 } 446 if incX == 0 { 447 panic(zeroIncX) 448 } 449 if incY == 0 { 450 panic(zeroIncY) 451 } 452 453 // Quick return if possible. 454 if m == 0 || n == 0 { 455 return 456 } 457 458 // For zero matrix size the following slice length checks are trivially satisfied. 459 if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { 460 panic(shortX) 461 } 462 if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { 463 panic(shortY) 464 } 465 if len(a) < lda*(m-1)+n { 466 panic(shortA) 467 } 468 469 // Quick return if possible. 470 if alpha == 0 { 471 return 472 } 473 474 var kx int 475 if incX < 0 { 476 kx = (1 - m) * incX 477 } 478 if incY == 1 { 479 for i := 0; i < m; i++ { 480 if x[kx] != 0 { 481 tmp := alpha * x[kx] 482 c128.AxpyUnitary(tmp, y[:n], a[i*lda:i*lda+n]) 483 } 484 kx += incX 485 } 486 return 487 } 488 var jy int 489 if incY < 0 { 490 jy = (1 - n) * incY 491 } 492 for i := 0; i < m; i++ { 493 if x[kx] != 0 { 494 tmp := alpha * x[kx] 495 c128.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(jy), 0) 496 } 497 kx += incX 498 } 499 } 500 501 // Zhbmv performs the matrix-vector operation 502 // 503 // y = alpha * A * x + beta * y 504 // 505 // where alpha and beta are scalars, x and y are vectors, and A is an n×n 506 // Hermitian band matrix with k super-diagonals. The imaginary parts of 507 // the diagonal elements of A are ignored and assumed to be zero. 508 func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { 509 switch uplo { 510 default: 511 panic(badUplo) 512 case blas.Upper, blas.Lower: 513 } 514 if n < 0 { 515 panic(nLT0) 516 } 517 if k < 0 { 518 panic(kLT0) 519 } 520 if lda < k+1 { 521 panic(badLdA) 522 } 523 if incX == 0 { 524 panic(zeroIncX) 525 } 526 if incY == 0 { 527 panic(zeroIncY) 528 } 529 530 // Quick return if possible. 531 if n == 0 { 532 return 533 } 534 535 // For zero matrix size the following slice length checks are trivially satisfied. 536 if len(a) < lda*(n-1)+k+1 { 537 panic(shortA) 538 } 539 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 540 panic(shortX) 541 } 542 if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { 543 panic(shortY) 544 } 545 546 // Quick return if possible. 547 if alpha == 0 && beta == 1 { 548 return 549 } 550 551 // Set up the start indices in X and Y. 552 var kx int 553 if incX < 0 { 554 kx = (1 - n) * incX 555 } 556 var ky int 557 if incY < 0 { 558 ky = (1 - n) * incY 559 } 560 561 // Form y = beta*y. 562 if beta != 1 { 563 if incY == 1 { 564 if beta == 0 { 565 for i := range y[:n] { 566 y[i] = 0 567 } 568 } else { 569 for i, v := range y[:n] { 570 y[i] = beta * v 571 } 572 } 573 } else { 574 iy := ky 575 if beta == 0 { 576 for i := 0; i < n; i++ { 577 y[iy] = 0 578 iy += incY 579 } 580 } else { 581 for i := 0; i < n; i++ { 582 y[iy] = beta * y[iy] 583 iy += incY 584 } 585 } 586 } 587 } 588 589 if alpha == 0 { 590 return 591 } 592 593 // The elements of A are accessed sequentially with one pass through a. 594 switch uplo { 595 case blas.Upper: 596 iy := ky 597 if incX == 1 { 598 for i := 0; i < n; i++ { 599 aRow := a[i*lda:] 600 alphaxi := alpha * x[i] 601 sum := alphaxi * complex(real(aRow[0]), 0) 602 u := min(k+1, n-i) 603 jy := incY 604 for j := 1; j < u; j++ { 605 v := aRow[j] 606 sum += alpha * x[i+j] * v 607 y[iy+jy] += alphaxi * cmplx.Conj(v) 608 jy += incY 609 } 610 y[iy] += sum 611 iy += incY 612 } 613 } else { 614 ix := kx 615 for i := 0; i < n; i++ { 616 aRow := a[i*lda:] 617 alphaxi := alpha * x[ix] 618 sum := alphaxi * complex(real(aRow[0]), 0) 619 u := min(k+1, n-i) 620 jx := incX 621 jy := incY 622 for j := 1; j < u; j++ { 623 v := aRow[j] 624 sum += alpha * x[ix+jx] * v 625 y[iy+jy] += alphaxi * cmplx.Conj(v) 626 jx += incX 627 jy += incY 628 } 629 y[iy] += sum 630 ix += incX 631 iy += incY 632 } 633 } 634 case blas.Lower: 635 iy := ky 636 if incX == 1 { 637 for i := 0; i < n; i++ { 638 l := max(0, k-i) 639 alphaxi := alpha * x[i] 640 jy := l * incY 641 aRow := a[i*lda:] 642 for j := l; j < k; j++ { 643 v := aRow[j] 644 y[iy] += alpha * v * x[i-k+j] 645 y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) 646 jy += incY 647 } 648 y[iy] += alphaxi * complex(real(aRow[k]), 0) 649 iy += incY 650 } 651 } else { 652 ix := kx 653 for i := 0; i < n; i++ { 654 l := max(0, k-i) 655 alphaxi := alpha * x[ix] 656 jx := l * incX 657 jy := l * incY 658 aRow := a[i*lda:] 659 for j := l; j < k; j++ { 660 v := aRow[j] 661 y[iy] += alpha * v * x[ix-k*incX+jx] 662 y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) 663 jx += incX 664 jy += incY 665 } 666 y[iy] += alphaxi * complex(real(aRow[k]), 0) 667 ix += incX 668 iy += incY 669 } 670 } 671 } 672 } 673 674 // Zhemv performs the matrix-vector operation 675 // 676 // y = alpha * A * x + beta * y 677 // 678 // where alpha and beta are scalars, x and y are vectors, and A is an n×n 679 // Hermitian matrix. The imaginary parts of the diagonal elements of A are 680 // ignored and assumed to be zero. 681 func (Implementation) Zhemv(uplo blas.Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { 682 switch uplo { 683 default: 684 panic(badUplo) 685 case blas.Upper, blas.Lower: 686 } 687 if n < 0 { 688 panic(nLT0) 689 } 690 if lda < max(1, n) { 691 panic(badLdA) 692 } 693 if incX == 0 { 694 panic(zeroIncX) 695 } 696 if incY == 0 { 697 panic(zeroIncY) 698 } 699 700 // Quick return if possible. 701 if n == 0 { 702 return 703 } 704 705 // For zero matrix size the following slice length checks are trivially satisfied. 706 if len(a) < lda*(n-1)+n { 707 panic(shortA) 708 } 709 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 710 panic(shortX) 711 } 712 if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { 713 panic(shortY) 714 } 715 716 // Quick return if possible. 717 if alpha == 0 && beta == 1 { 718 return 719 } 720 721 // Set up the start indices in X and Y. 722 var kx int 723 if incX < 0 { 724 kx = (1 - n) * incX 725 } 726 var ky int 727 if incY < 0 { 728 ky = (1 - n) * incY 729 } 730 731 // Form y = beta*y. 732 if beta != 1 { 733 if incY == 1 { 734 if beta == 0 { 735 for i := range y[:n] { 736 y[i] = 0 737 } 738 } else { 739 for i, v := range y[:n] { 740 y[i] = beta * v 741 } 742 } 743 } else { 744 iy := ky 745 if beta == 0 { 746 for i := 0; i < n; i++ { 747 y[iy] = 0 748 iy += incY 749 } 750 } else { 751 for i := 0; i < n; i++ { 752 y[iy] = beta * y[iy] 753 iy += incY 754 } 755 } 756 } 757 } 758 759 if alpha == 0 { 760 return 761 } 762 763 // The elements of A are accessed sequentially with one pass through 764 // the triangular part of A. 765 766 if uplo == blas.Upper { 767 // Form y when A is stored in upper triangle. 768 if incX == 1 && incY == 1 { 769 for i := 0; i < n; i++ { 770 tmp1 := alpha * x[i] 771 var tmp2 complex128 772 for j := i + 1; j < n; j++ { 773 y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) 774 tmp2 += a[i*lda+j] * x[j] 775 } 776 aii := complex(real(a[i*lda+i]), 0) 777 y[i] += tmp1*aii + alpha*tmp2 778 } 779 } else { 780 ix := kx 781 iy := ky 782 for i := 0; i < n; i++ { 783 tmp1 := alpha * x[ix] 784 var tmp2 complex128 785 jx := ix 786 jy := iy 787 for j := i + 1; j < n; j++ { 788 jx += incX 789 jy += incY 790 y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) 791 tmp2 += a[i*lda+j] * x[jx] 792 } 793 aii := complex(real(a[i*lda+i]), 0) 794 y[iy] += tmp1*aii + alpha*tmp2 795 ix += incX 796 iy += incY 797 } 798 } 799 return 800 } 801 802 // Form y when A is stored in lower triangle. 803 if incX == 1 && incY == 1 { 804 for i := 0; i < n; i++ { 805 tmp1 := alpha * x[i] 806 var tmp2 complex128 807 for j := 0; j < i; j++ { 808 y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) 809 tmp2 += a[i*lda+j] * x[j] 810 } 811 aii := complex(real(a[i*lda+i]), 0) 812 y[i] += tmp1*aii + alpha*tmp2 813 } 814 } else { 815 ix := kx 816 iy := ky 817 for i := 0; i < n; i++ { 818 tmp1 := alpha * x[ix] 819 var tmp2 complex128 820 jx := kx 821 jy := ky 822 for j := 0; j < i; j++ { 823 y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) 824 tmp2 += a[i*lda+j] * x[jx] 825 jx += incX 826 jy += incY 827 } 828 aii := complex(real(a[i*lda+i]), 0) 829 y[iy] += tmp1*aii + alpha*tmp2 830 ix += incX 831 iy += incY 832 } 833 } 834 } 835 836 // Zher performs the Hermitian rank-one operation 837 // 838 // A += alpha * x * xᴴ 839 // 840 // where A is an n×n Hermitian matrix, alpha is a real scalar, and x is an n 841 // element vector. On entry, the imaginary parts of the diagonal elements of A 842 // are ignored and assumed to be zero, on return they will be set to zero. 843 func (Implementation) Zher(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) { 844 switch uplo { 845 default: 846 panic(badUplo) 847 case blas.Upper, blas.Lower: 848 } 849 if n < 0 { 850 panic(nLT0) 851 } 852 if lda < max(1, n) { 853 panic(badLdA) 854 } 855 if incX == 0 { 856 panic(zeroIncX) 857 } 858 859 // Quick return if possible. 860 if n == 0 { 861 return 862 } 863 864 // For zero matrix size the following slice length checks are trivially satisfied. 865 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 866 panic(shortX) 867 } 868 if len(a) < lda*(n-1)+n { 869 panic(shortA) 870 } 871 872 // Quick return if possible. 873 if alpha == 0 { 874 return 875 } 876 877 var kx int 878 if incX < 0 { 879 kx = (1 - n) * incX 880 } 881 if uplo == blas.Upper { 882 if incX == 1 { 883 for i := 0; i < n; i++ { 884 if x[i] != 0 { 885 tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) 886 aii := real(a[i*lda+i]) 887 xtmp := real(tmp * cmplx.Conj(x[i])) 888 a[i*lda+i] = complex(aii+xtmp, 0) 889 for j := i + 1; j < n; j++ { 890 a[i*lda+j] += tmp * cmplx.Conj(x[j]) 891 } 892 } else { 893 aii := real(a[i*lda+i]) 894 a[i*lda+i] = complex(aii, 0) 895 } 896 } 897 return 898 } 899 900 ix := kx 901 for i := 0; i < n; i++ { 902 if x[ix] != 0 { 903 tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) 904 aii := real(a[i*lda+i]) 905 xtmp := real(tmp * cmplx.Conj(x[ix])) 906 a[i*lda+i] = complex(aii+xtmp, 0) 907 jx := ix + incX 908 for j := i + 1; j < n; j++ { 909 a[i*lda+j] += tmp * cmplx.Conj(x[jx]) 910 jx += incX 911 } 912 } else { 913 aii := real(a[i*lda+i]) 914 a[i*lda+i] = complex(aii, 0) 915 } 916 ix += incX 917 } 918 return 919 } 920 921 if incX == 1 { 922 for i := 0; i < n; i++ { 923 if x[i] != 0 { 924 tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) 925 for j := 0; j < i; j++ { 926 a[i*lda+j] += tmp * cmplx.Conj(x[j]) 927 } 928 aii := real(a[i*lda+i]) 929 xtmp := real(tmp * cmplx.Conj(x[i])) 930 a[i*lda+i] = complex(aii+xtmp, 0) 931 } else { 932 aii := real(a[i*lda+i]) 933 a[i*lda+i] = complex(aii, 0) 934 } 935 } 936 return 937 } 938 939 ix := kx 940 for i := 0; i < n; i++ { 941 if x[ix] != 0 { 942 tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) 943 jx := kx 944 for j := 0; j < i; j++ { 945 a[i*lda+j] += tmp * cmplx.Conj(x[jx]) 946 jx += incX 947 } 948 aii := real(a[i*lda+i]) 949 xtmp := real(tmp * cmplx.Conj(x[ix])) 950 a[i*lda+i] = complex(aii+xtmp, 0) 951 952 } else { 953 aii := real(a[i*lda+i]) 954 a[i*lda+i] = complex(aii, 0) 955 } 956 ix += incX 957 } 958 } 959 960 // Zher2 performs the Hermitian rank-two operation 961 // 962 // A += alpha * x * yᴴ + conj(alpha) * y * xᴴ 963 // 964 // where alpha is a scalar, x and y are n element vectors and A is an n×n 965 // Hermitian matrix. On entry, the imaginary parts of the diagonal elements are 966 // ignored and assumed to be zero. On return they will be set to zero. 967 func (Implementation) Zher2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { 968 switch uplo { 969 default: 970 panic(badUplo) 971 case blas.Upper, blas.Lower: 972 } 973 if n < 0 { 974 panic(nLT0) 975 } 976 if lda < max(1, n) { 977 panic(badLdA) 978 } 979 if incX == 0 { 980 panic(zeroIncX) 981 } 982 if incY == 0 { 983 panic(zeroIncY) 984 } 985 986 // Quick return if possible. 987 if n == 0 { 988 return 989 } 990 991 // For zero matrix size the following slice length checks are trivially satisfied. 992 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 993 panic(shortX) 994 } 995 if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { 996 panic(shortY) 997 } 998 if len(a) < lda*(n-1)+n { 999 panic(shortA) 1000 } 1001 1002 // Quick return if possible. 1003 if alpha == 0 { 1004 return 1005 } 1006 1007 var kx, ky int 1008 var ix, iy int 1009 if incX != 1 || incY != 1 { 1010 if incX < 0 { 1011 kx = (1 - n) * incX 1012 } 1013 if incY < 0 { 1014 ky = (1 - n) * incY 1015 } 1016 ix = kx 1017 iy = ky 1018 } 1019 if uplo == blas.Upper { 1020 if incX == 1 && incY == 1 { 1021 for i := 0; i < n; i++ { 1022 if x[i] != 0 || y[i] != 0 { 1023 tmp1 := alpha * x[i] 1024 tmp2 := cmplx.Conj(alpha) * y[i] 1025 aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) 1026 a[i*lda+i] = complex(aii, 0) 1027 for j := i + 1; j < n; j++ { 1028 a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) 1029 } 1030 } else { 1031 aii := real(a[i*lda+i]) 1032 a[i*lda+i] = complex(aii, 0) 1033 } 1034 } 1035 return 1036 } 1037 for i := 0; i < n; i++ { 1038 if x[ix] != 0 || y[iy] != 0 { 1039 tmp1 := alpha * x[ix] 1040 tmp2 := cmplx.Conj(alpha) * y[iy] 1041 aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) 1042 a[i*lda+i] = complex(aii, 0) 1043 jx := ix + incX 1044 jy := iy + incY 1045 for j := i + 1; j < n; j++ { 1046 a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) 1047 jx += incX 1048 jy += incY 1049 } 1050 } else { 1051 aii := real(a[i*lda+i]) 1052 a[i*lda+i] = complex(aii, 0) 1053 } 1054 ix += incX 1055 iy += incY 1056 } 1057 return 1058 } 1059 1060 if incX == 1 && incY == 1 { 1061 for i := 0; i < n; i++ { 1062 if x[i] != 0 || y[i] != 0 { 1063 tmp1 := alpha * x[i] 1064 tmp2 := cmplx.Conj(alpha) * y[i] 1065 for j := 0; j < i; j++ { 1066 a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) 1067 } 1068 aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) 1069 a[i*lda+i] = complex(aii, 0) 1070 } else { 1071 aii := real(a[i*lda+i]) 1072 a[i*lda+i] = complex(aii, 0) 1073 } 1074 } 1075 return 1076 } 1077 for i := 0; i < n; i++ { 1078 if x[ix] != 0 || y[iy] != 0 { 1079 tmp1 := alpha * x[ix] 1080 tmp2 := cmplx.Conj(alpha) * y[iy] 1081 jx := kx 1082 jy := ky 1083 for j := 0; j < i; j++ { 1084 a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) 1085 jx += incX 1086 jy += incY 1087 } 1088 aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) 1089 a[i*lda+i] = complex(aii, 0) 1090 } else { 1091 aii := real(a[i*lda+i]) 1092 a[i*lda+i] = complex(aii, 0) 1093 } 1094 ix += incX 1095 iy += incY 1096 } 1097 } 1098 1099 // Zhpmv performs the matrix-vector operation 1100 // 1101 // y = alpha * A * x + beta * y 1102 // 1103 // where alpha and beta are scalars, x and y are vectors, and A is an n×n 1104 // Hermitian matrix in packed form. The imaginary parts of the diagonal 1105 // elements of A are ignored and assumed to be zero. 1106 func (Implementation) Zhpmv(uplo blas.Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) { 1107 switch uplo { 1108 default: 1109 panic(badUplo) 1110 case blas.Upper, blas.Lower: 1111 } 1112 if n < 0 { 1113 panic(nLT0) 1114 } 1115 if incX == 0 { 1116 panic(zeroIncX) 1117 } 1118 if incY == 0 { 1119 panic(zeroIncY) 1120 } 1121 1122 // Quick return if possible. 1123 if n == 0 { 1124 return 1125 } 1126 1127 // For zero matrix size the following slice length checks are trivially satisfied. 1128 if len(ap) < n*(n+1)/2 { 1129 panic(shortAP) 1130 } 1131 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 1132 panic(shortX) 1133 } 1134 if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { 1135 panic(shortY) 1136 } 1137 1138 // Quick return if possible. 1139 if alpha == 0 && beta == 1 { 1140 return 1141 } 1142 1143 // Set up the start indices in X and Y. 1144 var kx int 1145 if incX < 0 { 1146 kx = (1 - n) * incX 1147 } 1148 var ky int 1149 if incY < 0 { 1150 ky = (1 - n) * incY 1151 } 1152 1153 // Form y = beta*y. 1154 if beta != 1 { 1155 if incY == 1 { 1156 if beta == 0 { 1157 for i := range y[:n] { 1158 y[i] = 0 1159 } 1160 } else { 1161 for i, v := range y[:n] { 1162 y[i] = beta * v 1163 } 1164 } 1165 } else { 1166 iy := ky 1167 if beta == 0 { 1168 for i := 0; i < n; i++ { 1169 y[iy] = 0 1170 iy += incY 1171 } 1172 } else { 1173 for i := 0; i < n; i++ { 1174 y[iy] *= beta 1175 iy += incY 1176 } 1177 } 1178 } 1179 } 1180 1181 if alpha == 0 { 1182 return 1183 } 1184 1185 // The elements of A are accessed sequentially with one pass through ap. 1186 1187 var kk int 1188 if uplo == blas.Upper { 1189 // Form y when ap contains the upper triangle. 1190 // Here, kk points to the current diagonal element in ap. 1191 if incX == 1 && incY == 1 { 1192 for i := 0; i < n; i++ { 1193 tmp1 := alpha * x[i] 1194 y[i] += tmp1 * complex(real(ap[kk]), 0) 1195 var tmp2 complex128 1196 k := kk + 1 1197 for j := i + 1; j < n; j++ { 1198 y[j] += tmp1 * cmplx.Conj(ap[k]) 1199 tmp2 += ap[k] * x[j] 1200 k++ 1201 } 1202 y[i] += alpha * tmp2 1203 kk += n - i 1204 } 1205 } else { 1206 ix := kx 1207 iy := ky 1208 for i := 0; i < n; i++ { 1209 tmp1 := alpha * x[ix] 1210 y[iy] += tmp1 * complex(real(ap[kk]), 0) 1211 var tmp2 complex128 1212 jx := ix 1213 jy := iy 1214 for k := kk + 1; k < kk+n-i; k++ { 1215 jx += incX 1216 jy += incY 1217 y[jy] += tmp1 * cmplx.Conj(ap[k]) 1218 tmp2 += ap[k] * x[jx] 1219 } 1220 y[iy] += alpha * tmp2 1221 ix += incX 1222 iy += incY 1223 kk += n - i 1224 } 1225 } 1226 return 1227 } 1228 1229 // Form y when ap contains the lower triangle. 1230 // Here, kk points to the beginning of current row in ap. 1231 if incX == 1 && incY == 1 { 1232 for i := 0; i < n; i++ { 1233 tmp1 := alpha * x[i] 1234 var tmp2 complex128 1235 k := kk 1236 for j := 0; j < i; j++ { 1237 y[j] += tmp1 * cmplx.Conj(ap[k]) 1238 tmp2 += ap[k] * x[j] 1239 k++ 1240 } 1241 aii := complex(real(ap[kk+i]), 0) 1242 y[i] += tmp1*aii + alpha*tmp2 1243 kk += i + 1 1244 } 1245 } else { 1246 ix := kx 1247 iy := ky 1248 for i := 0; i < n; i++ { 1249 tmp1 := alpha * x[ix] 1250 var tmp2 complex128 1251 jx := kx 1252 jy := ky 1253 for k := kk; k < kk+i; k++ { 1254 y[jy] += tmp1 * cmplx.Conj(ap[k]) 1255 tmp2 += ap[k] * x[jx] 1256 jx += incX 1257 jy += incY 1258 } 1259 aii := complex(real(ap[kk+i]), 0) 1260 y[iy] += tmp1*aii + alpha*tmp2 1261 ix += incX 1262 iy += incY 1263 kk += i + 1 1264 } 1265 } 1266 } 1267 1268 // Zhpr performs the Hermitian rank-1 operation 1269 // 1270 // A += alpha * x * xᴴ 1271 // 1272 // where alpha is a real scalar, x is a vector, and A is an n×n hermitian matrix 1273 // in packed form. On entry, the imaginary parts of the diagonal elements are 1274 // assumed to be zero, and on return they are set to zero. 1275 func (Implementation) Zhpr(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, ap []complex128) { 1276 switch uplo { 1277 default: 1278 panic(badUplo) 1279 case blas.Upper, blas.Lower: 1280 } 1281 if n < 0 { 1282 panic(nLT0) 1283 } 1284 if incX == 0 { 1285 panic(zeroIncX) 1286 } 1287 1288 // Quick return if possible. 1289 if n == 0 { 1290 return 1291 } 1292 1293 // For zero matrix size the following slice length checks are trivially satisfied. 1294 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 1295 panic(shortX) 1296 } 1297 if len(ap) < n*(n+1)/2 { 1298 panic(shortAP) 1299 } 1300 1301 // Quick return if possible. 1302 if alpha == 0 { 1303 return 1304 } 1305 1306 // Set up start index in X. 1307 var kx int 1308 if incX < 0 { 1309 kx = (1 - n) * incX 1310 } 1311 1312 // The elements of A are accessed sequentially with one pass through ap. 1313 1314 var kk int 1315 if uplo == blas.Upper { 1316 // Form A when upper triangle is stored in AP. 1317 // Here, kk points to the current diagonal element in ap. 1318 if incX == 1 { 1319 for i := 0; i < n; i++ { 1320 xi := x[i] 1321 if xi != 0 { 1322 aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) 1323 ap[kk] = complex(aii, 0) 1324 1325 tmp := complex(alpha, 0) * xi 1326 a := ap[kk+1 : kk+n-i] 1327 x := x[i+1 : n] 1328 for j, v := range x { 1329 a[j] += tmp * cmplx.Conj(v) 1330 } 1331 } else { 1332 ap[kk] = complex(real(ap[kk]), 0) 1333 } 1334 kk += n - i 1335 } 1336 } else { 1337 ix := kx 1338 for i := 0; i < n; i++ { 1339 xi := x[ix] 1340 if xi != 0 { 1341 aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) 1342 ap[kk] = complex(aii, 0) 1343 1344 tmp := complex(alpha, 0) * xi 1345 jx := ix + incX 1346 a := ap[kk+1 : kk+n-i] 1347 for k := range a { 1348 a[k] += tmp * cmplx.Conj(x[jx]) 1349 jx += incX 1350 } 1351 } else { 1352 ap[kk] = complex(real(ap[kk]), 0) 1353 } 1354 ix += incX 1355 kk += n - i 1356 } 1357 } 1358 return 1359 } 1360 1361 // Form A when lower triangle is stored in AP. 1362 // Here, kk points to the beginning of current row in ap. 1363 if incX == 1 { 1364 for i := 0; i < n; i++ { 1365 xi := x[i] 1366 if xi != 0 { 1367 tmp := complex(alpha, 0) * xi 1368 a := ap[kk : kk+i] 1369 for j, v := range x[:i] { 1370 a[j] += tmp * cmplx.Conj(v) 1371 } 1372 1373 aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) 1374 ap[kk+i] = complex(aii, 0) 1375 } else { 1376 ap[kk+i] = complex(real(ap[kk+i]), 0) 1377 } 1378 kk += i + 1 1379 } 1380 } else { 1381 ix := kx 1382 for i := 0; i < n; i++ { 1383 xi := x[ix] 1384 if xi != 0 { 1385 tmp := complex(alpha, 0) * xi 1386 a := ap[kk : kk+i] 1387 jx := kx 1388 for k := range a { 1389 a[k] += tmp * cmplx.Conj(x[jx]) 1390 jx += incX 1391 } 1392 1393 aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) 1394 ap[kk+i] = complex(aii, 0) 1395 } else { 1396 ap[kk+i] = complex(real(ap[kk+i]), 0) 1397 } 1398 ix += incX 1399 kk += i + 1 1400 } 1401 } 1402 } 1403 1404 // Zhpr2 performs the Hermitian rank-2 operation 1405 // 1406 // A += alpha * x * yᴴ + conj(alpha) * y * xᴴ 1407 // 1408 // where alpha is a complex scalar, x and y are n element vectors, and A is an 1409 // n×n Hermitian matrix, supplied in packed form. On entry, the imaginary parts 1410 // of the diagonal elements are assumed to be zero, and on return they are set to zero. 1411 func (Implementation) Zhpr2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) { 1412 switch uplo { 1413 default: 1414 panic(badUplo) 1415 case blas.Upper, blas.Lower: 1416 } 1417 if n < 0 { 1418 panic(nLT0) 1419 } 1420 if incX == 0 { 1421 panic(zeroIncX) 1422 } 1423 if incY == 0 { 1424 panic(zeroIncY) 1425 } 1426 1427 // Quick return if possible. 1428 if n == 0 { 1429 return 1430 } 1431 1432 // For zero matrix size the following slice length checks are trivially satisfied. 1433 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 1434 panic(shortX) 1435 } 1436 if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { 1437 panic(shortY) 1438 } 1439 if len(ap) < n*(n+1)/2 { 1440 panic(shortAP) 1441 } 1442 1443 // Quick return if possible. 1444 if alpha == 0 { 1445 return 1446 } 1447 1448 // Set up start indices in X and Y. 1449 var kx int 1450 if incX < 0 { 1451 kx = (1 - n) * incX 1452 } 1453 var ky int 1454 if incY < 0 { 1455 ky = (1 - n) * incY 1456 } 1457 1458 // The elements of A are accessed sequentially with one pass through ap. 1459 1460 var kk int 1461 if uplo == blas.Upper { 1462 // Form A when upper triangle is stored in AP. 1463 // Here, kk points to the current diagonal element in ap. 1464 if incX == 1 && incY == 1 { 1465 for i := 0; i < n; i++ { 1466 if x[i] != 0 || y[i] != 0 { 1467 tmp1 := alpha * x[i] 1468 tmp2 := cmplx.Conj(alpha) * y[i] 1469 aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) 1470 ap[kk] = complex(aii, 0) 1471 k := kk + 1 1472 for j := i + 1; j < n; j++ { 1473 ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) 1474 k++ 1475 } 1476 } else { 1477 ap[kk] = complex(real(ap[kk]), 0) 1478 } 1479 kk += n - i 1480 } 1481 } else { 1482 ix := kx 1483 iy := ky 1484 for i := 0; i < n; i++ { 1485 if x[ix] != 0 || y[iy] != 0 { 1486 tmp1 := alpha * x[ix] 1487 tmp2 := cmplx.Conj(alpha) * y[iy] 1488 aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) 1489 ap[kk] = complex(aii, 0) 1490 jx := ix + incX 1491 jy := iy + incY 1492 for k := kk + 1; k < kk+n-i; k++ { 1493 ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) 1494 jx += incX 1495 jy += incY 1496 } 1497 } else { 1498 ap[kk] = complex(real(ap[kk]), 0) 1499 } 1500 ix += incX 1501 iy += incY 1502 kk += n - i 1503 } 1504 } 1505 return 1506 } 1507 1508 // Form A when lower triangle is stored in AP. 1509 // Here, kk points to the beginning of current row in ap. 1510 if incX == 1 && incY == 1 { 1511 for i := 0; i < n; i++ { 1512 if x[i] != 0 || y[i] != 0 { 1513 tmp1 := alpha * x[i] 1514 tmp2 := cmplx.Conj(alpha) * y[i] 1515 k := kk 1516 for j := 0; j < i; j++ { 1517 ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) 1518 k++ 1519 } 1520 aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) 1521 ap[kk+i] = complex(aii, 0) 1522 } else { 1523 ap[kk+i] = complex(real(ap[kk+i]), 0) 1524 } 1525 kk += i + 1 1526 } 1527 } else { 1528 ix := kx 1529 iy := ky 1530 for i := 0; i < n; i++ { 1531 if x[ix] != 0 || y[iy] != 0 { 1532 tmp1 := alpha * x[ix] 1533 tmp2 := cmplx.Conj(alpha) * y[iy] 1534 jx := kx 1535 jy := ky 1536 for k := kk; k < kk+i; k++ { 1537 ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) 1538 jx += incX 1539 jy += incY 1540 } 1541 aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) 1542 ap[kk+i] = complex(aii, 0) 1543 } else { 1544 ap[kk+i] = complex(real(ap[kk+i]), 0) 1545 } 1546 ix += incX 1547 iy += incY 1548 kk += i + 1 1549 } 1550 } 1551 } 1552 1553 // Ztbmv performs one of the matrix-vector operations 1554 // 1555 // x = A * x if trans = blas.NoTrans 1556 // x = Aᵀ * x if trans = blas.Trans 1557 // x = Aᴴ * x if trans = blas.ConjTrans 1558 // 1559 // where x is an n element vector and A is an n×n triangular band matrix, with 1560 // (k+1) diagonals. 1561 func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { 1562 switch trans { 1563 default: 1564 panic(badTranspose) 1565 case blas.NoTrans, blas.Trans, blas.ConjTrans: 1566 } 1567 switch uplo { 1568 default: 1569 panic(badUplo) 1570 case blas.Upper, blas.Lower: 1571 } 1572 switch diag { 1573 default: 1574 panic(badDiag) 1575 case blas.NonUnit, blas.Unit: 1576 } 1577 if n < 0 { 1578 panic(nLT0) 1579 } 1580 if k < 0 { 1581 panic(kLT0) 1582 } 1583 if lda < k+1 { 1584 panic(badLdA) 1585 } 1586 if incX == 0 { 1587 panic(zeroIncX) 1588 } 1589 1590 // Quick return if possible. 1591 if n == 0 { 1592 return 1593 } 1594 1595 // For zero matrix size the following slice length checks are trivially satisfied. 1596 if len(a) < lda*(n-1)+k+1 { 1597 panic(shortA) 1598 } 1599 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 1600 panic(shortX) 1601 } 1602 1603 // Set up start index in X. 1604 var kx int 1605 if incX < 0 { 1606 kx = (1 - n) * incX 1607 } 1608 1609 switch trans { 1610 case blas.NoTrans: 1611 if uplo == blas.Upper { 1612 if incX == 1 { 1613 for i := 0; i < n; i++ { 1614 xi := x[i] 1615 if diag == blas.NonUnit { 1616 xi *= a[i*lda] 1617 } 1618 kk := min(k, n-i-1) 1619 for j, aij := range a[i*lda+1 : i*lda+kk+1] { 1620 xi += x[i+j+1] * aij 1621 } 1622 x[i] = xi 1623 } 1624 } else { 1625 ix := kx 1626 for i := 0; i < n; i++ { 1627 xi := x[ix] 1628 if diag == blas.NonUnit { 1629 xi *= a[i*lda] 1630 } 1631 kk := min(k, n-i-1) 1632 jx := ix + incX 1633 for _, aij := range a[i*lda+1 : i*lda+kk+1] { 1634 xi += x[jx] * aij 1635 jx += incX 1636 } 1637 x[ix] = xi 1638 ix += incX 1639 } 1640 } 1641 } else { 1642 if incX == 1 { 1643 for i := n - 1; i >= 0; i-- { 1644 xi := x[i] 1645 if diag == blas.NonUnit { 1646 xi *= a[i*lda+k] 1647 } 1648 kk := min(k, i) 1649 for j, aij := range a[i*lda+k-kk : i*lda+k] { 1650 xi += x[i-kk+j] * aij 1651 } 1652 x[i] = xi 1653 } 1654 } else { 1655 ix := kx + (n-1)*incX 1656 for i := n - 1; i >= 0; i-- { 1657 xi := x[ix] 1658 if diag == blas.NonUnit { 1659 xi *= a[i*lda+k] 1660 } 1661 kk := min(k, i) 1662 jx := ix - kk*incX 1663 for _, aij := range a[i*lda+k-kk : i*lda+k] { 1664 xi += x[jx] * aij 1665 jx += incX 1666 } 1667 x[ix] = xi 1668 ix -= incX 1669 } 1670 } 1671 } 1672 case blas.Trans: 1673 if uplo == blas.Upper { 1674 if incX == 1 { 1675 for i := n - 1; i >= 0; i-- { 1676 kk := min(k, n-i-1) 1677 xi := x[i] 1678 for j, aij := range a[i*lda+1 : i*lda+kk+1] { 1679 x[i+j+1] += xi * aij 1680 } 1681 if diag == blas.NonUnit { 1682 x[i] *= a[i*lda] 1683 } 1684 } 1685 } else { 1686 ix := kx + (n-1)*incX 1687 for i := n - 1; i >= 0; i-- { 1688 kk := min(k, n-i-1) 1689 jx := ix + incX 1690 xi := x[ix] 1691 for _, aij := range a[i*lda+1 : i*lda+kk+1] { 1692 x[jx] += xi * aij 1693 jx += incX 1694 } 1695 if diag == blas.NonUnit { 1696 x[ix] *= a[i*lda] 1697 } 1698 ix -= incX 1699 } 1700 } 1701 } else { 1702 if incX == 1 { 1703 for i := 0; i < n; i++ { 1704 kk := min(k, i) 1705 xi := x[i] 1706 for j, aij := range a[i*lda+k-kk : i*lda+k] { 1707 x[i-kk+j] += xi * aij 1708 } 1709 if diag == blas.NonUnit { 1710 x[i] *= a[i*lda+k] 1711 } 1712 } 1713 } else { 1714 ix := kx 1715 for i := 0; i < n; i++ { 1716 kk := min(k, i) 1717 jx := ix - kk*incX 1718 xi := x[ix] 1719 for _, aij := range a[i*lda+k-kk : i*lda+k] { 1720 x[jx] += xi * aij 1721 jx += incX 1722 } 1723 if diag == blas.NonUnit { 1724 x[ix] *= a[i*lda+k] 1725 } 1726 ix += incX 1727 } 1728 } 1729 } 1730 case blas.ConjTrans: 1731 if uplo == blas.Upper { 1732 if incX == 1 { 1733 for i := n - 1; i >= 0; i-- { 1734 kk := min(k, n-i-1) 1735 xi := x[i] 1736 for j, aij := range a[i*lda+1 : i*lda+kk+1] { 1737 x[i+j+1] += xi * cmplx.Conj(aij) 1738 } 1739 if diag == blas.NonUnit { 1740 x[i] *= cmplx.Conj(a[i*lda]) 1741 } 1742 } 1743 } else { 1744 ix := kx + (n-1)*incX 1745 for i := n - 1; i >= 0; i-- { 1746 kk := min(k, n-i-1) 1747 jx := ix + incX 1748 xi := x[ix] 1749 for _, aij := range a[i*lda+1 : i*lda+kk+1] { 1750 x[jx] += xi * cmplx.Conj(aij) 1751 jx += incX 1752 } 1753 if diag == blas.NonUnit { 1754 x[ix] *= cmplx.Conj(a[i*lda]) 1755 } 1756 ix -= incX 1757 } 1758 } 1759 } else { 1760 if incX == 1 { 1761 for i := 0; i < n; i++ { 1762 kk := min(k, i) 1763 xi := x[i] 1764 for j, aij := range a[i*lda+k-kk : i*lda+k] { 1765 x[i-kk+j] += xi * cmplx.Conj(aij) 1766 } 1767 if diag == blas.NonUnit { 1768 x[i] *= cmplx.Conj(a[i*lda+k]) 1769 } 1770 } 1771 } else { 1772 ix := kx 1773 for i := 0; i < n; i++ { 1774 kk := min(k, i) 1775 jx := ix - kk*incX 1776 xi := x[ix] 1777 for _, aij := range a[i*lda+k-kk : i*lda+k] { 1778 x[jx] += xi * cmplx.Conj(aij) 1779 jx += incX 1780 } 1781 if diag == blas.NonUnit { 1782 x[ix] *= cmplx.Conj(a[i*lda+k]) 1783 } 1784 ix += incX 1785 } 1786 } 1787 } 1788 } 1789 } 1790 1791 // Ztbsv solves one of the systems of equations 1792 // 1793 // A * x = b if trans == blas.NoTrans 1794 // Aᵀ * x = b if trans == blas.Trans 1795 // Aᴴ * x = b if trans == blas.ConjTrans 1796 // 1797 // where b and x are n element vectors and A is an n×n triangular band matrix 1798 // with (k+1) diagonals. 1799 // 1800 // On entry, x contains the values of b, and the solution is 1801 // stored in-place into x. 1802 // 1803 // No test for singularity or near-singularity is included in this 1804 // routine. Such tests must be performed before calling this routine. 1805 func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { 1806 switch trans { 1807 default: 1808 panic(badTranspose) 1809 case blas.NoTrans, blas.Trans, blas.ConjTrans: 1810 } 1811 switch uplo { 1812 default: 1813 panic(badUplo) 1814 case blas.Upper, blas.Lower: 1815 } 1816 switch diag { 1817 default: 1818 panic(badDiag) 1819 case blas.NonUnit, blas.Unit: 1820 } 1821 if n < 0 { 1822 panic(nLT0) 1823 } 1824 if k < 0 { 1825 panic(kLT0) 1826 } 1827 if lda < k+1 { 1828 panic(badLdA) 1829 } 1830 if incX == 0 { 1831 panic(zeroIncX) 1832 } 1833 1834 // Quick return if possible. 1835 if n == 0 { 1836 return 1837 } 1838 1839 // For zero matrix size the following slice length checks are trivially satisfied. 1840 if len(a) < lda*(n-1)+k+1 { 1841 panic(shortA) 1842 } 1843 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 1844 panic(shortX) 1845 } 1846 1847 // Set up start index in X. 1848 var kx int 1849 if incX < 0 { 1850 kx = (1 - n) * incX 1851 } 1852 1853 switch trans { 1854 case blas.NoTrans: 1855 if uplo == blas.Upper { 1856 if incX == 1 { 1857 for i := n - 1; i >= 0; i-- { 1858 kk := min(k, n-i-1) 1859 var sum complex128 1860 for j, aij := range a[i*lda+1 : i*lda+kk+1] { 1861 sum += x[i+1+j] * aij 1862 } 1863 x[i] -= sum 1864 if diag == blas.NonUnit { 1865 x[i] /= a[i*lda] 1866 } 1867 } 1868 } else { 1869 ix := kx + (n-1)*incX 1870 for i := n - 1; i >= 0; i-- { 1871 kk := min(k, n-i-1) 1872 var sum complex128 1873 jx := ix + incX 1874 for _, aij := range a[i*lda+1 : i*lda+kk+1] { 1875 sum += x[jx] * aij 1876 jx += incX 1877 } 1878 x[ix] -= sum 1879 if diag == blas.NonUnit { 1880 x[ix] /= a[i*lda] 1881 } 1882 ix -= incX 1883 } 1884 } 1885 } else { 1886 if incX == 1 { 1887 for i := 0; i < n; i++ { 1888 kk := min(k, i) 1889 var sum complex128 1890 for j, aij := range a[i*lda+k-kk : i*lda+k] { 1891 sum += x[i-kk+j] * aij 1892 } 1893 x[i] -= sum 1894 if diag == blas.NonUnit { 1895 x[i] /= a[i*lda+k] 1896 } 1897 } 1898 } else { 1899 ix := kx 1900 for i := 0; i < n; i++ { 1901 kk := min(k, i) 1902 var sum complex128 1903 jx := ix - kk*incX 1904 for _, aij := range a[i*lda+k-kk : i*lda+k] { 1905 sum += x[jx] * aij 1906 jx += incX 1907 } 1908 x[ix] -= sum 1909 if diag == blas.NonUnit { 1910 x[ix] /= a[i*lda+k] 1911 } 1912 ix += incX 1913 } 1914 } 1915 } 1916 case blas.Trans: 1917 if uplo == blas.Upper { 1918 if incX == 1 { 1919 for i := 0; i < n; i++ { 1920 if diag == blas.NonUnit { 1921 x[i] /= a[i*lda] 1922 } 1923 kk := min(k, n-i-1) 1924 xi := x[i] 1925 for j, aij := range a[i*lda+1 : i*lda+kk+1] { 1926 x[i+1+j] -= xi * aij 1927 } 1928 } 1929 } else { 1930 ix := kx 1931 for i := 0; i < n; i++ { 1932 if diag == blas.NonUnit { 1933 x[ix] /= a[i*lda] 1934 } 1935 kk := min(k, n-i-1) 1936 xi := x[ix] 1937 jx := ix + incX 1938 for _, aij := range a[i*lda+1 : i*lda+kk+1] { 1939 x[jx] -= xi * aij 1940 jx += incX 1941 } 1942 ix += incX 1943 } 1944 } 1945 } else { 1946 if incX == 1 { 1947 for i := n - 1; i >= 0; i-- { 1948 if diag == blas.NonUnit { 1949 x[i] /= a[i*lda+k] 1950 } 1951 kk := min(k, i) 1952 xi := x[i] 1953 for j, aij := range a[i*lda+k-kk : i*lda+k] { 1954 x[i-kk+j] -= xi * aij 1955 } 1956 } 1957 } else { 1958 ix := kx + (n-1)*incX 1959 for i := n - 1; i >= 0; i-- { 1960 if diag == blas.NonUnit { 1961 x[ix] /= a[i*lda+k] 1962 } 1963 kk := min(k, i) 1964 xi := x[ix] 1965 jx := ix - kk*incX 1966 for _, aij := range a[i*lda+k-kk : i*lda+k] { 1967 x[jx] -= xi * aij 1968 jx += incX 1969 } 1970 ix -= incX 1971 } 1972 } 1973 } 1974 case blas.ConjTrans: 1975 if uplo == blas.Upper { 1976 if incX == 1 { 1977 for i := 0; i < n; i++ { 1978 if diag == blas.NonUnit { 1979 x[i] /= cmplx.Conj(a[i*lda]) 1980 } 1981 kk := min(k, n-i-1) 1982 xi := x[i] 1983 for j, aij := range a[i*lda+1 : i*lda+kk+1] { 1984 x[i+1+j] -= xi * cmplx.Conj(aij) 1985 } 1986 } 1987 } else { 1988 ix := kx 1989 for i := 0; i < n; i++ { 1990 if diag == blas.NonUnit { 1991 x[ix] /= cmplx.Conj(a[i*lda]) 1992 } 1993 kk := min(k, n-i-1) 1994 xi := x[ix] 1995 jx := ix + incX 1996 for _, aij := range a[i*lda+1 : i*lda+kk+1] { 1997 x[jx] -= xi * cmplx.Conj(aij) 1998 jx += incX 1999 } 2000 ix += incX 2001 } 2002 } 2003 } else { 2004 if incX == 1 { 2005 for i := n - 1; i >= 0; i-- { 2006 if diag == blas.NonUnit { 2007 x[i] /= cmplx.Conj(a[i*lda+k]) 2008 } 2009 kk := min(k, i) 2010 xi := x[i] 2011 for j, aij := range a[i*lda+k-kk : i*lda+k] { 2012 x[i-kk+j] -= xi * cmplx.Conj(aij) 2013 } 2014 } 2015 } else { 2016 ix := kx + (n-1)*incX 2017 for i := n - 1; i >= 0; i-- { 2018 if diag == blas.NonUnit { 2019 x[ix] /= cmplx.Conj(a[i*lda+k]) 2020 } 2021 kk := min(k, i) 2022 xi := x[ix] 2023 jx := ix - kk*incX 2024 for _, aij := range a[i*lda+k-kk : i*lda+k] { 2025 x[jx] -= xi * cmplx.Conj(aij) 2026 jx += incX 2027 } 2028 ix -= incX 2029 } 2030 } 2031 } 2032 } 2033 } 2034 2035 // Ztpmv performs one of the matrix-vector operations 2036 // 2037 // x = A * x if trans = blas.NoTrans 2038 // x = Aᵀ * x if trans = blas.Trans 2039 // x = Aᴴ * x if trans = blas.ConjTrans 2040 // 2041 // where x is an n element vector and A is an n×n triangular matrix, supplied in 2042 // packed form. 2043 func (Implementation) Ztpmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex128, x []complex128, incX int) { 2044 switch uplo { 2045 default: 2046 panic(badUplo) 2047 case blas.Upper, blas.Lower: 2048 } 2049 switch trans { 2050 default: 2051 panic(badTranspose) 2052 case blas.NoTrans, blas.Trans, blas.ConjTrans: 2053 } 2054 switch diag { 2055 default: 2056 panic(badDiag) 2057 case blas.NonUnit, blas.Unit: 2058 } 2059 if n < 0 { 2060 panic(nLT0) 2061 } 2062 if incX == 0 { 2063 panic(zeroIncX) 2064 } 2065 2066 // Quick return if possible. 2067 if n == 0 { 2068 return 2069 } 2070 2071 // For zero matrix size the following slice length checks are trivially satisfied. 2072 if len(ap) < n*(n+1)/2 { 2073 panic(shortAP) 2074 } 2075 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 2076 panic(shortX) 2077 } 2078 2079 // Set up start index in X. 2080 var kx int 2081 if incX < 0 { 2082 kx = (1 - n) * incX 2083 } 2084 2085 // The elements of A are accessed sequentially with one pass through A. 2086 2087 if trans == blas.NoTrans { 2088 // Form x = A*x. 2089 if uplo == blas.Upper { 2090 // kk points to the current diagonal element in ap. 2091 kk := 0 2092 if incX == 1 { 2093 x = x[:n] 2094 for i := range x { 2095 if diag == blas.NonUnit { 2096 x[i] *= ap[kk] 2097 } 2098 if n-i-1 > 0 { 2099 x[i] += c128.DotuUnitary(ap[kk+1:kk+n-i], x[i+1:]) 2100 } 2101 kk += n - i 2102 } 2103 } else { 2104 ix := kx 2105 for i := 0; i < n; i++ { 2106 if diag == blas.NonUnit { 2107 x[ix] *= ap[kk] 2108 } 2109 if n-i-1 > 0 { 2110 x[ix] += c128.DotuInc(ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) 2111 } 2112 ix += incX 2113 kk += n - i 2114 } 2115 } 2116 } else { 2117 // kk points to the beginning of current row in ap. 2118 kk := n*(n+1)/2 - n 2119 if incX == 1 { 2120 for i := n - 1; i >= 0; i-- { 2121 if diag == blas.NonUnit { 2122 x[i] *= ap[kk+i] 2123 } 2124 if i > 0 { 2125 x[i] += c128.DotuUnitary(ap[kk:kk+i], x[:i]) 2126 } 2127 kk -= i 2128 } 2129 } else { 2130 ix := kx + (n-1)*incX 2131 for i := n - 1; i >= 0; i-- { 2132 if diag == blas.NonUnit { 2133 x[ix] *= ap[kk+i] 2134 } 2135 if i > 0 { 2136 x[ix] += c128.DotuInc(ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) 2137 } 2138 ix -= incX 2139 kk -= i 2140 } 2141 } 2142 } 2143 return 2144 } 2145 2146 if trans == blas.Trans { 2147 // Form x = Aᵀ*x. 2148 if uplo == blas.Upper { 2149 // kk points to the current diagonal element in ap. 2150 kk := n*(n+1)/2 - 1 2151 if incX == 1 { 2152 for i := n - 1; i >= 0; i-- { 2153 xi := x[i] 2154 if diag == blas.NonUnit { 2155 x[i] *= ap[kk] 2156 } 2157 if n-i-1 > 0 { 2158 c128.AxpyUnitary(xi, ap[kk+1:kk+n-i], x[i+1:n]) 2159 } 2160 kk -= n - i + 1 2161 } 2162 } else { 2163 ix := kx + (n-1)*incX 2164 for i := n - 1; i >= 0; i-- { 2165 xi := x[ix] 2166 if diag == blas.NonUnit { 2167 x[ix] *= ap[kk] 2168 } 2169 if n-i-1 > 0 { 2170 c128.AxpyInc(xi, ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) 2171 } 2172 ix -= incX 2173 kk -= n - i + 1 2174 } 2175 } 2176 } else { 2177 // kk points to the beginning of current row in ap. 2178 kk := 0 2179 if incX == 1 { 2180 x = x[:n] 2181 for i := range x { 2182 if i > 0 { 2183 c128.AxpyUnitary(x[i], ap[kk:kk+i], x[:i]) 2184 } 2185 if diag == blas.NonUnit { 2186 x[i] *= ap[kk+i] 2187 } 2188 kk += i + 1 2189 } 2190 } else { 2191 ix := kx 2192 for i := 0; i < n; i++ { 2193 if i > 0 { 2194 c128.AxpyInc(x[ix], ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) 2195 } 2196 if diag == blas.NonUnit { 2197 x[ix] *= ap[kk+i] 2198 } 2199 ix += incX 2200 kk += i + 1 2201 } 2202 } 2203 } 2204 return 2205 } 2206 2207 // Form x = Aᴴ*x. 2208 if uplo == blas.Upper { 2209 // kk points to the current diagonal element in ap. 2210 kk := n*(n+1)/2 - 1 2211 if incX == 1 { 2212 for i := n - 1; i >= 0; i-- { 2213 xi := x[i] 2214 if diag == blas.NonUnit { 2215 x[i] *= cmplx.Conj(ap[kk]) 2216 } 2217 k := kk + 1 2218 for j := i + 1; j < n; j++ { 2219 x[j] += xi * cmplx.Conj(ap[k]) 2220 k++ 2221 } 2222 kk -= n - i + 1 2223 } 2224 } else { 2225 ix := kx + (n-1)*incX 2226 for i := n - 1; i >= 0; i-- { 2227 xi := x[ix] 2228 if diag == blas.NonUnit { 2229 x[ix] *= cmplx.Conj(ap[kk]) 2230 } 2231 jx := ix + incX 2232 k := kk + 1 2233 for j := i + 1; j < n; j++ { 2234 x[jx] += xi * cmplx.Conj(ap[k]) 2235 jx += incX 2236 k++ 2237 } 2238 ix -= incX 2239 kk -= n - i + 1 2240 } 2241 } 2242 } else { 2243 // kk points to the beginning of current row in ap. 2244 kk := 0 2245 if incX == 1 { 2246 x = x[:n] 2247 for i, xi := range x { 2248 for j := 0; j < i; j++ { 2249 x[j] += xi * cmplx.Conj(ap[kk+j]) 2250 } 2251 if diag == blas.NonUnit { 2252 x[i] *= cmplx.Conj(ap[kk+i]) 2253 } 2254 kk += i + 1 2255 } 2256 } else { 2257 ix := kx 2258 for i := 0; i < n; i++ { 2259 xi := x[ix] 2260 jx := kx 2261 for j := 0; j < i; j++ { 2262 x[jx] += xi * cmplx.Conj(ap[kk+j]) 2263 jx += incX 2264 } 2265 if diag == blas.NonUnit { 2266 x[ix] *= cmplx.Conj(ap[kk+i]) 2267 } 2268 ix += incX 2269 kk += i + 1 2270 } 2271 } 2272 } 2273 } 2274 2275 // Ztpsv solves one of the systems of equations 2276 // 2277 // A * x = b if trans == blas.NoTrans 2278 // Aᵀ * x = b if trans == blas.Trans 2279 // Aᴴ * x = b if trans == blas.ConjTrans 2280 // 2281 // where b and x are n element vectors and A is an n×n triangular matrix in 2282 // packed form. 2283 // 2284 // On entry, x contains the values of b, and the solution is 2285 // stored in-place into x. 2286 // 2287 // No test for singularity or near-singularity is included in this 2288 // routine. Such tests must be performed before calling this routine. 2289 func (Implementation) Ztpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex128, x []complex128, incX int) { 2290 switch uplo { 2291 default: 2292 panic(badUplo) 2293 case blas.Upper, blas.Lower: 2294 } 2295 switch trans { 2296 default: 2297 panic(badTranspose) 2298 case blas.NoTrans, blas.Trans, blas.ConjTrans: 2299 } 2300 switch diag { 2301 default: 2302 panic(badDiag) 2303 case blas.NonUnit, blas.Unit: 2304 } 2305 if n < 0 { 2306 panic(nLT0) 2307 } 2308 if incX == 0 { 2309 panic(zeroIncX) 2310 } 2311 2312 // Quick return if possible. 2313 if n == 0 { 2314 return 2315 } 2316 2317 // For zero matrix size the following slice length checks are trivially satisfied. 2318 if len(ap) < n*(n+1)/2 { 2319 panic(shortAP) 2320 } 2321 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 2322 panic(shortX) 2323 } 2324 2325 // Set up start index in X. 2326 var kx int 2327 if incX < 0 { 2328 kx = (1 - n) * incX 2329 } 2330 2331 // The elements of A are accessed sequentially with one pass through ap. 2332 2333 if trans == blas.NoTrans { 2334 // Form x = inv(A)*x. 2335 if uplo == blas.Upper { 2336 kk := n*(n+1)/2 - 1 2337 if incX == 1 { 2338 for i := n - 1; i >= 0; i-- { 2339 aii := ap[kk] 2340 if n-i-1 > 0 { 2341 x[i] -= c128.DotuUnitary(x[i+1:n], ap[kk+1:kk+n-i]) 2342 } 2343 if diag == blas.NonUnit { 2344 x[i] /= aii 2345 } 2346 kk -= n - i + 1 2347 } 2348 } else { 2349 ix := kx + (n-1)*incX 2350 for i := n - 1; i >= 0; i-- { 2351 aii := ap[kk] 2352 if n-i-1 > 0 { 2353 x[ix] -= c128.DotuInc(x, ap[kk+1:kk+n-i], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) 2354 } 2355 if diag == blas.NonUnit { 2356 x[ix] /= aii 2357 } 2358 ix -= incX 2359 kk -= n - i + 1 2360 } 2361 } 2362 } else { 2363 kk := 0 2364 if incX == 1 { 2365 for i := 0; i < n; i++ { 2366 if i > 0 { 2367 x[i] -= c128.DotuUnitary(x[:i], ap[kk:kk+i]) 2368 } 2369 if diag == blas.NonUnit { 2370 x[i] /= ap[kk+i] 2371 } 2372 kk += i + 1 2373 } 2374 } else { 2375 ix := kx 2376 for i := 0; i < n; i++ { 2377 if i > 0 { 2378 x[ix] -= c128.DotuInc(x, ap[kk:kk+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) 2379 } 2380 if diag == blas.NonUnit { 2381 x[ix] /= ap[kk+i] 2382 } 2383 ix += incX 2384 kk += i + 1 2385 } 2386 } 2387 } 2388 return 2389 } 2390 2391 if trans == blas.Trans { 2392 // Form x = inv(Aᵀ)*x. 2393 if uplo == blas.Upper { 2394 kk := 0 2395 if incX == 1 { 2396 for j := 0; j < n; j++ { 2397 if diag == blas.NonUnit { 2398 x[j] /= ap[kk] 2399 } 2400 if n-j-1 > 0 { 2401 c128.AxpyUnitary(-x[j], ap[kk+1:kk+n-j], x[j+1:n]) 2402 } 2403 kk += n - j 2404 } 2405 } else { 2406 jx := kx 2407 for j := 0; j < n; j++ { 2408 if diag == blas.NonUnit { 2409 x[jx] /= ap[kk] 2410 } 2411 if n-j-1 > 0 { 2412 c128.AxpyInc(-x[jx], ap[kk+1:kk+n-j], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) 2413 } 2414 jx += incX 2415 kk += n - j 2416 } 2417 } 2418 } else { 2419 kk := n*(n+1)/2 - n 2420 if incX == 1 { 2421 for j := n - 1; j >= 0; j-- { 2422 if diag == blas.NonUnit { 2423 x[j] /= ap[kk+j] 2424 } 2425 if j > 0 { 2426 c128.AxpyUnitary(-x[j], ap[kk:kk+j], x[:j]) 2427 } 2428 kk -= j 2429 } 2430 } else { 2431 jx := kx + (n-1)*incX 2432 for j := n - 1; j >= 0; j-- { 2433 if diag == blas.NonUnit { 2434 x[jx] /= ap[kk+j] 2435 } 2436 if j > 0 { 2437 c128.AxpyInc(-x[jx], ap[kk:kk+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) 2438 } 2439 jx -= incX 2440 kk -= j 2441 } 2442 } 2443 } 2444 return 2445 } 2446 2447 // Form x = inv(Aᴴ)*x. 2448 if uplo == blas.Upper { 2449 kk := 0 2450 if incX == 1 { 2451 for j := 0; j < n; j++ { 2452 if diag == blas.NonUnit { 2453 x[j] /= cmplx.Conj(ap[kk]) 2454 } 2455 xj := x[j] 2456 k := kk + 1 2457 for i := j + 1; i < n; i++ { 2458 x[i] -= xj * cmplx.Conj(ap[k]) 2459 k++ 2460 } 2461 kk += n - j 2462 } 2463 } else { 2464 jx := kx 2465 for j := 0; j < n; j++ { 2466 if diag == blas.NonUnit { 2467 x[jx] /= cmplx.Conj(ap[kk]) 2468 } 2469 xj := x[jx] 2470 ix := jx + incX 2471 k := kk + 1 2472 for i := j + 1; i < n; i++ { 2473 x[ix] -= xj * cmplx.Conj(ap[k]) 2474 ix += incX 2475 k++ 2476 } 2477 jx += incX 2478 kk += n - j 2479 } 2480 } 2481 } else { 2482 kk := n*(n+1)/2 - n 2483 if incX == 1 { 2484 for j := n - 1; j >= 0; j-- { 2485 if diag == blas.NonUnit { 2486 x[j] /= cmplx.Conj(ap[kk+j]) 2487 } 2488 xj := x[j] 2489 for i := 0; i < j; i++ { 2490 x[i] -= xj * cmplx.Conj(ap[kk+i]) 2491 } 2492 kk -= j 2493 } 2494 } else { 2495 jx := kx + (n-1)*incX 2496 for j := n - 1; j >= 0; j-- { 2497 if diag == blas.NonUnit { 2498 x[jx] /= cmplx.Conj(ap[kk+j]) 2499 } 2500 xj := x[jx] 2501 ix := kx 2502 for i := 0; i < j; i++ { 2503 x[ix] -= xj * cmplx.Conj(ap[kk+i]) 2504 ix += incX 2505 } 2506 jx -= incX 2507 kk -= j 2508 } 2509 } 2510 } 2511 } 2512 2513 // Ztrmv performs one of the matrix-vector operations 2514 // 2515 // x = A * x if trans = blas.NoTrans 2516 // x = Aᵀ * x if trans = blas.Trans 2517 // x = Aᴴ * x if trans = blas.ConjTrans 2518 // 2519 // where x is a vector, and A is an n×n triangular matrix. 2520 func (Implementation) Ztrmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { 2521 switch trans { 2522 default: 2523 panic(badTranspose) 2524 case blas.NoTrans, blas.Trans, blas.ConjTrans: 2525 } 2526 switch uplo { 2527 default: 2528 panic(badUplo) 2529 case blas.Upper, blas.Lower: 2530 } 2531 switch diag { 2532 default: 2533 panic(badDiag) 2534 case blas.NonUnit, blas.Unit: 2535 } 2536 if n < 0 { 2537 panic(nLT0) 2538 } 2539 if lda < max(1, n) { 2540 panic(badLdA) 2541 } 2542 if incX == 0 { 2543 panic(zeroIncX) 2544 } 2545 2546 // Quick return if possible. 2547 if n == 0 { 2548 return 2549 } 2550 2551 // For zero matrix size the following slice length checks are trivially satisfied. 2552 if len(a) < lda*(n-1)+n { 2553 panic(shortA) 2554 } 2555 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 2556 panic(shortX) 2557 } 2558 2559 // Set up start index in X. 2560 var kx int 2561 if incX < 0 { 2562 kx = (1 - n) * incX 2563 } 2564 2565 // The elements of A are accessed sequentially with one pass through A. 2566 2567 if trans == blas.NoTrans { 2568 // Form x = A*x. 2569 if uplo == blas.Upper { 2570 if incX == 1 { 2571 for i := 0; i < n; i++ { 2572 if diag == blas.NonUnit { 2573 x[i] *= a[i*lda+i] 2574 } 2575 if n-i-1 > 0 { 2576 x[i] += c128.DotuUnitary(a[i*lda+i+1:i*lda+n], x[i+1:n]) 2577 } 2578 } 2579 } else { 2580 ix := kx 2581 for i := 0; i < n; i++ { 2582 if diag == blas.NonUnit { 2583 x[ix] *= a[i*lda+i] 2584 } 2585 if n-i-1 > 0 { 2586 x[ix] += c128.DotuInc(a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) 2587 } 2588 ix += incX 2589 } 2590 } 2591 } else { 2592 if incX == 1 { 2593 for i := n - 1; i >= 0; i-- { 2594 if diag == blas.NonUnit { 2595 x[i] *= a[i*lda+i] 2596 } 2597 if i > 0 { 2598 x[i] += c128.DotuUnitary(a[i*lda:i*lda+i], x[:i]) 2599 } 2600 } 2601 } else { 2602 ix := kx + (n-1)*incX 2603 for i := n - 1; i >= 0; i-- { 2604 if diag == blas.NonUnit { 2605 x[ix] *= a[i*lda+i] 2606 } 2607 if i > 0 { 2608 x[ix] += c128.DotuInc(a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) 2609 } 2610 ix -= incX 2611 } 2612 } 2613 } 2614 return 2615 } 2616 2617 if trans == blas.Trans { 2618 // Form x = Aᵀ*x. 2619 if uplo == blas.Upper { 2620 if incX == 1 { 2621 for i := n - 1; i >= 0; i-- { 2622 xi := x[i] 2623 if diag == blas.NonUnit { 2624 x[i] *= a[i*lda+i] 2625 } 2626 if n-i-1 > 0 { 2627 c128.AxpyUnitary(xi, a[i*lda+i+1:i*lda+n], x[i+1:n]) 2628 } 2629 } 2630 } else { 2631 ix := kx + (n-1)*incX 2632 for i := n - 1; i >= 0; i-- { 2633 xi := x[ix] 2634 if diag == blas.NonUnit { 2635 x[ix] *= a[i*lda+i] 2636 } 2637 if n-i-1 > 0 { 2638 c128.AxpyInc(xi, a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) 2639 } 2640 ix -= incX 2641 } 2642 } 2643 } else { 2644 if incX == 1 { 2645 for i := 0; i < n; i++ { 2646 if i > 0 { 2647 c128.AxpyUnitary(x[i], a[i*lda:i*lda+i], x[:i]) 2648 } 2649 if diag == blas.NonUnit { 2650 x[i] *= a[i*lda+i] 2651 } 2652 } 2653 } else { 2654 ix := kx 2655 for i := 0; i < n; i++ { 2656 if i > 0 { 2657 c128.AxpyInc(x[ix], a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) 2658 } 2659 if diag == blas.NonUnit { 2660 x[ix] *= a[i*lda+i] 2661 } 2662 ix += incX 2663 } 2664 } 2665 } 2666 return 2667 } 2668 2669 // Form x = Aᴴ*x. 2670 if uplo == blas.Upper { 2671 if incX == 1 { 2672 for i := n - 1; i >= 0; i-- { 2673 xi := x[i] 2674 if diag == blas.NonUnit { 2675 x[i] *= cmplx.Conj(a[i*lda+i]) 2676 } 2677 for j := i + 1; j < n; j++ { 2678 x[j] += xi * cmplx.Conj(a[i*lda+j]) 2679 } 2680 } 2681 } else { 2682 ix := kx + (n-1)*incX 2683 for i := n - 1; i >= 0; i-- { 2684 xi := x[ix] 2685 if diag == blas.NonUnit { 2686 x[ix] *= cmplx.Conj(a[i*lda+i]) 2687 } 2688 jx := ix + incX 2689 for j := i + 1; j < n; j++ { 2690 x[jx] += xi * cmplx.Conj(a[i*lda+j]) 2691 jx += incX 2692 } 2693 ix -= incX 2694 } 2695 } 2696 } else { 2697 if incX == 1 { 2698 for i := 0; i < n; i++ { 2699 for j := 0; j < i; j++ { 2700 x[j] += x[i] * cmplx.Conj(a[i*lda+j]) 2701 } 2702 if diag == blas.NonUnit { 2703 x[i] *= cmplx.Conj(a[i*lda+i]) 2704 } 2705 } 2706 } else { 2707 ix := kx 2708 for i := 0; i < n; i++ { 2709 jx := kx 2710 for j := 0; j < i; j++ { 2711 x[jx] += x[ix] * cmplx.Conj(a[i*lda+j]) 2712 jx += incX 2713 } 2714 if diag == blas.NonUnit { 2715 x[ix] *= cmplx.Conj(a[i*lda+i]) 2716 } 2717 ix += incX 2718 } 2719 } 2720 } 2721 } 2722 2723 // Ztrsv solves one of the systems of equations 2724 // 2725 // A * x = b if trans == blas.NoTrans 2726 // Aᵀ * x = b if trans == blas.Trans 2727 // Aᴴ * x = b if trans == blas.ConjTrans 2728 // 2729 // where b and x are n element vectors and A is an n×n triangular matrix. 2730 // 2731 // On entry, x contains the values of b, and the solution is 2732 // stored in-place into x. 2733 // 2734 // No test for singularity or near-singularity is included in this 2735 // routine. Such tests must be performed before calling this routine. 2736 func (Implementation) Ztrsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { 2737 switch trans { 2738 default: 2739 panic(badTranspose) 2740 case blas.NoTrans, blas.Trans, blas.ConjTrans: 2741 } 2742 switch uplo { 2743 default: 2744 panic(badUplo) 2745 case blas.Upper, blas.Lower: 2746 } 2747 switch diag { 2748 default: 2749 panic(badDiag) 2750 case blas.NonUnit, blas.Unit: 2751 } 2752 if n < 0 { 2753 panic(nLT0) 2754 } 2755 if lda < max(1, n) { 2756 panic(badLdA) 2757 } 2758 if incX == 0 { 2759 panic(zeroIncX) 2760 } 2761 2762 // Quick return if possible. 2763 if n == 0 { 2764 return 2765 } 2766 2767 // For zero matrix size the following slice length checks are trivially satisfied. 2768 if len(a) < lda*(n-1)+n { 2769 panic(shortA) 2770 } 2771 if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { 2772 panic(shortX) 2773 } 2774 2775 // Set up start index in X. 2776 var kx int 2777 if incX < 0 { 2778 kx = (1 - n) * incX 2779 } 2780 2781 // The elements of A are accessed sequentially with one pass through A. 2782 2783 if trans == blas.NoTrans { 2784 // Form x = inv(A)*x. 2785 if uplo == blas.Upper { 2786 if incX == 1 { 2787 for i := n - 1; i >= 0; i-- { 2788 aii := a[i*lda+i] 2789 if n-i-1 > 0 { 2790 x[i] -= c128.DotuUnitary(x[i+1:n], a[i*lda+i+1:i*lda+n]) 2791 } 2792 if diag == blas.NonUnit { 2793 x[i] /= aii 2794 } 2795 } 2796 } else { 2797 ix := kx + (n-1)*incX 2798 for i := n - 1; i >= 0; i-- { 2799 aii := a[i*lda+i] 2800 if n-i-1 > 0 { 2801 x[ix] -= c128.DotuInc(x, a[i*lda+i+1:i*lda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) 2802 } 2803 if diag == blas.NonUnit { 2804 x[ix] /= aii 2805 } 2806 ix -= incX 2807 } 2808 } 2809 } else { 2810 if incX == 1 { 2811 for i := 0; i < n; i++ { 2812 if i > 0 { 2813 x[i] -= c128.DotuUnitary(x[:i], a[i*lda:i*lda+i]) 2814 } 2815 if diag == blas.NonUnit { 2816 x[i] /= a[i*lda+i] 2817 } 2818 } 2819 } else { 2820 ix := kx 2821 for i := 0; i < n; i++ { 2822 if i > 0 { 2823 x[ix] -= c128.DotuInc(x, a[i*lda:i*lda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) 2824 } 2825 if diag == blas.NonUnit { 2826 x[ix] /= a[i*lda+i] 2827 } 2828 ix += incX 2829 } 2830 } 2831 } 2832 return 2833 } 2834 2835 if trans == blas.Trans { 2836 // Form x = inv(Aᵀ)*x. 2837 if uplo == blas.Upper { 2838 if incX == 1 { 2839 for j := 0; j < n; j++ { 2840 if diag == blas.NonUnit { 2841 x[j] /= a[j*lda+j] 2842 } 2843 if n-j-1 > 0 { 2844 c128.AxpyUnitary(-x[j], a[j*lda+j+1:j*lda+n], x[j+1:n]) 2845 } 2846 } 2847 } else { 2848 jx := kx 2849 for j := 0; j < n; j++ { 2850 if diag == blas.NonUnit { 2851 x[jx] /= a[j*lda+j] 2852 } 2853 if n-j-1 > 0 { 2854 c128.AxpyInc(-x[jx], a[j*lda+j+1:j*lda+n], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) 2855 } 2856 jx += incX 2857 } 2858 } 2859 } else { 2860 if incX == 1 { 2861 for j := n - 1; j >= 0; j-- { 2862 if diag == blas.NonUnit { 2863 x[j] /= a[j*lda+j] 2864 } 2865 xj := x[j] 2866 if j > 0 { 2867 c128.AxpyUnitary(-xj, a[j*lda:j*lda+j], x[:j]) 2868 } 2869 } 2870 } else { 2871 jx := kx + (n-1)*incX 2872 for j := n - 1; j >= 0; j-- { 2873 if diag == blas.NonUnit { 2874 x[jx] /= a[j*lda+j] 2875 } 2876 if j > 0 { 2877 c128.AxpyInc(-x[jx], a[j*lda:j*lda+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) 2878 } 2879 jx -= incX 2880 } 2881 } 2882 } 2883 return 2884 } 2885 2886 // Form x = inv(Aᴴ)*x. 2887 if uplo == blas.Upper { 2888 if incX == 1 { 2889 for j := 0; j < n; j++ { 2890 if diag == blas.NonUnit { 2891 x[j] /= cmplx.Conj(a[j*lda+j]) 2892 } 2893 xj := x[j] 2894 for i := j + 1; i < n; i++ { 2895 x[i] -= xj * cmplx.Conj(a[j*lda+i]) 2896 } 2897 } 2898 } else { 2899 jx := kx 2900 for j := 0; j < n; j++ { 2901 if diag == blas.NonUnit { 2902 x[jx] /= cmplx.Conj(a[j*lda+j]) 2903 } 2904 xj := x[jx] 2905 ix := jx + incX 2906 for i := j + 1; i < n; i++ { 2907 x[ix] -= xj * cmplx.Conj(a[j*lda+i]) 2908 ix += incX 2909 } 2910 jx += incX 2911 } 2912 } 2913 } else { 2914 if incX == 1 { 2915 for j := n - 1; j >= 0; j-- { 2916 if diag == blas.NonUnit { 2917 x[j] /= cmplx.Conj(a[j*lda+j]) 2918 } 2919 xj := x[j] 2920 for i := 0; i < j; i++ { 2921 x[i] -= xj * cmplx.Conj(a[j*lda+i]) 2922 } 2923 } 2924 } else { 2925 jx := kx + (n-1)*incX 2926 for j := n - 1; j >= 0; j-- { 2927 if diag == blas.NonUnit { 2928 x[jx] /= cmplx.Conj(a[j*lda+j]) 2929 } 2930 xj := x[jx] 2931 ix := kx 2932 for i := 0; i < j; i++ { 2933 x[ix] -= xj * cmplx.Conj(a[j*lda+i]) 2934 ix += incX 2935 } 2936 jx -= incX 2937 } 2938 } 2939 } 2940 }