I have a use case where I need to scramble an input in such a way that:
- Each specific input always maps to a specific pseudo-random output.
- The output must shuffle the input sufficiently so that an incrementing input maps to a pseudo-random output.
For example, if the input is 64 bits, there must be exactly 2^64 unique outputs, and these must break incrementing inputs as much as possible (arbitrary requirement).
I will code this in C#, but can translate from Java or C, so long as there are not SIMD intrinsics. What I am looking for is some already existing code, rather than reinventing the wheel.
I have looked on Google, but haven’t found anything that does a 1:1 mapping.
This seems to work fairly well:
You can change the constants to whatever as long as
multiplieris odd andmulinv_multiplieris the modular multiplicative inverse (see wiki:modular multiplicative inverse or Hackers Delight 10-15 Exact Division by Constants) ofmultiplier(modulo 2^64, obviously – and that’s whymultiplierhas to be odd, otherwise it has no inverse).The offset can be anything, but make it relatively prime with 2^64 just to be on the safe side.
These specific constants come from Knuths linear congruential generator.
There’s one small thing: it puts the complement of the LSB of the input in the LSB of the result. If that’s a problem, you could just rotate it by any nonzero amount.
For 32 bits, the constants can be
multiplier = 0x4c957f2d,offset = 0xf767814f,mulinv_multiplier = 0x329e28a5.For 64 bits,
multiplier = 12790229573962758597,mulinv_multiplier = 16500474117902441741may work better.Or, you could use a CRC, which is reversible for this use (ie the input is the same size as the CRC) for CRC64 it requires some modifications of course.