The function Álvaro describes is a
hash function. A hash function maps one input value (or set of values) to a value within a fixed range; ie, mapping a set of 2D, 3D or other coordinates to a single 8-bit, 16-bit, or 32-bit value.
Many hashing functions operate on the same principle as a
Linear Congruential Generator (LCG) pseudo-random generator. In the past, many built-in random number generators for various systems have been implemented using an LCG. The idea of an LCG is to take some starting value (in fixed-state systems, the seed) and multiply it by some special number, then add another special number. If the numbers are chosen correctly, the output sequence appears to be random. When using an LCG to hash a value instead of store a seed as internal state somewhere, you pass the value into the function and use that value where the seed is normally used. The function then becomes a hash that maps this input state (seed) to a seemingly-random output value.
If the input is more complicated than a single value (such as a set of input coordinates) then the input values are commonly folded together into a single value, then that value is hashed to an output value.
Another commonly used tool when hashing integral values is the XOR operator. When you XOR two integral values, wherever the corresponding bits in the operands are different, a 1 bit is generated in the output value; otherwise a 0 bit is generated. By XOR-ing a value with some number, the effect is to sort of 'mix' the bits up in a predictable and deterministic fashion, with the output result having a seemingly-random appearance. This is the trick that Álvaro uses in places in his hash function.
The problem with XOR-ing alone, though, is that while at first glance the output might seem random-enough, there are in truth patterns generated in the output, and when doing Perlin noise you really want to avoid patterns. So the above hash function doesn't rely on a single XOR, but rather mixes XOR with LCG-like behavior (multiplying by specially chosen numbers) as well as some bit-shifting. The whole point of all of this is to get a really good mix or churn on the input bit pattern, and to hopefully remove any semblance of a visual pattern when the hash is used to generate noise.
If you study the reference implementation for Perlin noise, you can see a different form of hashing at work, one which uses a look-up table. Essentially you use the input value to look up a value in a table; the table is shuffled, adding an element of randomness to the look-up. Since look-up tables take up memory, the reference implementation folds the input coordinate state down so that it falls in the range [0,511] and the output hash is an 8-bit value in the range [0,255].
There is no one way to implement a hash. But a good way of understanding hashes is to study pseudo-random generator functions which use many of the same techniques that make for good hashes. (For example, see the list of generators created by
George Marsaglia). Also do google searches for hash functions, which might turn up things like the
FNV hash.