Skip to content

Commit

Permalink
lib: fix for negative numbers: imuln, modrn, idivn
Browse files Browse the repository at this point in the history
  • Loading branch information
fanatid authored and dcousens committed Jun 18, 2018
1 parent 8963ee9 commit e69c617
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
16 changes: 13 additions & 3 deletions lib/bn.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -1935,7 +1938,7 @@
this.length++;
}

return this;
return isNegNum ? this.ineg() : this;
};

BN.prototype.muln = function muln (num) {
Expand Down Expand Up @@ -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;

Expand All @@ -2489,7 +2495,7 @@
acc = (p * acc + (this.words[i] | 0)) % num;
}

return acc;
return isNegNum ? -acc : acc;
};

// WARNING: DEPRECATED
Expand All @@ -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;
Expand All @@ -2508,7 +2517,8 @@
carry = w % num;
}

return this._strip();
this._strip();
return isNegNum ? this.ineg() : this;
};

BN.prototype.divn = function divn (num) {
Expand Down
12 changes: 12 additions & 0 deletions test/arithmetic-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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');
Expand Down

0 comments on commit e69c617

Please sign in to comment.