Created
October 9, 2016 13:18
-
-
Save rplantiko/4d5c642e98baddcd11d5aa7242dc7622 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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