I asked a very similar question at the tigsource forums.
Hashing
At least in games, a hash function could probably do what you want. You could do it like this
class ReversibleRNG {
int x;
public:
ReversibleRNG(int seed) : x(seed) {}
int next(){return yourFavoriteHash(++x);}
int prev(){return yourFavoriteHash(--x);}
};
Reversible linear congruential generator (lcg)
As multiple people have pointed out, an lcg is indeed reversible. In an lcg, the next state is computed like this:
x = (a * prevx + c) mod m
We can reorder this:
x ≡ a * prevx + c (mod m)
x - c ≡ a * prevx (mod m)
Since a and m are chosen to be relatively prime in an lcg, we can find the inverse by using the extended euclid’s algorithm.
ainverse = extEuclid(a, m).x;
ainverse * (x - c) ≡ ainverse * a * prevx (mod m)
ainverse * (x - c) ≡ prevx (mod m)
Which means
prevx = ainverse * (x - c) mod m
If you choose m and a carefully, the algorithm can have a period of 2^64
Implementation
I did a header-only implementation of this algorithm in case anyone’s interested.