[Issue 12958] core.checkedint.mulu is broken
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Mon Jun 23 16:02:32 PDT 2014
https://issues.dlang.org/show_bug.cgi?id=12958
David Bregman <uber.daveb at gmail.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |uber.daveb at gmail.com
--- Comment #2 from David Bregman <uber.daveb at gmail.com> ---
That won't work because there can still be overflows when summing the partial
products. Consider this test case:
assert(mulu(2uL*uint.max,uint.max,overflow) == 18446744056529682434uL);
assert(overflow);
To do the full thing, I'm pretty sure we essentially need to use addu()
(inlined of course) to sum the partials.
I also noticed that addu should be simplified:
((x+y<x) || (x+y<y)) == (x+y < (x|y))
So here's my proposed solution (below): The overflow checks are written in such
a way that DMD is able to generate branchless code (I checked the assembler).
uint mulu(uint x, uint y, ref bool overflow)
{
ulong r = cast(ulong)x*y;
overflow |= !!(r >> 32);
return cast(uint)r;
}
ulong mulu(ulong x, ulong y, ref bool overflow)
{
// x = b:a, y = d:c
immutable uint a = cast(uint)x;
immutable uint b = x >> 32;
immutable uint c = cast(uint)y;
immutable uint d = y >> 32;
immutable low = cast(ulong)a*c;
immutable mid1 = cast(ulong)b*c;
immutable mid2 = cast(ulong)a*d;
immutable mid = mid1+mid2;
overflow |= !!b & !!d;
overflow |= mid < (mid1|mid2);
overflow |= !!(mid >> 32);
immutable mid_lo = mid<<32;
immutable r = low + mid_lo;
overflow |= r < (low|mid_lo);
return r;
}
--
More information about the Digitalmars-d-bugs
mailing list