Source file src/cmd/compile/internal/types2/hilbert_test.go

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     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  	// generate source
    24  	src := program(*H, *out)
    25  	if *out != "" {
    26  		os.WriteFile(*out, src, 0666)
    27  		return
    28  	}
    29  
    30  	DefPredeclaredTestFuncs() // declare assert (used by code generated by verify)
    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  	// verify ok at type-check time
   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