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