gitee.com/quant1x/gox@v1.7.6/num/vek_amd64.go (about) 1 package num 2 3 import ( 4 "gitee.com/quant1x/gox/num/internal/functions" 5 "golang.org/x/exp/constraints" 6 "golang.org/x/exp/slices" 7 "golang.org/x/sys/cpu" 8 "math" 9 "unsafe" 10 ) 11 12 // Arithmetic 13 14 // Add returns the result of adding two slices element-wise. 15 func Add(x, y []float64) []float64 { 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 []float64) { 23 checkEqualLength(x, y) 24 checkOverlap(x, y) 25 if functions.UseAVX2 { 26 functions.Add_AVX2_F64(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 []float64) []float64 { 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 []float64) []float64 { 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 []float64) { 50 checkEqualLength(x, y) 51 checkOverlap(x, y) 52 if functions.UseAVX2 { 53 functions.Sub_AVX2_F64(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 []float64) []float64 { 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 []float64) []float64 { 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 []float64) { 77 checkEqualLength(x, y) 78 checkOverlap(x, y) 79 if functions.UseAVX2 { 80 functions.Mul_AVX2_F64(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 []float64) []float64 { 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 []float64) []float64 { 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 []float64) { 104 checkEqualLength(x, y) 105 checkOverlap(x, y) 106 if functions.UseAVX2 { 107 functions.Div_AVX2_F64(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 []float64) []float64 { 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 []float64, a float64) []float64 { 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 []float64, a float64) { 131 if functions.UseAVX2 { 132 functions.AddNumber_AVX2_F64(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 []float64, a float64) []float64 { 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 []float64, a float64) []float64 { 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 []float64, a float64) { 157 if functions.UseAVX2 { 158 functions.SubNumber_AVX2_F64(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 []float64, a float64) []float64 { 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 []float64, a float64) []float64 { 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 []float64, a float64) { 183 if functions.UseAVX2 { 184 functions.MulNumber_AVX2_F64(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 []float64, a float64) []float64 { 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 []float64, a float64) []float64 { 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 []float64, a float64) { 209 if functions.UseAVX2 { 210 functions.DivNumber_AVX2_F64(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 []float64, a float64) []float64 { 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 []float64) []float64 { 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 []float64) { 235 if functions.UseAVX2 { 236 functions.Abs_AVX2_F64(x) 237 } else { 238 functions.Abs_Go_F64(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 []float64) []float64 { 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 []float64) []float64 { 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 []float64) { 261 if functions.UseAVX2 { 262 functions.Neg_AVX2_F64(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 []float64) []float64 { 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 []float64) []float64 { 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 []float64) { 287 if functions.UseAVX2 { 288 functions.Inv_AVX2_F64(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 []float64) []float64 { 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 []float64) float64 { 308 if functions.UseAVX2 { 309 return functions.Sum_AVX2_F64(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 []float64) []float64 { 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 []float64) { 325 if functions.UseAVX2 { 326 functions.CumSum_AVX2_F64(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 []float64) []float64 { 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 []float64) float64 { 344 if functions.UseAVX2 { 345 return functions.Prod_AVX2_F64(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 []float64) []float64 { 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 []float64) { 362 if functions.UseAVX2 { 363 functions.CumProd_AVX2_F64(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 []float64) []float64 { 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 []float64) float64 { 381 checkNotEmpty(x) 382 if functions.UseAVX2 { 383 return functions.Mean_AVX2_F64(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 []float64) float64 { 391 checkNotEmpty(x) 392 if functions.UseAVX2 { 393 return functions.Median_AVX2_F64(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 []float64, q float64) float64 { 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_F64(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 []float64) float64 { 417 checkNotEmpty(x) 418 checkEqualLength(x, y) 419 if functions.UseAVX2 { 420 return functions.Dot_AVX2_F64(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 []float64) float64 { 428 checkNotEmpty(x) 429 if functions.UseAVX2 { 430 return functions.Norm_AVX2_F64(x) 431 } else { 432 return functions.Norm_Go_F64(x) 433 } 434 } 435 436 // Distance returns the Euclidean distance between two vectors. 437 func Distance(x, y []float64) float64 { 438 checkNotEmpty(x) 439 checkEqualLength(x, y) 440 if functions.UseAVX2 { 441 return functions.Distance_AVX2_F64(x, y) 442 } else { 443 return functions.Distance_Go_F64(x, y) 444 } 445 } 446 447 // ManhattanNorm returns the sum of absolute values of the slice elements. 448 func ManhattanNorm(x []float64) float64 { 449 checkNotEmpty(x) 450 if functions.UseAVX2 { 451 return functions.ManhattanNorm_AVX2_F64(x) 452 } else { 453 return functions.ManhattanNorm_Go_F64(x) 454 } 455 } 456 457 // ManhattanDistance returns the sum of element-wise absolute differences between two slices. 458 func ManhattanDistance(x, y []float64) float64 { 459 checkNotEmpty(x) 460 checkEqualLength(x, y) 461 if functions.UseAVX2 { 462 return functions.ManhattanDistance_AVX2_F64(x, y) 463 } else { 464 return functions.ManhattanDistance_Go_F64(x, y) 465 } 466 } 467 468 // CosineSimilarity returns the cosine similarity of two vectors. 469 func CosineSimilarity(x, y []float64) float64 { 470 checkNotEmpty(x) 471 checkEqualLength(x, y) 472 if functions.UseAVX2 { 473 return functions.CosineSimilarity_AVX2_F64(x, y) 474 } else { 475 return functions.CosineSimilarity_Go_F64(x, y) 476 } 477 } 478 479 // Matrices 480 481 func checkDimensions[T constraints.Float](x, y []T, n int) (int, int) { 482 if n < 1 || len(x) == 0 || len(y) == 0 { 483 panic("slices must be non-empty with positive n") 484 } 485 m := len(x) / n 486 p := len(y) / n 487 if m*n < len(x) || n*p < len(y) { 488 panic("slice lengths must be multiple of n") 489 } 490 return m, p 491 } 492 493 // MatMul multiplies an m-by-n and n-by-p matrix and returns the resulting m-by-p matrix. 494 // The matrices should be in row-major order. To multiply a matrix and a vector pass an 495 // n-by-1 matrix. 496 func MatMul(x, y []float64, n int) []float64 { 497 m, p := checkDimensions(x, y, n) 498 dst := make([]float64, m*p) 499 if functions.UseAVX2 { 500 functions.MatMul_Parallel_AVX2_F64(dst, x, y, m, n, p) 501 } else { 502 functions.MatMul_Parallel_Go(dst, x, y, m, n, p) 503 } 504 return dst 505 } 506 507 // MatMul_Into multiplies an m-by-n and n-by-p matrix and stores the resulting m-by-p matrix 508 // in the destination slice. The matrices should be in row-major order. To multiply a matrix 509 // and a vector pass an n-by-1 matrix. 510 func MatMul_Into(dst, x, y []float64, n int) []float64 { 511 m, p := checkDimensions(x, y, n) 512 if cap(dst) < m*p { 513 panic("destination slice not large enough to hold result") 514 } 515 Zeros_Into(dst, m*p) 516 if functions.UseAVX2 { 517 functions.MatMul_Parallel_AVX2_F64(dst, x, y, m, n, p) 518 } else { 519 functions.MatMul_Parallel_Go(dst, x, y, m, n, p) 520 } 521 return dst[:m*p] 522 } 523 524 // Mat4Mul multiplies two 4-by-4 matrices and returns the resulting 4-by-4 matrix. The matrices 525 // should be in row-major order. To multiply a matrix and a vector batch them into groups of 4. 526 func Mat4Mul(x, y []float64) []float64 { 527 var dst [16]float64 528 return Mat4Mul_Into(dst[:], x, y) 529 } 530 531 // Mat4Mul_Into multiplies two 4-by-4 matrices and stores the resulting 4-by-4 matrix in the 532 // destination slice. The matrices should be in row-major order. To multiply a matrix and a vector 533 // batch them into groups of 4. 534 func Mat4Mul_Into(dst, x, y []float64) []float64 { 535 // Note: skipping overlap check due to overhead 536 if cap(dst) < 16 || len(x) != 16 || len(y) != 16 { 537 panic("slices must be length 16 (4 by 4)") 538 } 539 if functions.UseAVX2 { 540 functions.Mat4Mul_AVX2_F64(dst, x, y) 541 } else { 542 functions.Mat4Mul_Go(dst, x, y) 543 } 544 return dst[:16] 545 } 546 547 // Special 548 549 // Sqrt returns the square root of each slice element. 550 func Sqrt(x []float64) []float64 { 551 x = slices.Clone(x) 552 Sqrt_Inplace(x) 553 return x 554 } 555 556 // Sqrt_Inplace computes the square root of each slice element, inplace. 557 func Sqrt_Inplace(x []float64) { 558 if functions.UseAVX2 { 559 functions.Sqrt_AVX2_F64(x) 560 } else { 561 functions.Sqrt_Go_F64(x) 562 } 563 } 564 565 // Sqrt_Into computes the square root of each slice element and stores the result in the 566 // destination slice. 567 func Sqrt_Into(dst, x []float64) []float64 { 568 dst = checkCapacity(dst, x) 569 checkOverlap(dst, x) 570 copy(dst, x) 571 Sqrt_Inplace(dst) 572 return dst 573 } 574 575 // Round returns the result of rounding each slice element to the nearest integer value. 576 func Round(x []float64) []float64 { 577 x = slices.Clone(x) 578 Round_Inplace(x) 579 return x 580 } 581 582 // Round_Inplace rounds each slice element to the nearest integer value, inplace. 583 func Round_Inplace(x []float64) { 584 if functions.UseAVX2 { 585 functions.Round_AVX2_F64(x) 586 } else { 587 functions.Round_Go_F64(x) 588 } 589 } 590 591 // Round_Into rounds each slice element to the nearest integer value and stores the result 592 // in the destination slice. 593 func Round_Into(dst, x []float64) []float64 { 594 dst = checkCapacity(dst, x) 595 checkOverlap(dst, x) 596 copy(dst, x) 597 Round_Inplace(dst) 598 return dst 599 } 600 601 // Floor returns the result of rounding each slice element to the nearest lesser integer value. 602 func Floor(x []float64) []float64 { 603 x = slices.Clone(x) 604 Floor_Inplace(x) 605 return x 606 } 607 608 // Floor_Inplace rounds each slice element to the nearest lesser integer value, inplace. 609 func Floor_Inplace(x []float64) { 610 if functions.UseAVX2 { 611 functions.Floor_AVX2_F64(x) 612 } else { 613 functions.Floor_Go_F64(x) 614 } 615 } 616 617 // Floor_Into rounds each slice element to the nearest lesser integer value and stores the result 618 // in the destination slice. 619 func Floor_Into(dst, x []float64) []float64 { 620 dst = checkCapacity(dst, x) 621 checkOverlap(dst, x) 622 copy(dst, x) 623 Floor_Inplace(dst) 624 return dst 625 } 626 627 // Ceil returns the result of rounding each slice element to the nearest greater integer value. 628 func Ceil(x []float64) []float64 { 629 x = slices.Clone(x) 630 Ceil_Inplace(x) 631 return x 632 } 633 634 // Ceil_Inplace rounds each slice element to the nearest greater integer value, inplace. 635 func Ceil_Inplace(x []float64) { 636 if functions.UseAVX2 { 637 functions.Ceil_AVX2_F64(x) 638 } else { 639 functions.Ceil_Go_F64(x) 640 } 641 } 642 643 // Ceil_Into rounds each slice element to the nearest greater integer value and stores the result 644 // in the destination slice. 645 func Ceil_Into(dst, x []float64) []float64 { 646 dst = checkCapacity(dst, x) 647 checkOverlap(dst, x) 648 copy(dst, x) 649 Ceil_Inplace(dst) 650 return dst 651 } 652 653 // Pow returns the elements in the first slice raised to the power in the second. 654 func Pow(x, y []float64) []float64 { 655 x = slices.Clone(x) 656 Pow_Inplace(x, y) 657 return x 658 } 659 660 // Pow_Inplace raises the elements in the first slice to the power in the second, inplace. 661 func Pow_Inplace(x, y []float64) { 662 checkEqualLength(x, y) 663 checkOverlap(x, y) 664 if functions.UseAVX2 { 665 functions.Pow_AVX2_F64(x, y) 666 } else { 667 functions.Pow_Go_F64(x, y) 668 } 669 } 670 671 // Pow_Into raises the elements in the first slice to the power in the second and stores the 672 // result in the destination slice. 673 func Pow_Into(dst, x, y []float64) []float64 { 674 dst = checkCapacity(dst, x) 675 checkOverlap(dst, x) 676 copy(dst, x) 677 Pow_Inplace(dst, y) 678 return dst 679 } 680 681 // Comparison 682 683 // Min returns the minimum value of a slice. 684 func Min(x []float64) float64 { 685 checkNotEmpty(x) 686 if functions.UseAVX2 { 687 return functions.Min_AVX2_F64(x) 688 } else { 689 return functions.Min_Go(x) 690 } 691 } 692 693 // ArgMin returns the (first) index of the minimum value of a slice. 694 func ArgMin(x []float64) int { 695 checkNotEmpty(x) 696 if functions.UseAVX2 { 697 return functions.ArgMin_AVX2_F64(x) 698 } else { 699 return functions.ArgMin_Go(x) 700 } 701 } 702 703 // Minimum returns the element-wise minimum values between two slices. 704 func Minimum(x, y []float64) []float64 { 705 x = slices.Clone(x) 706 Minimum_Inplace(x, y) 707 return x 708 } 709 710 // Minimum_Inplace compares two slices element-wise and replaces the values in the first slice 711 // with the minimum value. 712 func Minimum_Inplace(x, y []float64) { 713 checkEqualLength(x, y) 714 checkOverlap(x, y) 715 if functions.UseAVX2 { 716 functions.Minimum_AVX2_F64(x, y) 717 } else { 718 functions.Minimum_Go(x, y) 719 } 720 } 721 722 // Minimum_Into compares two slices element-wise and stores the minimum values in the destination 723 // slice. 724 func Minimum_Into(dst, x, y []float64) []float64 { 725 dst = checkCapacity(dst, x) 726 checkOverlap(dst, x) 727 copy(dst, x) 728 Minimum_Inplace(dst, y) 729 return dst 730 } 731 732 // MinimumNumber returns the minimum of a number and each slice element. 733 func MinimumNumber(x []float64, a float64) []float64 { 734 x = slices.Clone(x) 735 MinimumNumber_Inplace(x, a) 736 return x 737 } 738 739 // MinimumNumber_Inplace compares a number to each slice element and replaces the values in the 740 // slice with the minimum value. 741 func MinimumNumber_Inplace(x []float64, a float64) { 742 if functions.UseAVX2 { 743 functions.MinimumNumber_AVX2_F64(x, a) 744 } else { 745 functions.MinimumNumber_Go(x, a) 746 } 747 } 748 749 // MinimumNumber_Into compares a number to each slice element and stores the minimum values in 750 // the destination slice. 751 func MinimumNumber_Into(dst, x []float64, a float64) []float64 { 752 dst = checkCapacity(dst, x) 753 checkOverlap(dst, x) 754 copy(dst, x) 755 MinimumNumber_Inplace(dst, a) 756 return dst 757 } 758 759 // Max returns the maximum value of a slice. 760 func Max(x []float64) float64 { 761 checkNotEmpty(x) 762 if functions.UseAVX2 { 763 return functions.Max_AVX2_F64(x) 764 } else { 765 return functions.Max_Go(x) 766 } 767 } 768 769 // ArgMax returns the (first) index of the maximum value of a slice. 770 func ArgMax(x []float64) int { 771 checkNotEmpty(x) 772 if functions.UseAVX2 { 773 return functions.ArgMax_AVX2_F64(x) 774 } else { 775 return functions.ArgMax_Go(x) 776 } 777 } 778 779 // Maximum returns the element-wise maximum values between two slices. 780 func Maximum(x, y []float64) []float64 { 781 x = slices.Clone(x) 782 Maximum_Inplace(x, y) 783 return x 784 } 785 786 // Maximum_Inplace compares two slices element-wise and replaces the values in the first slice 787 // with the maximum value. 788 func Maximum_Inplace(x, y []float64) { 789 checkEqualLength(x, y) 790 checkOverlap(x, y) 791 if functions.UseAVX2 { 792 functions.Maximum_AVX2_F64(x, y) 793 } else { 794 functions.Maximum_Go(x, y) 795 } 796 } 797 798 // Maximum_Into compares two slices element-wise and stores the maximum values in the destination 799 // slice. 800 func Maximum_Into(dst, x, y []float64) []float64 { 801 dst = checkCapacity(dst, x) 802 checkOverlap(dst, x) 803 copy(dst, x) 804 Maximum_Inplace(dst, y) 805 return dst 806 } 807 808 // MaximumNumber returns the maximum of a number and each slice element. 809 func MaximumNumber(x []float64, a float64) []float64 { 810 x = slices.Clone(x) 811 MaximumNumber_Inplace(x, a) 812 return x 813 } 814 815 // MaximumNumber_Inplace compares a number to each slice element and replaces the values in the 816 // slice with the maximum value. 817 func MaximumNumber_Inplace(x []float64, a float64) { 818 if functions.UseAVX2 { 819 functions.MaximumNumber_AVX2_F64(x, a) 820 } else { 821 functions.MaximumNumber_Go(x, a) 822 } 823 } 824 825 // MaximumNumber_Into compares a number to each slice element and stores the maximum values in 826 // the destination slice. 827 func MaximumNumber_Into(dst, x []float64, a float64) []float64 { 828 dst = checkCapacity(dst, x) 829 checkOverlap(dst, x) 830 copy(dst, x) 831 MaximumNumber_Inplace(dst, a) 832 return dst 833 } 834 835 // Find returns the index of the first slice element equal to the given value, or -1 if not found. 836 func Find(x []float64, a float64) int { 837 if functions.UseAVX2 { 838 idx := functions.Find_AVX2_F64(x, a) 839 if idx == len(x) { 840 return -1 841 } 842 return idx 843 } else { 844 return functions.Find_Go(x, a) 845 } 846 } 847 848 // Lt returns an element-wise "less than" comparison between two slices. 849 func Lt(x, y []float64) []bool { 850 dst := make([]bool, len(x)) 851 return Lt_Into(dst, x, y) 852 } 853 854 // Lt_Into stores an element-wise "less than" comparison between two slices in the destination 855 // slice. 856 func Lt_Into(dst []bool, x, y []float64) []bool { 857 checkEqualLength(x, y) 858 dst = checkCapacity(dst, x) 859 if functions.UseAVX2 { 860 functions.Lt_AVX2_F64(dst, x, y) 861 } else { 862 functions.Lt_Go(dst, x, y) 863 } 864 return dst 865 } 866 867 // LtNumber returns an element-wise "less than" comparison between each slice element and 868 // a number. 869 func LtNumber(x []float64, a float64) []bool { 870 dst := make([]bool, len(x)) 871 return LtNumber_Into(dst, x, a) 872 } 873 874 // LtNumber_Into stores an element-wise "less than" comparison between each slice element 875 // and a number in the destination slice. 876 func LtNumber_Into(dst []bool, x []float64, a float64) []bool { 877 dst = checkCapacity(dst, x) 878 if functions.UseAVX2 { 879 functions.LtNumber_AVX2_F64(dst, x, a) 880 } else { 881 functions.LtNumber_Go(dst, x, a) 882 } 883 return dst 884 } 885 886 // Lte returns an element-wise "less than or equal" comparison between two slices. 887 func Lte(x, y []float64) []bool { 888 dst := make([]bool, len(x)) 889 return Lte_Into(dst, x, y) 890 } 891 892 // Lte_Into stores an element-wise "less than or equal" comparison between two slices in the 893 // destination slice. 894 func Lte_Into(dst []bool, x, y []float64) []bool { 895 checkEqualLength(x, y) 896 dst = checkCapacity(dst, x) 897 if functions.UseAVX2 { 898 functions.Lte_AVX2_F64(dst, x, y) 899 } else { 900 functions.Lte_Go(dst, x, y) 901 } 902 return dst 903 } 904 905 // LteNumber returns an element-wise "less than or equal" comparison between each slice element 906 // and a number. 907 func LteNumber(x []float64, a float64) []bool { 908 dst := make([]bool, len(x)) 909 return LteNumber_Into(dst, x, a) 910 } 911 912 // LteNumber_Into stores an element-wise "less than or equal" comparison between each slice 913 // element and a number in the destination slice. 914 func LteNumber_Into(dst []bool, x []float64, a float64) []bool { 915 dst = checkCapacity(dst, x) 916 if functions.UseAVX2 { 917 functions.LteNumber_AVX2_F64(dst, x, a) 918 } else { 919 functions.LteNumber_Go(dst, x, a) 920 } 921 return dst 922 } 923 924 // Gt returns an element-wise "greater than" comparison between two slices. 925 func Gt(x, y []float64) []bool { 926 dst := make([]bool, len(x)) 927 return Gt_Into(dst, x, y) 928 } 929 930 // Gt_Into stores an element-wise "greater than" comparison between two slices in the destination 931 // slice. 932 func Gt_Into(dst []bool, x, y []float64) []bool { 933 checkEqualLength(x, y) 934 dst = checkCapacity(dst, x) 935 if functions.UseAVX2 { 936 functions.Gt_AVX2_F64(dst, x, y) 937 } else { 938 functions.Gt_Go(dst, x, y) 939 } 940 return dst 941 } 942 943 // GtNumber returns an element-wise "greater than" comparison between each slice element and 944 // a number. 945 func GtNumber(x []float64, a float64) []bool { 946 dst := make([]bool, len(x)) 947 return GtNumber_Into(dst, x, a) 948 } 949 950 // GtNumber_Into stores an element-wise "greater than" comparison between each slice element and 951 // a number in the destination slice. 952 func GtNumber_Into(dst []bool, x []float64, a float64) []bool { 953 dst = checkCapacity(dst, x) 954 if functions.UseAVX2 { 955 functions.GtNumber_AVX2_F64(dst, x, a) 956 } else { 957 functions.GtNumber_Go(dst, x, a) 958 } 959 return dst 960 } 961 962 // Gte returns an element-wise "greater than or equal" comparison between two slices. 963 func Gte(x, y []float64) []bool { 964 dst := make([]bool, len(x)) 965 return Gte_Into(dst, x, y) 966 } 967 968 // Gte_Into stores an element-wise "greater than or equal" comparison between two slices in the 969 // destination slice. 970 func Gte_Into(dst []bool, x, y []float64) []bool { 971 checkEqualLength(x, y) 972 dst = checkCapacity(dst, x) 973 if functions.UseAVX2 { 974 functions.Gte_AVX2_F64(dst, x, y) 975 } else { 976 functions.Gte_Go(dst, x, y) 977 } 978 return dst 979 } 980 981 // GteNumber returns an element-wise "greater than or equal" comparison between each slice element 982 // and a number. 983 func GteNumber(x []float64, a float64) []bool { 984 dst := make([]bool, len(x)) 985 return GteNumber_Into(dst, x, a) 986 } 987 988 // GteNumber_Into stores an element-wise "greater than or equal" comparison between each slice 989 // element and a number in the destination slice. 990 func GteNumber_Into(dst []bool, x []float64, a float64) []bool { 991 dst = checkCapacity(dst, x) 992 if functions.UseAVX2 { 993 functions.GteNumber_AVX2_F64(dst, x, a) 994 } else { 995 functions.GteNumber_Go(dst, x, a) 996 } 997 return dst 998 } 999 1000 // Eq returns an element-wise equality comparison between two slices. 1001 func Eq(x, y []float64) []bool { 1002 dst := make([]bool, len(x)) 1003 return Eq_Into(dst, x, y) 1004 } 1005 1006 // Eq_Into stores an element-wise equality comparison between two slices in the destination 1007 // slice. 1008 func Eq_Into(dst []bool, x, y []float64) []bool { 1009 checkEqualLength(x, y) 1010 dst = checkCapacity(dst, x) 1011 if functions.UseAVX2 { 1012 functions.Eq_AVX2_F64(dst, x, y) 1013 } else { 1014 functions.Eq_Go(dst, x, y) 1015 } 1016 return dst 1017 } 1018 1019 // EqNumber returns an element-wise equality comparison between each slice element and a number. 1020 func EqNumber(x []float64, a float64) []bool { 1021 dst := make([]bool, len(x)) 1022 return EqNumber_Into(dst, x, a) 1023 } 1024 1025 // EqNumber_Into stores an element-wise equality comparison between each slice element and a 1026 // number in the destination slice. 1027 func EqNumber_Into(dst []bool, x []float64, a float64) []bool { 1028 dst = checkCapacity(dst, x) 1029 if functions.UseAVX2 { 1030 functions.EqNumber_AVX2_F64(dst, x, a) 1031 } else { 1032 functions.EqNumber_Go(dst, x, a) 1033 } 1034 return dst 1035 } 1036 1037 // Neq returns an element-wise "not equal" comparison between two slices. 1038 func Neq(x, y []float64) []bool { 1039 dst := make([]bool, len(x)) 1040 return Neq_Into(dst, x, y) 1041 } 1042 1043 // Neq_Into stores an element-wise "not equal" comparison between two slices in the destination 1044 // slice. 1045 func Neq_Into(dst []bool, x, y []float64) []bool { 1046 checkEqualLength(x, y) 1047 dst = checkCapacity(dst, x) 1048 if functions.UseAVX2 { 1049 functions.Neq_AVX2_F64(dst, x, y) 1050 } else { 1051 functions.Neq_Go(dst, x, y) 1052 } 1053 return dst 1054 } 1055 1056 // NeqNumber returns an element-wise "not equal" comparison between each slice element and a number. 1057 func NeqNumber(x []float64, a float64) []bool { 1058 dst := make([]bool, len(x)) 1059 return NeqNumber_Into(dst, x, a) 1060 } 1061 1062 // NeqNumber_Into stores an element-wise "not equal" comparison between each slice element and a 1063 // number in the destination slice. 1064 func NeqNumber_Into(dst []bool, x []float64, a float64) []bool { 1065 dst = checkCapacity(dst, x) 1066 if functions.UseAVX2 { 1067 functions.NeqNumber_AVX2_F64(dst, x, a) 1068 } else { 1069 functions.NeqNumber_Go(dst, x, a) 1070 } 1071 return dst 1072 } 1073 1074 // Boolean 1075 1076 // Not returns the logical negation of each slice element. 1077 func Not(x []bool) []bool { 1078 x = slices.Clone(x) 1079 Not_Inplace(x) 1080 return x 1081 } 1082 1083 // Not_Inplace computes the logical negation of each slice element, inplace. 1084 func Not_Inplace(x []bool) { 1085 if functions.UseAVX2 { 1086 functions.Not_AVX2(x) 1087 } else { 1088 functions.Not_Go(x) 1089 } 1090 } 1091 1092 // Not_Into stores the logical negation of each slice element in the destination slice. 1093 func Not_Into(dst, x []bool) []bool { 1094 dst = checkCapacity(dst, x) 1095 checkOverlap(dst, x) 1096 copy(dst, x) 1097 Not_Inplace(dst) 1098 return dst 1099 } 1100 1101 // And returns the element-wise logical "and" operation between two slices. 1102 func And(x, y []bool) []bool { 1103 x = slices.Clone(x) 1104 And_Inplace(x, y) 1105 return x 1106 } 1107 1108 // And_Inplace computes the element-wise logical "and" operation between two slices, inplace. 1109 func And_Inplace(x, y []bool) { 1110 checkEqualLength(x, y) 1111 checkOverlap(x, y) 1112 if functions.UseAVX2 { 1113 functions.And_AVX2(x, y) 1114 } else { 1115 functions.And_Go(x, y) 1116 } 1117 } 1118 1119 // And_Into stores the element-wise logical "and" operation between two slices in the destination 1120 // slice. 1121 func And_Into(dst, x, y []bool) []bool { 1122 dst = checkCapacity(dst, x) 1123 checkOverlap(dst, x) 1124 copy(dst, x) 1125 And_Inplace(dst, y) 1126 return dst 1127 } 1128 1129 // Or returns the element-wise logical "or" operation between two slices. 1130 func Or(x, y []bool) []bool { 1131 x = slices.Clone(x) 1132 Or_Inplace(x, y) 1133 return x 1134 } 1135 1136 // Or_Inplace computes the element-wise logical "or" operation between two slices, inplace. 1137 func Or_Inplace(x, y []bool) { 1138 checkEqualLength(x, y) 1139 checkOverlap(x, y) 1140 if functions.UseAVX2 { 1141 functions.Or_AVX2(x, y) 1142 } else { 1143 functions.Or_Go(x, y) 1144 } 1145 } 1146 1147 // Or_Into stores the element-wise logical "or" operation between two slices in the destination 1148 // slice. 1149 func Or_Into(dst, x, y []bool) []bool { 1150 dst = checkCapacity(dst, x) 1151 checkOverlap(dst, x) 1152 copy(dst, x) 1153 Or_Inplace(dst, y) 1154 return dst 1155 } 1156 1157 // Xor returns the element-wise "exclusive or" operation between two slices. 1158 func Xor(x, y []bool) []bool { 1159 x = slices.Clone(x) 1160 Xor_Inplace(x, y) 1161 return x 1162 } 1163 1164 // Xor_Inplace computes the element-wise "exclusive or" operation between two slices, inplace. 1165 func Xor_Inplace(x, y []bool) { 1166 checkEqualLength(x, y) 1167 checkOverlap(x, y) 1168 if functions.UseAVX2 { 1169 functions.Xor_AVX2(x, y) 1170 } else { 1171 functions.Xor_Go(x, y) 1172 } 1173 } 1174 1175 // Xor_Into stores the element-wise "exclusive or" operation between two slices in the destination 1176 // slice. 1177 func Xor_Into(dst, x, y []bool) []bool { 1178 dst = checkCapacity(dst, x) 1179 checkOverlap(dst, x) 1180 copy(dst, x) 1181 Xor_Inplace(dst, y) 1182 return dst 1183 } 1184 1185 // Select returns the slice elements for which the corresponding boolean values are true. 1186 func Select(x []float64, y []bool) []float64 { 1187 dst := make([]float64, 0) 1188 return Select_Into(dst, x, y) 1189 } 1190 1191 // Select_Into stores the slice elements for which the corresponding boolean values are true in 1192 // the destination slice. This function grows the destination slice if the selection yields more 1193 // values than it has capacity for. 1194 func Select_Into(dst, x []float64, y []bool) []float64 { 1195 checkEqualLength(x, y) 1196 //checkOverlap(dst[:cap(dst)], x) 1197 return functions.Select_Go(dst, x, y) 1198 } 1199 1200 // All returns whether all boolean values in the slice are true. 1201 func All(x []bool) bool { 1202 if functions.UseAVX2 { 1203 return functions.All_AVX2(x) != 0 1204 } else { 1205 return functions.All_Go(x) 1206 } 1207 } 1208 1209 // Any returns whether at least one boolean value in the slice is true. 1210 func Any(x []bool) bool { 1211 if functions.UseAVX2 { 1212 return functions.Any_AVX2(x) != 0 1213 } else { 1214 return functions.Any_Go(x) 1215 } 1216 } 1217 1218 // None returns whether none of the boolean values in the slice are true. 1219 func None(x []bool) bool { 1220 if functions.UseAVX2 { 1221 return functions.None_AVX2(x) != 0 1222 } else { 1223 return functions.None_Go(x) 1224 } 1225 } 1226 1227 // Count returns the number of boolean values that are true. 1228 func Count(x []bool) int { 1229 if functions.UseAVX2 { 1230 return functions.Count_AVX2(x) 1231 } else { 1232 return functions.Count_Go(x) 1233 } 1234 } 1235 1236 // Construction 1237 1238 // Zeros returns a new slice of length n filled with zeros. 1239 func Zeros(n int) []float64 { 1240 if n < 0 { 1241 panic("n must be positive") 1242 } 1243 dst := make([]float64, n) 1244 return Repeat_Into(dst, 0, n) 1245 } 1246 1247 // Zeros_Into sets the first n elements in the destination slice to zero. 1248 func Zeros_Into(dst []float64, n int) []float64 { 1249 return Repeat_Into(dst, 0, n) 1250 } 1251 1252 // Ones returns a new slice of length n filled with ones. 1253 func Ones(n int) []float64 { 1254 if n < 0 { 1255 panic("n must be positive") 1256 } 1257 dst := make([]float64, n) 1258 return Repeat_Into(dst, 1, n) 1259 } 1260 1261 // Ones_Into sets the first n elements in the destination slice to one. 1262 func Ones_Into(dst []float64, n int) []float64 { 1263 return Repeat_Into(dst, 1, n) 1264 } 1265 1266 // Repeat returns a new slice of length n filled with the given value. 1267 func Repeat(a float64, n int) []float64 { 1268 if n < 0 { 1269 panic("n must be positive") 1270 } 1271 dst := make([]float64, n) 1272 return Repeat_Into(dst, a, n) 1273 } 1274 1275 // Repeat_Into sets the first n elements in the destination slice to the given value. 1276 func Repeat_Into(dst []float64, a float64, n int) []float64 { 1277 if n < 0 { 1278 panic("n must be positive") 1279 } 1280 if cap(dst) < n { 1281 panic("destination slice not large enough to hold result") 1282 } 1283 if functions.UseAVX2 { 1284 functions.Repeat_AVX2_F64(dst, a, n) 1285 } else { 1286 functions.Repeat_Go(dst, a, n) 1287 } 1288 return dst[:n] 1289 } 1290 1291 // Range returns a new slice with values incrementing from a to b (excl.) in steps of 1. 1292 func Range(a, b float64) []float64 { 1293 dst := make([]float64, int(math.Max(0, math.Ceil(b-a)))) 1294 return Range_Into(dst, a, b) 1295 } 1296 1297 // Range_Into writes values incrementing from a to b (excl.) in steps of 1 to the destination slice. 1298 func Range_Into(dst []float64, a, b float64) []float64 { 1299 n := int(math.Max(0, math.Ceil(b-a))) 1300 if cap(dst) < n { 1301 panic("destination slice not large enough to hold result") 1302 } 1303 if functions.UseAVX2 { 1304 functions.Range_AVX2_F64(dst, a, n) 1305 } else { 1306 functions.Range_Go(dst, a, n) 1307 } 1308 return dst[:n] 1309 } 1310 1311 // Gather returns a new slice containing just the elements at the given indices. 1312 func Gather(x []float64, idx []int) []float64 { 1313 dst := make([]float64, len(idx)) 1314 return Gather_Into(dst, x, idx) 1315 } 1316 1317 // Gather_Into stores the slice elements at the given indices in the destination slice. 1318 func Gather_Into(dst, x []float64, idx []int) []float64 { 1319 dst = checkCapacity(dst, idx) 1320 checkOverlap(dst, x) 1321 functions.Gather_Go(dst, x, idx) 1322 return dst 1323 } 1324 1325 // Scatter returns a slice of size elements where position idx[i] is set to x[i], for all 1326 // i < len(x) = len(idx). The other elements are set to zero. 1327 func Scatter(x []float64, idx []int, size int) []float64 { 1328 dst := make([]float64, size) 1329 return Scatter_Into(dst, x, idx) 1330 } 1331 1332 // Scatter_Into sets positions idx[i] to x[i] in the destination slice, for all 1333 // i < len(x) = len(idx). The other elements are not modified. 1334 func Scatter_Into(dst, x []float64, idx []int) []float64 { 1335 checkEqualLength(x, idx) 1336 checkOverlap(dst, x) 1337 functions.Scatter_Go(dst, x, idx) 1338 return dst 1339 } 1340 1341 // FromBool creates a slice of floats from a slice of bools by converting all false values to 0 1342 // and all true values to 1. 1343 func FromBool(x []bool) []float64 { 1344 dst := make([]float64, len(x)) 1345 return FromBool_Into(dst, x) 1346 } 1347 1348 // FromBool_Into creates a slice of floats from a slice of bools by converting all false values 1349 // to 0 and all true values to 1. The result is stored in the destination slice. 1350 func FromBool_Into(dst []float64, x []bool) []float64 { 1351 dst = checkCapacity(dst, x) 1352 if functions.UseAVX2 { 1353 functions.FromBool_AVX2_F64(dst, x) 1354 } else { 1355 functions.FromBool_Go(dst, x) 1356 } 1357 return dst 1358 } 1359 1360 // FromInt64 creates a slice of floats from a slice of 64-bit ints. Standard conversion rules 1361 // apply. 1362 func FromInt64(x []int64) []float64 { 1363 dst := make([]float64, len(x)) 1364 return FromInt64_Into(dst, x) 1365 } 1366 1367 // FromInt64_Into creates a slice of floats from a slice of 64-bit ints. Standard conversion 1368 // rules apply. The result is stored in the destination slice. 1369 func FromInt64_Into(dst []float64, x []int64) []float64 { 1370 dst = checkCapacity(dst, x) 1371 if functions.UseAVX2 { 1372 functions.FromInt64_AVX2_F64(dst, x) 1373 } else { 1374 functions.FromNumber_Go(dst, x) 1375 } 1376 return dst 1377 } 1378 1379 // FromInt32 creates a slice of floats from a slice of 32-bit ints. Standard conversion rules 1380 // apply. 1381 func FromInt32(x []int32) []float64 { 1382 dst := make([]float64, len(x)) 1383 return FromInt32_Into(dst, x) 1384 } 1385 1386 // FromInt32_Into creates a slice of floats from a slice of 32-bit ints. Standard conversion 1387 // rules apply. The result is stored in the destination slice. 1388 func FromInt32_Into(dst []float64, x []int32) []float64 { 1389 dst = checkCapacity(dst, x) 1390 if functions.UseAVX2 { 1391 functions.FromInt32_AVX2_F64(dst, x) 1392 } else { 1393 functions.FromNumber_Go(dst, x) 1394 } 1395 return dst 1396 } 1397 1398 // FromFloat32 creates a slice of floats from a slice of 32-bit floats. Standard conversion 1399 // rules apply. 1400 func FromFloat32(x []float32) []float64 { 1401 dst := make([]float64, len(x)) 1402 return FromFloat32_Into(dst, x) 1403 } 1404 1405 // FromFloat32_Into creates a slice of floats from a slice of 32-bit floats. Standard conversion 1406 // rules apply. The result is stored in the destination slice. 1407 func FromFloat32_Into(dst []float64, x []float32) []float64 { 1408 dst = checkCapacity(dst, x) 1409 if functions.UseAVX2 { 1410 functions.FromFloat32_AVX2_F64(dst, x) 1411 } else { 1412 functions.FromNumber_Go(dst, x) 1413 } 1414 return dst 1415 } 1416 1417 // ToBool converts a slice of floats to a slice of bools by setting all zero values to true and 1418 // all non-zero values to false. 1419 func ToBool(x []float64) []bool { 1420 dst := make([]bool, len(x)) 1421 return ToBool_Into(dst, x) 1422 } 1423 1424 // ToBool_Into converts a slice of floats to a slice of bools by setting all zero values to true 1425 // and all non-zero values to false. The result is stored in the destination slice. 1426 func ToBool_Into(dst []bool, x []float64) []bool { 1427 dst = checkCapacity(dst, x) 1428 if functions.UseAVX2 { 1429 functions.ToBool_AVX2_F64(dst, x) 1430 } else { 1431 functions.ToBool_Go(dst, x) 1432 } 1433 return dst 1434 } 1435 1436 // ToInt64 converts a slice of floats to a slice of 64-bit ints. Standard conversion rules apply. 1437 func ToInt64(x []float64) []int64 { 1438 dst := make([]int64, len(x)) 1439 return ToInt64_Into(dst, x) 1440 } 1441 1442 // ToInt64_Into converts a slice of floats to a slice of 64-bit ints. Standard conversion rules 1443 // apply. The result is stored in the destination slice. 1444 func ToInt64_Into(dst []int64, x []float64) []int64 { 1445 dst = checkCapacity(dst, x) 1446 if functions.UseAVX2 { 1447 functions.ToInt64_AVX2_F64(dst, x) 1448 } else { 1449 functions.ToNumber_Go(dst, x) 1450 } 1451 return dst 1452 } 1453 1454 // ToInt32 converts a slice of floats to a slice of 32-bit ints. Standard conversion rules apply. 1455 func ToInt32(x []float64) []int32 { 1456 dst := make([]int32, len(x)) 1457 return ToInt32_Into(dst, x) 1458 } 1459 1460 // ToInt32_Into converts a slice of floats to a slice of 32-bit ints. Standard conversion rules 1461 // apply. The result is stored in the destination slice. 1462 func ToInt32_Into(dst []int32, x []float64) []int32 { 1463 dst = checkCapacity(dst, x) 1464 if functions.UseAVX2 { 1465 functions.ToInt32_AVX2_F64(dst, x) 1466 } else { 1467 functions.ToNumber_Go(dst, x) 1468 } 1469 return dst 1470 } 1471 1472 // ToFloat32 converts a slice of floats to a slice of 32-bit floats. Standard conversion rules 1473 // apply. 1474 func ToFloat32(x []float64) []float32 { 1475 dst := make([]float32, len(x)) 1476 return ToFloat32_Into(dst, x) 1477 } 1478 1479 // ToFloat32_Into converts a slice of floats to a slice of 32-bit floats. Standard conversion 1480 // rules apply. The result is stored in the destination slice. 1481 func ToFloat32_Into(dst []float32, x []float64) []float32 { 1482 dst = checkCapacity(dst, x) 1483 if functions.UseAVX2 { 1484 functions.FromFloat64_AVX2_F32(dst, x) 1485 } else { 1486 functions.ToNumber_Go(dst, x) 1487 } 1488 return dst 1489 } 1490 1491 // Misc 1492 1493 // SetAcceleration toggles simd acceleration. Not thread safe. 1494 func SetAcceleration(enabled bool) { 1495 if enabled && !(cpu.X86.HasAVX2 && cpu.X86.HasFMA) { 1496 panic("acceleration not supported on this platform") 1497 } 1498 functions.UseAVX2 = enabled 1499 } 1500 1501 // Validation 1502 1503 func slicesOverlap[T, F any](x []T, y []F) bool { 1504 if len(x) == 0 || len(y) == 0 { 1505 return false 1506 } 1507 xStart := uintptr(unsafe.Pointer(&x[0])) 1508 xEnd := uintptr(unsafe.Pointer(&x[len(x)-1])) 1509 yStart := uintptr(unsafe.Pointer(&y[0])) 1510 yEnd := uintptr(unsafe.Pointer(&y[len(y)-1])) 1511 return xStart <= yEnd && yStart <= xEnd 1512 } 1513 1514 func checkCapacity[T, F any](dst []T, x []F) []T { 1515 if cap(dst) < len(x) { 1516 panic("destination slice not large enough to hold result") 1517 } 1518 return dst[:len(x)] 1519 } 1520 1521 func checkEqualLength[T, F any](x []T, y []F) { 1522 if len(x) != len(y) { 1523 panic("slices must be of equal length") 1524 } 1525 } 1526 1527 func checkNotEmpty[T any](x []T) { 1528 if len(x) == 0 { 1529 panic("slice must not be empty") 1530 } 1531 } 1532 1533 func checkOverlap[T, F any](x []T, y []F) { 1534 if slicesOverlap(x, y) { 1535 panic("destination slice must not overlap input slice") 1536 } 1537 }