From 264bf86faa7de15a595ae8ddf2a2ad7bb9fde6a6 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Wed, 13 Mar 2019 13:16:26 +0100 Subject: [PATCH 01/17] Override add to apply modulo on overflow --- index.js | 24 ++++++++++++++++++++++++ tests/index.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/index.js b/index.js index b4ebcf6..d68ee05 100644 --- a/index.js +++ b/index.js @@ -57,6 +57,26 @@ const factory = module.exports = function factory (maxWidth, minWidth = 0) { toArrayLike (type, endian) { return super.toArrayLike(type, endian, this._maxWidth / 8) } + + toBN () { + return super.clone() + } + + // Applies modulo on overflow + add (num) { + let r = super.add(num) + if (r.byteLength() * 8 > this._maxWidth) { + const f = factory(this._maxWidth, this._minWidth) + r = r.mod(f.maxInteger()) + } + return r + } + + clone () { + const r = new (factory(this._maxWidth, this._minWidth))(0) + this.copy(r) + return r + } } /** @@ -84,6 +104,10 @@ const factory = module.exports = function factory (maxWidth, minWidth = 0) { return minWidth === fixBN.minWidth && maxWidth === fixBN.maxWidth } + FixWidth.maxInteger = () => { + return new FixWidth('0x' + new BN(2).pow(new BN(maxWidth)).subn(1).toString('hex')) + } + return FixWidth } diff --git a/tests/index.js b/tests/index.js index 46a1d47..6e22e10 100644 --- a/tests/index.js +++ b/tests/index.js @@ -1,4 +1,5 @@ const tape = require('tape') +const BN = require('bn.js') const FixedBN = require('../') tape('fix length tests', t => { @@ -56,3 +57,30 @@ tape('fix length tests', t => { t.ok(threw, 'should throw error whith invalid length') t.end() }) + +tape('toBN', t => { + const a = new FixedBN.U256(9) + const b = a.toBN() + t.equal(typeof b.maxWidth, 'undefined') + t.end() +}) + +tape('ops', t => { + t.test('op should return FixedBN', st => { + const a = new FixedBN.U256(53) + const b = new FixedBN.U256(7) + const c = a.add(b) + st.equal(c.maxWidth, 256, 'add result should have same width') + st.end() + }) + + t.test('add should not overflow width', st => { + const max = new BN(2).pow(new BN(256)).subn(1) + const a = new FixedBN.U256('0x' + max.toString('hex')) + const b = new FixedBN.U256(1) + const c = a.add(b) + st.equal(c.maxWidth, 256) + st.deepEqual(c.toString('hex'), new FixedBN.U256(1).toString('hex')) + st.end() + }) +}) From 9709bb6e189abfbd25d1248fbd077b9d2363047f Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 19 Mar 2019 10:54:59 +0100 Subject: [PATCH 02/17] Mv index.js to src/index.ts --- index.js => src/index.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename index.js => src/index.ts (100%) diff --git a/index.js b/src/index.ts similarity index 100% rename from index.js rename to src/index.ts From 4693dc7eba13cc143ffeac11d4ea2d64b2e392b8 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 14:33:11 +0100 Subject: [PATCH 03/17] Add typescript-related config --- .gitignore | 1 + .nycrc | 3 +++ .prettierignore | 6 ++++++ package.json | 37 +++++++++++++++++++++++++++++-------- prettier.config.js | 1 + tsconfig.json | 4 ++++ tsconfig.prod.json | 7 +++++++ tslint.json | 3 +++ 8 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 .nycrc create mode 100644 .prettierignore create mode 100644 prettier.config.js create mode 100644 tsconfig.json create mode 100644 tsconfig.prod.json create mode 100644 tslint.json diff --git a/.gitignore b/.gitignore index d5f19d8..87807d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules package-lock.json +dist diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..b54064b --- /dev/null +++ b/.nycrc @@ -0,0 +1,3 @@ +{ + "extends": "@ethereumjs/config-nyc" +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..732234f --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +node_modules +.vscode +package.json +dist +.nyc_output +docs diff --git a/package.json b/package.json index 3acdbb0..34d31e1 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,24 @@ "name": "fixed-bn.js", "version": "0.0.2", "description": "bn.js wrapper that constrains numbers to a fixed width", - "main": "index.js", + "main": "dist/index.js", + "types": "dist/index.d.ts", "scripts": { - "coverage": "istanbul cover ./tests/index.js", - "coveralls": "npm run coverage && coveralls <coverage/lcov.info", - "lint": "standard", - "test": "tape ./tests/index.js" + "build": "ethereumjs-config-build", + "prepublishOnly": "npm run test && npm run build", + "coverage": "ethereumjs-config-coverage", + "coveralls": "ethereumjs-config-coveralls", + "format": "ethereumjs-config-format", + "format:fix": "ethereumjs-config-format-fix", + "tslint": "ethereumjs-config-tslint", + "tslint:fix": "ethereumjs-config-tslint-fix", + "tsc": "ethereumjs-config-tsc", + "lint": "ethereumjs-config-lint", + "lint:fix": "ethereumjs-config-lint-fix", + "unitTests": "ts-node ./node_modules/tape/bin/tape ./tests/*.ts", + "test": "npm run lint && npm run unitTests", + "test:fix": "npm run lint:fix && npm run unitTests", + "docs:build": "typedoc --out docs --excludePrivate --excludeExternals --mode file --readme none --theme markdown --mdEngine github src/*.ts" }, "keywords": [ "bn.js" @@ -15,10 +27,19 @@ "author": "mjbecze <mjbecze@gmail.com>", "license": "MPL-2.0", "devDependencies": { + "@ethereumjs/config-prettier": "^1.1.1", + "@ethereumjs/config-tsc": "^1.1.1", + "@ethereumjs/config-tslint": "^1.1.1", + "@types/bn.js": "^4.11.4", + "@types/node": "^11.11.3", + "@types/tape": "^4.2.33", "coveralls": "^3.0.0", - "istanbul": "^0.4.5", - "standard": "^11.0.0", - "tape": "^4.6.3" + "prettier": "^1.16.4", + "tape": "^4.6.3", + "ts-node": "^8.0.3", + "tslint": "^5.14.0", + "typescript": "^3.3.3333", + "typestrict": "^1.0.2" }, "repository": { "type": "git", diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..0f2e5b7 --- /dev/null +++ b/prettier.config.js @@ -0,0 +1 @@ +module.exports = require('@ethereumjs/config-prettier') diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e7f1cf6 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@ethereumjs/config-tsc", + "include": ["src/**/*.ts", "src/**/*.json", "tests/*.ts", "tests/*.json"] +} diff --git a/tsconfig.prod.json b/tsconfig.prod.json new file mode 100644 index 0000000..854acb1 --- /dev/null +++ b/tsconfig.prod.json @@ -0,0 +1,7 @@ +{ + "extends": "@ethereumjs/config-tsc", + "compilerOptions": { + "outDir": "./dist" + }, + "include": ["src/**/*.ts", "src/**/*.json"] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..2ba21c4 --- /dev/null +++ b/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "@ethereumjs/config-tslint" +} From 237f597033364881c113b046a1a4232edf5f0aa5 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 14:33:37 +0100 Subject: [PATCH 04/17] Add re-written source and tests --- src/factory.ts | 26 +++++ src/fixed-width.ts | 232 +++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 123 ++--------------------- tests/factory.ts | 52 ++++++++++ tests/fixed-width.ts | 156 +++++++++++++++++++++++++++++ tests/index.js | 86 ---------------- 6 files changed, 473 insertions(+), 202 deletions(-) create mode 100644 src/factory.ts create mode 100644 src/fixed-width.ts create mode 100644 tests/factory.ts create mode 100644 tests/fixed-width.ts delete mode 100644 tests/index.js diff --git a/src/factory.ts b/src/factory.ts new file mode 100644 index 0000000..12f8ecd --- /dev/null +++ b/src/factory.ts @@ -0,0 +1,26 @@ +import BN = require('bn.js') +import { FixedWidthBN, Endianness } from './fixed-width' + +export class Factory { + width: number + + constructor(width: number) { + this.width = width + } + + fromNumber(value: number): FixedWidthBN { + return new FixedWidthBN(this.width, value) + } + + fromBN(value: BN): FixedWidthBN { + return FixedWidthBN.fromBN(this.width, value) + } + + fromString(value: string, base: number = 16): FixedWidthBN { + return FixedWidthBN.fromString(this.width, value, base) + } + + fromBuffer(value: Buffer, endian: Endianness = 'be'): FixedWidthBN { + return FixedWidthBN.fromBuffer(this.width, value, endian) + } +} diff --git a/src/fixed-width.ts b/src/fixed-width.ts new file mode 100644 index 0000000..d4f6b0f --- /dev/null +++ b/src/fixed-width.ts @@ -0,0 +1,232 @@ +const assert = require('assert') +const stripHexPrefix = require('strip-hex-prefix') +const isHexPrefixed = require('is-hex-prefixed') +import BN = require('bn.js') + +export type Endianness = 'le' | 'be' + +export class FixedWidthBN { + _width: number + _bn: BN + _modulus: BN + + constructor(width: number, value: number = 0) { + assert(width >= 1, 'Invalid width') + assert(width % 8 === 0, 'Width should be divisible by 8') + this._width = width + this._bn = new BN(value) + // 2 ** width + // Used for taking modulo, e.g. after addMod, mulMod + this._modulus = new BN(2).pow(new BN(this._width)) + } + + static fromBN(width: number, value: BN): FixedWidthBN { + assert(BN.isBN(value), 'Value should be BN') + assert(value.bitLength() <= width, 'Value exceeds width') + assert(!value.isNeg(), 'Value should be positive') + + const n = new FixedWidthBN(width, 0) + n._width = width + n._bn = value + + return n + } + + static fromString(width: number, value: string, base: number = 16): FixedWidthBN { + assert(typeof value === 'string') + if (isHexPrefixed(value)) { + value = stripHexPrefix(value) + } + + const bn = new BN(value, base) + return FixedWidthBN.fromBN(width, bn) + } + + static fromBuffer(width: number, value: Buffer, endian: Endianness = 'be'): FixedWidthBN { + assert(Buffer.isBuffer(value)) + const bn = new BN(value, 10, endian) + return FixedWidthBN.fromBN(width, bn) + } + + get width(): number { + return this._width + } + + get modulus(): BN { + return this._modulus + } + + toBN(): BN { + return this._bn + } + + toBuffer(endian: Endianness = 'be'): Buffer { + return this._bn.toBuffer(endian, this._width / 8) + } + + toArray(endian: Endianness = 'be'): number[] { + return this._bn.toArray(endian, this._width / 8) + } + + toNumber(): number { + assert(this._bn.bitLength() <= 53) + return this._bn.toNumber() + } + + toString(base: number = 16): string { + // BN.toString accepts length as number of chars in output string + // which is 2 for each byte, and hence: 2 * (bits / 8) + return this._bn.toString(base, this._width / 4) + } + + clone(): FixedWidthBN { + const bn = this._bn.clone() + return FixedWidthBN.fromBN(this._width, bn) + } + + bitLength(): number { + return this._bn.bitLength() + } + + hasSameWidth(b: FixedWidthBN): boolean { + return this._width === b._width + } + + isEven(): boolean { + return this._bn.isEven() + } + + isOdd(): boolean { + return this._bn.isOdd() + } + + isZero(): boolean { + return this._bn.isZero() + } + + cmp(b: FixedWidthBN): number { + assert(this.hasSameWidth(b)) + return this._bn.cmp(b._bn) + } + + lt(b: FixedWidthBN): boolean { + assert(this.hasSameWidth(b)) + return this._bn.lt(b._bn) + } + + lte(b: FixedWidthBN): boolean { + assert(this.hasSameWidth(b)) + return this._bn.lte(b._bn) + } + + gt(b: FixedWidthBN): boolean { + assert(this.hasSameWidth(b)) + return this._bn.gt(b._bn) + } + + gte(b: FixedWidthBN): boolean { + assert(this.hasSameWidth(b)) + return this._bn.gte(b._bn) + } + + eq(b: FixedWidthBN): boolean { + assert(this.hasSameWidth(b)) + return this._bn.eq(b._bn) + } + + add(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.add(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + addMod(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.add(b._bn).mod(this.modulus) + return FixedWidthBN.fromBN(this._width, c) + } + + sub(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.sub(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + subMod(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.sub(b._bn).umod(this.modulus) + return FixedWidthBN.fromBN(this._width, c) + } + + mul(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.mul(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + mulMod(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.mul(b._bn).mod(this.modulus) + return FixedWidthBN.fromBN(this._width, c) + } + + sqr(): FixedWidthBN { + const c = this._bn.sqr() + return FixedWidthBN.fromBN(this._width, c) + } + + sqrMod(): FixedWidthBN { + const c = this._bn.sqr().mod(this.modulus) + return FixedWidthBN.fromBN(this._width, c) + } + + pow(b: FixedWidthBN): FixedWidthBN { + const c = this._bn.pow(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + powMod(b: FixedWidthBN): FixedWidthBN { + const c = this._bn.pow(b._bn).mod(this.modulus) + return FixedWidthBN.fromBN(this._width, c) + } + + div(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.div(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + divMod(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.div(b._bn).mod(this.modulus) + return FixedWidthBN.fromBN(this._width, c) + } + + or(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.or(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + and(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.and(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + xor(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.xor(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + + shln(b: number): FixedWidthBN { + const c = this._bn.shln(b) + return FixedWidthBN.fromBN(this._width, c) + } + + shrn(b: number): FixedWidthBN { + const c = this._bn.shrn(b) + return FixedWidthBN.fromBN(this._width, c) + } +} diff --git a/src/index.ts b/src/index.ts index d68ee05..65f8da6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,118 +1,9 @@ -const stripHexPrefix = require('strip-hex-prefix') -const isHexPrefixed = require('is-hex-prefixed') -const BN = require('bn.js') +import { Factory } from './factory' -/** - * A factory that produces BN.js constructors for a given width - * @param {Integer} maxWidth the max length in bits that the bn.js instance can handle - * @param {Integer} minWidth the min length in bits that the bn.js instance can handle - * @return {bn.js} returns a bn.js constuctor that that is constained to `maxWidth` and `minWidth` - */ -const factory = module.exports = function factory (maxWidth, minWidth = 0) { - class FixWidth extends BN { - constructor (value) { - // bn.js still doesn't support hex prefixes... - if ((typeof value === 'string') && isHexPrefixed(value)) { - super(stripHexPrefix(value), 16) - } else { - super(value, 10) - } +export { FixedWidthBN } from './fixed-width' +export { Factory } from './factory' - if (this.byteLength() * 8 > maxWidth) { - throw Error(`number must be less then ${maxWidth} bits`) - } - - if (this.byteLength() * 8 < minWidth) { - throw new Error(`number must be more then ${minWidth} bits`) - } - this._maxWidth = maxWidth - this._minWidth = minWidth - } - - /** - * retuns Max Width - * @returns {integer} - */ - get maxWidth () { - return this._maxWidth - } - - /** - * retuns Min Width - * @returns {integer} - */ - get minWidth () { - return this._minWidth - } - - // This assumes Uint8Array in LSB (WASM code) - toBuffer (endian = 'be') { - return super.toBuffer(endian, this._maxWidth / 8) - } - - toArray (endian) { - return super.toArray(endian, this._maxWidth / 8) - } - - toArrayLike (type, endian) { - return super.toArrayLike(type, endian, this._maxWidth / 8) - } - - toBN () { - return super.clone() - } - - // Applies modulo on overflow - add (num) { - let r = super.add(num) - if (r.byteLength() * 8 > this._maxWidth) { - const f = factory(this._maxWidth, this._minWidth) - r = r.mod(f.maxInteger()) - } - return r - } - - clone () { - const r = new (factory(this._maxWidth, this._minWidth))(0) - this.copy(r) - return r - } - } - - /** - * converts a buffer to a fixed-bn.js - * @param {string | integer} value - * @param {string} endain - */ - FixWidth.fromBuffer = (value, endian = 'be') => { - return new FixWidth(value, 16, endian) - } - - /** - * checks if a BN instance is a fixed BN instance - * @param {bn.js} bn - */ - FixWidth.isFixBN = (bn) => { - return bn.hasOwnProperty('_minWidth') && bn.hasOwnProperty('_maxWidth') - } - - /** - * checks if a fixed-bn instance is the same width as the contructor - * @param {bn.js} fixBN - */ - FixWidth.isSameWidth = (fixBN) => { - return minWidth === fixBN.minWidth && maxWidth === fixBN.maxWidth - } - - FixWidth.maxInteger = () => { - return new FixWidth('0x' + new BN(2).pow(new BN(maxWidth)).subn(1).toString('hex')) - } - - return FixWidth -} - -factory.U256 = factory(256) -factory.U160 = factory(160) -factory.U128 = factory(128) -factory.U64 = factory(64) -factory.Address = factory(160, 160) +export const U256 = new Factory(256) +export const U128 = new Factory(128) +export const U160 = new Factory(160) +export const U64 = new Factory(64) diff --git a/tests/factory.ts b/tests/factory.ts new file mode 100644 index 0000000..494a5e9 --- /dev/null +++ b/tests/factory.ts @@ -0,0 +1,52 @@ +import * as tape from 'tape' +import BN = require('bn.js') +import { U64, U256 } from '../src' + +tape('Factory types', (t: tape.Test) => { + t.test('should instantiate from number', (st: tape.Test) => { + const n = U256.fromNumber(5) + st.equal(n.width, 256) + st.equal(n.toNumber(), 5) + st.end() + }) + + t.test('should instantiate from BN', (st: tape.Test) => { + // (2 ** 64) - 1 + const hex = 'ffffffffffffffff' + const bn = new BN(hex, 16) + const n = U256.fromBN(bn) + st.equal(n.width, 256) + st.equal(n.toString(), padHexToLength(hex, 256)) + st.end() + }) + + t.test('should instantiate from string', (st: tape.Test) => { + const hex = 'ffffffffffffffff' + const n = U256.fromString(hex) + st.equal(n.toString(), padHexToLength(hex, 256)) + st.end() + }) + + t.test('should instantiate from buffer', (st: tape.Test) => { + const hex = 'ffffffffffffffff' + const buf = Buffer.from([255, 255, 255, 255, 255, 255, 255, 255]) + const n = U64.fromBuffer(buf) + st.equal(n.toString(), padHexToLength(hex, 64)) + st.end() + }) + + t.test('should throw on instantiating when value exceeds width', (st: tape.Test) => { + // (2 ** 72) - 1 + const hex = 'ffffffffffffffffff' + const buf = Buffer.from(hex, 'hex') + const bn = new BN(hex, 16) + st.throws(() => U64.fromBN(bn)) + st.throws(() => U64.fromString(hex)) + st.throws(() => U64.fromBuffer(buf)) + st.end() + }) +}) + +const padHexToLength = (hex: string, bitLength: number): string => { + return '0'.repeat(2 * (bitLength / 8 - hex.length / 2)).concat(hex) +} diff --git a/tests/fixed-width.ts b/tests/fixed-width.ts new file mode 100644 index 0000000..6a9e584 --- /dev/null +++ b/tests/fixed-width.ts @@ -0,0 +1,156 @@ +import * as tape from 'tape' +import BN = require('bn.js') +import { FixedWidthBN } from '../src' + +tape('Constructor', (t: tape.Test) => { + t.test('should instantiate from number', (st: tape.Test) => { + const n = new FixedWidthBN(256, 5) + st.equal(n.width, 256) + st.equal(n.toNumber(), 5) + st.end() + }) + + t.test('should not construct with invalid width', (st: tape.Test) => { + st.throws(() => new FixedWidthBN(255, 5)) + st.end() + }) +}) + +tape('Comparison', (t: tape.Test) => { + t.test('should compare two same width BNs', (st: tape.Test) => { + const a = new FixedWidthBN(64, 21) + const b = new FixedWidthBN(64, 20) + st.equal(a.lt(b), false) + st.equal(a.lte(b), false) + st.equal(a.gt(b), true) + st.equal(a.gte(b), true) + st.equal(a.eq(b), false) + st.end() + }) + + t.test('should throw on comparing BNs with varying width', (st: tape.Test) => { + const a = new FixedWidthBN(64, 21) + const b = new FixedWidthBN(56, 20) + st.throws(() => a.lt(b)) + st.throws(() => a.lte(b)) + st.throws(() => a.gt(b)) + st.throws(() => a.gte(b)) + st.throws(() => a.eq(b)) + st.end() + }) +}) + +tape('Add', (t: tape.Test) => { + t.test('should add two same width numbers', (st: tape.Test) => { + const a = new FixedWidthBN(64, 101) + const b = new FixedWidthBN(64, 73) + const c = a.add(b) + st.equal(c.width, 64) + st.equal(c.toNumber(), 174) + // Ensure a and b haven't changed + st.equal(a.toNumber(), 101) + st.equal(b.toNumber(), 73) + st.end() + }) + + t.test('should throw when add overflows', (st: tape.Test) => { + const a = FixedWidthBN.fromString(64, 'fffffffffffffffe') + const b = new FixedWidthBN(64, 2) + st.throws(() => a.add(b)) + st.end() + }) + + t.test('should wrap when addMod overflows', (st: tape.Test) => { + const a = FixedWidthBN.fromString(64, 'fffffffffffffffe') + const b = new FixedWidthBN(64, 3) + const c = a.addMod(b) + st.equal(c.width, 64) + st.equal(c.toNumber(), 1) + st.end() + }) +}) + +tape('Sub', (t: tape.Test) => { + t.test('should sub two same width numbers', (st: tape.Test) => { + const a = new FixedWidthBN(64, 101) + const b = new FixedWidthBN(64, 73) + const c = a.sub(b) + st.equal(c.width, 64) + st.equal(c.toNumber(), 101 - 73) + // Ensure a and b haven't changed + st.equal(a.toNumber(), 101) + st.equal(b.toNumber(), 73) + st.end() + }) + + t.test('should throw sub underflows', (st: tape.Test) => { + const a = new FixedWidthBN(64, 2) + const b = new FixedWidthBN(64, 3) + st.throws(() => a.sub(b)) + st.end() + }) + + t.test('should wrap when subMod underflows', (st: tape.Test) => { + const a = new FixedWidthBN(64, 2) + const b = new FixedWidthBN(64, 3) + const c = a.subMod(b) + st.equal(c.width, 64) + st.equal(c.toString(), 'ffffffffffffffff') + st.end() + }) +}) + +tape('Mul', (t: tape.Test) => { + t.test('should mul two same width numbers', (st: tape.Test) => { + const a = new FixedWidthBN(64, 101) + const b = new FixedWidthBN(64, 73) + const c = a.mul(b) + st.equal(c.width, 64) + st.equal(c.toNumber(), 7373) + // Ensure a and b haven't changed + st.equal(a.toNumber(), 101) + st.equal(b.toNumber(), 73) + st.end() + }) + + t.test('should throw when mul overflows', (st: tape.Test) => { + const a = FixedWidthBN.fromString(64, '8000000000000008') + const b = new FixedWidthBN(64, 2) + st.throws(() => a.mul(b)) + st.end() + }) + + t.test('should wrap when addMod overflows', (st: tape.Test) => { + const a = FixedWidthBN.fromString(64, '8000000000000008') + const b = new FixedWidthBN(64, 2) + const c = a.mulMod(b) + st.equal(c.width, 64) + st.equal(c.toString(), '0000000000000010') + st.end() + }) +}) + +tape('Sqr', (t: tape.Test) => { + t.test('should sqr number', (st: tape.Test) => { + const a = new FixedWidthBN(64, 8) + const c = a.sqr() + st.equal(c.width, 64) + st.equal(c.toNumber(), 64) + st.equal(a.toNumber(), 8) + st.end() + }) + + t.test('should throw when sqr overflows', (st: tape.Test) => { + const a = FixedWidthBN.fromString(64, '100000000') // 2 ** 32 + st.throws(() => a.sqr()) + st.end() + }) + + t.test('should wrap when sqrMod overflows', (st: tape.Test) => { + const a = FixedWidthBN.fromString(64, '100000000') + const c = a.sqrMod() + st.equal(c.width, 64) + st.true(c.isZero()) + st.end() + }) +}) diff --git a/tests/index.js b/tests/index.js deleted file mode 100644 index 6e22e10..0000000 --- a/tests/index.js +++ /dev/null @@ -1,86 +0,0 @@ -const tape = require('tape') -const BN = require('bn.js') -const FixedBN = require('../') - -tape('fix length tests', t => { - let bn = new FixedBN.U256(9879879) - let array = bn.toArray() - t.equals(array.length, 32, 'toArray should produce the correct length') - - t.ok(FixedBN.U256.isFixBN(bn), 'should detect that bn is a fixed bn') - t.ok(FixedBN.U256.isSameWidth(bn), 'should detect that bn is the same length') - - let maxWidth = bn.maxWidth - t.equals(maxWidth, 256, 'should have correct lenght') - - let minWidth = bn.minWidth - t.equals(minWidth, 0, 'should have correct lenght') - - let buffer = bn.toBuffer() - t.equals(buffer.length, 32, 'toBuffer should produce the correct length') - - let fromBN = FixedBN.U256.fromBuffer(buffer) - t.true(fromBN.eq(bn)) - - let arrayLike = bn.toArrayLike(Buffer) - t.equals(arrayLike.length, 32, 'toArrayLike should produce the correct length') - - bn = new FixedBN.U64(9879879) - array = bn.toArray() - t.equals(array.length, 8, 'toArray should produce the correct length') - - buffer = bn.toBuffer() - t.equals(buffer.length, 8, 'toBuffer should produce the correct length') - - arrayLike = bn.toArrayLike(Buffer) - t.equals(arrayLike.length, 8, 'toArrayLike should produce the correct length') - - const fromHex = new FixedBN.U64('0x5555555') - t.equals(fromHex.toString(), '89478485', 'should handle hex strings') - - let threw = false - try { - threw = new FixedBN.U64('0x55555555555555555') - } catch (e) { - threw = true - } - - t.ok(threw, 'should throw error whith invalid length') - - threw = false - try { - threw = new FixedBN.Address('0x55555555555555555') - } catch (e) { - threw = true - } - - t.ok(threw, 'should throw error whith invalid length') - t.end() -}) - -tape('toBN', t => { - const a = new FixedBN.U256(9) - const b = a.toBN() - t.equal(typeof b.maxWidth, 'undefined') - t.end() -}) - -tape('ops', t => { - t.test('op should return FixedBN', st => { - const a = new FixedBN.U256(53) - const b = new FixedBN.U256(7) - const c = a.add(b) - st.equal(c.maxWidth, 256, 'add result should have same width') - st.end() - }) - - t.test('add should not overflow width', st => { - const max = new BN(2).pow(new BN(256)).subn(1) - const a = new FixedBN.U256('0x' + max.toString('hex')) - const b = new FixedBN.U256(1) - const c = a.add(b) - st.equal(c.maxWidth, 256) - st.deepEqual(c.toString('hex'), new FixedBN.U256(1).toString('hex')) - st.end() - }) -}) From 2bf6b0b84026aa128af61ea464109a4caa92f98c Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 14:33:49 +0100 Subject: [PATCH 05/17] Fix linting errors in README.md --- README.md | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 8170190..4259245 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ -# SYNOPSIS +# SYNOPSIS + [](https://www.npmjs.org/package/fixed-bn.js) [](https://travis-ci.org/ewasm/fixed-bn.js) [](https://coveralls.io/r/ewasm/fixed-bn.js) -[](https://github.com/feross/standard) +[](https://github.com/feross/standard) a bn.js factory wrapper that constrains numbers to a fixed width # USAGE + ```javascript const FixedBN = require('fixed-bn.js') @@ -22,85 +24,88 @@ bnNum.toBuffer() // you can also create an arbitary fixed lenght bn // max bit lenght is 199 bits and min length is 2 bits -const I199 = FixedBN(199, 2) +const I199 = FixedBN(199, 2) const newBnNum = new I199(390248) ``` # API -Since this module extends [BN.js](https://github.com/indutny/bn.js/) it has the methods as it does plus a few extras. +Since this module extends [BN.js](https://github.com/indutny/bn.js/) it has the methods as it does plus a few extras. ## factory -[./index.js:11-87](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L11-L87 "Source code on GitHub") +[./index.js:11-87](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L11-L87 'Source code on GitHub') A factory that produces BN.js constructors for a given width **Parameters** -- `maxWidth` **Integer** the max length in bits that the bn.js instance can handle -- `minWidth` **Integer** the min length in bits that the bn.js instance can handle +- `maxWidth` **Integer** the max length in bits that the bn.js instance can handle +- `minWidth` **Integer** the min length in bits that the bn.js instance can handle Returns **bn.js** returns a bn.js constuctor that that is constained to `maxWidth` and `minWidth` ## builtin length + the factory has the following builtins + - `FixedBN.U64` - `FixedBN.U128` - `FixedBN.U160` - `FixedBN.U256` ## bn.js instance + Each instance has the following additional methods ## maxWidth -[./index.js:35-37](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L35-L37 "Source code on GitHub") +[./index.js:35-37](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L35-L37 'Source code on GitHub') retuns Max Width -Returns **integer** +Returns **integer** ## minWidth -[./index.js:43-45](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L43-L45 "Source code on GitHub") +[./index.js:43-45](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L43-L45 'Source code on GitHub') retuns Min Width -Returns **integer** +Returns **integer** ## fromBuffer -[./index.js:66-68](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L66-L68 "Source code on GitHub") +[./index.js:66-68](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L66-L68 'Source code on GitHub') converts a buffer to a fixed-bn.js **Parameters** -- `value` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | integer)** -- `endain` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -- `endian` (optional, default `'be'`) +- `value` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | integer)** +- `endain` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +- `endian` (optional, default `'be'`) ## isFixBN -[./index.js:74-76](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L74-L76 "Source code on GitHub") +[./index.js:74-76](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L74-L76 'Source code on GitHub') checks if a BN instance is a fixed BN instance **Parameters** -- `bn` **bn.js** +- `bn` **bn.js** ## isSameWidth -[./index.js:82-84](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L82-L84 "Source code on GitHub") +[./index.js:82-84](https://github.com/ewasm/fixedBN/blob/814e88711940f48efc341ed0c1296f7fa6cdd111/./index.js#L82-L84 'Source code on GitHub') checks if a fixed-bn instance is the same width as the contructor **Parameters** -- `fixBN` **bn.js** - +- `fixBN` **bn.js** # LICENSE -[MPL-2.0](https://tldrlegal.com/license/mozilla-public-license-2.0-(mpl-2)) + +[MPL-2.0](<https://tldrlegal.com/license/mozilla-public-license-2.0-(mpl-2)>) From 675599660490b047235d9ce9c3d39353327c4e97 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 14:38:15 +0100 Subject: [PATCH 06/17] Fix coverage script --- .gitignore | 2 ++ package.json | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 87807d9..c8c6820 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules package-lock.json dist +.nyc_output +coverage diff --git a/package.json b/package.json index 34d31e1..3a11b56 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "author": "mjbecze <mjbecze@gmail.com>", "license": "MPL-2.0", "devDependencies": { + "@ethereumjs/config-nyc": "^1.1.1", "@ethereumjs/config-prettier": "^1.1.1", "@ethereumjs/config-tsc": "^1.1.1", "@ethereumjs/config-tslint": "^1.1.1", @@ -34,6 +35,7 @@ "@types/node": "^11.11.3", "@types/tape": "^4.2.33", "coveralls": "^3.0.0", + "nyc": "^13.3.0", "prettier": "^1.16.4", "tape": "^4.6.3", "ts-node": "^8.0.3", From a9a7bc827ea83a2771487693e57deaad74f1cf8e Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 16:45:18 +0100 Subject: [PATCH 07/17] Add tests for pow and div --- tests/factory.ts | 5 +---- tests/fixed-width.ts | 39 +++++++++++++++++++++++++++++++++++++++ tests/utils.ts | 3 +++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 tests/utils.ts diff --git a/tests/factory.ts b/tests/factory.ts index 494a5e9..22aef67 100644 --- a/tests/factory.ts +++ b/tests/factory.ts @@ -1,6 +1,7 @@ import * as tape from 'tape' import BN = require('bn.js') import { U64, U256 } from '../src' +import { padHexToLength } from './utils' tape('Factory types', (t: tape.Test) => { t.test('should instantiate from number', (st: tape.Test) => { @@ -46,7 +47,3 @@ tape('Factory types', (t: tape.Test) => { st.end() }) }) - -const padHexToLength = (hex: string, bitLength: number): string => { - return '0'.repeat(2 * (bitLength / 8 - hex.length / 2)).concat(hex) -} diff --git a/tests/fixed-width.ts b/tests/fixed-width.ts index 6a9e584..5ee8492 100644 --- a/tests/fixed-width.ts +++ b/tests/fixed-width.ts @@ -1,6 +1,7 @@ import * as tape from 'tape' import BN = require('bn.js') import { FixedWidthBN } from '../src' +import { padHexToLength } from './utils' tape('Constructor', (t: tape.Test) => { t.test('should instantiate from number', (st: tape.Test) => { @@ -154,3 +155,41 @@ tape('Sqr', (t: tape.Test) => { st.end() }) }) + +tape('Pow', (t: tape.Test) => { + t.test('should pow number', (st: tape.Test) => { + const a = new FixedWidthBN(64, 8) + const b = new FixedWidthBN(64, 4) + const c = a.pow(b) + st.equal(c.width, 64) + st.equal(c.toNumber(), 4096) + st.end() + }) + + t.test('should throw when pow overflows', (st: tape.Test) => { + const a = new FixedWidthBN(64, 2) + const b = new FixedWidthBN(64, 65) + st.throws(() => a.pow(b)) + st.end() + }) + + t.test('should wrap when powMod overflows', (st: tape.Test) => { + const a = new FixedWidthBN(64, 5) + const b = new FixedWidthBN(64, 28) + const c = a.powMod(b) + st.equal(c.width, 64) + st.equal(c.toString(), padHexToLength('4fce5e3e2502611', 64)) + st.end() + }) +}) + +tape('Div', (t: tape.Test) => { + t.test('should div same width numbers', (st: tape.Test) => { + const a = new FixedWidthBN(64, 64) + const b = new FixedWidthBN(64, 4) + const c = a.div(b) + st.equal(c.width, 64) + st.equal(c.toNumber(), 16) + st.end() + }) +}) diff --git a/tests/utils.ts b/tests/utils.ts new file mode 100644 index 0000000..55fce0d --- /dev/null +++ b/tests/utils.ts @@ -0,0 +1,3 @@ +export const padHexToLength = (hex: string, bitLength: number): string => { + return '0'.repeat(2 * ((bitLength / 8) - (hex.length / 2))).concat(hex) +} From 9c47393ef0c50598f8b9a555327153201c906858 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 16:45:49 +0100 Subject: [PATCH 08/17] Add some docs --- src/factory.ts | 4 + src/fixed-width.ts | 200 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 198 insertions(+), 6 deletions(-) diff --git a/src/factory.ts b/src/factory.ts index 12f8ecd..d445211 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -1,6 +1,10 @@ import BN = require('bn.js') import { FixedWidthBN, Endianness } from './fixed-width' +/** + * Convenience class for creating FixedWidthBN values + * with the same width. + */ export class Factory { width: number diff --git a/src/fixed-width.ts b/src/fixed-width.ts index d4f6b0f..f7b3389 100644 --- a/src/fixed-width.ts +++ b/src/fixed-width.ts @@ -5,11 +5,23 @@ import BN = require('bn.js') export type Endianness = 'le' | 'be' +/** + * A [BN](https://github.com/indutny/bn.js) wrapper that limits numbers to + * a fixed width. The width should be a factor of 8, and the number is limited + * to be only unsigned currently. + */ export class FixedWidthBN { _width: number _bn: BN _modulus: BN + /** + * Instantiate a FixedWidthBN given width and a number value. + * @param width - Width of number in number of bits + * @param value - Value + * @throws if width < 1 + * @throws if width % 8 !== 0 + */ constructor(width: number, value: number = 0) { assert(width >= 1, 'Invalid width') assert(width % 8 === 0, 'Width should be divisible by 8') @@ -20,6 +32,14 @@ export class FixedWidthBN { this._modulus = new BN(2).pow(new BN(this._width)) } + /** + * Instantiates from a BN object. + * @param width - Width in number of bits + * @param value - Value + * @throws if value is not a BN + * @throws if BN value is larger than the given width + * @throws if value is negative + */ static fromBN(width: number, value: BN): FixedWidthBN { assert(BN.isBN(value), 'Value should be BN') assert(value.bitLength() <= width, 'Value exceeds width') @@ -32,6 +52,15 @@ export class FixedWidthBN { return n } + /** + * Instantiates from a string. It strips `0x` from beginning + * of strings. + * @param width - Width in number of bits + * @param value - Encoded value + * @param base - Base in which number is encoded + * @throws if value is not a string + * @throws if value is larger than the given width + */ static fromString(width: number, value: string, base: number = 16): FixedWidthBN { assert(typeof value === 'string') if (isHexPrefixed(value)) { @@ -42,12 +71,24 @@ export class FixedWidthBN { return FixedWidthBN.fromBN(width, bn) } + /** + * Instantiates from a buffer. + * @param width - Width in number of bits + * @param value - Value + * @param endian - Endianness of number + * @throws if vlaue is not a buffer + * @throws if value is larger than given width + */ static fromBuffer(width: number, value: Buffer, endian: Endianness = 'be'): FixedWidthBN { assert(Buffer.isBuffer(value)) const bn = new BN(value, 10, endian) return FixedWidthBN.fromBN(width, bn) } + /** + * Width of number in number of bits. Note that this doesn't + * necessarily equate the current bit length of the number. + */ get width(): number { return this._width } @@ -56,175 +97,322 @@ export class FixedWidthBN { return this._modulus } + /** + * Returns a normal BN from the FixedWidthBN. + */ toBN(): BN { return this._bn } + /** + * Returns number as a Buffer. + * @param endian - Endianness + */ toBuffer(endian: Endianness = 'be'): Buffer { return this._bn.toBuffer(endian, this._width / 8) } + /** + * Returns number as an array. + * @param endian - Endianness + */ toArray(endian: Endianness = 'be'): number[] { return this._bn.toArray(endian, this._width / 8) } + /** + * Returns value as a Javascript number (limited to 53 bits). + * @throws if bit length of value is larger than 53 + */ toNumber(): number { assert(this._bn.bitLength() <= 53) return this._bn.toNumber() } + /** + * Returns value encoded as a string (without `0x` prefix for base 16). + * @param base - Base for encoding (e.g. 16 for hex) + */ toString(base: number = 16): string { // BN.toString accepts length as number of chars in output string // which is 2 for each byte, and hence: 2 * (bits / 8) return this._bn.toString(base, this._width / 4) } + /** + * Clones value. + */ clone(): FixedWidthBN { const bn = this._bn.clone() return FixedWidthBN.fromBN(this._width, bn) } + /** + * Returns bit length of value. + */ bitLength(): number { return this._bn.bitLength() } + /** + * Returns true if `b` has same width (not bit length) as value. + */ hasSameWidth(b: FixedWidthBN): boolean { return this._width === b._width } + /** + * Returns true if number is even. + */ isEven(): boolean { return this._bn.isEven() } + /** + * Returns true if number is odd. + */ isOdd(): boolean { return this._bn.isOdd() } + /** + * Returns true if number is zero. + */ isZero(): boolean { return this._bn.isZero() } + /** + * Compares numbers and returns -1 (a < b), 0 (a == b) or 1 (a > b). + * @param b - Value to be compared against + * @throws if `b` has a different width + */ cmp(b: FixedWidthBN): number { assert(this.hasSameWidth(b)) return this._bn.cmp(b._bn) } + /** + * Returns true if value is less than `b`. + * @param b - Value to be compared against + * @throws if `b` has a different width + */ lt(b: FixedWidthBN): boolean { assert(this.hasSameWidth(b)) return this._bn.lt(b._bn) } + /** + * Returns true if value is less than or equal to `b`. + * @param b - Value to be compared against + * @throws if `b` has a different width + */ lte(b: FixedWidthBN): boolean { assert(this.hasSameWidth(b)) return this._bn.lte(b._bn) } + /** + * Returns true if value is greated than `b`. + * @param b - Value to be compared against + * @throws if `b` has a different width + */ gt(b: FixedWidthBN): boolean { assert(this.hasSameWidth(b)) return this._bn.gt(b._bn) } + /** + * Returns true if value is greated than or equal to `b`. + * @param b - Value to be compared against + * @throws if `b` has a different width + */ gte(b: FixedWidthBN): boolean { assert(this.hasSameWidth(b)) return this._bn.gte(b._bn) } + /** + * Returns true if value is equal to `b`. + * @param b - Value to be compared against + * @throws if `b` has a different width + */ eq(b: FixedWidthBN): boolean { assert(this.hasSameWidth(b)) return this._bn.eq(b._bn) } + /** + * Returns a new FixedWidthBN computed from adding value with `b`. + * @param b - Second operand + * @throws if `b` has a different width + * @throws if add overflows the width + */ add(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.add(b._bn) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from adding value with `b`. + * It wraps the result on overflow. + * @param b - Second operand + * @throws if `b` has a different width + */ addMod(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.add(b._bn).mod(this.modulus) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from subtracting value from `b`. + * @param b - Second operand + * @throws if `b` has a different width + * @throws if sub underflows + */ sub(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.sub(b._bn) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from subtracting value from `b`. + * It wraps the result on underflow, e.g. if width is 8, `2 - 3 == 255`. + * @param b - Second operand + * @throws if `b` has a different width + */ subMod(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.sub(b._bn).umod(this.modulus) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from multiplying value with `b`. + * @param b - Second operand + * @throws if `b` has a different width + * @throws if mul overflows + */ mul(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.mul(b._bn) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from multiplying value with `b`. + * It wraps the result on overflow. + * @param b - Second operand + * @throws if `b` has a different width + */ mulMod(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.mul(b._bn).mod(this.modulus) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from multiplying value with itself (square of value). + * @throws if sqr overflows + */ sqr(): FixedWidthBN { const c = this._bn.sqr() return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from multiplying value with itself (square of value). + * It wraps the result on overflow. + */ sqrMod(): FixedWidthBN { const c = this._bn.sqr().mod(this.modulus) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from raising value to power of `b`. + * @param b - Exponent + * @throws if `b` has a different width + * @throws if pow overflows + */ pow(b: FixedWidthBN): FixedWidthBN { const c = this._bn.pow(b._bn) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from raising value to power of `b`. + * It wraps the result on overflow. + * @param b - Exponent + * @throws if `b` has a different width + */ powMod(b: FixedWidthBN): FixedWidthBN { const c = this._bn.pow(b._bn).mod(this.modulus) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from dividing value by `b`. + * @param b - Divisor + * @throws if `b` has a different width + */ div(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.div(b._bn) return FixedWidthBN.fromBN(this._width, c) } - divMod(b: FixedWidthBN): FixedWidthBN { - assert(this.hasSameWidth(b)) - const c = this._bn.div(b._bn).mod(this.modulus) - return FixedWidthBN.fromBN(this._width, c) - } - + /** + * Returns a new FixedWidthBN computed from applying a bitwise or. + * @param b - Second operand + * @throws if `b` has a different width + */ or(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.or(b._bn) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from applying a bitwise and. + * @param b - Second operand + * @throws if `b` has a different width + */ and(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.and(b._bn) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from applying a bitwise xor. + * @param b - Second operand + * @throws if `b` has a different width + */ xor(b: FixedWidthBN): FixedWidthBN { assert(this.hasSameWidth(b)) const c = this._bn.xor(b._bn) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from shifting value to left + * by a number of bits. + * @param b - Number of bits to shift + */ shln(b: number): FixedWidthBN { const c = this._bn.shln(b) return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from shifting value to right + * by a number of bits. + * @param b - Number of bits to shift + */ shrn(b: number): FixedWidthBN { const c = this._bn.shrn(b) return FixedWidthBN.fromBN(this._width, c) From ae231a68bf2ad807f10071d24d11257938540f6d Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 16:51:29 +0100 Subject: [PATCH 09/17] Generate md docs --- docs/README.md | 74 +++ docs/classes/factory.md | 134 ++++++ docs/classes/fixedwidthbn.md | 852 +++++++++++++++++++++++++++++++++++ package.json | 4 +- 4 files changed, 1063 insertions(+), 1 deletion(-) create mode 100644 docs/README.md create mode 100644 docs/classes/factory.md create mode 100644 docs/classes/fixedwidthbn.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..e13e574 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,74 @@ + +# fixed-bn.js + +## Index + +### Classes + +* [Factory](classes/factory.md) +* [FixedWidthBN](classes/fixedwidthbn.md) + +### Type aliases + +* [Endianness](#endianness) + +### Variables + +* [U128](#u128) +* [U160](#u160) +* [U256](#u256) +* [U64](#u64) + +--- + +## Type aliases + +<a id="endianness"></a> + +### Endianness + +**Ƭ Endianness**: *"le" \| "be"* + +*Defined in [fixed-width.ts:6](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L6)* + +___ + +## Variables + +<a id="u128"></a> + +### `<Const>` U128 + +**● U128**: *[Factory](classes/factory.md)* = new Factory(128) + +*Defined in [index.ts:7](https://github.com/ewasm/fixed-bn.js/blob/master/src/index.ts#L7)* + +___ +<a id="u160"></a> + +### `<Const>` U160 + +**● U160**: *[Factory](classes/factory.md)* = new Factory(160) + +*Defined in [index.ts:8](https://github.com/ewasm/fixed-bn.js/blob/master/src/index.ts#L8)* + +___ +<a id="u256"></a> + +### `<Const>` U256 + +**● U256**: *[Factory](classes/factory.md)* = new Factory(256) + +*Defined in [index.ts:6](https://github.com/ewasm/fixed-bn.js/blob/master/src/index.ts#L6)* + +___ +<a id="u64"></a> + +### `<Const>` U64 + +**● U64**: *[Factory](classes/factory.md)* = new Factory(64) + +*Defined in [index.ts:9](https://github.com/ewasm/fixed-bn.js/blob/master/src/index.ts#L9)* + +___ + diff --git a/docs/classes/factory.md b/docs/classes/factory.md new file mode 100644 index 0000000..871bdf9 --- /dev/null +++ b/docs/classes/factory.md @@ -0,0 +1,134 @@ +[fixed-bn.js](../README.md) > [Factory](../classes/factory.md) + +# Class: Factory + +Convenience class for creating FixedWidthBN values with the same width. + +## Hierarchy + +**Factory** + +## Index + +### Constructors + +* [constructor](factory.md#constructor) + +### Properties + +* [width](factory.md#width) + +### Methods + +* [fromBN](factory.md#frombn) +* [fromBuffer](factory.md#frombuffer) +* [fromNumber](factory.md#fromnumber) +* [fromString](factory.md#fromstring) + +--- + +## Constructors + +<a id="constructor"></a> + +### constructor + +⊕ **new Factory**(width: *`number`*): [Factory](factory.md) + +*Defined in [factory.ts:9](https://github.com/ewasm/fixed-bn.js/blob/master/src/factory.ts#L9)* + +**Parameters:** + +| Name | Type | +| ------ | ------ | +| width | `number` | + +**Returns:** [Factory](factory.md) + +___ + +## Properties + +<a id="width"></a> + +### width + +**● width**: *`number`* + +*Defined in [factory.ts:9](https://github.com/ewasm/fixed-bn.js/blob/master/src/factory.ts#L9)* + +___ + +## Methods + +<a id="frombn"></a> + +### fromBN + +▸ **fromBN**(value: *`BN`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [factory.ts:19](https://github.com/ewasm/fixed-bn.js/blob/master/src/factory.ts#L19)* + +**Parameters:** + +| Name | Type | +| ------ | ------ | +| value | `BN` | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="frombuffer"></a> + +### fromBuffer + +▸ **fromBuffer**(value: *`Buffer`*, endian?: *[Endianness](../#endianness)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [factory.ts:27](https://github.com/ewasm/fixed-bn.js/blob/master/src/factory.ts#L27)* + +**Parameters:** + +| Name | Type | Default value | +| ------ | ------ | ------ | +| value | `Buffer` | - | +| `Default value` endian | [Endianness](../#endianness) | "be" | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="fromnumber"></a> + +### fromNumber + +▸ **fromNumber**(value: *`number`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [factory.ts:15](https://github.com/ewasm/fixed-bn.js/blob/master/src/factory.ts#L15)* + +**Parameters:** + +| Name | Type | +| ------ | ------ | +| value | `number` | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="fromstring"></a> + +### fromString + +▸ **fromString**(value: *`string`*, base?: *`number`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [factory.ts:23](https://github.com/ewasm/fixed-bn.js/blob/master/src/factory.ts#L23)* + +**Parameters:** + +| Name | Type | Default value | +| ------ | ------ | ------ | +| value | `string` | - | +| `Default value` base | `number` | 16 | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ + diff --git a/docs/classes/fixedwidthbn.md b/docs/classes/fixedwidthbn.md new file mode 100644 index 0000000..7cb8c30 --- /dev/null +++ b/docs/classes/fixedwidthbn.md @@ -0,0 +1,852 @@ +[fixed-bn.js](../README.md) > [FixedWidthBN](../classes/fixedwidthbn.md) + +# Class: FixedWidthBN + +A [BN](https://github.com/indutny/bn.js) wrapper that limits numbers to a fixed width. The width should be a factor of 8, and the number is limited to be only unsigned currently. + +## Hierarchy + +**FixedWidthBN** + +## Index + +### Constructors + +* [constructor](fixedwidthbn.md#constructor) + +### Properties + +* [_bn](fixedwidthbn.md#_bn) +* [_modulus](fixedwidthbn.md#_modulus) +* [_width](fixedwidthbn.md#_width) + +### Accessors + +* [modulus](fixedwidthbn.md#modulus) +* [width](fixedwidthbn.md#width) + +### Methods + +* [add](fixedwidthbn.md#add) +* [addMod](fixedwidthbn.md#addmod) +* [and](fixedwidthbn.md#and) +* [bitLength](fixedwidthbn.md#bitlength) +* [clone](fixedwidthbn.md#clone) +* [cmp](fixedwidthbn.md#cmp) +* [div](fixedwidthbn.md#div) +* [eq](fixedwidthbn.md#eq) +* [gt](fixedwidthbn.md#gt) +* [gte](fixedwidthbn.md#gte) +* [hasSameWidth](fixedwidthbn.md#hassamewidth) +* [isEven](fixedwidthbn.md#iseven) +* [isOdd](fixedwidthbn.md#isodd) +* [isZero](fixedwidthbn.md#iszero) +* [lt](fixedwidthbn.md#lt) +* [lte](fixedwidthbn.md#lte) +* [mul](fixedwidthbn.md#mul) +* [mulMod](fixedwidthbn.md#mulmod) +* [or](fixedwidthbn.md#or) +* [pow](fixedwidthbn.md#pow) +* [powMod](fixedwidthbn.md#powmod) +* [shln](fixedwidthbn.md#shln) +* [shrn](fixedwidthbn.md#shrn) +* [sqr](fixedwidthbn.md#sqr) +* [sqrMod](fixedwidthbn.md#sqrmod) +* [sub](fixedwidthbn.md#sub) +* [subMod](fixedwidthbn.md#submod) +* [toArray](fixedwidthbn.md#toarray) +* [toBN](fixedwidthbn.md#tobn) +* [toBuffer](fixedwidthbn.md#tobuffer) +* [toNumber](fixedwidthbn.md#tonumber) +* [toString](fixedwidthbn.md#tostring) +* [xor](fixedwidthbn.md#xor) +* [fromBN](fixedwidthbn.md#frombn) +* [fromBuffer](fixedwidthbn.md#frombuffer) +* [fromString](fixedwidthbn.md#fromstring) + +--- + +## Constructors + +<a id="constructor"></a> + +### constructor + +⊕ **new FixedWidthBN**(width: *`number`*, value?: *`number`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:16](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L16)* + +Instantiate a FixedWidthBN given width and a number value. + +*__throws__*: if width < 1 + +*__throws__*: if width % 8 !== 0 + +**Parameters:** + +| Name | Type | Default value | Description | +| ------ | ------ | ------ | ------ | +| width | `number` | - | Width of number in number of bits | +| `Default value` value | `number` | 0 | Value | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ + +## Properties + +<a id="_bn"></a> + +### _bn + +**● _bn**: *`BN`* + +*Defined in [fixed-width.ts:15](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L15)* + +___ +<a id="_modulus"></a> + +### _modulus + +**● _modulus**: *`BN`* + +*Defined in [fixed-width.ts:16](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L16)* + +___ +<a id="_width"></a> + +### _width + +**● _width**: *`number`* + +*Defined in [fixed-width.ts:14](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L14)* + +___ + +## Accessors + +<a id="modulus"></a> + +### modulus + +**get modulus**(): `BN` + +*Defined in [fixed-width.ts:96](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L96)* + +**Returns:** `BN` + +___ +<a id="width"></a> + +### width + +**get width**(): `number` + +*Defined in [fixed-width.ts:92](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L92)* + +Width of number in number of bits. Note that this doesn't necessarily equate the current bit length of the number. + +**Returns:** `number` + +___ + +## Methods + +<a id="add"></a> + +### add + +▸ **add**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:251](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L251)* + +Returns a new FixedWidthBN computed from adding value with `b`. + +*__throws__*: if `b` has a different width + +*__throws__*: if add overflows the width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="addmod"></a> + +### addMod + +▸ **addMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:263](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L263)* + +Returns a new FixedWidthBN computed from adding value with `b`. It wraps the result on overflow. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="and"></a> + +### and + +▸ **and**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:384](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L384)* + +Returns a new FixedWidthBN computed from applying a bitwise and. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="bitlength"></a> + +### bitLength + +▸ **bitLength**(): `number` + +*Defined in [fixed-width.ts:153](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L153)* + +Returns bit length of value. + +**Returns:** `number` + +___ +<a id="clone"></a> + +### clone + +▸ **clone**(): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:145](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L145)* + +Clones value. + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="cmp"></a> + +### cmp + +▸ **cmp**(b: *[FixedWidthBN](fixedwidthbn.md)*): `number` + +*Defined in [fixed-width.ts:190](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L190)* + +Compares numbers and returns -1 (a < b), 0 (a == b) or 1 (a > b). + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Value to be compared against | + +**Returns:** `number` + +___ +<a id="div"></a> + +### div + +▸ **div**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:362](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L362)* + +Returns a new FixedWidthBN computed from dividing value by `b`. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Divisor | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="eq"></a> + +### eq + +▸ **eq**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` + +*Defined in [fixed-width.ts:240](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L240)* + +Returns true if value is equal to `b`. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Value to be compared against | + +**Returns:** `boolean` + +___ +<a id="gt"></a> + +### gt + +▸ **gt**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` + +*Defined in [fixed-width.ts:220](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L220)* + +Returns true if value is greated than `b`. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Value to be compared against | + +**Returns:** `boolean` + +___ +<a id="gte"></a> + +### gte + +▸ **gte**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` + +*Defined in [fixed-width.ts:230](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L230)* + +Returns true if value is greated than or equal to `b`. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Value to be compared against | + +**Returns:** `boolean` + +___ +<a id="hassamewidth"></a> + +### hasSameWidth + +▸ **hasSameWidth**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` + +*Defined in [fixed-width.ts:160](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L160)* + +Returns true if `b` has same width (not bit length) as value. + +**Parameters:** + +| Name | Type | +| ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | + +**Returns:** `boolean` + +___ +<a id="iseven"></a> + +### isEven + +▸ **isEven**(): `boolean` + +*Defined in [fixed-width.ts:167](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L167)* + +Returns true if number is even. + +**Returns:** `boolean` + +___ +<a id="isodd"></a> + +### isOdd + +▸ **isOdd**(): `boolean` + +*Defined in [fixed-width.ts:174](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L174)* + +Returns true if number is odd. + +**Returns:** `boolean` + +___ +<a id="iszero"></a> + +### isZero + +▸ **isZero**(): `boolean` + +*Defined in [fixed-width.ts:181](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L181)* + +Returns true if number is zero. + +**Returns:** `boolean` + +___ +<a id="lt"></a> + +### lt + +▸ **lt**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` + +*Defined in [fixed-width.ts:200](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L200)* + +Returns true if value is less than `b`. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Value to be compared against | + +**Returns:** `boolean` + +___ +<a id="lte"></a> + +### lte + +▸ **lte**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` + +*Defined in [fixed-width.ts:210](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L210)* + +Returns true if value is less than or equal to `b`. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Value to be compared against | + +**Returns:** `boolean` + +___ +<a id="mul"></a> + +### mul + +▸ **mul**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:299](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L299)* + +Returns a new FixedWidthBN computed from multiplying value with `b`. + +*__throws__*: if `b` has a different width + +*__throws__*: if mul overflows + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="mulmod"></a> + +### mulMod + +▸ **mulMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:311](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L311)* + +Returns a new FixedWidthBN computed from multiplying value with `b`. It wraps the result on overflow. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="or"></a> + +### or + +▸ **or**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:373](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L373)* + +Returns a new FixedWidthBN computed from applying a bitwise or. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="pow"></a> + +### pow + +▸ **pow**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:341](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L341)* + +Returns a new FixedWidthBN computed from raising value to power of `b`. + +*__throws__*: if `b` has a different width + +*__throws__*: if pow overflows + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Exponent | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="powmod"></a> + +### powMod + +▸ **powMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:352](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L352)* + +Returns a new FixedWidthBN computed from raising value to power of `b`. It wraps the result on overflow. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Exponent | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="shln"></a> + +### shln + +▸ **shln**(b: *`number`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:406](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L406)* + +Returns a new FixedWidthBN computed from shifting value to left by a number of bits. + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | `number` | Number of bits to shift | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="shrn"></a> + +### shrn + +▸ **shrn**(b: *`number`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:416](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L416)* + +Returns a new FixedWidthBN computed from shifting value to right by a number of bits. + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | `number` | Number of bits to shift | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="sqr"></a> + +### sqr + +▸ **sqr**(): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:321](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L321)* + +Returns a new FixedWidthBN computed from multiplying value with itself (square of value). + +*__throws__*: if sqr overflows + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="sqrmod"></a> + +### sqrMod + +▸ **sqrMod**(): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:330](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L330)* + +Returns a new FixedWidthBN computed from multiplying value with itself (square of value). It wraps the result on overflow. + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="sub"></a> + +### sub + +▸ **sub**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:275](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L275)* + +Returns a new FixedWidthBN computed from subtracting value from `b`. + +*__throws__*: if `b` has a different width + +*__throws__*: if sub underflows + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="submod"></a> + +### subMod + +▸ **subMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:287](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L287)* + +Returns a new FixedWidthBN computed from subtracting value from `b`. It wraps the result on underflow, e.g. if width is 8, `2 - 3 == 255`. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="toarray"></a> + +### toArray + +▸ **toArray**(endian?: *[Endianness](../#endianness)*): `number`[] + +*Defined in [fixed-width.ts:119](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L119)* + +Returns number as an array. + +**Parameters:** + +| Name | Type | Default value | Description | +| ------ | ------ | ------ | ------ | +| `Default value` endian | [Endianness](../#endianness) | "be" | Endianness | + +**Returns:** `number`[] + +___ +<a id="tobn"></a> + +### toBN + +▸ **toBN**(): `BN` + +*Defined in [fixed-width.ts:103](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L103)* + +Returns a normal BN from the FixedWidthBN. + +**Returns:** `BN` + +___ +<a id="tobuffer"></a> + +### toBuffer + +▸ **toBuffer**(endian?: *[Endianness](../#endianness)*): `Buffer` + +*Defined in [fixed-width.ts:111](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L111)* + +Returns number as a Buffer. + +**Parameters:** + +| Name | Type | Default value | Description | +| ------ | ------ | ------ | ------ | +| `Default value` endian | [Endianness](../#endianness) | "be" | Endianness | + +**Returns:** `Buffer` + +___ +<a id="tonumber"></a> + +### toNumber + +▸ **toNumber**(): `number` + +*Defined in [fixed-width.ts:127](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L127)* + +Returns value as a Javascript number (limited to 53 bits). + +*__throws__*: if bit length of value is larger than 53 + +**Returns:** `number` + +___ +<a id="tostring"></a> + +### toString + +▸ **toString**(base?: *`number`*): `string` + +*Defined in [fixed-width.ts:136](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L136)* + +Returns value encoded as a string (without `0x` prefix for base 16). + +**Parameters:** + +| Name | Type | Default value | Description | +| ------ | ------ | ------ | ------ | +| `Default value` base | `number` | 16 | Base for encoding (e.g. 16 for hex) | + +**Returns:** `string` + +___ +<a id="xor"></a> + +### xor + +▸ **xor**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:395](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L395)* + +Returns a new FixedWidthBN computed from applying a bitwise xor. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Second operand | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="frombn"></a> + +### `<Static>` fromBN + +▸ **fromBN**(width: *`number`*, value: *`BN`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:43](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L43)* + +Instantiates from a BN object. + +*__throws__*: if value is not a BN + +*__throws__*: if BN value is larger than the given width + +*__throws__*: if value is negative + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| width | `number` | Width in number of bits | +| value | `BN` | Value | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="frombuffer"></a> + +### `<Static>` fromBuffer + +▸ **fromBuffer**(width: *`number`*, value: *`Buffer`*, endian?: *[Endianness](../#endianness)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:82](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L82)* + +Instantiates from a buffer. + +*__throws__*: if vlaue is not a buffer + +*__throws__*: if value is larger than given width + +**Parameters:** + +| Name | Type | Default value | Description | +| ------ | ------ | ------ | ------ | +| width | `number` | - | Width in number of bits | +| value | `Buffer` | - | Value | +| `Default value` endian | [Endianness](../#endianness) | "be" | Endianness of number | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ +<a id="fromstring"></a> + +### `<Static>` fromString + +▸ **fromString**(width: *`number`*, value: *`string`*, base?: *`number`*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:64](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L64)* + +Instantiates from a string. It strips `0x` from beginning of strings. + +*__throws__*: if value is not a string + +*__throws__*: if value is larger than the given width + +**Parameters:** + +| Name | Type | Default value | Description | +| ------ | ------ | ------ | ------ | +| width | `number` | - | Width in number of bits | +| value | `string` | - | Encoded value | +| `Default value` base | `number` | 16 | Base in which number is encoded | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + +___ + diff --git a/package.json b/package.json index 3a11b56..3a11737 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "unitTests": "ts-node ./node_modules/tape/bin/tape ./tests/*.ts", "test": "npm run lint && npm run unitTests", "test:fix": "npm run lint:fix && npm run unitTests", - "docs:build": "typedoc --out docs --excludePrivate --excludeExternals --mode file --readme none --theme markdown --mdEngine github src/*.ts" + "docs:build": "typedoc --out docs --mode file --readme none --theme markdown --mdEngine github --gitRevision master --excludeNotExported src/*.ts" }, "keywords": [ "bn.js" @@ -40,6 +40,8 @@ "tape": "^4.6.3", "ts-node": "^8.0.3", "tslint": "^5.14.0", + "typedoc": "^0.14.2", + "typedoc-plugin-markdown": "^1.1.27", "typescript": "^3.3.3333", "typestrict": "^1.0.2" }, From 221862672e57f751a9d11fe6b3a932fba9b01ea4 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Mon, 25 Mar 2019 16:55:51 +0100 Subject: [PATCH 10/17] Fix linting error --- tests/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils.ts b/tests/utils.ts index 55fce0d..7c9d165 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -1,3 +1,3 @@ export const padHexToLength = (hex: string, bitLength: number): string => { - return '0'.repeat(2 * ((bitLength / 8) - (hex.length / 2))).concat(hex) + return '0'.repeat(2 * (bitLength / 8 - hex.length / 2)).concat(hex) } From c4cd685a755ceef9128503488982e85db63907dd Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 26 Mar 2019 10:57:39 +0100 Subject: [PATCH 11/17] Fix toString for base 2, fix shl shr, add not --- src/fixed-width.ts | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/fixed-width.ts b/src/fixed-width.ts index f7b3389..a2b183d 100644 --- a/src/fixed-width.ts +++ b/src/fixed-width.ts @@ -132,11 +132,21 @@ export class FixedWidthBN { /** * Returns value encoded as a string (without `0x` prefix for base 16). * @param base - Base for encoding (e.g. 16 for hex) + * @param pad - Pad output string to width (only for bases 2 and 16) */ - toString(base: number = 16): string { - // BN.toString accepts length as number of chars in output string - // which is 2 for each byte, and hence: 2 * (bits / 8) - return this._bn.toString(base, this._width / 4) + toString(base: number = 16, pad: boolean = true): string { + if (pad && (base !== 2 && base !== 16)) { + throw new Error('Padding string only supported for bases divisible by 2') + } + + if (pad) { + // BN.toString accepts length as number of chars in output string + // which, e.g. for base 16 is 2 for each byte, and hence: 2 * (bits / 8) + const length = base === 16 ? this._width / 4 : this._width + return this._bn.toString(base, length) + } else { + return this._bn.toString(base) + } } /** @@ -400,21 +410,29 @@ export class FixedWidthBN { /** * Returns a new FixedWidthBN computed from shifting value to left - * by a number of bits. + * by a number of bits. It discards bits that are shifted out of width. * @param b - Number of bits to shift */ - shln(b: number): FixedWidthBN { + shl(b: number): FixedWidthBN { const c = this._bn.shln(b) return FixedWidthBN.fromBN(this._width, c) } /** * Returns a new FixedWidthBN computed from shifting value to right - * by a number of bits. + * by a number of bits. It discards bits that are shifted out of width. * @param b - Number of bits to shift */ - shrn(b: number): FixedWidthBN { - const c = this._bn.shrn(b) + shr(b: number): FixedWidthBN { + const c = this._bn.shrn(b).mod(this.modulus) + return FixedWidthBN.fromBN(this._width, c) + } + + /** + * Returns a new FixedWidthBN computed from bitwise negation of value. + */ + not(): FixedWidthBN { + const c = this._bn.notn(this._width) return FixedWidthBN.fromBN(this._width, c) } } From a19670553d4a88d53566c3b9214b22d3f935edbd Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 26 Mar 2019 10:57:52 +0100 Subject: [PATCH 12/17] Add tests for bitwise ops --- tests/fixed-width.ts | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/fixed-width.ts b/tests/fixed-width.ts index 5ee8492..40fed9a 100644 --- a/tests/fixed-width.ts +++ b/tests/fixed-width.ts @@ -193,3 +193,54 @@ tape('Div', (t: tape.Test) => { st.end() }) }) + +tape('Or', (t: tape.Test) => { + const a = FixedWidthBN.fromString(8, '11001100', 2) + const b = FixedWidthBN.fromString(8, '10110101', 2) + const c = a.or(b) + t.equal(c.toString(2), '11111101') + t.end() +}) + +tape('And', (t: tape.Test) => { + const a = FixedWidthBN.fromString(8, '11001100', 2) + const b = FixedWidthBN.fromString(8, '10110101', 2) + const c = a.and(b) + t.equal(c.toString(2), '10000100') + t.end() +}) + +tape('Xor', (t: tape.Test) => { + const a = FixedWidthBN.fromString(8, '11001100', 2) + const b = FixedWidthBN.fromString(8, '10110101', 2) + const c = a.xor(b) + t.equal(c.toString(2), '01111001') + t.end() +}) + +tape('Not', (t: tape.Test) => { + const a = FixedWidthBN.fromString(8, '11001100', 2) + const c = a.not() + t.equal(c.toString(2), '00110011') + t.end() +}) + +tape('Shl', (t: tape.Test) => { + const a = FixedWidthBN.fromString(8, '11001100', 2) + const c = a.shl(3) + t.equal(c.toString(2), '01100000') + t.end() +}) + +tape('Shr', (t: tape.Test) => { + const a = FixedWidthBN.fromString(8, '11001100', 2) + const c = a.shr(3) + t.equal(c.toString(2), '00011001') + t.end() +}) + +tape('ToString', (t: tape.Test) => { + const a = FixedWidthBN.fromString(16, '00110011', 2) + t.equal(a.toString(2), '0000000000110011') + t.end() +}) From e423594590dc1233344570f4675a3049ffff2cda Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 26 Mar 2019 11:04:04 +0100 Subject: [PATCH 13/17] Add mod op, refix shl --- src/fixed-width.ts | 13 ++++++++++++- tests/fixed-width.ts | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/fixed-width.ts b/src/fixed-width.ts index a2b183d..78bd3bd 100644 --- a/src/fixed-width.ts +++ b/src/fixed-width.ts @@ -375,6 +375,17 @@ export class FixedWidthBN { return FixedWidthBN.fromBN(this._width, c) } + /** + * Returns a new FixedWidthBN computed from value mod b. + * @param b - Modulus + * @throws if `b` has a different width + */ + mod(b: FixedWidthBN): FixedWidthBN { + assert(this.hasSameWidth(b)) + const c = this._bn.mod(b._bn) + return FixedWidthBN.fromBN(this._width, c) + } + /** * Returns a new FixedWidthBN computed from applying a bitwise or. * @param b - Second operand @@ -414,7 +425,7 @@ export class FixedWidthBN { * @param b - Number of bits to shift */ shl(b: number): FixedWidthBN { - const c = this._bn.shln(b) + const c = this._bn.shln(b).mod(this.modulus) return FixedWidthBN.fromBN(this._width, c) } diff --git a/tests/fixed-width.ts b/tests/fixed-width.ts index 40fed9a..e344c6b 100644 --- a/tests/fixed-width.ts +++ b/tests/fixed-width.ts @@ -194,6 +194,14 @@ tape('Div', (t: tape.Test) => { }) }) +tape('Mod', (t: tape.Test) => { + const a = new FixedWidthBN(8, 17) + const b = new FixedWidthBN(8, 4) + const c = a.mod(b) + t.equal(c.toNumber(), 1) + t.end() +}) + tape('Or', (t: tape.Test) => { const a = FixedWidthBN.fromString(8, '11001100', 2) const b = FixedWidthBN.fromString(8, '10110101', 2) From 0ce88cb49e2d3b3fc5808325021fd2dc295618cf Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 26 Mar 2019 11:06:32 +0100 Subject: [PATCH 14/17] Generate docs --- docs/classes/fixedwidthbn.md | 117 +++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 40 deletions(-) diff --git a/docs/classes/fixedwidthbn.md b/docs/classes/fixedwidthbn.md index 7cb8c30..090c8d2 100644 --- a/docs/classes/fixedwidthbn.md +++ b/docs/classes/fixedwidthbn.md @@ -43,13 +43,15 @@ A [BN](https://github.com/indutny/bn.js) wrapper that limits numbers to a fixed * [isZero](fixedwidthbn.md#iszero) * [lt](fixedwidthbn.md#lt) * [lte](fixedwidthbn.md#lte) +* [mod](fixedwidthbn.md#mod) * [mul](fixedwidthbn.md#mul) * [mulMod](fixedwidthbn.md#mulmod) +* [not](fixedwidthbn.md#not) * [or](fixedwidthbn.md#or) * [pow](fixedwidthbn.md#pow) * [powMod](fixedwidthbn.md#powmod) -* [shln](fixedwidthbn.md#shln) -* [shrn](fixedwidthbn.md#shrn) +* [shl](fixedwidthbn.md#shl) +* [shr](fixedwidthbn.md#shr) * [sqr](fixedwidthbn.md#sqr) * [sqrMod](fixedwidthbn.md#sqrmod) * [sub](fixedwidthbn.md#sub) @@ -158,7 +160,7 @@ ___ ▸ **add**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:251](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L251)* +*Defined in [fixed-width.ts:261](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L261)* Returns a new FixedWidthBN computed from adding value with `b`. @@ -181,7 +183,7 @@ ___ ▸ **addMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:263](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L263)* +*Defined in [fixed-width.ts:273](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L273)* Returns a new FixedWidthBN computed from adding value with `b`. It wraps the result on overflow. @@ -202,7 +204,7 @@ ___ ▸ **and**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:384](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L384)* +*Defined in [fixed-width.ts:405](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L405)* Returns a new FixedWidthBN computed from applying a bitwise and. @@ -223,7 +225,7 @@ ___ ▸ **bitLength**(): `number` -*Defined in [fixed-width.ts:153](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L153)* +*Defined in [fixed-width.ts:163](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L163)* Returns bit length of value. @@ -236,7 +238,7 @@ ___ ▸ **clone**(): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:145](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L145)* +*Defined in [fixed-width.ts:155](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L155)* Clones value. @@ -249,7 +251,7 @@ ___ ▸ **cmp**(b: *[FixedWidthBN](fixedwidthbn.md)*): `number` -*Defined in [fixed-width.ts:190](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L190)* +*Defined in [fixed-width.ts:200](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L200)* Compares numbers and returns -1 (a < b), 0 (a == b) or 1 (a > b). @@ -270,7 +272,7 @@ ___ ▸ **div**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:362](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L362)* +*Defined in [fixed-width.ts:372](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L372)* Returns a new FixedWidthBN computed from dividing value by `b`. @@ -291,7 +293,7 @@ ___ ▸ **eq**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` -*Defined in [fixed-width.ts:240](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L240)* +*Defined in [fixed-width.ts:250](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L250)* Returns true if value is equal to `b`. @@ -312,7 +314,7 @@ ___ ▸ **gt**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` -*Defined in [fixed-width.ts:220](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L220)* +*Defined in [fixed-width.ts:230](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L230)* Returns true if value is greated than `b`. @@ -333,7 +335,7 @@ ___ ▸ **gte**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` -*Defined in [fixed-width.ts:230](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L230)* +*Defined in [fixed-width.ts:240](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L240)* Returns true if value is greated than or equal to `b`. @@ -354,7 +356,7 @@ ___ ▸ **hasSameWidth**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` -*Defined in [fixed-width.ts:160](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L160)* +*Defined in [fixed-width.ts:170](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L170)* Returns true if `b` has same width (not bit length) as value. @@ -373,7 +375,7 @@ ___ ▸ **isEven**(): `boolean` -*Defined in [fixed-width.ts:167](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L167)* +*Defined in [fixed-width.ts:177](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L177)* Returns true if number is even. @@ -386,7 +388,7 @@ ___ ▸ **isOdd**(): `boolean` -*Defined in [fixed-width.ts:174](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L174)* +*Defined in [fixed-width.ts:184](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L184)* Returns true if number is odd. @@ -399,7 +401,7 @@ ___ ▸ **isZero**(): `boolean` -*Defined in [fixed-width.ts:181](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L181)* +*Defined in [fixed-width.ts:191](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L191)* Returns true if number is zero. @@ -412,7 +414,7 @@ ___ ▸ **lt**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` -*Defined in [fixed-width.ts:200](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L200)* +*Defined in [fixed-width.ts:210](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L210)* Returns true if value is less than `b`. @@ -433,7 +435,7 @@ ___ ▸ **lte**(b: *[FixedWidthBN](fixedwidthbn.md)*): `boolean` -*Defined in [fixed-width.ts:210](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L210)* +*Defined in [fixed-width.ts:220](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L220)* Returns true if value is less than or equal to `b`. @@ -447,6 +449,27 @@ Returns true if value is less than or equal to `b`. **Returns:** `boolean` +___ +<a id="mod"></a> + +### mod + +▸ **mod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:383](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L383)* + +Returns a new FixedWidthBN computed from value mod b. + +*__throws__*: if `b` has a different width + +**Parameters:** + +| Name | Type | Description | +| ------ | ------ | ------ | +| b | [FixedWidthBN](fixedwidthbn.md) | Modulus | + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + ___ <a id="mul"></a> @@ -454,7 +477,7 @@ ___ ▸ **mul**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:299](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L299)* +*Defined in [fixed-width.ts:309](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L309)* Returns a new FixedWidthBN computed from multiplying value with `b`. @@ -477,7 +500,7 @@ ___ ▸ **mulMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:311](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L311)* +*Defined in [fixed-width.ts:321](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L321)* Returns a new FixedWidthBN computed from multiplying value with `b`. It wraps the result on overflow. @@ -491,6 +514,19 @@ Returns a new FixedWidthBN computed from multiplying value with `b`. It wraps th **Returns:** [FixedWidthBN](fixedwidthbn.md) +___ +<a id="not"></a> + +### not + +▸ **not**(): [FixedWidthBN](fixedwidthbn.md) + +*Defined in [fixed-width.ts:445](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L445)* + +Returns a new FixedWidthBN computed from bitwise negation of value. + +**Returns:** [FixedWidthBN](fixedwidthbn.md) + ___ <a id="or"></a> @@ -498,7 +534,7 @@ ___ ▸ **or**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:373](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L373)* +*Defined in [fixed-width.ts:394](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L394)* Returns a new FixedWidthBN computed from applying a bitwise or. @@ -519,7 +555,7 @@ ___ ▸ **pow**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:341](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L341)* +*Defined in [fixed-width.ts:351](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L351)* Returns a new FixedWidthBN computed from raising value to power of `b`. @@ -542,7 +578,7 @@ ___ ▸ **powMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:352](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L352)* +*Defined in [fixed-width.ts:362](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L362)* Returns a new FixedWidthBN computed from raising value to power of `b`. It wraps the result on overflow. @@ -557,15 +593,15 @@ Returns a new FixedWidthBN computed from raising value to power of `b`. It wraps **Returns:** [FixedWidthBN](fixedwidthbn.md) ___ -<a id="shln"></a> +<a id="shl"></a> -### shln +### shl -▸ **shln**(b: *`number`*): [FixedWidthBN](fixedwidthbn.md) +▸ **shl**(b: *`number`*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:406](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L406)* +*Defined in [fixed-width.ts:427](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L427)* -Returns a new FixedWidthBN computed from shifting value to left by a number of bits. +Returns a new FixedWidthBN computed from shifting value to left by a number of bits. It discards bits that are shifted out of width. **Parameters:** @@ -576,15 +612,15 @@ Returns a new FixedWidthBN computed from shifting value to left by a number of b **Returns:** [FixedWidthBN](fixedwidthbn.md) ___ -<a id="shrn"></a> +<a id="shr"></a> -### shrn +### shr -▸ **shrn**(b: *`number`*): [FixedWidthBN](fixedwidthbn.md) +▸ **shr**(b: *`number`*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:416](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L416)* +*Defined in [fixed-width.ts:437](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L437)* -Returns a new FixedWidthBN computed from shifting value to right by a number of bits. +Returns a new FixedWidthBN computed from shifting value to right by a number of bits. It discards bits that are shifted out of width. **Parameters:** @@ -601,7 +637,7 @@ ___ ▸ **sqr**(): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:321](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L321)* +*Defined in [fixed-width.ts:331](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L331)* Returns a new FixedWidthBN computed from multiplying value with itself (square of value). @@ -616,7 +652,7 @@ ___ ▸ **sqrMod**(): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:330](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L330)* +*Defined in [fixed-width.ts:340](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L340)* Returns a new FixedWidthBN computed from multiplying value with itself (square of value). It wraps the result on overflow. @@ -629,7 +665,7 @@ ___ ▸ **sub**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:275](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L275)* +*Defined in [fixed-width.ts:285](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L285)* Returns a new FixedWidthBN computed from subtracting value from `b`. @@ -652,7 +688,7 @@ ___ ▸ **subMod**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:287](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L287)* +*Defined in [fixed-width.ts:297](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L297)* Returns a new FixedWidthBN computed from subtracting value from `b`. It wraps the result on underflow, e.g. if width is 8, `2 - 3 == 255`. @@ -737,9 +773,9 @@ ___ ### toString -▸ **toString**(base?: *`number`*): `string` +▸ **toString**(base?: *`number`*, pad?: *`boolean`*): `string` -*Defined in [fixed-width.ts:136](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L136)* +*Defined in [fixed-width.ts:137](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L137)* Returns value encoded as a string (without `0x` prefix for base 16). @@ -748,6 +784,7 @@ Returns value encoded as a string (without `0x` prefix for base 16). | Name | Type | Default value | Description | | ------ | ------ | ------ | ------ | | `Default value` base | `number` | 16 | Base for encoding (e.g. 16 for hex) | +| `Default value` pad | `boolean` | true | Pad output string to width (only for bases 2 and 16) | **Returns:** `string` @@ -758,7 +795,7 @@ ___ ▸ **xor**(b: *[FixedWidthBN](fixedwidthbn.md)*): [FixedWidthBN](fixedwidthbn.md) -*Defined in [fixed-width.ts:395](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L395)* +*Defined in [fixed-width.ts:416](https://github.com/ewasm/fixed-bn.js/blob/master/src/fixed-width.ts#L416)* Returns a new FixedWidthBN computed from applying a bitwise xor. From 06fd1aec6b754cc0c9ae1ba953d8fa30884798a6 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 26 Mar 2019 14:22:22 +0100 Subject: [PATCH 15/17] Add byteLength, ltn, lten, gtn, gten --- src/fixed-width.ts | 40 ++++++++++++++++++++++++++++++++++++++++ tests/fixed-width.ts | 8 ++++++++ 2 files changed, 48 insertions(+) diff --git a/src/fixed-width.ts b/src/fixed-width.ts index 78bd3bd..3fdd5f3 100644 --- a/src/fixed-width.ts +++ b/src/fixed-width.ts @@ -164,6 +164,13 @@ export class FixedWidthBN { return this._bn.bitLength() } + /** + * Returns byte length of value. + */ + byteLength(): number { + return this._bn.byteLength() + } + /** * Returns true if `b` has same width (not bit length) as value. */ @@ -222,6 +229,22 @@ export class FixedWidthBN { return this._bn.lte(b._bn) } + /** + * Returns true if value is less than `b`. + * @param b - Value to be compared against + */ + ltn(b: number): boolean { + return this._bn.ltn(b) + } + + /** + * Returns true if value is less than or equal to `b`. + * @param b - Value to be compared against + */ + lten(b: number): boolean { + return this._bn.lten(b) + } + /** * Returns true if value is greated than `b`. * @param b - Value to be compared against @@ -242,6 +265,23 @@ export class FixedWidthBN { return this._bn.gte(b._bn) } + /** + * Returns true if value is greated than `b`. + * @param b - Value to be compared against + */ + gtn(b: number): boolean { + return this._bn.gtn(b) + } + + /** + * Returns true if value is greated than or equal to `b`. + * @param b - Value to be compared against + * @throws if `b` has a different width + */ + gten(b: number): boolean { + return this._bn.gten(b) + } + /** * Returns true if value is equal to `b`. * @param b - Value to be compared against diff --git a/tests/fixed-width.ts b/tests/fixed-width.ts index e344c6b..a014283 100644 --- a/tests/fixed-width.ts +++ b/tests/fixed-width.ts @@ -21,11 +21,19 @@ tape('Comparison', (t: tape.Test) => { t.test('should compare two same width BNs', (st: tape.Test) => { const a = new FixedWidthBN(64, 21) const b = new FixedWidthBN(64, 20) + const c = 99 + const d = 21 st.equal(a.lt(b), false) st.equal(a.lte(b), false) st.equal(a.gt(b), true) st.equal(a.gte(b), true) st.equal(a.eq(b), false) + st.equal(a.ltn(c), true) + st.equal(a.lten(c), true) + st.equal(a.lten(d), true) + st.equal(a.gtn(c), false) + st.equal(a.gten(c), false) + st.equal(a.gten(d), true) st.end() }) From d7aaedd13653e1e8cba1df7bfb53be44ad23a238 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 26 Mar 2019 15:04:09 +0100 Subject: [PATCH 16/17] Add method for testing if a bit is set --- src/fixed-width.ts | 10 +++++++++- tests/fixed-width.ts | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/fixed-width.ts b/src/fixed-width.ts index 3fdd5f3..c73f054 100644 --- a/src/fixed-width.ts +++ b/src/fixed-width.ts @@ -136,7 +136,7 @@ export class FixedWidthBN { */ toString(base: number = 16, pad: boolean = true): string { if (pad && (base !== 2 && base !== 16)) { - throw new Error('Padding string only supported for bases divisible by 2') + throw new Error('Padding string only supported for bases 2 and 16') } if (pad) { @@ -479,6 +479,14 @@ export class FixedWidthBN { return FixedWidthBN.fromBN(this._width, c) } + /** + * Tests if a specific bit is set. + * @param b - Index of bit to test + */ + test(b: number): boolean { + return this._bn.testn(b) + } + /** * Returns a new FixedWidthBN computed from bitwise negation of value. */ diff --git a/tests/fixed-width.ts b/tests/fixed-width.ts index a014283..147047f 100644 --- a/tests/fixed-width.ts +++ b/tests/fixed-width.ts @@ -255,6 +255,14 @@ tape('Shr', (t: tape.Test) => { t.end() }) +tape('Test', (t: tape.Test) => { + const a = FixedWidthBN.fromString(8, '11001100', 2) + t.equal(a.test(0), false) + t.equal(a.test(7), true) + t.equal(a.test(2), true) + t.end() +}) + tape('ToString', (t: tape.Test) => { const a = FixedWidthBN.fromString(16, '00110011', 2) t.equal(a.toString(2), '0000000000110011') From 8407f6be65eba7e306c6b0907d7d61554e7859d9 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <itz.s1na@gmail.com> Date: Tue, 26 Mar 2019 16:16:56 +0100 Subject: [PATCH 17/17] Add pad? param to toBuffer and toArray --- src/fixed-width.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/fixed-width.ts b/src/fixed-width.ts index c73f054..1540281 100644 --- a/src/fixed-width.ts +++ b/src/fixed-width.ts @@ -108,16 +108,18 @@ export class FixedWidthBN { * Returns number as a Buffer. * @param endian - Endianness */ - toBuffer(endian: Endianness = 'be'): Buffer { - return this._bn.toBuffer(endian, this._width / 8) + toBuffer(endian: Endianness = 'be', pad: boolean = false): Buffer { + const length = pad ? this._width / 8 : 1 + return this._bn.toBuffer(endian, length) } /** * Returns number as an array. * @param endian - Endianness */ - toArray(endian: Endianness = 'be'): number[] { - return this._bn.toArray(endian, this._width / 8) + toArray(endian: Endianness = 'be', pad: boolean = false): number[] { + const length = pad ? this._width / 8 : 1 + return this._bn.toArray(endian, length) } /**