3

Additional requirements:

  • Input of the function are two numbers, not necessarily integers

  • Speed is the major concern; it should be as fast as possible

  • Doesn't have to be secure, as long as its output looks sufficiently random.

Examples:

getValue(0,0) -> 0.326458921
getValue(100,30) -> 0.598713621
getValue(5.12687, 600.471536) -> 0.21458796

Edit To clarify: the output values should be deterministic, but random-looking.

user1542912
  • 106
  • 5
  • 4
    To clarify; are you looking for a hash function? – Oliver Charlesworth Jul 21 '12 at 16:33
  • I think so. But I want it to output a value uniformly distributed between 0 and 1. – user1542912 Jul 21 '12 at 16:36
  • 1
    What have you tried and where are you stuck? We wont just do the coding for you! – Sirko Jul 21 '12 at 16:37
  • Are you familiar with `Math.random()`? What do the two numbers have to do with anything? – Pointy Jul 21 '12 at 16:39
  • @Pointy: That won't help if the OP is looking for a deterministic mapping. – Oliver Charlesworth Jul 21 '12 at 16:40
  • Exactly, I'm looking for a deterministic mapping. @sirko: I was thinking of just using one of the 'famous' hash functions and scaling the output to a number between 0 and 1. But the fact that my function doesn't need to be secure should make it possible to have a more efficient implementation, right? – user1542912 Jul 21 '12 at 16:43
  • Are there limits on the input? And what about Pointy's second question: what do the two numbers have to do with anything? What are they? – Jonathan M Jul 21 '12 at 16:45
  • @JonathanM: The input numbers are coordinates on a 2d-map. I want the map to be infinitively large and infinitively 'zoomable', so no limits on the input. The output of the function should be deterministic, but randomly looking. – user1542912 Jul 21 '12 at 16:49
  • @user1542912, OK, and what's the purpose of the hashed value? – Jonathan M Jul 21 '12 at 16:50
  • @JonathanM: It will be used in further algorithms to generate terrain. It's important that the values are deterministic, so that the terrain is always the same at the same coordinates. – user1542912 Jul 21 '12 at 16:56
  • 1
    @user1542912, sounds like you're wanting not only deterministic algorithm, but a unique result for each input set. – Jonathan M Jul 21 '12 at 17:02
  • 1
    Yes - I don't think the word "random" has a place here :-) – Pointy Jul 21 '12 at 17:03
  • @Pointy I think "random-looking" means http://en.wikipedia.org/wiki/Avalanche_effect – Esailija Jul 21 '12 at 17:24
  • Maybe, although it also might be desired that adjacent points in the plain map to values that are close together. It's just unclear. – Pointy Jul 21 '12 at 17:27
  • Esailija has it right. I don't want adjacent points to have any correlation. I'm sorry if I was not very clear; I don't know how else I could have phrased my question. – user1542912 Jul 21 '12 at 17:30

3 Answers3

0

Don't know if this fits your needs, this is just an idea I had spontaneously (using a JavaScript implementation of Java's String.hashCode(), taken from this website: http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/)

<script>
    String.prototype.hashCode = function(){
        var hash = 0;
        if (this.length == 0) return hash;
        for (i = 0; i < this.length; i++) {
            char = this.charCodeAt(i);
            hash = ((hash<<5)-hash)+char;
            hash = hash & hash; // Convert to 32bit integer
        }
        return hash;
    }

    function hash(x, y) {
        var hash = Math.abs((x + "" + y).hashCode())
        return hash / Math.pow(10, (hash + "").length);
    }

    alert(hash(5.12687, 600.471536));
</script>
Aletheios
  • 3,960
  • 2
  • 33
  • 46
0

You can write a hash function :

function hash(x, y) {
    // You cast the int parts and decimal parts of your entries as 16-bits signed integers.
    var xi = x & 0xFFFF;
    var xf = (((x-xi) * (1 << 16)) & 0xFFFF);
    var yi = y & 0xFFFF;
    var yf = (((y-yi) * (1 << 16)) & 0xFFFF);

    // You hash theses numbers
    var r1 = ((39769 * xi) & 0xFFFF);
    r1 = ((r1 + xf) * 23747) & 0xFFFF;
    r1 = ((r1 + yi) * 19073) & 0xFFFF;
    r1 = ((r1 + yf) * 25609) & 0xFFFF;

    var r2 = ((25609 * xf) & 0xFFFF);
    r2 = ((r2 + yf) * 39769) & 0xFFFF;
    r2 = ((r2 + xi) * 23747) & 0xFFFF;
    r2 = ((r2 + yi) * 19073) & 0xFFFF;

    // And returns a floating number between 0 and 1.
    return ((r1&0xFF)/(1<<24)) + ((r2&0xFFFF)/(1<<16));
}

This function wrap each 65536, as I only keep the first 16 bits of the int part, but the idea is here, you can modify the hash function. A much better way would be :

var arrayBuffer = new ArrayBuffer(8);
var dataView = new DataView(arrayBuffer);

function hash(x, y) {
    dataView.setFloat32(0, x);
    dataView.setFloat32(4, y);

    var xi = dataView.getUint16(0);
    var xf = dataView.getUint16(2);
    var yi = dataView.getUint16(4);
    var yf = dataView.getUint16(6);

    // You hash theses numbers
    var r1 = ((39769 * xi) & 0xFFFF);
    r1 = ((r1 + xf) * 23747) & 0xFFFF;
    r1 = ((r1 + yi) * 19073) & 0xFFFF;
    r1 = ((r1 + yf) * 25609) & 0xFFFF;

    var r2 = ((25609 * xf) & 0xFFFF);
    r2 = ((r2 + yf) * 39769) & 0xFFFF;
    r2 = ((r2 + xi) * 23747) & 0xFFFF;
    r2 = ((r2 + yi) * 19073) & 0xFFFF;

    // And returns a floating number between 0 and 1.
    dataView.setUint16(0, r1);
    dataView.setUint16(2, r2);
    return Math.abs(dataView.getFloat32(0) % 1);
}

This last method use WebGL TypedArray, which lets you have access to bits of your entries, and have a way better hash. But, from my experience, this is really slower (800 millions calls/sec for the first method on my computer, only 2 millions for the second one - for information, the classic random function is 200 millions calls/sec), and WebGL may not be available on all browsers.

Ilod
  • 146
  • 2
  • Thanks for your answer! Can you point me to a good resource explaining this kind of algorithms? Where do the numbers 39769, 23747,... come from? – user1542912 Jul 27 '12 at 08:50
  • At least when the output is quantized to 0-255 integer range (for outputting a color), it seems to have rather short and obvious pattern: http://jsfiddle.net/aTuGs/2/ :( – Tapio Oct 08 '12 at 07:01
0
unsigned int hash(int key) {
    key +=~(key << 15);
    key ^=(key >> 10);
    key +=(key << 3);
    key ^=(key >> 6);
    key +=~(key << 11);
    key ^=(key >> 16);
    return key;
}

unsigned int localseed = hash(x^hash(y^baseSeed));

This uses a baseSeed value, but that's optional. Basically creates a hash from x/y coordinates.

roach374
  • 61
  • 1
  • 6