Applied algebra

Today I faced a problem: how to generate a pseudo-random permutation of numbers in range [0,2^128), such that each number appears exactly once. An obvious solution is to initialize an array A[i]=i and then shuffle elements with repeated calls to random(). However, that would use a large amount of memory, which is not acceptable in this particular case.

So I remembered a bit of algebra that I learned long time ago at the university. It's about cyclic groups. Consider the sequence k*a0 % M for k = 0, 1, .... In my case M=2^128. This sequence generates all numbers less than M exactly once, provided that a0 and M are relatively prime. Shortly, a0 is a generator of an additive cyclic group where the set of elements are natural numbers in the range G=[0,2^128), and the operation is addition modulo M.

The code is even simpler (pseudo-C):

a = 0;
do {
/* use a in some way */
a += a0;
if(a > M) a -= M;
} while(a);

When a becomes 0 again, the whole group of M elements has been generated, so the loop exits. In other words, a has cycled through all elements in G exactly once. This is also connected with pseudo-random number generators. I'm not interested in the exact statistical properties of generated numbers; the only requirement is that consecutive numbers are "far enough" apart (which I define by chosing an appropriate constant a0).


No comments: