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()