kenqtade's picture
Use ken-q org namespace for project Spaces
0865492
Raw
History Blame Contribute Delete
23.9 kB
/**
* BLAKE3 Compression Function - Highly Optimized
*
* Optimization techniques applied (from Fleek Network case study):
* 1. Use 16 SMI variables for state instead of TypedArray
* 2. Use 16 SMI variables for message words
* 3. Fully inlined G function (no function call overhead)
* 4. Use `| 0` for integer coercion (forces V8 to use 32-bit ALU)
* 5. Hardcoded permutation swaps using only 2 temporary variables
* 6. Offset-based access pattern (avoid creating new views)
*
* The compression function takes:
* - cv: 8-word chaining value
* - block: 16-word message block (64 bytes)
* - counter: 64-bit block counter
* - blockLen: number of input bytes in this block
* - flags: domain separation flags
*
* And outputs 8 or 16 words depending on whether this is a root node.
*/
/**
* Compress a single block.
*
* This is the hot path - every optimization matters here.
*
* @param cv - Chaining value array
* @param cvOff - Offset into cv
* @param block - Message block words
* @param blockOff - Offset into block
* @param out - Output array (8 or 16 words)
* @param outOff - Offset into out
* @param full - If true, output all 16 words (for XOF); if false, output 8 words
* @param counter - 64-bit block counter
* @param blockLen - Number of bytes in this block (0-64)
* @param flags - Domain separation flags
*/
export function compress(
cv: Uint32Array,
cvOff: number,
block: Uint32Array,
blockOff: number,
out: Uint32Array,
outOff: number,
full: boolean,
counter: number,
blockLen: number,
flags: number,
): void {
// Load message words into SMI variables for maximum performance
// V8 optimizes SMI arithmetic directly with the ALU
let m0 = block[blockOff] | 0;
let m1 = block[blockOff + 1] | 0;
let m2 = block[blockOff + 2] | 0;
let m3 = block[blockOff + 3] | 0;
let m4 = block[blockOff + 4] | 0;
let m5 = block[blockOff + 5] | 0;
let m6 = block[blockOff + 6] | 0;
let m7 = block[blockOff + 7] | 0;
let m8 = block[blockOff + 8] | 0;
let m9 = block[blockOff + 9] | 0;
let m10 = block[blockOff + 10] | 0;
let m11 = block[blockOff + 11] | 0;
let m12 = block[blockOff + 12] | 0;
let m13 = block[blockOff + 13] | 0;
let m14 = block[blockOff + 14] | 0;
let m15 = block[blockOff + 15] | 0;
// Initialize state: first 8 words from chaining value
let s0 = cv[cvOff] | 0;
let s1 = cv[cvOff + 1] | 0;
let s2 = cv[cvOff + 2] | 0;
let s3 = cv[cvOff + 3] | 0;
let s4 = cv[cvOff + 4] | 0;
let s5 = cv[cvOff + 5] | 0;
let s6 = cv[cvOff + 6] | 0;
let s7 = cv[cvOff + 7] | 0;
// Words 8-11: IV constants
let s8 = 0x6a09e667;
let s9 = 0xbb67ae85;
let s10 = 0x3c6ef372;
let s11 = 0xa54ff53a;
// Words 12-15: counter, blockLen, flags
// Note: counter is 64-bit, split into low and high 32-bit words
let s12 = counter | 0;
let s13 = (counter / 0x100000000) | 0;
let s14 = blockLen | 0;
let s15 = flags | 0;
// ============================================================
// 7 rounds of mixing
// Each round consists of 4 column G functions and 4 diagonal G functions
// followed by a message word permutation (except for round 7)
// ============================================================
// ROUND 1 (message schedule: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
// Column G functions
// G(0, 4, 8, 12) with m0, m1
s0 = (((s0 + s4) | 0) + m0) | 0;
s12 ^= s0;
s12 = (s12 >>> 16) | (s12 << 16);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 12) | (s4 << 20);
s0 = (((s0 + s4) | 0) + m1) | 0;
s12 ^= s0;
s12 = (s12 >>> 8) | (s12 << 24);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 7) | (s4 << 25);
// G(1, 5, 9, 13) with m2, m3
s1 = (((s1 + s5) | 0) + m2) | 0;
s13 ^= s1;
s13 = (s13 >>> 16) | (s13 << 16);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 12) | (s5 << 20);
s1 = (((s1 + s5) | 0) + m3) | 0;
s13 ^= s1;
s13 = (s13 >>> 8) | (s13 << 24);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 7) | (s5 << 25);
// G(2, 6, 10, 14) with m4, m5
s2 = (((s2 + s6) | 0) + m4) | 0;
s14 ^= s2;
s14 = (s14 >>> 16) | (s14 << 16);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 12) | (s6 << 20);
s2 = (((s2 + s6) | 0) + m5) | 0;
s14 ^= s2;
s14 = (s14 >>> 8) | (s14 << 24);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 7) | (s6 << 25);
// G(3, 7, 11, 15) with m6, m7
s3 = (((s3 + s7) | 0) + m6) | 0;
s15 ^= s3;
s15 = (s15 >>> 16) | (s15 << 16);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 12) | (s7 << 20);
s3 = (((s3 + s7) | 0) + m7) | 0;
s15 ^= s3;
s15 = (s15 >>> 8) | (s15 << 24);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 7) | (s7 << 25);
// Diagonal G functions
// G(0, 5, 10, 15) with m8, m9
s0 = (((s0 + s5) | 0) + m8) | 0;
s15 ^= s0;
s15 = (s15 >>> 16) | (s15 << 16);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 12) | (s5 << 20);
s0 = (((s0 + s5) | 0) + m9) | 0;
s15 ^= s0;
s15 = (s15 >>> 8) | (s15 << 24);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 7) | (s5 << 25);
// G(1, 6, 11, 12) with m10, m11
s1 = (((s1 + s6) | 0) + m10) | 0;
s12 ^= s1;
s12 = (s12 >>> 16) | (s12 << 16);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 12) | (s6 << 20);
s1 = (((s1 + s6) | 0) + m11) | 0;
s12 ^= s1;
s12 = (s12 >>> 8) | (s12 << 24);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 7) | (s6 << 25);
// G(2, 7, 8, 13) with m12, m13
s2 = (((s2 + s7) | 0) + m12) | 0;
s13 ^= s2;
s13 = (s13 >>> 16) | (s13 << 16);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 12) | (s7 << 20);
s2 = (((s2 + s7) | 0) + m13) | 0;
s13 ^= s2;
s13 = (s13 >>> 8) | (s13 << 24);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 7) | (s7 << 25);
// G(3, 4, 9, 14) with m14, m15
s3 = (((s3 + s4) | 0) + m14) | 0;
s14 ^= s3;
s14 = (s14 >>> 16) | (s14 << 16);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 12) | (s4 << 20);
s3 = (((s3 + s4) | 0) + m15) | 0;
s14 ^= s3;
s14 = (s14 >>> 8) | (s14 << 24);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 7) | (s4 << 25);
// Permute message words for round 2
// Permutation: [2,6,3,10,7,0,4,13,1,11,12,5,9,14,15,8]
// Using 2 temps for the two cycles in the permutation
{
const t0 = m0,
t1 = m1;
m0 = m2;
m2 = m3;
m3 = m10;
m10 = m12;
m12 = m9;
m9 = m11;
m11 = m5;
m5 = t0;
m1 = m6;
m6 = m4;
m4 = m7;
m7 = m13;
m13 = m14;
m14 = m15;
m15 = m8;
m8 = t1;
}
// ROUND 2 (message schedule: 2,6,3,10,7,0,4,13,1,11,12,5,9,14,15,8)
s0 = (((s0 + s4) | 0) + m0) | 0;
s12 ^= s0;
s12 = (s12 >>> 16) | (s12 << 16);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 12) | (s4 << 20);
s0 = (((s0 + s4) | 0) + m1) | 0;
s12 ^= s0;
s12 = (s12 >>> 8) | (s12 << 24);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 7) | (s4 << 25);
s1 = (((s1 + s5) | 0) + m2) | 0;
s13 ^= s1;
s13 = (s13 >>> 16) | (s13 << 16);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 12) | (s5 << 20);
s1 = (((s1 + s5) | 0) + m3) | 0;
s13 ^= s1;
s13 = (s13 >>> 8) | (s13 << 24);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 7) | (s5 << 25);
s2 = (((s2 + s6) | 0) + m4) | 0;
s14 ^= s2;
s14 = (s14 >>> 16) | (s14 << 16);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 12) | (s6 << 20);
s2 = (((s2 + s6) | 0) + m5) | 0;
s14 ^= s2;
s14 = (s14 >>> 8) | (s14 << 24);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 7) | (s6 << 25);
s3 = (((s3 + s7) | 0) + m6) | 0;
s15 ^= s3;
s15 = (s15 >>> 16) | (s15 << 16);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 12) | (s7 << 20);
s3 = (((s3 + s7) | 0) + m7) | 0;
s15 ^= s3;
s15 = (s15 >>> 8) | (s15 << 24);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 7) | (s7 << 25);
s0 = (((s0 + s5) | 0) + m8) | 0;
s15 ^= s0;
s15 = (s15 >>> 16) | (s15 << 16);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 12) | (s5 << 20);
s0 = (((s0 + s5) | 0) + m9) | 0;
s15 ^= s0;
s15 = (s15 >>> 8) | (s15 << 24);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 7) | (s5 << 25);
s1 = (((s1 + s6) | 0) + m10) | 0;
s12 ^= s1;
s12 = (s12 >>> 16) | (s12 << 16);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 12) | (s6 << 20);
s1 = (((s1 + s6) | 0) + m11) | 0;
s12 ^= s1;
s12 = (s12 >>> 8) | (s12 << 24);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 7) | (s6 << 25);
s2 = (((s2 + s7) | 0) + m12) | 0;
s13 ^= s2;
s13 = (s13 >>> 16) | (s13 << 16);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 12) | (s7 << 20);
s2 = (((s2 + s7) | 0) + m13) | 0;
s13 ^= s2;
s13 = (s13 >>> 8) | (s13 << 24);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 7) | (s7 << 25);
s3 = (((s3 + s4) | 0) + m14) | 0;
s14 ^= s3;
s14 = (s14 >>> 16) | (s14 << 16);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 12) | (s4 << 20);
s3 = (((s3 + s4) | 0) + m15) | 0;
s14 ^= s3;
s14 = (s14 >>> 8) | (s14 << 24);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 7) | (s4 << 25);
// Permute for round 3
{
const t0 = m0,
t1 = m1;
m0 = m2;
m2 = m3;
m3 = m10;
m10 = m12;
m12 = m9;
m9 = m11;
m11 = m5;
m5 = t0;
m1 = m6;
m6 = m4;
m4 = m7;
m7 = m13;
m13 = m14;
m14 = m15;
m15 = m8;
m8 = t1;
}
// ROUND 3 (message schedule: 3,4,10,12,13,2,7,14,6,5,9,0,11,15,8,1)
s0 = (((s0 + s4) | 0) + m0) | 0;
s12 ^= s0;
s12 = (s12 >>> 16) | (s12 << 16);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 12) | (s4 << 20);
s0 = (((s0 + s4) | 0) + m1) | 0;
s12 ^= s0;
s12 = (s12 >>> 8) | (s12 << 24);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 7) | (s4 << 25);
s1 = (((s1 + s5) | 0) + m2) | 0;
s13 ^= s1;
s13 = (s13 >>> 16) | (s13 << 16);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 12) | (s5 << 20);
s1 = (((s1 + s5) | 0) + m3) | 0;
s13 ^= s1;
s13 = (s13 >>> 8) | (s13 << 24);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 7) | (s5 << 25);
s2 = (((s2 + s6) | 0) + m4) | 0;
s14 ^= s2;
s14 = (s14 >>> 16) | (s14 << 16);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 12) | (s6 << 20);
s2 = (((s2 + s6) | 0) + m5) | 0;
s14 ^= s2;
s14 = (s14 >>> 8) | (s14 << 24);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 7) | (s6 << 25);
s3 = (((s3 + s7) | 0) + m6) | 0;
s15 ^= s3;
s15 = (s15 >>> 16) | (s15 << 16);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 12) | (s7 << 20);
s3 = (((s3 + s7) | 0) + m7) | 0;
s15 ^= s3;
s15 = (s15 >>> 8) | (s15 << 24);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 7) | (s7 << 25);
s0 = (((s0 + s5) | 0) + m8) | 0;
s15 ^= s0;
s15 = (s15 >>> 16) | (s15 << 16);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 12) | (s5 << 20);
s0 = (((s0 + s5) | 0) + m9) | 0;
s15 ^= s0;
s15 = (s15 >>> 8) | (s15 << 24);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 7) | (s5 << 25);
s1 = (((s1 + s6) | 0) + m10) | 0;
s12 ^= s1;
s12 = (s12 >>> 16) | (s12 << 16);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 12) | (s6 << 20);
s1 = (((s1 + s6) | 0) + m11) | 0;
s12 ^= s1;
s12 = (s12 >>> 8) | (s12 << 24);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 7) | (s6 << 25);
s2 = (((s2 + s7) | 0) + m12) | 0;
s13 ^= s2;
s13 = (s13 >>> 16) | (s13 << 16);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 12) | (s7 << 20);
s2 = (((s2 + s7) | 0) + m13) | 0;
s13 ^= s2;
s13 = (s13 >>> 8) | (s13 << 24);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 7) | (s7 << 25);
s3 = (((s3 + s4) | 0) + m14) | 0;
s14 ^= s3;
s14 = (s14 >>> 16) | (s14 << 16);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 12) | (s4 << 20);
s3 = (((s3 + s4) | 0) + m15) | 0;
s14 ^= s3;
s14 = (s14 >>> 8) | (s14 << 24);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 7) | (s4 << 25);
// Permute for round 4
{
const t0 = m0,
t1 = m1;
m0 = m2;
m2 = m3;
m3 = m10;
m10 = m12;
m12 = m9;
m9 = m11;
m11 = m5;
m5 = t0;
m1 = m6;
m6 = m4;
m4 = m7;
m7 = m13;
m13 = m14;
m14 = m15;
m15 = m8;
m8 = t1;
}
// ROUND 4 (message schedule: 10,7,12,9,14,3,13,15,4,0,11,2,5,8,1,6)
s0 = (((s0 + s4) | 0) + m0) | 0;
s12 ^= s0;
s12 = (s12 >>> 16) | (s12 << 16);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 12) | (s4 << 20);
s0 = (((s0 + s4) | 0) + m1) | 0;
s12 ^= s0;
s12 = (s12 >>> 8) | (s12 << 24);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 7) | (s4 << 25);
s1 = (((s1 + s5) | 0) + m2) | 0;
s13 ^= s1;
s13 = (s13 >>> 16) | (s13 << 16);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 12) | (s5 << 20);
s1 = (((s1 + s5) | 0) + m3) | 0;
s13 ^= s1;
s13 = (s13 >>> 8) | (s13 << 24);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 7) | (s5 << 25);
s2 = (((s2 + s6) | 0) + m4) | 0;
s14 ^= s2;
s14 = (s14 >>> 16) | (s14 << 16);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 12) | (s6 << 20);
s2 = (((s2 + s6) | 0) + m5) | 0;
s14 ^= s2;
s14 = (s14 >>> 8) | (s14 << 24);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 7) | (s6 << 25);
s3 = (((s3 + s7) | 0) + m6) | 0;
s15 ^= s3;
s15 = (s15 >>> 16) | (s15 << 16);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 12) | (s7 << 20);
s3 = (((s3 + s7) | 0) + m7) | 0;
s15 ^= s3;
s15 = (s15 >>> 8) | (s15 << 24);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 7) | (s7 << 25);
s0 = (((s0 + s5) | 0) + m8) | 0;
s15 ^= s0;
s15 = (s15 >>> 16) | (s15 << 16);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 12) | (s5 << 20);
s0 = (((s0 + s5) | 0) + m9) | 0;
s15 ^= s0;
s15 = (s15 >>> 8) | (s15 << 24);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 7) | (s5 << 25);
s1 = (((s1 + s6) | 0) + m10) | 0;
s12 ^= s1;
s12 = (s12 >>> 16) | (s12 << 16);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 12) | (s6 << 20);
s1 = (((s1 + s6) | 0) + m11) | 0;
s12 ^= s1;
s12 = (s12 >>> 8) | (s12 << 24);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 7) | (s6 << 25);
s2 = (((s2 + s7) | 0) + m12) | 0;
s13 ^= s2;
s13 = (s13 >>> 16) | (s13 << 16);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 12) | (s7 << 20);
s2 = (((s2 + s7) | 0) + m13) | 0;
s13 ^= s2;
s13 = (s13 >>> 8) | (s13 << 24);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 7) | (s7 << 25);
s3 = (((s3 + s4) | 0) + m14) | 0;
s14 ^= s3;
s14 = (s14 >>> 16) | (s14 << 16);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 12) | (s4 << 20);
s3 = (((s3 + s4) | 0) + m15) | 0;
s14 ^= s3;
s14 = (s14 >>> 8) | (s14 << 24);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 7) | (s4 << 25);
// Permute for round 5
{
const t0 = m0,
t1 = m1;
m0 = m2;
m2 = m3;
m3 = m10;
m10 = m12;
m12 = m9;
m9 = m11;
m11 = m5;
m5 = t0;
m1 = m6;
m6 = m4;
m4 = m7;
m7 = m13;
m13 = m14;
m14 = m15;
m15 = m8;
m8 = t1;
}
// ROUND 5 (message schedule: 12,13,9,11,15,10,14,8,7,2,5,3,0,1,6,4)
s0 = (((s0 + s4) | 0) + m0) | 0;
s12 ^= s0;
s12 = (s12 >>> 16) | (s12 << 16);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 12) | (s4 << 20);
s0 = (((s0 + s4) | 0) + m1) | 0;
s12 ^= s0;
s12 = (s12 >>> 8) | (s12 << 24);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 7) | (s4 << 25);
s1 = (((s1 + s5) | 0) + m2) | 0;
s13 ^= s1;
s13 = (s13 >>> 16) | (s13 << 16);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 12) | (s5 << 20);
s1 = (((s1 + s5) | 0) + m3) | 0;
s13 ^= s1;
s13 = (s13 >>> 8) | (s13 << 24);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 7) | (s5 << 25);
s2 = (((s2 + s6) | 0) + m4) | 0;
s14 ^= s2;
s14 = (s14 >>> 16) | (s14 << 16);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 12) | (s6 << 20);
s2 = (((s2 + s6) | 0) + m5) | 0;
s14 ^= s2;
s14 = (s14 >>> 8) | (s14 << 24);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 7) | (s6 << 25);
s3 = (((s3 + s7) | 0) + m6) | 0;
s15 ^= s3;
s15 = (s15 >>> 16) | (s15 << 16);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 12) | (s7 << 20);
s3 = (((s3 + s7) | 0) + m7) | 0;
s15 ^= s3;
s15 = (s15 >>> 8) | (s15 << 24);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 7) | (s7 << 25);
s0 = (((s0 + s5) | 0) + m8) | 0;
s15 ^= s0;
s15 = (s15 >>> 16) | (s15 << 16);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 12) | (s5 << 20);
s0 = (((s0 + s5) | 0) + m9) | 0;
s15 ^= s0;
s15 = (s15 >>> 8) | (s15 << 24);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 7) | (s5 << 25);
s1 = (((s1 + s6) | 0) + m10) | 0;
s12 ^= s1;
s12 = (s12 >>> 16) | (s12 << 16);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 12) | (s6 << 20);
s1 = (((s1 + s6) | 0) + m11) | 0;
s12 ^= s1;
s12 = (s12 >>> 8) | (s12 << 24);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 7) | (s6 << 25);
s2 = (((s2 + s7) | 0) + m12) | 0;
s13 ^= s2;
s13 = (s13 >>> 16) | (s13 << 16);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 12) | (s7 << 20);
s2 = (((s2 + s7) | 0) + m13) | 0;
s13 ^= s2;
s13 = (s13 >>> 8) | (s13 << 24);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 7) | (s7 << 25);
s3 = (((s3 + s4) | 0) + m14) | 0;
s14 ^= s3;
s14 = (s14 >>> 16) | (s14 << 16);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 12) | (s4 << 20);
s3 = (((s3 + s4) | 0) + m15) | 0;
s14 ^= s3;
s14 = (s14 >>> 8) | (s14 << 24);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 7) | (s4 << 25);
// Permute for round 6
{
const t0 = m0,
t1 = m1;
m0 = m2;
m2 = m3;
m3 = m10;
m10 = m12;
m12 = m9;
m9 = m11;
m11 = m5;
m5 = t0;
m1 = m6;
m6 = m4;
m4 = m7;
m7 = m13;
m13 = m14;
m14 = m15;
m15 = m8;
m8 = t1;
}
// ROUND 6 (message schedule: 9,14,11,5,8,12,15,1,13,3,0,10,2,6,4,7)
s0 = (((s0 + s4) | 0) + m0) | 0;
s12 ^= s0;
s12 = (s12 >>> 16) | (s12 << 16);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 12) | (s4 << 20);
s0 = (((s0 + s4) | 0) + m1) | 0;
s12 ^= s0;
s12 = (s12 >>> 8) | (s12 << 24);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 7) | (s4 << 25);
s1 = (((s1 + s5) | 0) + m2) | 0;
s13 ^= s1;
s13 = (s13 >>> 16) | (s13 << 16);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 12) | (s5 << 20);
s1 = (((s1 + s5) | 0) + m3) | 0;
s13 ^= s1;
s13 = (s13 >>> 8) | (s13 << 24);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 7) | (s5 << 25);
s2 = (((s2 + s6) | 0) + m4) | 0;
s14 ^= s2;
s14 = (s14 >>> 16) | (s14 << 16);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 12) | (s6 << 20);
s2 = (((s2 + s6) | 0) + m5) | 0;
s14 ^= s2;
s14 = (s14 >>> 8) | (s14 << 24);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 7) | (s6 << 25);
s3 = (((s3 + s7) | 0) + m6) | 0;
s15 ^= s3;
s15 = (s15 >>> 16) | (s15 << 16);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 12) | (s7 << 20);
s3 = (((s3 + s7) | 0) + m7) | 0;
s15 ^= s3;
s15 = (s15 >>> 8) | (s15 << 24);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 7) | (s7 << 25);
s0 = (((s0 + s5) | 0) + m8) | 0;
s15 ^= s0;
s15 = (s15 >>> 16) | (s15 << 16);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 12) | (s5 << 20);
s0 = (((s0 + s5) | 0) + m9) | 0;
s15 ^= s0;
s15 = (s15 >>> 8) | (s15 << 24);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 7) | (s5 << 25);
s1 = (((s1 + s6) | 0) + m10) | 0;
s12 ^= s1;
s12 = (s12 >>> 16) | (s12 << 16);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 12) | (s6 << 20);
s1 = (((s1 + s6) | 0) + m11) | 0;
s12 ^= s1;
s12 = (s12 >>> 8) | (s12 << 24);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 7) | (s6 << 25);
s2 = (((s2 + s7) | 0) + m12) | 0;
s13 ^= s2;
s13 = (s13 >>> 16) | (s13 << 16);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 12) | (s7 << 20);
s2 = (((s2 + s7) | 0) + m13) | 0;
s13 ^= s2;
s13 = (s13 >>> 8) | (s13 << 24);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 7) | (s7 << 25);
s3 = (((s3 + s4) | 0) + m14) | 0;
s14 ^= s3;
s14 = (s14 >>> 16) | (s14 << 16);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 12) | (s4 << 20);
s3 = (((s3 + s4) | 0) + m15) | 0;
s14 ^= s3;
s14 = (s14 >>> 8) | (s14 << 24);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 7) | (s4 << 25);
// Permute for round 7
{
const t0 = m0,
t1 = m1;
m0 = m2;
m2 = m3;
m3 = m10;
m10 = m12;
m12 = m9;
m9 = m11;
m11 = m5;
m5 = t0;
m1 = m6;
m6 = m4;
m4 = m7;
m7 = m13;
m13 = m14;
m14 = m15;
m15 = m8;
m8 = t1;
}
// ROUND 7 (message schedule: 11,15,5,0,1,9,8,6,14,10,2,12,3,4,7,13)
s0 = (((s0 + s4) | 0) + m0) | 0;
s12 ^= s0;
s12 = (s12 >>> 16) | (s12 << 16);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 12) | (s4 << 20);
s0 = (((s0 + s4) | 0) + m1) | 0;
s12 ^= s0;
s12 = (s12 >>> 8) | (s12 << 24);
s8 = (s8 + s12) | 0;
s4 ^= s8;
s4 = (s4 >>> 7) | (s4 << 25);
s1 = (((s1 + s5) | 0) + m2) | 0;
s13 ^= s1;
s13 = (s13 >>> 16) | (s13 << 16);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 12) | (s5 << 20);
s1 = (((s1 + s5) | 0) + m3) | 0;
s13 ^= s1;
s13 = (s13 >>> 8) | (s13 << 24);
s9 = (s9 + s13) | 0;
s5 ^= s9;
s5 = (s5 >>> 7) | (s5 << 25);
s2 = (((s2 + s6) | 0) + m4) | 0;
s14 ^= s2;
s14 = (s14 >>> 16) | (s14 << 16);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 12) | (s6 << 20);
s2 = (((s2 + s6) | 0) + m5) | 0;
s14 ^= s2;
s14 = (s14 >>> 8) | (s14 << 24);
s10 = (s10 + s14) | 0;
s6 ^= s10;
s6 = (s6 >>> 7) | (s6 << 25);
s3 = (((s3 + s7) | 0) + m6) | 0;
s15 ^= s3;
s15 = (s15 >>> 16) | (s15 << 16);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 12) | (s7 << 20);
s3 = (((s3 + s7) | 0) + m7) | 0;
s15 ^= s3;
s15 = (s15 >>> 8) | (s15 << 24);
s11 = (s11 + s15) | 0;
s7 ^= s11;
s7 = (s7 >>> 7) | (s7 << 25);
s0 = (((s0 + s5) | 0) + m8) | 0;
s15 ^= s0;
s15 = (s15 >>> 16) | (s15 << 16);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 12) | (s5 << 20);
s0 = (((s0 + s5) | 0) + m9) | 0;
s15 ^= s0;
s15 = (s15 >>> 8) | (s15 << 24);
s10 = (s10 + s15) | 0;
s5 ^= s10;
s5 = (s5 >>> 7) | (s5 << 25);
s1 = (((s1 + s6) | 0) + m10) | 0;
s12 ^= s1;
s12 = (s12 >>> 16) | (s12 << 16);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 12) | (s6 << 20);
s1 = (((s1 + s6) | 0) + m11) | 0;
s12 ^= s1;
s12 = (s12 >>> 8) | (s12 << 24);
s11 = (s11 + s12) | 0;
s6 ^= s11;
s6 = (s6 >>> 7) | (s6 << 25);
s2 = (((s2 + s7) | 0) + m12) | 0;
s13 ^= s2;
s13 = (s13 >>> 16) | (s13 << 16);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 12) | (s7 << 20);
s2 = (((s2 + s7) | 0) + m13) | 0;
s13 ^= s2;
s13 = (s13 >>> 8) | (s13 << 24);
s8 = (s8 + s13) | 0;
s7 ^= s8;
s7 = (s7 >>> 7) | (s7 << 25);
s3 = (((s3 + s4) | 0) + m14) | 0;
s14 ^= s3;
s14 = (s14 >>> 16) | (s14 << 16);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 12) | (s4 << 20);
s3 = (((s3 + s4) | 0) + m15) | 0;
s14 ^= s3;
s14 = (s14 >>> 8) | (s14 << 24);
s9 = (s9 + s14) | 0;
s4 ^= s9;
s4 = (s4 >>> 7) | (s4 << 25);
// ============================================================
// Final XOR and output
// ============================================================
// If full output needed (XOF mode), write words 8-15 first
// (written first in case out === cv)
if (full) {
out[outOff + 8] = s8 ^ cv[cvOff];
out[outOff + 9] = s9 ^ cv[cvOff + 1];
out[outOff + 10] = s10 ^ cv[cvOff + 2];
out[outOff + 11] = s11 ^ cv[cvOff + 3];
out[outOff + 12] = s12 ^ cv[cvOff + 4];
out[outOff + 13] = s13 ^ cv[cvOff + 5];
out[outOff + 14] = s14 ^ cv[cvOff + 6];
out[outOff + 15] = s15 ^ cv[cvOff + 7];
}
// Standard output: XOR state[0..7] with state[8..15]
out[outOff] = s0 ^ s8;
out[outOff + 1] = s1 ^ s9;
out[outOff + 2] = s2 ^ s10;
out[outOff + 3] = s3 ^ s11;
out[outOff + 4] = s4 ^ s12;
out[outOff + 5] = s5 ^ s13;
out[outOff + 6] = s6 ^ s14;
out[outOff + 7] = s7 ^ s15;
}