github.com/gopherd/gonum@v0.0.4/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 "github.com/gopherd/gonum/blas" 11 "github.com/gopherd/gonum/blas/blas64" 12 "github.com/gopherd/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 // 1 - The sum of the element magnitudes 269 // 2 - The Euclidean norm, the square root of the sum of the squares of the elements 270 // Inf - The maximum element magnitude 271 // 272 // Norm will panic with ErrNormOrder if an illegal norm is specified and with 273 // ErrZeroLength if the vector has zero size. 274 func (v *VecDense) Norm(norm float64) float64 { 275 if v.IsEmpty() { 276 panic(ErrZeroLength) 277 } 278 switch norm { 279 default: 280 panic(ErrNormOrder) 281 case 1: 282 return blas64.Asum(v.mat) 283 case 2: 284 return blas64.Nrm2(v.mat) 285 case math.Inf(1): 286 imax := blas64.Iamax(v.mat) 287 return math.Abs(v.at(imax)) 288 } 289 } 290 291 // ScaleVec scales the vector a by alpha, placing the result in the receiver. 292 func (v *VecDense) ScaleVec(alpha float64, a Vector) { 293 n := a.Len() 294 295 if v == a { 296 if v.mat.Inc == 1 { 297 f64.ScalUnitary(alpha, v.mat.Data) 298 return 299 } 300 f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc)) 301 return 302 } 303 304 v.reuseAsNonZeroed(n) 305 306 if rv, ok := a.(RawVectorer); ok { 307 mat := rv.RawVector() 308 v.checkOverlap(mat) 309 if v.mat.Inc == 1 && mat.Inc == 1 { 310 f64.ScalUnitaryTo(v.mat.Data, alpha, mat.Data) 311 return 312 } 313 f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc), 314 alpha, mat.Data, uintptr(n), uintptr(mat.Inc)) 315 return 316 } 317 318 for i := 0; i < n; i++ { 319 v.setVec(i, alpha*a.AtVec(i)) 320 } 321 } 322 323 // AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver. 324 func (v *VecDense) AddScaledVec(a Vector, alpha float64, b Vector) { 325 if alpha == 1 { 326 v.AddVec(a, b) 327 return 328 } 329 if alpha == -1 { 330 v.SubVec(a, b) 331 return 332 } 333 334 ar := a.Len() 335 br := b.Len() 336 337 if ar != br { 338 panic(ErrShape) 339 } 340 341 var amat, bmat blas64.Vector 342 fast := true 343 aU, _ := untransposeExtract(a) 344 if rv, ok := aU.(*VecDense); ok { 345 amat = rv.mat 346 if v != a { 347 v.checkOverlap(amat) 348 } 349 } else { 350 fast = false 351 } 352 bU, _ := untransposeExtract(b) 353 if rv, ok := bU.(*VecDense); ok { 354 bmat = rv.mat 355 if v != b { 356 v.checkOverlap(bmat) 357 } 358 } else { 359 fast = false 360 } 361 362 v.reuseAsNonZeroed(ar) 363 364 switch { 365 case alpha == 0: // v <- a 366 if v == a { 367 return 368 } 369 v.CopyVec(a) 370 case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v 371 blas64.Scal(alpha+1, v.mat) 372 case !fast: // v <- a + alpha * b without blas64 support. 373 for i := 0; i < ar; i++ { 374 v.setVec(i, a.AtVec(i)+alpha*b.AtVec(i)) 375 } 376 case v == a && v != b: // v <- v + alpha * b 377 if v.mat.Inc == 1 && bmat.Inc == 1 { 378 // Fast path for a common case. 379 f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data) 380 } else { 381 f64.AxpyInc(alpha, bmat.Data, v.mat.Data, 382 uintptr(ar), uintptr(bmat.Inc), uintptr(v.mat.Inc), 0, 0) 383 } 384 default: // v <- a + alpha * b or v <- a + alpha * v 385 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 386 // Fast path for a common case. 387 f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data) 388 } else { 389 f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, 390 alpha, bmat.Data, amat.Data, 391 uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) 392 } 393 } 394 } 395 396 // AddVec adds the vectors a and b, placing the result in the receiver. 397 func (v *VecDense) AddVec(a, b Vector) { 398 ar := a.Len() 399 br := b.Len() 400 401 if ar != br { 402 panic(ErrShape) 403 } 404 405 v.reuseAsNonZeroed(ar) 406 407 aU, _ := untransposeExtract(a) 408 bU, _ := untransposeExtract(b) 409 410 if arv, ok := aU.(*VecDense); ok { 411 if brv, ok := bU.(*VecDense); ok { 412 amat := arv.mat 413 bmat := brv.mat 414 415 if v != a { 416 v.checkOverlap(amat) 417 } 418 if v != b { 419 v.checkOverlap(bmat) 420 } 421 422 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 423 // Fast path for a common case. 424 f64.AxpyUnitaryTo(v.mat.Data, 1, bmat.Data, amat.Data) 425 return 426 } 427 f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, 428 1, bmat.Data, amat.Data, 429 uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) 430 return 431 } 432 } 433 434 for i := 0; i < ar; i++ { 435 v.setVec(i, a.AtVec(i)+b.AtVec(i)) 436 } 437 } 438 439 // SubVec subtracts the vector b from a, placing the result in the receiver. 440 func (v *VecDense) SubVec(a, b Vector) { 441 ar := a.Len() 442 br := b.Len() 443 444 if ar != br { 445 panic(ErrShape) 446 } 447 448 v.reuseAsNonZeroed(ar) 449 450 aU, _ := untransposeExtract(a) 451 bU, _ := untransposeExtract(b) 452 453 if arv, ok := aU.(*VecDense); ok { 454 if brv, ok := bU.(*VecDense); ok { 455 amat := arv.mat 456 bmat := brv.mat 457 458 if v != a { 459 v.checkOverlap(amat) 460 } 461 if v != b { 462 v.checkOverlap(bmat) 463 } 464 465 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 466 // Fast path for a common case. 467 f64.AxpyUnitaryTo(v.mat.Data, -1, bmat.Data, amat.Data) 468 return 469 } 470 f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, 471 -1, bmat.Data, amat.Data, 472 uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) 473 return 474 } 475 } 476 477 for i := 0; i < ar; i++ { 478 v.setVec(i, a.AtVec(i)-b.AtVec(i)) 479 } 480 } 481 482 // MulElemVec performs element-wise multiplication of a and b, placing the result 483 // in the receiver. 484 func (v *VecDense) MulElemVec(a, b Vector) { 485 ar := a.Len() 486 br := b.Len() 487 488 if ar != br { 489 panic(ErrShape) 490 } 491 492 v.reuseAsNonZeroed(ar) 493 494 aU, _ := untransposeExtract(a) 495 bU, _ := untransposeExtract(b) 496 497 if arv, ok := aU.(*VecDense); ok { 498 if brv, ok := bU.(*VecDense); ok { 499 amat := arv.mat 500 bmat := brv.mat 501 502 if v != a { 503 v.checkOverlap(amat) 504 } 505 if v != b { 506 v.checkOverlap(bmat) 507 } 508 509 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 510 // Fast path for a common case. 511 for i, a := range amat.Data { 512 v.mat.Data[i] = a * bmat.Data[i] 513 } 514 return 515 } 516 var ia, ib int 517 for i := 0; i < ar; i++ { 518 v.setVec(i, amat.Data[ia]*bmat.Data[ib]) 519 ia += amat.Inc 520 ib += bmat.Inc 521 } 522 return 523 } 524 } 525 526 for i := 0; i < ar; i++ { 527 v.setVec(i, a.AtVec(i)*b.AtVec(i)) 528 } 529 } 530 531 // DivElemVec performs element-wise division of a by b, placing the result 532 // in the receiver. 533 func (v *VecDense) DivElemVec(a, b Vector) { 534 ar := a.Len() 535 br := b.Len() 536 537 if ar != br { 538 panic(ErrShape) 539 } 540 541 v.reuseAsNonZeroed(ar) 542 543 aU, _ := untransposeExtract(a) 544 bU, _ := untransposeExtract(b) 545 546 if arv, ok := aU.(*VecDense); ok { 547 if brv, ok := bU.(*VecDense); ok { 548 amat := arv.mat 549 bmat := brv.mat 550 551 if v != a { 552 v.checkOverlap(amat) 553 } 554 if v != b { 555 v.checkOverlap(bmat) 556 } 557 558 if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { 559 // Fast path for a common case. 560 for i, a := range amat.Data { 561 v.setVec(i, a/bmat.Data[i]) 562 } 563 return 564 } 565 var ia, ib int 566 for i := 0; i < ar; i++ { 567 v.setVec(i, amat.Data[ia]/bmat.Data[ib]) 568 ia += amat.Inc 569 ib += bmat.Inc 570 } 571 } 572 } 573 574 for i := 0; i < ar; i++ { 575 v.setVec(i, a.AtVec(i)/b.AtVec(i)) 576 } 577 } 578 579 // MulVec computes a * b. The result is stored into the receiver. 580 // MulVec panics if the number of columns in a does not equal the number of rows in b 581 // or if the number of columns in b does not equal 1. 582 func (v *VecDense) MulVec(a Matrix, b Vector) { 583 r, c := a.Dims() 584 br, bc := b.Dims() 585 if c != br || bc != 1 { 586 panic(ErrShape) 587 } 588 589 aU, trans := untransposeExtract(a) 590 var bmat blas64.Vector 591 fast := true 592 bU, _ := untransposeExtract(b) 593 if rv, ok := bU.(*VecDense); ok { 594 bmat = rv.mat 595 if v != b { 596 v.checkOverlap(bmat) 597 } 598 } else { 599 fast = false 600 } 601 602 v.reuseAsNonZeroed(r) 603 var restore func() 604 if v == aU { 605 v, restore = v.isolatedWorkspace(aU.(*VecDense)) 606 defer restore() 607 } else if v == b { 608 v, restore = v.isolatedWorkspace(b) 609 defer restore() 610 } 611 612 // TODO(kortschak): Improve the non-fast paths. 613 switch aU := aU.(type) { 614 case Vector: 615 if b.Len() == 1 { 616 // {n,1} x {1,1} 617 v.ScaleVec(b.AtVec(0), aU) 618 return 619 } 620 621 // {1,n} x {n,1} 622 if fast { 623 if rv, ok := aU.(*VecDense); ok { 624 amat := rv.mat 625 if v != aU { 626 v.checkOverlap(amat) 627 } 628 629 if amat.Inc == 1 && bmat.Inc == 1 { 630 // Fast path for a common case. 631 v.setVec(0, f64.DotUnitary(amat.Data, bmat.Data)) 632 return 633 } 634 v.setVec(0, f64.DotInc(amat.Data, bmat.Data, 635 uintptr(c), uintptr(amat.Inc), uintptr(bmat.Inc), 0, 0)) 636 return 637 } 638 } 639 var sum float64 640 for i := 0; i < c; i++ { 641 sum += aU.AtVec(i) * b.AtVec(i) 642 } 643 v.setVec(0, sum) 644 return 645 case *SymBandDense: 646 if fast { 647 aU.checkOverlap(v.asGeneral()) 648 blas64.Sbmv(1, aU.mat, bmat, 0, v.mat) 649 return 650 } 651 case *SymDense: 652 if fast { 653 aU.checkOverlap(v.asGeneral()) 654 blas64.Symv(1, aU.mat, bmat, 0, v.mat) 655 return 656 } 657 case *TriDense: 658 if fast { 659 v.CopyVec(b) 660 aU.checkOverlap(v.asGeneral()) 661 ta := blas.NoTrans 662 if trans { 663 ta = blas.Trans 664 } 665 blas64.Trmv(ta, aU.mat, v.mat) 666 return 667 } 668 case *Dense: 669 if fast { 670 aU.checkOverlap(v.asGeneral()) 671 t := blas.NoTrans 672 if trans { 673 t = blas.Trans 674 } 675 blas64.Gemv(t, 1, aU.mat, bmat, 0, v.mat) 676 return 677 } 678 default: 679 if fast { 680 for i := 0; i < r; i++ { 681 var f float64 682 for j := 0; j < c; j++ { 683 f += a.At(i, j) * bmat.Data[j*bmat.Inc] 684 } 685 v.setVec(i, f) 686 } 687 return 688 } 689 } 690 691 for i := 0; i < r; i++ { 692 var f float64 693 for j := 0; j < c; j++ { 694 f += a.At(i, j) * b.AtVec(j) 695 } 696 v.setVec(i, f) 697 } 698 } 699 700 // ReuseAsVec changes the receiver if it IsEmpty() to be of size n×1. 701 // 702 // ReuseAsVec re-uses the backing data slice if it has sufficient capacity, 703 // otherwise a new slice is allocated. The backing data is zero on return. 704 // 705 // ReuseAsVec panics if the receiver is not empty, and panics if 706 // the input size is less than one. To empty the receiver for re-use, 707 // Reset should be used. 708 func (v *VecDense) ReuseAsVec(n int) { 709 if n <= 0 { 710 if n == 0 { 711 panic(ErrZeroLength) 712 } 713 panic(ErrNegativeDimension) 714 } 715 if !v.IsEmpty() { 716 panic(ErrReuseNonEmpty) 717 } 718 v.reuseAsZeroed(n) 719 } 720 721 // reuseAsNonZeroed resizes an empty vector to a r×1 vector, 722 // or checks that a non-empty matrix is r×1. 723 func (v *VecDense) reuseAsNonZeroed(r int) { 724 // reuseAsNonZeroed must be kept in sync with reuseAsZeroed. 725 if r == 0 { 726 panic(ErrZeroLength) 727 } 728 if v.IsEmpty() { 729 v.mat = blas64.Vector{ 730 N: r, 731 Inc: 1, 732 Data: use(v.mat.Data, r), 733 } 734 return 735 } 736 if r != v.mat.N { 737 panic(ErrShape) 738 } 739 } 740 741 // reuseAsZeroed resizes an empty vector to a r×1 vector, 742 // or checks that a non-empty matrix is r×1. 743 func (v *VecDense) reuseAsZeroed(r int) { 744 // reuseAsZeroed must be kept in sync with reuseAsNonZeroed. 745 if r == 0 { 746 panic(ErrZeroLength) 747 } 748 if v.IsEmpty() { 749 v.mat = blas64.Vector{ 750 N: r, 751 Inc: 1, 752 Data: useZeroed(v.mat.Data, r), 753 } 754 return 755 } 756 if r != v.mat.N { 757 panic(ErrShape) 758 } 759 v.Zero() 760 } 761 762 // IsEmpty returns whether the receiver is empty. Empty matrices can be the 763 // receiver for size-restricted operations. The receiver can be emptied using 764 // Reset. 765 func (v *VecDense) IsEmpty() bool { 766 // It must be the case that v.Dims() returns 767 // zeros in this case. See comment in Reset(). 768 return v.mat.Inc == 0 769 } 770 771 func (v *VecDense) isolatedWorkspace(a Vector) (n *VecDense, restore func()) { 772 l := a.Len() 773 if l == 0 { 774 panic(ErrZeroLength) 775 } 776 n = getVecDenseWorkspace(l, false) 777 return n, func() { 778 v.CopyVec(n) 779 putVecDenseWorkspace(n) 780 } 781 } 782 783 // asDense returns a Dense representation of the receiver with the same 784 // underlying data. 785 func (v *VecDense) asDense() *Dense { 786 return &Dense{ 787 mat: v.asGeneral(), 788 capRows: v.mat.N, 789 capCols: 1, 790 } 791 } 792 793 // asGeneral returns a blas64.General representation of the receiver with the 794 // same underlying data. 795 func (v *VecDense) asGeneral() blas64.General { 796 return blas64.General{ 797 Rows: v.mat.N, 798 Cols: 1, 799 Stride: v.mat.Inc, 800 Data: v.mat.Data, 801 } 802 } 803 804 // ColViewOf reflects the column j of the RawMatrixer m, into the receiver 805 // backed by the same underlying data. The receiver must either be empty 806 // have length equal to the number of rows of m. 807 func (v *VecDense) ColViewOf(m RawMatrixer, j int) { 808 rm := m.RawMatrix() 809 810 if j >= rm.Cols || j < 0 { 811 panic(ErrColAccess) 812 } 813 if !v.IsEmpty() && v.mat.N != rm.Rows { 814 panic(ErrShape) 815 } 816 817 v.mat.Inc = rm.Stride 818 v.mat.Data = rm.Data[j : (rm.Rows-1)*rm.Stride+j+1] 819 v.mat.N = rm.Rows 820 } 821 822 // RowViewOf reflects the row i of the RawMatrixer m, into the receiver 823 // backed by the same underlying data. The receiver must either be 824 // empty or have length equal to the number of columns of m. 825 func (v *VecDense) RowViewOf(m RawMatrixer, i int) { 826 rm := m.RawMatrix() 827 828 if i >= rm.Rows || i < 0 { 829 panic(ErrRowAccess) 830 } 831 if !v.IsEmpty() && v.mat.N != rm.Cols { 832 panic(ErrShape) 833 } 834 835 v.mat.Inc = 1 836 v.mat.Data = rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] 837 v.mat.N = rm.Cols 838 }