Skip to content

Commit

Permalink
helpers: power of two related functions added
Browse files Browse the repository at this point in the history
  • Loading branch information
royaltm committed Sep 30, 2019
1 parent c9e7edf commit 30bac22
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
28 changes: 28 additions & 0 deletions lib/utils/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,31 @@ exports.validateIntegerOption = function(options, name, min, max) {
if (max !== undefined && value > max) throw new TypeError(`options.${name} must be <= ${max}`);
return value;
};

/**
* Returns `true` if the num is a power of two in the range of [1, 2^32].
*
* @param {number} num
* @return {bool}
**/
exports.isPowerOfTwo32 = function(num) {
return (num - 1) >>> 0 === (num - 1) && num !== 0 && !(num & (num - 1))
};

/**
* Returns the next power of two in the range of [1, 2^31]. Otherwise returns 0.
*
* @param {number} num
* @return {number}
**/
exports.nextPowerOfTwo32 = function(num) {
num = num >> 0;
num--;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
num++;
return num;
};
54 changes: 53 additions & 1 deletion test/utils/test.helpers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018 Rafał Michalski <[email protected]>
* Copyright (c) 2016-2019 Rafał Michalski <[email protected]>
* License: LGPL
*/
"use strict";
Expand Down Expand Up @@ -337,3 +337,55 @@ test('validateIntegerOption', t => {
t.throws(() => helpers.validateIntegerOption({foo: '100'}, 'foo', null, 99), new TypeError("options.foo must be <= 99"));
t.end();
});

test('isPowerOfTwo32', t => {
t.strictEquals(helpers.isPowerOfTwo32(), false);
t.strictEquals(helpers.isPowerOfTwo32([]), false);
t.strictEquals(helpers.isPowerOfTwo32({}), false);
t.strictEquals(helpers.isPowerOfTwo32(null), false);
t.strictEquals(helpers.isPowerOfTwo32(0), false);
t.strictEquals(helpers.isPowerOfTwo32(1), true);
t.strictEquals(helpers.isPowerOfTwo32(-1), false);
var res = [];
for (let v = -65536; v <= 65536; ++v) {
if (helpers.isPowerOfTwo32(v)) {
res.push(v);
}
}
t.strictSame(res, [1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536]);
t.strictEquals(helpers.isPowerOfTwo32(16777215), false);
t.strictEquals(helpers.isPowerOfTwo32(16777216), true);
t.strictEquals(helpers.isPowerOfTwo32(16777217), false);
t.strictEquals(helpers.isPowerOfTwo32(2**31+1), false);
t.strictEquals(helpers.isPowerOfTwo32(2**31), true);
t.strictEquals(helpers.isPowerOfTwo32(2**31-1), false);
t.strictEquals(helpers.isPowerOfTwo32(2**32), true);
t.strictEquals(helpers.isPowerOfTwo32(2**32-1), false);
t.end();
});

test('nextPowerOfTwo32', t => {
var res = new Map();
t.strictEquals(helpers.nextPowerOfTwo32(), 0);
t.strictEquals(helpers.nextPowerOfTwo32([]), 0);
t.strictEquals(helpers.nextPowerOfTwo32({}), 0);
t.strictEquals(helpers.nextPowerOfTwo32(null), 0);
t.strictEquals(helpers.nextPowerOfTwo32(0), 0);
t.strictEquals(helpers.nextPowerOfTwo32(-1), 0);
t.strictEquals(helpers.nextPowerOfTwo32(1), 1);
t.strictEquals(helpers.nextPowerOfTwo32(2), 2);
t.strictEquals(helpers.nextPowerOfTwo32(3), 4);
t.strictEquals(helpers.nextPowerOfTwo32(4), 4);
for (let x = -65536; x <= 65536; ++x) {
let y = helpers.nextPowerOfTwo32(x);
res.set(y, (res.get(y)||0) + 1);
}
t.strictSame(Array.from(res.keys()), [0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536]);
t.strictSame(Array.from(res.values()), [65537,1,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768]);
t.strictEquals(helpers.nextPowerOfTwo32(2**31+1), 0);
t.strictEquals(helpers.nextPowerOfTwo32(2**31), 0x80000000);
t.strictEquals(helpers.nextPowerOfTwo32(2**31-1), 0x80000000);
t.strictEquals(helpers.nextPowerOfTwo32(2**32), 0);
t.strictEquals(helpers.nextPowerOfTwo32(2**32-1), 0);
t.end();
});

0 comments on commit 30bac22

Please sign in to comment.