| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | package main |
| |
|
| | import ( |
| | "bytes" |
| | "fmt" |
| | "go/format" |
| | "log" |
| | "strings" |
| | "text/template" |
| | ) |
| |
|
| | type op struct { |
| | name, symbol string |
| | } |
| | type szD struct { |
| | name string |
| | sn string |
| | u []uint64 |
| | i []int64 |
| | oponly string |
| | } |
| |
|
| | var szs = []szD{ |
| | {name: "uint64", sn: "64", u: []uint64{0, 1, 4294967296, 0x8000000000000000, 0xffffFFFFffffFFFF}}, |
| | {name: "uint64", sn: "64", u: []uint64{3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"}, |
| |
|
| | {name: "int64", sn: "64", i: []int64{-0x8000000000000000, -0x7FFFFFFFFFFFFFFF, |
| | -4294967296, -1, 0, 1, 4294967296, 0x7FFFFFFFFFFFFFFE, 0x7FFFFFFFFFFFFFFF}}, |
| | {name: "int64", sn: "64", i: []int64{-9, -5, -3, 3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"}, |
| |
|
| | {name: "uint32", sn: "32", u: []uint64{0, 1, 4294967295}}, |
| | {name: "uint32", sn: "32", u: []uint64{3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"}, |
| |
|
| | {name: "int32", sn: "32", i: []int64{-0x80000000, -0x7FFFFFFF, -1, 0, |
| | 1, 0x7FFFFFFF}}, |
| | {name: "int32", sn: "32", i: []int64{-9, -5, -3, 3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"}, |
| |
|
| | {name: "uint16", sn: "16", u: []uint64{0, 1, 65535}}, |
| | {name: "int16", sn: "16", i: []int64{-32768, -32767, -1, 0, 1, 32766, 32767}}, |
| |
|
| | {name: "uint8", sn: "8", u: []uint64{0, 1, 255}}, |
| | {name: "int8", sn: "8", i: []int64{-128, -127, -1, 0, 1, 126, 127}}, |
| | } |
| |
|
| | var ops = []op{ |
| | {"add", "+"}, |
| | {"sub", "-"}, |
| | {"div", "/"}, |
| | {"mul", "*"}, |
| | {"lsh", "<<"}, |
| | {"rsh", ">>"}, |
| | {"mod", "%"}, |
| | {"and", "&"}, |
| | {"or", "|"}, |
| | {"xor", "^"}, |
| | } |
| |
|
| | |
| | func ansU(i, j uint64, t, op string) string { |
| | var ans uint64 |
| | switch op { |
| | case "+": |
| | ans = i + j |
| | case "-": |
| | ans = i - j |
| | case "*": |
| | ans = i * j |
| | case "/": |
| | if j != 0 { |
| | ans = i / j |
| | } |
| | case "%": |
| | if j != 0 { |
| | ans = i % j |
| | } |
| | case "<<": |
| | ans = i << j |
| | case ">>": |
| | ans = i >> j |
| | case "&": |
| | ans = i & j |
| | case "|": |
| | ans = i | j |
| | case "^": |
| | ans = i ^ j |
| | } |
| | switch t { |
| | case "uint32": |
| | ans = uint64(uint32(ans)) |
| | case "uint16": |
| | ans = uint64(uint16(ans)) |
| | case "uint8": |
| | ans = uint64(uint8(ans)) |
| | } |
| | return fmt.Sprintf("%d", ans) |
| | } |
| |
|
| | |
| | func ansS(i, j int64, t, op string) string { |
| | var ans int64 |
| | switch op { |
| | case "+": |
| | ans = i + j |
| | case "-": |
| | ans = i - j |
| | case "*": |
| | ans = i * j |
| | case "/": |
| | if j != 0 { |
| | ans = i / j |
| | } |
| | case "%": |
| | if j != 0 { |
| | ans = i % j |
| | } |
| | case "<<": |
| | ans = i << uint64(j) |
| | case ">>": |
| | ans = i >> uint64(j) |
| | case "&": |
| | ans = i & j |
| | case "|": |
| | ans = i | j |
| | case "^": |
| | ans = i ^ j |
| | } |
| | switch t { |
| | case "int32": |
| | ans = int64(int32(ans)) |
| | case "int16": |
| | ans = int64(int16(ans)) |
| | case "int8": |
| | ans = int64(int8(ans)) |
| | } |
| | return fmt.Sprintf("%d", ans) |
| | } |
| |
|
| | func main() { |
| | w := new(bytes.Buffer) |
| | fmt.Fprintf(w, "// Code generated by gen/arithConstGen.go. DO NOT EDIT.\n\n") |
| | fmt.Fprintf(w, "package main;\n") |
| | fmt.Fprintf(w, "import \"testing\"\n") |
| |
|
| | fncCnst1 := template.Must(template.New("fnc").Parse( |
| | `//go:noinline |
| | func {{.Name}}_{{.Type_}}_{{.FNumber}}(a {{.Type_}}) {{.Type_}} { return a {{.Symbol}} {{.Number}} } |
| | `)) |
| | fncCnst2 := template.Must(template.New("fnc").Parse( |
| | `//go:noinline |
| | func {{.Name}}_{{.FNumber}}_{{.Type_}}(a {{.Type_}}) {{.Type_}} { return {{.Number}} {{.Symbol}} a } |
| | `)) |
| |
|
| | type fncData struct { |
| | Name, Type_, Symbol, FNumber, Number string |
| | } |
| |
|
| | for _, s := range szs { |
| | for _, o := range ops { |
| | if s.oponly != "" && s.oponly != o.name { |
| | continue |
| | } |
| | fd := fncData{o.name, s.name, o.symbol, "", ""} |
| |
|
| | |
| | if len(s.u) > 0 { |
| | for _, i := range s.u { |
| | fd.Number = fmt.Sprintf("%d", i) |
| | fd.FNumber = strings.ReplaceAll(fd.Number, "-", "Neg") |
| |
|
| | |
| | if o.name != "mod" && o.name != "div" || i != 0 { |
| | |
| | |
| | number := fd.Number |
| | if (o.name == "lsh" || o.name == "rsh") && uint64(uint32(i)) != i { |
| | fd.Number = fmt.Sprintf("uint64(%s)", number) |
| | } |
| | fncCnst1.Execute(w, fd) |
| | fd.Number = number |
| | } |
| |
|
| | fncCnst2.Execute(w, fd) |
| | } |
| | } |
| |
|
| | |
| | if len(s.i) > 0 { |
| | |
| | if o.name == "lsh" || o.name == "rsh" { |
| | continue |
| | } |
| | for _, i := range s.i { |
| | fd.Number = fmt.Sprintf("%d", i) |
| | fd.FNumber = strings.ReplaceAll(fd.Number, "-", "Neg") |
| |
|
| | |
| | if o.name != "mod" && o.name != "div" || i != 0 { |
| | fncCnst1.Execute(w, fd) |
| | } |
| | fncCnst2.Execute(w, fd) |
| | } |
| | } |
| | } |
| | } |
| |
|
| | vrf1 := template.Must(template.New("vrf1").Parse(` |
| | test_{{.Size}}{fn: {{.Name}}_{{.FNumber}}_{{.Type_}}, fnname: "{{.Name}}_{{.FNumber}}_{{.Type_}}", in: {{.Input}}, want: {{.Ans}}},`)) |
| |
|
| | vrf2 := template.Must(template.New("vrf2").Parse(` |
| | test_{{.Size}}{fn: {{.Name}}_{{.Type_}}_{{.FNumber}}, fnname: "{{.Name}}_{{.Type_}}_{{.FNumber}}", in: {{.Input}}, want: {{.Ans}}},`)) |
| |
|
| | type cfncData struct { |
| | Size, Name, Type_, Symbol, FNumber, Number string |
| | Ans, Input string |
| | } |
| | for _, s := range szs { |
| | fmt.Fprintf(w, ` |
| | type test_%[1]s%[2]s struct { |
| | fn func (%[1]s) %[1]s |
| | fnname string |
| | in %[1]s |
| | want %[1]s |
| | } |
| | `, s.name, s.oponly) |
| | fmt.Fprintf(w, "var tests_%[1]s%[2]s =[]test_%[1]s {\n\n", s.name, s.oponly) |
| |
|
| | if len(s.u) > 0 { |
| | for _, o := range ops { |
| | if s.oponly != "" && s.oponly != o.name { |
| | continue |
| | } |
| | fd := cfncData{s.name, o.name, s.name, o.symbol, "", "", "", ""} |
| | for _, i := range s.u { |
| | fd.Number = fmt.Sprintf("%d", i) |
| | fd.FNumber = strings.ReplaceAll(fd.Number, "-", "Neg") |
| |
|
| | |
| | for _, j := range s.u { |
| |
|
| | if o.name != "mod" && o.name != "div" || j != 0 { |
| | fd.Ans = ansU(i, j, s.name, o.symbol) |
| | fd.Input = fmt.Sprintf("%d", j) |
| | if err := vrf1.Execute(w, fd); err != nil { |
| | panic(err) |
| | } |
| | } |
| |
|
| | if o.name != "mod" && o.name != "div" || i != 0 { |
| | fd.Ans = ansU(j, i, s.name, o.symbol) |
| | fd.Input = fmt.Sprintf("%d", j) |
| | if err := vrf2.Execute(w, fd); err != nil { |
| | panic(err) |
| | } |
| | } |
| |
|
| | } |
| | } |
| |
|
| | } |
| | } |
| |
|
| | |
| | if len(s.i) > 0 { |
| | for _, o := range ops { |
| | if s.oponly != "" && s.oponly != o.name { |
| | continue |
| | } |
| | |
| | if o.name == "lsh" || o.name == "rsh" { |
| | continue |
| | } |
| | fd := cfncData{s.name, o.name, s.name, o.symbol, "", "", "", ""} |
| | for _, i := range s.i { |
| | fd.Number = fmt.Sprintf("%d", i) |
| | fd.FNumber = strings.ReplaceAll(fd.Number, "-", "Neg") |
| | for _, j := range s.i { |
| | if o.name != "mod" && o.name != "div" || j != 0 { |
| | fd.Ans = ansS(i, j, s.name, o.symbol) |
| | fd.Input = fmt.Sprintf("%d", j) |
| | if err := vrf1.Execute(w, fd); err != nil { |
| | panic(err) |
| | } |
| | } |
| |
|
| | if o.name != "mod" && o.name != "div" || i != 0 { |
| | fd.Ans = ansS(j, i, s.name, o.symbol) |
| | fd.Input = fmt.Sprintf("%d", j) |
| | if err := vrf2.Execute(w, fd); err != nil { |
| | panic(err) |
| | } |
| | } |
| |
|
| | } |
| | } |
| |
|
| | } |
| | } |
| |
|
| | fmt.Fprintf(w, "}\n\n") |
| | } |
| |
|
| | fmt.Fprint(w, ` |
| | |
| | // TestArithmeticConst tests results for arithmetic operations against constants. |
| | func TestArithmeticConst(t *testing.T) { |
| | `) |
| |
|
| | for _, s := range szs { |
| | fmt.Fprintf(w, `for _, test := range tests_%s%s {`, s.name, s.oponly) |
| | |
| | w.WriteString(`if got := test.fn(test.in); got != test.want { |
| | t.Errorf("%s(%d) = %d, want %d\n", test.fnname, test.in, got, test.want) |
| | } |
| | } |
| | `) |
| | } |
| |
|
| | fmt.Fprint(w, ` |
| | } |
| | `) |
| |
|
| | |
| | b := w.Bytes() |
| | src, err := format.Source(b) |
| | if err != nil { |
| | fmt.Printf("%s\n", b) |
| | panic(err) |
| | } |
| |
|
| | |
| | err = os.WriteFile("../arithConst_test.go", src, 0666) |
| | if err != nil { |
| | log.Fatalf("can't write output: %v\n", err) |
| | } |
| | } |
| |
|