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