github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/bit/gen.go (about) 1 // +build ignore 2 3 // This program generates tables.go 4 // go run gen.go -output tables.go 5 // 6 package main 7 8 import ( 9 "bytes" 10 "flag" 11 "fmt" 12 "go/format" 13 "io" 14 "io/ioutil" 15 "log" 16 "math" 17 ) 18 19 const notFound = 0xFF 20 21 func scanRight(x uint64) uint64 { 22 for k := 63; k >= 0; k -= 1 { 23 if x&(1<<byte(k)) != 0 { 24 return uint64(k) 25 } 26 } 27 return notFound 28 } 29 30 func scanLeft(x uint64) uint64 { 31 for k := byte(0); k < 64; k += 1 { 32 if x&(1<<k) != 0 { 33 return uint64(k) 34 } 35 } 36 return notFound 37 } 38 39 func reverse(x, width uint64) (rx uint64) { 40 for i := uint64(0); i < width; i += 1 { 41 rx <<= 1 42 rx |= x & 1 43 x >>= 1 44 } 45 return 46 } 47 48 var filename = flag.String("output", "tables.go", "output file name") 49 50 func table(out io.Writer, name string, count int, fn func(v uint64) uint64) { 51 line := int(math.Sqrt(float64(count))) 52 53 fmt.Fprintf(out, "var %s = [%d]byte{\n", name, count) 54 for i := 0; i < count; i += 1 { 55 if i&(line-1) == 0 { 56 fmt.Fprint(out, "\t") 57 } else { 58 fmt.Fprint(out, " ") 59 } 60 fmt.Fprintf(out, "0x%02x, ", fn(uint64(i))) 61 if i&(line-1) == line-1 { 62 fmt.Fprintln(out) 63 } 64 } 65 fmt.Fprintln(out, "}") 66 fmt.Fprintln(out) 67 } 68 69 func main() { 70 flag.Parse() 71 72 var buf bytes.Buffer 73 74 fmt.Fprintln(&buf, "package bit") 75 fmt.Fprintln(&buf) 76 fmt.Fprintln(&buf, "// autogenerated by go run gen.go -output tables.go") 77 fmt.Fprintln(&buf) 78 79 table(&buf, "reverseByte", 256, func(v uint64) uint64 { return reverse(v, 8) }) 80 81 fmt.Fprintln(&buf) 82 fmt.Fprintln(&buf, "const scanTableBits = 16") 83 fmt.Fprintln(&buf, "const scanTableMask = (1<<scanTableBits)-1") 84 85 table(&buf, "scanLeftTable", 256*256, scanLeft) 86 87 table(&buf, "scanRightTable", 256*256, scanRight) 88 89 data, err := format.Source(buf.Bytes()) 90 if err != nil { 91 log.Fatal(err) 92 } 93 94 err = ioutil.WriteFile(*filename, data, 0644) 95 if err != nil { 96 log.Fatal(err) 97 } 98 }