# Source file src/math/big/bits_test.go

```     1  // Copyright 2015 The Go Authors. All rights reserved.
2  // Use of this source code is governed by a BSD-style
4
5  // This file implements the Bits type used for testing Float operations
6  // via an independent (albeit slower) representations for floating-point
7  // numbers.
8
9  package big
10
11  import (
12  	"fmt"
13  	"sort"
14  	"testing"
15  )
16
17  // A Bits value b represents a finite floating-point number x of the form
18  //
19  //	x = 2**b[0] + 2**b[1] + ... 2**b[len(b)-1]
20  //
21  // The order of slice elements is not significant. Negative elements may be
22  // used to form fractions. A Bits value is normalized if each b[i] occurs at
23  // most once. For instance Bits{0, 0, 1} is not normalized but represents the
24  // same floating-point number as Bits{2}, which is normalized. The zero (nil)
25  // value of Bits is a ready to use Bits value and represents the value 0.
26  type Bits []int
27
28  func (x Bits) add(y Bits) Bits {
29  	return append(x, y...)
30  }
31
32  func (x Bits) mul(y Bits) Bits {
33  	var p Bits
34  	for _, x := range x {
35  		for _, y := range y {
36  			p = append(p, x+y)
37  		}
38  	}
39  	return p
40  }
41
42  func TestMulBits(t *testing.T) {
43  	for _, test := range []struct {
44  		x, y, want Bits
45  	}{
46  		{nil, nil, nil},
47  		{Bits{}, Bits{}, nil},
48  		{Bits{0}, Bits{0}, Bits{0}},
49  		{Bits{0}, Bits{1}, Bits{1}},
50  		{Bits{1}, Bits{1, 2, 3}, Bits{2, 3, 4}},
51  		{Bits{-1}, Bits{1}, Bits{0}},
52  		{Bits{-10, -1, 0, 1, 10}, Bits{1, 2, 3}, Bits{-9, -8, -7, 0, 1, 2, 1, 2, 3, 2, 3, 4, 11, 12, 13}},
53  	} {
54  		got := fmt.Sprintf("%v", test.x.mul(test.y))
55  		want := fmt.Sprintf("%v", test.want)
56  		if got != want {
57  			t.Errorf("%v * %v = %s; want %s", test.x, test.y, got, want)
58  		}
59
60  	}
61  }
62
63  // norm returns the normalized bits for x: It removes multiple equal entries
64  // by treating them as an addition (e.g., Bits{5, 5} => Bits{6}), and it sorts
65  // the result list for reproducible results.
66  func (x Bits) norm() Bits {
67  	m := make(map[int]bool)
68  	for _, b := range x {
69  		for m[b] {
70  			m[b] = false
71  			b++
72  		}
73  		m[b] = true
74  	}
75  	var z Bits
76  	for b, set := range m {
77  		if set {
78  			z = append(z, b)
79  		}
80  	}
81  	sort.Ints([]int(z))
82  	return z
83  }
84
85  func TestNormBits(t *testing.T) {
86  	for _, test := range []struct {
87  		x, want Bits
88  	}{
89  		{nil, nil},
90  		{Bits{}, Bits{}},
91  		{Bits{0}, Bits{0}},
92  		{Bits{0, 0}, Bits{1}},
93  		{Bits{3, 1, 1}, Bits{2, 3}},
94  		{Bits{10, 9, 8, 7, 6, 6}, Bits{11}},
95  	} {
96  		got := fmt.Sprintf("%v", test.x.norm())
97  		want := fmt.Sprintf("%v", test.want)
98  		if got != want {
99  			t.Errorf("normBits(%v) = %s; want %s", test.x, got, want)
100  		}
101
102  	}
103  }
104
105  // round returns the Float value corresponding to x after rounding x
106  // to prec bits according to mode.
107  func (x Bits) round(prec uint, mode RoundingMode) *Float {
108  	x = x.norm()
109
110  	// determine range
111  	var min, max int
112  	for i, b := range x {
113  		if i == 0 || b < min {
114  			min = b
115  		}
116  		if i == 0 || b > max {
117  			max = b
118  		}
119  	}
120  	prec0 := uint(max + 1 - min)
121  	if prec >= prec0 {
122  		return x.Float()
123  	}
124  	// prec < prec0
125
126  	// determine bit 0, rounding, and sticky bit, and result bits z
127  	var bit0, rbit, sbit uint
128  	var z Bits
129  	r := max - int(prec)
130  	for _, b := range x {
131  		switch {
132  		case b == r:
133  			rbit = 1
134  		case b < r:
135  			sbit = 1
136  		default:
137  			// b > r
138  			if b == r+1 {
139  				bit0 = 1
140  			}
141  			z = append(z, b)
142  		}
143  	}
144
145  	// round
146  	f := z.Float() // rounded to zero
147  	if mode == ToNearestAway {
148  		panic("not yet implemented")
149  	}
150  	if mode == ToNearestEven && rbit == 1 && (sbit == 1 || sbit == 0 && bit0 != 0) || mode == AwayFromZero {
151  		// round away from zero
152  		f.SetMode(ToZero).SetPrec(prec)
154  	}
155  	return f
156  }
157
158  // Float returns the *Float z of the smallest possible precision such that
159  // z = sum(2**bits[i]), with i = range bits. If multiple bits[i] are equal,
160  // they are added: Bits{0, 1, 0}.Float() == 2**0 + 2**1 + 2**0 = 4.
161  func (bits Bits) Float() *Float {
162  	// handle 0
163  	if len(bits) == 0 {
164  		return new(Float)
165  	}
166  	// len(bits) > 0
167
168  	// determine lsb exponent
169  	var min int
170  	for i, b := range bits {
171  		if i == 0 || b < min {
172  			min = b
173  		}
174  	}
175
176  	// create bit pattern
177  	x := NewInt(0)
178  	for _, b := range bits {
179  		badj := b - min
180  		// propagate carry if necessary
181  		for x.Bit(badj) != 0 {
184  		}
186  	}
187
188  	// create corresponding float
189  	z := new(Float).SetInt(x) // normalized
190  	if e := int64(z.exp) + int64(min); MinExp <= e && e <= MaxExp {
191  		z.exp = int32(e)
192  	} else {
193  		// this should never happen for our test cases
194  		panic("exponent out of range")
195  	}
196  	return z
197  }
198
199  func TestFromBits(t *testing.T) {
200  	for _, test := range []struct {
201  		bits Bits
202  		want string
203  	}{
204  		// all different bit numbers
205  		{nil, "0"},
206  		{Bits{0}, "0x.8p+1"},
207  		{Bits{1}, "0x.8p+2"},
208  		{Bits{-1}, "0x.8p+0"},
209  		{Bits{63}, "0x.8p+64"},
210  		{Bits{33, -30}, "0x.8000000000000001p+34"},
211  		{Bits{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p+256"},
212
213  		// multiple equal bit numbers
214  		{Bits{0, 0}, "0x.8p+2"},
215  		{Bits{0, 0, 0, 0}, "0x.8p+3"},
216  		{Bits{0, 1, 0}, "0x.8p+3"},
217  		{append(Bits{2, 1, 0} /* 7 */, Bits{3, 1} /* 10 */ ...), "0x.88p+5" /* 17 */},
218  	} {
219  		f := test.bits.Float()
220  		if got := f.Text('p', 0); got != test.want {
221  			t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
222  		}
223  	}
224  }
225
```

View as plain text