primitives_64.ts 9.1 KB

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