Invertible Xor Rotate
JavaScript
const rot32 = (x, i) => (x << i)|(x >>> (32-i));
function xor_rot2(x, a, b) {
return x ^ rot32(x,a) ^ rot32(x,b);
}
function xor_rot2_inv(x, a, b) {
// Perform the five steps (and keep 'a' and 'b' in range given
// how 'rot' is defined above) as a sequence of transforms.
// The order reversed of above (products of powers of M commute).
x = xor_rot2(x,a,b); a = (a+a) & 0x1f; b = (b+b) & 0x1f; // t0 = M x
x = xor_rot2(x,a,b); a = (a+a) & 0x1f; b = (b+b) & 0x1f; // t1 = M^2 t0
x = xor_rot2(x,a,b); a = (a+a) & 0x1f; b = (b+b) & 0x1f; // t2 = M^4 t1
x = xor_rot2(x,a,b); a = (a+a) & 0x1f; b = (b+b) & 0x1f; // t3 = M^8 t2
x = xor_rot2(x,a,b); // x' = M^16 t3
return x;
}
const u31 = 256 * 256 * 256 * 128
const getRand = () => (Math.random() * u31)
const p = (x, l) => x.toFixed().padStart(l)
function run(x, a, b) {
const t = xor_rot2(x, a, b)
const r = xor_rot2_inv(t, a, b)
const d = r - x
console.log(`${p(x,10)} ${p(a,2)} ${p(b,2)} = ${p(t,10)} = ${p(r, 10)} :: ${d.toFixed()}`)
}
function runRand() {
const x = getRand()
const a = getRand() & 31
const b = getRand() & 31
const i = a > b
return run(x, i ? b : a, i ? a : b)
}
function runTimes(c = 10) {
for (let i = 0; i < c; i++) runRand()
}
run(471490377, 6, 13)
runTimes()