Hashing / Randomizing using (long, long) as input

How can I pseudo-generate random numbers having a (long, long) as input?

I want the random number generator to generate the same numbers with the same seeds, of course, so I get the same random number when calling it with (1, 1) twice.

I’ve tried something like this:


long rand(long x, long y) {
    final long a = 2147483647177471651L; // Didn't know any other big primes... should have been prime
    final long b = 9223372036854775783L; // Biggest 63-bit prime
    final long c = 1858404738118378471L; // Random number
    final long d = 1592548884139547179L; // Random numbers
    return ((a * x + b * y + c) ^ d);
}

but that gave me bad results when simply out-putting it to an image:

well the easiest way would be to use the standard Random class:

new Random(long1^long2).getLong();

But if you do not want to use the standard Random Class then you can use a Multiply With Carry PRNG… http://en.wikipedia.org/wiki/Multiply-with-carry It even has some C code that you can just port to Java.

Don’t try to write your own hash functions or random number generators. I don’t have time to throw together a code snippet ATM, but you can do the following: break the 2 64-bit inputs into 4 32-bit, hash with mumurhash 2…this allows computing the initial 4 part in parallel which goes to a final cascade. Then feed that to a 32 bit XorShift (there a code for that on this site). Or if you need 64-bit output, use Jenkins to hash and feed to a 64-bit XorShift (also code on this site).

XORing two numbers is high correlated.

Opps…just relooked at your snippet. Skip the XorShift part…just return Jenkins.

Sigh. I guess I’m off my game today…what I had in mind was a hash by Wang:


public final static long hashWang(long key)
{
  key = (~key) + (key << 21); // key = (key << 21) - key - 1;
  key = key ^ (key >>> 24);
  key = (key + (key << 3)) + (key << 8); // key * 265
  key = key ^ (key >>> 14);
  key = (key + (key << 2)) + (key << 4); // key * 21
  key = key ^ (key >>> 28);
  key = key + (key << 31);

  return key;
}

This is probably much higher quality that you need, so it could probably replace with a cheaper function. What’s this to be used for? Do you really want 64-bit integer result?

the only people who should write hashing/crypto algorithms are mathematicians.

use existing code D:

Thank you very much, Roquen, this worked out very well! :slight_smile:

I love simplex noise. Now also without pregenerating, but simply “asking” for a noise value at a given point (for learning, probably for using too, when performance is not needed):

Food for thought. Note that you’re doing massive overkill. You’re ultimately generating a float, so no need for a 64-bit hash. The wang hash is excellent (by today’s standards) and you only really need mediocre hash functions for noise functions (how good depends on which noise we’re talking about). Also since you’re only generating one random number per hash…just use the hash as the random number.

I don’t know any hash functions…

What would be an example of a medicore hash function? :slight_smile:

Depends on what you are using it for. For game noise and even hashing for hash tables, you want something fast and good enough. For simulation you want something fast, and good statistical properties. For crytography you want it to be as close as practical to a random oracle model and one way. Speed is a distant 3rd.

Rule one: for cryto get an official one. Never do your own.

Otherwise doing your own is quite practical but perhaps a little bit of a waste of time. For simulation my rng that i posted here, is many times faster than MT( a crap rng for simulations seriously) and has extra statistical properties over both MT and java.util.Random(), and faster than both. I said that already.

For games you can get away with a lot. A common one for 2 numbers is something like

result=(a*x+b)*y+c

with primes a,b,c. This can be extended for any number of numbers. This will give some “patterns” but for the most part is not too bad. The * are not really that expensive compared to moving all the data around. Then you can just use bitshift mixing functions(aka the wang example), both conditional and non conditional shifts. There are lots around the web for that, with different values of good. Most are for hash table stuff but work non the less. There are some that are optimized for the old Shader langs as well. These often use small lookup tables combined with the above examples. Some use nested lookups

results=randTable[(randTable[x&0xff]+y)&0xff];

. But i have never bothered since there is a small number space for that.

A bad function would be

result=x+y;

Since we get a linear relationship between both values, and close input results in close output. Typically we want it to be more random.

delt0r’s suggesting is reasonable. For my 2D simplex noise I use the downright abysmal:


  return ((y<<8)^(x)) * 0xB5262C85;

This does have noticeable defects, but I’ve only seen them when zoomed out far enough that the result is white noise…so farther than is useful. It’s possible that I just haven’t noticed them at lower scales however.

Whatever hash you use, you can do the following:


final float value00 = ((hash(cellX0, cellY0) >> 31) & 2) - 1;

and if you’re using a good to excellent hashing function, you can skip on the shift.