value range propagation for _bitwise_ OR
PBa
spam at goto-hell.com
Fri Apr 9 06:29:52 PDT 2010
Am 10.04.2010, 23:17 Uhr, schrieb Don <nospam at nospam.com>:
> 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). If 'maxb' is
>> exactly 1 less than a power of 2, then 'candidate' will be 0. Now
>> consider a in [0, 16], b in [0, 15]. Your function will produce 16, but
>> the real maximum is 31.
>> For maximum accuracy, you have to consider the minima as well as the
>> maxima when calculating the new maximum. With 'a' in [16, 16] and 'b'
>> in [16, 16], the new range can only be [16, 16]. With 'a' in [0, 16]
>> and 'b' in [0, 16], the correct new range is [0, 31].
>>
>
> It's a very interesting puzzle. There are some pretty complex cases.
>
> Consider (all numbers binary) a in [1010, 1100] and b in [101,101]. The
> maximum value is when a=1011, b=101, so max is 1111.
How about this?
import std.stdio, std.conv, std.intrinsic;
void main(string[] args)
{
int total = 0, match = 0, from = to!(int)(args[1]), to =
to!(int)(args[2]);
uint res, resBF;
for(int i = from; i < to; ++i)
{
for(int j = i; j < to; ++j)
{
for(int k = from; k < to; ++k)
{
for(int m = k; m < to; ++m)
{
++total;
res = maxOr(i, j, k, m);
resBF = maxOrBF(i, j, k, m);
if(res == resBF) ++match;
//else writefln("mismatch: minA %s, maxA %s, minB %s, maxB %s,
maxOr %s, maxOrBF %s", i, j, k, m, res, resBF);
}
}
}
}
writefln("total %s, match %s", total, match);
}
uint max(uint a, uint b)
{
return (a > b) ? a : b;
}
uint maxOr(uint minA, uint maxA, uint minB, uint maxB)
{
uint result = minA | maxA | minB | maxB,
diff = max(maxA - minA, maxB - minB);
if(diff)
{
result |= (1 << (bsr(diff) + 1)) - 1;
}
return result;
}
/* compute result using brute force */
uint maxOrBF(uint minA, uint maxA, uint minB, uint maxB)
{
return bitsSetInIntervallBF(minA, maxA) | bitsSetInIntervallBF(minB,
maxB);
}
uint bitsSetInIntervallBF(uint min, uint max)
{
uint result = 0;
for(; min <= max; ++min)
{
result |= min;
}
return result;
}
More information about the Digitalmars-d
mailing list