how to store exclusive OR boolean as bitmask

173 views Asked by At

I am working with a interface where most flags are implicitly false when not set, but some parameters have an explicit 'x-not-set' flag, so that either flag can be passed in but never both and in some cases, neither should be passed in. I think the underlying logic is that 'x-not-set' is not equivalent to excluding 'x-set' in scenarios where x should not default to enabled.

Example parameter flag permutations for parameters X, Z with flags X, Z, no-Z:

<empty>
/X
/Z
/no-Z
/X /Z
/X /no-Z

So if I treat Z and no-Z as one bit on a mask, this makes an empty bitmask and only setting no-Z both 00, but if I handle them as separate bits, then both could be set like:

/Z /no-Z
/X /Z /no-Z

which not only could have unpredictable or fatal response, but in my real-world scenario where there could be 5 simple (like /X) parameters and 3 XOR (like /Z, /no-Z, or empty), testing all permutations versus all valid-permutations ( 2^11 vs (2^8)+8 ) has significantly higher cost.

Is there a way I'm not thinking of to set the bits so that some of them are either on or off while others are (for lack of better terms), on, off, or NULL?

Quick Afterthought:

Having written all of that out, the easiest solution that comes to mind is to define constants where those illegal combinations are set and then XOR the options mask against those so that if both are set both get unset. But I'm still not sure how to do this in an elegant way, ie some way of 'marking' which of the bits are XOR bits (if that makes any sense. I've just hit my wall on this level of logic).

1

There are 1 answers

0
Axel Kemper On

You could encode the three possible configurations for Z as follows using two bits:

Z1  Z0
-------
 0   0      Z undefined (value for Z0 irrelevant)
 1   0      Z = No
 1   1      Z = Yes

To define the value for Z, bit Z1 has to be set via OR. Bit Z0 can also be set via OR or cleared via AND of and inverted mask.

Example in C syntax:

 #define DEF_Z 2
 #define SET_Z 1

 flags = (flags | DEF_Z) | SET_Z;     //   /Z

 flags = (flags | DEF_Z) & ~ SET_Z    //   /no-Z