diff --git a/lib/bn.js b/lib/bn.js index 5eba6eb..0854c1c 100644 --- a/lib/bn.js +++ b/lib/bn.js @@ -1915,6 +1915,9 @@ }; BN.prototype.imuln = function imuln (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; + assert(typeof num === 'number'); assert(num < 0x4000000); @@ -1935,7 +1938,7 @@ this.length++; } - return this; + return isNegNum ? this.ineg() : this; }; BN.prototype.muln = function muln (num) { @@ -2481,6 +2484,9 @@ }; BN.prototype.modrn = function modrn (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; + assert(num <= 0x3ffffff); var p = (1 << 26) % num; @@ -2489,7 +2495,7 @@ acc = (p * acc + (this.words[i] | 0)) % num; } - return acc; + return isNegNum ? -acc : acc; }; // WARNING: DEPRECATED @@ -2499,6 +2505,9 @@ // In-place division by number BN.prototype.idivn = function idivn (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; + assert(num <= 0x3ffffff); var carry = 0; @@ -2508,7 +2517,8 @@ carry = w % num; } - return this._strip(); + this._strip(); + return isNegNum ? this.ineg() : this; }; BN.prototype.divn = function divn (num) { diff --git a/test/arithmetic-test.js b/test/arithmetic-test.js index e9c47d4..67956ff 100644 --- a/test/arithmetic-test.js +++ b/test/arithmetic-test.js @@ -290,6 +290,16 @@ describe('BN.js/Arithmetic', function () { new BN(0).imuln(0x4000000); }, /^Error: Assertion failed$/); }); + + it('should negate number if number is negative', function () { + var a = new BN('dead', 16); + assert.equal(a.clone().imuln(-1).toString(16), a.clone().neg().toString(16)); + assert.equal(a.clone().muln(-1).toString(16), a.clone().neg().toString(16)); + + var b = new BN('dead', 16); + assert.equal(b.clone().imuln(-42).toString(16), b.clone().neg().muln(42).toString(16)); + assert.equal(b.clone().muln(-42).toString(16), b.clone().neg().muln(42).toString(16)); + }); }); describe('.pow()', function () { @@ -392,6 +402,7 @@ describe('BN.js/Arithmetic', function () { describe('.idivn()', function () { it('should divide numbers in-place', function () { assert.equal(new BN('10', 16).idivn(3).toString(16), '5'); + assert.equal(new BN('10', 16).idivn(-3).toString(16), '-5'); assert.equal(new BN('12', 16).idivn(3).toString(16), '6'); assert.equal(new BN('10000000000000000').idivn(3).toString(10), '3333333333333333'); @@ -530,6 +541,7 @@ describe('BN.js/Arithmetic', function () { describe('.modrn()', function () { it('should act like .mod() on small numbers', function () { assert.equal(new BN('10', 16).modrn(256).toString(16), '10'); + assert.equal(new BN('10', 16).modrn(-256).toString(16), '-10'); assert.equal(new BN('100', 16).modrn(256).toString(16), '0'); assert.equal(new BN('1001', 16).modrn(256).toString(16), '1'); assert.equal(new BN('100000000001', 16).modrn(256).toString(16), '1');