Skip to content

Instantly share code, notes, and snippets.

@rplantiko
Created October 9, 2016 13:18
Show Gist options
  • Save rplantiko/4d5c642e98baddcd11d5aa7242dc7622 to your computer and use it in GitHub Desktop.
Save rplantiko/4d5c642e98baddcd11d5aa7242dc7622 to your computer and use it in GitHub Desktop.
// A bitfield represents a binary number of arbitrary length
// This implementation requires the JavaScript Uint32Array data type
function BitField(length,data) {
if (length instanceof BitField) {
// Copy-Constructor from a given BitField
this.length = length.length
this.maxIndex = length.maxIndex
this.maxMask = length.maxMask
this.maxPlaces = length.maxPlaces
this.data = Uint32Array.from(length.data)
}
else {
this.length = length
this.maxIndex = ( ~~(length/32) + (length % 32 && 1) ) - 1
this.maxMask = length % 32 ? (1 << length % 32) - 1 : 0xffffffff
this.maxPlaces = length % 32 || 32
if (data) {
if (data instanceof Uint32Array)
this.data = data
else if (data instanceof Array) {
this.data = Uint32Array.from(data)
}
else if (typeof data == "number") {
this.data = new Uint32Array( this.maxIndex + 1 )
this.data[0] = data
}
}
else
this.data = new Uint32Array( this.maxIndex + 1 )
}
}
BitField.prototype.get = function(pos) {
return ( this.data[~~(pos/32)] & (1 << (pos % 32) ) ) && 1
}
BitField.prototype.set = function(pos) {
this.data[~~(pos/32)] |= ( 1 << (pos % 32))
}
BitField.prototype.unset = function(pos) {
this.data[~~(pos/32)] &= ~( 1 << (pos % 32))
}
BitField.prototype.clear = function() {
this.data.fill(0)
}
BitField.prototype.increment = function() {
for (var i=0;i<this.maxIndex;i++) {
if (this.data[i] != 0xffffffff) {
this.data[i]++
return true
}
else {
this.data[i] = 0
}
}
if (this.data[this.maxIndex] != this.maxMask) {
this.data[this.maxIndex]++
return true
}
else {
return false // Maximum reached
}
}
BitField.prototype.equals = function(bf) {
if (this.length != bf.length) return false
for (var i=0;i<this.maxIndex;i++) {
if (this.data[i] != bf.data[i]) return false;
}
return (((this.data[this.maxIndex]^bf.data[this.maxIndex])&this.maxMask)==0)
}
BitField.prototype.toString = function() {
return pad((this.data[this.maxIndex]&this.maxMask).toString(2),this.maxPlaces) +
this.data.slice(0,this.data.length-1).reverse().map(function(i){
return pad(i.toString(2),32)
}).join("")
function pad(s,k) {
return ("00000000000000000000000000000000"+s).slice(-k)
}
}
/* Some additions for retarded browsers
The implementations do not pretend to be fully-featured
They are just enough to make the class BitField usable in older browsers */
if (!Uint32Array.from) {
Uint32Array.from = function(array) {
var result = new Uint32Array(array.length)
for (var i=0;i<array.length;i++) result[i] = array[i]
return result
}
}
if (!Array.prototype.fill) {
Array.prototype.fill = function(value) {
for (var i=0;i<this.length;i++) this[i] = value
return this
}
}
if (!Uint32Array.prototype.slice) {
Uint32Array.prototype.slice = function(i1,i2) {
var result = new Uint32Array(i2-i1)
for (var i=i1;i<i2;i++) result[i-i1] = this[i]
return result
}
}
if (!Uint32Array.prototype.reverse) {
Uint32Array.prototype.reverse = function() {
var len = this.length
var result = new Uint32Array(len)
for (var i=0;i<len;i++) result[i]=this[len-i-1]
return result
}
}
if (!Uint32Array.prototype.map) {
Uint32Array.prototype.map = function(f) {
var len = this.length
var result = new Uint32Array(len)
for (var i=0;i<len;i++) result[i] = f(this[i])
return result
}
}
if (!Uint32Array.prototype.join) {
Uint32Array.prototype.join = function(s) {
var len = this.length
var result = ""
for (var i=0;i<len;i++) {
if (i>0 && i<len-1) result += s
result += this[i]
}
return result
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment