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  }