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  }