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