gitee.com/quant1x/gox@v1.7.6/num/vek_arm64.go (about)

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