#include <misc/modgray.hh>
Public Member Functions | |
loopless_modular_mixed_radix_gray_code (int n) | |
virtual | ~loopless_modular_mixed_radix_gray_code () |
iteration over an element in a tuple | |
The class does not know how to modify the elements of the tuple (Knuth's ajs). These changes are therefore abstracted using the a_first(), a_next(), and a_last() abstract functions. These need to be implemented in subclasses as appropriate. | |
virtual void | a_first (int j)=0 |
Reset aj to its initial value. | |
virtual void | a_next (int j)=0 |
Advance aj to its next value. | |
virtual bool | a_last (int j) const =0 |
Whether aj is on its last value. | |
iteration over all the tuples | |
void | first () |
Reset the iteration to the first tuple. | |
bool | last () const |
Whether this the last tuple. | |
bool | done () const |
Whether all tuple have been explored. | |
int | next () |
Update one item of the tuple and return its position. | |
Protected Attributes | |
int | n_ |
bool | done_ |
int * | a_ |
int * | f_ |
int * | m_ |
int * | s_ |
int * | non_one_radixes_ |
This class is based on the loopless modular mixed radix gray code algorithm described in exercise 77 of "The Art of Computer Programming", Pre-Fascicle 2A (Draft of section 7.2.1.1: generating all n-tuples) by Donald E. Knuth.
The idea is to enumerate the set of all n-tuples (a0,a1,...,an-1) where each aj range over a distinct set (this is the mixed radix part), so that only one aj changes between two successive tuples of the iteration (that is the Gray code part), and that this changes occurs always in the same direction, cycling over the set aj must cover (i.e., modular). The algorithm is loopless in that computing the next tuple done without any loop, i.e., in constant time.
This class does not need to know the type of the aj, it will handle them indirectly through three methods: a_first(), a_next(), and a_last(). These methods need to be implemented in a subclass for the particular type of aj at hand.
The class itself offers four functions to control the iteration over the set of all the (a0,a1,..., an-1) tuples: first(), next(), last(), and done(). These functions are usually used as follows:
for (g.first(); !g.done(); g.next())
use the tuple
Finally, let's mention two differences between this algorithm and the one in Knuth's book. This version of the algorithm does not need to know the radixes (i.e., the size of set of each aj) beforehand: it will discover them on-the-fly when a_last(j) first return true. It will also work with aj that cannot be changed. (This is achieved by reindexing the elements through non_one_radixes_
, to consider only the elements with a non-singleton range.)
|
Constructor.
|
|
|
|
Reset aj to its initial value.
|
|
Whether aj is on its last value.
|
|
Advance aj to its next value. This will never be called if a_last(j) is true. |
|
Whether all tuple have been explored.
|
|
Reset the iteration to the first tuple. This must be called before calling any of next(), last(), or done(). |
|
Whether this the last tuple. At this point it is still OK to call next(), and then done() will become true. |
|
Update one item of the tuple and return its position. next() should never be called if done() is true. If it is called on the last tuple (i.e., last() is true), it will return -1. Otherwise it will update one aj of the tuple through one the aj handling functions, and return j. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|