1 |
3a515b92
|
cagy
|
# <img src="./logo.png" alt="bn.js" width="160" height="160" />
|
2 |
|
|
|
3 |
|
|
> BigNum in pure javascript
|
4 |
|
|
|
5 |
|
|
[](http://travis-ci.org/indutny/bn.js)
|
6 |
|
|
|
7 |
|
|
## Install
|
8 |
|
|
`npm install --save bn.js`
|
9 |
|
|
|
10 |
|
|
## Usage
|
11 |
|
|
|
12 |
|
|
```js
|
13 |
|
|
const BN = require('bn.js');
|
14 |
|
|
|
15 |
|
|
var a = new BN('dead', 16);
|
16 |
|
|
var b = new BN('101010', 2);
|
17 |
|
|
|
18 |
|
|
var res = a.add(b);
|
19 |
|
|
console.log(res.toString(10)); // 57047
|
20 |
|
|
```
|
21 |
|
|
|
22 |
|
|
**Note**: decimals are not supported in this library.
|
23 |
|
|
|
24 |
|
|
## Notation
|
25 |
|
|
|
26 |
|
|
### Prefixes
|
27 |
|
|
|
28 |
|
|
There are several prefixes to instructions that affect the way the work. Here
|
29 |
|
|
is the list of them in the order of appearance in the function name:
|
30 |
|
|
|
31 |
|
|
* `i` - perform operation in-place, storing the result in the host object (on
|
32 |
|
|
which the method was invoked). Might be used to avoid number allocation costs
|
33 |
|
|
* `u` - unsigned, ignore the sign of operands when performing operation, or
|
34 |
|
|
always return positive value. Second case applies to reduction operations
|
35 |
|
|
like `mod()`. In such cases if the result will be negative - modulo will be
|
36 |
|
|
added to the result to make it positive
|
37 |
|
|
|
38 |
|
|
### Postfixes
|
39 |
|
|
|
40 |
|
|
The only available postfix at the moment is:
|
41 |
|
|
|
42 |
|
|
* `n` - which means that the argument of the function must be a plain JavaScript
|
43 |
|
|
Number. Decimals are not supported.
|
44 |
|
|
|
45 |
|
|
### Examples
|
46 |
|
|
|
47 |
|
|
* `a.iadd(b)` - perform addition on `a` and `b`, storing the result in `a`
|
48 |
|
|
* `a.umod(b)` - reduce `a` modulo `b`, returning positive value
|
49 |
|
|
* `a.iushln(13)` - shift bits of `a` left by 13
|
50 |
|
|
|
51 |
|
|
## Instructions
|
52 |
|
|
|
53 |
|
|
Prefixes/postfixes are put in parens at the of the line. `endian` - could be
|
54 |
|
|
either `le` (little-endian) or `be` (big-endian).
|
55 |
|
|
|
56 |
|
|
### Utilities
|
57 |
|
|
|
58 |
|
|
* `a.clone()` - clone number
|
59 |
|
|
* `a.toString(base, length)` - convert to base-string and pad with zeroes
|
60 |
|
|
* `a.toNumber()` - convert to Javascript Number (limited to 53 bits)
|
61 |
|
|
* `a.toJSON()` - convert to JSON compatible hex string (alias of `toString(16)`)
|
62 |
|
|
* `a.toArray(endian, length)` - convert to byte `Array`, and optionally zero
|
63 |
|
|
pad to length, throwing if already exceeding
|
64 |
|
|
* `a.toArrayLike(type, endian, length)` - convert to an instance of `type`,
|
65 |
|
|
which must behave like an `Array`
|
66 |
|
|
* `a.toBuffer(endian, length)` - convert to Node.js Buffer (if available). For
|
67 |
|
|
compatibility with browserify and similar tools, use this instead:
|
68 |
|
|
`a.toArrayLike(Buffer, endian, length)`
|
69 |
|
|
* `a.bitLength()` - get number of bits occupied
|
70 |
|
|
* `a.zeroBits()` - return number of less-significant consequent zero bits
|
71 |
|
|
(example: `1010000` has 4 zero bits)
|
72 |
|
|
* `a.byteLength()` - return number of bytes occupied
|
73 |
|
|
* `a.isNeg()` - true if the number is negative
|
74 |
|
|
* `a.isEven()` - no comments
|
75 |
|
|
* `a.isOdd()` - no comments
|
76 |
|
|
* `a.isZero()` - no comments
|
77 |
|
|
* `a.cmp(b)` - compare numbers and return `-1` (a `<` b), `0` (a `==` b), or `1` (a `>` b)
|
78 |
|
|
depending on the comparison result (`ucmp`, `cmpn`)
|
79 |
|
|
* `a.lt(b)` - `a` less than `b` (`n`)
|
80 |
|
|
* `a.lte(b)` - `a` less than or equals `b` (`n`)
|
81 |
|
|
* `a.gt(b)` - `a` greater than `b` (`n`)
|
82 |
|
|
* `a.gte(b)` - `a` greater than or equals `b` (`n`)
|
83 |
|
|
* `a.eq(b)` - `a` equals `b` (`n`)
|
84 |
|
|
* `a.toTwos(width)` - convert to two's complement representation, where `width` is bit width
|
85 |
|
|
* `a.fromTwos(width)` - convert from two's complement representation, where `width` is the bit width
|
86 |
|
|
* `BN.isBN(object)` - returns true if the supplied `object` is a BN.js instance
|
87 |
|
|
|
88 |
|
|
### Arithmetics
|
89 |
|
|
|
90 |
|
|
* `a.neg()` - negate sign (`i`)
|
91 |
|
|
* `a.abs()` - absolute value (`i`)
|
92 |
|
|
* `a.add(b)` - addition (`i`, `n`, `in`)
|
93 |
|
|
* `a.sub(b)` - subtraction (`i`, `n`, `in`)
|
94 |
|
|
* `a.mul(b)` - multiply (`i`, `n`, `in`)
|
95 |
|
|
* `a.sqr()` - square (`i`)
|
96 |
|
|
* `a.pow(b)` - raise `a` to the power of `b`
|
97 |
|
|
* `a.div(b)` - divide (`divn`, `idivn`)
|
98 |
|
|
* `a.mod(b)` - reduct (`u`, `n`) (but no `umodn`)
|
99 |
|
|
* `a.divRound(b)` - rounded division
|
100 |
|
|
|
101 |
|
|
### Bit operations
|
102 |
|
|
|
103 |
|
|
* `a.or(b)` - or (`i`, `u`, `iu`)
|
104 |
|
|
* `a.and(b)` - and (`i`, `u`, `iu`, `andln`) (NOTE: `andln` is going to be replaced
|
105 |
|
|
with `andn` in future)
|
106 |
|
|
* `a.xor(b)` - xor (`i`, `u`, `iu`)
|
107 |
|
|
* `a.setn(b)` - set specified bit to `1`
|
108 |
|
|
* `a.shln(b)` - shift left (`i`, `u`, `iu`)
|
109 |
|
|
* `a.shrn(b)` - shift right (`i`, `u`, `iu`)
|
110 |
|
|
* `a.testn(b)` - test if specified bit is set
|
111 |
|
|
* `a.maskn(b)` - clear bits with indexes higher or equal to `b` (`i`)
|
112 |
|
|
* `a.bincn(b)` - add `1 << b` to the number
|
113 |
|
|
* `a.notn(w)` - not (for the width specified by `w`) (`i`)
|
114 |
|
|
|
115 |
|
|
### Reduction
|
116 |
|
|
|
117 |
|
|
* `a.gcd(b)` - GCD
|
118 |
|
|
* `a.egcd(b)` - Extended GCD results (`{ a: ..., b: ..., gcd: ... }`)
|
119 |
|
|
* `a.invm(b)` - inverse `a` modulo `b`
|
120 |
|
|
|
121 |
|
|
## Fast reduction
|
122 |
|
|
|
123 |
|
|
When doing lots of reductions using the same modulo, it might be beneficial to
|
124 |
|
|
use some tricks: like [Montgomery multiplication][0], or using special algorithm
|
125 |
|
|
for [Mersenne Prime][1].
|
126 |
|
|
|
127 |
|
|
### Reduction context
|
128 |
|
|
|
129 |
|
|
To enable this tricks one should create a reduction context:
|
130 |
|
|
|
131 |
|
|
```js
|
132 |
|
|
var red = BN.red(num);
|
133 |
|
|
```
|
134 |
|
|
where `num` is just a BN instance.
|
135 |
|
|
|
136 |
|
|
Or:
|
137 |
|
|
|
138 |
|
|
```js
|
139 |
|
|
var red = BN.red(primeName);
|
140 |
|
|
```
|
141 |
|
|
|
142 |
|
|
Where `primeName` is either of these [Mersenne Primes][1]:
|
143 |
|
|
|
144 |
|
|
* `'k256'`
|
145 |
|
|
* `'p224'`
|
146 |
|
|
* `'p192'`
|
147 |
|
|
* `'p25519'`
|
148 |
|
|
|
149 |
|
|
Or:
|
150 |
|
|
|
151 |
|
|
```js
|
152 |
|
|
var red = BN.mont(num);
|
153 |
|
|
```
|
154 |
|
|
|
155 |
|
|
To reduce numbers with [Montgomery trick][0]. `.mont()` is generally faster than
|
156 |
|
|
`.red(num)`, but slower than `BN.red(primeName)`.
|
157 |
|
|
|
158 |
|
|
### Converting numbers
|
159 |
|
|
|
160 |
|
|
Before performing anything in reduction context - numbers should be converted
|
161 |
|
|
to it. Usually, this means that one should:
|
162 |
|
|
|
163 |
|
|
* Convert inputs to reducted ones
|
164 |
|
|
* Operate on them in reduction context
|
165 |
|
|
* Convert outputs back from the reduction context
|
166 |
|
|
|
167 |
|
|
Here is how one may convert numbers to `red`:
|
168 |
|
|
|
169 |
|
|
```js
|
170 |
|
|
var redA = a.toRed(red);
|
171 |
|
|
```
|
172 |
|
|
Where `red` is a reduction context created using instructions above
|
173 |
|
|
|
174 |
|
|
Here is how to convert them back:
|
175 |
|
|
|
176 |
|
|
```js
|
177 |
|
|
var a = redA.fromRed();
|
178 |
|
|
```
|
179 |
|
|
|
180 |
|
|
### Red instructions
|
181 |
|
|
|
182 |
|
|
Most of the instructions from the very start of this readme have their
|
183 |
|
|
counterparts in red context:
|
184 |
|
|
|
185 |
|
|
* `a.redAdd(b)`, `a.redIAdd(b)`
|
186 |
|
|
* `a.redSub(b)`, `a.redISub(b)`
|
187 |
|
|
* `a.redShl(num)`
|
188 |
|
|
* `a.redMul(b)`, `a.redIMul(b)`
|
189 |
|
|
* `a.redSqr()`, `a.redISqr()`
|
190 |
|
|
* `a.redSqrt()` - square root modulo reduction context's prime
|
191 |
|
|
* `a.redInvm()` - modular inverse of the number
|
192 |
|
|
* `a.redNeg()`
|
193 |
|
|
* `a.redPow(b)` - modular exponentiation
|
194 |
|
|
|
195 |
|
|
## LICENSE
|
196 |
|
|
|
197 |
|
|
This software is licensed under the MIT License.
|
198 |
|
|
|
199 |
|
|
Copyright Fedor Indutny, 2015.
|
200 |
|
|
|
201 |
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
202 |
|
|
copy of this software and associated documentation files (the
|
203 |
|
|
"Software"), to deal in the Software without restriction, including
|
204 |
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
205 |
|
|
distribute, sublicense, and/or sell copies of the Software, and to permit
|
206 |
|
|
persons to whom the Software is furnished to do so, subject to the
|
207 |
|
|
following conditions:
|
208 |
|
|
|
209 |
|
|
The above copyright notice and this permission notice shall be included
|
210 |
|
|
in all copies or substantial portions of the Software.
|
211 |
|
|
|
212 |
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
213 |
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
214 |
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
215 |
|
|
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
216 |
|
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
217 |
|
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
218 |
|
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
219 |
|
|
|
220 |
|
|
[0]: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
|
221 |
|
|
[1]: https://en.wikipedia.org/wiki/Mersenne_prime
|