OP: "Currently I have a workaround for the uint32_t factor"
The factor == 2^32
is a corner case and is all that is needed to be solved here as OP's "workaround" can handle factors [0 ... 2^32-1]
.
If the dividend
can be doubled without overflow, simple use factor == 2^31
with a doubled dividend
.
If the divisor
is even, use factor == 2^31
with a halved divisor
. @Weather Vane
Else the dividend
is large. Recall that the quotient is in [-2^31 ... 2^31-1]
range. In general, the product of the large dividend
and factor == 2^32
dividend by the divisor
will out of the int32_t
range, so those out-of-range combinations are not of concern as "result: is guaranteed to fit in a int32_t
".
The acceptable edge conditions occur with a final quotient near the edge of the int32_t
range.
pow(2,63) == 9223372036854775808
pow(2,62) == 4611686018427387904
pow(2,32) == 4294967296
pow(2,31) == 2147483648
Smallest Dividends Factor Largest Divisors Smallest Quotients
-4611686018427387905 4294967296 -9223372036854775807 2147483648.00+
-4611686018427387905 4294967296 9223372036854775807 -2147483648.00+ OK
4611686018427387904 4294967296 -9223372036854775807 -2147483648.00+ OK
4611686018427387904 4294967296 9223372036854775807 2147483648.00+
After testing, dividend
and divisor
, the only representable answer in INT32_MIN
.
Sample Code:
int32_t muldiv64(int64_t dividend, uint64_t factor, int64_t divisor) {
if (factor >= 0x100000000) {
assert(factor == 0x100000000);
factor /= 2;
if (dividend >= INT64_MIN/2 && dividend <= INT64_MAX/2) {
dividend *= 2;
} else if (divisor %2 == 0) {
divisor /= 2;
} else {
return INT32_MIN;
}
}
return workaround_for_the_uint32_t_factor(dividend, factor, divisor);
}
The original problem is to detect this edge condition and how to handle it.. The workaround_for_the_uint32_t_factor()
may not have been coded yet, thus it was not posted.
factor
.int64_t
? – Pennywise2**32
use a shift, but if you have no hardware implementation for multiply or divide it's unlikely that a 64-bit overflow can be handled. – Traynorfactor
, for2**32
can you tolerate using2**31
and either doubling the dividend or halving the divisor? – Traynorworkaround for the uint32_t factor
.) – Jahnresult = (dividend / divisor) * factor
? Or am I misunderstanding the problem? – Tautomerresult = (int32_t)((dividend / divisor) * factor + ((dividend % divisor) * factor) / divisor);
? (Can the OP please include the assembly generated for the existing work-around?) – Jahn