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
Modified: trunk/reactos/lib/kernel32/misc/muldiv.c
_____
Modified: trunk/reactos/lib/kernel32/misc/muldiv.c
--- trunk/reactos/lib/kernel32/misc/muldiv.c 2005-10-09 22:09:02 UTC
(rev 18385)
+++ trunk/reactos/lib/kernel32/misc/muldiv.c 2005-10-09 22:12:56 UTC
(rev 18386)
@@ -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;
}
+