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