mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
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:
parent
315e77dfab
commit
690727fe99
1 changed files with 35 additions and 41 deletions
|
@ -13,48 +13,42 @@
|
||||||
*
|
*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
INT STDCALL MulDiv(
|
INT
|
||||||
INT nMultiplicand,
|
WINAPI
|
||||||
INT nMultiplier,
|
MulDiv(INT nNumber,
|
||||||
INT nDivisor)
|
INT nNumerator,
|
||||||
|
INT nDenominator)
|
||||||
{
|
{
|
||||||
#if SIZEOF_LONG_LONG >= 8
|
LARGE_INTEGER Result;
|
||||||
long long ret;
|
LONG Negative;
|
||||||
|
|
||||||
if (!nDivisor) return -1;
|
/* Find out if this will be a negative result */
|
||||||
|
Negative = nNumber ^ nNumerator ^ nDenominator;
|
||||||
/* We want to deal with a positive divisor to simplify the logic. */
|
|
||||||
if (nDivisor < 0)
|
/* 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;
|
/* Divide the product to get the quotient and remainder */
|
||||||
nDivisor = -nDivisor;
|
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. */
|
/* Return overflow */
|
||||||
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
|
return - 1;
|
||||||
( (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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue