gitee.com/quant1x/num@v0.3.2/x64/vek.go (about)

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