function split2D(width, height) {
const { random } = Math;
const flip = () => random() < 0.5;
function splitHalf(w, h, source, target, offset) {
const left = w >> 1;
const right = w - left;
let lNumerator = 0,
rNumerator = 0;
const denominator = right < left ? right : left;
let i = offset,
j = offset + left * h,
k = offset;
const end = offset + w * h;
while (k < end) {
lNumerator += left;
rNumerator += right;
while (lNumerator >= denominator) {
target[i++] = source[k++];
lNumerator -= denominator;
}
while (rNumerator >= denominator) {
target[j++] = source[k++];
rNumerator -= denominator;
}
}
return left;
}
function divide(x, y, w, h, source, target, offset) {
if (w === 1 && h === 1) {
indices[x + y * width] = source[offset];
} else if (w > h) {
const left = splitHalf(w, h, source, target, offset);
const right = w - left;
divide(x, y, left, h, target, source, offset);
divide(x + left, y, right, h, target, source, offset + left * h);
} else {
const top = splitHalf(h, w, source, target, offset);
const bottom = h - top;
divide(x, y, w, top, target, source, offset);
divide(x, y + top, w, bottom, target, source, offset + top * w);
}
}
const indices = new Int32Array(width * height);
const buffer = new Int32Array(width * height * 2);
const source0 = buffer.subarray(0, width * height);
const target0 = buffer.subarray(width * height, width * height * 2);
for (let i = 0; i < width * height; i++) source0[i] = i;
divide(0, 0, width, height, source0, target0, 0);
return indices;
}