File: main.go

package info (click to toggle)
golang-github-bits-and-blooms-bitset 1.22.0-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 760 kB
  • sloc: makefile: 3
file content (139 lines) | stat: -rw-r--r-- 3,016 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/format"
	"math/bits"
	"os"
)

// pextByte handles single-byte PEXT operation
func pextByte(b, m uint8) uint8 {
	var result, bitPos uint8
	for i := uint8(0); i < 8; i++ {
		if m&(1<<i) != 0 {
			if b&(1<<i) != 0 {
				result |= 1 << bitPos
			}
			bitPos++
		}
	}
	return result
}

// pdepByte handles single-byte PDEP operation
func pdepByte(b, m uint8) uint8 {
	var result, bitPos uint8
	for i := uint8(0); i < 8; i++ {
		if m&(1<<i) != 0 {
			if b&(1<<bitPos) != 0 {
				result |= 1 << i
			}
			bitPos++
		}
	}
	return result
}

func generateTable(name string, data interface{}, comment string) string {
	var buf bytes.Buffer

	if comment != "" {
		fmt.Fprintf(&buf, "// %s\n", comment)
	}
	fmt.Fprintf(&buf, "var %s = ", name)

	switch v := data.(type) {
	case [256]uint8:
		buf.WriteString("[256]uint8{")
		for i, val := range v {
			if i%16 == 0 {
				buf.WriteString("\n\t")
			}
			fmt.Fprintf(&buf, "%d,", val)
		}
		buf.WriteString("\n}")

	case [256][256]uint8:
		buf.WriteString("[256][256]uint8{")
		for i, row := range v {
			if i%4 == 0 {
				buf.WriteString("\n\t")
			}
			buf.WriteString("{")
			for j, val := range row {
				if j%16 == 0 {
					buf.WriteString("\n\t\t")
				}
				fmt.Fprintf(&buf, "%d,", val)
			}
			buf.WriteString("\n\t},")
		}
		buf.WriteString("\n}")
	}

	return buf.String()
}

func main() {
	packageName := flag.String("pkg", "", "package name for generated code")
	flag.Parse()

	if *packageName == "" {
		fmt.Fprintln(os.Stderr, "package name is required")
		return
	}

	// Initialize lookup tables
	var pextLUT [256][256]uint8
	var pdepLUT [256][256]uint8
	var popLUT [256]uint8

	for b := 0; b < 256; b++ {
		popLUT[b] = uint8(bits.OnesCount8(uint8(b)))
		for m := 0; m < 256; m++ {
			pextLUT[b][m] = pextByte(uint8(b), uint8(m))
			pdepLUT[b][m] = pdepByte(uint8(b), uint8(m))
		}
	}

	// Generate code
	var buf bytes.Buffer
	buf.WriteString("// Code generated by cmd/pextgen/main.go; DO NOT EDIT.\n")
	buf.WriteString("//\n")
	buf.WriteString("// To regenerate this file:\n")
	buf.WriteString("//   go run cmd/pextgen/main.go\n")
	buf.WriteString("\n")
	fmt.Fprintf(&buf, "package %s\n\n", *packageName)

	tables := []struct {
		name    string
		data    interface{}
		comment string
	}{
		{"pextLUT", pextLUT, "pextLUT contains pre-computed parallel bit extraction results"},
		{"pdepLUT", pdepLUT, "pdepLUT contains pre-computed parallel bit deposit results"},
		{"popLUT", popLUT, "popLUT contains pre-computed population counts"},
	}

	for _, table := range tables {
		buf.WriteString(generateTable(table.name, table.data, table.comment))
		buf.WriteString("\n\n")
	}

	// Format the generated code
	formatted, err := format.Source(buf.Bytes())
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to format code: %v\n", err)
		os.Exit(1)
	}

	// Write to tables.go
	err = os.WriteFile("pext.gen.go", formatted, 0644)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to write file: %v\n", err)
		os.Exit(1)
	}
}