You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					201 lines
				
				6.0 KiB
			
		
		
			
		
	
	
					201 lines
				
				6.0 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# <img src="./logo.png" alt="bn.js" width="160" height="160" />
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> BigNum in pure javascript
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[](http://travis-ci.org/indutny/bn.js)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Install
							 | 
						||
| 
								 | 
							
								`npm install --save bn.js`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Usage
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const BN = require('bn.js');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var a = new BN('dead', 16);
							 | 
						||
| 
								 | 
							
								var b = new BN('101010', 2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var res = a.add(b);
							 | 
						||
| 
								 | 
							
								console.log(res.toString(10));  // 57047
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								**Note**: decimals are not supported in this library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Notation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Prefixes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								There are several prefixes to instructions that affect the way the work. Here
							 | 
						||
| 
								 | 
							
								is the list of them in the order of appearance in the function name:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `i` - perform operation in-place, storing the result in the host object (on
							 | 
						||
| 
								 | 
							
								  which the method was invoked). Might be used to avoid number allocation costs
							 | 
						||
| 
								 | 
							
								* `u` - unsigned, ignore the sign of operands when performing operation, or
							 | 
						||
| 
								 | 
							
								  always return positive value. Second case applies to reduction operations
							 | 
						||
| 
								 | 
							
								  like `mod()`. In such cases if the result will be negative - modulo will be
							 | 
						||
| 
								 | 
							
								  added to the result to make it positive
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Postfixes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The only available postfix at the moment is:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `n` - which means that the argument of the function must be a plain JavaScript
							 | 
						||
| 
								 | 
							
								  Number. Decimals are not supported.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Examples
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `a.iadd(b)` - perform addition on `a` and `b`, storing the result in `a`
							 | 
						||
| 
								 | 
							
								* `a.umod(b)` - reduce `a` modulo `b`, returning positive value
							 | 
						||
| 
								 | 
							
								* `a.iushln(13)` - shift bits of `a` left by 13
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Instructions
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Prefixes/postfixes are put in parens at the of the line. `endian` - could be
							 | 
						||
| 
								 | 
							
								either `le` (little-endian) or `be` (big-endian).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Utilities
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `a.clone()` - clone number
							 | 
						||
| 
								 | 
							
								* `a.toString(base, length)` - convert to base-string and pad with zeroes
							 | 
						||
| 
								 | 
							
								* `a.toNumber()` - convert to Javascript Number (limited to 53 bits)
							 | 
						||
| 
								 | 
							
								* `a.toJSON()` - convert to JSON compatible hex string (alias of `toString(16)`)
							 | 
						||
| 
								 | 
							
								* `a.toArray(endian, length)` - convert to byte `Array`, and optionally zero
							 | 
						||
| 
								 | 
							
								  pad to length, throwing if already exceeding
							 | 
						||
| 
								 | 
							
								* `a.toArrayLike(type, endian, length)` - convert to an instance of `type`,
							 | 
						||
| 
								 | 
							
								  which must behave like an `Array`
							 | 
						||
| 
								 | 
							
								* `a.toBuffer(endian, length)` - convert to Node.js Buffer (if available). For
							 | 
						||
| 
								 | 
							
								  compatibility with browserify and similar tools, use this instead:
							 | 
						||
| 
								 | 
							
								  `a.toArrayLike(Buffer, endian, length)`
							 | 
						||
| 
								 | 
							
								* `a.bitLength()` - get number of bits occupied
							 | 
						||
| 
								 | 
							
								* `a.zeroBits()` - return number of less-significant consequent zero bits
							 | 
						||
| 
								 | 
							
								  (example: `1010000` has 4 zero bits)
							 | 
						||
| 
								 | 
							
								* `a.byteLength()` - return number of bytes occupied
							 | 
						||
| 
								 | 
							
								* `a.isNeg()` - true if the number is negative
							 | 
						||
| 
								 | 
							
								* `a.isEven()` - no comments
							 | 
						||
| 
								 | 
							
								* `a.isOdd()` - no comments
							 | 
						||
| 
								 | 
							
								* `a.isZero()` - no comments
							 | 
						||
| 
								 | 
							
								* `a.cmp(b)` - compare numbers and return `-1` (a `<` b), `0` (a `==` b), or `1` (a `>` b)
							 | 
						||
| 
								 | 
							
								  depending on the comparison result (`ucmp`, `cmpn`)
							 | 
						||
| 
								 | 
							
								* `a.lt(b)` - `a` less than `b` (`n`)
							 | 
						||
| 
								 | 
							
								* `a.lte(b)` - `a` less than or equals `b` (`n`)
							 | 
						||
| 
								 | 
							
								* `a.gt(b)` - `a` greater than `b` (`n`)
							 | 
						||
| 
								 | 
							
								* `a.gte(b)` - `a` greater than or equals `b` (`n`)
							 | 
						||
| 
								 | 
							
								* `a.eq(b)` - `a` equals `b` (`n`)
							 | 
						||
| 
								 | 
							
								* `a.toTwos(width)` - convert to two's complement representation, where `width` is bit width
							 | 
						||
| 
								 | 
							
								* `a.fromTwos(width)` - convert from two's complement representation, where `width` is the bit width
							 | 
						||
| 
								 | 
							
								* `BN.isBN(object)` - returns true if the supplied `object` is a BN.js instance
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Arithmetics
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `a.neg()` - negate sign (`i`)
							 | 
						||
| 
								 | 
							
								* `a.abs()` - absolute value (`i`)
							 | 
						||
| 
								 | 
							
								* `a.add(b)` - addition (`i`, `n`, `in`)
							 | 
						||
| 
								 | 
							
								* `a.sub(b)` - subtraction (`i`, `n`, `in`)
							 | 
						||
| 
								 | 
							
								* `a.mul(b)` - multiply (`i`, `n`, `in`)
							 | 
						||
| 
								 | 
							
								* `a.sqr()` - square (`i`)
							 | 
						||
| 
								 | 
							
								* `a.pow(b)` - raise `a` to the power of `b`
							 | 
						||
| 
								 | 
							
								* `a.div(b)` - divide (`divn`, `idivn`)
							 | 
						||
| 
								 | 
							
								* `a.mod(b)` - reduct (`u`, `n`) (but no `umodn`)
							 | 
						||
| 
								 | 
							
								* `a.divRound(b)` - rounded division
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Bit operations
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `a.or(b)` - or (`i`, `u`, `iu`)
							 | 
						||
| 
								 | 
							
								* `a.and(b)` - and (`i`, `u`, `iu`, `andln`) (NOTE: `andln` is going to be replaced
							 | 
						||
| 
								 | 
							
								  with `andn` in future)
							 | 
						||
| 
								 | 
							
								* `a.xor(b)` - xor (`i`, `u`, `iu`)
							 | 
						||
| 
								 | 
							
								* `a.setn(b)` - set specified bit to `1`
							 | 
						||
| 
								 | 
							
								* `a.shln(b)` - shift left (`i`, `u`, `iu`)
							 | 
						||
| 
								 | 
							
								* `a.shrn(b)` - shift right (`i`, `u`, `iu`)
							 | 
						||
| 
								 | 
							
								* `a.testn(b)` - test if specified bit is set
							 | 
						||
| 
								 | 
							
								* `a.maskn(b)` - clear bits with indexes higher or equal to `b` (`i`)
							 | 
						||
| 
								 | 
							
								* `a.bincn(b)` - add `1 << b` to the number
							 | 
						||
| 
								 | 
							
								* `a.notn(w)` - not (for the width specified by `w`) (`i`)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Reduction
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `a.gcd(b)` - GCD
							 | 
						||
| 
								 | 
							
								* `a.egcd(b)` - Extended GCD results (`{ a: ..., b: ..., gcd: ... }`)
							 | 
						||
| 
								 | 
							
								* `a.invm(b)` - inverse `a` modulo `b`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Fast reduction
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When doing lots of reductions using the same modulo, it might be beneficial to
							 | 
						||
| 
								 | 
							
								use some tricks: like [Montgomery multiplication][0], or using special algorithm
							 | 
						||
| 
								 | 
							
								for [Mersenne Prime][1].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Reduction context
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To enable this tricks one should create a reduction context:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var red = BN.red(num);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								where `num` is just a BN instance.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Or:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var red = BN.red(primeName);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Where `primeName` is either of these [Mersenne Primes][1]:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `'k256'`
							 | 
						||
| 
								 | 
							
								* `'p224'`
							 | 
						||
| 
								 | 
							
								* `'p192'`
							 | 
						||
| 
								 | 
							
								* `'p25519'`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Or:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var red = BN.mont(num);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To reduce numbers with [Montgomery trick][0]. `.mont()` is generally faster than
							 | 
						||
| 
								 | 
							
								`.red(num)`, but slower than `BN.red(primeName)`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Converting numbers
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Before performing anything in reduction context - numbers should be converted
							 | 
						||
| 
								 | 
							
								to it. Usually, this means that one should:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Convert inputs to reducted ones
							 | 
						||
| 
								 | 
							
								* Operate on them in reduction context
							 | 
						||
| 
								 | 
							
								* Convert outputs back from the reduction context
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Here is how one may convert numbers to `red`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var redA = a.toRed(red);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Where `red` is a reduction context created using instructions above
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Here is how to convert them back:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var a = redA.fromRed();
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Red instructions
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Most of the instructions from the very start of this readme have their
							 | 
						||
| 
								 | 
							
								counterparts in red context:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `a.redAdd(b)`, `a.redIAdd(b)`
							 | 
						||
| 
								 | 
							
								* `a.redSub(b)`, `a.redISub(b)`
							 | 
						||
| 
								 | 
							
								* `a.redShl(num)`
							 | 
						||
| 
								 | 
							
								* `a.redMul(b)`, `a.redIMul(b)`
							 | 
						||
| 
								 | 
							
								* `a.redSqr()`, `a.redISqr()`
							 | 
						||
| 
								 | 
							
								* `a.redSqrt()` - square root modulo reduction context's prime
							 | 
						||
| 
								 | 
							
								* `a.redInvm()` - modular inverse of the number
							 | 
						||
| 
								 | 
							
								* `a.redNeg()`
							 | 
						||
| 
								 | 
							
								* `a.redPow(b)` - modular exponentiation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## LICENSE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This software is licensed under the MIT License.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[0]: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
							 | 
						||
| 
								 | 
							
								[1]: https://en.wikipedia.org/wiki/Mersenne_prime
							 |