Author: tkreuzer
Date: Tue Jan 1 12:09:53 2013
New Revision: 58082
URL:
http://svn.reactos.org/svn/reactos?rev=58082&view=rev
Log:
[WIN32K]
Rewrite EngMulDiv.
Modified:
trunk/reactos/win32ss/gdi/eng/math.c
Modified: trunk/reactos/win32ss/gdi/eng/math.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/math.c?rev…
==============================================================================
--- trunk/reactos/win32ss/gdi/eng/math.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/eng/math.c [iso-8859-1] Tue Jan 1 12:09:53 2013
@@ -21,53 +21,57 @@
#include <win32k.h>
-/*
- * 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;
-
- 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;
+ i64Multiplied -= (iDivisor / 2);
}
- /* 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;
+ /* Now do the divide */
+ i64Result = i64Multiplied / iDivisor;
- return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+ /* Check for positive overflow */
+ if (i64Result > INT_MAX)
+ {
+ return INT_MAX;
+ }
-#endif
+ /* Check for negative overflow. */
+ if (i64Result < INT_MIN)
+ {
+ return INT_MIN;
+ }
+
+ return (INT)i64Result;
}
+