1
2
3
4
5 package types2_test
6
7 import (
8 "bytes"
9 "flag"
10 "fmt"
11 "os"
12 "testing"
13
14 . "cmd/compile/internal/types2"
15 )
16
17 var (
18 H = flag.Int("H", 5, "Hilbert matrix size")
19 out = flag.String("out", "", "write generated program to out")
20 )
21
22 func TestHilbert(t *testing.T) {
23
24 src := program(*H, *out)
25 if *out != "" {
26 os.WriteFile(*out, src, 0666)
27 return
28 }
29
30 DefPredeclaredTestFuncs()
31 mustTypecheck(string(src), nil, nil)
32 }
33
34 func program(n int, out string) []byte {
35 var g gen
36
37 g.p(`// Code generated by: go test -run=Hilbert -H=%d -out=%q. DO NOT EDIT.
38
39 // +`+`build ignore
40
41 // This program tests arbitrary precision constant arithmetic
42 // by generating the constant elements of a Hilbert matrix H,
43 // its inverse I, and the product P = H*I. The product should
44 // be the identity matrix.
45 package main
46
47 func main() {
48 if !ok {
49 printProduct()
50 return
51 }
52 println("PASS")
53 }
54
55 `, n, out)
56 g.hilbert(n)
57 g.inverse(n)
58 g.product(n)
59 g.verify(n)
60 g.printProduct(n)
61 g.binomials(2*n - 1)
62 g.factorials(2*n - 1)
63
64 return g.Bytes()
65 }
66
67 type gen struct {
68 bytes.Buffer
69 }
70
71 func (g *gen) p(format string, args ...interface{}) {
72 fmt.Fprintf(&g.Buffer, format, args...)
73 }
74
75 func (g *gen) hilbert(n int) {
76 g.p(`// Hilbert matrix, n = %d
77 const (
78 `, n)
79 for i := 0; i < n; i++ {
80 g.p("\t")
81 for j := 0; j < n; j++ {
82 if j > 0 {
83 g.p(", ")
84 }
85 g.p("h%d_%d", i, j)
86 }
87 if i == 0 {
88 g.p(" = ")
89 for j := 0; j < n; j++ {
90 if j > 0 {
91 g.p(", ")
92 }
93 g.p("1.0/(iota + %d)", j+1)
94 }
95 }
96 g.p("\n")
97 }
98 g.p(")\n\n")
99 }
100
101 func (g *gen) inverse(n int) {
102 g.p(`// Inverse Hilbert matrix
103 const (
104 `)
105 for i := 0; i < n; i++ {
106 for j := 0; j < n; j++ {
107 s := "+"
108 if (i+j)&1 != 0 {
109 s = "-"
110 }
111 g.p("\ti%d_%d = %s%d * b%d_%d * b%d_%d * b%d_%d * b%d_%d\n",
112 i, j, s, i+j+1, n+i, n-j-1, n+j, n-i-1, i+j, i, i+j, i)
113 }
114 g.p("\n")
115 }
116 g.p(")\n\n")
117 }
118
119 func (g *gen) product(n int) {
120 g.p(`// Product matrix
121 const (
122 `)
123 for i := 0; i < n; i++ {
124 for j := 0; j < n; j++ {
125 g.p("\tp%d_%d = ", i, j)
126 for k := 0; k < n; k++ {
127 if k > 0 {
128 g.p(" + ")
129 }
130 g.p("h%d_%d*i%d_%d", i, k, k, j)
131 }
132 g.p("\n")
133 }
134 g.p("\n")
135 }
136 g.p(")\n\n")
137 }
138
139 func (g *gen) verify(n int) {
140 g.p(`// Verify that product is the identity matrix
141 const ok =
142 `)
143 for i := 0; i < n; i++ {
144 for j := 0; j < n; j++ {
145 if j == 0 {
146 g.p("\t")
147 } else {
148 g.p(" && ")
149 }
150 v := 0
151 if i == j {
152 v = 1
153 }
154 g.p("p%d_%d == %d", i, j, v)
155 }
156 g.p(" &&\n")
157 }
158 g.p("\ttrue\n\n")
159
160
161 if *out == "" {
162 g.p("const _ = assert(ok)\n\n")
163 }
164 }
165
166 func (g *gen) printProduct(n int) {
167 g.p("func printProduct() {\n")
168 for i := 0; i < n; i++ {
169 g.p("\tprintln(")
170 for j := 0; j < n; j++ {
171 if j > 0 {
172 g.p(", ")
173 }
174 g.p("p%d_%d", i, j)
175 }
176 g.p(")\n")
177 }
178 g.p("}\n\n")
179 }
180
181 func (g *gen) binomials(n int) {
182 g.p(`// Binomials
183 const (
184 `)
185 for j := 0; j <= n; j++ {
186 if j > 0 {
187 g.p("\n")
188 }
189 for k := 0; k <= j; k++ {
190 g.p("\tb%d_%d = f%d / (f%d*f%d)\n", j, k, j, k, j-k)
191 }
192 }
193 g.p(")\n\n")
194 }
195
196 func (g *gen) factorials(n int) {
197 g.p(`// Factorials
198 const (
199 f0 = 1
200 f1 = 1
201 `)
202 for i := 2; i <= n; i++ {
203 g.p("\tf%d = f%d * %d\n", i, i-1, i)
204 }
205 g.p(")\n\n")
206 }
207
View as plain text