UNPKG

9.37 kBPlain TextView Raw
1/*
2 * Note 1: All the functions in this file guarantee only that the bottom 32-bits of the returned Int_64 are correct.
3 * JavaScript is flakey when it comes to bit operations and a '1' in the highest order bit of a 32-bit number causes
4 * it to be interpreted as a negative number per two's complement.
5 *
6 * Note 2: Per the ECMAScript spec, all JavaScript operations mask the shift amount by 0x1F. This results in weird
7 * cases like 1 << 32 == 1 and 1 << 33 === 1 << 1 === 2
8 */
9
10/**
11 * Int_64 is a object for 2 32-bit numbers emulating a 64-bit number.
12 */
13export class Int_64 {
14 /**
15 * @param msint_32 The most significant 32-bits of a 64-bit number.
16 * @param lsint_32 The least significant 32-bits of a 64-bit number.
17 */
18 readonly highOrder: number;
19 readonly lowOrder: number;
20 constructor(msint_32: number, lsint_32: number) {
21 this.highOrder = msint_32;
22 this.lowOrder = lsint_32;
23 }
24}
25
26/**
27 * The 64-bit implementation of circular rotate left.
28 *
29 * This does not work for n >= 64 or n == 32 but those are never done.
30 *
31 * @param x The 64-bit integer argument.
32 * @param n The number of bits to shift.
33 * @returns `x` shifted left circularly by `n` bits.
34 */
35export function rotl_64(x: Int_64, n: number): Int_64 {
36 let tmp;
37 if (n > 32) {
38 tmp = 64 - n;
39 return new Int_64((x.lowOrder << n) | (x.highOrder >>> tmp), (x.highOrder << n) | (x.lowOrder >>> tmp));
40 } else if (0 !== n) {
41 tmp = 32 - n;
42 return new Int_64((x.highOrder << n) | (x.lowOrder >>> tmp), (x.lowOrder << n) | (x.highOrder >>> tmp));
43 } else {
44 return x;
45 }
46}
47
48/**
49 * The 64-bit implementation of circular rotate right.
50 *
51 * This does not work for n >= 64, n == 32, or n == 0 but those are never done.
52 *
53 * @param x The 64-bit integer argument.
54 * @param n The number of bits to shift.
55 * @returns `x` shifted right circularly by `n` bits.
56 */
57function rotr_64(x: Int_64, n: number): Int_64 {
58 let tmp;
59 if (n < 32) {
60 tmp = 32 - n;
61 return new Int_64((x.highOrder >>> n) | (x.lowOrder << tmp), (x.lowOrder >>> n) | (x.highOrder << tmp));
62 } else {
63 tmp = 64 - n;
64 return new Int_64((x.lowOrder >>> n) | (x.highOrder << tmp), (x.highOrder >>> n) | (x.lowOrder << tmp));
65 }
66}
67
68/**
69 * The 64-bit implementation of shift right.
70 *
71 * This does not work for n >= 32 but is only called for n < 32.
72 *
73 * @param x The 64-bit integer argument.
74 * @param n The number of bits to shift.
75 * @returns `x` shifted right by `n` bits
76 */
77function shr_64(x: Int_64, n: number): Int_64 {
78 return new Int_64(x.highOrder >>> n, (x.lowOrder >>> n) | (x.highOrder << (32 - n)));
79}
80
81/**
82 * The 64-bit implementation of the NIST specified Ch function.
83 *
84 * @param x The first 64-bit integer argument.
85 * @param y The second 64-bit integer argument.
86 * @param z The third 64-bit integer argument.
87 * @returns The NIST specified output of the function.
88 */
89export function ch_64(x: Int_64, y: Int_64, z: Int_64): Int_64 {
90 return new Int_64(
91 (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
92 (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
93 );
94}
95
96/**
97 * The 64-bit implementation of the NIST specified Maj function.
98 *
99 * @param x The first 64-bit integer argument.
100 * @param y The second 64-bit integer argument.
101 * @param z The third 64-bit integer argument.
102 * @returns The NIST specified output of the function.
103 */
104export function maj_64(x: Int_64, y: Int_64, z: Int_64): Int_64 {
105 return new Int_64(
106 (x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder),
107 (x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder)
108 );
109}
110
111/**
112 * The 64-bit implementation of the NIST specified Sigma0 function.
113 *
114 * @param x The 64-bit integer argument.
115 * @returns The NIST specified output of the function.
116 */
117export function sigma0_64(x: Int_64): Int_64 {
118 const rotr28 = rotr_64(x, 28),
119 rotr34 = rotr_64(x, 34),
120 rotr39 = rotr_64(x, 39);
121
122 return new Int_64(
123 rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
124 rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
125 );
126}
127
128/**
129 * Add two 64-bit integers.
130 *
131 * @param x The first 64-bit integer argument to be added.
132 * @param y The second 64-bit integer argument to be added.
133 * @returns The sum of `x` + `y`.
134 */
135export function safeAdd_64_2(x: Int_64, y: Int_64): Int_64 {
136 let lsw, msw;
137
138 lsw = (x.lowOrder & 0xffff) + (y.lowOrder & 0xffff);
139 msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
140 const lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
141
142 lsw = (x.highOrder & 0xffff) + (y.highOrder & 0xffff) + (msw >>> 16);
143 msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
144 const highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
145
146 return new Int_64(highOrder, lowOrder);
147}
148
149/**
150 * Add four 64-bit integers.
151 *
152 * @param a The first 64-bit integer argument to be added.
153 * @param b The second 64-bit integer argument to be added.
154 * @param c The third 64-bit integer argument to be added.
155 * @param d The fouth 64-bit integer argument to be added.
156 * @returns The sum of `a` + `b` + `c` + `d`.
157 */
158export function safeAdd_64_4(a: Int_64, b: Int_64, c: Int_64, d: Int_64): Int_64 {
159 let lsw, msw;
160
161 lsw = (a.lowOrder & 0xffff) + (b.lowOrder & 0xffff) + (c.lowOrder & 0xffff) + (d.lowOrder & 0xffff);
162 msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
163 const lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
164
165 lsw =
166 (a.highOrder & 0xffff) + (b.highOrder & 0xffff) + (c.highOrder & 0xffff) + (d.highOrder & 0xffff) + (msw >>> 16);
167 msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
168 const highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
169
170 return new Int_64(highOrder, lowOrder);
171}
172
173/**
174 * Add five 64-bit integers.
175 *
176 * @param a The first 64-bit integer argument to be added.
177 * @param b The second 64-bit integer argument to be added.
178 * @param c The third 64-bit integer argument to be added.
179 * @param d The fouth 64-bit integer argument to be added.
180 * @param e The fifth 64-bit integer argument to be added.
181 * @returns The sum of `a` + `b` + `c` + `d` + `e`.
182 */
183export function safeAdd_64_5(a: Int_64, b: Int_64, c: Int_64, d: Int_64, e: Int_64): Int_64 {
184 let lsw, msw;
185
186 lsw =
187 (a.lowOrder & 0xffff) +
188 (b.lowOrder & 0xffff) +
189 (c.lowOrder & 0xffff) +
190 (d.lowOrder & 0xffff) +
191 (e.lowOrder & 0xffff);
192 msw =
193 (a.lowOrder >>> 16) +
194 (b.lowOrder >>> 16) +
195 (c.lowOrder >>> 16) +
196 (d.lowOrder >>> 16) +
197 (e.lowOrder >>> 16) +
198 (lsw >>> 16);
199 const lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
200
201 lsw =
202 (a.highOrder & 0xffff) +
203 (b.highOrder & 0xffff) +
204 (c.highOrder & 0xffff) +
205 (d.highOrder & 0xffff) +
206 (e.highOrder & 0xffff) +
207 (msw >>> 16);
208 msw =
209 (a.highOrder >>> 16) +
210 (b.highOrder >>> 16) +
211 (c.highOrder >>> 16) +
212 (d.highOrder >>> 16) +
213 (e.highOrder >>> 16) +
214 (lsw >>> 16);
215 const highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
216
217 return new Int_64(highOrder, lowOrder);
218}
219
220/**
221 * XORs two given arguments.
222 *
223 * @param a The first argument to be XORed.
224 * @param b The second argument to be XORed.
225 * @returns The The XOR `a` and `b`
226 */
227export function xor_64_2(a: Int_64, b: Int_64): Int_64 {
228 return new Int_64(a.highOrder ^ b.highOrder, a.lowOrder ^ b.lowOrder);
229}
230
231/**
232 * XORs five given arguments.
233 *
234 * @param a The first argument to be XORed.
235 * @param b The second argument to be XORed.
236 * @param c The third argument to be XORed.
237 * @param d The fourth argument to be XORed.
238 * @param e The fifth argument to be XORed.
239 * @returns The XOR of `a`, `b`, `c`, `d`, and `e`.
240 */
241export function xor_64_5(a: Int_64, b: Int_64, c: Int_64, d: Int_64, e: Int_64): Int_64 {
242 return new Int_64(
243 a.highOrder ^ b.highOrder ^ c.highOrder ^ d.highOrder ^ e.highOrder,
244 a.lowOrder ^ b.lowOrder ^ c.lowOrder ^ d.lowOrder ^ e.lowOrder
245 );
246}
247
248/**
249 * The 64-bit implementation of the NIST specified Gamma1 function.
250 *
251 * @param x The 64-bit integer argument.
252 * @returns The NIST specified output of the function.
253 */
254export function gamma1_64(x: Int_64): Int_64 {
255 const rotr19 = rotr_64(x, 19),
256 rotr61 = rotr_64(x, 61),
257 shr6 = shr_64(x, 6);
258
259 return new Int_64(
260 rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
261 rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
262 );
263}
264
265/**
266 * The 64-bit implementation of the NIST specified Gamma0 function.
267 *
268 * @param x The 64-bit integer argument.
269 * @returns The NIST specified output of the function.
270 */
271export function gamma0_64(x: Int_64): Int_64 {
272 const rotr1 = rotr_64(x, 1),
273 rotr8 = rotr_64(x, 8),
274 shr7 = shr_64(x, 7);
275
276 return new Int_64(
277 rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
278 rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
279 );
280}
281
282/**
283 * The 64-bit implementation of the NIST specified Sigma1 function.
284 *
285 * @param x The 64-bit integer argument.
286 * @returns The NIST specified output of the function.
287 */
288export function sigma1_64(x: Int_64): Int_64 {
289 const rotr14 = rotr_64(x, 14),
290 rotr18 = rotr_64(x, 18),
291 rotr41 = rotr_64(x, 41);
292
293 return new Int_64(
294 rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
295 rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
296 );
297}