├── .npmignore ├── package.json ├── README.md ├── lib ├── bit-array.js └── bit-typed-array.js └── test └── bit-array-test.js /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bit-array", 3 | "description": "JavaScript implementation of bit arrays", 4 | "version": "0.2.4", 5 | "author": "Bram Stein (http://www.bramstein.com)", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/bramstein/bit-array.git" 9 | }, 10 | "keywords": ["bit array", "bit-array", "bit vector", "bitset", "bitmap", "bitstring"], 11 | "main": "./lib/bit-typed-array.js", 12 | "directories": { 13 | "lib": "./lib" 14 | }, 15 | "devDependencies": { 16 | "mocha": "=1.10.0", 17 | "expect.js": "=0.2.0" 18 | }, 19 | "scripts": { 20 | "test": "mocha --reporter spec" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Bit-Array is deprecated. 2 | 3 | Please use BitSet.js 4 | 5 | ## JavaScript Bit Array Library 6 | 7 | This library contains a JavaScript implementation of bit arrays. The library supports: 8 | 9 | * getting, setting and toggling of individual bits 10 | * iterating over each bit 11 | * counting the number of "on" bits 12 | * bitwise operations with other bit arrays such as OR, AND and XOR. 13 | * serialization to and from JSON 14 | * Browser, Node.js and Ender.js compatible 15 | 16 | The bit array is sparse. The following example shows how to set and get individual bits within the array: 17 | 18 | a = new BitArray(32); 19 | a.set(0, true); 20 | a.set(31, true); 21 | a.toString(); // "10000000000000000000000000000001" 22 | a.get(1); // false 23 | a.get(31); // true 24 | 25 | Note that the array internally uses 32 bit integers (actually, JavaScript's number type is 64 bit, but only 32 bits can be addressed using bitwise operations,) so going beyond the given length throws an error: 26 | 27 | a.set(32, true); // throws an index of range exception 28 | 29 | Even though bit arrays are not that useful in JavaScript, there is one place where they excel; encoding large boolean sets for transfer between the browser and server. A JSON representation of a bit array is much smaller than an actual boolean array. 30 | 31 | ## API 32 | 33 | The BitArray module has two constructors: 34 | 35 |
36 |
BitArray(size)
37 |
Creates a new empty bit array with the given size in bits.
38 | 39 |
BitArray(size, hex)
40 |
Creates a new bit array with the given size and using the hex string as value
41 |
42 | 43 | The following instance methods are supported: 44 | 45 |
46 |
size()
47 |
Returns the total number of bits in the BitArray.
48 | 49 |
set(index, boolean)
50 |
Sets the bit at index to a value (boolean.)
51 | 52 |
get(index)
53 |
Returns the value of the bit at index (boolean.)
54 | 55 |
toggle(index)
56 |
Toggles the bit at index. If the bit is on, it is turned off. Likewise, if the bit is off it is turned on.
57 | 58 |
reset()
59 |
Resets the BitArray so that it is empty and can be re-used.
60 | 61 |
copy()
62 |
Returns a copy of this BitArray.
63 | 64 |
equals(other)
65 |
Returns true if this BitArray equals another. Two BitArrays are considered equal if both have the same length and bit pattern.
66 | 67 |
toJSON()
68 |
Returns the JSON representation of this BitArray.
69 | 70 |
toString()
71 |
Returns a string representation of the BitArray with bits in logical order.
72 | 73 |
toHexString()
74 |
Returns a hex representation of the BitArray.
75 | 76 |
toArray()
77 |
Convert the BitArray to an Array of boolean values.
78 | 79 |
count()
80 |
Returns the total number of bits set to 1 in this BitArray.
81 | 82 |
not()
83 |
Inverts this BitArray.
84 | 85 |
or(other)
86 |
Bitwise OR on the values of this BitArray using BitArray `other`.
87 | 88 |
and(other)
89 |
Bitwise AND on the values of this BitArray using BitArray `other`.
90 | 91 |
xor(other)
92 |
Bitwise XOR on the values of this BitArray using BitArray `other`.
93 |
94 | 95 | ## Installation 96 | 97 | You can install the bit array module using npm: 98 | 99 | > npm install bit-array 100 | 101 | Alternatively you could just include [bit-array.js](lib/bit-array.js) in your project. 102 | 103 | ## License 104 | 105 | Licensed under the revised BSD License. Copyright 2010-2012 Bram Stein. All rights reserved. 106 | 107 | Ports 108 | ----- 109 | https://github.com/foglcz/bit-array - PHP port by Pavel Ptacek 110 | -------------------------------------------------------------------------------- /lib/bit-array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JavaScript BitArray - v0.2.0 3 | * 4 | * Licensed under the revised BSD License. 5 | * Copyright 2010-2012 Bram Stein 6 | * All rights reserved. 7 | */ 8 | 9 | /** 10 | * Creates a new empty BitArray with the given length or initialises the BitArray with the given hex representation. 11 | */ 12 | var BitArray = function (size, hex) { 13 | this.values = []; 14 | 15 | if (hex) { 16 | hex = hex.slice(/^0x/.exec(hex) ? 2 : 0); 17 | 18 | if (hex.length * 4 > this.length) { 19 | throw 'Hex value is too large for this bit array.' 20 | } else if (hex.length * 4 < this.length) { 21 | // pad it 22 | while(hex.length * 4 < this.length) { 23 | hex = '0' + hex; 24 | } 25 | } 26 | 27 | for (var i = 0; i < (hex.length / 8); i++) { 28 | var slice = hex.slice(i * 8, i * 8 + 8); 29 | this.values[i] = parseInt(slice, 16); 30 | } 31 | } else { 32 | for (var i = 0; i < Math.ceil(size / 32); i += 1) { 33 | this.values[i] = 0; 34 | } 35 | } 36 | }; 37 | 38 | /** 39 | * Returns the total number of bits in this BitArray. 40 | */ 41 | BitArray.prototype.size = function () { 42 | return this.values.length * 32; 43 | }; 44 | 45 | /** 46 | * Sets the bit at index to a value (boolean.) 47 | */ 48 | BitArray.prototype.set = function (index, value) { 49 | var i = Math.floor(index / 32); 50 | // Since "undefined | 1 << index" is equivalent to "0 | 1 << index" we do not need to initialise the array explicitly here. 51 | if (value) { 52 | this.values[i] |= 1 << index - i * 32; 53 | } else { 54 | this.values[i] &= ~(1 << index - i * 32); 55 | } 56 | return this; 57 | }; 58 | 59 | /** 60 | * Toggles the bit at index. If the bit is on, it is turned off. Likewise, if the bit is off it is turned on. 61 | */ 62 | BitArray.prototype.toggle = function (index) { 63 | var i = Math.floor(index / 32); 64 | this.values[i] ^= 1 << index - i * 32; 65 | return this; 66 | }; 67 | 68 | /** 69 | * Returns the value of the bit at index (boolean.) 70 | */ 71 | BitArray.prototype.get = function (index) { 72 | var i = Math.floor(index / 32); 73 | return !!(this.values[i] & (1 << index - i * 32)); 74 | }; 75 | 76 | /** 77 | * Resets the BitArray so that it is empty and can be re-used. 78 | */ 79 | BitArray.prototype.reset = function () { 80 | this.values = []; 81 | return this; 82 | }; 83 | 84 | /** 85 | * Returns a copy of this BitArray. 86 | */ 87 | BitArray.prototype.copy = function () { 88 | var cp = new BitArray(); 89 | cp.length = this.length; 90 | cp.values = [].concat(this.values); 91 | return cp; 92 | }; 93 | 94 | /** 95 | * Returns true if this BitArray equals another. Two BitArrays are considered 96 | * equal if both have the same length and bit pattern. 97 | */ 98 | BitArray.prototype.equals = function (x) { 99 | return this.values.length === x.values.length && 100 | this.values.every(function (value, index) { 101 | return value === x.values[index]; 102 | }); 103 | }; 104 | 105 | /** 106 | * Returns the JSON representation of this BitArray. 107 | */ 108 | BitArray.prototype.toJSON = function () { 109 | return JSON.stringify(this.values); 110 | }; 111 | 112 | /** 113 | * Returns a string representation of the BitArray with bits 114 | * in logical order. 115 | */ 116 | BitArray.prototype.toString = function () { 117 | return this.toArray().map(function (value) { 118 | return value ? '1' : '0'; 119 | }).join(''); 120 | }; 121 | 122 | /** 123 | * Returns a string representation of the BitArray with bits 124 | * in mathemetical order. 125 | */ 126 | BitArray.prototype.toBinaryString = function () { 127 | return this.toArray().map(function (value) { 128 | return value ? '1' : '0'; 129 | }).reverse().join(''); 130 | }; 131 | 132 | /** 133 | * Returns a hexadecimal string representation of the BitArray 134 | * with bits in logical order. 135 | */ 136 | BitArray.prototype.toHexString = function () { 137 | var result = []; 138 | 139 | for (var i = 0; i < this.values.length; i += 1) { 140 | result.push(('00000000' + (this.values[i] >>> 0).toString(16)).slice(-8)); 141 | } 142 | return result.join(''); 143 | }; 144 | 145 | /** 146 | * Convert the BitArray to an Array of boolean values. 147 | */ 148 | BitArray.prototype.toArray = function () { 149 | var result = []; 150 | 151 | for (var i = 0; i < this.values.length * 32; i += 1) { 152 | result.push(this.get(i)); 153 | } 154 | return result; 155 | }; 156 | 157 | /** 158 | * Returns the total number of bits set to one in this BitArray. 159 | */ 160 | BitArray.prototype.count = function () { 161 | var total = 0; 162 | 163 | // If we remove the toggle method we could efficiently cache the number of bits without calculating it on the fly. 164 | this.values.forEach(function (x) { 165 | // See: http://bits.stephan-brumme.com/countBits.html for an explanation 166 | x = x - ((x >> 1) & 0x55555555); 167 | x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 168 | x = x + (x >> 4); 169 | x &= 0xF0F0F0F; 170 | 171 | total += (x * 0x01010101) >> 24; 172 | }); 173 | return total; 174 | }; 175 | 176 | /** 177 | * Inverts this BitArray. 178 | */ 179 | BitArray.prototype.not = function () { 180 | this.values = this.values.map(function (v) { 181 | return ~v; 182 | }); 183 | return this; 184 | }; 185 | 186 | /** 187 | * Bitwise OR on the values of this BitArray using BitArray x. 188 | */ 189 | BitArray.prototype.or = function (x) { 190 | if (this.values.length !== x.values.length) { 191 | throw 'Arguments must be of the same length.'; 192 | } 193 | this.values = this.values.map(function (v, i) { 194 | return v | x.values[i]; 195 | }); 196 | return this; 197 | }; 198 | 199 | /** 200 | * Bitwise AND on the values of this BitArray using BitArray x. 201 | */ 202 | BitArray.prototype.and = function (x) { 203 | if (this.values.length !== x.values.length) { 204 | throw 'Arguments must be of the same length.'; 205 | } 206 | this.values = this.values.map(function (v, i) { 207 | return v & x.values[i]; 208 | }); 209 | return this; 210 | }; 211 | 212 | /** 213 | * Bitwise XOR on the values of this BitArray using BitArray x. 214 | */ 215 | BitArray.prototype.xor = function (x) { 216 | if (this.values.length !== x.values.length) { 217 | throw 'Arguments must be of the same length.'; 218 | } 219 | this.values = this.values.map(function (v, i) { 220 | return v ^ x.values[i]; 221 | }); 222 | return this; 223 | }; 224 | 225 | module.exports = BitArray; 226 | -------------------------------------------------------------------------------- /test/bit-array-test.js: -------------------------------------------------------------------------------- 1 | var BitArray = require('../lib/bit-typed-array.js'), 2 | expect = require('expect.js'); 3 | 4 | describe('BitArray', function () { 5 | it('should create an empty bit array', function () { 6 | expect(new BitArray(0).toString().length).to.eql(0); 7 | expect(new BitArray(0).size()).to.eql(0); 8 | }); 9 | 10 | it('should parse hex given to the constructor', function () { 11 | var b = new BitArray(32, 'deadbeef'); 12 | 13 | expect(b.toBinaryString()).to.eql('11011110101011011011111011101111'); 14 | expect(b.toHexString()).to.eql('deadbeef'); 15 | 16 | var c = new BitArray(64, '0000c0ffeec0ffee').and(new BitArray(64, 'ffffffffff000000')); 17 | 18 | expect(c.toHexString()).to.eql('0000c0ffee000000'); 19 | }); 20 | 21 | it('should correctly pad hex given in the constructor', function () { 22 | var b = new BitArray(32, 'f'); 23 | 24 | expect(b.toHexString()).to.eql('0000000f'); 25 | expect(b.toBinaryString()).to.eql('00000000000000000000000000001111'); 26 | }); 27 | 28 | it('should correctly convert a bit array to hex', function () { 29 | var b = new BitArray(32); 30 | 31 | b.set(5, true); 32 | b.set(6, true); 33 | 34 | expect(b.toHexString()).to.eql('00000060'); 35 | expect(b.toBinaryString()).to.eql('00000000000000000000000001100000'); 36 | 37 | var c = new BitArray(32, b.toHexString()); 38 | 39 | expect(c.toHexString()).to.eql('00000060'); 40 | expect(c.toBinaryString()).to.eql('00000000000000000000000001100000'); 41 | }); 42 | 43 | it('should set individual bits', function () { 44 | var b = new BitArray(32); 45 | 46 | b.set(31, true); // 0 | 1 << 30 47 | expect(b.size()).to.eql(32); 48 | expect(b.toString()).to.eql('00000000000000000000000000000001'); 49 | 50 | b.set(0, true); // 0 | 1 << 31 | 1 << 0 51 | expect(b.size()).to.eql(32); 52 | expect(b.toString()).to.eql('10000000000000000000000000000001'); 53 | 54 | b.set(15, true); // 0 | 1 << 31 | 1 << 0 | 1 << 15 55 | expect(b.size()).to.eql(32); 56 | expect(b.toString(), '10000000000000010000000000000001'); 57 | 58 | // Reset bit 15 to false 59 | b.set(15, false); // 0 | 1 << 31 | 1 << 0 60 | expect(b.size()).to.eql(32); 61 | expect(b.toString()).to.eql('10000000000000000000000000000001'); 62 | 63 | // Reset bit 0 to false 64 | b.set(0, false) // 0 | 1 << 31 65 | expect(b.size()).to.eql(32); 66 | expect(b.toString()).to.eql('00000000000000000000000000000001'); 67 | 68 | // Reset bit 31 to false 69 | b.set(31, false) // 0 70 | expect(b.size()).to.eql(32); 71 | expect(b.toString()).to.eql('00000000000000000000000000000000'); 72 | }); 73 | 74 | it('should be able to set bits beyond a single integer', function () { 75 | var b = new BitArray(64); 76 | 77 | b.set(32, true); 78 | 79 | expect(b.size()).to.eql(64); 80 | expect(b.toString()).to.eql('0000000000000000000000000000000010000000000000000000000000000000'); 81 | }); 82 | 83 | it('should get individual bits', function () { 84 | var b = new BitArray(32); 85 | b.set(0, true); 86 | b.set(4, true); 87 | b.set(31, true); 88 | 89 | expect(b.get(0)).to.be(true); 90 | expect(b.get(4)).to.be(true); 91 | expect(b.get(31)).to.be(true); 92 | }); 93 | 94 | it('should be able to get bits beyond a single integer', function () { 95 | var b = new BitArray(64); 96 | b.set(32, true); 97 | 98 | expect(b.size()).to.eql(64); 99 | expect(b.get(32)).to.be(true); 100 | }); 101 | 102 | it('should toggle individual bits', function () { 103 | var b = new BitArray(32); 104 | b.set(0, true); 105 | b.set(31, true); 106 | 107 | expect(b.toggle(0).get(0)).to.be(false); 108 | expect(b.toggle(4).get(4)).to.be(true); 109 | expect(b.toggle(31).get(31)).to.be(false); 110 | }); 111 | 112 | it('should toggle individual bits beyond a single integer', function () { 113 | var b = new BitArray(64); 114 | b.set(32, true); 115 | 116 | expect(b.size()).to.eql(64); 117 | expect(b.toggle(32).get(32)).to.be(false); 118 | expect(b.toggle(33).get(33)).to.be(true); 119 | }); 120 | 121 | it('should report the correct size', function () { 122 | var b = new BitArray(224); 123 | b.set(200, true); // Math.floor(200 / 32) + 1 * 32; 124 | expect(b.size()).to.eql(224); 125 | }); 126 | 127 | it('should count the individual on bits', function () { 128 | var b = new BitArray(72); 129 | 130 | b.set(32, true); 131 | b.set(70, true); 132 | b.set(1, true); 133 | b.set(12, true); 134 | 135 | expect(b.count()).to.eql(4); 136 | }); 137 | 138 | it('should be able to compare bit arrays', function () { 139 | var a = new BitArray(224), 140 | b = new BitArray(224), 141 | c = new BitArray(224), 142 | d = new BitArray(224); 143 | 144 | a.set(0, true); 145 | a.set(1, true); 146 | a.set(200, true); 147 | a.set(36, true); 148 | 149 | b.set(0, true); 150 | b.set(1, true); 151 | b.set(200, true); 152 | b.set(36, true); 153 | 154 | c.set(0, true); 155 | c.set(1, true); 156 | c.set(200, true); 157 | 158 | d.set(0, true); 159 | d.set(1, true); 160 | d.set(36, true); 161 | 162 | expect(a.equals(b)).to.be(true); 163 | expect(a.equals(c)).to.be(false); 164 | expect(a.equals(d)).to.be(false); 165 | }); 166 | 167 | it('should copy a bit array', function () { 168 | var a = new BitArray(224), 169 | b; 170 | 171 | a.set(0, true); 172 | a.set(1, true); 173 | a.set(200, true); 174 | a.set(36, true); 175 | 176 | b = a.copy(); 177 | expect(a.toString()).to.eql(b.toString()); 178 | }); 179 | 180 | it('should negate bit arrays', function () { 181 | var b = new BitArray(64), 182 | a; 183 | 184 | b.set(2, true); 185 | b.set(7, true); 186 | b.set(18, true); 187 | b.set(26, true); 188 | b.set(30, true); 189 | 190 | a = b.toString(); 191 | a = a.replace(/0/g, 'x'); 192 | a = a.replace(/1/g, '0'); 193 | a = a.replace(/x/g, '1'); 194 | b.not(); 195 | 196 | expect(b.toString()).to.eql(a); 197 | }); 198 | 199 | it('should or bit arrays', function () { 200 | var a = new BitArray(32), 201 | b = new BitArray(32); 202 | 203 | a.set(0, true);//1110 204 | a.set(1, false); 205 | a.set(2, true); 206 | a.set(3, false); 207 | 208 | b.set(0, true); 209 | b.set(1, true); 210 | b.set(2, false); 211 | b.set(3, false); 212 | 213 | expect(a.or(b).toString()).to.eql('11100000000000000000000000000000'); 214 | }); 215 | 216 | it('should and bit arrays', function () { 217 | var a = new BitArray(32), 218 | b = new BitArray(32); 219 | 220 | a.set(0, true); 221 | a.set(1, false); 222 | a.set(2, true); 223 | a.set(3, false); 224 | 225 | b.set(0, true); 226 | b.set(1, true); 227 | b.set(2, false); 228 | b.set(3, false); 229 | 230 | expect(a.and(b).toString()).to.eql('10000000000000000000000000000000'); 231 | }); 232 | 233 | it('should xor bit arrays', function () { 234 | var a = new BitArray(32), 235 | b = new BitArray(32); 236 | 237 | a.set(0, true); 238 | a.set(1, false); 239 | a.set(2, true); 240 | a.set(3, false); 241 | 242 | b.set(0, true); 243 | b.set(1, true); 244 | b.set(2, false); 245 | b.set(3, false); 246 | 247 | expect(a.xor(b).toString()).to.eql('01100000000000000000000000000000'); 248 | }); 249 | }); 250 | -------------------------------------------------------------------------------- /lib/bit-typed-array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JavaScript BitArray - v0.2.0 3 | * 4 | * Licensed under the revised BSD License. 5 | * Copyright 2010-2012 Bram Stein 6 | * All rights reserved. 7 | */ 8 | 9 | /** 10 | * Creates a new empty BitArray with the given length or initialises the BitArray with the given hex representation. 11 | */ 12 | var BitArray = function (size, hex) { 13 | this.length = size; 14 | this.buffer = new ArrayBuffer(Math.ceil(this.length / 32) * 4); 15 | this.wordArray = new Uint32Array(this.buffer); 16 | 17 | if (hex) { 18 | hex = hex.slice(/^0x/.exec(hex) ? 2 : 0); 19 | 20 | if (hex.length * 4 > this.length) { 21 | throw 'Hex value is too large for this bit array.' 22 | } else if (hex.length * 4 < this.length) { 23 | // pad it 24 | while(hex.length * 4 < this.length) { 25 | hex = '0' + hex; 26 | } 27 | } 28 | 29 | for (var i = 0; i < (hex.length / 8); i++) { 30 | var slice = hex.slice(i * 8, i * 8 + 8); 31 | this.wordArray[i] = parseInt(slice, 16); 32 | } 33 | } 34 | }; 35 | 36 | /** 37 | * Returns the total number of bits in this BitArray. 38 | */ 39 | BitArray.prototype.size = function() { 40 | return this.length; 41 | }; 42 | 43 | /** 44 | * Sets the bit at index to a value (boolean.) 45 | */ 46 | BitArray.prototype.set = function(index, value) { 47 | if (arguments.length !== 2) { 48 | throw 'Index and value are required arguments.'; 49 | } 50 | if (index > this.length - 1) { 51 | throw 'Index too large.' + index + ' ' + this.length; 52 | } 53 | var wordOffset = Math.floor(index / 32); 54 | // The underlying byte buffer will be initialized to zeros. 55 | var bitOffset = index - wordOffset * 32; 56 | if (value) { 57 | this.wordArray[wordOffset] |= (1 << bitOffset); 58 | } else { 59 | this.wordArray[wordOffset] &= ~(1 << bitOffset); 60 | } 61 | return this; 62 | }; 63 | 64 | /** 65 | * Toggles the bit at index. If the bit is on, it is turned off. Likewise, if the bit is off it is turned on. 66 | */ 67 | BitArray.prototype.toggle = function(index) { 68 | if (index > this.length - 1) { 69 | throw 'Index too large.'; 70 | } 71 | var wordOffset = Math.floor(index / 32); 72 | var bitOffset = index - wordOffset * 32; 73 | this.wordArray[wordOffset] ^= 1 << bitOffset; 74 | return this; 75 | }; 76 | 77 | /** 78 | * Returns the value of the bit at index (boolean.) 79 | */ 80 | BitArray.prototype.get = function(index) { 81 | if (index > this.length - 1) { 82 | throw 'Index too large.'; 83 | } 84 | var wordOffset = Math.floor(index / 32); 85 | var bitOffset = index - wordOffset * 32; 86 | return !! (this.wordArray[wordOffset] & (1 << bitOffset)); 87 | }; 88 | 89 | /** 90 | * Resets the BitArray so that it is empty and can be re-used. 91 | */ 92 | BitArray.prototype.reset = function() { 93 | this.buffer = new ArrayBuffer(Math.ceil(this.length / 32) * 4); 94 | this.wordArray = new Uint32Array(this.buffer); 95 | return this; 96 | }; 97 | 98 | /** 99 | * Returns a copy of this BitArray. 100 | */ 101 | BitArray.prototype.copy = function() { 102 | var cp = new BitArray(this.length); 103 | for (var i = 0; i < this.wordArray.length; i++) { 104 | cp.wordArray[i] = this.wordArray[i]; 105 | } 106 | return cp; 107 | }; 108 | 109 | /** 110 | * Returns true if this BitArray equals another. Two BitArrays are considered 111 | * equal if both have the same length and bit pattern. 112 | */ 113 | BitArray.prototype.equals = function(x) { 114 | if (this.length !== x.length) { 115 | return false; 116 | } 117 | for (var i = 0; i < this.wordArray.length; i++) { 118 | if (this.wordArray[i] !== x.wordArray[i]) { 119 | return false; 120 | } 121 | } 122 | return true; 123 | }; 124 | 125 | /** 126 | * Returns the JSON representation of this BitArray. 127 | */ 128 | BitArray.prototype.toJSON = function() { 129 | return JSON.stringify(this.toArray()); 130 | }; 131 | 132 | /** 133 | * Returns a string representation of the BitArray with bits 134 | * in mathemetical order. 135 | */ 136 | BitArray.prototype.toBinaryString = function () { 137 | return this.toArray().map(function (value) { 138 | return value ? '1' : '0'; 139 | }).reverse().join(''); 140 | }; 141 | 142 | /** 143 | * Returns a hexadecimal string representation of the BitArray 144 | * with bits in logical order. 145 | */ 146 | BitArray.prototype.toHexString = function () { 147 | var result = []; 148 | 149 | for (var i = 0; i < this.wordArray.length; i += 1) { 150 | //result.push(this.wordArray[i].toString(16)); 151 | result.push(('00000000' + (this.wordArray[i] >>> 0).toString(16)).slice(-8)); 152 | } 153 | return result.join(''); 154 | }; 155 | 156 | /** 157 | * Returns a string representation of the BitArray with bits 158 | * in logical order. 159 | */ 160 | BitArray.prototype.toString = function() { 161 | return this.toArray().map(function(value) { 162 | return value ? '1': '0'; 163 | }).join(''); 164 | }; 165 | 166 | /** 167 | * Convert the BitArray to an Array of boolean values (slow). 168 | */ 169 | BitArray.prototype.toArray = function() { 170 | var result = []; 171 | for (var i = 0; i < this.length; i++) { 172 | result.push(Boolean(this.get(i))); 173 | } 174 | return result; 175 | }; 176 | 177 | /** 178 | * Returns the total number of bits set to one in this BitArray. 179 | */ 180 | BitArray.prototype.count = function() { 181 | var total = 0; 182 | for (var i = 0; i < this.wordArray.length; i++) { 183 | x = this.wordArray[i]; 184 | // count bits of each 2-bit chunk 185 | x = x - ((x >> 1) & 0x55555555); 186 | // count bits of each 4-bit chunk 187 | x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 188 | // count bits of each 8-bit chunk 189 | x = x + (x >> 4); 190 | // mask out junk 191 | x &= 0xF0F0F0F; 192 | // add all four 8-bit chunks 193 | total += (x * 0x01010101) >> 24; 194 | } 195 | return total; 196 | }; 197 | 198 | /** 199 | * Inverts this BitArray. 200 | */ 201 | BitArray.prototype.not = function() { 202 | for (var i = 0; i < this.wordArray.length; i++) { 203 | this.wordArray[i] = ~(this.wordArray[i]); 204 | } 205 | return this; 206 | }; 207 | 208 | /** 209 | * Bitwise OR on the values of this BitArray using BitArray x. 210 | */ 211 | BitArray.prototype.or = function(x) { 212 | if (this.length !== x.length) { 213 | throw 'Arguments must be of the same length.'; 214 | } 215 | for (var i = 0; i < this.wordArray.length; i++) { 216 | this.wordArray[i] |= x.wordArray[i]; 217 | } 218 | return this; 219 | }; 220 | 221 | /** 222 | * Bitwise AND on the values of this BitArray using BitArray x. 223 | */ 224 | BitArray.prototype.and = function(x) { 225 | if (this.length !== x.length) { 226 | throw 'Arguments must be of the same length.'; 227 | } 228 | for (var i = 0; i < this.wordArray.length; i++) { 229 | this.wordArray[i] &= x.wordArray[i]; 230 | } 231 | return this; 232 | }; 233 | 234 | /** 235 | * Bitwise XOR on the values of this BitArray using BitArray x. 236 | */ 237 | BitArray.prototype.xor = function(x) { 238 | if (this.length !== x.length) { 239 | throw 'Arguments must be of the same length.'; 240 | } 241 | for (var i = 0; i < this.wordArray.length; i++) { 242 | this.wordArray[i] ^= x.wordArray[i]; 243 | } 244 | return this; 245 | }; 246 | 247 | module.exports = BitArray; 248 | --------------------------------------------------------------------------------