I would like to have a user-defined key in a C++ std::map. The key is a binary representation of an integer set with maximum value 2^V so I can’t represent all 2^V possible values. I do so by means of an efficient binary set representation, i.e., an array of uint64_t.
Now the problem is that to put this user-defined bitset as key in a std::map, I need to define a valid comparison between bitset values but if I have a maximum size of, say, V=1000, then I cannot get a number I can compare, let alone aggregating them all i.e., 2^1000 is not representable.
Therefore my question is, suppose I have two different sets (by setting the right bits in my bitset representation) and I cannot represent the final number because it will overflow:
id_1 = 2^0 + 2^1 + ... + 2^V
id_2 = 2^0 + 2^1 + ... + 2^V
Is there a suitable transformation that would lead to a value I can compare? I need to be able to say id_1 < id_2 so I would like to transform a sum of exponentials to a value that is representable BUT maintaining the invariant of the “less than”. I was thinking along the lines of e.g. applying a log transformation in a clever way to preserve “less than”.
Here is an example:
set_1 = {2,3,4}; set_2 = {8}
id(set_1) = 2^2 + 2^3 + 2^4 = 28; id(set_2) = 2^8 = 256
id(set_1) < id(set_2)
Perfect! How about a general set that can have {1,...,V}, and thus 2^V possible subsets?
Supposing that this array is accessed via a data member
raof the key typeKey, and both arrays are of lengthN, then you want a comparator something like this:This implicitly considers the array to be big-endian, i.e. the first
uint64_tis the most significant. If you don’t like that, that’s fair enough, since you might already have in mind some relative significance for whatever order you’ve stored yourVbits into your array. There’s no great mystery tolexicographical_compare, so just look at an example implementation and modify as required.This is called “lexicographical order”. Other than the facts that I’ve used
uint64_tinstead ofcharand both arrays are the same length, it is how strings are compared[*] — in fact the use ofuint64_tisn’t important, you could just usestd::memcmpin your comparator instead of comparing 64-bit chunks.operator<for strings doesn’t work by converting the whole string to an integer, and neither should your comparator.[*] until you bring locale-specific collation rules into play.