@amritk/nish-x86_64-linux 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/nish +0 -0
- package/docs/AI.md +10 -4
- package/package.json +1 -1
- package/std/README.md +1 -0
- package/std/crypto/bcrypt.ts +152 -101
- package/std/sort.ts +178 -0
package/bin/nish
CHANGED
|
Binary file
|
package/docs/AI.md
CHANGED
|
@@ -49,7 +49,7 @@ stdout, nothing on stderr, every field 1-based with `endLine`/`endColumn`
|
|
|
49
49
|
exclusive:
|
|
50
50
|
|
|
51
51
|
```json
|
|
52
|
-
{"file":"p.ts","line":3,"column":17,"endLine":3,"endColumn":20,"severity":"error","code":"NL2249","message":"Unknown method `map` on i32[] (supported: push, pop, indexOf, join, set, fill)"}
|
|
52
|
+
{"file":"p.ts","line":3,"column":17,"endLine":3,"endColumn":20,"severity":"error","code":"NL2249","message":"Unknown method `map` on i32[] (supported: push, pop, indexOf, join, set, fill, sort)"}
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
- **Key on `code`, never on `message`.** A code is a promise: `NL2249` means
|
|
@@ -159,7 +159,7 @@ rejects. This table is the highest-value part of the page.
|
|
|
159
159
|
| `x == y` | `Loose equality is forbidden` | `x === y` |
|
|
160
160
|
| `throw new Error(m)` | `` `throw` is forbidden `` | `return Err(m)`, or `panic(m)` to end the process |
|
|
161
161
|
| `try { … } catch { … }` | `` `try`/`catch`/`finally` is forbidden `` | `Result<T, E>` and `isErr()` |
|
|
162
|
-
| `xs.map(f)`, `.filter`, `.reduce`, `.forEach`, `.slice`, `.
|
|
162
|
+
| `xs.map(f)`, `.filter`, `.reduce`, `.forEach`, `.slice`, `.shift` | `` Unknown method `map` on i32[] (supported: push, pop, indexOf, join, set, fill, sort) `` | a `for` loop, or a top-level `map(xs, f)` with a [function parameter](#function-parameters) |
|
|
163
163
|
| `s.toUpperCase()`, `s.split()`, `s.trim()`, `s.replace()` | `` Unknown method … on string `` | index bytes with `charCodeAt` / `substring` |
|
|
164
164
|
| `a?.b`, `a ?? b` | `?.` only in a chain that ends in `??`; `??` only on a `T \| null`, a chain or `m.get(k)` | `a?.b ?? d`, `a ?? d`, or `if (a !== null)` first |
|
|
165
165
|
| `x as T`, `<T>x`, `x satisfies T` | `Unsupported expression in Phase 1: AsExpression` (to `any` or `unknown`: `` Type assertion to `any` is forbidden ``); `x!` is a syntax error | there are no casts; `implements` is the only widening |
|
|
@@ -852,7 +852,8 @@ export const main = (): i32 => {
|
|
|
852
852
|
(`` The arrow reads `k`, a `let` of the function it is written in: ... bind the value to a `const` before the call ``),
|
|
853
853
|
read `this` (bind `const self = this`), or read a function parameter of its
|
|
854
854
|
function. An arrow inside another arrow, or given to a method, a
|
|
855
|
-
constructor, `expose` or `exposeWith`, captures nothing.
|
|
855
|
+
constructor, `expose` or `exposeWith`, captures nothing; `xs.sort(cmp)`'s
|
|
856
|
+
comparator is the exception, and captures as an arrow argument does.
|
|
856
857
|
- **The argument's type must match exactly**: `(x: i32) => i64` for a
|
|
857
858
|
`(x: i32) => i32` parameter is refused. A generic function cannot be passed
|
|
858
859
|
by name — write `(x) => identity(x)`.
|
|
@@ -2138,7 +2139,12 @@ there is no `undefined` to return), `a.indexOf(v)`, `a.join(sep)` — **`join` i
|
|
|
2138
2139
|
`string[]` only** — and, on an array of numbers only, `dst.set(src[, offset])`
|
|
2139
2140
|
(one `memmove`; a range past the end panics) and `a.fill(v[, start[, end]])`
|
|
2140
2141
|
(ends clamped and counted back from the end when negative, as in JavaScript;
|
|
2141
|
-
never panics). Both are statements.
|
|
2142
|
+
never panics). Both are statements. `a.sort(cmp)` sorts in place, stably, and
|
|
2143
|
+
answers `a` — the same order Node gives; the comparator is required (`a.sort()`
|
|
2144
|
+
is refused, since JavaScript would compare strings), a readonly array and
|
|
2145
|
+
`process.argv` are refused, `a - b` panics on `i32` values a full range apart
|
|
2146
|
+
(compare with `a > b ? 1 : a < b ? -1 : 0` there), and the comparator may read the caller's `const` locals and parameters but not
|
|
2147
|
+
a `let`, as any arrow argument may. That is every array method there is. A
|
|
2142
2148
|
window into a buffer is `(buf, offset, length)`; there is no view type.
|
|
2143
2149
|
|
|
2144
2150
|
**Strings.** `s.length` (**bytes**), `s.charCodeAt(i)` (the byte, bounds-checked),
|
package/package.json
CHANGED
package/std/README.md
CHANGED
|
@@ -12,6 +12,7 @@ whatever program imports it, and subject to the same rules as `examples/` or
|
|
|
12
12
|
| [`testing.ts`](./testing.ts) | a test runner: a `Suite` a program drives with straight-line assertions, printing the `PASS` / `FAIL` / `SKIP` lines the repository's own harness prints, and answering the exit code |
|
|
13
13
|
| [`text.ts`](./text.ts) | the string operations a program would otherwise write inline: `splitLines`, `splitWhitespace`, `trim` and its halves, `contains`, `replaceAll`, `firstDifference` over two arrays of lines, `codePointLength`, the number of Unicode code points (what JSON Schema's `minLength` counts, where `.length` counts UTF-8 bytes natively and UTF-16 units under Node; it answers the same on both by asking which it is reading), and `indexOfAny(text, bytes, from)`, the first index at or after `from` whose byte is one of 1 to 16 ASCII `bytes`. Its walker is the meaning and what runs under Node; natively the compiler replaces the one call to it with the runtime kernel `nish_str_index_of_any`, which reads 16 or 32 bytes at a time and is variable-time ([`docs/LANGUAGE.md`](../docs/LANGUAGE.md#byte-search-indexofany-in-nishtext)). `tests/link/std_text_index_of_any*` are its programs |
|
|
14
14
|
| [`math.ts`](./math.ts) | `Math.tan`, `Math.atan2` and `Math.hypot` on `f64`, ported from fdlibm (`LICENSE-fdlibm`) so that every target, wasm included, answers alike without libm. A program never imports it: a call to one of the three loads it, and the compiler copies the functions the call reaches into the calling module as `internal` ones. JavaScript's answer for every NaN, signed zero and infinity, and within one ulp elsewhere (0.83, 0.84 and 0.93 ulp measured against mpmath). `tests/cases/math_std_edges` pins the special values |
|
|
15
|
+
| [`sort.ts`](./sort.ts) | `xs.sort(cmp)` on any array: `sortWith`, a stable merge sort over runs of 32 sorted by insertion — one scratch array released before it returns, a pair of runs already in order copied without merging, no bounds check left in it — so its order is element for element Node's `Array.prototype.sort`. Like `math.ts` it is one the compiler knows about: a program never imports it, a `.sort(cmp)` call loads it, the checker rewrites the call to `sortWith`, and each comparator's instantiation — the comparator called directly, no function pointer — is copied into the module that sorts. Under Node the call stays the platform's own. `tests/cases/arr_sort_cmp*` are its programs, a 10,000-element sort with ties among them |
|
|
15
16
|
| [`regex.ts`](./regex.ts) | Regular expressions in JavaScript's syntax with the `u` flag's strictness, matched by a Pike VM in time linear in the input whatever the pattern; finding every match is one search per match, so `findAll` and its kin can be quadratic when a long branch is preferred to a short one that wins ([`docs/security/regex.md`](../docs/security/regex.md)). `regexCompile(pattern, flags)` answers a `Regex` or the error text; `test`, `exec` into a reused `RegexMatch`, `find`, `findAll`, `count`, `replace` and `replaceAll` with `$&`, `$1` and `$<name>`, and `split`. Flags `i`, `m`, `s` and `u`; `i` folds by Unicode's simple case folding, ASCII letters only to ASCII. `\p{…}` and `\P{…}` take Unicode 16.0's General_Category, Script, Script_Extensions and binary properties by JavaScript's names, from tables `scripts/gen-regex-unicode.mjs` generates into the module and checks against Node's `RegExp`; backreferences and lookaround are refused at compile time. Offsets are UTF-8 bytes. A search allocates nothing beyond its answer: the thread lists and capture tables are the `Regex`'s, so one `Regex` serves one thread at a time. A leading literal is found with `indexOf`, a small leading set with `indexOfAny`. `tests/link/std_regex` and `tests/link/std_regex_unicode` check it against JavaScript's own answers |
|
|
16
17
|
| [`json.ts`](./json.ts) | `jsonField(object, name)`: the value of one field of one flat JSON object, which is the shape the compiler's own `--json` diagnostics have. A reader and not a parser — it answers text, answers `null` for a field that is not there, and does not validate. `JsonWriter` is the other direction: any JSON value written into a caller-owned `u8[]`, commas and colons included, byte for byte what `JSON.stringify` writes, and allocating nothing per call except an `f64`'s digits, a temporary string the call gives back before it returns (`text()` and `jsonStringifyString` build strings by design); misuse and a full buffer set a sticky negative `JSON_WRITE_*` code in `failed` rather than panicking. `setIndent(n)` and `setIndentTab()` write what `JSON.stringify(v, null, n)` or `(v, null, "\t")` writes, with no allocation for the indent, and `setStrict(true)` makes NaN and the infinities the sticky `JSON_WRITE_NON_FINITE` instead of `null`; both modes are off by default and kept by `reset`. `jsonStringifyString(s)` is the string rule answered as a string. `stringBytes(bytes, off, len)` and `keyBytes(bytes, off, len)` write a window of a byte array as `string` and `key` write a string of those bytes, allocating nothing, and refuse a window outside the array with `JSON_WRITE_BAD_WINDOW` |
|
|
17
18
|
| [`json-tokenizer.ts`](./json-tokenizer.ts) | `JsonTokenizer`: a validating, streaming tokenizer for RFC 8259 JSON held in a window of a `u8[]`. `next()` answers one `JSON_TOK_*` token at a time — object and array openers and closers, keys, strings, numbers and the three literals — then `JSON_TOK_END`, or a negative `JSON_TOK_ERR_*` code that sticks in `failed`, with the byte in `errorAt`. Strings are checked as UTF-8 and a lone surrogate escape is refused; `stringInto` decodes the current string into the caller's array and `keyEquals` compares it with a name, neither allocating. `numberF64` is correctly rounded; `isInteger` and `numberI64` read an integer that fits an `i64`, and `isU64` and `numberU64` one that fits a `u64`. `isIntegral` asks whether a number's value is whole however it is written (`1.0`, `1e2`, `1e400`), JSON Schema's "integer", from the text and at any exponent. `skipValue` steps over a value. `JsonLimits` caps nesting depth, string, number and total bytes, each with its own code; `reset` reuses the tokenizer, so a reused body keeps the arena flat. Duplicate keys are reported as tokens. No input panics and no byte outside the window is read; [`docs/security/json.md`](../docs/security/json.md) is its record, and `tests/link/std_json_tokenizer` runs JSONTestSuite and a seeded fuzz |
|
package/std/crypto/bcrypt.ts
CHANGED
|
@@ -1024,7 +1024,9 @@ const bcryptLoadSlot = (state: Secret<u32[]>, password: Secret<u8[]>, slot: i32)
|
|
|
1024
1024
|
// the lane count changed (bench/crypto/bcrypt/gen-body.mjs writes them), not
|
|
1025
1025
|
// one loop over a lane count: the lanes' l and r must live in registers and
|
|
1026
1026
|
// their loads be scheduled together, which a loop over an array of lanes
|
|
1027
|
-
// does not give.
|
|
1027
|
+
// does not give. Two lanes take each byte by its own shift and write every
|
|
1028
|
+
// lane's bytes before any lane's update, the form all widths had before the
|
|
1029
|
+
// rotated copy, which measured slower there.
|
|
1028
1030
|
|
|
1029
1031
|
/** `bcryptBody4`'s interleave on two lanes. */
|
|
1030
1032
|
const bcryptBody2 = (st: u32[]): void => {
|
|
@@ -1089,35 +1091,41 @@ const bcryptBody3 = (st: u32[]): void => {
|
|
|
1089
1091
|
l1 ^= st[1042]
|
|
1090
1092
|
l2 ^= st[2084]
|
|
1091
1093
|
for (let n: i32 = 1; n < 17; n += 2) {
|
|
1094
|
+
const l0e: u32 = ctSelect((l0 >>> 8) | (l0 << 24), 0xffffffff, 0)
|
|
1092
1095
|
const l0a: i32 = toI32(l0 >>> 24) & 0xff
|
|
1093
|
-
const l0b: i32 = toI32(
|
|
1094
|
-
const l0c: i32 = toI32(
|
|
1096
|
+
const l0b: i32 = toI32(l0e >>> 8) & 0xff
|
|
1097
|
+
const l0c: i32 = toI32(l0e) & 0xff
|
|
1095
1098
|
const l0d: i32 = toI32(l0) & 0xff
|
|
1099
|
+
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1100
|
+
const l1e: u32 = ctSelect((l1 >>> 8) | (l1 << 24), 0xffffffff, 0)
|
|
1096
1101
|
const l1a: i32 = toI32(l1 >>> 24) & 0xff
|
|
1097
|
-
const l1b: i32 = toI32(
|
|
1098
|
-
const l1c: i32 = toI32(
|
|
1102
|
+
const l1b: i32 = toI32(l1e >>> 8) & 0xff
|
|
1103
|
+
const l1c: i32 = toI32(l1e) & 0xff
|
|
1099
1104
|
const l1d: i32 = toI32(l1) & 0xff
|
|
1105
|
+
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1106
|
+
const l2e: u32 = ctSelect((l2 >>> 8) | (l2 << 24), 0xffffffff, 0)
|
|
1100
1107
|
const l2a: i32 = toI32(l2 >>> 24) & 0xff
|
|
1101
|
-
const l2b: i32 = toI32(
|
|
1102
|
-
const l2c: i32 = toI32(
|
|
1108
|
+
const l2b: i32 = toI32(l2e >>> 8) & 0xff
|
|
1109
|
+
const l2c: i32 = toI32(l2e) & 0xff
|
|
1103
1110
|
const l2d: i32 = toI32(l2) & 0xff
|
|
1104
|
-
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1105
|
-
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1106
1111
|
r2 ^= st[2084 + n] ^ (((st[2102 + l2a] + st[2358 + l2b]) ^ st[2614 + l2c]) + st[2870 + l2d])
|
|
1112
|
+
const r0e: u32 = ctSelect((r0 >>> 8) | (r0 << 24), 0xffffffff, 0)
|
|
1107
1113
|
const r0a: i32 = toI32(r0 >>> 24) & 0xff
|
|
1108
|
-
const r0b: i32 = toI32(
|
|
1109
|
-
const r0c: i32 = toI32(
|
|
1114
|
+
const r0b: i32 = toI32(r0e >>> 8) & 0xff
|
|
1115
|
+
const r0c: i32 = toI32(r0e) & 0xff
|
|
1110
1116
|
const r0d: i32 = toI32(r0) & 0xff
|
|
1117
|
+
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1118
|
+
const r1e: u32 = ctSelect((r1 >>> 8) | (r1 << 24), 0xffffffff, 0)
|
|
1111
1119
|
const r1a: i32 = toI32(r1 >>> 24) & 0xff
|
|
1112
|
-
const r1b: i32 = toI32(
|
|
1113
|
-
const r1c: i32 = toI32(
|
|
1120
|
+
const r1b: i32 = toI32(r1e >>> 8) & 0xff
|
|
1121
|
+
const r1c: i32 = toI32(r1e) & 0xff
|
|
1114
1122
|
const r1d: i32 = toI32(r1) & 0xff
|
|
1123
|
+
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1124
|
+
const r2e: u32 = ctSelect((r2 >>> 8) | (r2 << 24), 0xffffffff, 0)
|
|
1115
1125
|
const r2a: i32 = toI32(r2 >>> 24) & 0xff
|
|
1116
|
-
const r2b: i32 = toI32(
|
|
1117
|
-
const r2c: i32 = toI32(
|
|
1126
|
+
const r2b: i32 = toI32(r2e >>> 8) & 0xff
|
|
1127
|
+
const r2c: i32 = toI32(r2e) & 0xff
|
|
1118
1128
|
const r2d: i32 = toI32(r2) & 0xff
|
|
1119
|
-
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1120
|
-
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1121
1129
|
l2 ^= st[2084 + n + 1] ^ (((st[2102 + r2a] + st[2358 + r2b]) ^ st[2614 + r2c]) + st[2870 + r2d])
|
|
1122
1130
|
}
|
|
1123
1131
|
const t0: u32 = r0
|
|
@@ -1143,6 +1151,19 @@ const bcryptBody3 = (st: u32[]): void => {
|
|
|
1143
1151
|
* place, the four encryption chains interleaved round by round so that one
|
|
1144
1152
|
* lane's S-box loads overlap the others' instead of waiting on their own. The
|
|
1145
1153
|
* hot loop of the batch: 2^(cost+1) calls of 521 blocks per lane.
|
|
1154
|
+
*
|
|
1155
|
+
* Each lane's half-round is written whole, its bytes and then its update,
|
|
1156
|
+
* before the next lane's. The two middle index bytes come from one copy of the
|
|
1157
|
+
* word rotated right by 8 (`e`: byte 1 is its low byte, byte 2 its second),
|
|
1158
|
+
* behind the value barrier: `ctSelect(v, 0xffffffff, 0)` is `v`, opaque, so
|
|
1159
|
+
* LLVM cannot fold the two bytes back into two shifts of the word, and copies
|
|
1160
|
+
* it once instead of twice; on a BMI2 target the copy is one `rorx`. Three
|
|
1161
|
+
* and five lanes rotate the copy the same way; six shift it right by 8, which
|
|
1162
|
+
* has the same two low bytes and measured faster there. On a
|
|
1163
|
+
* Xeon Platinum 8260 that is 6% less time a hash at the best width, 9% under
|
|
1164
|
+
* `--cpu x86-64-v3` (docs/security/crypto-bcrypt.md, "Cascade Lake"). The
|
|
1165
|
+
* barrier is an identity on a register: it adds no branch and no load, and
|
|
1166
|
+
* the round reads the same four S-box words.
|
|
1146
1167
|
*/
|
|
1147
1168
|
const bcryptBody4 = (st: u32[]): void => {
|
|
1148
1169
|
if (st.length < 4168) {
|
|
@@ -1162,45 +1183,53 @@ const bcryptBody4 = (st: u32[]): void => {
|
|
|
1162
1183
|
l2 ^= st[2084]
|
|
1163
1184
|
l3 ^= st[3126]
|
|
1164
1185
|
for (let n: i32 = 1; n < 17; n += 2) {
|
|
1186
|
+
const l0e: u32 = ctSelect((l0 >>> 8) | (l0 << 24), 0xffffffff, 0)
|
|
1165
1187
|
const l0a: i32 = toI32(l0 >>> 24) & 0xff
|
|
1166
|
-
const l0b: i32 = toI32(
|
|
1167
|
-
const l0c: i32 = toI32(
|
|
1188
|
+
const l0b: i32 = toI32(l0e >>> 8) & 0xff
|
|
1189
|
+
const l0c: i32 = toI32(l0e) & 0xff
|
|
1168
1190
|
const l0d: i32 = toI32(l0) & 0xff
|
|
1191
|
+
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1192
|
+
const l1e: u32 = ctSelect((l1 >>> 8) | (l1 << 24), 0xffffffff, 0)
|
|
1169
1193
|
const l1a: i32 = toI32(l1 >>> 24) & 0xff
|
|
1170
|
-
const l1b: i32 = toI32(
|
|
1171
|
-
const l1c: i32 = toI32(
|
|
1194
|
+
const l1b: i32 = toI32(l1e >>> 8) & 0xff
|
|
1195
|
+
const l1c: i32 = toI32(l1e) & 0xff
|
|
1172
1196
|
const l1d: i32 = toI32(l1) & 0xff
|
|
1197
|
+
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1198
|
+
const l2e: u32 = ctSelect((l2 >>> 8) | (l2 << 24), 0xffffffff, 0)
|
|
1173
1199
|
const l2a: i32 = toI32(l2 >>> 24) & 0xff
|
|
1174
|
-
const l2b: i32 = toI32(
|
|
1175
|
-
const l2c: i32 = toI32(
|
|
1200
|
+
const l2b: i32 = toI32(l2e >>> 8) & 0xff
|
|
1201
|
+
const l2c: i32 = toI32(l2e) & 0xff
|
|
1176
1202
|
const l2d: i32 = toI32(l2) & 0xff
|
|
1203
|
+
r2 ^= st[2084 + n] ^ (((st[2102 + l2a] + st[2358 + l2b]) ^ st[2614 + l2c]) + st[2870 + l2d])
|
|
1204
|
+
const l3e: u32 = ctSelect((l3 >>> 8) | (l3 << 24), 0xffffffff, 0)
|
|
1177
1205
|
const l3a: i32 = toI32(l3 >>> 24) & 0xff
|
|
1178
|
-
const l3b: i32 = toI32(
|
|
1179
|
-
const l3c: i32 = toI32(
|
|
1206
|
+
const l3b: i32 = toI32(l3e >>> 8) & 0xff
|
|
1207
|
+
const l3c: i32 = toI32(l3e) & 0xff
|
|
1180
1208
|
const l3d: i32 = toI32(l3) & 0xff
|
|
1181
|
-
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1182
|
-
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1183
|
-
r2 ^= st[2084 + n] ^ (((st[2102 + l2a] + st[2358 + l2b]) ^ st[2614 + l2c]) + st[2870 + l2d])
|
|
1184
1209
|
r3 ^= st[3126 + n] ^ (((st[3144 + l3a] + st[3400 + l3b]) ^ st[3656 + l3c]) + st[3912 + l3d])
|
|
1210
|
+
const r0e: u32 = ctSelect((r0 >>> 8) | (r0 << 24), 0xffffffff, 0)
|
|
1185
1211
|
const r0a: i32 = toI32(r0 >>> 24) & 0xff
|
|
1186
|
-
const r0b: i32 = toI32(
|
|
1187
|
-
const r0c: i32 = toI32(
|
|
1212
|
+
const r0b: i32 = toI32(r0e >>> 8) & 0xff
|
|
1213
|
+
const r0c: i32 = toI32(r0e) & 0xff
|
|
1188
1214
|
const r0d: i32 = toI32(r0) & 0xff
|
|
1215
|
+
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1216
|
+
const r1e: u32 = ctSelect((r1 >>> 8) | (r1 << 24), 0xffffffff, 0)
|
|
1189
1217
|
const r1a: i32 = toI32(r1 >>> 24) & 0xff
|
|
1190
|
-
const r1b: i32 = toI32(
|
|
1191
|
-
const r1c: i32 = toI32(
|
|
1218
|
+
const r1b: i32 = toI32(r1e >>> 8) & 0xff
|
|
1219
|
+
const r1c: i32 = toI32(r1e) & 0xff
|
|
1192
1220
|
const r1d: i32 = toI32(r1) & 0xff
|
|
1221
|
+
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1222
|
+
const r2e: u32 = ctSelect((r2 >>> 8) | (r2 << 24), 0xffffffff, 0)
|
|
1193
1223
|
const r2a: i32 = toI32(r2 >>> 24) & 0xff
|
|
1194
|
-
const r2b: i32 = toI32(
|
|
1195
|
-
const r2c: i32 = toI32(
|
|
1224
|
+
const r2b: i32 = toI32(r2e >>> 8) & 0xff
|
|
1225
|
+
const r2c: i32 = toI32(r2e) & 0xff
|
|
1196
1226
|
const r2d: i32 = toI32(r2) & 0xff
|
|
1227
|
+
l2 ^= st[2084 + n + 1] ^ (((st[2102 + r2a] + st[2358 + r2b]) ^ st[2614 + r2c]) + st[2870 + r2d])
|
|
1228
|
+
const r3e: u32 = ctSelect((r3 >>> 8) | (r3 << 24), 0xffffffff, 0)
|
|
1197
1229
|
const r3a: i32 = toI32(r3 >>> 24) & 0xff
|
|
1198
|
-
const r3b: i32 = toI32(
|
|
1199
|
-
const r3c: i32 = toI32(
|
|
1230
|
+
const r3b: i32 = toI32(r3e >>> 8) & 0xff
|
|
1231
|
+
const r3c: i32 = toI32(r3e) & 0xff
|
|
1200
1232
|
const r3d: i32 = toI32(r3) & 0xff
|
|
1201
|
-
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1202
|
-
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1203
|
-
l2 ^= st[2084 + n + 1] ^ (((st[2102 + r2a] + st[2358 + r2b]) ^ st[2614 + r2c]) + st[2870 + r2d])
|
|
1204
1233
|
l3 ^= st[3126 + n + 1] ^ (((st[3144 + r3a] + st[3400 + r3b]) ^ st[3656 + r3c]) + st[3912 + r3d])
|
|
1205
1234
|
}
|
|
1206
1235
|
const t0: u32 = r0
|
|
@@ -1248,55 +1277,65 @@ const bcryptBody5 = (st: u32[]): void => {
|
|
|
1248
1277
|
l3 ^= st[3126]
|
|
1249
1278
|
l4 ^= st[4168]
|
|
1250
1279
|
for (let n: i32 = 1; n < 17; n += 2) {
|
|
1280
|
+
const l0e: u32 = ctSelect((l0 >>> 8) | (l0 << 24), 0xffffffff, 0)
|
|
1251
1281
|
const l0a: i32 = toI32(l0 >>> 24) & 0xff
|
|
1252
|
-
const l0b: i32 = toI32(
|
|
1253
|
-
const l0c: i32 = toI32(
|
|
1282
|
+
const l0b: i32 = toI32(l0e >>> 8) & 0xff
|
|
1283
|
+
const l0c: i32 = toI32(l0e) & 0xff
|
|
1254
1284
|
const l0d: i32 = toI32(l0) & 0xff
|
|
1285
|
+
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1286
|
+
const l1e: u32 = ctSelect((l1 >>> 8) | (l1 << 24), 0xffffffff, 0)
|
|
1255
1287
|
const l1a: i32 = toI32(l1 >>> 24) & 0xff
|
|
1256
|
-
const l1b: i32 = toI32(
|
|
1257
|
-
const l1c: i32 = toI32(
|
|
1288
|
+
const l1b: i32 = toI32(l1e >>> 8) & 0xff
|
|
1289
|
+
const l1c: i32 = toI32(l1e) & 0xff
|
|
1258
1290
|
const l1d: i32 = toI32(l1) & 0xff
|
|
1291
|
+
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1292
|
+
const l2e: u32 = ctSelect((l2 >>> 8) | (l2 << 24), 0xffffffff, 0)
|
|
1259
1293
|
const l2a: i32 = toI32(l2 >>> 24) & 0xff
|
|
1260
|
-
const l2b: i32 = toI32(
|
|
1261
|
-
const l2c: i32 = toI32(
|
|
1294
|
+
const l2b: i32 = toI32(l2e >>> 8) & 0xff
|
|
1295
|
+
const l2c: i32 = toI32(l2e) & 0xff
|
|
1262
1296
|
const l2d: i32 = toI32(l2) & 0xff
|
|
1297
|
+
r2 ^= st[2084 + n] ^ (((st[2102 + l2a] + st[2358 + l2b]) ^ st[2614 + l2c]) + st[2870 + l2d])
|
|
1298
|
+
const l3e: u32 = ctSelect((l3 >>> 8) | (l3 << 24), 0xffffffff, 0)
|
|
1263
1299
|
const l3a: i32 = toI32(l3 >>> 24) & 0xff
|
|
1264
|
-
const l3b: i32 = toI32(
|
|
1265
|
-
const l3c: i32 = toI32(
|
|
1300
|
+
const l3b: i32 = toI32(l3e >>> 8) & 0xff
|
|
1301
|
+
const l3c: i32 = toI32(l3e) & 0xff
|
|
1266
1302
|
const l3d: i32 = toI32(l3) & 0xff
|
|
1303
|
+
r3 ^= st[3126 + n] ^ (((st[3144 + l3a] + st[3400 + l3b]) ^ st[3656 + l3c]) + st[3912 + l3d])
|
|
1304
|
+
const l4e: u32 = ctSelect((l4 >>> 8) | (l4 << 24), 0xffffffff, 0)
|
|
1267
1305
|
const l4a: i32 = toI32(l4 >>> 24) & 0xff
|
|
1268
|
-
const l4b: i32 = toI32(
|
|
1269
|
-
const l4c: i32 = toI32(
|
|
1306
|
+
const l4b: i32 = toI32(l4e >>> 8) & 0xff
|
|
1307
|
+
const l4c: i32 = toI32(l4e) & 0xff
|
|
1270
1308
|
const l4d: i32 = toI32(l4) & 0xff
|
|
1271
|
-
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1272
|
-
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1273
|
-
r2 ^= st[2084 + n] ^ (((st[2102 + l2a] + st[2358 + l2b]) ^ st[2614 + l2c]) + st[2870 + l2d])
|
|
1274
|
-
r3 ^= st[3126 + n] ^ (((st[3144 + l3a] + st[3400 + l3b]) ^ st[3656 + l3c]) + st[3912 + l3d])
|
|
1275
1309
|
r4 ^= st[4168 + n] ^ (((st[4186 + l4a] + st[4442 + l4b]) ^ st[4698 + l4c]) + st[4954 + l4d])
|
|
1310
|
+
const r0e: u32 = ctSelect((r0 >>> 8) | (r0 << 24), 0xffffffff, 0)
|
|
1276
1311
|
const r0a: i32 = toI32(r0 >>> 24) & 0xff
|
|
1277
|
-
const r0b: i32 = toI32(
|
|
1278
|
-
const r0c: i32 = toI32(
|
|
1312
|
+
const r0b: i32 = toI32(r0e >>> 8) & 0xff
|
|
1313
|
+
const r0c: i32 = toI32(r0e) & 0xff
|
|
1279
1314
|
const r0d: i32 = toI32(r0) & 0xff
|
|
1315
|
+
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1316
|
+
const r1e: u32 = ctSelect((r1 >>> 8) | (r1 << 24), 0xffffffff, 0)
|
|
1280
1317
|
const r1a: i32 = toI32(r1 >>> 24) & 0xff
|
|
1281
|
-
const r1b: i32 = toI32(
|
|
1282
|
-
const r1c: i32 = toI32(
|
|
1318
|
+
const r1b: i32 = toI32(r1e >>> 8) & 0xff
|
|
1319
|
+
const r1c: i32 = toI32(r1e) & 0xff
|
|
1283
1320
|
const r1d: i32 = toI32(r1) & 0xff
|
|
1321
|
+
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1322
|
+
const r2e: u32 = ctSelect((r2 >>> 8) | (r2 << 24), 0xffffffff, 0)
|
|
1284
1323
|
const r2a: i32 = toI32(r2 >>> 24) & 0xff
|
|
1285
|
-
const r2b: i32 = toI32(
|
|
1286
|
-
const r2c: i32 = toI32(
|
|
1324
|
+
const r2b: i32 = toI32(r2e >>> 8) & 0xff
|
|
1325
|
+
const r2c: i32 = toI32(r2e) & 0xff
|
|
1287
1326
|
const r2d: i32 = toI32(r2) & 0xff
|
|
1327
|
+
l2 ^= st[2084 + n + 1] ^ (((st[2102 + r2a] + st[2358 + r2b]) ^ st[2614 + r2c]) + st[2870 + r2d])
|
|
1328
|
+
const r3e: u32 = ctSelect((r3 >>> 8) | (r3 << 24), 0xffffffff, 0)
|
|
1288
1329
|
const r3a: i32 = toI32(r3 >>> 24) & 0xff
|
|
1289
|
-
const r3b: i32 = toI32(
|
|
1290
|
-
const r3c: i32 = toI32(
|
|
1330
|
+
const r3b: i32 = toI32(r3e >>> 8) & 0xff
|
|
1331
|
+
const r3c: i32 = toI32(r3e) & 0xff
|
|
1291
1332
|
const r3d: i32 = toI32(r3) & 0xff
|
|
1333
|
+
l3 ^= st[3126 + n + 1] ^ (((st[3144 + r3a] + st[3400 + r3b]) ^ st[3656 + r3c]) + st[3912 + r3d])
|
|
1334
|
+
const r4e: u32 = ctSelect((r4 >>> 8) | (r4 << 24), 0xffffffff, 0)
|
|
1292
1335
|
const r4a: i32 = toI32(r4 >>> 24) & 0xff
|
|
1293
|
-
const r4b: i32 = toI32(
|
|
1294
|
-
const r4c: i32 = toI32(
|
|
1336
|
+
const r4b: i32 = toI32(r4e >>> 8) & 0xff
|
|
1337
|
+
const r4c: i32 = toI32(r4e) & 0xff
|
|
1295
1338
|
const r4d: i32 = toI32(r4) & 0xff
|
|
1296
|
-
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1297
|
-
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1298
|
-
l2 ^= st[2084 + n + 1] ^ (((st[2102 + r2a] + st[2358 + r2b]) ^ st[2614 + r2c]) + st[2870 + r2d])
|
|
1299
|
-
l3 ^= st[3126 + n + 1] ^ (((st[3144 + r3a] + st[3400 + r3b]) ^ st[3656 + r3c]) + st[3912 + r3d])
|
|
1300
1339
|
l4 ^= st[4168 + n + 1] ^ (((st[4186 + r4a] + st[4442 + r4b]) ^ st[4698 + r4c]) + st[4954 + r4d])
|
|
1301
1340
|
}
|
|
1302
1341
|
const t0: u32 = r0
|
|
@@ -1352,65 +1391,77 @@ const bcryptBody6 = (st: u32[]): void => {
|
|
|
1352
1391
|
l4 ^= st[4168]
|
|
1353
1392
|
l5 ^= st[5210]
|
|
1354
1393
|
for (let n: i32 = 1; n < 17; n += 2) {
|
|
1394
|
+
const l0e: u32 = ctSelect(l0 >>> 8, 0xffffffff, 0)
|
|
1355
1395
|
const l0a: i32 = toI32(l0 >>> 24) & 0xff
|
|
1356
|
-
const l0b: i32 = toI32(
|
|
1357
|
-
const l0c: i32 = toI32(
|
|
1396
|
+
const l0b: i32 = toI32(l0e >>> 8) & 0xff
|
|
1397
|
+
const l0c: i32 = toI32(l0e) & 0xff
|
|
1358
1398
|
const l0d: i32 = toI32(l0) & 0xff
|
|
1399
|
+
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1400
|
+
const l1e: u32 = ctSelect(l1 >>> 8, 0xffffffff, 0)
|
|
1359
1401
|
const l1a: i32 = toI32(l1 >>> 24) & 0xff
|
|
1360
|
-
const l1b: i32 = toI32(
|
|
1361
|
-
const l1c: i32 = toI32(
|
|
1402
|
+
const l1b: i32 = toI32(l1e >>> 8) & 0xff
|
|
1403
|
+
const l1c: i32 = toI32(l1e) & 0xff
|
|
1362
1404
|
const l1d: i32 = toI32(l1) & 0xff
|
|
1405
|
+
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1406
|
+
const l2e: u32 = ctSelect(l2 >>> 8, 0xffffffff, 0)
|
|
1363
1407
|
const l2a: i32 = toI32(l2 >>> 24) & 0xff
|
|
1364
|
-
const l2b: i32 = toI32(
|
|
1365
|
-
const l2c: i32 = toI32(
|
|
1408
|
+
const l2b: i32 = toI32(l2e >>> 8) & 0xff
|
|
1409
|
+
const l2c: i32 = toI32(l2e) & 0xff
|
|
1366
1410
|
const l2d: i32 = toI32(l2) & 0xff
|
|
1411
|
+
r2 ^= st[2084 + n] ^ (((st[2102 + l2a] + st[2358 + l2b]) ^ st[2614 + l2c]) + st[2870 + l2d])
|
|
1412
|
+
const l3e: u32 = ctSelect(l3 >>> 8, 0xffffffff, 0)
|
|
1367
1413
|
const l3a: i32 = toI32(l3 >>> 24) & 0xff
|
|
1368
|
-
const l3b: i32 = toI32(
|
|
1369
|
-
const l3c: i32 = toI32(
|
|
1414
|
+
const l3b: i32 = toI32(l3e >>> 8) & 0xff
|
|
1415
|
+
const l3c: i32 = toI32(l3e) & 0xff
|
|
1370
1416
|
const l3d: i32 = toI32(l3) & 0xff
|
|
1417
|
+
r3 ^= st[3126 + n] ^ (((st[3144 + l3a] + st[3400 + l3b]) ^ st[3656 + l3c]) + st[3912 + l3d])
|
|
1418
|
+
const l4e: u32 = ctSelect(l4 >>> 8, 0xffffffff, 0)
|
|
1371
1419
|
const l4a: i32 = toI32(l4 >>> 24) & 0xff
|
|
1372
|
-
const l4b: i32 = toI32(
|
|
1373
|
-
const l4c: i32 = toI32(
|
|
1420
|
+
const l4b: i32 = toI32(l4e >>> 8) & 0xff
|
|
1421
|
+
const l4c: i32 = toI32(l4e) & 0xff
|
|
1374
1422
|
const l4d: i32 = toI32(l4) & 0xff
|
|
1423
|
+
r4 ^= st[4168 + n] ^ (((st[4186 + l4a] + st[4442 + l4b]) ^ st[4698 + l4c]) + st[4954 + l4d])
|
|
1424
|
+
const l5e: u32 = ctSelect(l5 >>> 8, 0xffffffff, 0)
|
|
1375
1425
|
const l5a: i32 = toI32(l5 >>> 24) & 0xff
|
|
1376
|
-
const l5b: i32 = toI32(
|
|
1377
|
-
const l5c: i32 = toI32(
|
|
1426
|
+
const l5b: i32 = toI32(l5e >>> 8) & 0xff
|
|
1427
|
+
const l5c: i32 = toI32(l5e) & 0xff
|
|
1378
1428
|
const l5d: i32 = toI32(l5) & 0xff
|
|
1379
|
-
r0 ^= st[n] ^ (((st[18 + l0a] + st[274 + l0b]) ^ st[530 + l0c]) + st[786 + l0d])
|
|
1380
|
-
r1 ^= st[1042 + n] ^ (((st[1060 + l1a] + st[1316 + l1b]) ^ st[1572 + l1c]) + st[1828 + l1d])
|
|
1381
|
-
r2 ^= st[2084 + n] ^ (((st[2102 + l2a] + st[2358 + l2b]) ^ st[2614 + l2c]) + st[2870 + l2d])
|
|
1382
|
-
r3 ^= st[3126 + n] ^ (((st[3144 + l3a] + st[3400 + l3b]) ^ st[3656 + l3c]) + st[3912 + l3d])
|
|
1383
|
-
r4 ^= st[4168 + n] ^ (((st[4186 + l4a] + st[4442 + l4b]) ^ st[4698 + l4c]) + st[4954 + l4d])
|
|
1384
1429
|
r5 ^= st[5210 + n] ^ (((st[5228 + l5a] + st[5484 + l5b]) ^ st[5740 + l5c]) + st[5996 + l5d])
|
|
1430
|
+
const r0e: u32 = ctSelect(r0 >>> 8, 0xffffffff, 0)
|
|
1385
1431
|
const r0a: i32 = toI32(r0 >>> 24) & 0xff
|
|
1386
|
-
const r0b: i32 = toI32(
|
|
1387
|
-
const r0c: i32 = toI32(
|
|
1432
|
+
const r0b: i32 = toI32(r0e >>> 8) & 0xff
|
|
1433
|
+
const r0c: i32 = toI32(r0e) & 0xff
|
|
1388
1434
|
const r0d: i32 = toI32(r0) & 0xff
|
|
1435
|
+
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1436
|
+
const r1e: u32 = ctSelect(r1 >>> 8, 0xffffffff, 0)
|
|
1389
1437
|
const r1a: i32 = toI32(r1 >>> 24) & 0xff
|
|
1390
|
-
const r1b: i32 = toI32(
|
|
1391
|
-
const r1c: i32 = toI32(
|
|
1438
|
+
const r1b: i32 = toI32(r1e >>> 8) & 0xff
|
|
1439
|
+
const r1c: i32 = toI32(r1e) & 0xff
|
|
1392
1440
|
const r1d: i32 = toI32(r1) & 0xff
|
|
1441
|
+
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1442
|
+
const r2e: u32 = ctSelect(r2 >>> 8, 0xffffffff, 0)
|
|
1393
1443
|
const r2a: i32 = toI32(r2 >>> 24) & 0xff
|
|
1394
|
-
const r2b: i32 = toI32(
|
|
1395
|
-
const r2c: i32 = toI32(
|
|
1444
|
+
const r2b: i32 = toI32(r2e >>> 8) & 0xff
|
|
1445
|
+
const r2c: i32 = toI32(r2e) & 0xff
|
|
1396
1446
|
const r2d: i32 = toI32(r2) & 0xff
|
|
1447
|
+
l2 ^= st[2084 + n + 1] ^ (((st[2102 + r2a] + st[2358 + r2b]) ^ st[2614 + r2c]) + st[2870 + r2d])
|
|
1448
|
+
const r3e: u32 = ctSelect(r3 >>> 8, 0xffffffff, 0)
|
|
1397
1449
|
const r3a: i32 = toI32(r3 >>> 24) & 0xff
|
|
1398
|
-
const r3b: i32 = toI32(
|
|
1399
|
-
const r3c: i32 = toI32(
|
|
1450
|
+
const r3b: i32 = toI32(r3e >>> 8) & 0xff
|
|
1451
|
+
const r3c: i32 = toI32(r3e) & 0xff
|
|
1400
1452
|
const r3d: i32 = toI32(r3) & 0xff
|
|
1453
|
+
l3 ^= st[3126 + n + 1] ^ (((st[3144 + r3a] + st[3400 + r3b]) ^ st[3656 + r3c]) + st[3912 + r3d])
|
|
1454
|
+
const r4e: u32 = ctSelect(r4 >>> 8, 0xffffffff, 0)
|
|
1401
1455
|
const r4a: i32 = toI32(r4 >>> 24) & 0xff
|
|
1402
|
-
const r4b: i32 = toI32(
|
|
1403
|
-
const r4c: i32 = toI32(
|
|
1456
|
+
const r4b: i32 = toI32(r4e >>> 8) & 0xff
|
|
1457
|
+
const r4c: i32 = toI32(r4e) & 0xff
|
|
1404
1458
|
const r4d: i32 = toI32(r4) & 0xff
|
|
1459
|
+
l4 ^= st[4168 + n + 1] ^ (((st[4186 + r4a] + st[4442 + r4b]) ^ st[4698 + r4c]) + st[4954 + r4d])
|
|
1460
|
+
const r5e: u32 = ctSelect(r5 >>> 8, 0xffffffff, 0)
|
|
1405
1461
|
const r5a: i32 = toI32(r5 >>> 24) & 0xff
|
|
1406
|
-
const r5b: i32 = toI32(
|
|
1407
|
-
const r5c: i32 = toI32(
|
|
1462
|
+
const r5b: i32 = toI32(r5e >>> 8) & 0xff
|
|
1463
|
+
const r5c: i32 = toI32(r5e) & 0xff
|
|
1408
1464
|
const r5d: i32 = toI32(r5) & 0xff
|
|
1409
|
-
l0 ^= st[n + 1] ^ (((st[18 + r0a] + st[274 + r0b]) ^ st[530 + r0c]) + st[786 + r0d])
|
|
1410
|
-
l1 ^= st[1042 + n + 1] ^ (((st[1060 + r1a] + st[1316 + r1b]) ^ st[1572 + r1c]) + st[1828 + r1d])
|
|
1411
|
-
l2 ^= st[2084 + n + 1] ^ (((st[2102 + r2a] + st[2358 + r2b]) ^ st[2614 + r2c]) + st[2870 + r2d])
|
|
1412
|
-
l3 ^= st[3126 + n + 1] ^ (((st[3144 + r3a] + st[3400 + r3b]) ^ st[3656 + r3c]) + st[3912 + r3d])
|
|
1413
|
-
l4 ^= st[4168 + n + 1] ^ (((st[4186 + r4a] + st[4442 + r4b]) ^ st[4698 + r4c]) + st[4954 + r4d])
|
|
1414
1465
|
l5 ^= st[5210 + n + 1] ^ (((st[5228 + r5a] + st[5484 + r5b]) ^ st[5740 + r5c]) + st[5996 + r5d])
|
|
1415
1466
|
}
|
|
1416
1467
|
const t0: u32 = r0
|
package/std/sort.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `std/sort` — `xs.sort(cmp)` on an array, in Nish: a stable merge sort,
|
|
3
|
+
* compiled once per comparator.
|
|
4
|
+
*
|
|
5
|
+
* A program does not import this module. A `.sort(cmp)` call is what loads it
|
|
6
|
+
* (the checker's `importSort`), and the checker routes the call to `sortWith`
|
|
7
|
+
* here. `cmp` is a compile-time function parameter, so each comparator is an
|
|
8
|
+
* instantiation of its own whose body calls the comparator directly — there is
|
|
9
|
+
* no function pointer. Under Node and `tsc` the call is the platform's
|
|
10
|
+
* `Array.prototype.sort`, so nothing here runs there.
|
|
11
|
+
*
|
|
12
|
+
* **Same order as Node.** `Array.prototype.sort` is stable (ES2019), so for a
|
|
13
|
+
* comparator that is a consistent total preorder there is exactly one answer,
|
|
14
|
+
* and any stable sort gives it. A comparator's result is read only as "greater
|
|
15
|
+
* than zero or not": a later element moves before an earlier one only when
|
|
16
|
+
* the comparator answers a positive number for (earlier, later), so a negative
|
|
17
|
+
* zero and NaN are zero, as Node treats them.
|
|
18
|
+
*
|
|
19
|
+
* **Shape.** The array is copied once into a scratch array of the same
|
|
20
|
+
* length, the only allocation, which the function's arena scope gives back
|
|
21
|
+
* before it returns, so a sort leaves `Arena.used()` where it was. Runs of
|
|
22
|
+
* `RUN` are sorted by insertion from the scratch into the array (a strictly
|
|
23
|
+
* descending run is copied reversed instead), then merged
|
|
24
|
+
* bottom-up, alternating between the two, and copied back once if the last
|
|
25
|
+
* pass ended in the scratch. A pair of runs already in order is copied without
|
|
26
|
+
* a merge. Every merge takes from the left run on a tie, which is what makes
|
|
27
|
+
* it stable.
|
|
28
|
+
*
|
|
29
|
+
* **No element is held across a write.** An `interface` element is stored
|
|
30
|
+
* inline, and `const v = xs[i]` is a pointer into the array, so an insertion
|
|
31
|
+
* sort in place would overwrite the element it is inserting. Every step here
|
|
32
|
+
* reads from one array and writes the other, and moves a whole slot, which for
|
|
33
|
+
* an inline record is one copy of its bytes.
|
|
34
|
+
*
|
|
35
|
+
* **Proofs.** Every index is proven in range by the guard written beside it,
|
|
36
|
+
* so no access keeps its bounds check. The run arithmetic wraps only where
|
|
37
|
+
* the operands are proven to lie in `0..n`, so it cannot wrap: a difference
|
|
38
|
+
* of two of them, or a sum taken only when it stays below `n`.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { wrappingAdd, wrappingSub } from "nish:unsafe"
|
|
42
|
+
|
|
43
|
+
/** The length of the runs insertion sort makes before the first merge. */
|
|
44
|
+
const RUN: i32 = 32
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* `lo + step`, or `n` when that is not below `n`. Every caller has
|
|
48
|
+
* `0 <= lo <= n`, so `n - lo` cannot wrap, and the sum is taken only below `n`.
|
|
49
|
+
*/
|
|
50
|
+
const stepTo = (lo: i32, step: i32, n: i32): i32 => (wrappingSub(n, lo) > step ? wrappingAdd(lo, step) : n)
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* `src[lo..hi)` sorted by insertion into `dst[lo..hi)`. The comparator call
|
|
54
|
+
* forgets every array length, so each access after it repeats its guard.
|
|
55
|
+
*/
|
|
56
|
+
const insertionRun = <T>(src: T[], dst: T[], cmp: (a: T, b: T) => number, lo: i32, hi: i32): void => {
|
|
57
|
+
// A strictly descending run is copied reversed: no two of its elements are
|
|
58
|
+
// equal, so reversing it keeps the sort stable, and costs one comparison each.
|
|
59
|
+
// `lo < hi`, and `d` steps only while below `hi`, so neither `+ 1` wraps.
|
|
60
|
+
let d = wrappingAdd(lo, 1)
|
|
61
|
+
while (d > 0 && d < hi && d < toI32(src.length)) {
|
|
62
|
+
const p = d - 1
|
|
63
|
+
if (!(cmp(src[p], src[d]) > 0)) {
|
|
64
|
+
break
|
|
65
|
+
}
|
|
66
|
+
d = wrappingAdd(d, 1)
|
|
67
|
+
}
|
|
68
|
+
if (d >= hi) {
|
|
69
|
+
// `hi > lo >= 0`, so `hi - 1` does not wrap, and `r` steps down only from `r >= 0`.
|
|
70
|
+
let r = wrappingSub(hi, 1)
|
|
71
|
+
for (let k: i32 = lo; k >= 0 && k < hi && k < toI32(dst.length) && r >= 0 && r < toI32(src.length); k++) {
|
|
72
|
+
dst[k] = src[r]
|
|
73
|
+
r = wrappingSub(r, 1)
|
|
74
|
+
}
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
for (let i: i32 = lo; i >= 0 && i < hi; i++) {
|
|
78
|
+
let j = i
|
|
79
|
+
while (j > lo && j > 0 && j < toI32(dst.length) && i < toI32(src.length)) {
|
|
80
|
+
const k = j - 1
|
|
81
|
+
if (!(cmp(dst[k], src[i]) > 0) || k < 0 || k >= toI32(dst.length) || j >= toI32(dst.length)) {
|
|
82
|
+
break
|
|
83
|
+
}
|
|
84
|
+
dst[j] = dst[k]
|
|
85
|
+
j = k
|
|
86
|
+
}
|
|
87
|
+
if (i < toI32(src.length) && j >= 0 && j < toI32(dst.length)) {
|
|
88
|
+
dst[j] = src[i]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** `src[lo..hi)` copied into `dst[lo..hi)`. */
|
|
94
|
+
const copyRun = <T>(src: T[], dst: T[], lo: i32, hi: i32): void => {
|
|
95
|
+
for (let k: i32 = lo; k >= 0 && k < hi && k < toI32(src.length) && k < toI32(dst.length); k++) {
|
|
96
|
+
dst[k] = src[k]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The sorted runs `src[lo..mid)` and `src[mid..hi)` merged into `dst[lo..hi)`,
|
|
102
|
+
* or copied when the last of the left run is not after the first of the right.
|
|
103
|
+
*/
|
|
104
|
+
const mergeRuns = <T>(src: T[], dst: T[], cmp: (a: T, b: T) => number, lo: i32, mid: i32, hi: i32): void => {
|
|
105
|
+
if (mid > 0 && mid < hi && mid < toI32(src.length)) {
|
|
106
|
+
const last = mid - 1
|
|
107
|
+
if (last < toI32(src.length) && !(cmp(src[last], src[mid]) > 0)) {
|
|
108
|
+
copyRun(src, dst, lo, hi)
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
let i = lo
|
|
113
|
+
let j = mid
|
|
114
|
+
for (let k: i32 = lo; k >= 0 && k < hi; k++) {
|
|
115
|
+
let right = i >= mid
|
|
116
|
+
if (!right && j < hi && i >= 0 && i < toI32(src.length) && j >= 0 && j < toI32(src.length)) {
|
|
117
|
+
right = cmp(src[i], src[j]) > 0
|
|
118
|
+
}
|
|
119
|
+
if (right) {
|
|
120
|
+
if (j >= 0 && j < toI32(src.length) && k < toI32(dst.length)) {
|
|
121
|
+
dst[k] = src[j]
|
|
122
|
+
}
|
|
123
|
+
// `j` steps at most `hi - mid` times from `mid`, so it stays at most `hi`.
|
|
124
|
+
j = wrappingAdd(j, 1)
|
|
125
|
+
} else {
|
|
126
|
+
if (i >= 0 && i < toI32(src.length) && k < toI32(dst.length)) {
|
|
127
|
+
dst[k] = src[i]
|
|
128
|
+
}
|
|
129
|
+
// `i` steps at most `mid - lo` times from `lo`, so it stays at most `mid`.
|
|
130
|
+
i = wrappingAdd(i, 1)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** One bottom-up pass: every pair of adjacent `width`-runs of `src` merged into `dst`. */
|
|
136
|
+
const mergePass = <T>(src: T[], dst: T[], cmp: (a: T, b: T) => number, n: i32, width: i32): void => {
|
|
137
|
+
let lo: i32 = 0
|
|
138
|
+
while (lo >= 0 && lo < n) {
|
|
139
|
+
const mid = stepTo(lo, width, n)
|
|
140
|
+
const hi = stepTo(mid, width, n)
|
|
141
|
+
mergeRuns(src, dst, cmp, lo, mid, hi)
|
|
142
|
+
lo = hi
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** `xs` sorted in place by `cmp`, stably, and answered: what `xs.sort(cmp)` compiles to. */
|
|
147
|
+
export const sortWith = <T>(xs: T[], cmp: (a: T, b: T) => number): T[] => {
|
|
148
|
+
const n: i32 = toI32(xs.length)
|
|
149
|
+
if (n < 2) {
|
|
150
|
+
return xs
|
|
151
|
+
}
|
|
152
|
+
// One allocation at full size, every slot written before any is read: the
|
|
153
|
+
// checker lets this `new Array<T>(n)` hold any `T`, and neither emitter
|
|
154
|
+
// zero-fills it (`isSortInstance`).
|
|
155
|
+
const tmp = new Array<T>(n)
|
|
156
|
+
copyRun(xs, tmp, 0, n)
|
|
157
|
+
let lo: i32 = 0
|
|
158
|
+
while (lo >= 0 && lo < n) {
|
|
159
|
+
const hi = stepTo(lo, RUN, n)
|
|
160
|
+
insertionRun(tmp, xs, cmp, lo, hi)
|
|
161
|
+
lo = hi
|
|
162
|
+
}
|
|
163
|
+
let inTmp = false
|
|
164
|
+
let width: i32 = RUN
|
|
165
|
+
while (width > 0 && width < n) {
|
|
166
|
+
if (inTmp) {
|
|
167
|
+
mergePass(tmp, xs, cmp, n, width)
|
|
168
|
+
} else {
|
|
169
|
+
mergePass(xs, tmp, cmp, n, width)
|
|
170
|
+
}
|
|
171
|
+
inTmp = !inTmp
|
|
172
|
+
width = stepTo(width, width, n)
|
|
173
|
+
}
|
|
174
|
+
if (inTmp) {
|
|
175
|
+
copyRun(tmp, xs, 0, n)
|
|
176
|
+
}
|
|
177
|
+
return xs
|
|
178
|
+
}
|