1 Star 0 Fork 2

王布衣 / num

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
vek.go 39.43 KB
一键复制 编辑 原始数据 按行查看 历史
王布衣 提交于 2024-02-12 09:23 . 调整package
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526
package x64
import (
"gitee.com/quant1x/num/internal/constraints"
"gitee.com/quant1x/num/internal/functions"
"math"
"slices"
"unsafe"
)
// Arithmetic
// Add returns the result of adding two slices element-wise.
func Add(x, y []float64) []float64 {
x = slices.Clone(x)
Add_Inplace(x, y)
return x
}
// Add_Inplace adds a slice element-wise to the first slice, inplace.
func Add_Inplace(x, y []float64) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Add_AVX2_F64(x, y)
} else {
functions.Add_Go(x, y)
}
}
// Add_Into adds two slices element-wise and stores the result in the destination slice.
func Add_Into(dst, x, y []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Add_Inplace(dst, y)
return dst
}
// Sub returns the result of subtracting two slices element-wise.
func Sub(x, y []float64) []float64 {
x = slices.Clone(x)
Sub_Inplace(x, y)
return x
}
// Sub_Inplace subtracts a slice element-wise from the first slice, inplace.
func Sub_Inplace(x, y []float64) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Sub_AVX2_F64(x, y)
} else {
functions.Sub_Go(x, y)
}
}
// Sub_Into subtracts two slices element-wise and stores the result in the destination slice.
func Sub_Into(dst, x, y []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Sub_Inplace(dst, y)
return dst
}
// Mul returns the result of multiplying two slices element-wise.
func Mul(x, y []float64) []float64 {
x = slices.Clone(x)
Mul_Inplace(x, y)
return x
}
// Mul_Inplace multiplies the first slice element-wise by the second, inplace.
func Mul_Inplace(x, y []float64) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Mul_AVX2_F64(x, y)
} else {
functions.Mul_Go(x, y)
}
}
// Mul_Into multiplies two slices element-wise and stores the result in the destination slice.
func Mul_Into(dst, x, y []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Mul_Inplace(dst, y)
return dst
}
// Div returns the result of dividing two slices element-wise.
func Div(x, y []float64) []float64 {
x = slices.Clone(x)
Div_Inplace(x, y)
return x
}
// Div_Inplace divides the first slice element-wise by the second, inplace.
func Div_Inplace(x, y []float64) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Div_AVX2_F64(x, y)
} else {
functions.Div_Go(x, y)
}
}
// Div_Into divides two slices element-wise and stores the result in the destination slice.
func Div_Into(dst, x, y []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Div_Inplace(dst, y)
return dst
}
// AddNumber returns the result of adding a number to each slice element.
func AddNumber(x []float64, a float64) []float64 {
x = slices.Clone(x)
AddNumber_Inplace(x, a)
return x
}
// AddNumber_Inplace adds a number to each slice element, inplace.
func AddNumber_Inplace(x []float64, a float64) {
if functions.UseAVX2 {
functions.AddNumber_AVX2_F64(x, a)
} else {
functions.AddNumber_Go(x, a)
}
}
// AddNumber_Into adds a number to each slice element and stores the result in the
// destination slice.
func AddNumber_Into(dst, x []float64, a float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
AddNumber_Inplace(dst, a)
return dst
}
// SubNumber returns the result of subtracting a number from each slice element.
func SubNumber(x []float64, a float64) []float64 {
x = slices.Clone(x)
SubNumber_Inplace(x, a)
return x
}
// SubNumber_Inplace subtracts a number from each slice element, inplace.
func SubNumber_Inplace(x []float64, a float64) {
if functions.UseAVX2 {
functions.SubNumber_AVX2_F64(x, a)
} else {
functions.SubNumber_Go(x, a)
}
}
// SubNumber_Into subtracts a number from each slice element and stores the result in the
// destination slice.
func SubNumber_Into(dst, x []float64, a float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
SubNumber_Inplace(dst, a)
return dst
}
// MulNumber returns the result of multiplying each slice element by a number.
func MulNumber(x []float64, a float64) []float64 {
x = slices.Clone(x)
MulNumber_Inplace(x, a)
return x
}
// MulNumber_Inplace multiplies each slice element by a number, inplace.
func MulNumber_Inplace(x []float64, a float64) {
if functions.UseAVX2 {
functions.MulNumber_AVX2_F64(x, a)
} else {
functions.MulNumber_Go(x, a)
}
}
// MulNumber_Into multiplies each slice element by a number and stores the result in the
// destination slice.
func MulNumber_Into(dst, x []float64, a float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
MulNumber_Inplace(dst, a)
return dst
}
// DivNumber returns the result of dividing each slice element by a number.
func DivNumber(x []float64, a float64) []float64 {
x = slices.Clone(x)
DivNumber_Inplace(x, a)
return x
}
// DivNumber_Inplace divides each slice element by a number, inplace.
func DivNumber_Inplace(x []float64, a float64) {
if functions.UseAVX2 {
functions.DivNumber_AVX2_F64(x, a)
} else {
functions.DivNumber_Go(x, a)
}
}
// DivNumber_Into divides each slice element by a number and stores the result in the
// destination slice.
func DivNumber_Into(dst, x []float64, a float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
DivNumber_Inplace(dst, a)
return dst
}
// Abs returns the absolute value of each slice element.
func Abs(x []float64) []float64 {
x = slices.Clone(x)
Abs_Inplace(x)
return x
}
// Abs_Inplace computes the absolute value of each slice element, inplace.
func Abs_Inplace(x []float64) {
if functions.UseAVX2 {
functions.Abs_AVX2_F64(x)
} else {
functions.Abs_Go_F64(x)
}
}
// Abs_Into computes the absolute value of each slice element and stores the result in the
// destination slice.
func Abs_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Abs_Inplace(dst)
return dst
}
// Neg returns the additive inverse of each slice element.
func Neg(x []float64) []float64 {
x = slices.Clone(x)
Neg_Inplace(x)
return x
}
// Neg_Inplace computes the additive inverse of each slice element, inplace.
func Neg_Inplace(x []float64) {
if functions.UseAVX2 {
functions.Neg_AVX2_F64(x)
} else {
functions.Neg_Go(x)
}
}
// Neg_Into computes the additive inverse of each slice element and stores the result in the
// destination slice.
func Neg_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Neg_Inplace(dst)
return dst
}
// Inv returns the multiplicative inverse of each slice element.
func Inv(x []float64) []float64 {
x = slices.Clone(x)
Inv_Inplace(x)
return x
}
// Inv_Inplace computes the multiplicative inverse of each slice element, inplace.
func Inv_Inplace(x []float64) {
if functions.UseAVX2 {
functions.Inv_AVX2_F64(x)
} else {
functions.Inv_Go(x)
}
}
// Inv_Into computes the multiplicative inverse of each slice element and stores the result
// in the destination slice.
func Inv_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Inv_Inplace(dst)
return dst
}
// Aggregates
// Sum returns the sum of all elements in a slice.
func Sum(x []float64) float64 {
if functions.UseAVX2 {
return functions.Sum_AVX2_F64(x)
} else {
return functions.Sum_Go(x)
}
}
// CumSum returns the cumulative sum of a slice. The element at index i equals the sum of x[:i+1].
func CumSum(x []float64) []float64 {
x = slices.Clone(x)
CumSum_Inplace(x)
return x
}
// CumSum_Inplace computes the cumulative sum of a slice, inplace. The new element at index i
// equals the sum of x[:i+1].
func CumSum_Inplace(x []float64) {
if functions.UseAVX2 {
functions.CumSum_AVX2_F64(x)
} else {
functions.CumSum_Go(x)
}
}
// CumSum_Into computes the cumulative sum of a slice and stores the result in the destination
// slice. The element at index i equals the sum of x[:i+1].
func CumSum_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
CumSum_Inplace(dst)
return dst
}
// Prod returns the product of all elements in a slice.
func Prod(x []float64) float64 {
if functions.UseAVX2 {
return functions.Prod_AVX2_F64(x)
} else {
return functions.Prod_Go(x)
}
}
// CumProd returns the cumulative product of a slice. The element at index i equals the product
// of x[:i+1].
func CumProd(x []float64) []float64 {
x = slices.Clone(x)
CumProd_Inplace(x)
return x
}
// CumProd_Inplace computes the cumulative product of a slice, inplace. The new element at index i
// equals the product of x[:i+1].
func CumProd_Inplace(x []float64) {
if functions.UseAVX2 {
functions.CumProd_AVX2_F64(x)
} else {
functions.CumProd_Go(x)
}
}
// CumProd_Into computes the cumulative product of a slice and stores the result in the destination
// slice. The element at index i equals the product of x[:i+1].
func CumProd_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
CumProd_Inplace(dst)
return dst
}
// Mean returns the arithmetic average of the slice elements.
func Mean(x []float64) float64 {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.Mean_AVX2_F64(x)
} else {
return functions.Mean_Go(x)
}
}
// Median returns the median value of the slice elements.
func Median(x []float64) float64 {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.Median_AVX2_F64(x)
} else {
return functions.Median_Go(x)
}
}
// Quantile returns the q-th quantile of the slice elements. The value of q should be between
// 0 and 1 (inclusive).
func Quantile(x []float64, q float64) float64 {
if q < 0 || q > 1 {
panic("value of q should be between 0 and 1")
}
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.Quantile_AVX2_F64(x, q)
} else {
return functions.Quantile_Go(x, q)
}
}
// Distance
// Dot returns the dot product of two vectors.
func Dot(x, y []float64) float64 {
checkNotEmpty(x)
checkEqualLength(x, y)
if functions.UseAVX2 {
return functions.Dot_AVX2_F64(x, y)
} else {
return functions.Dot_Go(x, y)
}
}
// Norm returns the Euclidean norm of a vector, i.e. its length.
func Norm(x []float64) float64 {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.Norm_AVX2_F64(x)
} else {
return functions.Norm_Go_F64(x)
}
}
// Distance returns the Euclidean distance between two vectors.
func Distance(x, y []float64) float64 {
checkNotEmpty(x)
checkEqualLength(x, y)
if functions.UseAVX2 {
return functions.Distance_AVX2_F64(x, y)
} else {
return functions.Distance_Go_F64(x, y)
}
}
// ManhattanNorm returns the sum of absolute values of the slice elements.
func ManhattanNorm(x []float64) float64 {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.ManhattanNorm_AVX2_F64(x)
} else {
return functions.ManhattanNorm_Go_F64(x)
}
}
// ManhattanDistance returns the sum of element-wise absolute differences between two slices.
func ManhattanDistance(x, y []float64) float64 {
checkNotEmpty(x)
checkEqualLength(x, y)
if functions.UseAVX2 {
return functions.ManhattanDistance_AVX2_F64(x, y)
} else {
return functions.ManhattanDistance_Go_F64(x, y)
}
}
// CosineSimilarity returns the cosine similarity of two vectors.
func CosineSimilarity(x, y []float64) float64 {
checkNotEmpty(x)
checkEqualLength(x, y)
if functions.UseAVX2 {
return functions.CosineSimilarity_AVX2_F64(x, y)
} else {
return functions.CosineSimilarity_Go_F64(x, y)
}
}
// Matrices
func checkDimensions[T constraints.Float](x, y []T, n int) (int, int) {
if n < 1 || len(x) == 0 || len(y) == 0 {
panic("slices must be non-empty with positive n")
}
m := len(x) / n
p := len(y) / n
if m*n < len(x) || n*p < len(y) {
panic("slice lengths must be multiple of n")
}
return m, p
}
// MatMul multiplies an m-by-n and n-by-p matrix and returns the resulting m-by-p matrix.
// The matrices should be in row-major order. To multiply a matrix and a vector pass an
// n-by-1 matrix.
func MatMul(x, y []float64, n int) []float64 {
m, p := checkDimensions(x, y, n)
dst := make([]float64, m*p)
if functions.UseAVX2 {
functions.MatMul_Parallel_AVX2_F64(dst, x, y, m, n, p)
} else {
functions.MatMul_Parallel_Go(dst, x, y, m, n, p)
}
return dst
}
// MatMul_Into multiplies an m-by-n and n-by-p matrix and stores the resulting m-by-p matrix
// in the destination slice. The matrices should be in row-major order. To multiply a matrix
// and a vector pass an n-by-1 matrix.
func MatMul_Into(dst, x, y []float64, n int) []float64 {
m, p := checkDimensions(x, y, n)
if cap(dst) < m*p {
panic("destination slice not large enough to hold result")
}
Zeros_Into(dst, m*p)
if functions.UseAVX2 {
functions.MatMul_Parallel_AVX2_F64(dst, x, y, m, n, p)
} else {
functions.MatMul_Parallel_Go(dst, x, y, m, n, p)
}
return dst[:m*p]
}
// Mat4Mul multiplies two 4-by-4 matrices and returns the resulting 4-by-4 matrix. The matrices
// should be in row-major order. To multiply a matrix and a vector batch them into groups of 4.
func Mat4Mul(x, y []float64) []float64 {
var dst [16]float64
return Mat4Mul_Into(dst[:], x, y)
}
// Mat4Mul_Into multiplies two 4-by-4 matrices and stores the resulting 4-by-4 matrix in the
// destination slice. The matrices should be in row-major order. To multiply a matrix and a vector
// batch them into groups of 4.
func Mat4Mul_Into(dst, x, y []float64) []float64 {
// Note: skipping overlap check due to overhead
if cap(dst) < 16 || len(x) != 16 || len(y) != 16 {
panic("slices must be length 16 (4 by 4)")
}
if functions.UseAVX2 {
functions.Mat4Mul_AVX2_F64(dst, x, y)
} else {
functions.Mat4Mul_Go(dst, x, y)
}
return dst[:16]
}
// Special
// Sqrt returns the square root of each slice element.
func Sqrt(x []float64) []float64 {
x = slices.Clone(x)
Sqrt_Inplace(x)
return x
}
// Sqrt_Inplace computes the square root of each slice element, inplace.
func Sqrt_Inplace(x []float64) {
if functions.UseAVX2 {
functions.Sqrt_AVX2_F64(x)
} else {
functions.Sqrt_Go_F64(x)
}
}
// Sqrt_Into computes the square root of each slice element and stores the result in the
// destination slice.
func Sqrt_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Sqrt_Inplace(dst)
return dst
}
// Round returns the result of rounding each slice element to the nearest integer value.
func Round(x []float64) []float64 {
x = slices.Clone(x)
Round_Inplace(x)
return x
}
// Round_Inplace rounds each slice element to the nearest integer value, inplace.
func Round_Inplace(x []float64) {
if functions.UseAVX2 {
functions.Round_AVX2_F64(x)
} else {
functions.Round_Go_F64(x)
}
}
// Round_Into rounds each slice element to the nearest integer value and stores the result
// in the destination slice.
func Round_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Round_Inplace(dst)
return dst
}
// Floor returns the result of rounding each slice element to the nearest lesser integer value.
func Floor(x []float64) []float64 {
x = slices.Clone(x)
Floor_Inplace(x)
return x
}
// Floor_Inplace rounds each slice element to the nearest lesser integer value, inplace.
func Floor_Inplace(x []float64) {
if functions.UseAVX2 {
functions.Floor_AVX2_F64(x)
} else {
functions.Floor_Go_F64(x)
}
}
// Floor_Into rounds each slice element to the nearest lesser integer value and stores the result
// in the destination slice.
func Floor_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Floor_Inplace(dst)
return dst
}
// Ceil returns the result of rounding each slice element to the nearest greater integer value.
func Ceil(x []float64) []float64 {
x = slices.Clone(x)
Ceil_Inplace(x)
return x
}
// Ceil_Inplace rounds each slice element to the nearest greater integer value, inplace.
func Ceil_Inplace(x []float64) {
if functions.UseAVX2 {
functions.Ceil_AVX2_F64(x)
} else {
functions.Ceil_Go_F64(x)
}
}
// Ceil_Into rounds each slice element to the nearest greater integer value and stores the result
// in the destination slice.
func Ceil_Into(dst, x []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Ceil_Inplace(dst)
return dst
}
// Pow returns the elements in the first slice raised to the power in the second.
func Pow(x, y []float64) []float64 {
x = slices.Clone(x)
Pow_Inplace(x, y)
return x
}
// Pow_Inplace raises the elements in the first slice to the power in the second, inplace.
func Pow_Inplace(x, y []float64) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Pow_AVX2_F64(x, y)
} else {
functions.Pow_Go_F64(x, y)
}
}
// Pow_Into raises the elements in the first slice to the power in the second and stores the
// result in the destination slice.
func Pow_Into(dst, x, y []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Pow_Inplace(dst, y)
return dst
}
// Comparison
// Min returns the minimum value of a slice.
func Min(x []float64) float64 {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.Min_AVX2_F64(x)
} else {
return functions.Min_Go(x)
}
}
// ArgMin returns the (first) index of the minimum value of a slice.
func ArgMin(x []float64) int {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.ArgMin_AVX2_F64(x)
} else {
return functions.ArgMin_Go(x)
}
}
// Minimum returns the element-wise minimum values between two slices.
func Minimum(x, y []float64) []float64 {
x = slices.Clone(x)
Minimum_Inplace(x, y)
return x
}
// Minimum_Inplace compares two slices element-wise and replaces the values in the first slice
// with the minimum value.
func Minimum_Inplace(x, y []float64) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Minimum_AVX2_F64(x, y)
} else {
functions.Minimum_Go(x, y)
}
}
// Minimum_Into compares two slices element-wise and stores the minimum values in the destination
// slice.
func Minimum_Into(dst, x, y []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Minimum_Inplace(dst, y)
return dst
}
// MinimumNumber returns the minimum of a number and each slice element.
func MinimumNumber(x []float64, a float64) []float64 {
x = slices.Clone(x)
MinimumNumber_Inplace(x, a)
return x
}
// MinimumNumber_Inplace compares a number to each slice element and replaces the values in the
// slice with the minimum value.
func MinimumNumber_Inplace(x []float64, a float64) {
if functions.UseAVX2 {
functions.MinimumNumber_AVX2_F64(x, a)
} else {
functions.MinimumNumber_Go(x, a)
}
}
// MinimumNumber_Into compares a number to each slice element and stores the minimum values in
// the destination slice.
func MinimumNumber_Into(dst, x []float64, a float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
MinimumNumber_Inplace(dst, a)
return dst
}
// Max returns the maximum value of a slice.
func Max(x []float64) float64 {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.Max_AVX2_F64(x)
} else {
return functions.Max_Go(x)
}
}
// ArgMax returns the (first) index of the maximum value of a slice.
func ArgMax(x []float64) int {
checkNotEmpty(x)
if functions.UseAVX2 {
return functions.ArgMax_AVX2_F64(x)
} else {
return functions.ArgMax_Go(x)
}
}
// Maximum returns the element-wise maximum values between two slices.
func Maximum(x, y []float64) []float64 {
x = slices.Clone(x)
Maximum_Inplace(x, y)
return x
}
// Maximum_Inplace compares two slices element-wise and replaces the values in the first slice
// with the maximum value.
func Maximum_Inplace(x, y []float64) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Maximum_AVX2_F64(x, y)
} else {
functions.Maximum_Go(x, y)
}
}
// Maximum_Into compares two slices element-wise and stores the maximum values in the destination
// slice.
func Maximum_Into(dst, x, y []float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Maximum_Inplace(dst, y)
return dst
}
// MaximumNumber returns the maximum of a number and each slice element.
func MaximumNumber(x []float64, a float64) []float64 {
x = slices.Clone(x)
MaximumNumber_Inplace(x, a)
return x
}
// MaximumNumber_Inplace compares a number to each slice element and replaces the values in the
// slice with the maximum value.
func MaximumNumber_Inplace(x []float64, a float64) {
if functions.UseAVX2 {
functions.MaximumNumber_AVX2_F64(x, a)
} else {
functions.MaximumNumber_Go(x, a)
}
}
// MaximumNumber_Into compares a number to each slice element and stores the maximum values in
// the destination slice.
func MaximumNumber_Into(dst, x []float64, a float64) []float64 {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
MaximumNumber_Inplace(dst, a)
return dst
}
// Find returns the index of the first slice element equal to the given value, or -1 if not found.
func Find(x []float64, a float64) int {
if functions.UseAVX2 {
idx := functions.Find_AVX2_F64(x, a)
if idx == len(x) {
return -1
}
return idx
} else {
return functions.Find_Go(x, a)
}
}
// Lt returns an element-wise "less than" comparison between two slices.
func Lt(x, y []float64) []bool {
dst := make([]bool, len(x))
return Lt_Into(dst, x, y)
}
// Lt_Into stores an element-wise "less than" comparison between two slices in the destination
// slice.
func Lt_Into(dst []bool, x, y []float64) []bool {
checkEqualLength(x, y)
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.Lt_AVX2_F64(dst, x, y)
} else {
functions.Lt_Go(dst, x, y)
}
return dst
}
// LtNumber returns an element-wise "less than" comparison between each slice element and
// a number.
func LtNumber(x []float64, a float64) []bool {
dst := make([]bool, len(x))
return LtNumber_Into(dst, x, a)
}
// LtNumber_Into stores an element-wise "less than" comparison between each slice element
// and a number in the destination slice.
func LtNumber_Into(dst []bool, x []float64, a float64) []bool {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.LtNumber_AVX2_F64(dst, x, a)
} else {
functions.LtNumber_Go(dst, x, a)
}
return dst
}
// Lte returns an element-wise "less than or equal" comparison between two slices.
func Lte(x, y []float64) []bool {
dst := make([]bool, len(x))
return Lte_Into(dst, x, y)
}
// Lte_Into stores an element-wise "less than or equal" comparison between two slices in the
// destination slice.
func Lte_Into(dst []bool, x, y []float64) []bool {
checkEqualLength(x, y)
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.Lte_AVX2_F64(dst, x, y)
} else {
functions.Lte_Go(dst, x, y)
}
return dst
}
// LteNumber returns an element-wise "less than or equal" comparison between each slice element
// and a number.
func LteNumber(x []float64, a float64) []bool {
dst := make([]bool, len(x))
return LteNumber_Into(dst, x, a)
}
// LteNumber_Into stores an element-wise "less than or equal" comparison between each slice
// element and a number in the destination slice.
func LteNumber_Into(dst []bool, x []float64, a float64) []bool {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.LteNumber_AVX2_F64(dst, x, a)
} else {
functions.LteNumber_Go(dst, x, a)
}
return dst
}
// Gt returns an element-wise "greater than" comparison between two slices.
func Gt(x, y []float64) []bool {
dst := make([]bool, len(x))
return Gt_Into(dst, x, y)
}
// Gt_Into stores an element-wise "greater than" comparison between two slices in the destination
// slice.
func Gt_Into(dst []bool, x, y []float64) []bool {
checkEqualLength(x, y)
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.Gt_AVX2_F64(dst, x, y)
} else {
functions.Gt_Go(dst, x, y)
}
return dst
}
// GtNumber returns an element-wise "greater than" comparison between each slice element and
// a number.
func GtNumber(x []float64, a float64) []bool {
dst := make([]bool, len(x))
return GtNumber_Into(dst, x, a)
}
// GtNumber_Into stores an element-wise "greater than" comparison between each slice element and
// a number in the destination slice.
func GtNumber_Into(dst []bool, x []float64, a float64) []bool {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.GtNumber_AVX2_F64(dst, x, a)
} else {
functions.GtNumber_Go(dst, x, a)
}
return dst
}
// Gte returns an element-wise "greater than or equal" comparison between two slices.
func Gte(x, y []float64) []bool {
dst := make([]bool, len(x))
return Gte_Into(dst, x, y)
}
// Gte_Into stores an element-wise "greater than or equal" comparison between two slices in the
// destination slice.
func Gte_Into(dst []bool, x, y []float64) []bool {
checkEqualLength(x, y)
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.Gte_AVX2_F64(dst, x, y)
} else {
functions.Gte_Go(dst, x, y)
}
return dst
}
// GteNumber returns an element-wise "greater than or equal" comparison between each slice element
// and a number.
func GteNumber(x []float64, a float64) []bool {
dst := make([]bool, len(x))
return GteNumber_Into(dst, x, a)
}
// GteNumber_Into stores an element-wise "greater than or equal" comparison between each slice
// element and a number in the destination slice.
func GteNumber_Into(dst []bool, x []float64, a float64) []bool {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.GteNumber_AVX2_F64(dst, x, a)
} else {
functions.GteNumber_Go(dst, x, a)
}
return dst
}
// Eq returns an element-wise equality comparison between two slices.
func Eq(x, y []float64) []bool {
dst := make([]bool, len(x))
return Eq_Into(dst, x, y)
}
// Eq_Into stores an element-wise equality comparison between two slices in the destination
// slice.
func Eq_Into(dst []bool, x, y []float64) []bool {
checkEqualLength(x, y)
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.Eq_AVX2_F64(dst, x, y)
} else {
functions.Eq_Go(dst, x, y)
}
return dst
}
// EqNumber returns an element-wise equality comparison between each slice element and a number.
func EqNumber(x []float64, a float64) []bool {
dst := make([]bool, len(x))
return EqNumber_Into(dst, x, a)
}
// EqNumber_Into stores an element-wise equality comparison between each slice element and a
// number in the destination slice.
func EqNumber_Into(dst []bool, x []float64, a float64) []bool {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.EqNumber_AVX2_F64(dst, x, a)
} else {
functions.EqNumber_Go(dst, x, a)
}
return dst
}
// Neq returns an element-wise "not equal" comparison between two slices.
func Neq(x, y []float64) []bool {
dst := make([]bool, len(x))
return Neq_Into(dst, x, y)
}
// Neq_Into stores an element-wise "not equal" comparison between two slices in the destination
// slice.
func Neq_Into(dst []bool, x, y []float64) []bool {
checkEqualLength(x, y)
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.Neq_AVX2_F64(dst, x, y)
} else {
functions.Neq_Go(dst, x, y)
}
return dst
}
// NeqNumber returns an element-wise "not equal" comparison between each slice element and a number.
func NeqNumber(x []float64, a float64) []bool {
dst := make([]bool, len(x))
return NeqNumber_Into(dst, x, a)
}
// NeqNumber_Into stores an element-wise "not equal" comparison between each slice element and a
// number in the destination slice.
func NeqNumber_Into(dst []bool, x []float64, a float64) []bool {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.NeqNumber_AVX2_F64(dst, x, a)
} else {
functions.NeqNumber_Go(dst, x, a)
}
return dst
}
// Boolean
// Not returns the logical negation of each slice element.
func Not(x []bool) []bool {
x = slices.Clone(x)
Not_Inplace(x)
return x
}
// Not_Inplace computes the logical negation of each slice element, inplace.
func Not_Inplace(x []bool) {
if functions.UseAVX2 {
functions.Not_AVX2(x)
} else {
functions.Not_Go(x)
}
}
// Not_Into stores the logical negation of each slice element in the destination slice.
func Not_Into(dst, x []bool) []bool {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Not_Inplace(dst)
return dst
}
// And returns the element-wise logical "and" operation between two slices.
func And(x, y []bool) []bool {
x = slices.Clone(x)
And_Inplace(x, y)
return x
}
// And_Inplace computes the element-wise logical "and" operation between two slices, inplace.
func And_Inplace(x, y []bool) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.And_AVX2(x, y)
} else {
functions.And_Go(x, y)
}
}
// And_Into stores the element-wise logical "and" operation between two slices in the destination
// slice.
func And_Into(dst, x, y []bool) []bool {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
And_Inplace(dst, y)
return dst
}
// Or returns the element-wise logical "or" operation between two slices.
func Or(x, y []bool) []bool {
x = slices.Clone(x)
Or_Inplace(x, y)
return x
}
// Or_Inplace computes the element-wise logical "or" operation between two slices, inplace.
func Or_Inplace(x, y []bool) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Or_AVX2(x, y)
} else {
functions.Or_Go(x, y)
}
}
// Or_Into stores the element-wise logical "or" operation between two slices in the destination
// slice.
func Or_Into(dst, x, y []bool) []bool {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Or_Inplace(dst, y)
return dst
}
// Xor returns the element-wise "exclusive or" operation between two slices.
func Xor(x, y []bool) []bool {
x = slices.Clone(x)
Xor_Inplace(x, y)
return x
}
// Xor_Inplace computes the element-wise "exclusive or" operation between two slices, inplace.
func Xor_Inplace(x, y []bool) {
checkEqualLength(x, y)
checkOverlap(x, y)
if functions.UseAVX2 {
functions.Xor_AVX2(x, y)
} else {
functions.Xor_Go(x, y)
}
}
// Xor_Into stores the element-wise "exclusive or" operation between two slices in the destination
// slice.
func Xor_Into(dst, x, y []bool) []bool {
dst = checkCapacity(dst, x)
checkOverlap(dst, x)
copy(dst, x)
Xor_Inplace(dst, y)
return dst
}
// Select returns the slice elements for which the corresponding boolean values are true.
func Select(x []float64, y []bool) []float64 {
dst := make([]float64, 0)
return Select_Into(dst, x, y)
}
// Select_Into stores the slice elements for which the corresponding boolean values are true in
// the destination slice. This function grows the destination slice if the selection yields more
// values than it has capacity for.
func Select_Into(dst, x []float64, y []bool) []float64 {
checkEqualLength(x, y)
//checkOverlap(dst[:cap(dst)], x)
return functions.Select_Go(dst, x, y)
}
// All returns whether all boolean values in the slice are true.
func All(x []bool) bool {
if functions.UseAVX2 {
return functions.All_AVX2(x) != 0
} else {
return functions.All_Go(x)
}
}
// Any returns whether at least one boolean value in the slice is true.
func Any(x []bool) bool {
if functions.UseAVX2 {
return functions.Any_AVX2(x) != 0
} else {
return functions.Any_Go(x)
}
}
// None returns whether none of the boolean values in the slice are true.
func None(x []bool) bool {
if functions.UseAVX2 {
return functions.None_AVX2(x) != 0
} else {
return functions.None_Go(x)
}
}
// Count returns the number of boolean values that are true.
func Count(x []bool) int {
if functions.UseAVX2 {
return functions.Count_AVX2(x)
} else {
return functions.Count_Go(x)
}
}
// Construction
// Zeros returns a new slice of length n filled with zeros.
func Zeros(n int) []float64 {
if n < 0 {
panic("n must be positive")
}
dst := make([]float64, n)
return Repeat_Into(dst, 0, n)
}
// Zeros_Into sets the first n elements in the destination slice to zero.
func Zeros_Into(dst []float64, n int) []float64 {
return Repeat_Into(dst, 0, n)
}
// Ones returns a new slice of length n filled with ones.
func Ones(n int) []float64 {
if n < 0 {
panic("n must be positive")
}
dst := make([]float64, n)
return Repeat_Into(dst, 1, n)
}
// Ones_Into sets the first n elements in the destination slice to one.
func Ones_Into(dst []float64, n int) []float64 {
return Repeat_Into(dst, 1, n)
}
// Repeat returns a new slice of length n filled with the given value.
func Repeat(a float64, n int) []float64 {
if n < 0 {
panic("n must be positive")
}
dst := make([]float64, n)
return Repeat_Into(dst, a, n)
}
// Repeat_Into sets the first n elements in the destination slice to the given value.
func Repeat_Into(dst []float64, a float64, n int) []float64 {
if n < 0 {
panic("n must be positive")
}
if cap(dst) < n {
panic("destination slice not large enough to hold result")
}
if functions.UseAVX2 {
functions.Repeat_AVX2_F64(dst, a, n)
} else {
functions.Repeat_Go(dst, a, n)
}
return dst[:n]
}
// Range returns a new slice with values incrementing from a to b (excl.) in steps of 1.
func Range(a, b float64) []float64 {
dst := make([]float64, int(math.Max(0, math.Ceil(b-a))))
return Range_Into(dst, a, b)
}
// Range_Into writes values incrementing from a to b (excl.) in steps of 1 to the destination slice.
func Range_Into(dst []float64, a, b float64) []float64 {
n := int(math.Max(0, math.Ceil(b-a)))
if cap(dst) < n {
panic("destination slice not large enough to hold result")
}
if functions.UseAVX2 {
functions.Range_AVX2_F64(dst, a, n)
} else {
functions.Range_Go(dst, a, n)
}
return dst[:n]
}
// Gather returns a new slice containing just the elements at the given indices.
func Gather(x []float64, idx []int) []float64 {
dst := make([]float64, len(idx))
return Gather_Into(dst, x, idx)
}
// Gather_Into stores the slice elements at the given indices in the destination slice.
func Gather_Into(dst, x []float64, idx []int) []float64 {
dst = checkCapacity(dst, idx)
checkOverlap(dst, x)
functions.Gather_Go(dst, x, idx)
return dst
}
// Scatter returns a slice of size elements where position idx[i] is set to x[i], for all
// i < len(x) = len(idx). The other elements are set to zero.
func Scatter(x []float64, idx []int, size int) []float64 {
dst := make([]float64, size)
return Scatter_Into(dst, x, idx)
}
// Scatter_Into sets positions idx[i] to x[i] in the destination slice, for all
// i < len(x) = len(idx). The other elements are not modified.
func Scatter_Into(dst, x []float64, idx []int) []float64 {
checkEqualLength(x, idx)
checkOverlap(dst, x)
functions.Scatter_Go(dst, x, idx)
return dst
}
// FromBool creates a slice of floats from a slice of bools by converting all false values to 0
// and all true values to 1.
func FromBool(x []bool) []float64 {
dst := make([]float64, len(x))
return FromBool_Into(dst, x)
}
// FromBool_Into creates a slice of floats from a slice of bools by converting all false values
// to 0 and all true values to 1. The result is stored in the destination slice.
func FromBool_Into(dst []float64, x []bool) []float64 {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.FromBool_AVX2_F64(dst, x)
} else {
functions.FromBool_Go(dst, x)
}
return dst
}
// FromInt64 creates a slice of floats from a slice of 64-bit ints. Standard conversion rules
// apply.
func FromInt64(x []int64) []float64 {
dst := make([]float64, len(x))
return FromInt64_Into(dst, x)
}
// FromInt64_Into creates a slice of floats from a slice of 64-bit ints. Standard conversion
// rules apply. The result is stored in the destination slice.
func FromInt64_Into(dst []float64, x []int64) []float64 {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.FromInt64_AVX2_F64(dst, x)
} else {
functions.FromNumber_Go(dst, x)
}
return dst
}
// FromInt32 creates a slice of floats from a slice of 32-bit ints. Standard conversion rules
// apply.
func FromInt32(x []int32) []float64 {
dst := make([]float64, len(x))
return FromInt32_Into(dst, x)
}
// FromInt32_Into creates a slice of floats from a slice of 32-bit ints. Standard conversion
// rules apply. The result is stored in the destination slice.
func FromInt32_Into(dst []float64, x []int32) []float64 {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.FromInt32_AVX2_F64(dst, x)
} else {
functions.FromNumber_Go(dst, x)
}
return dst
}
// FromFloat32 creates a slice of floats from a slice of 32-bit floats. Standard conversion
// rules apply.
func FromFloat32(x []float32) []float64 {
dst := make([]float64, len(x))
return FromFloat32_Into(dst, x)
}
// FromFloat32_Into creates a slice of floats from a slice of 32-bit floats. Standard conversion
// rules apply. The result is stored in the destination slice.
func FromFloat32_Into(dst []float64, x []float32) []float64 {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.FromFloat32_AVX2_F64(dst, x)
} else {
functions.FromNumber_Go(dst, x)
}
return dst
}
// ToBool converts a slice of floats to a slice of bools by setting all zero values to true and
// all non-zero values to false.
func ToBool(x []float64) []bool {
dst := make([]bool, len(x))
return ToBool_Into(dst, x)
}
// ToBool_Into converts a slice of floats to a slice of bools by setting all zero values to true
// and all non-zero values to false. The result is stored in the destination slice.
func ToBool_Into(dst []bool, x []float64) []bool {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.ToBool_AVX2_F64(dst, x)
} else {
functions.ToBool_Go(dst, x)
}
return dst
}
// ToInt64 converts a slice of floats to a slice of 64-bit ints. Standard conversion rules apply.
func ToInt64(x []float64) []int64 {
dst := make([]int64, len(x))
return ToInt64_Into(dst, x)
}
// ToInt64_Into converts a slice of floats to a slice of 64-bit ints. Standard conversion rules
// apply. The result is stored in the destination slice.
func ToInt64_Into(dst []int64, x []float64) []int64 {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.ToInt64_AVX2_F64(dst, x)
} else {
functions.ToNumber_Go(dst, x)
}
return dst
}
// ToInt32 converts a slice of floats to a slice of 32-bit ints. Standard conversion rules apply.
func ToInt32(x []float64) []int32 {
dst := make([]int32, len(x))
return ToInt32_Into(dst, x)
}
// ToInt32_Into converts a slice of floats to a slice of 32-bit ints. Standard conversion rules
// apply. The result is stored in the destination slice.
func ToInt32_Into(dst []int32, x []float64) []int32 {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.ToInt32_AVX2_F64(dst, x)
} else {
functions.ToNumber_Go(dst, x)
}
return dst
}
// ToFloat32 converts a slice of floats to a slice of 32-bit floats. Standard conversion rules
// apply.
func ToFloat32(x []float64) []float32 {
dst := make([]float32, len(x))
return ToFloat32_Into(dst, x)
}
// ToFloat32_Into converts a slice of floats to a slice of 32-bit floats. Standard conversion
// rules apply. The result is stored in the destination slice.
func ToFloat32_Into(dst []float32, x []float64) []float32 {
dst = checkCapacity(dst, x)
if functions.UseAVX2 {
functions.FromFloat64_AVX2_F32(dst, x)
} else {
functions.ToNumber_Go(dst, x)
}
return dst
}
// Validation
func slicesOverlap[T, F any](x []T, y []F) bool {
if len(x) == 0 || len(y) == 0 {
return false
}
xStart := uintptr(unsafe.Pointer(&x[0]))
xEnd := uintptr(unsafe.Pointer(&x[len(x)-1]))
yStart := uintptr(unsafe.Pointer(&y[0]))
yEnd := uintptr(unsafe.Pointer(&y[len(y)-1]))
return xStart <= yEnd && yStart <= xEnd
}
func checkCapacity[T, F any](dst []T, x []F) []T {
if cap(dst) < len(x) {
panic("destination slice not large enough to hold result")
}
return dst[:len(x)]
}
func checkEqualLength[T, F any](x []T, y []F) {
if len(x) != len(y) {
panic("slices must be of equal length")
}
}
func checkNotEmpty[T any](x []T) {
if len(x) == 0 {
panic("slice must not be empty")
}
}
func checkOverlap[T, F any](x []T, y []F) {
if slicesOverlap(x, y) {
panic("destination slice must not overlap input slice")
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/quant1x/num.git
git@gitee.com:quant1x/num.git
quant1x
num
num
v0.3.1

搜索帮助

Bbcd6f05 5694891 0cc6727d 5694891