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