Source file src/simd/archsimd/_gen/sgutil/asbits.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package sgutil
     6  
     7  import (
     8  	"bytes"
     9  	"io"
    10  	"text/template"
    11  )
    12  
    13  type TforAsBits interface {
    14  	ElemBits() int
    15  	Name_() string
    16  }
    17  
    18  const (
    19  	ToBitsName        = "ToBits"
    20  	ToIntsName        = "BitsToInt{{.To.ElemBits}}"
    21  	ConvertToIntName  = "ConvertToInt{{.To.ElemBits}}"
    22  	ConvertToUintName = "ConvertToUint{{.From.ElemBits}}" // backwards because done with ToInts
    23  	ToFloatsName      = "BitsToFloat{{.To.ElemBits}}"
    24  	ReshapeName       = "ReshapeToUint{{.To.ElemBits}}s"
    25  )
    26  
    27  func templateOf(name, text string) *template.Template {
    28  	return template.Must(template.New(name).Parse(text))
    29  }
    30  
    31  var ToBitsCall = templateOf("toBitsCall", "."+ToBitsName+"()")
    32  var ToIntsCall = templateOf("toBitsCall", "."+ToIntsName+"()")
    33  var ToFloatsCall = templateOf("toBitsCall", "."+ToFloatsName+"()")
    34  var ReshapeCall = templateOf("toBitsCall", "."+ReshapeName+"()")
    35  
    36  var ToBitsDcl = templateOf("toBitsDcl", `
    37  	// `+ToBitsName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector
    38  	func (x {{.From.Name_}}) `+ToBitsName+`() {{.To.Name_}}
    39  `)
    40  
    41  // ToBitsIntrinsic is used in a uint -> T context, but reverse, so T is method receiver.
    42  var ToBitsIntrinsic = templateOf("toBitsIntrin", `{{.To.Name_}}.`+ToBitsName)
    43  
    44  var ToIntsDcl = templateOf("toIntsDcl", `
    45  	// `+ToIntsName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector
    46  	func (x {{.From.Name_}}) `+ToIntsName+`() {{.To.Name_}}
    47  
    48  	// `+ConvertToIntName+` converts a {{.From.Name_}} vector to a {{.To.Name_}} vector
    49  	func (x {{.From.Name_}}) `+ConvertToIntName+`() {{.To.Name_}}
    50  
    51  	// `+ConvertToUintName+` converts a {{.To.Name_}} vector to a {{.From.Name_}} vector
    52  	func (x {{.To.Name_}}) `+ConvertToUintName+`() {{.From.Name_}}
    53  `)
    54  
    55  var ToIntsIntrinsic = templateOf("toIntsIntrin", `{{.From.Name_}}.`+ToIntsName)
    56  var CvtToIntsIntrinsic = templateOf("cvtToIntIntrin", `{{.From.Name_}}.`+ConvertToIntName)
    57  
    58  // Also used in a to-from-reversed context.
    59  var CvtToUintsIntrinsic = templateOf("cvtToUintIntrin", `{{.To.Name_}}.`+ConvertToUintName)
    60  
    61  var ToFloatsDcl = templateOf("toFloatsDcl", `
    62  	// `+ToFloatsName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector
    63  	func (x {{.From.Name_}}) `+ToFloatsName+`() {{.To.Name_}}
    64  `)
    65  
    66  var ToFloatsIntrinsic = templateOf("toFloatsIntrin", `{{.From.Name_}}.`+ToFloatsName)
    67  
    68  var ReshapeDcl = templateOf("reshapeDcl", `
    69  	// `+ReshapeName+` reinterprets the bits of a {{.From.Name_}} vector as a {{.To.Name_}} vector
    70  	func (x {{.From.Name_}}) `+ReshapeName+`() {{.To.Name_}}
    71  `)
    72  
    73  var ReshapeIntrinsic = templateOf("reshapeIntrinsic", `{{.From.Name_}}.`+ReshapeName)
    74  
    75  var AsOp = templateOf("asConversion", `
    76  	// As{{.To.Name}} reinterprets the bits of a {{.From.Name}} vector as a {{.To.Name}} vector
    77  	//
    78  	// Deprecated: use combinations of ToBits, BitsTo{Int<N>,Float<N>}, ReshapeToUint<N>
    79  	//
    80  	//go:fix inline
    81  	func (x {{.From.Name}}) As{{.To.Name}}() {{.To.Name}} {
    82  		return x{{.AsTranslation}}
    83  	}
    84  `)
    85  
    86  type AsConversion struct {
    87  	From, To TforAsBits
    88  }
    89  
    90  func Conversion(from, to TforAsBits) *AsConversion {
    91  	return &AsConversion{from, to}
    92  }
    93  
    94  type TypeDotMethod struct {
    95  	TypeDotMethod string
    96  }
    97  
    98  func (c *AsConversion) TypeDotMethod(t *template.Template) *TypeDotMethod {
    99  	var b bytes.Buffer
   100  	t.Execute(&b, c)
   101  	return &TypeDotMethod{b.String()}
   102  }
   103  
   104  // ExecuteIntrinsicTemplateOfTypeDotMethod executes the template t on a
   105  // variety of TypeDotMethod inputs with template parameter TypeDotMethod
   106  func (c *AsConversion) ExecuteIntrinsicTemplateOfTypeDotMethod(w io.Writer, t *template.Template) {
   107  	from, to := c.From, c.To
   108  	switch to.Name_()[0] {
   109  	case 'F': // U -> F
   110  		t.Execute(w, c.TypeDotMethod(ToFloatsIntrinsic))
   111  		t.Execute(w, c.TypeDotMethod(ToBitsIntrinsic))
   112  	case 'I': // U -> I
   113  		t.Execute(w, c.TypeDotMethod(ToIntsIntrinsic))
   114  		t.Execute(w, c.TypeDotMethod(CvtToIntsIntrinsic))
   115  		t.Execute(w, c.TypeDotMethod(CvtToUintsIntrinsic))
   116  		t.Execute(w, c.TypeDotMethod(ToBitsIntrinsic))
   117  	case 'U': // U -> U
   118  		if from.Name_()[0] == 'U' {
   119  			t.Execute(w, c.TypeDotMethod(ReshapeIntrinsic))
   120  		}
   121  	}
   122  }
   123  
   124  func (a *AsConversion) AsTranslation() string {
   125  	var b bytes.Buffer
   126  	if a.From.Name_()[0] != 'U' {
   127  		ToBitsCall.Execute(&b, a)
   128  	}
   129  	if a.From.ElemBits() != a.To.ElemBits() {
   130  		ReshapeCall.Execute(&b, a)
   131  	}
   132  	if a.To.Name_()[0] == 'F' {
   133  		ToFloatsCall.Execute(&b, a)
   134  	}
   135  	if a.To.Name_()[0] == 'I' {
   136  		ToIntsCall.Execute(&b, a)
   137  	}
   138  	return b.String()
   139  }
   140  

View as plain text