From: Timo Kreuzer Date: Tue, 1 Jan 2013 12:09:53 +0000 (+0000) Subject: [WIN32K] X-Git-Tag: backups/ros-csrss@60644~85^2~57 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=5b8a6dd3cc3e0a9c023a1c522bbd048cce631fd0;ds=sidebyside [WIN32K] Rewrite EngMulDiv. svn path=/trunk/; revision=58082 --- diff --git a/reactos/win32ss/gdi/eng/math.c b/reactos/win32ss/gdi/eng/math.c index 46036ee6bcc..f14abf8c943 100644 --- a/reactos/win32ss/gdi/eng/math.c +++ b/reactos/win32ss/gdi/eng/math.c @@ -21,53 +21,57 @@ #include -/* - * FIXME: Is there a better algorithm, like FT_MulDiv? - * - * @implemented - */ -INT APIENTRY EngMulDiv( - INT nMultiplicand, - INT nMultiplier, - INT nDivisor) +INT +APIENTRY +EngMulDiv( + _In_ INT iMultiplicand, + _In_ INT iMultiplier, + _In_ INT iDivisor) { -#if SIZEOF_LONG_LONG >= 8 - long long ret; + INT64 i64Multiplied, i64Result; - if (!nDivisor) return -1; + /* Check for divide by zero */ + if (iDivisor == 0) + { + /* Quick sign check and return "infinite" */ + return ((iMultiplicand ^ iMultiplier) < 0) ? INT_MIN : INT_MAX; + } /* We want to deal with a positive divisor to simplify the logic. */ - if (nDivisor < 0) + if (iDivisor < 0) { - nMultiplicand = - nMultiplicand; - nDivisor = -nDivisor; + iMultiplicand = -iMultiplicand; + iDivisor = -iDivisor; } - /* 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; + /* Do the multiplication */ + i64Multiplied = Int32x32To64(iMultiplicand, iMultiplier); + + /* If the result is positive, we add to round, else we subtract to round. */ + if (i64Multiplied >= 0) + { + i64Multiplied += (iDivisor / 2); + } else - ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; + { + i64Multiplied -= (iDivisor / 2); + } - if ((ret > 2147483647) || (ret < -2147483647)) return -1; - return ret; -#else - if (!nDivisor) return -1; + /* Now do the divide */ + i64Result = i64Multiplied / iDivisor; - /* We want to deal with a positive divisor to simplify the logic. */ - if (nDivisor < 0) + /* Check for positive overflow */ + if (i64Result > INT_MAX) { - nMultiplicand = - nMultiplicand; - nDivisor = -nDivisor; + return INT_MAX; } - /* 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; + /* Check for negative overflow. */ + if (i64Result < INT_MIN) + { + return INT_MIN; + } -#endif + return (INT)i64Result; } +