gitee.com/quant1x/gox@v1.7.6/num/num32/vek_amd64.go (about) 1 package num32 2 3 import ( 4 "gitee.com/quant1x/gox/num" 5 "gitee.com/quant1x/gox/num/internal/functions" 6 "github.com/chewxy/math32" 7 "golang.org/x/exp/constraints" 8 "golang.org/x/exp/slices" 9 "unsafe" 10 ) 11 12 // Arithmetic 13 14 // Add returns the result of adding two slices element-wise. 15 func Add(x, y []float32) []float32 { 16 x = slices.Clone(x) 17 Add_Inplace(x, y) 18 return x 19 } 20 21 // Add_Inplace adds a slice element-wise to the first slice, inplace. 22 func Add_Inplace(x, y []float32) { 23 checkEqualLength(x, y) 24 checkOverlap(x, y) 25 if functions.UseAVX2 { 26 functions.Add_AVX2_F32(x, y) 27 } else { 28 functions.Add_Go(x, y) 29 } 30 } 31 32 // Add_Into adds two slices element-wise and stores the result in the destination slice. 33 func Add_Into(dst, x, y []float32) []float32 { 34 dst = checkCapacity(dst, x) 35 checkOverlap(dst, x) 36 copy(dst, x) 37 Add_Inplace(dst, y) 38 return dst 39 } 40 41 // Sub returns the result of subtracting two slices element-wise. 42 func Sub(x, y []float32) []float32 { 43 x = slices.Clone(x) 44 Sub_Inplace(x, y) 45 return x 46 } 47 48 // Sub_Inplace subtracts a slice element-wise from the first slice, inplace. 49 func Sub_Inplace(x, y []float32) { 50 checkEqualLength(x, y) 51 checkOverlap(x, y) 52 if functions.UseAVX2 { 53 functions.Sub_AVX2_F32(x, y) 54 } else { 55 functions.Sub_Go(x, y) 56 } 57 } 58 59 // Sub_Into subtracts two slices element-wise and stores the result in the destination slice. 60 func Sub_Into(dst, x, y []float32) []float32 { 61 dst = checkCapacity(dst, x) 62 checkOverlap(dst, x) 63 copy(dst, x) 64 Sub_Inplace(dst, y) 65 return dst 66 } 67 68 // Mul returns the result of multiplying two slices element-wise. 69 func Mul(x, y []float32) []float32 { 70 x = slices.Clone(x) 71 Mul_Inplace(x, y) 72 return x 73 } 74 75 // Mul_Inplace multiplies the first slice element-wise by the second, inplace. 76 func Mul_Inplace(x, y []float32) { 77 checkEqualLength(x, y) 78 checkOverlap(x, y) 79 if functions.UseAVX2 { 80 functions.Mul_AVX2_F32(x, y) 81 } else { 82 functions.Mul_Go(x, y) 83 } 84 } 85 86 // Mul_Into multiplies two slices element-wise and stores the result in the destination slice. 87 func Mul_Into(dst, x, y []float32) []float32 { 88 dst = checkCapacity(dst, x) 89 checkOverlap(dst, x) 90 copy(dst, x) 91 Mul_Inplace(dst, y) 92 return dst 93 } 94 95 // Div returns the result of dividing two slices element-wise. 96 func Div(x, y []float32) []float32 { 97 x = slices.Clone(x) 98 Div_Inplace(x, y) 99 return x 100 } 101 102 // Div_Inplace divides the first slice element-wise by the second, inplace. 103 func Div_Inplace(x, y []float32) { 104 checkEqualLength(x, y) 105 checkOverlap(x, y) 106 if functions.UseAVX2 { 107 functions.Div_AVX2_F32(x, y) 108 } else { 109 functions.Div_Go(x, y) 110 } 111 } 112 113 // Div_Into divides two slices element-wise and stores the result in the destination slice. 114 func Div_Into(dst, x, y []float32) []float32 { 115 dst = checkCapacity(dst, x) 116 checkOverlap(dst, x) 117 copy(dst, x) 118 Div_Inplace(dst, y) 119 return dst 120 } 121 122 // AddNumber returns the result of adding a number to each slice element. 123 func AddNumber(x []float32, a float32) []float32 { 124 x = slices.Clone(x) 125 AddNumber_Inplace(x, a) 126 return x 127 } 128 129 // AddNumber_Inplace adds a number to each slice element, inplace. 130 func AddNumber_Inplace(x []float32, a float32) { 131 if functions.UseAVX2 { 132 functions.AddNumber_AVX2_F32(x, a) 133 } else { 134 functions.AddNumber_Go(x, a) 135 } 136 } 137 138 // AddNumber_Into adds a number to each slice element and stores the result in the 139 // destination slice. 140 func AddNumber_Into(dst, x []float32, a float32) []float32 { 141 dst = checkCapacity(dst, x) 142 checkOverlap(dst, x) 143 copy(dst, x) 144 AddNumber_Inplace(dst, a) 145 return dst 146 } 147 148 // SubNumber returns the result of subtracting a number from each slice element. 149 func SubNumber(x []float32, a float32) []float32 { 150 x = slices.Clone(x) 151 SubNumber_Inplace(x, a) 152 return x 153 } 154 155 // SubNumber_Inplace subtracts a number from each slice element, inplace. 156 func SubNumber_Inplace(x []float32, a float32) { 157 if functions.UseAVX2 { 158 functions.SubNumber_AVX2_F32(x, a) 159 } else { 160 functions.SubNumber_Go(x, a) 161 } 162 } 163 164 // SubNumber_Into subtracts a number from each slice element and stores the result in the 165 // destination slice. 166 func SubNumber_Into(dst, x []float32, a float32) []float32 { 167 dst = checkCapacity(dst, x) 168 checkOverlap(dst, x) 169 copy(dst, x) 170 SubNumber_Inplace(dst, a) 171 return dst 172 } 173 174 // MulNumber returns the result of multiplying each slice element by a number. 175 func MulNumber(x []float32, a float32) []float32 { 176 x = slices.Clone(x) 177 MulNumber_Inplace(x, a) 178 return x 179 } 180 181 // MulNumber_Inplace multiplies each slice element by a number, inplace. 182 func MulNumber_Inplace(x []float32, a float32) { 183 if functions.UseAVX2 { 184 functions.MulNumber_AVX2_F32(x, a) 185 } else { 186 functions.MulNumber_Go(x, a) 187 } 188 } 189 190 // MulNumber_Into multiplies each slice element by a number and stores the result in the 191 // destination slice. 192 func MulNumber_Into(dst, x []float32, a float32) []float32 { 193 dst = checkCapacity(dst, x) 194 checkOverlap(dst, x) 195 copy(dst, x) 196 MulNumber_Inplace(dst, a) 197 return dst 198 } 199 200 // DivNumber returns the result of dividing each slice element by a number. 201 func DivNumber(x []float32, a float32) []float32 { 202 x = slices.Clone(x) 203 DivNumber_Inplace(x, a) 204 return x 205 } 206 207 // DivNumber_Inplace divides each slice element by a number, inplace. 208 func DivNumber_Inplace(x []float32, a float32) { 209 if functions.UseAVX2 { 210 functions.DivNumber_AVX2_F32(x, a) 211 } else { 212 functions.DivNumber_Go(x, a) 213 } 214 } 215 216 // DivNumber_Into divides each slice element by a number and stores the result in the 217 // destination slice. 218 func DivNumber_Into(dst, x []float32, a float32) []float32 { 219 dst = checkCapacity(dst, x) 220 checkOverlap(dst, x) 221 copy(dst, x) 222 DivNumber_Inplace(dst, a) 223 return dst 224 } 225 226 // Abs returns the absolute value of each slice element. 227 func Abs(x []float32) []float32 { 228 x = slices.Clone(x) 229 Abs_Inplace(x) 230 return x 231 } 232 233 // Abs_Inplace computes the absolute value of each slice element, inplace. 234 func Abs_Inplace(x []float32) { 235 if functions.UseAVX2 { 236 functions.Abs_AVX2_F32(x) 237 } else { 238 functions.Abs_Go_F32(x) 239 } 240 } 241 242 // Abs_Into computes the absolute value of each slice element and stores the result in the 243 // destination slice. 244 func Abs_Into(dst, x []float32) []float32 { 245 dst = checkCapacity(dst, x) 246 checkOverlap(dst, x) 247 copy(dst, x) 248 Abs_Inplace(dst) 249 return dst 250 } 251 252 // Neg returns the additive inverse of each slice element. 253 func Neg(x []float32) []float32 { 254 x = slices.Clone(x) 255 Neg_Inplace(x) 256 return x 257 } 258 259 // Neg_Inplace computes the additive inverse of each slice element, inplace. 260 func Neg_Inplace(x []float32) { 261 if functions.UseAVX2 { 262 functions.Neg_AVX2_F32(x) 263 } else { 264 functions.Neg_Go(x) 265 } 266 } 267 268 // Neg_Into computes the additive inverse of each slice element and stores the result in the 269 // destination slice. 270 func Neg_Into(dst, x []float32) []float32 { 271 dst = checkCapacity(dst, x) 272 checkOverlap(dst, x) 273 copy(dst, x) 274 Neg_Inplace(dst) 275 return dst 276 } 277 278 // Inv returns the multiplicative inverse of each slice element. 279 func Inv(x []float32) []float32 { 280 x = slices.Clone(x) 281 Inv_Inplace(x) 282 return x 283 } 284 285 // Inv_Inplace computes the multiplicative inverse of each slice element, inplace. 286 func Inv_Inplace(x []float32) { 287 if functions.UseAVX2 { 288 functions.Inv_AVX2_F32(x) 289 } else { 290 functions.Inv_Go(x) 291 } 292 } 293 294 // Inv_Into computes the multiplicative inverse of each slice element and stores the result 295 // in the destination slice. 296 func Inv_Into(dst, x []float32) []float32 { 297 dst = checkCapacity(dst, x) 298 checkOverlap(dst, x) 299 copy(dst, x) 300 Inv_Inplace(dst) 301 return dst 302 } 303 304 // Aggregates 305 306 // Sum returns the sum of all elements in a slice. 307 func Sum(x []float32) float32 { 308 if functions.UseAVX2 { 309 return functions.Sum_AVX2_F32(x) 310 } else { 311 return functions.Sum_Go(x) 312 } 313 } 314 315 // CumSum returns the cumulative sum of a slice. The element at index i equals the sum of x[:i+1]. 316 func CumSum(x []float32) []float32 { 317 x = slices.Clone(x) 318 CumSum_Inplace(x) 319 return x 320 } 321 322 // CumSum_Inplace computes the cumulative sum of a slice, inplace. The new element at index i 323 // equals the sum of x[:i+1]. 324 func CumSum_Inplace(x []float32) { 325 if functions.UseAVX2 { 326 functions.CumSum_AVX2_F32(x) 327 } else { 328 functions.CumSum_Go(x) 329 } 330 } 331 332 // CumSum_Into computes the cumulative sum of a slice and stores the result in the destination 333 // slice. The element at index i equals the sum of x[:i+1]. 334 func CumSum_Into(dst, x []float32) []float32 { 335 dst = checkCapacity(dst, x) 336 checkOverlap(dst, x) 337 copy(dst, x) 338 CumSum_Inplace(dst) 339 return dst 340 } 341 342 // Prod returns the product of all elements in a slice. 343 func Prod(x []float32) float32 { 344 if functions.UseAVX2 { 345 return functions.Prod_AVX2_F32(x) 346 } else { 347 return functions.Prod_Go(x) 348 } 349 } 350 351 // CumProd returns the cumulative product of a slice. The element at index i equals the product 352 // of x[:i+1]. 353 func CumProd(x []float32) []float32 { 354 x = slices.Clone(x) 355 CumProd_Inplace(x) 356 return x 357 } 358 359 // CumProd_Inplace computes the cumulative product of a slice, inplace. The new element at index i 360 // equals the product of x[:i+1]. 361 func CumProd_Inplace(x []float32) { 362 if functions.UseAVX2 { 363 functions.CumProd_AVX2_F32(x) 364 } else { 365 functions.CumProd_Go(x) 366 } 367 } 368 369 // CumProd_Into computes the cumulative product of a slice and stores the result in the destination 370 // slice. The element at index i equals the product of x[:i+1]. 371 func CumProd_Into(dst, x []float32) []float32 { 372 dst = checkCapacity(dst, x) 373 checkOverlap(dst, x) 374 copy(dst, x) 375 CumProd_Inplace(dst) 376 return dst 377 } 378 379 // Mean returns the arithmetic average of the slice elements. 380 func Mean(x []float32) float32 { 381 checkNotEmpty(x) 382 if functions.UseAVX2 { 383 return functions.Mean_AVX2_F32(x) 384 } else { 385 return functions.Mean_Go(x) 386 } 387 } 388 389 // Median returns the median value of the slice elements. 390 func Median(x []float32) float32 { 391 checkNotEmpty(x) 392 if functions.UseAVX2 { 393 return functions.Median_AVX2_F32(x) 394 } else { 395 return functions.Median_Go(x) 396 } 397 } 398 399 // Quantile returns the q-th quantile of the slice elements. The value of q should be between 400 // 0 and 1 (inclusive). 401 func Quantile(x []float32, q float32) float32 { 402 if q < 0 || q > 1 { 403 panic("value of q should be between 0 and 1") 404 } 405 checkNotEmpty(x) 406 if functions.UseAVX2 { 407 return functions.Quantile_AVX2_F32(x, q) 408 } else { 409 return functions.Quantile_Go(x, q) 410 } 411 } 412 413 // Distance 414 415 // Dot returns the dot product of two vectors. 416 func Dot(x, y []float32) float32 { 417 checkNotEmpty(x) 418 checkEqualLength(x, y) 419 if functions.UseAVX2 { 420 return functions.Dot_AVX2_F32(x, y) 421 } else { 422 return functions.Dot_Go(x, y) 423 } 424 } 425 426 // Norm returns the Euclidean norm of a vector, i.e. its length. 427 func Norm(x []float32) float32 { 428 checkNotEmpty(x) 429 if functions.UseAVX2 { 430 return functions.Norm_AVX2_F32(x) 431 } else { 432 return functions.Norm_Go_F32(x) 433 } 434 } 435 436 // Distance returns the Euclidean distance between two vectors. 437 func Distance(x, y []float32) float32 { 438 checkNotEmpty(x) 439 checkEqualLength(x, y) 440 if functions.UseAVX2 { 441 return functions.Distance_AVX2_F32(x, y) 442 } else { 443 return functions.Distance_Go_F32(x, y) 444 } 445 } 446 447 // ManhattanNorm returns the sum of absolute values of the slice elements. 448 func ManhattanNorm(x []float32) float32 { 449 checkNotEmpty(x) 450 if functions.UseAVX2 { 451 return functions.ManhattanNorm_AVX2_F32(x) 452 } else { 453 return functions.ManhattanNorm_Go_F32(x) 454 } 455 } 456 457 // ManhattanDistance returns the sum of element-wise absolute differences between two slices. 458 func ManhattanDistance(x, y []float32) float32 { 459 checkNotEmpty(x) 460 checkEqualLength(x, y) 461 if functions.UseAVX2 { 462 return functions.ManhattanDistance_AVX2_F32(x, y) 463 } else { 464 return functions.ManhattanDistance_Go_F32(x, y) 465 } 466 } 467 468 // CosineSimilarity returns the cosine similarity of two vectors. 469 func CosineSimilarity(x, y []float32) float32 { 470 checkNotEmpty(x) 471 checkEqualLength(x, y) 472 if functions.UseAVX2 { 473 return functions.CosineSimilarity_AVX2_F32(x, y) 474 } else { 475 return functions.CosineSimilarity_Go_F32(x, y) 476 } 477 } 478 479 // Matrices 480 481 func checkDimensions[T constraints.Float](x, y []T, n int) (int, int) { 482 m := len(x) / n 483 p := len(y) / n 484 if m*n < len(x) || n*p < len(y) { 485 panic("slice lengths must be multiple of n") 486 } 487 return m, p 488 } 489 490 // MatMul multiplies an m-by-n and n-by-p matrix and returns the resulting m-by-p matrix. 491 // The matrices should be in row-major order. To multiply a matrix and a vector pass an 492 // n-by-1 matrix. 493 func MatMul(x, y []float32, n int) []float32 { 494 m, p := checkDimensions(x, y, n) 495 dst := make([]float32, m*p) 496 if functions.UseAVX2 { 497 functions.MatMul_Parallel_AVX2_F32(dst, x, y, m, n, p) 498 } else { 499 functions.MatMul_Parallel_Go(dst, x, y, m, n, p) 500 } 501 return dst 502 } 503 504 // MatMul_Into multiplies an m-by-n and n-by-p matrix and stores the resulting m-by-p matrix 505 // in the destination slice. The matrices should be in row-major order. To multiply a matrix 506 // and a vector pass an n-by-1 matrix. 507 func MatMul_Into(dst, x, y []float32, n int) []float32 { 508 m, p := checkDimensions(x, y, n) 509 if cap(dst) < m*p { 510 panic("destination slice not large enough to hold result") 511 } 512 Zeros_Into(dst, m*p) 513 if functions.UseAVX2 { 514 functions.MatMul_Parallel_AVX2_F32(dst, x, y, m, n, p) 515 } else { 516 functions.MatMul_Parallel_Go(dst, x, y, m, n, p) 517 } 518 return dst[:m*p] 519 } 520 521 // Mat4Mul multiplies two 4-by-4 matrices and returns the resulting 4-by-4 matrix. The matrices 522 // should be in row-major order. To multiply a matrix and a vector batch them into groups of 4. 523 func Mat4Mul(x, y []float32) []float32 { 524 var dst [16]float32 525 return Mat4Mul_Into(dst[:], x, y) 526 } 527 528 // Mat4Mul_Into multiplies two 4-by-4 matrices and stores the resulting 4-by-4 matrix in the 529 // destination slice. The matrices should be in row-major order. To multiply a matrix and a vector 530 // batch them into groups of 4. 531 func Mat4Mul_Into(dst, x, y []float32) []float32 { 532 // Note: skipping overlap check due to overhead 533 if cap(dst) < 16 || len(x) != 16 || len(y) != 16 { 534 panic("slices must be length 16 (4 by 4)") 535 } 536 if functions.UseAVX2 { 537 functions.Mat4Mul_AVX2_F32(dst, x, y) 538 } else { 539 functions.Mat4Mul_Go(dst, x, y) 540 } 541 return dst[:16] 542 } 543 544 // Special 545 546 // Sqrt returns the square root of each slice element. 547 func Sqrt(x []float32) []float32 { 548 x = slices.Clone(x) 549 Sqrt_Inplace(x) 550 return x 551 } 552 553 // Sqrt_Inplace computes the square root of each slice element, inplace. 554 func Sqrt_Inplace(x []float32) { 555 if functions.UseAVX2 { 556 functions.Sqrt_AVX2_F32(x) 557 } else { 558 functions.Sqrt_Go_F32(x) 559 } 560 } 561 562 // Sqrt_Into computes the square root of each slice element and stores the result in the 563 // destination slice. 564 func Sqrt_Into(dst, x []float32) []float32 { 565 dst = checkCapacity(dst, x) 566 checkOverlap(dst, x) 567 copy(dst, x) 568 Sqrt_Inplace(dst) 569 return dst 570 } 571 572 // Round returns the result of rounding each slice element to the nearest integer value. 573 func Round(x []float32) []float32 { 574 x = slices.Clone(x) 575 Round_Inplace(x) 576 return x 577 } 578 579 // Round_Inplace rounds each slice element to the nearest integer value, inplace. 580 func Round_Inplace(x []float32) { 581 if functions.UseAVX2 { 582 functions.Round_AVX2_F32(x) 583 } else { 584 functions.Round_Go_F32(x) 585 } 586 } 587 588 // Round_Into rounds each slice element to the nearest integer value and stores the result 589 // in the destination slice. 590 func Round_Into(dst, x []float32) []float32 { 591 dst = checkCapacity(dst, x) 592 checkOverlap(dst, x) 593 copy(dst, x) 594 Round_Inplace(dst) 595 return dst 596 } 597 598 // Floor returns the result of rounding each slice element to the nearest lesser integer value. 599 func Floor(x []float32) []float32 { 600 x = slices.Clone(x) 601 Floor_Inplace(x) 602 return x 603 } 604 605 // Floor_Inplace rounds each slice element to the nearest lesser integer value, inplace. 606 func Floor_Inplace(x []float32) { 607 if functions.UseAVX2 { 608 functions.Floor_AVX2_F32(x) 609 } else { 610 functions.Floor_Go_F32(x) 611 } 612 } 613 614 // Floor_Into rounds each slice element to the nearest lesser integer value and stores the result 615 // in the destination slice. 616 func Floor_Into(dst, x []float32) []float32 { 617 dst = checkCapacity(dst, x) 618 checkOverlap(dst, x) 619 copy(dst, x) 620 Floor_Inplace(dst) 621 return dst 622 } 623 624 // Ceil returns the result of rounding each slice element to the nearest greater integer value. 625 func Ceil(x []float32) []float32 { 626 x = slices.Clone(x) 627 Ceil_Inplace(x) 628 return x 629 } 630 631 // Ceil_Inplace rounds each slice element to the nearest greater integer value, inplace. 632 func Ceil_Inplace(x []float32) { 633 if functions.UseAVX2 { 634 functions.Ceil_AVX2_F32(x) 635 } else { 636 functions.Ceil_Go_F32(x) 637 } 638 } 639 640 // Ceil_Into rounds each slice element to the nearest greater integer value and stores the result 641 // in the destination slice. 642 func Ceil_Into(dst, x []float32) []float32 { 643 dst = checkCapacity(dst, x) 644 checkOverlap(dst, x) 645 copy(dst, x) 646 Ceil_Inplace(dst) 647 return dst 648 } 649 650 // Pow returns the elements in the first slice raised to the power in the second. 651 func Pow(x, y []float32) []float32 { 652 x = slices.Clone(x) 653 Pow_Inplace(x, y) 654 return x 655 } 656 657 // Pow_Inplace raises the elements in the first slice to the power in the second, inplace. 658 func Pow_Inplace(x, y []float32) { 659 checkEqualLength(x, y) 660 checkOverlap(x, y) 661 if functions.UseAVX2 { 662 functions.Pow_AVX2_F32(x, y) 663 } else { 664 functions.Pow_Go_F32(x, y) 665 } 666 } 667 668 // Pow_Into raises the elements in the first slice to the power in the second and stores the 669 // result in the destination slice. 670 func Pow_Into(dst, x, y []float32) []float32 { 671 dst = checkCapacity(dst, x) 672 checkOverlap(dst, x) 673 copy(dst, x) 674 Pow_Inplace(dst, y) 675 return dst 676 } 677 678 // Special (32-bit only) 679 680 // Sin returns the sine of each element. 681 func Sin(x []float32) []float32 { 682 x = slices.Clone(x) 683 Sin_Inplace(x) 684 return x 685 } 686 687 // Sin_Inplace computes the sine of each element, inplace. 688 func Sin_Inplace(x []float32) { 689 if functions.UseAVX2 { 690 functions.Sin_AVX2_F32(x) 691 } else { 692 functions.Sin_Go_F32(x) 693 } 694 } 695 696 // Sin_Into stores the sine of each element in the destination slice. 697 func Sin_Into(dst, x []float32) []float32 { 698 dst = checkCapacity(dst, x) 699 checkOverlap(dst, x) 700 copy(dst, x) 701 Sin_Inplace(dst) 702 return dst 703 } 704 705 // Cos returns the cosine of each element. 706 func Cos(x []float32) []float32 { 707 x = slices.Clone(x) 708 Cos_Inplace(x) 709 return x 710 } 711 712 // Cos_Inplace computes the cosine of each element, inplace. 713 func Cos_Inplace(x []float32) { 714 if functions.UseAVX2 { 715 functions.Cos_AVX2_F32(x) 716 } else { 717 functions.Cos_Go_F32(x) 718 } 719 } 720 721 // Cos_Into stores the cosine of each element in the destination slice. 722 func Cos_Into(dst, x []float32) []float32 { 723 dst = checkCapacity(dst, x) 724 checkOverlap(dst, x) 725 copy(dst, x) 726 Cos_Inplace(dst) 727 return dst 728 } 729 730 // SinCos_Into stores the sine and cosine of each element in the destination slices. Faster than 731 // calling Sin_Into and Cos_Into individually if both are needed. 732 func SinCos_Into(dstSin, dstCos, x []float32) { 733 dstSin = checkCapacity(dstSin, x) 734 dstCos = checkCapacity(dstCos, x) 735 checkOverlap(dstSin, x) 736 checkOverlap(dstCos, x) 737 if functions.UseAVX2 { 738 functions.SinCos_AVX2_F32(dstSin, dstCos, x) 739 } else { 740 functions.SinCos_Go_F32(dstSin, dstCos, x) 741 } 742 } 743 744 // Exp returns the exponential of each element. 745 func Exp(x []float32) []float32 { 746 x = slices.Clone(x) 747 Exp_Inplace(x) 748 return x 749 } 750 751 // Exp_Inplace computes the exponential of each element, inplace. 752 func Exp_Inplace(x []float32) { 753 if functions.UseAVX2 { 754 functions.Exp_AVX2_F32(x) 755 } else { 756 functions.Exp_Go_F32(x) 757 } 758 } 759 760 // Exp_Into stores the exponential of each element in the destination slice. 761 func Exp_Into(dst, x []float32) []float32 { 762 dst = checkCapacity(dst, x) 763 checkOverlap(dst, x) 764 copy(dst, x) 765 Exp_Inplace(dst) 766 return dst 767 } 768 769 // Log returns the natural logarithm of each element. 770 func Log(x []float32) []float32 { 771 x = slices.Clone(x) 772 Log_Inplace(x) 773 return x 774 } 775 776 // Log_Inplace computes the natural logarithm of each element, inplace. 777 func Log_Inplace(x []float32) { 778 if functions.UseAVX2 { 779 functions.Log_AVX2_F32(x) 780 } else { 781 functions.Log_Go_F32(x) 782 } 783 } 784 785 // Log_Into stores the natural logarithm of each element in the destination slice. 786 func Log_Into(dst, x []float32) []float32 { 787 dst = checkCapacity(dst, x) 788 checkOverlap(dst, x) 789 copy(dst, x) 790 Log_Inplace(dst) 791 return dst 792 } 793 794 // Log2 returns the base 2 logarithm of each element. 795 func Log2(x []float32) []float32 { 796 x = slices.Clone(x) 797 Log2_Inplace(x) 798 return x 799 } 800 801 // Log2_Inplace computes the base 2 logarithm of each element, inplace. 802 func Log2_Inplace(x []float32) { 803 if functions.UseAVX2 { 804 functions.Log2_AVX2_F32(x) 805 } else { 806 functions.Log2_Go_F32(x) 807 } 808 } 809 810 // Log2_Into stores the base 2 logarithm of each element in the destination slice. 811 func Log2_Into(dst, x []float32) []float32 { 812 dst = checkCapacity(dst, x) 813 checkOverlap(dst, x) 814 copy(dst, x) 815 Log2_Inplace(dst) 816 return dst 817 } 818 819 // Log10 returns the base 10 logarithm of each element. 820 func Log10(x []float32) []float32 { 821 x = slices.Clone(x) 822 Log10_Inplace(x) 823 return x 824 } 825 826 // Log10_Inplace computes the base 10 logarithm of each element, inplace. 827 func Log10_Inplace(x []float32) { 828 if functions.UseAVX2 { 829 functions.Log10_AVX2_F32(x) 830 } else { 831 functions.Log10_Go_F32(x) 832 } 833 } 834 835 // Log10_Into stores the base 10 logarithm of each element in the destination slice. 836 func Log10_Into(dst, x []float32) []float32 { 837 dst = checkCapacity(dst, x) 838 checkOverlap(dst, x) 839 copy(dst, x) 840 Log10_Inplace(dst) 841 return dst 842 } 843 844 // Comparison 845 846 // Min returns the minimum value of a slice. 847 func Min(x []float32) float32 { 848 checkNotEmpty(x) 849 if functions.UseAVX2 { 850 return functions.Min_AVX2_F32(x) 851 } else { 852 return functions.Min_Go(x) 853 } 854 } 855 856 // ArgMin returns the (first) index of the minimum value of a slice. 857 func ArgMin(x []float32) int { 858 checkNotEmpty(x) 859 if functions.UseAVX2 { 860 return functions.ArgMin_AVX2_F32(x) 861 } else { 862 return functions.ArgMin_Go(x) 863 } 864 } 865 866 // Minimum returns the element-wise minimum values between two slices. 867 func Minimum(x, y []float32) []float32 { 868 x = slices.Clone(x) 869 Minimum_Inplace(x, y) 870 return x 871 } 872 873 // Minimum_Inplace compares two slices element-wise and replaces the values in the first slice 874 // with the minimum value. 875 func Minimum_Inplace(x, y []float32) { 876 checkEqualLength(x, y) 877 checkOverlap(x, y) 878 if functions.UseAVX2 { 879 functions.Minimum_AVX2_F32(x, y) 880 } else { 881 functions.Minimum_Go(x, y) 882 } 883 } 884 885 // Minimum_Into compares two slices element-wise and stores the minimum values in the destination 886 // slice. 887 func Minimum_Into(dst, x, y []float32) []float32 { 888 dst = checkCapacity(dst, x) 889 checkOverlap(dst, x) 890 copy(dst, x) 891 Minimum_Inplace(dst, y) 892 return dst 893 } 894 895 // MinimumNumber returns the minimum of a number and each slice element. 896 func MinimumNumber(x []float32, a float32) []float32 { 897 x = slices.Clone(x) 898 MinimumNumber_Inplace(x, a) 899 return x 900 } 901 902 // MinimumNumber_Inplace compares a number to each slice element and replaces the values in the 903 // slice with the minimum value. 904 func MinimumNumber_Inplace(x []float32, a float32) { 905 if functions.UseAVX2 { 906 functions.MinimumNumber_AVX2_F32(x, a) 907 } else { 908 functions.MinimumNumber_Go(x, a) 909 } 910 } 911 912 // MinimumNumber_Into compares a number to each slice element and stores the minimum values in 913 // the destination slice. 914 func MinimumNumber_Into(dst, x []float32, a float32) []float32 { 915 dst = checkCapacity(dst, x) 916 checkOverlap(dst, x) 917 copy(dst, x) 918 MinimumNumber_Inplace(dst, a) 919 return dst 920 } 921 922 // Max returns the maximum value of a slice. 923 func Max(x []float32) float32 { 924 checkNotEmpty(x) 925 if functions.UseAVX2 { 926 return functions.Max_AVX2_F32(x) 927 } else { 928 return functions.Max_Go(x) 929 } 930 } 931 932 // ArgMax returns the (first) index of the maximum value of a slice. 933 func ArgMax(x []float32) int { 934 checkNotEmpty(x) 935 if functions.UseAVX2 { 936 return functions.ArgMax_AVX2_F32(x) 937 } else { 938 return functions.ArgMax_Go(x) 939 } 940 } 941 942 // Maximum returns the element-wise maximum values between two slices. 943 func Maximum(x, y []float32) []float32 { 944 x = slices.Clone(x) 945 Maximum_Inplace(x, y) 946 return x 947 } 948 949 // Maximum_Inplace compares two slices element-wise and replaces the values in the first slice 950 // with the maximum value. 951 func Maximum_Inplace(x, y []float32) { 952 checkEqualLength(x, y) 953 checkOverlap(x, y) 954 if functions.UseAVX2 { 955 functions.Maximum_AVX2_F32(x, y) 956 } else { 957 functions.Maximum_Go(x, y) 958 } 959 } 960 961 // Maximum_Into compares two slices element-wise and stores the maximum values in the destination 962 // slice. 963 func Maximum_Into(dst, x, y []float32) []float32 { 964 dst = checkCapacity(dst, x) 965 checkOverlap(dst, x) 966 copy(dst, x) 967 Maximum_Inplace(dst, y) 968 return dst 969 } 970 971 // MaximumNumber returns the maximum of a number and each slice element. 972 func MaximumNumber(x []float32, a float32) []float32 { 973 x = slices.Clone(x) 974 MaximumNumber_Inplace(x, a) 975 return x 976 } 977 978 // MaximumNumber_Inplace compares a number to each slice element and replaces the values in the 979 // slice with the maximum value. 980 func MaximumNumber_Inplace(x []float32, a float32) { 981 if functions.UseAVX2 { 982 functions.MaximumNumber_AVX2_F32(x, a) 983 } else { 984 functions.MaximumNumber_Go(x, a) 985 } 986 } 987 988 // MaximumNumber_Into compares a number to each slice element and stores the maximum values in 989 // the destination slice. 990 func MaximumNumber_Into(dst, x []float32, a float32) []float32 { 991 dst = checkCapacity(dst, x) 992 checkOverlap(dst, x) 993 copy(dst, x) 994 MaximumNumber_Inplace(dst, a) 995 return dst 996 } 997 998 // Find returns the index of the first slice element equal to the given value, or -1 if not found. 999 func Find(x []float32, a float32) int { 1000 if functions.UseAVX2 { 1001 idx := functions.Find_AVX2_F32(x, a) 1002 if idx == len(x) { 1003 return -1 1004 } 1005 return idx 1006 } else { 1007 return functions.Find_Go(x, a) 1008 } 1009 } 1010 1011 // Lt returns an element-wise "less than" comparison between two slices. 1012 func Lt(x, y []float32) []bool { 1013 dst := make([]bool, len(x)) 1014 return Lt_Into(dst, x, y) 1015 } 1016 1017 // Lt_Into stores an element-wise "less than" comparison between two slices in the destination 1018 // slice. 1019 func Lt_Into(dst []bool, x, y []float32) []bool { 1020 checkEqualLength(x, y) 1021 dst = checkCapacity(dst, x) 1022 if functions.UseAVX2 { 1023 functions.Lt_AVX2_F32(dst, x, y) 1024 } else { 1025 functions.Lt_Go(dst, x, y) 1026 } 1027 return dst 1028 } 1029 1030 // LtNumber returns an element-wise "less than" comparison between each slice element and 1031 // a number. 1032 func LtNumber(x []float32, a float32) []bool { 1033 dst := make([]bool, len(x)) 1034 return LtNumber_Into(dst, x, a) 1035 } 1036 1037 // LtNumber_Into stores an element-wise "less than" comparison between each slice element 1038 // and a number in the destination slice. 1039 func LtNumber_Into(dst []bool, x []float32, a float32) []bool { 1040 dst = checkCapacity(dst, x) 1041 if functions.UseAVX2 { 1042 functions.LtNumber_AVX2_F32(dst, x, a) 1043 } else { 1044 functions.LtNumber_Go(dst, x, a) 1045 } 1046 return dst 1047 } 1048 1049 // Lte returns an element-wise "less than or equal" comparison between two slices. 1050 func Lte(x, y []float32) []bool { 1051 dst := make([]bool, len(x)) 1052 return Lte_Into(dst, x, y) 1053 } 1054 1055 // Lte_Into stores an element-wise "less than or equal" comparison between two slices in the 1056 // destination slice. 1057 func Lte_Into(dst []bool, x, y []float32) []bool { 1058 checkEqualLength(x, y) 1059 dst = checkCapacity(dst, x) 1060 if functions.UseAVX2 { 1061 functions.Lte_AVX2_F32(dst, x, y) 1062 } else { 1063 functions.Lte_Go(dst, x, y) 1064 } 1065 return dst 1066 } 1067 1068 // LteNumber returns an element-wise "less than or equal" comparison between each slice element 1069 // and a number. 1070 func LteNumber(x []float32, a float32) []bool { 1071 dst := make([]bool, len(x)) 1072 return LteNumber_Into(dst, x, a) 1073 } 1074 1075 // LteNumber_Into stores an element-wise "less than or equal" comparison between each slice 1076 // element and a number in the destination slice. 1077 func LteNumber_Into(dst []bool, x []float32, a float32) []bool { 1078 dst = checkCapacity(dst, x) 1079 if functions.UseAVX2 { 1080 functions.LteNumber_AVX2_F32(dst, x, a) 1081 } else { 1082 functions.LteNumber_Go(dst, x, a) 1083 } 1084 return dst 1085 } 1086 1087 // Gt returns an element-wise "greater than" comparison between two slices. 1088 func Gt(x, y []float32) []bool { 1089 dst := make([]bool, len(x)) 1090 return Gt_Into(dst, x, y) 1091 } 1092 1093 // Gt_Into stores an element-wise "greater than" comparison between two slices in the destination 1094 // slice. 1095 func Gt_Into(dst []bool, x, y []float32) []bool { 1096 checkEqualLength(x, y) 1097 dst = checkCapacity(dst, x) 1098 if functions.UseAVX2 { 1099 functions.Gt_AVX2_F32(dst, x, y) 1100 } else { 1101 functions.Gt_Go(dst, x, y) 1102 } 1103 return dst 1104 } 1105 1106 // GtNumber returns an element-wise "greater than" comparison between each slice element and 1107 // a number. 1108 func GtNumber(x []float32, a float32) []bool { 1109 dst := make([]bool, len(x)) 1110 return GtNumber_Into(dst, x, a) 1111 } 1112 1113 // GtNumber_Into stores an element-wise "greater than" comparison between each slice element and 1114 // a number in the destination slice. 1115 func GtNumber_Into(dst []bool, x []float32, a float32) []bool { 1116 dst = checkCapacity(dst, x) 1117 if functions.UseAVX2 { 1118 functions.GtNumber_AVX2_F32(dst, x, a) 1119 } else { 1120 functions.GtNumber_Go(dst, x, a) 1121 } 1122 return dst 1123 } 1124 1125 // Gte returns an element-wise "greater than or equal" comparison between two slices. 1126 func Gte(x, y []float32) []bool { 1127 dst := make([]bool, len(x)) 1128 return Gte_Into(dst, x, y) 1129 } 1130 1131 // Gte_Into stores an element-wise "greater than or equal" comparison between two slices in the 1132 // destination slice. 1133 func Gte_Into(dst []bool, x, y []float32) []bool { 1134 checkEqualLength(x, y) 1135 dst = checkCapacity(dst, x) 1136 if functions.UseAVX2 { 1137 functions.Gte_AVX2_F32(dst, x, y) 1138 } else { 1139 functions.Gte_Go(dst, x, y) 1140 } 1141 return dst 1142 } 1143 1144 // GteNumber returns an element-wise "greater than or equal" comparison between each slice element 1145 // and a number. 1146 func GteNumber(x []float32, a float32) []bool { 1147 dst := make([]bool, len(x)) 1148 return GteNumber_Into(dst, x, a) 1149 } 1150 1151 // GteNumber_Into stores an element-wise "greater than or equal" comparison between each slice 1152 // element and a number in the destination slice. 1153 func GteNumber_Into(dst []bool, x []float32, a float32) []bool { 1154 dst = checkCapacity(dst, x) 1155 if functions.UseAVX2 { 1156 functions.GteNumber_AVX2_F32(dst, x, a) 1157 } else { 1158 functions.GteNumber_Go(dst, x, a) 1159 } 1160 return dst 1161 } 1162 1163 // Eq returns an element-wise equality comparison between two slices. 1164 func Eq(x, y []float32) []bool { 1165 dst := make([]bool, len(x)) 1166 return Eq_Into(dst, x, y) 1167 } 1168 1169 // Eq_Into stores an element-wise equality comparison between two slices in the destination 1170 // slice. 1171 func Eq_Into(dst []bool, x, y []float32) []bool { 1172 checkEqualLength(x, y) 1173 dst = checkCapacity(dst, x) 1174 if functions.UseAVX2 { 1175 functions.Eq_AVX2_F32(dst, x, y) 1176 } else { 1177 functions.Eq_Go(dst, x, y) 1178 } 1179 return dst 1180 } 1181 1182 // EqNumber returns an element-wise equality comparison between each slice element and a number. 1183 func EqNumber(x []float32, a float32) []bool { 1184 dst := make([]bool, len(x)) 1185 return EqNumber_Into(dst, x, a) 1186 } 1187 1188 // EqNumber_Into stores an element-wise equality comparison between each slice element and a 1189 // number in the destination slice. 1190 func EqNumber_Into(dst []bool, x []float32, a float32) []bool { 1191 dst = checkCapacity(dst, x) 1192 if functions.UseAVX2 { 1193 functions.EqNumber_AVX2_F32(dst, x, a) 1194 } else { 1195 functions.EqNumber_Go(dst, x, a) 1196 } 1197 return dst 1198 } 1199 1200 // Neq returns an element-wise "not equal" comparison between two slices. 1201 func Neq(x, y []float32) []bool { 1202 dst := make([]bool, len(x)) 1203 return Neq_Into(dst, x, y) 1204 } 1205 1206 // Neq_Into stores an element-wise "not equal" comparison between two slices in the destination 1207 // slice. 1208 func Neq_Into(dst []bool, x, y []float32) []bool { 1209 checkEqualLength(x, y) 1210 dst = checkCapacity(dst, x) 1211 if functions.UseAVX2 { 1212 functions.Neq_AVX2_F32(dst, x, y) 1213 } else { 1214 functions.Neq_Go(dst, x, y) 1215 } 1216 return dst 1217 } 1218 1219 // NeqNumber returns an element-wise "not equal" comparison between each slice element and a number. 1220 func NeqNumber(x []float32, a float32) []bool { 1221 dst := make([]bool, len(x)) 1222 return NeqNumber_Into(dst, x, a) 1223 } 1224 1225 // NeqNumber_Into stores an element-wise "not equal" comparison between each slice element and a 1226 // number in the destination slice. 1227 func NeqNumber_Into(dst []bool, x []float32, a float32) []bool { 1228 dst = checkCapacity(dst, x) 1229 if functions.UseAVX2 { 1230 functions.NeqNumber_AVX2_F32(dst, x, a) 1231 } else { 1232 functions.NeqNumber_Go(dst, x, a) 1233 } 1234 return dst 1235 } 1236 1237 // Boolean 1238 1239 // Not returns the logical negation of each slice element. 1240 func Not(x []bool) []bool { 1241 x = slices.Clone(x) 1242 Not_Inplace(x) 1243 return x 1244 } 1245 1246 // Not_Inplace computes the logical negation of each slice element, inplace. 1247 func Not_Inplace(x []bool) { 1248 if functions.UseAVX2 { 1249 functions.Not_AVX2(x) 1250 } else { 1251 functions.Not_Go(x) 1252 } 1253 } 1254 1255 // Not_Into stores the logical negation of each slice element in the destination slice. 1256 func Not_Into(dst, x []bool) []bool { 1257 dst = checkCapacity(dst, x) 1258 checkOverlap(dst, x) 1259 copy(dst, x) 1260 Not_Inplace(dst) 1261 return dst 1262 } 1263 1264 // And returns the element-wise logical "and" operation between two slices. 1265 func And(x, y []bool) []bool { 1266 x = slices.Clone(x) 1267 And_Inplace(x, y) 1268 return x 1269 } 1270 1271 // And_Inplace computes the element-wise logical "and" operation between two slices, inplace. 1272 func And_Inplace(x, y []bool) { 1273 checkEqualLength(x, y) 1274 checkOverlap(x, y) 1275 if functions.UseAVX2 { 1276 functions.And_AVX2(x, y) 1277 } else { 1278 functions.And_Go(x, y) 1279 } 1280 } 1281 1282 // And_Into stores the element-wise logical "and" operation between two slices in the destination 1283 // slice. 1284 func And_Into(dst, x, y []bool) []bool { 1285 dst = checkCapacity(dst, x) 1286 checkOverlap(dst, x) 1287 copy(dst, x) 1288 And_Inplace(dst, y) 1289 return dst 1290 } 1291 1292 // Or returns the element-wise logical "or" operation between two slices. 1293 func Or(x, y []bool) []bool { 1294 x = slices.Clone(x) 1295 Or_Inplace(x, y) 1296 return x 1297 } 1298 1299 // Or_Inplace computes the element-wise logical "or" operation between two slices, inplace. 1300 func Or_Inplace(x, y []bool) { 1301 checkEqualLength(x, y) 1302 checkOverlap(x, y) 1303 if functions.UseAVX2 { 1304 functions.Or_AVX2(x, y) 1305 } else { 1306 functions.Or_Go(x, y) 1307 } 1308 } 1309 1310 // Or_Into stores the element-wise logical "or" operation between two slices in the destination 1311 // slice. 1312 func Or_Into(dst, x, y []bool) []bool { 1313 dst = checkCapacity(dst, x) 1314 checkOverlap(dst, x) 1315 copy(dst, x) 1316 Or_Inplace(dst, y) 1317 return dst 1318 } 1319 1320 // Xor returns the element-wise "exclusive or" operation between two slices. 1321 func Xor(x, y []bool) []bool { 1322 x = slices.Clone(x) 1323 Xor_Inplace(x, y) 1324 return x 1325 } 1326 1327 // Xor_Inplace computes the element-wise "exclusive or" operation between two slices, inplace. 1328 func Xor_Inplace(x, y []bool) { 1329 checkEqualLength(x, y) 1330 checkOverlap(x, y) 1331 if functions.UseAVX2 { 1332 functions.Xor_AVX2(x, y) 1333 } else { 1334 functions.Xor_Go(x, y) 1335 } 1336 } 1337 1338 // Xor_Into stores the element-wise "exclusive or" operation between two slices in the destination 1339 // slice. 1340 func Xor_Into(dst, x, y []bool) []bool { 1341 dst = checkCapacity(dst, x) 1342 checkOverlap(dst, x) 1343 copy(dst, x) 1344 Xor_Inplace(dst, y) 1345 return dst 1346 } 1347 1348 // Select returns the slice elements for which the corresponding boolean values are true. 1349 func Select(x []float32, y []bool) []float32 { 1350 dst := make([]float32, 0) 1351 return Select_Into(dst, x, y) 1352 } 1353 1354 // Select_Into stores the slice elements for which the corresponding boolean values are true in 1355 // the destination slice. This function grows the destination slice if the selection yields more 1356 // values than it has capacity for. 1357 func Select_Into(dst, x []float32, y []bool) []float32 { 1358 checkEqualLength(x, y) 1359 //checkOverlap(dst[:cap(dst)], x) 1360 return functions.Select_Go(dst, x, y) 1361 } 1362 1363 // All returns whether all boolean values in the slice are true. 1364 func All(x []bool) bool { 1365 if functions.UseAVX2 { 1366 return functions.All_AVX2(x) != 0 1367 } else { 1368 return functions.All_Go(x) 1369 } 1370 } 1371 1372 // Any returns whether at least one boolean value in the slice is true. 1373 func Any(x []bool) bool { 1374 if functions.UseAVX2 { 1375 return functions.Any_AVX2(x) != 0 1376 } else { 1377 return functions.Any_Go(x) 1378 } 1379 } 1380 1381 // None returns whether none of the boolean values in the slice are true. 1382 func None(x []bool) bool { 1383 if functions.UseAVX2 { 1384 return functions.None_AVX2(x) != 0 1385 } else { 1386 return functions.None_Go(x) 1387 } 1388 } 1389 1390 // Count returns the number of boolean values that are true. 1391 func Count(x []bool) int { 1392 if functions.UseAVX2 { 1393 return functions.Count_AVX2(x) 1394 } else { 1395 return functions.Count_Go(x) 1396 } 1397 } 1398 1399 // Construction 1400 1401 // Zeros returns a new slice of length n filled with zeros. 1402 func Zeros(n int) []float32 { 1403 dst := make([]float32, n) 1404 return Repeat_Into(dst, 0, n) 1405 } 1406 1407 // Zeros_Into sets the first n elements in the destination slice to zero. 1408 func Zeros_Into(dst []float32, n int) []float32 { 1409 return Repeat_Into(dst, 0, n) 1410 } 1411 1412 // Ones returns a new slice of length n filled with ones. 1413 func Ones(n int) []float32 { 1414 dst := make([]float32, n) 1415 return Repeat_Into(dst, 1, n) 1416 } 1417 1418 // Ones_Into sets the first n elements in the destination slice to one. 1419 func Ones_Into(dst []float32, n int) []float32 { 1420 return Repeat_Into(dst, 1, n) 1421 } 1422 1423 // Repeat returns a new slice of length n filled with the given value. 1424 func Repeat(a float32, n int) []float32 { 1425 dst := make([]float32, n) 1426 return Repeat_Into(dst, a, n) 1427 } 1428 1429 // Repeat_Into sets the first n elements in the destination slice to the given value. 1430 func Repeat_Into(dst []float32, a float32, n int) []float32 { 1431 if cap(dst) < n { 1432 panic("destination slice not large enough to hold result") 1433 } 1434 if functions.UseAVX2 { 1435 functions.Repeat_AVX2_F32(dst, a, n) 1436 } else { 1437 functions.Repeat_Go(dst, a, n) 1438 } 1439 return dst[:n] 1440 } 1441 1442 // Range returns a new slice with values incrementing from a to b (excl.) in steps of 1. 1443 func Range(a, b float32) []float32 { 1444 dst := make([]float32, int(math32.Max(0, math32.Ceil(b-a)))) 1445 return Range_Into(dst, a, b) 1446 } 1447 1448 // Range_Into writes values incrementing from a to b (excl.) in steps of 1 to the destination slice. 1449 func Range_Into(dst []float32, a, b float32) []float32 { 1450 n := int(math32.Max(0, math32.Ceil(b-a))) 1451 if cap(dst) < n { 1452 panic("destination slice not large enough to hold result") 1453 } 1454 if functions.UseAVX2 { 1455 functions.Range_AVX2_F32(dst, a, n) 1456 } else { 1457 functions.Range_Go(dst, a, n) 1458 } 1459 return dst[:n] 1460 } 1461 1462 // Gather returns a new slice containing just the elements at the given indices. 1463 func Gather(x []float32, idx []int) []float32 { 1464 dst := make([]float32, len(idx)) 1465 return Gather_Into(dst, x, idx) 1466 } 1467 1468 // Gather_Into stores the slice elements at the given indices in the destination slice. 1469 func Gather_Into(dst, x []float32, idx []int) []float32 { 1470 dst = checkCapacity(dst, idx) 1471 checkOverlap(dst, x) 1472 functions.Gather_Go(dst, x, idx) 1473 return dst 1474 } 1475 1476 // Scatter returns a slice of size elements where position idx[i] is set to x[i], for all 1477 // i < len(x) = len(idx). The other elements are set to zero. 1478 func Scatter(x []float32, idx []int, size int) []float32 { 1479 dst := make([]float32, size) 1480 return Scatter_Into(dst, x, idx) 1481 } 1482 1483 // Scatter_Into sets positions idx[i] to x[i] in the destination slice, for all 1484 // i < len(x) = len(idx). The other elements are not modified. 1485 func Scatter_Into(dst, x []float32, idx []int) []float32 { 1486 checkOverlap(dst, x) 1487 functions.Scatter_Go(dst, x, idx) 1488 return dst 1489 } 1490 1491 // FromBool creates a slice of floats from a slice of bools by converting all false values to 0 1492 // and all true values to 1. 1493 func FromBool(x []bool) []float32 { 1494 dst := make([]float32, len(x)) 1495 return FromBool_Into(dst, x) 1496 } 1497 1498 // FromBool_Into creates a slice of floats from a slice of bools by converting all false values 1499 // to 0 and all true values to 1. The result is stored in the destination slice. 1500 func FromBool_Into(dst []float32, x []bool) []float32 { 1501 dst = checkCapacity(dst, x) 1502 if functions.UseAVX2 { 1503 functions.FromBool_AVX2_F32(dst, x) 1504 } else { 1505 functions.FromBool_Go(dst, x) 1506 } 1507 return dst 1508 } 1509 1510 // FromInt64 creates a slice of floats from a slice of 64-bit ints. Standard conversion rules 1511 // apply. 1512 func FromInt64(x []int64) []float32 { 1513 dst := make([]float32, len(x)) 1514 return FromInt64_Into(dst, x) 1515 } 1516 1517 // FromInt64_Into creates a slice of floats from a slice of 64-bit ints. Standard conversion 1518 // rules apply. The result is stored in the destination slice. 1519 func FromInt64_Into(dst []float32, x []int64) []float32 { 1520 dst = checkCapacity(dst, x) 1521 if functions.UseAVX2 { 1522 functions.FromInt64_AVX2_F32(dst, x) 1523 } else { 1524 functions.FromNumber_Go(dst, x) 1525 } 1526 return dst 1527 } 1528 1529 // FromInt32 creates a slice of floats from a slice of 32-bit ints. Standard conversion rules 1530 // apply. 1531 func FromInt32(x []int32) []float32 { 1532 dst := make([]float32, len(x)) 1533 return FromInt32_Into(dst, x) 1534 } 1535 1536 // FromInt32_Into creates a slice of floats from a slice of 32-bit ints. Standard conversion 1537 // rules apply. The result is stored in the destination slice. 1538 func FromInt32_Into(dst []float32, x []int32) []float32 { 1539 dst = checkCapacity(dst, x) 1540 if functions.UseAVX2 { 1541 functions.FromInt32_AVX2_F32(dst, x) 1542 } else { 1543 functions.FromNumber_Go(dst, x) 1544 } 1545 return dst 1546 } 1547 1548 // FromFloat64 creates a slice of floats from a slice of 64-bit floats. Standard conversion 1549 // rules apply. 1550 func FromFloat64(x []float64) []float32 { 1551 dst := make([]float32, len(x)) 1552 return FromFloat64_Into(dst, x) 1553 } 1554 1555 // FromFloat64_Into creates a slice of floats from a slice of 32-bit floats. Standard conversion 1556 // rules apply. The result is stored in the destination slice. 1557 func FromFloat64_Into(dst []float32, x []float64) []float32 { 1558 dst = checkCapacity(dst, x) 1559 if functions.UseAVX2 { 1560 functions.FromFloat64_AVX2_F32(dst, x) 1561 } else { 1562 functions.FromNumber_Go(dst, x) 1563 } 1564 return dst 1565 } 1566 1567 // ToBool converts a slice of floats to a slice of bools by setting all zero values to true and 1568 // all non-zero values to false. 1569 func ToBool(x []float64) []bool { 1570 dst := make([]bool, len(x)) 1571 return ToBool_Into(dst, x) 1572 } 1573 1574 // ToBool_Into converts a slice of floats to a slice of bools by setting all zero values to true 1575 // and all non-zero values to false. The result is stored in the destination slice. 1576 func ToBool_Into(dst []bool, x []float64) []bool { 1577 dst = checkCapacity(dst, x) 1578 if functions.UseAVX2 { 1579 functions.ToBool_AVX2_F64(dst, x) 1580 } else { 1581 functions.ToBool_Go(dst, x) 1582 } 1583 return dst 1584 } 1585 1586 // ToInt64 converts a slice of floats to a slice of 64-bit ints. Standard conversion rules apply. 1587 func ToInt64(x []float32) []int64 { 1588 dst := make([]int64, len(x)) 1589 return ToInt64_Into(dst, x) 1590 } 1591 1592 // ToInt64_Into converts a slice of floats to a slice of 64-bit ints. Standard conversion rules 1593 // apply. The result is stored in the destination slice. 1594 func ToInt64_Into(dst []int64, x []float32) []int64 { 1595 dst = checkCapacity(dst, x) 1596 if functions.UseAVX2 { 1597 functions.ToInt64_AVX2_F32(dst, x) 1598 } else { 1599 functions.ToNumber_Go(dst, x) 1600 } 1601 return dst 1602 } 1603 1604 // ToInt32 converts a slice of floats to a slice of 32-bit ints. Standard conversion rules apply. 1605 func ToInt32(x []float32) []int32 { 1606 dst := make([]int32, len(x)) 1607 return ToInt32_Into(dst, x) 1608 } 1609 1610 // ToInt32_Into converts a slice of floats to a slice of 32-bit ints. Standard conversion rules 1611 // apply. The result is stored in the destination slice. 1612 func ToInt32_Into(dst []int32, x []float32) []int32 { 1613 dst = checkCapacity(dst, x) 1614 if functions.UseAVX2 { 1615 functions.ToInt32_AVX2_F32(dst, x) 1616 } else { 1617 functions.ToNumber_Go(dst, x) 1618 } 1619 return dst 1620 } 1621 1622 // ToFloat64 converts a slice of floats to a slice of 32-bit floats. Standard conversion rules 1623 // apply. 1624 func ToFloat64(x []float32) []float64 { 1625 dst := make([]float64, len(x)) 1626 return ToFloat64_Into(dst, x) 1627 } 1628 1629 // ToFloat64_Into converts a slice of floats to a slice of 64-bit floats. Standard conversion 1630 // rules apply. The result is stored in the destination slice. 1631 func ToFloat64_Into(dst []float64, x []float32) []float64 { 1632 dst = checkCapacity(dst, x) 1633 if functions.UseAVX2 { 1634 functions.FromFloat32_AVX2_F64(dst, x) 1635 } else { 1636 functions.ToNumber_Go(dst, x) 1637 } 1638 return dst 1639 } 1640 1641 // Misc 1642 1643 // Info returns information about the current operating environment. 1644 func Info() num.SystemInfo { 1645 return num.Info() 1646 } 1647 1648 // SetAcceleration toggles simd acceleration. Not thread safe. 1649 func SetAcceleration(enabled bool) { 1650 num.SetAcceleration(enabled) 1651 } 1652 1653 // Validation 1654 1655 func slicesOverlap[T, F any](x []T, y []F) bool { 1656 if len(x) == 0 || len(y) == 0 { 1657 return false 1658 } 1659 xStart := uintptr(unsafe.Pointer(&x[0])) 1660 xEnd := uintptr(unsafe.Pointer(&x[len(x)-1])) 1661 yStart := uintptr(unsafe.Pointer(&y[0])) 1662 yEnd := uintptr(unsafe.Pointer(&y[len(y)-1])) 1663 return xStart <= yEnd && yStart <= xEnd 1664 } 1665 1666 func checkCapacity[T, F any](dst []T, x []F) []T { 1667 if cap(dst) < len(x) { 1668 panic("destination slice not large enough to hold result") 1669 } 1670 return dst[:len(x)] 1671 } 1672 1673 func checkEqualLength[T, F any](x []T, y []F) { 1674 if len(x) != len(y) { 1675 panic("slices must be of equal length") 1676 } 1677 } 1678 1679 func checkNotEmpty[T any](x []T) { 1680 if len(x) == 0 { 1681 panic("slice must not be empty") 1682 } 1683 } 1684 1685 func checkOverlap[T, F any](x []T, y []F) { 1686 if slicesOverlap(x, y) { 1687 panic("destination slice must not overlap input slice") 1688 } 1689 }