// Copyright 2026 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package sgutil import ( "bytes" "io" "text/template" ) type TforAsBits interface { ElemBits() int Name_() string } const ( ToBitsName = "ToBits" ToIntsName = "BitsToInt{{.To.ElemBits}}" ConvertToIntName = "ConvertToInt{{.To.ElemBits}}" ConvertToUintName = "ConvertToUint{{.From.ElemBits}}" // backwards because done with ToInts ToFloatsName = "BitsToFloat{{.To.ElemBits}}" ReshapeName = "ReshapeToUint{{.To.ElemBits}}s" ) func templateOf(name, text string) *template.Template { return template.Must(template.New(name).Parse(text)) } var ToBitsCall = templateOf("toBitsCall", "."+ToBitsName+"()") var ToIntsCall = templateOf("toBitsCall", "."+ToIntsName+"()") var ToFloatsCall = templateOf("toBitsCall", "."+ToFloatsName+"()") var ReshapeCall = templateOf("toBitsCall", "."+ReshapeName+"()") var ToBitsDcl = templateOf("toBitsDcl", ` // `+ToBitsName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector func (x {{.From.Name_}}) `+ToBitsName+`() {{.To.Name_}} `) // ToBitsIntrinsic is used in a uint -> T context, but reverse, so T is method receiver. var ToBitsIntrinsic = templateOf("toBitsIntrin", `{{.To.Name_}}.`+ToBitsName) var ToIntsDcl = templateOf("toIntsDcl", ` // `+ToIntsName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector func (x {{.From.Name_}}) `+ToIntsName+`() {{.To.Name_}} // `+ConvertToIntName+` converts a {{.From.Name_}} vector to a {{.To.Name_}} vector func (x {{.From.Name_}}) `+ConvertToIntName+`() {{.To.Name_}} // `+ConvertToUintName+` converts a {{.To.Name_}} vector to a {{.From.Name_}} vector func (x {{.To.Name_}}) `+ConvertToUintName+`() {{.From.Name_}} `) var ToIntsIntrinsic = templateOf("toIntsIntrin", `{{.From.Name_}}.`+ToIntsName) var CvtToIntsIntrinsic = templateOf("cvtToIntIntrin", `{{.From.Name_}}.`+ConvertToIntName) // Also used in a to-from-reversed context. var CvtToUintsIntrinsic = templateOf("cvtToUintIntrin", `{{.To.Name_}}.`+ConvertToUintName) var ToFloatsDcl = templateOf("toFloatsDcl", ` // `+ToFloatsName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector func (x {{.From.Name_}}) `+ToFloatsName+`() {{.To.Name_}} `) var ToFloatsIntrinsic = templateOf("toFloatsIntrin", `{{.From.Name_}}.`+ToFloatsName) var ReshapeDcl = templateOf("reshapeDcl", ` // `+ReshapeName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector func (x {{.From.Name_}}) `+ReshapeName+`() {{.To.Name_}} `) var ReshapeIntrinsic = templateOf("reshapeIntrinsic", `{{.From.Name_}}.`+ReshapeName) var AsOp = templateOf("asConversion", ` // As{{.To.Name}} reinterprets the bits of a {{.From.Name}} vector as a {{.To.Name}} vector // // Deprecated: use combinations of ToBits, BitsTo{Int,Float}, ReshapeToUint // //go:fix inline func (x {{.From.Name}}) As{{.To.Name}}() {{.To.Name}} { return x{{.AsTranslation}} } `) type AsConversion struct { From, To TforAsBits } func Conversion(from, to TforAsBits) *AsConversion { return &AsConversion{from, to} } type TypeDotMethod struct { TypeDotMethod string } func (c *AsConversion) TypeDotMethod(t *template.Template) *TypeDotMethod { var b bytes.Buffer t.Execute(&b, c) return &TypeDotMethod{b.String()} } // ExecuteIntrinsicTemplateOfTypeDotMethod executes the template t on a // variety of TypeDotMethod inputs with template parameter TypeDotMethod func (c *AsConversion) ExecuteIntrinsicTemplateOfTypeDotMethod(w io.Writer, t *template.Template) { from, to := c.From, c.To switch to.Name_()[0] { case 'F': // U -> F t.Execute(w, c.TypeDotMethod(ToFloatsIntrinsic)) t.Execute(w, c.TypeDotMethod(ToBitsIntrinsic)) case 'I': // U -> I t.Execute(w, c.TypeDotMethod(ToIntsIntrinsic)) t.Execute(w, c.TypeDotMethod(CvtToIntsIntrinsic)) t.Execute(w, c.TypeDotMethod(CvtToUintsIntrinsic)) t.Execute(w, c.TypeDotMethod(ToBitsIntrinsic)) case 'U': // U -> U if from.Name_()[0] == 'U' { t.Execute(w, c.TypeDotMethod(ReshapeIntrinsic)) } } } func (a *AsConversion) AsTranslation() string { var b bytes.Buffer if a.From.Name_()[0] != 'U' { ToBitsCall.Execute(&b, a) } if a.From.ElemBits() != a.To.ElemBits() { ReshapeCall.Execute(&b, a) } if a.To.Name_()[0] == 'F' { ToFloatsCall.Execute(&b, a) } if a.To.Name_()[0] == 'I' { ToIntsCall.Execute(&b, a) } return b.String() }