value range propagation for _bitwise_ OR
Steven Schveighoffer
schveiguy at yahoo.com
Sat Apr 10 21:30:07 PDT 2010
On Sat, 10 Apr 2010 22:53:42 -0400, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> On 04/10/2010 09:51 PM, Steven Schveighoffer wrote:
>> Andrei Alexandrescu Wrote:
>>
>>> On 04/10/2010 12:01 PM, Andrei Alexandrescu wrote:
>>>> Consider:
>>>>
>>>> byte c = a | b;
>>>>
>>>> Say you already know min_a, max_a, min_b, and max_b. How do you
>>>> compute min_c and max_c? I thought of it for a bit and it seems
>>>> quite tricky.
>>>>
>>>>
>>>> Thanks,
>>>>
>>>> Andrei
>>>
>>> I think this would work:
>>>
>>> uint maxOR(uint maxa, uint maxb) { if (maxa< maxb) return
>>> maxOR(maxb, maxa); uint candidate = 0; foreach (i, bit;
>>> byBitDescending(maxa)) { if (bit) continue; auto t = candidate |
>>> (1<< (31 - i)); if (t<= maxb) candidate = t; } return maxa |
>>> candidate; }
>>>
>>> The idea is to find the candidate that would fill as many zeros in
>>> maxa as possible.
>>>
>>> But this is inefficient. I'm wondering whether a simple bitwise
>>> manipulation expression could do the trick.
>>
>> Don't you need to take into account the minimum of b also? That is,
>> the candidate needs to be greater than minb. Because filling in more
>> holes doesn't necessarily mean biggest number, I don't think it
>> works.
>
> Ha! Good point. I'd forgotten the initial requirement and considered
> both values to start at 0. They don't! Adam? :o)
Couldn't help it, this seems like such a fun problem, I had to solve it :)
uint maxor(uint mina, uint maxa, uint minb, uint maxb)
{
uint bt = 1 << 31;
uint result = 0;
while(bt)
{
if((bt & maxa) && (bt & mina))
{
result |= bt;
if((bt & minb) ^ (bt & maxb))
{
return result | (bt-1);// always can choose all 1s for
rest of b
}
}
else if((bt & maxb) && (bt & minb))
{
result |= bt;
if((bt & mina) ^ (bt & maxa))
{
return result | (bt-1);// always can choose all 1s for
rest of a
}
}
else if(bt & (maxa | maxb))
{
result |= bt;
if(bt & (maxa & maxb))
{
// both maxa and maxb have bt set, and both mina and minb
have
// bt unset. This means we can choose this bit to be set
on
// either, and it is possible to have all 1s set for the
other
// for the rest of the bits.
return result | (bt - 1);
}
else if(bt & maxa)
{
// now that we are using this bit from maxa, we need to
raise
// mina so it becomes the smallest value with bt set.
However,
// we don't really care about bits above bt, so setting
// it to 0 is fine.
mina = 0;
}
else
{
minb = 0;
}
}
// else, neither maxa or maxb have bt set, continue to next bit.
bt >>= 1;
}
return result;
}
This only solves unsigned (tested all ranges against a brute force
solution up to max values of 64, given the nature of binary, I don't think
there can be any weird cases that wouldn't have problems at lower ranges.
Note that in my solution, maxa and maxb are inclusive.
Signed is probably trickier, suppose one is always negative and one is
always positive! I'm satisfied solving the unsigned for now, maybe
someone else can modify this solution to work with signed integers also :)
-Steve
More information about the Digitalmars-d
mailing list