| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package bf | |
| 6 | |
| 7 import ( | |
| 8 "fmt" | |
| 9 ) | |
| 10 | |
| 11 // BitField is a AppEngine-serializable bit field implementation. It should | |
| 12 // be nice and fast for non-AppEngine use as well. | |
| 13 // | |
| 14 // You should construct a new one with bf.Make, rather than by direct | |
| 15 // construction. The field names are public due to an appengine artifact. | |
| 16 type BitField struct { | |
| 17 // fields are public so that datastore can see them... but don't touch t
hem if | |
| 18 // you know what's good for you. | |
| 19 | |
| 20 // Data is the actual bits data. rightmost bit of 0th number is the firs
t bit. | |
| 21 Data []int64 `datastore:",noindex"` | |
| 22 | |
| 23 // NumBits is the number of bits held in this BitField. It's stored as a | |
| 24 // casted uint64 since datastore can't store unsigned things, apparently
. | |
| 25 NumBits int64 `datastore:",noindex"` | |
| 26 } | |
| 27 | |
| 28 // Make creates a new properly-initialized BitField. | |
| 29 func Make(size uint64) BitField { | |
| 30 return BitField{ | |
| 31 Data: make([]int64, (size+64-1)>>6), | |
| 32 NumBits: int64(size), | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 // Size returns the number of bits which this BitField can hold. | |
| 37 func (bf BitField) Size() uint64 { | |
| 38 return uint64(bf.NumBits) | |
| 39 } | |
| 40 | |
| 41 // Set turns the given bit to true, regardless of its previous value. Error | |
| 42 // returned is for bounds checking. | |
| 43 func (bf BitField) Set(idx uint64) error { | |
| 44 if idx >= bf.Size() { | |
| 45 return fmt.Errorf("Cannot set bit %d in BitField of size %d", id
x, bf.Size()) | |
| 46 } | |
| 47 bf.Data[idx>>6] |= 1 << (idx % 64) | |
| 48 return nil | |
| 49 } | |
| 50 | |
| 51 // Clear turns the given bit to false, regardless of its previous value. Error | |
| 52 // returned is for bounds checking. | |
| 53 func (bf BitField) Clear(idx uint64) error { | |
| 54 if idx >= bf.Size() { | |
| 55 return fmt.Errorf("Cannot clear bit %d in BitField of size %d",
idx, bf.Size()) | |
| 56 } | |
| 57 bf.Data[idx>>6] &^= 1 << (idx % 64) | |
| 58 return nil | |
| 59 } | |
| 60 | |
| 61 // All returns true iff all of the bits are equal to `val`. | |
| 62 func (bf BitField) All(val bool) bool { | |
| 63 targ := bf.Size() | |
| 64 if !val { | |
| 65 targ = 0 | |
| 66 } | |
| 67 return bf.CountSet() == targ | |
| 68 } | |
| 69 | |
| 70 func countBitsSet(v uint64) uint8 { | |
| 71 // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetPara
llel | |
| 72 const ( | |
| 73 maxUint64 = ^(uint64(0)) | |
| 74 eightyfives = maxUint64 / 3 // 0x555555... | |
| 75 fiftyones = maxUint64 / 15 * 3 // 0x333333... | |
| 76 fifteens = maxUint64 / 255 * 15 // 0x0f0f0f... | |
| 77 ones = maxUint64 / 255 // 0x010101... | |
| 78 offset = (64/8 - 1) * 8 // 56 | |
| 79 ) | |
| 80 | |
| 81 v -= v >> 1 & eightyfives | |
| 82 v = v&fiftyones + v>>2&fiftyones | |
| 83 v = (v + v>>4) & fifteens | |
| 84 return uint8(v * ones >> offset) | |
| 85 } | |
| 86 | |
| 87 // CountSet returns the number of true bits. | |
| 88 func (bf BitField) CountSet() uint64 { | |
| 89 ret := uint64(0) | |
| 90 for _, word := range bf.Data { | |
| 91 if word != 0 { | |
| 92 ret += uint64(countBitsSet(uint64(word))) | |
| 93 } | |
| 94 } | |
| 95 return ret | |
| 96 } | |
| 97 | |
| 98 // IsSet returns the value of a given bit. | |
| 99 func (bf BitField) IsSet(idx uint64) bool { | |
| 100 return idx < bf.Size() && ((bf.Data[idx>>6] & (1 << (idx % 64))) != 0) | |
| 101 } | |
| OLD | NEW |