1// runoutput
2
3// Copyright 2017 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package main
8
9import "fmt"
10
11// Check that expressions like (c*n + d*(n+k)) get correctly merged by
12// the compiler into (c+d)*n + d*k (with c+d and d*k computed at
13// compile time).
14//
15// The merging is performed by a combination of the multiplication
16// merge rules
17//  (c*n + d*n) -> (c+d)*n
18// and the distributive multiplication rules
19//  c * (d+x)  ->  c*d + c*x
20
21// Generate a MergeTest that looks like this:
22//
23//   a8, b8 = m1*n8 + m2*(n8+k), (m1+m2)*n8 + m2*k
24//   if a8 != b8 {
25// 	   // print error msg and panic
26//   }
27func makeMergeAddTest(m1, m2, k int, size string) string {
28
29	model := "    a" + size + ", b" + size
30	model += fmt.Sprintf(" = %%d*n%s + %%d*(n%s+%%d), (%%d+%%d)*n%s + (%%d*%%d)", size, size, size)
31
32	test := fmt.Sprintf(model, m1, m2, k, m1, m2, m2, k)
33	test += fmt.Sprintf(`
34    if a%s != b%s {
35        fmt.Printf("MergeAddTest(%d, %d, %d, %s) failed\n")
36        fmt.Printf("%%d != %%d\n", a%s, b%s)
37        panic("FAIL")
38    }
39`, size, size, m1, m2, k, size, size, size)
40	return test + "\n"
41}
42
43// Check that expressions like (c*n - d*(n+k)) get correctly merged by
44// the compiler into (c-d)*n - d*k (with c-d and d*k computed at
45// compile time).
46//
47// The merging is performed by a combination of the multiplication
48// merge rules
49//  (c*n - d*n) -> (c-d)*n
50// and the distributive multiplication rules
51//  c * (d-x)  ->  c*d - c*x
52
53// Generate a MergeTest that looks like this:
54//
55//   a8, b8 = m1*n8 - m2*(n8+k), (m1-m2)*n8 - m2*k
56//   if a8 != b8 {
57// 	   // print error msg and panic
58//   }
59func makeMergeSubTest(m1, m2, k int, size string) string {
60
61	model := "    a" + size + ", b" + size
62	model += fmt.Sprintf(" = %%d*n%s - %%d*(n%s+%%d), (%%d-%%d)*n%s - (%%d*%%d)", size, size, size)
63
64	test := fmt.Sprintf(model, m1, m2, k, m1, m2, m2, k)
65	test += fmt.Sprintf(`
66    if a%s != b%s {
67        fmt.Printf("MergeSubTest(%d, %d, %d, %s) failed\n")
68        fmt.Printf("%%d != %%d\n", a%s, b%s)
69        panic("FAIL")
70    }
71`, size, size, m1, m2, k, size, size, size)
72	return test + "\n"
73}
74
75func makeAllSizes(m1, m2, k int) string {
76	var tests string
77	tests += makeMergeAddTest(m1, m2, k, "8")
78	tests += makeMergeAddTest(m1, m2, k, "16")
79	tests += makeMergeAddTest(m1, m2, k, "32")
80	tests += makeMergeAddTest(m1, m2, k, "64")
81	tests += makeMergeSubTest(m1, m2, k, "8")
82	tests += makeMergeSubTest(m1, m2, k, "16")
83	tests += makeMergeSubTest(m1, m2, k, "32")
84	tests += makeMergeSubTest(m1, m2, k, "64")
85	tests += "\n"
86	return tests
87}
88
89func main() {
90	fmt.Println(`package main
91
92import "fmt"
93
94var n8 int8 = 42
95var n16 int16 = 42
96var n32 int32 = 42
97var n64 int64 = 42
98
99func main() {
100    var a8, b8 int8
101    var a16, b16 int16
102    var a32, b32 int32
103    var a64, b64 int64
104`)
105
106	fmt.Println(makeAllSizes(03, 05, 0)) // 3*n + 5*n
107	fmt.Println(makeAllSizes(17, 33, 0))
108	fmt.Println(makeAllSizes(80, 45, 0))
109	fmt.Println(makeAllSizes(32, 64, 0))
110
111	fmt.Println(makeAllSizes(7, 11, +1)) // 7*n + 11*(n+1)
112	fmt.Println(makeAllSizes(9, 13, +2))
113	fmt.Println(makeAllSizes(11, 16, -1))
114	fmt.Println(makeAllSizes(17, 9, -2))
115
116	fmt.Println("}")
117}
118