github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/compile/internal/gc/bv.go (about)

     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 gc
     6  
     7  const (
     8  	WORDBITS  = 32
     9  	WORDMASK  = WORDBITS - 1
    10  	WORDSHIFT = 5
    11  )
    12  
    13  // A bvec is a bit vector.
    14  type bvec struct {
    15  	n int32    // number of bits in vector
    16  	b []uint32 // words holding bits
    17  }
    18  
    19  func bvalloc(n int32) bvec {
    20  	nword := (n + WORDBITS - 1) / WORDBITS
    21  	return bvec{n, make([]uint32, nword)}
    22  }
    23  
    24  type bulkBvec struct {
    25  	words []uint32
    26  	nbit  int32
    27  	nword int32
    28  }
    29  
    30  func bvbulkalloc(nbit int32, count int32) bulkBvec {
    31  	nword := (nbit + WORDBITS - 1) / WORDBITS
    32  	return bulkBvec{
    33  		words: make([]uint32, nword*count),
    34  		nbit:  nbit,
    35  		nword: nword,
    36  	}
    37  }
    38  
    39  func (b *bulkBvec) next() bvec {
    40  	out := bvec{b.nbit, b.words[:b.nword]}
    41  	b.words = b.words[b.nword:]
    42  	return out
    43  }
    44  
    45  func (bv1 bvec) Eq(bv2 bvec) bool {
    46  	if bv1.n != bv2.n {
    47  		Fatalf("bvequal: lengths %d and %d are not equal", bv1.n, bv2.n)
    48  	}
    49  	for i, x := range bv1.b {
    50  		if x != bv2.b[i] {
    51  			return false
    52  		}
    53  	}
    54  	return true
    55  }
    56  
    57  func (dst bvec) Copy(src bvec) {
    58  	copy(dst.b, src.b)
    59  }
    60  
    61  func (bv bvec) Get(i int32) bool {
    62  	if i < 0 || i >= bv.n {
    63  		Fatalf("bvget: index %d is out of bounds with length %d\n", i, bv.n)
    64  	}
    65  	mask := uint32(1 << uint(i%WORDBITS))
    66  	return bv.b[i>>WORDSHIFT]&mask != 0
    67  }
    68  
    69  func (bv bvec) Set(i int32) {
    70  	if i < 0 || i >= bv.n {
    71  		Fatalf("bvset: index %d is out of bounds with length %d\n", i, bv.n)
    72  	}
    73  	mask := uint32(1 << uint(i%WORDBITS))
    74  	bv.b[i/WORDBITS] |= mask
    75  }
    76  
    77  func (bv bvec) Unset(i int32) {
    78  	if i < 0 || i >= bv.n {
    79  		Fatalf("bvunset: index %d is out of bounds with length %d\n", i, bv.n)
    80  	}
    81  	mask := uint32(1 << uint(i%WORDBITS))
    82  	bv.b[i/WORDBITS] &^= mask
    83  }
    84  
    85  // bvnext returns the smallest index >= i for which bvget(bv, i) == 1.
    86  // If there is no such index, bvnext returns -1.
    87  func (bv bvec) Next(i int32) int32 {
    88  	if i >= bv.n {
    89  		return -1
    90  	}
    91  
    92  	// Jump i ahead to next word with bits.
    93  	if bv.b[i>>WORDSHIFT]>>uint(i&WORDMASK) == 0 {
    94  		i &^= WORDMASK
    95  		i += WORDBITS
    96  		for i < bv.n && bv.b[i>>WORDSHIFT] == 0 {
    97  			i += WORDBITS
    98  		}
    99  	}
   100  
   101  	if i >= bv.n {
   102  		return -1
   103  	}
   104  
   105  	// Find 1 bit.
   106  	w := bv.b[i>>WORDSHIFT] >> uint(i&WORDMASK)
   107  
   108  	for w&1 == 0 {
   109  		w >>= 1
   110  		i++
   111  	}
   112  
   113  	return i
   114  }
   115  
   116  func (bv bvec) IsEmpty() bool {
   117  	for i := int32(0); i < bv.n; i += WORDBITS {
   118  		if bv.b[i>>WORDSHIFT] != 0 {
   119  			return false
   120  		}
   121  	}
   122  	return true
   123  }
   124  
   125  func (bv bvec) Not() {
   126  	i := int32(0)
   127  	w := int32(0)
   128  	for ; i < bv.n; i, w = i+WORDBITS, w+1 {
   129  		bv.b[w] = ^bv.b[w]
   130  	}
   131  }
   132  
   133  // union
   134  func (dst bvec) Or(src1, src2 bvec) {
   135  	for i, x := range src1.b {
   136  		dst.b[i] = x | src2.b[i]
   137  	}
   138  }
   139  
   140  // intersection
   141  func (dst bvec) And(src1, src2 bvec) {
   142  	for i, x := range src1.b {
   143  		dst.b[i] = x & src2.b[i]
   144  	}
   145  }
   146  
   147  // difference
   148  func (dst bvec) AndNot(src1, src2 bvec) {
   149  	for i, x := range src1.b {
   150  		dst.b[i] = x &^ src2.b[i]
   151  	}
   152  }
   153  
   154  func (bv bvec) String() string {
   155  	s := make([]byte, 2+bv.n)
   156  	copy(s, "#*")
   157  	for i := int32(0); i < bv.n; i++ {
   158  		ch := byte('0')
   159  		if bv.Get(i) {
   160  			ch = '1'
   161  		}
   162  		s[2+i] = ch
   163  	}
   164  	return string(s)
   165  }
   166  
   167  func (bv bvec) Clear() {
   168  	for i := range bv.b {
   169  		bv.b[i] = 0
   170  	}
   171  }