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  }