Spaces:
Sleeping
Sleeping
| /** | |
| * Bit twiddling hacks for JavaScript. | |
| * | |
| * Author: Mikola Lysenko | |
| * | |
| * Ported from Stanford bit twiddling hack library: | |
| * http://graphics.stanford.edu/~seander/bithacks.html | |
| */ | |
| ; "use restrict"; | |
| //Number of bits in an integer | |
| var INT_BITS = 32; | |
| //Constants | |
| exports.INT_BITS = INT_BITS; | |
| exports.INT_MAX = 0x7fffffff; | |
| exports.INT_MIN = -1<<(INT_BITS-1); | |
| //Returns -1, 0, +1 depending on sign of x | |
| exports.sign = function(v) { | |
| return (v > 0) - (v < 0); | |
| } | |
| //Computes absolute value of integer | |
| exports.abs = function(v) { | |
| var mask = v >> (INT_BITS-1); | |
| return (v ^ mask) - mask; | |
| } | |
| //Computes minimum of integers x and y | |
| exports.min = function(x, y) { | |
| return y ^ ((x ^ y) & -(x < y)); | |
| } | |
| //Computes maximum of integers x and y | |
| exports.max = function(x, y) { | |
| return x ^ ((x ^ y) & -(x < y)); | |
| } | |
| //Checks if a number is a power of two | |
| exports.isPow2 = function(v) { | |
| return !(v & (v-1)) && (!!v); | |
| } | |
| //Computes log base 2 of v | |
| exports.log2 = function(v) { | |
| var r, shift; | |
| r = (v > 0xFFFF) << 4; v >>>= r; | |
| shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; | |
| shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; | |
| shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; | |
| return r | (v >> 1); | |
| } | |
| //Computes log base 10 of v | |
| exports.log10 = function(v) { | |
| return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : | |
| (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : | |
| (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; | |
| } | |
| //Counts number of bits | |
| exports.popCount = function(v) { | |
| v = v - ((v >>> 1) & 0x55555555); | |
| v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); | |
| return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; | |
| } | |
| //Counts number of trailing zeros | |
| function countTrailingZeros(v) { | |
| var c = 32; | |
| v &= -v; | |
| if (v) c--; | |
| if (v & 0x0000FFFF) c -= 16; | |
| if (v & 0x00FF00FF) c -= 8; | |
| if (v & 0x0F0F0F0F) c -= 4; | |
| if (v & 0x33333333) c -= 2; | |
| if (v & 0x55555555) c -= 1; | |
| return c; | |
| } | |
| exports.countTrailingZeros = countTrailingZeros; | |
| //Rounds to next power of 2 | |
| exports.nextPow2 = function(v) { | |
| v += v === 0; | |
| --v; | |
| v |= v >>> 1; | |
| v |= v >>> 2; | |
| v |= v >>> 4; | |
| v |= v >>> 8; | |
| v |= v >>> 16; | |
| return v + 1; | |
| } | |
| //Rounds down to previous power of 2 | |
| exports.prevPow2 = function(v) { | |
| v |= v >>> 1; | |
| v |= v >>> 2; | |
| v |= v >>> 4; | |
| v |= v >>> 8; | |
| v |= v >>> 16; | |
| return v - (v>>>1); | |
| } | |
| //Computes parity of word | |
| exports.parity = function(v) { | |
| v ^= v >>> 16; | |
| v ^= v >>> 8; | |
| v ^= v >>> 4; | |
| v &= 0xf; | |
| return (0x6996 >>> v) & 1; | |
| } | |
| var REVERSE_TABLE = new Array(256); | |
| (function(tab) { | |
| for(var i=0; i<256; ++i) { | |
| var v = i, r = i, s = 7; | |
| for (v >>>= 1; v; v >>>= 1) { | |
| r <<= 1; | |
| r |= v & 1; | |
| --s; | |
| } | |
| tab[i] = (r << s) & 0xff; | |
| } | |
| })(REVERSE_TABLE); | |
| //Reverse bits in a 32 bit word | |
| exports.reverse = function(v) { | |
| return (REVERSE_TABLE[ v & 0xff] << 24) | | |
| (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | | |
| (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | | |
| REVERSE_TABLE[(v >>> 24) & 0xff]; | |
| } | |
| //Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes | |
| exports.interleave2 = function(x, y) { | |
| x &= 0xFFFF; | |
| x = (x | (x << 8)) & 0x00FF00FF; | |
| x = (x | (x << 4)) & 0x0F0F0F0F; | |
| x = (x | (x << 2)) & 0x33333333; | |
| x = (x | (x << 1)) & 0x55555555; | |
| y &= 0xFFFF; | |
| y = (y | (y << 8)) & 0x00FF00FF; | |
| y = (y | (y << 4)) & 0x0F0F0F0F; | |
| y = (y | (y << 2)) & 0x33333333; | |
| y = (y | (y << 1)) & 0x55555555; | |
| return x | (y << 1); | |
| } | |
| //Extracts the nth interleaved component | |
| exports.deinterleave2 = function(v, n) { | |
| v = (v >>> n) & 0x55555555; | |
| v = (v | (v >>> 1)) & 0x33333333; | |
| v = (v | (v >>> 2)) & 0x0F0F0F0F; | |
| v = (v | (v >>> 4)) & 0x00FF00FF; | |
| v = (v | (v >>> 16)) & 0x000FFFF; | |
| return (v << 16) >> 16; | |
| } | |
| //Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes | |
| exports.interleave3 = function(x, y, z) { | |
| x &= 0x3FF; | |
| x = (x | (x<<16)) & 4278190335; | |
| x = (x | (x<<8)) & 251719695; | |
| x = (x | (x<<4)) & 3272356035; | |
| x = (x | (x<<2)) & 1227133513; | |
| y &= 0x3FF; | |
| y = (y | (y<<16)) & 4278190335; | |
| y = (y | (y<<8)) & 251719695; | |
| y = (y | (y<<4)) & 3272356035; | |
| y = (y | (y<<2)) & 1227133513; | |
| x |= (y << 1); | |
| z &= 0x3FF; | |
| z = (z | (z<<16)) & 4278190335; | |
| z = (z | (z<<8)) & 251719695; | |
| z = (z | (z<<4)) & 3272356035; | |
| z = (z | (z<<2)) & 1227133513; | |
| return x | (z << 2); | |
| } | |
| //Extracts nth interleaved component of a 3-tuple | |
| exports.deinterleave3 = function(v, n) { | |
| v = (v >>> n) & 1227133513; | |
| v = (v | (v>>>2)) & 3272356035; | |
| v = (v | (v>>>4)) & 251719695; | |
| v = (v | (v>>>8)) & 4278190335; | |
| v = (v | (v>>>16)) & 0x3FF; | |
| return (v<<22)>>22; | |
| } | |
| //Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) | |
| exports.nextCombination = function(v) { | |
| var t = v | (v - 1); | |
| return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); | |
| } | |