1 | # n64
|
2 |
|
3 | Optimized int64 object for javascript.
|
4 |
|
5 | ---
|
6 |
|
7 | There are a few different int64 libraries which currently exist for javascript.
|
8 | Some native, some non-native. Most are lacking test coverage. `n64` gives you a
|
9 | native and non-native version which both have full test coverage.
|
10 |
|
11 | ## Install
|
12 |
|
13 | ``` bash
|
14 | $ npm install n64
|
15 | ```
|
16 |
|
17 | ## Usage
|
18 |
|
19 | ``` js
|
20 | const {U64, I64} = require('n64');
|
21 |
|
22 | console.log(U64(0x12345678900).muln(0x12345678));
|
23 | console.log(I64(0x12345678900).muln(0x12345678));
|
24 | ```
|
25 |
|
26 | Outputs:
|
27 |
|
28 | ```
|
29 | <U64: 13145376755874150400>
|
30 | <I64: -5301367317835401216>
|
31 | ```
|
32 |
|
33 | ## API
|
34 |
|
35 | `n64` tries to mimic the [bn.js] API as much as possible. Like bn.js, each
|
36 | method follows a pattern of `(i?)(operation)(n?)`.
|
37 |
|
38 | ### Prefixes
|
39 |
|
40 | - `i` - Perform the operation in-place.
|
41 |
|
42 | ### Postfixes
|
43 |
|
44 | - `n` - Function must be passed a 32 bit javascript number.
|
45 |
|
46 | For example, `a.add(b)` will clone the current object, do the addition, and
|
47 | return a new object. `a.iadd(b)` will do the addition _in place_. `a.addn(b)`
|
48 | will do the "cloned" addition with `b` being a 32 bit JS number, and
|
49 | `a.iaddn(b)` will do the same thing _in-place_.
|
50 |
|
51 | ### Constructor
|
52 |
|
53 | There are two constructors: `U64` and `I64`, both containing the same methods.
|
54 | The `N64` object documented below applies to both `n64.U64` and `n64.I64`.
|
55 |
|
56 | - `new N64()` - Instantiate.
|
57 | - `new N64(num)` - Instantiate from JS number.
|
58 | - `new N64(bool)` - Instantiate from boolean.
|
59 | - `new N64(hi, lo)` - Instantiate from hi/lo bits.
|
60 | - `new N64(obj)` - Instantiate from object (hi & lo).
|
61 | - `new N64(str, base?)` - Instantiate from string.
|
62 | - `new N64(bn)` - Instantiate from bn.js bignumber.
|
63 | - `new N64(data)` - Instantiate from bytes (little endian).
|
64 |
|
65 | ### Properties
|
66 |
|
67 | - `hi` - Internal hi bits (int32).
|
68 | - `lo` - Internal lo bits (int32).
|
69 | - `sign` - Whether the int64 is signed (0 or 1).
|
70 |
|
71 | ### Static Methods
|
72 |
|
73 | - `N64.min(a, b)` - Pick min value.
|
74 | - `N64.max(a, b)` - Pick max value.
|
75 | - `N64.random()` - Instantiate random int64.
|
76 | - `N64.pow(num, exp)` - Instantiate from number and power.
|
77 | - `N64.shift(num, bits)` - Instantiate from left shift.
|
78 | - `N64.readLE(data, off)` - Instantiate from `data` at `off` (little endian).
|
79 | - `N64.readBE(data, off)` - Instantiate from `data` at `off` (big endian).
|
80 | - `N64.readRaw(data, off)` - Instantiate from `data` at `off` (little endian).
|
81 | - `N64.fromNumber(num)` - Instantiate from JS number.
|
82 | - `N64.fromInt(lo)` - Instantiate from lo bits.
|
83 | - `N64.fromBool(value)` - Instantiate from boolean.
|
84 | - `N64.fromBits(hi, lo)` - Instantiate from hi/lo bits.
|
85 | - `N64.fromObject(obj)` - Instantiate from object (hi & lo).
|
86 | - `N64.fromString(str, base?)` - Instantiate from string.
|
87 | - `N64.fromJSON(json)` - Instantiate from JSON.
|
88 | - `N64.fromBN(bn)` - Instantiate from bn.js bignumber.
|
89 | - `N64.fromLE(data)` - Instantiate from bytes (little endian).
|
90 | - `N64.fromBE(data)` - Instantiate from bytes (big endian).
|
91 | - `N64.fromRaw(data)` - Instantiate from bytes (little endian).
|
92 | - `N64.from()` - Instantiate.
|
93 | - `N64.from(num)` - Instantiate from JS number.
|
94 | - `N64.from(bool)` - Instantiate from boolean.
|
95 | - `N64.from(hi, lo)` - Instantiate from hi/lo bits.
|
96 | - `N64.from(obj)` - Instantiate from object (hi & lo).
|
97 | - `N64.from(str, base?)` - Instantiate from string.
|
98 | - `N64.from(bn)` - Instantiate from bn.js bignumber.
|
99 | - `N64.from(data)` - Instantiate from bytes (little endian).
|
100 | - `N64.isN64(obj)` - Test instanceof N64.
|
101 | - `N64.isU64(obj)` - Test instanceof U64.
|
102 | - `N64.isI64(obj)` - Test instanceof I64.
|
103 |
|
104 | ### Methods
|
105 |
|
106 | #### Arithmetic
|
107 |
|
108 | - `N64#iadd(obj)` - In-place addition with another int64.
|
109 | - `N64#iaddn(num)` - In-place addition with a JS number.
|
110 | - `N64#add(obj)` - Cloned addition with another int64.
|
111 | - `N64#addn(num)` - Cloned addition with a JS number.
|
112 | - `N64#isub(obj)` - In-place subtraction with another int64.
|
113 | - `N64#isubn(num)` - In-place subtraction with a JS number.
|
114 | - `N64#sub(obj)` - Cloned subtraction with another int64.
|
115 | - `N64#subn(num)` - Cloned subtraction with a JS number.
|
116 | - `N64#imul(obj)` - In-place multiplication with another int64.
|
117 | - `N64#imuln(num)` - In-place multiplication with a JS number.
|
118 | - `N64#mul(obj)` - Cloned multiplication with another int64.
|
119 | - `N64#muln(num)` - Cloned multiplication with a JS number.
|
120 | - `N64#idiv(obj)` - In-place division with another int64.
|
121 | - `N64#idivn(num)` - In-place division with a JS number.
|
122 | - `N64#div(obj)` - Cloned division with another int64.
|
123 | - `N64#divn(num)` - Cloned division with a JS number.
|
124 | - `N64#imod(obj)` - In-place modulo with another int64.
|
125 | - `N64#imodn(num)` - In-place modulo with a JS number.
|
126 | - `N64#mod(obj)` - Cloned modulo with another int64.
|
127 | - `N64#modn(num)` - Cloned modulo with a JS number.
|
128 | - `N64#ipow(obj)` - In-place exponentiation with another int64.
|
129 | - `N64#ipown(num)` - In-place exponentiation with a JS number.
|
130 | - `N64#pow(obj)` - Cloned exponentiation with another int64.
|
131 | - `N64#pown(num)` - Cloned exponentiation with a JS number.
|
132 | - `N64#isqr()` - Square number in-place.
|
133 | - `N64#sqr()` - Clone and square number.
|
134 |
|
135 | #### Bitwise
|
136 |
|
137 | - `N64#iand(obj)` - In-place `AND` with another int64.
|
138 | - `N64#iandn(num)` - In-place `AND` with a JS number.
|
139 | - `N64#and(obj)` - Cloned `AND` with another int64.
|
140 | - `N64#andn(num)` - Cloned `AND` with a JS number.
|
141 | - `N64#ior(obj)` - In-place `OR` with another int64.
|
142 | - `N64#iorn(num)` - In-place `OR` with a JS number.
|
143 | - `N64#or(obj)` - Cloned `OR` with another int64.
|
144 | - `N64#orn(num)` - Cloned `OR` with a JS number.
|
145 | - `N64#ixor(obj)` - In-place `XOR` with another int64.
|
146 | - `N64#ixorn(num)` - In-place `XOR` with a JS number.
|
147 | - `N64#xor(obj)` - Cloned `XOR` with another int64.
|
148 | - `N64#xorn(num)` - Cloned `XOR` with a JS number.
|
149 | - `N64#inot()` - In-place `NOT`.
|
150 | - `N64#not()` - Cloned `NOT`.
|
151 | - `N64#ishl(obj)` - In-place left-shift with another int64.
|
152 | - `N64#ishln(num)` - In-place left-shift with a JS number.
|
153 | - `N64#shl(obj)` - Cloned left-shift with another int64.
|
154 | - `N64#shln(num)` - Cloned left-shift with a JS number.
|
155 | - `N64#ishr(obj)` - In-place right-shift with another int64.
|
156 | - `N64#ishrn(num)` - In-place right-shift with a JS number.
|
157 | - `N64#shr(obj)` - Cloned right-shift with another int64.
|
158 | - `N64#shrn(num)` - Cloned right-shift with a JS number.
|
159 | - `N64#iushr(obj)` - In-place unsigned right-shift with another int64.
|
160 | - `N64#iushrn(num)` - In-place unsigned right-shift with a JS number.
|
161 | - `N64#ushr(obj)` - Cloned unsigned right-shift with another int64.
|
162 | - `N64#ushrn(num)` - Cloned unsigned right-shift with a JS number.
|
163 | - `N64#setn(bit, val)` - Set specified bit to `val` (in-place).
|
164 | - `N64#testn(bit)` - Test whether a bit is set.
|
165 | - `N64#setb(pos, ch)` - Set byte `ch` at position `pos` (in-place).
|
166 | - `N64#orb(pos, ch)` - OR byte `ch` at position `pos` (in-place).
|
167 | - `N64#getb(pos)` - Get byte at position `pos`.
|
168 | - `N64#imaskn(bit)` - Clear bits higher or equal to `bit` (in-place).
|
169 | - `N64#maskn(bit)` - Clear bits higher or equal to `bit`.
|
170 | - `N64#andln(num)` - Perform `AND` on lo 32 bits (returns JS number).
|
171 |
|
172 | #### Negation
|
173 |
|
174 | - `N64#ineg()` - In-place negation.
|
175 | - `N64#neg()` - Cloned negation.
|
176 | - `N64#iabs()` - In-place absolute.
|
177 | - `N64#abs()` - Cloned absolute.
|
178 |
|
179 | #### Comparison
|
180 |
|
181 | - `N64#cmp(obj)` - Compare to another int64.
|
182 | - `N64#cmpn(num)` - Compare to a JS number.
|
183 | - `N64#eq(obj)` - Test equality against another int64.
|
184 | - `N64#eqn(num)` - Test equality against a JS number.
|
185 | - `N64#gt(obj)` - Greater than (int64).
|
186 | - `N64#gtn(num)` - Greater than (JS number).
|
187 | - `N64#gte(obj)` - Greater than or equal to (int64).
|
188 | - `N64#gten(num)` - Greater than or equal to (JS number).
|
189 | - `N64#lt(obj)` - Less than (int64).
|
190 | - `N64#ltn(num)` - Less than (JS number).
|
191 | - `N64#lte(obj)` - Less than or equal to (int64).
|
192 | - `N64#lten(num)` - Less than or equal to (JS number).
|
193 | - `N64#isZero()` - Test whether int64 is zero.
|
194 | - `N64#isNeg()` - Test whether int64 is negative.
|
195 | - `N64#isOdd()` - Test whether int64 is odd.
|
196 | - `N64#isEven()` - Test whether int64 is even.
|
197 |
|
198 | #### Helpers
|
199 |
|
200 | - `N64#clone()` - Clone and return a new int64.
|
201 | - `N64#inject(obj)` - Inject properties from int64.
|
202 | - `N64#set(num)` - Set the int64 to a JS number value.
|
203 | - `N64#join(hi, lo)` - Join hi and lo bits.
|
204 | - `N64#bitLength()` - Count number of bits.
|
205 | - `N64#byteLength()` - Count number of bytes.
|
206 | - `N64#isSafe()` - Test whether the number is less than or equal to 53 bits.
|
207 | - `N64#inspect()` - Inspect number.
|
208 |
|
209 | #### Encoding
|
210 |
|
211 | - `N64#readLE(data, off)` - Read number from `data` at `off` (little endian).
|
212 | - `N64#readBE(data, off)` - Read number from `data` at `off` (big endian).
|
213 | - `N64#readRaw(data, off)` - Read number from `data` at `off` (little endian).
|
214 | - `N64#writeLE(data, off)` - Write number to `data` at `off` (little endian).
|
215 | - `N64#writeBE(data, off)` - Write number to `data` at `off` (big endian).
|
216 | - `N64#writeRaw(data, off)` - Write number to `data` at `off` (little endian).
|
217 |
|
218 | #### Conversion
|
219 |
|
220 | - `N64#toU64()` - Cast to unsigned. Returns a U64.
|
221 | - `N64#toI64()` - Cast to signed. Returns an I64.
|
222 | - `N64#toNumber()` - Convert int64 to a JS number (throws on >53 bits).
|
223 | - `N64#toDouble()` - Convert int64 to a JS number.
|
224 | - `N64#toInt()` - Convert lo bits to a JS number.
|
225 | - `N64#toBool()` - Convert to a boolean.
|
226 | - `N64#toBits()` - Convert to an array containing hi and lo bits.
|
227 | - `N64#toObject()` - Convert to an object containing hi and lo bits.
|
228 | - `N64#toString(base?, pad?)` - Convert to string of `base`. Optional padding.
|
229 | - `N64#toJSON()` - Convert to hex string.
|
230 | - `N64#toBN(BN)` - Convert to bn.js big number (must pass BN constructor).
|
231 | - `N64#toLE(ArrayLike)` - Convert to `ArrayLike` instance (little endian).
|
232 | - `N64#toBE(ArrayLike)` - Convert to `ArrayLike` instance (big endian).
|
233 | - `N64#toRaw(ArrayLike)` - Convert to `ArrayLike` instance (little endian).
|
234 |
|
235 | ### Constants
|
236 |
|
237 | - `U64.ULONG_MIN` - Unsigned int32 minimum (number).
|
238 | - `U64.ULONG_MAX` - Unsigned int32 maximum (number).
|
239 | - `U64.UINT32_MIN` - Unsigned int32 minimum (U64).
|
240 | - `U64.UINT32_MAX` - Unsigned int32 maximum (U64).
|
241 | - `U64.UINT64_MIN` - Unsigned int64 minimum (U64).
|
242 | - `U64.UINT64_MAX` - Unsigned int64 maximum (U64).
|
243 | - `I64.LONG_MIN` - Int32 minimum (number).
|
244 | - `I64.LONG_MAX` - Int32 maximum (number).
|
245 | - `I64.INT32_MIN` - Int32 minimum (I64).
|
246 | - `I64.INT32_MAX` - Int32 maximum (I64).
|
247 | - `I64.INT64_MIN` - Int64 minimum (I64).
|
248 | - `I64.INT64_MAX` - Int64 maximum (I64).
|
249 |
|
250 | ## Casting
|
251 |
|
252 | With mixed types, the left operand will cast the right operand to its sign.
|
253 |
|
254 | With the `n`-postfix methods, numbers passed into them will be cast to 32 bit
|
255 | integers. If the left had operand is signed, the number is cast to an
|
256 | `int32_t`. If unsigned, the number is cast to an `uint32_t`.
|
257 |
|
258 | ### Examples
|
259 |
|
260 | In JS:
|
261 |
|
262 | ``` js
|
263 | const a = I64(1);
|
264 | const b = U64('ffffffffffffffff', 16);
|
265 | const r = a.add(b);
|
266 | console.log(r.toString());
|
267 | ```
|
268 |
|
269 | In C:
|
270 |
|
271 | ``` c
|
272 | int64_t a = 1;
|
273 | uint64_t b = 0xffffffffffffffff;
|
274 | int64_t r = a + (int64_t)b;
|
275 | printf("%lld\n", r);
|
276 | ```
|
277 |
|
278 | Outputs `0`, as `(int64_t)ULLONG_MAX == -1LL`.
|
279 |
|
280 | ---
|
281 |
|
282 | In JS:
|
283 |
|
284 | ``` js
|
285 | const a = I64(0);
|
286 | const r = a.addn(0xffffffff);
|
287 | console.log(r.toString());
|
288 | ```
|
289 |
|
290 | In C:
|
291 |
|
292 | ``` c
|
293 | int64_t a = 0;
|
294 | int64_t r = a + (int32_t)0xffffffff;
|
295 | printf("%lld\n", r);
|
296 | ```
|
297 |
|
298 | Outputs `-1`.
|
299 |
|
300 | ---
|
301 |
|
302 | In JS:
|
303 |
|
304 | ``` js
|
305 | const a = U64(0);
|
306 | const r = a.addn(-1);
|
307 | console.log(r.toString());
|
308 | ```
|
309 |
|
310 | In C:
|
311 |
|
312 | ``` c
|
313 | uint64_t a = 0;
|
314 | uint64_t r = a + (uint32_t)-1;
|
315 | printf("%llu\n", r);
|
316 | ```
|
317 |
|
318 | Outputs `4294967295`.
|
319 |
|
320 | ## Testing
|
321 |
|
322 | ``` bash
|
323 | $ npm test
|
324 | ```
|
325 |
|
326 | This should run all test vectors for both the native and non-native backend.
|
327 |
|
328 | ## Fuzzing
|
329 |
|
330 | A fuzzer is present for testing of operations vs. actual machine operations.
|
331 |
|
332 | ``` bash
|
333 | $ node test/fuzz.js
|
334 | ```
|
335 |
|
336 | ## Benchmarks
|
337 |
|
338 | Benchmarks are run against bn.js.
|
339 |
|
340 | ``` bash
|
341 | $ node bench
|
342 | ```
|
343 |
|
344 | ## Contribution and License Agreement
|
345 |
|
346 | If you contribute code to this project, you are implicitly allowing your code
|
347 | to be distributed under the MIT license. You are also implicitly verifying that
|
348 | all code is your original work. `</legalese>`
|
349 |
|
350 | ## License
|
351 |
|
352 | - Copyright (c) 2017, Christopher Jeffrey. (MIT License)
|
353 |
|
354 | See LICENSE for more info.
|
355 |
|
356 | [bn.js]: https://github.com/indutny/bn.js
|