blob: 9438045c863826bddf260dadfe23d2e54304bdea [file] [log] [blame]
Robert Griesemerce164402008-11-06 14:23:49 -08001// $G $D/$F.go && $L $F.$A && ./$A.out
2
3// Copyright 2009 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
7// A little test program for rational arithmetics.
8// Computes a Hilbert matrix, its inverse, multiplies them
9// and verifies that the product is the identity matrix.
10
11package main
12
13import Big "bignum"
14import Fmt "fmt"
15
16
17func assert(p bool) {
18 if !p {
19 panic("assert failed");
20 }
21}
22
23
Russ Cox839a6842009-01-20 14:40:40 -080024var (
Robert Griesemerce164402008-11-06 14:23:49 -080025 Zero = Big.Rat(0, 1);
26 One = Big.Rat(1, 1);
27)
28
29
Russ Cox839a6842009-01-20 14:40:40 -080030type Matrix struct {
Robert Griesemerce164402008-11-06 14:23:49 -080031 n, m int;
Russ Coxd47d8882008-12-18 22:37:22 -080032 a []*Big.Rational;
Robert Griesemerce164402008-11-06 14:23:49 -080033}
34
35
36func (a *Matrix) at(i, j int) *Big.Rational {
37 assert(0 <= i && i < a.n && 0 <= j && j < a.m);
38 return a.a[i*a.m + j];
39}
40
41
42func (a *Matrix) set(i, j int, x *Big.Rational) {
43 assert(0 <= i && i < a.n && 0 <= j && j < a.m);
44 a.a[i*a.m + j] = x;
45}
46
47
Russ Cox839a6842009-01-20 14:40:40 -080048func NewMatrix(n, m int) *Matrix {
Robert Griesemerce164402008-11-06 14:23:49 -080049 assert(0 <= n && 0 <= m);
Russ Cox55645042009-01-06 15:19:02 -080050 a := new(Matrix);
Robert Griesemerce164402008-11-06 14:23:49 -080051 a.n = n;
52 a.m = m;
Russ Cox55645042009-01-06 15:19:02 -080053 a.a = make([]*Big.Rational, n*m);
Robert Griesemerce164402008-11-06 14:23:49 -080054 return a;
55}
56
57
Russ Cox839a6842009-01-20 14:40:40 -080058func NewUnit(n int) *Matrix {
Robert Griesemerce164402008-11-06 14:23:49 -080059 a := NewMatrix(n, n);
60 for i := 0; i < n; i++ {
61 for j := 0; j < n; j++ {
62 x := Zero;
63 if i == j {
64 x = One;
65 }
66 a.set(i, j, x);
67 }
68 }
69 return a;
70}
71
72
Russ Cox839a6842009-01-20 14:40:40 -080073func NewHilbert(n int) *Matrix {
Robert Griesemerce164402008-11-06 14:23:49 -080074 a := NewMatrix(n, n);
75 for i := 0; i < n; i++ {
76 for j := 0; j < n; j++ {
Robert Griesemerf401cb32009-07-07 10:30:31 -070077 x := Big.Rat(1, int64(i + j + 1));
Robert Griesemerce164402008-11-06 14:23:49 -080078 a.set(i, j, x);
79 }
80 }
81 return a;
82}
83
84
Russ Cox839a6842009-01-20 14:40:40 -080085func MakeRat(x Big.Natural) *Big.Rational {
Robert Griesemerce164402008-11-06 14:23:49 -080086 return Big.MakeRat(Big.MakeInt(false, x), Big.Nat(1));
87}
88
89
Russ Cox839a6842009-01-20 14:40:40 -080090func NewInverseHilbert(n int) *Matrix {
Robert Griesemerce164402008-11-06 14:23:49 -080091 a := NewMatrix(n, n);
92 for i := 0; i < n; i++ {
93 for j := 0; j < n; j++ {
94 x0 := One;
95 if (i+j)&1 != 0 {
96 x0 = x0.Neg();
97 }
Robert Griesemerf401cb32009-07-07 10:30:31 -070098 x1 := Big.Rat(int64(i + j + 1), 1);
Robert Griesemerce164402008-11-06 14:23:49 -080099 x2 := MakeRat(Big.Binomial(uint(n+i), uint(n-j-1)));
100 x3 := MakeRat(Big.Binomial(uint(n+j), uint(n-i-1)));
101 x4 := MakeRat(Big.Binomial(uint(i+j), uint(i)));
102 x4 = x4.Mul(x4);
Ken Thompsonb2dfd782008-12-30 14:02:20 -0800103 a.set(i, j, x0.Mul(x1).Mul(x2).Mul(x3).Mul(x4));
Robert Griesemerce164402008-11-06 14:23:49 -0800104 }
105 }
106 return a;
107}
108
109
110func (a *Matrix) Mul(b *Matrix) *Matrix {
111 assert(a.m == b.n);
112 c := NewMatrix(a.n, b.m);
113 for i := 0; i < c.n; i++ {
114 for j := 0; j < c.m; j++ {
115 x := Zero;
116 for k := 0; k < a.m; k++ {
Ken Thompsonb2dfd782008-12-30 14:02:20 -0800117 x = x.Add(a.at(i, k).Mul(b.at(k, j)));
Robert Griesemerce164402008-11-06 14:23:49 -0800118 }
119 c.set(i, j, x);
120 }
121 }
122 return c;
123}
124
125
126func (a *Matrix) Eql(b *Matrix) bool {
127 if a.n != b.n || a.m != b.m {
128 return false;
129 }
130 for i := 0; i < a.n; i++ {
131 for j := 0; j < a.m; j++ {
Ken Thompsonb2dfd782008-12-30 14:02:20 -0800132 if a.at(i, j).Cmp(b.at(i,j)) != 0 {
Robert Griesemerce164402008-11-06 14:23:49 -0800133 return false;
134 }
135 }
136 }
137 return true;
138}
139
140
141func (a *Matrix) String() string {
142 s := "";
143 for i := 0; i < a.n; i++ {
144 for j := 0; j < a.m; j++ {
Rob Pike61f33022009-01-15 13:48:11 -0800145 s += Fmt.Sprintf("\t%s", a.at(i, j));
Robert Griesemerce164402008-11-06 14:23:49 -0800146 }
147 s += "\n";
148 }
149 return s;
150}
151
152
153func main() {
154 n := 10;
155 a := NewHilbert(n);
156 b := NewInverseHilbert(n);
157 I := NewUnit(n);
158 ab := a.Mul(b);
159 if !ab.Eql(I) {
Rob Pike61f33022009-01-15 13:48:11 -0800160 Fmt.Println("a =", a);
161 Fmt.Println("b =", b);
162 Fmt.Println("a*b =", ab);
163 Fmt.Println("I =", I);
Robert Griesemerce164402008-11-06 14:23:49 -0800164 panic("FAILED");
165 }
166}