From 690727fe99b944d8346164ccdf59091c29fd173d Mon Sep 17 00:00:00 2001 From: Gunnar Dalsnes Date: Sun, 9 Oct 2005 22:12:56 +0000 Subject: [PATCH] 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 --- reactos/lib/kernel32/misc/muldiv.c | 76 ++++++++++++++---------------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/reactos/lib/kernel32/misc/muldiv.c b/reactos/lib/kernel32/misc/muldiv.c index 9bb8c895fc8..bbfa3023a49 100644 --- a/reactos/lib/kernel32/misc/muldiv.c +++ b/reactos/lib/kernel32/misc/muldiv.c @@ -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; } +