You don't have to use PCG!

The table on the front page of this site is a double edged sword. It helps people realize that generators they like may have problems, but it also leads some people to think that I'm just trying to aggressively promote my own work.

So, let's be clear, it's certainly nice if you like my work, but the success or otherwise of the PCG family isn't in any way essential to my own career or life success. It's an unexpected side project that I enjoy working on because I find the topic interesting. PCG is free; I don't get any royalties if you use it, and I won't mind if you use another good generator. If you don't see quality in the same way I do, you're entitled to your opinion. In other posts, such as the ones on randutils, I didn't even use my own generator.

So what are some other good generators? I'll mention a couple here...

XorShift* 128/64 and/or XorShift* 64/32

As I say in the PCG paper, truncated XorShift* generators have excellent statistical properties and excellent heritage. Once you get up to a reasonable size, it seems like they're challenging to predict as well. (Just to be clear, I'm not saying that either is challenging enough to be used for cryptography, but they're not trivially predictable, and as a result it seems like they're annoying enough to make it hard to mount an algorithmic complexity attack on a randomized algorithm that uses them.)

It doesn't have streams, but we could add them easily enough by xor-ing with a constant before performing the multiply step. As such it would do what I want streams to do. If you want more than that, PCG's or SplitMix's streams probably won't please you either.

Arbitrary jump-ahead is possible, although annoying to write and a bit slow. Having a cheap distance function seems harder, but few people need that feature.

If you can't find a good implementation to use, I've thrown one together that you can try; it's available as a GitHub gist.

ChaCha

ChaCha can provide a nice counter-based RNG using a cryptographic-hash output function. Obviously, it's really hard to predict, and I like that. Distance and jump ahead are essentially free.

I like Orson Peters's implementation. It lets you configure the number of rounds, since every round adds overhead and you may not need full cryptographic strength (but don't set it too low though). The code also includes hand-optimized assembly to run faster on x86 processors.

Orson Peters actually wrote this implementation when he wanted to prove me wrong when I claimed that cryptographic PRNGs were slow. It was a learning experience for both of us; it was faster than I'd previously seen, but not nearly as fast as he'd hoped from what he had read. There is a difference between encrypting large blocks of data and hashing a small counter.

Lovable Classics

Sometimes the path of least resistance is to use a classic generator, even if it has some flaws. I write a fair amount of code in C++, where there are quite a few choices available, none of which are great, but there are choices that will do in a pinch.

The Mersenne Twister

Okay, it doesn't really meet any of my criteria. It fails some statistical tests, it's huge, and it's kinda slow. But it's available for a lot of languages, so it's often the easy choice.

Linear Congruential Generators

Linear Congruential Generators are old and extremely well understood. Large ones (e.g., 128-bit) do pass statistical tests without assistance and can be very fast, and there are specialized uses for the small ones. In some contexts, their flaws (the regularity) can be assets. But I've been burned in the past by using a smaller LCG when I optimized for pure speed, thinking statistical quality wouldn't matter, only to discover that it did matter after all.

Others

There may be other good choices too. There are a lot of PRNGs out there. What I want is: statistically good, annoying to predict, fast, useful features, not too bloated, mathematically sound. If you want something else, that's okay, too.

(Sadly, Xoroshiro128+ and Xorshift128+ are not on this list. I thought they were good because good claims are made about them, but I have recently discovered otherwise. You can test them yourself with PractRand or TestU01 and determine their quality; it's quite easy to do. You can also read the caveats given in their source code. Or you can wait: a blog post is coming. The news isn't good.)