Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 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 | import "fmt" |
| 8 | |
| 9 | const ( |
| 10 | WORDSIZE = 4 |
| 11 | WORDBITS = 32 |
| 12 | WORDMASK = WORDBITS - 1 |
| 13 | WORDSHIFT = 5 |
| 14 | ) |
| 15 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 16 | // A Bvec is a bit vector. |
| 17 | type Bvec struct { |
| 18 | n int32 // number of bits in vector |
| 19 | b []uint32 // words holding bits |
| 20 | } |
| 21 | |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 22 | func bvsize(n uint32) uint32 { |
| 23 | return ((n + WORDBITS - 1) / WORDBITS) * WORDSIZE |
| 24 | } |
| 25 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 26 | func bvbits(bv Bvec) int32 { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 27 | return bv.n |
| 28 | } |
| 29 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 30 | func bvwords(bv Bvec) int32 { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 31 | return (bv.n + WORDBITS - 1) / WORDBITS |
| 32 | } |
| 33 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 34 | func bvalloc(n int32) Bvec { |
| 35 | return Bvec{n, make([]uint32, bvsize(uint32(n))/4)} |
| 36 | } |
| 37 | |
| 38 | type bulkBvec struct { |
| 39 | words []uint32 |
| 40 | nbit int32 |
| 41 | nword int32 |
| 42 | } |
| 43 | |
| 44 | func bvbulkalloc(nbit int32, count int32) bulkBvec { |
| 45 | nword := (nbit + WORDBITS - 1) / WORDBITS |
| 46 | return bulkBvec{ |
| 47 | words: make([]uint32, nword*count), |
| 48 | nbit: nbit, |
| 49 | nword: nword, |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | func (b *bulkBvec) next() Bvec { |
| 54 | out := Bvec{b.nbit, b.words[:b.nword]} |
| 55 | b.words = b.words[b.nword:] |
| 56 | return out |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | /* difference */ |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 60 | func bvandnot(dst Bvec, src1 Bvec, src2 Bvec) { |
Russ Cox | c819834 | 2015-03-12 18:45:30 -0400 | [diff] [blame] | 61 | for i, x := range src1.b { |
| 62 | dst.b[i] = x &^ src2.b[i] |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 63 | } |
| 64 | } |
| 65 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 66 | func bvcmp(bv1 Bvec, bv2 Bvec) int { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 67 | if bv1.n != bv2.n { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 68 | Fatalf("bvequal: lengths %d and %d are not equal", bv1.n, bv2.n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 69 | } |
| 70 | for i, x := range bv1.b { |
| 71 | if x != bv2.b[i] { |
| 72 | return 1 |
| 73 | } |
| 74 | } |
| 75 | return 0 |
| 76 | } |
| 77 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 78 | func bvcopy(dst Bvec, src Bvec) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 79 | for i, x := range src.b { |
| 80 | dst.b[i] = x |
| 81 | } |
| 82 | } |
| 83 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 84 | func bvconcat(src1 Bvec, src2 Bvec) Bvec { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 85 | dst := bvalloc(src1.n + src2.n) |
| 86 | for i := int32(0); i < src1.n; i++ { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 87 | if bvget(src1, i) != 0 { |
| 88 | bvset(dst, i) |
| 89 | } |
| 90 | } |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 91 | for i := int32(0); i < src2.n; i++ { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 92 | if bvget(src2, i) != 0 { |
| 93 | bvset(dst, i+src1.n) |
| 94 | } |
| 95 | } |
| 96 | return dst |
| 97 | } |
| 98 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 99 | func bvget(bv Bvec, i int32) int { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 100 | if i < 0 || i >= bv.n { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 101 | Fatalf("bvget: index %d is out of bounds with length %d\n", i, bv.n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 102 | } |
| 103 | return int((bv.b[i>>WORDSHIFT] >> uint(i&WORDMASK)) & 1) |
| 104 | } |
| 105 | |
| 106 | // bvnext returns the smallest index >= i for which bvget(bv, i) == 1. |
| 107 | // If there is no such index, bvnext returns -1. |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 108 | func bvnext(bv Bvec, i int32) int { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 109 | if i >= bv.n { |
| 110 | return -1 |
| 111 | } |
| 112 | |
| 113 | // Jump i ahead to next word with bits. |
| 114 | if bv.b[i>>WORDSHIFT]>>uint(i&WORDMASK) == 0 { |
| 115 | i &^= WORDMASK |
| 116 | i += WORDBITS |
| 117 | for i < bv.n && bv.b[i>>WORDSHIFT] == 0 { |
| 118 | i += WORDBITS |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | if i >= bv.n { |
| 123 | return -1 |
| 124 | } |
| 125 | |
| 126 | // Find 1 bit. |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 127 | w := bv.b[i>>WORDSHIFT] >> uint(i&WORDMASK) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 128 | |
| 129 | for w&1 == 0 { |
| 130 | w >>= 1 |
| 131 | i++ |
| 132 | } |
| 133 | |
| 134 | return int(i) |
| 135 | } |
| 136 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 137 | func bvisempty(bv Bvec) bool { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 138 | for i := int32(0); i < bv.n; i += WORDBITS { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 139 | if bv.b[i>>WORDSHIFT] != 0 { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 140 | return false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 141 | } |
| 142 | } |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 143 | return true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 144 | } |
| 145 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 146 | func bvnot(bv Bvec) { |
Russ Cox | c819834 | 2015-03-12 18:45:30 -0400 | [diff] [blame] | 147 | i := int32(0) |
| 148 | w := int32(0) |
Russ Cox | d7f6d46 | 2015-03-09 00:31:13 -0400 | [diff] [blame] | 149 | for ; i < bv.n; i, w = i+WORDBITS, w+1 { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 150 | bv.b[w] = ^bv.b[w] |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | /* union */ |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 155 | func bvor(dst Bvec, src1 Bvec, src2 Bvec) { |
Russ Cox | c819834 | 2015-03-12 18:45:30 -0400 | [diff] [blame] | 156 | for i, x := range src1.b { |
| 157 | dst.b[i] = x | src2.b[i] |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 158 | } |
| 159 | } |
| 160 | |
| 161 | /* intersection */ |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 162 | func bvand(dst Bvec, src1 Bvec, src2 Bvec) { |
Russ Cox | c819834 | 2015-03-12 18:45:30 -0400 | [diff] [blame] | 163 | for i, x := range src1.b { |
| 164 | dst.b[i] = x & src2.b[i] |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 165 | } |
| 166 | } |
| 167 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 168 | func bvprint(bv Bvec) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 169 | fmt.Printf("#*") |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 170 | for i := int32(0); i < bv.n; i++ { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 171 | fmt.Printf("%d", bvget(bv, i)) |
| 172 | } |
| 173 | } |
| 174 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 175 | func bvreset(bv Bvec, i int32) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 176 | if i < 0 || i >= bv.n { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 177 | Fatalf("bvreset: index %d is out of bounds with length %d\n", i, bv.n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 178 | } |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 179 | mask := uint32(^(1 << uint(i%WORDBITS))) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 180 | bv.b[i/WORDBITS] &= mask |
| 181 | } |
| 182 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 183 | func bvresetall(bv Bvec) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 184 | for i := range bv.b { |
| 185 | bv.b[i] = 0 |
| 186 | } |
| 187 | } |
| 188 | |
Russ Cox | 0153137 | 2015-03-02 21:25:33 -0500 | [diff] [blame] | 189 | func bvset(bv Bvec, i int32) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 190 | if i < 0 || i >= bv.n { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 191 | Fatalf("bvset: index %d is out of bounds with length %d\n", i, bv.n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 192 | } |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 193 | mask := uint32(1 << uint(i%WORDBITS)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 194 | bv.b[i/WORDBITS] |= mask |
| 195 | } |