Fix MulDiv. This fixes almost any progress-bar to stop showing negative values during installations or etc. Thanks to kichik for originally having found the bug.

Patch by alex ionescu

svn path=/trunk/; revision=18386
This commit is contained in:
Gunnar Dalsnes 2005-10-09 22:12:56 +00:00
parent 315e77dfab
commit 690727fe99

View file

@ -13,48 +13,42 @@
*
* @implemented
*/
INT STDCALL MulDiv(
INT nMultiplicand,
INT nMultiplier,
INT nDivisor)
INT
WINAPI
MulDiv(INT nNumber,
INT nNumerator,
INT nDenominator)
{
#if SIZEOF_LONG_LONG >= 8
long long ret;
if (!nDivisor) return -1;
/* We want to deal with a positive divisor to simplify the logic. */
if (nDivisor < 0)
LARGE_INTEGER Result;
LONG Negative;
/* Find out if this will be a negative result */
Negative = nNumber ^ nNumerator ^ nDenominator;
/* Turn all the parameters into absolute values */
if (nNumber < 0) nNumber *= -1;
if (nNumerator < 0) nNumerator *= -1;
if (nDenominator < 0) nDenominator *= -1;
/* Calculate the result */
Result.QuadPart = Int32x32To64(nNumber, nNumerator) + (nDenominator / 2);
/* Now check for overflow */
if (nDenominator > Result.HighPart)
{
nMultiplicand = - nMultiplicand;
nDivisor = -nDivisor;
/* Divide the product to get the quotient and remainder */
Result.LowPart = RtlEnlargedUnsignedDivide(*(PULARGE_INTEGER)&Result,
(ULONG)nDenominator,
&Result.HighPart);
/* Do the sign changes */
if ((LONG)Result.LowPart >= 0)
{
return (Negative >= 0) ? Result.LowPart : -(LONG)Result.LowPart;
}
}
/* If the result is positive, we "add" to round. else, we subtract to round. */
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
else
ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
if ((ret > 2147483647) || (ret < -2147483647)) return -1;
return ret;
#else
if (!nDivisor) return -1;
/* We want to deal with a positive divisor to simplify the logic. */
if (nDivisor < 0)
{
nMultiplicand = - nMultiplicand;
nDivisor = -nDivisor;
}
/* If the result is positive, we "add" to round. else, we subtract to round. */
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
#endif
/* Return overflow */
return - 1;
}