From 088e44e5e3343ef967698565678384fa474b003b Mon Sep 17 00:00:00 2001 From: Max Graey Date: Fri, 26 Nov 2021 00:37:04 +0200 Subject: [PATCH] feat: Add ctz and clz methods (#105) --- README.md | 6 ++++++ index.d.ts | 20 ++++++++++++++++++++ index.js | 47 ++++++++++++++++++++++++++++++++++++++++++++++- tests/index.js | 18 ++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 31039f1..ab168f1 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,12 @@ API * Long#**not**(): `Long`
Returns the bitwise NOT of this Long. +* Long#**countLeadingZeros**/**clz**(): `number`
+ Returns count leading zeros of this Long. + +* Long#**countTrailingZeros**/**ctz**(): `number`
+ Returns count trailing zeros of this Long. + * Long#**notEquals**/**neq**/**ne**(other: `Long | number | string`): `boolean`
Tests if this Long's value differs from the specified's. diff --git a/index.d.ts b/index.d.ts index 1f1fd03..5472d8e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -289,6 +289,26 @@ declare class Long { */ not(): Long; + /** + * Returns count leading zeros of this Long. + */ + countLeadingZeros(): number; + + /** + * Returns count leading zeros of this Long. + */ + clz(): number; + + /** + * Returns count trailing zeros of this Long. + */ + countTrailingZeros(): number; + + /** + * Returns count trailing zeros of this Long. + */ + ctz(): number; + /** * Tests if this Long's value differs from the specified's. */ diff --git a/index.js b/index.js index 2fd859b..f04775e 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,7 @@ * @license * Copyright 2009 The Closure Library Authors * Copyright 2020 Daniel Wirtz / The long.js Authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -96,6 +96,17 @@ function isLong(obj) { return (obj && obj["__isLong__"]) === true; } +/** + * @function + * @param {*} value number + * @returns {number} + * @inner + */ +function ctz32(value) { + var c = Math.clz32(value & -value); + return value ? 31 - c : c; +} + /** * Tests if the specified object is a Long. * @function @@ -1126,6 +1137,40 @@ LongPrototype.not = function not() { return fromBits(~this.low, ~this.high, this.unsigned); }; +/** + * Returns count leading zeros of this Long. + * @this {!Long} + * @returns {!number} + */ +LongPrototype.countLeadingZeros = function countLeadingZeros() { + return this.high ? Math.clz32(this.high) : Math.clz32(this.low) + 32; +}; + +/** + * Returns count leading zeros. This is an alias of {@link Long#countLeadingZeros}. + * @function + * @param {!Long} + * @returns {!number} + */ +LongPrototype.clz = LongPrototype.countLeadingZeros; + +/** + * Returns count trailing zeros of this Long. + * @this {!Long} + * @returns {!number} + */ +LongPrototype.countTrailingZeros = function countTrailingZeros() { + return this.low ? ctz32(this.low) : ctz32(this.high) + 32; +}; + +/** + * Returns count trailing zeros. This is an alias of {@link Long#countTrailingZeros}. + * @function + * @param {!Long} + * @returns {!number} + */ +LongPrototype.ctz = LongPrototype.countTrailingZeros; + /** * Returns the bitwise AND of this Long and the specified. * @this {!Long} diff --git a/tests/index.js b/tests/index.js index e5a4e4b..b935f9a 100644 --- a/tests/index.js +++ b/tests/index.js @@ -177,6 +177,7 @@ var tests = [ // BEGIN TEST CASES v = longVal.rotateLeft(32); assert.deepEqual(v, longValS); }, + function testRotateRight() { var longVal = Long.fromBits(0x01234567, 0x89ABCDEF); var longValL = Long.fromBits(0x12345678, 0x9ABCDEF0); @@ -191,6 +192,23 @@ var tests = [ // BEGIN TEST CASES // swap v = longVal.rotateRight(32); assert.deepEqual(v, longValS); + }, + + function testClzAndCtz() { + var longVal0 = Long.fromBits(0, 0); + var longVal1 = Long.fromBits(1, 0); + var longVal2 = Long.fromBits(0, 1); + var longVal3 = Long.fromBits(1, 1); + + assert.deepEqual(longVal0.clz(), 64); + assert.deepEqual(longVal1.clz(), 63); + assert.deepEqual(longVal2.clz(), 31); + assert.deepEqual(longVal3.clz(), 31); + + assert.deepEqual(longVal0.ctz(), 64); + assert.deepEqual(longVal1.ctz(), 0); + assert.deepEqual(longVal2.ctz(), 32); + assert.deepEqual(longVal3.ctz(), 0); } ]; // END TEST CASES