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