Skip to content

Instantly share code, notes, and snippets.

@Veedrac
Created November 29, 2016 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Veedrac/67b8c488300076560f426bab01043cf7 to your computer and use it in GitHub Desktop.
Save Veedrac/67b8c488300076560f426bab01043cf7 to your computer and use it in GitHub Desktop.
import random
# Make this higher when you want better graphs
iters = 100
def trunc(x):
return x % (2**64)
def test_row(f, swaps):
seen = set()
diff_counts = [0] * 64
for _ in range(iters):
while True:
x = random.randrange(2**64)
x &= random.randrange(2**64)
x &= random.randrange(2**64)
x &= random.randrange(2**64)
x &= ~((1 << 32) - 1)
# If we don't do this, there's
# huge bias towards certain values,
# even for completely random functions
if x not in seen:
seen.add(x)
seen.add(x ^ swaps)
break
diffs = f(x) ^ f(x ^ swaps)
for i in range(64):
if (diffs >> i) & 1:
diff_counts[i] += 1
return diff_counts
BAD = 2
chars = " "*BAD + "░▒▓" + "█"*BAD
def format_row(row, ord):
return "".join(chars[x * len(chars) // (iters+1)] for x in ord(row))
def display():
ord = reversed
for i in reversed(range(64)):
print(
format_row(test_row(f1, 1 << i), ord),
format_row(test_row(f2, 1 << i), ord),
format_row(test_row(f3, 1 << i), ord),
)
print()
# For SVG output:
# def format_row(row, x, y, ord):
# for i, count in enumerate(ord(row)):
# yield "<rect x='{}' y='{}' width='4.1' height='4.1' fill='rgb({},{},{})'/>".format(
# x * 4 + i * 4, (63-y) * 4, count * 255 / (iters+1), 0, 0
# )
# def display():
# ord = reversed
# print("<svg width='256' height='256' version='1.1' xmlns='http://www.w3.org/2000/svg'>")
# for i in reversed(range(64)):
# print(*format_row(test_row(f1, 1 << i), 0, i, ord))
# print(*format_row(test_row(f2, 1 << i), 70, i, ord))
# print(*format_row(test_row(f3, 1 << i), 140, i, ord))
# print()
def f1(x):
x = trunc(x * 0x6eed4e9da4d94a4b)
x ^= (x >> 32) >> (x >> 60)
x = trunc(x * 0x6eed4e9da4d94a4b)
# x ^= (x >> 32) >> (x >> 60)
# x = trunc(x * 0x6eed4e9da4d94a4b)
# x ^= (x >> 32) >> (x >> 60)
return x
def f2(x):
x = trunc(x * 0x6eed4e9da4d94a4b)
x ^= x >> 32
x = trunc(x * 0x6eed4e9da4d94a4b)
x ^= x >> 32
# x = trunc(x * 0x6eed4e9da4d94a4b)
# x ^= x >> 32
return x
# The cache should be unnecessary since
# repeats are handled already, but
# this wasn't always the case.
seen = {}
def f3(x):
# Yes, yes, Python's `random` isn't actually perfectly random.
return seen.setdefault(x, random.randrange(2**64))
display()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment