To represent an "exclusive" set of n
options (i.e. exactly one must be chosen), we require at least ceil(log2(n))
bits. For example, option k
can be represented by the number k
in base-2
.
To represent an "orthogonal" set of n
options (i.e. any combination of size 0, 1, ..., n
can be chosen), we require at least n
bits. For example, options k0, k1, k2
could be represented by the binary number whose bits are zero except for bits 0, 1, 2
.
So, to represent multiple option sets simultaneously, we add up the number of bits required for each option set (depending on whether it is "exclusive" or "orthogonal") to get the total number of bits required.
In short, to pick the enum values,
- "exclusive" option
k
uses k << r
- "orthogonal" option
k0, k1, ..., k{n-1}
uses 0x1 << r, 0x1 << (r+1), ..., 0x1 << (r+n-1)
where offset r
is the number of bits used by the preceding option sets.
Example of how to automate this construction, in Java:
/**
* Construct a set of enum values, for the given sizes and types
* (exclusive vs orthogonal) of options sets.
*
* @param optionSetSizes
* number of elements in each option set
* @param isOptionSetExclusive
* true if corresponding option set is exclusive, false if
* orthogonal
* @returns
* array of m elements representing the enum values, where
* m is the sum of option set sizes. The enum values are
* given in the order of the option sets in optionSetSizes
* and isOptionSetExclusive.
*/
int[] constructEnumValues(
int[] optionSetSizes,
boolean[] isOptionSetExclusive)
{
assert optionSetSizes.length == isOptionSetExclusive.length;
// determine length of the return value
int m = 0;
for (int i = 0; i < optionSetSizes.length; i++) m += optionSetSizes[i];
int[] vals = new int[m];
int r = 0; // number of bits used by the preceding options sets
int c = 0; // counter for enum values used
for (int i = 0; i < optionSetSizes.length; i++)
{
// size of this option set
int n = optionSetSizes[i];
// is this option set exclusive?
boolean exclusive = isOptionSetExclusive[i];
for (int k = 0; k < n; k++)
{
vals[c] = (exclusive) ? (k << r) : (0x1 << (r + k));
c++;
}
r += (exclusive) ? (int) Math.ceil(Math.log(n)/Math.log(2)) : n;
}
return vals;
}