value range propagation for _bitwise_ OR
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Sat Apr 10 15:33:36 PDT 2010
On 04/10/2010 04:50 PM, "Jérôme M. Berger" wrote:
> Andrei Alexandrescu wrote:
>> On 04/10/2010 01:55 PM, Rainer Deyke wrote:
>>> On 4/10/2010 11:52, Andrei Alexandrescu wrote:
>>>> 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;
>>>> }
>>>
>>> This looks wrong. Your function, if I understand it correctly, flips
>>> all the bits in 'maxb' (excluding the leading zeros).
>>
>> It tries to set all bits in which maxa is zero starting and keeps them
>> set if the resulting number is less than maxb.
>>
> In other words: maxa | ((1<< highbit (maxb))-1) where:
>
> int highbit (uint n) {
> auto result = 0;
> if (n& 0xFFFF0000) {
> result += 16;
> n = n>> 16;
> }
> if (n& 0xFF00) {
> result += 8;
> n = n>> 8;
> }
> if (n& 0xF0) {
> result += 4;
> n = n>> 4;
> }
> if (n& 0xC) {
> result += 2;
> n = n>> 2;
> }
> if (n& 0x2) {
> result += 1;
> n = n>> 1;
> }
> if (n& 0x1) {
> result += 1;
> }
> return result;
> }
>
> Jerome
Interesting. I don't get how your version is equivalent to mine, and I
don't get how it actually works, but it seems to. Could you please explain?
The program below compiles, runs, and prints
total=100000000; equal=3850865 (3.85087%)
Here it is:
import std.contracts, std.stdio;
uint maxOR(uint maxa, uint maxb) {
return maxa | ((1 << highbit (maxb))-1);
}
uint highbit(uint n) {
auto result = 0;
if (n & 0xFFFF0000) {
result += 16;
n = n >> 16;
}
if (n & 0xFF00) {
result += 8;
n = n >> 8;
}
if (n & 0xF0) {
result += 4;
n = n >> 4;
}
if (n & 0xC) {
result += 2;
n = n >> 2;
}
if (n & 0x2) {
result += 1;
n = n >> 1;
}
if (n & 0x1) {
result += 1;
}
return result;
}
void main() {
ulong total, equal;
uint N = 10000;
foreach (a; 0 .. N) {
foreach (b; 0 .. N) {
auto c = maxOR(a, b);
enforce((a|b) <= c);
if ((a|b) == c) equal++;
total++;
}
}
writeln("total=", total, "; equal=", equal,
" (", equal * 100. / total, "%)");
}
However, your method is not the tightest; seems like mine is tighter.
When I replaced maxOR with this:
uint maxOR2(uint maxa, uint maxb) {
if (maxa < maxb) return maxOR(maxb, maxa);
uint candidate = 0;
uint mask = 1u << 31;
for (uint i = 0; i < 32; ++i, mask >>= 1) {
if (maxa & mask) continue;
auto t = candidate | (1 << (31 - i));
if (t <= maxb) candidate = t;
}
return maxa | candidate;
}
I got:
total=100000000; equal=9822516 (9.82252%)
Besides, I verified that my method returns numbers <= yours.
Andrei
More information about the Digitalmars-d
mailing list