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?factor, for2**32can you tolerate using2**31and either doubling the dividend or halving the divisor?workaround for the uint32_t factor.)result = (int32_t)((dividend / divisor) * factor + ((dividend % divisor) * factor) / divisor);? (Can the OP please include the assembly generated for the existing work-around?)