gonum.org/v1/gonum@v0.14.0/mat/vector.go (about) 1 // Copyright ©2013 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 mat 6 7 import ( 8 "math" 9 10 "gonum.org/v1/gonum/blas" 11 "gonum.org/v1/gonum/blas/blas64" 12 "gonum.org/v1/gonum/internal/asm/f64" 13 ) 14 15 var ( 16 vector *VecDense 17 18 _ Matrix = vector 19 _ allMatrix = vector 20 _ Vector = vector 21 _ Reseter = vector 22 _ MutableVector = vector 23 ) 24 25 // Vector is a vector. 26 type Vector interface { 27 Matrix 28 AtVec(int) float64 29 Len() int 30 } 31 32 // A MutableVector can set elements of a vector. 33 type MutableVector interface { 34 Vector 35 SetVec(i int, v float64) 36 } 37 38 // TransposeVec is a type for performing an implicit transpose of a Vector. 39 // It implements the Vector interface, returning values from the transpose 40 // of the vector within. 41 type TransposeVec struct { 42 Vector Vector 43 } 44 45 // At returns the value of the element at row i and column j of the transposed 46 // matrix, that is, row j and column i of the Vector field. 47 func (t TransposeVec) At(i, j int) float64 { 48 return t.Vector.At(j, i) 49 } 50 51 // AtVec returns the element at position i. It panics if i is out of bounds. 52 func (t TransposeVec) AtVec(i int) float64 { 53 return t.Vector.AtVec(i) 54 } 55 56 // Dims returns the dimensions of the transposed vector. 57 func (t TransposeVec) Dims() (r, c int) { 58 c, r = t.Vector.Dims() 59 return r, c 60 } 61 62 // T performs an implicit transpose by returning the Vector field. 63 func (t TransposeVec) T() Matrix { 64 return t.Vector 65 } 66 67 // Len returns the number of columns in the vector. 68 func (t TransposeVec) Len() int { 69 return t.Vector.Len() 70 } 71 72 // TVec performs an implicit transpose by returning the Vector field. 73 func (t TransposeVec) TVec() Vector { 74 return t.Vector 75 } 76 77 // Untranspose returns the Vector field. 78 func (t TransposeVec) Untranspose() Matrix { 79 return t.Vector 80 } 81 82 func (t TransposeVec) UntransposeVec() Vector { 83 return t.Vector 84 } 85 86 // VecDense represents a column vector. 87 type VecDense struct { 88 mat blas64.Vector 89 // A BLAS vector can have a negative increment, but allowing this 90 // in the mat type complicates a lot of code, and doesn't gain anything. 91 // VecDense must have positive increment in this package. 92 } 93 94 // NewVecDense creates a new VecDense of length n. If data == nil, 95 // a new slice is allocated for the backing slice. If len(data) == n, data is 96 // used as the backing slice, and changes to the elements of the returned VecDense 97 // will be reflected in data. If neither of these is true, NewVecDense will panic. 98 // NewVecDense will panic if n is zero. 99 func NewVecDense(n int, data []float64) *VecDense { 100 if n <= 0 { 101 if n == 0 { 102 panic(ErrZeroLength) 103 } 104 panic("mat: negative dimension") 105 } 106 if len(data) != n && data != nil { 107 panic(ErrShape) 108 } 109 if data == nil { 110 data = make([]float64, n) 111 } 112 return &VecDense{ 113 mat: blas64.Vector{ 114 N: n, 115 Inc: 1, 116 Data: data, 117 }, 118 } 119 } 120 121 // SliceVec returns a new Vector that shares backing data with the receiver. 122 // The returned matrix starts at i of the receiver and extends k-i elements. 123 // SliceVec panics with ErrIndexOutOfRange if the slice is outside the capacity 124 // of the receiver. 125 func (v *VecDense) SliceVec(i, k int) Vector { 126 return v.sliceVec(i, k) 127 } 128 129 func (v *VecDense) sliceVec(i, k int) *VecDense { 130 if i < 0 || k <= i || v.Cap() < k { 131 panic(ErrIndexOutOfRange) 132 } 133 return &VecDense{ 134 mat: blas64.Vector{ 135 N: k - i, 136 Inc: v.mat.Inc, 137 Data: v.mat.Data[i*v.mat.Inc : (k-1)*v.mat.Inc+1], 138 }, 139 } 140 } 141 142 // Dims returns the number of rows and columns in the matrix. Columns is always 1 143 // for a non-Reset vector. 144 func (v *VecDense) Dims() (r, c int) { 145 if v.IsEmpty() { 146 return 0, 0 147 } 148 return v.mat.N, 1 149 } 150 151 // Caps returns the number of rows and columns in the backing matrix. Columns is always 1 152 // for a non-Reset vector. 153 func (v *VecDense) Caps() (r, c int) { 154 if v.IsEmpty() { 155 return 0, 0 156 } 157 return v.Cap(), 1 158 } 159 160 // Len returns the length of the vector. 161 func (v *VecDense) Len() int { 162 return v.mat.N 163 } 164 165 // Cap returns the capacity of the vector. 166 func (v *VecDense) Cap() int { 167 if v.IsEmpty() { 168 return 0 169 } 170 return (cap(v.mat.Data)-1)/v.mat.Inc + 1 171 } 172 173 // T performs an implicit transpose by returning the receiver inside a Transpose. 174 func (v *VecDense) T() Matrix { 175 return Transpose{v} 176 } 177 178 // TVec performs an implicit transpose by returning the receiver inside a TransposeVec. 179 func (v *VecDense) TVec() Vector { 180 return TransposeVec{v} 181 } 182 183 // Reset empties the matrix so that it can be reused as the 184 // receiver of a dimensionally restricted operation. 185 // 186 // Reset should not be used when the matrix shares backing data. 187 // See the Reseter interface for more information. 188 func (v *VecDense) Reset() { 189 // No change of Inc or N to 0 may be 190 // made unless both are set to 0. 191 v.mat.Inc = 0 192 v.mat.N = 0 193 v.mat.Data = v.mat.Data[:0] 194 } 195 196 // Zero sets all of the matrix elements to zero. 197 func (v *VecDense) Zero() { 198 for i := 0; i < v.mat.N; i++ { 199 v.mat.Data[v.mat.Inc*i] = 0 200 } 201 } 202 203 // CloneFromVec makes a copy of a into the receiver, overwriting the previous value 204 // of the receiver. 205 func (v *VecDense) CloneFromVec(a Vector) { 206 if v == a { 207 return 208 } 209 n := a.Len() 210 v.mat = blas64.Vector{ 211 N: n, 212 Inc: 1, 213 Data: use(v.mat.Data, n), 214 } 215 if r, ok := a.(RawVectorer); ok { 216 blas64.Copy(r.RawVector(), v.mat) 217 return 218 } 219 for i := 0; i < a.Len(); i++ { 220 v.setVec(i, a.AtVec(i)) 221 } 222 } 223 224 // VecDenseCopyOf returns a newly allocated copy of the elements of a. 225 func VecDenseCopyOf(a Vector) *VecDense { 226 v := &VecDense{} 227 v.CloneFromVec(a) 228 return v 229 } 230 231 // RawVector returns the underlying blas64.Vector used by the receiver. 232 // Changes to elements in the receiver following the call will be reflected 233 // in returned blas64.Vector. 234 func (v *VecDense) RawVector() blas64.Vector { 235 return v.mat 236 } 237 238 // SetRawVector sets the underlying blas64.Vector used by the receiver. 239 // Changes to elements in the receiver following the call will be reflected 240 // in the input. 241 func (v *VecDense) SetRawVector(a blas64.Vector) { 242 v.mat = a 243 } 244 245 // CopyVec makes a copy of elements of a into the receiver. It is similar to the 246 // built-in copy; it copies as much as the overlap between the two vectors and 247 // returns the number of elements it copied. 248 func (v *VecDense) CopyVec(a Vector) int { 249 n := min(v.Len(), a.Len()) 250 if v == a { 251 return n 252 } 253 if r, ok := a.(RawVectorer); ok { 254 src := r.RawVector() 255 src.N = n 256 dst := v.mat 257 dst.N = n 258 blas64.Copy(src, dst) 259 return n 260 } 261 for i := 0; i < n; i++ { 262 v.setVec(i, a.AtVec(i)) 263 } 264 return n 265 } 266 267 // Norm returns the specified norm of the receiver. Valid norms are: 268 // 269 // 1 - The sum of the element magnitudes 270 // 2 - The Euclidean norm, the square root of the sum of the squares of the elements 271 // Inf - The maximum element magnitude 272 // 273 // Norm will panic with ErrNormOrder if an illegal norm is specified and with 274 // ErrZeroLength if the vector has zero size. 275 func (v *VecDense) Norm(norm float64) float64 { 276 if v.IsEmpty() { 277 panic(ErrZeroLength) 278 } 279 switch norm { 280 default: 281 panic(ErrNormOrder) 282 case 1: 283 return blas64.Asum(v.mat) 284 case 2: 285 return blas64.Nrm2(v.mat) 286 case math.Inf(1): 287 imax := blas64.Iamax(v.mat) 288 return math.Abs(v.at(imax)) 289 } 290 } 291 292 // ScaleVec scales the vector a by alpha, placing the result in the receiver. 293 func (v *VecDense) ScaleVec(alpha float64, a Vector) { 294 n := a.Len() 295 296 if v == a { 297 if v.mat.Inc == 1 { 298 f64.ScalUnitary(alpha, v.mat.Data) 299 return 300 } 301 f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc)) 302 return 303 } 304 305 v.reuseAsNonZeroed(n) 306 307 if rv, ok := a.(RawVectorer); ok { 308 mat := rv.RawVector() 309 v.checkOverlap(mat) 310 if v.mat.Inc == 1 && mat.Inc == 1 { 311 f64.ScalUnitaryTo(v.mat.Data, alpha, mat.Data) 312 return 313 } 314 f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc), 315 alpha, mat.Data, uintptr(n), uintptr(mat.Inc)) 316 return 317 } 318 319 for i := 0; i < n; i++ { 320 v.setVec(i, alpha*a.AtVec(i)) 321 } 322 } 323 324 // AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver. 325 func (v *VecDense) AddScaledVec(a Vector, alpha float64, b Vector) { 326 if alpha == 1 { 327 v.AddVec(a, b) 328 return 329 } 330 if alpha == -1 { 331 v.SubVec(a, b) 332 return 333 } 334 335 ar := a.Len() 336 br := b.Len() 337 338 if ar != br { 339 panic(ErrShape) 340 } 341 342 var amat, bmat blas64.Vector 343 fast := true 344 aU, _ := untransposeExtract(a) 345 if rv, ok := aU.(*VecDense); ok { 346 amat = rv.mat 347 if v != a { 348 v.checkOverlap(amat) 349 } 350 } else { 351 fast = false 352 } 353 bU, _ := untransposeExtract(b) 354 if rv, ok := bU.(*VecDense); ok { 355 bmat = rv.mat 356 if v != b { 357 v.checkOverlap(bmat) 358 } 359 } else { 360 fast = false 361 } 362 363 v.reuseAsNonZeroed(ar) 364 365 switch { 366 case alpha == 0: // v <- a 367 if v == a { 368 return 369 } 370 v.CopyVec(a) 371 case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v 372 blas64.Scal(alpha+1, v.mat) 373 case !fast: // v <- a + alpha * b without blas64 support. 374 for i := 0; i < ar; i++ { 375 v.setVec(i, a.AtVec(i)+alpha*b.AtVec(i)) 376 } 377 case v == a && v != b: // v <- v + alpha * b 378 if v.mat.Inc == 1 && bmat.Inc == 1 { 379 // Fast path for a common case. 380 f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data) 381 } else { 382 f64.AxpyInc(alpha, bmat.Data, v.mat.Data, 383 uintptr(ar), uintptr(bmat.Inc), uintptr(v.mat.Inc), 0, 0) 384 } 385 default: // v <- a + alpha * b or v <- a + alpha * v 386 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 387 // Fast path for a common case. 388 f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data) 389 } else { 390 f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, 391 alpha, bmat.Data, amat.Data, 392 uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) 393 } 394 } 395 } 396 397 // AddVec adds the vectors a and b, placing the result in the receiver. 398 func (v *VecDense) AddVec(a, b Vector) { 399 ar := a.Len() 400 br := b.Len() 401 402 if ar != br { 403 panic(ErrShape) 404 } 405 406 v.reuseAsNonZeroed(ar) 407 408 aU, _ := untransposeExtract(a) 409 bU, _ := untransposeExtract(b) 410 411 if arv, ok := aU.(*VecDense); ok { 412 if brv, ok := bU.(*VecDense); ok { 413 amat := arv.mat 414 bmat := brv.mat 415 416 if v != a { 417 v.checkOverlap(amat) 418 } 419 if v != b { 420 v.checkOverlap(bmat) 421 } 422 423 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 424 // Fast path for a common case. 425 f64.AxpyUnitaryTo(v.mat.Data, 1, bmat.Data, amat.Data) 426 return 427 } 428 f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, 429 1, bmat.Data, amat.Data, 430 uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) 431 return 432 } 433 } 434 435 for i := 0; i < ar; i++ { 436 v.setVec(i, a.AtVec(i)+b.AtVec(i)) 437 } 438 } 439 440 // SubVec subtracts the vector b from a, placing the result in the receiver. 441 func (v *VecDense) SubVec(a, b Vector) { 442 ar := a.Len() 443 br := b.Len() 444 445 if ar != br { 446 panic(ErrShape) 447 } 448 449 v.reuseAsNonZeroed(ar) 450 451 aU, _ := untransposeExtract(a) 452 bU, _ := untransposeExtract(b) 453 454 if arv, ok := aU.(*VecDense); ok { 455 if brv, ok := bU.(*VecDense); ok { 456 amat := arv.mat 457 bmat := brv.mat 458 459 if v != a { 460 v.checkOverlap(amat) 461 } 462 if v != b { 463 v.checkOverlap(bmat) 464 } 465 466 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 467 // Fast path for a common case. 468 f64.AxpyUnitaryTo(v.mat.Data, -1, bmat.Data, amat.Data) 469 return 470 } 471 f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, 472 -1, bmat.Data, amat.Data, 473 uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) 474 return 475 } 476 } 477 478 for i := 0; i < ar; i++ { 479 v.setVec(i, a.AtVec(i)-b.AtVec(i)) 480 } 481 } 482 483 // MulElemVec performs element-wise multiplication of a and b, placing the result 484 // in the receiver. 485 func (v *VecDense) MulElemVec(a, b Vector) { 486 ar := a.Len() 487 br := b.Len() 488 489 if ar != br { 490 panic(ErrShape) 491 } 492 493 v.reuseAsNonZeroed(ar) 494 495 aU, _ := untransposeExtract(a) 496 bU, _ := untransposeExtract(b) 497 498 if arv, ok := aU.(*VecDense); ok { 499 if brv, ok := bU.(*VecDense); ok { 500 amat := arv.mat 501 bmat := brv.mat 502 503 if v != a { 504 v.checkOverlap(amat) 505 } 506 if v != b { 507 v.checkOverlap(bmat) 508 } 509 510 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 511 // Fast path for a common case. 512 for i, a := range amat.Data { 513 v.mat.Data[i] = a * bmat.Data[i] 514 } 515 return 516 } 517 var ia, ib int 518 for i := 0; i < ar; i++ { 519 v.setVec(i, amat.Data[ia]*bmat.Data[ib]) 520 ia += amat.Inc 521 ib += bmat.Inc 522 } 523 return 524 } 525 } 526 527 for i := 0; i < ar; i++ { 528 v.setVec(i, a.AtVec(i)*b.AtVec(i)) 529 } 530 } 531 532 // DivElemVec performs element-wise division of a by b, placing the result 533 // in the receiver. 534 func (v *VecDense) DivElemVec(a, b Vector) { 535 ar := a.Len() 536 br := b.Len() 537 538 if ar != br { 539 panic(ErrShape) 540 } 541 542 v.reuseAsNonZeroed(ar) 543 544 aU, _ := untransposeExtract(a) 545 bU, _ := untransposeExtract(b) 546 547 if arv, ok := aU.(*VecDense); ok { 548 if brv, ok := bU.(*VecDense); ok { 549 amat := arv.mat 550 bmat := brv.mat 551 552 if v != a { 553 v.checkOverlap(amat) 554 } 555 if v != b { 556 v.checkOverlap(bmat) 557 } 558 559 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 560 // Fast path for a common case. 561 for i, a := range amat.Data { 562 v.setVec(i, a/bmat.Data[i]) 563 } 564 return 565 } 566 var ia, ib int 567 for i := 0; i < ar; i++ { 568 v.setVec(i, amat.Data[ia]/bmat.Data[ib]) 569 ia += amat.Inc 570 ib += bmat.Inc 571 } 572 } 573 } 574 575 for i := 0; i < ar; i++ { 576 v.setVec(i, a.AtVec(i)/b.AtVec(i)) 577 } 578 } 579 580 // MulVec computes a * b. The result is stored into the receiver. 581 // MulVec panics if the number of columns in a does not equal the number of rows in b 582 // or if the number of columns in b does not equal 1. 583 func (v *VecDense) MulVec(a Matrix, b Vector) { 584 r, c := a.Dims() 585 br, bc := b.Dims() 586 if c != br || bc != 1 { 587 panic(ErrShape) 588 } 589 590 aU, trans := untransposeExtract(a) 591 var bmat blas64.Vector 592 fast := true 593 bU, _ := untransposeExtract(b) 594 if rv, ok := bU.(*VecDense); ok { 595 bmat = rv.mat 596 if v != b { 597 v.checkOverlap(bmat) 598 } 599 } else { 600 fast = false 601 } 602 603 v.reuseAsNonZeroed(r) 604 var restore func() 605 if v == aU { 606 v, restore = v.isolatedWorkspace(aU.(*VecDense)) 607 defer restore() 608 } else if v == b { 609 v, restore = v.isolatedWorkspace(b) 610 defer restore() 611 } 612 613 // TODO(kortschak): Improve the non-fast paths. 614 switch aU := aU.(type) { 615 case Vector: 616 if b.Len() == 1 { 617 // {n,1} x {1,1} 618 v.ScaleVec(b.AtVec(0), aU) 619 return 620 } 621 622 // {1,n} x {n,1} 623 if fast { 624 if rv, ok := aU.(*VecDense); ok { 625 amat := rv.mat 626 if v != aU { 627 v.checkOverlap(amat) 628 } 629 630 if amat.Inc == 1 && bmat.Inc == 1 { 631 // Fast path for a common case. 632 v.setVec(0, f64.DotUnitary(amat.Data, bmat.Data)) 633 return 634 } 635 v.setVec(0, f64.DotInc(amat.Data, bmat.Data, 636 uintptr(c), uintptr(amat.Inc), uintptr(bmat.Inc), 0, 0)) 637 return 638 } 639 } 640 var sum float64 641 for i := 0; i < c; i++ { 642 sum += aU.AtVec(i) * b.AtVec(i) 643 } 644 v.setVec(0, sum) 645 return 646 case *SymBandDense: 647 if fast { 648 aU.checkOverlap(v.asGeneral()) 649 blas64.Sbmv(1, aU.mat, bmat, 0, v.mat) 650 return 651 } 652 case *SymDense: 653 if fast { 654 aU.checkOverlap(v.asGeneral()) 655 blas64.Symv(1, aU.mat, bmat, 0, v.mat) 656 return 657 } 658 case *TriDense: 659 if fast { 660 v.CopyVec(b) 661 aU.checkOverlap(v.asGeneral()) 662 ta := blas.NoTrans 663 if trans { 664 ta = blas.Trans 665 } 666 blas64.Trmv(ta, aU.mat, v.mat) 667 return 668 } 669 case *Dense: 670 if fast { 671 aU.checkOverlap(v.asGeneral()) 672 t := blas.NoTrans 673 if trans { 674 t = blas.Trans 675 } 676 blas64.Gemv(t, 1, aU.mat, bmat, 0, v.mat) 677 return 678 } 679 default: 680 if fast { 681 for i := 0; i < r; i++ { 682 var f float64 683 for j := 0; j < c; j++ { 684 f += a.At(i, j) * bmat.Data[j*bmat.Inc] 685 } 686 v.setVec(i, f) 687 } 688 return 689 } 690 } 691 692 for i := 0; i < r; i++ { 693 var f float64 694 for j := 0; j < c; j++ { 695 f += a.At(i, j) * b.AtVec(j) 696 } 697 v.setVec(i, f) 698 } 699 } 700 701 // ReuseAsVec changes the receiver if it IsEmpty() to be of size n×1. 702 // 703 // ReuseAsVec re-uses the backing data slice if it has sufficient capacity, 704 // otherwise a new slice is allocated. The backing data is zero on return. 705 // 706 // ReuseAsVec panics if the receiver is not empty, and panics if 707 // the input size is less than one. To empty the receiver for re-use, 708 // Reset should be used. 709 func (v *VecDense) ReuseAsVec(n int) { 710 if n <= 0 { 711 if n == 0 { 712 panic(ErrZeroLength) 713 } 714 panic(ErrNegativeDimension) 715 } 716 if !v.IsEmpty() { 717 panic(ErrReuseNonEmpty) 718 } 719 v.reuseAsZeroed(n) 720 } 721 722 // reuseAsNonZeroed resizes an empty vector to a r×1 vector, 723 // or checks that a non-empty matrix is r×1. 724 func (v *VecDense) reuseAsNonZeroed(r int) { 725 // reuseAsNonZeroed must be kept in sync with reuseAsZeroed. 726 if r == 0 { 727 panic(ErrZeroLength) 728 } 729 if v.IsEmpty() { 730 v.mat = blas64.Vector{ 731 N: r, 732 Inc: 1, 733 Data: use(v.mat.Data, r), 734 } 735 return 736 } 737 if r != v.mat.N { 738 panic(ErrShape) 739 } 740 } 741 742 // reuseAsZeroed resizes an empty vector to a r×1 vector, 743 // or checks that a non-empty matrix is r×1. 744 func (v *VecDense) reuseAsZeroed(r int) { 745 // reuseAsZeroed must be kept in sync with reuseAsNonZeroed. 746 if r == 0 { 747 panic(ErrZeroLength) 748 } 749 if v.IsEmpty() { 750 v.mat = blas64.Vector{ 751 N: r, 752 Inc: 1, 753 Data: useZeroed(v.mat.Data, r), 754 } 755 return 756 } 757 if r != v.mat.N { 758 panic(ErrShape) 759 } 760 v.Zero() 761 } 762 763 // IsEmpty returns whether the receiver is empty. Empty matrices can be the 764 // receiver for size-restricted operations. The receiver can be emptied using 765 // Reset. 766 func (v *VecDense) IsEmpty() bool { 767 // It must be the case that v.Dims() returns 768 // zeros in this case. See comment in Reset(). 769 return v.mat.Inc == 0 770 } 771 772 func (v *VecDense) isolatedWorkspace(a Vector) (n *VecDense, restore func()) { 773 l := a.Len() 774 if l == 0 { 775 panic(ErrZeroLength) 776 } 777 n = getVecDenseWorkspace(l, false) 778 return n, func() { 779 v.CopyVec(n) 780 putVecDenseWorkspace(n) 781 } 782 } 783 784 // asDense returns a Dense representation of the receiver with the same 785 // underlying data. 786 func (v *VecDense) asDense() *Dense { 787 return &Dense{ 788 mat: v.asGeneral(), 789 capRows: v.mat.N, 790 capCols: 1, 791 } 792 } 793 794 // asGeneral returns a blas64.General representation of the receiver with the 795 // same underlying data. 796 func (v *VecDense) asGeneral() blas64.General { 797 return blas64.General{ 798 Rows: v.mat.N, 799 Cols: 1, 800 Stride: v.mat.Inc, 801 Data: v.mat.Data, 802 } 803 } 804 805 // ColViewOf reflects the column j of the RawMatrixer m, into the receiver 806 // backed by the same underlying data. The receiver must either be empty 807 // have length equal to the number of rows of m. 808 func (v *VecDense) ColViewOf(m RawMatrixer, j int) { 809 rm := m.RawMatrix() 810 811 if j >= rm.Cols || j < 0 { 812 panic(ErrColAccess) 813 } 814 if !v.IsEmpty() && v.mat.N != rm.Rows { 815 panic(ErrShape) 816 } 817 818 v.mat.Inc = rm.Stride 819 v.mat.Data = rm.Data[j : (rm.Rows-1)*rm.Stride+j+1] 820 v.mat.N = rm.Rows 821 } 822 823 // RowViewOf reflects the row i of the RawMatrixer m, into the receiver 824 // backed by the same underlying data. The receiver must either be 825 // empty or have length equal to the number of columns of m. 826 func (v *VecDense) RowViewOf(m RawMatrixer, i int) { 827 rm := m.RawMatrix() 828 829 if i >= rm.Rows || i < 0 { 830 panic(ErrRowAccess) 831 } 832 if !v.IsEmpty() && v.mat.N != rm.Cols { 833 panic(ErrShape) 834 } 835 836 v.mat.Inc = 1 837 v.mat.Data = rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] 838 v.mat.N = rm.Cols 839 }