UNPKG

uint32

Version:

a javascript library for dealing with (bitwise) uint32 operations

251 lines (221 loc) 8.97 kB
/* jshint bitwise: false */ /** * @license (c) Franz X Antesberger 2013 */ (function (exporter) { 'use strict'; var POW_2_32 = 0x0100000000; var POW_2_52 = 0x10000000000000; // // Creating and Extracting // /** * Creates an uint32 from the given bytes in big endian order. * @param {Number} highByte the high byte * @param {Number} secondHighByte the 2nd high byte * @param {Number} thirdHighByte the 3rd high byte * @param {Number} lowByte the low byte * @returns highByte concat secondHighByte concat thirdHighByte concat lowByte */ exporter.fromBytesBigEndian = function (highByte, secondHighByte, thirdHighByte, lowByte) { return ((highByte << 24) | (secondHighByte << 16) | (thirdHighByte << 8) | lowByte) >>> 0; }; /** * Returns the byte. * e.g. when byteNo is 0, the high byte is returned, when byteNo = 3 the low byte is returned. * @param {Number} uint32value the source to be extracted * @param {Number} byteNo 0-3 the byte number, 0 is the high byte, 3 the low byte * @returns {Number} the 0-255 byte according byteNo */ exporter.getByteBigEndian = function (uint32value, byteNo) { return (uint32value >>> (8 * (3 - byteNo))) & 0xff; }; /** * Returns the bytes as array. * @param {Number} uint32value the source to be extracted * @returns {Array} the array [highByte, 2ndHighByte, 3rdHighByte, lowByte] */ exporter.getBytesBigEndian = function (uint32value) { return [ exporter.getByteBigEndian(uint32value, 0), exporter.getByteBigEndian(uint32value, 1), exporter.getByteBigEndian(uint32value, 2), exporter.getByteBigEndian(uint32value, 3) ]; }; /** * Converts a given uin32 to a hex string including leading zeros. * @param {Number} uint32value the uint32 to be stringified * @param {Number} optionalMinLength the optional (default 8) */ exporter.toHex = function (uint32value, optionalMinLength) { optionalMinLength = optionalMinLength || 8; var result = uint32value.toString(16); if (result.length < optionalMinLength) { result = new Array(optionalMinLength - result.length + 1).join('0') + result; } return result; }; /** * Converts a number to an uint32. * @param {Number} number the number to be converted. * @return {Number} an uint32 value */ exporter.toUint32 = function (number) { // the shift operator forces js to perform the internal ToUint32 (see ecmascript spec 9.6) return number >>> 0; }; /** * Returns the part above the uint32 border. * Depending to the javascript engine, that are the 54-32 = 22 high bits * @param {Number} number the number to extract the high part * @return {Number} the high part of the number */ exporter.highPart = function (number) { return exporter.toUint32(number / POW_2_32); }; // // Bitwise Logical Operators // /** * Returns a bitwise OR operation on two or more values. * @param {Number} uint32val0 first uint32 value * @param {Number} argv one or more uint32 values * @return {Number} the bitwise OR uint32 value */ exporter.or = function (uint32val0, argv) { var result = uint32val0; for (var index = 1; index < arguments.length; index += 1) { result = (result | arguments[index]); } return result >>> 0; }; /** * Returns a bitwise AND operation on two or more values. * @param {Number} uint32val0 first uint32 value * @param {Number} argv one or more uint32 values * @return {Number} the bitwise AND uint32 value */ exporter.and = function (uint32val0, argv) { var result = uint32val0; for (var index = 1; index < arguments.length; index += 1) { result = (result & arguments[index]); } return result >>> 0; }; /** * Returns a bitwise XOR operation on two or more values. * @param {Number} uint32val0 first uint32 value * @param {Number} argv one or more uint32 values * @return {Number} the bitwise XOR uint32 value */ exporter.xor = function (uint32val0, argv) { var result = uint32val0; for (var index = 1; index < arguments.length; index += 1) { result = (result ^ arguments[index]); } return result >>> 0; }; exporter.not = function (uint32val) { return (~uint32val) >>> 0; }; // // Shifting and Rotating // /** * Returns the uint32 representation of a << operation. * @param {Number} uint32val the word to be shifted * @param {Number} numBits the number of bits to be shifted (0-31) * @returns {Number} the uint32 value of the shifted word */ exporter.shiftLeft = function (uint32val, numBits) { return (uint32val << numBits) >>> 0; }; /** * Returns the uint32 representation of a >>> operation. * @param {Number} uint32val the word to be shifted * @param {Number} numBits the number of bits to be shifted (0-31) * @returns {Number} the uint32 value of the shifted word */ exporter.shiftRight = function (uint32val, numBits) { return uint32val >>> numBits; }; exporter.rotateLeft = function (uint32val, numBits) { return (((uint32val << numBits) >>> 0) | (uint32val >>> (32 - numBits))) >>> 0; }; exporter.rotateRight = function (uint32val, numBits) { return (((uint32val) >>> (numBits)) | ((uint32val) << (32 - numBits)) >>> 0) >>> 0; }; // // Logical Gates // /** * Bitwise choose bits from y or z, as a bitwise x ? y : z */ exporter.choose = function (x, y, z) { return ((x & (y ^ z)) ^ z) >>> 0; }; /** * Majority gate for three parameters. Takes bitwise the majority of x, y and z, * @see https://en.wikipedia.org/wiki/Majority_function */ exporter.majority = function (x, y, z) { return ((x & (y | z)) | (y & z)) >>> 0; }; // // Arithmetic // /** * Adds the given values modulus 2^32. * @returns the sum of the given values modulus 2^32 */ exporter.addMod32 = function (uint32val0/*, optionalValues*/) { var result = uint32val0; for (var index = 1; index < arguments.length; index += 1) { result += arguments[index]; } return result >>> 0; }; /** * Returns the log base 2 of the given value. That is the number of the highest set bit. * @param {Number} uint32val the value, the log2 is calculated of * @return {Number} the logarithm base 2, an integer between 0 and 31 */ exporter.log2 = function (uint32val) { return Math.floor(Math.log(uint32val) / Math.LN2); }; /* // this implementation does the same, looks much funnier, but takes 2 times longer (according to jsperf) ... var log2_u = new Uint32Array(2); var log2_d = new Float64Array(log2_u.buffer); exporter.log2 = function (uint32val) { // Ported from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogIEEE64Float to javascript // (public domain) if (uint32val === 0) { return -Infinity; } // fill in the low part log2_u[0] = uint32val; // set the mantissa to 2^52 log2_u[1] = 0x43300000; // subtract 2^52 log2_d[0] -= 0x10000000000000; return (log2_u[1] >>> 20) - 0x3FF; }; */ /** * Returns the the low and the high uint32 of the multiplication. * @param {Number} factor1 an uint32 * @param {Number} factor2 an uint32 * @param {Uint32Array[2]} resultUint32Array2 the Array, where the result will be written to * @returns undefined */ exporter.mult = function (factor1, factor2, resultUint32Array2) { var high16 = ((factor1 & 0xffff0000) >>> 0) * factor2; var low16 = (factor1 & 0x0000ffff) * factor2; // the addition is dangerous, because the result will be rounded, so the result depends on the lowest bits, which will be cut away! var carry = ((exporter.toUint32(high16) + exporter.toUint32(low16)) >= POW_2_32) ? 1 : 0; resultUint32Array2[0] = (exporter.highPart(high16) + exporter.highPart(low16) + carry) >>> 0; resultUint32Array2[1] = ((high16 >>> 0) + (low16 >>> 0));// >>> 0; }; }) ((typeof module !== 'undefined') ? module.exports = {} : window.uint32 = {});