Hi,

I am sorry, I hate it myself when people talk in acronyms, assuming everyone knows what they are referring to. PNG stands for Pseudo-random Number Generator. Here is an example for a simple trigonometric pseudo random hash function.

Cheers,

zipit

"""A simple example for a very simple "one-at-a-time" Pseudo-random Number
Generator (PNG).
It is basically just one line of code, which you can find on line 32.
"""
import c4d
import math
def hash_11(x, seed=1234, magic=(1234.4567, 98765.4321)):
"""Returns a pseudo random floating point hash for a floating point number.
The hash will lie int the interval [-1, 1] and the function is a very
simple generator that exploits the periodicity of the trigonometric
functions. A more sophisticated approach would be to exploit avalanche
behavior in bit-shift operations on binary data, like the Jenkins
Rotation does for example.
The postfix in the name (_11) is a common way to denote the inputs and
outputs for PNGs. 11 means that it will take one (real) number and return
one (real) number. 13 means that it takes one and returns three, i.e. returns
an (euclidean) vector.
Args:
x (float): The value to hash into a pseudo random number.
seed (int, optional): The seed value. This could also be a float.
magic (tuple, optional): The magic numbers. The second one should be
bigger then the first and both should be real numbers.
Returns:
float: The pseudo random hash for x in the interval [-1, 1].
"""
return math.modf(math.sin(x + seed + magic[0]) * magic[1])[0]
def hash_13(x, seed=1234, magic=(1234.4567, 98765.4321)):
"""Returns a pseudo random vector hash for a floating point number.
Wraps around hash_11.
Returns:
c4d.Vector: The pseudo random hash for x in the interval [-1, 1].
"""
vx = hash_11(x, seed, magic)
vy = hash_11(x + vx, seed, magic)
vz = hash_11(x + vy, seed, magic)
return c4d.Vector(vx, vy, vz)
def main():
"""Entry point.
"""
# Some very crude statistics for the hashes.
samples = int(1E6)
# Generate 1E6 of each
numbers = {i: hash_11(i) for i in range(samples)}
vectors = {i: hash_13(i) for i in range(samples)}
# Compute their arithmetic mean.
amean_numbers = sum(numbers.values()) * (1./samples)
amean_vectors = sum(vectors.values()) * (1./samples)
# Report the results.
print "First three random numbers: ", numbers.values()[:3]
print "First three random vectors: ", vectors.values()[:3]
msg = "Arithmetic mean of all random numbers (should converge to zero): "
print msg, amean_numbers
msg = "Arithmetic mean of all random vectors (should converge to zero): "
print msg, amean_vectors
if __name__ == "__main__":
main()
First three random numbers: [-0.8036933662078809, 0.20401213006516628, 0.6249060598929645]
First three random vectors: [Vector(-0.804, -0.022, -0.872), Vector(0.204, 0.541, 0.115), Vector(0.625, 0.782, 0.896)]
Arithmetic mean of all random numbers (should converge to zero): -0.000127638074863
Arithmetic mean of all random vectors (should converge to zero): Vector(0, 0, 0)