mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[WIN32K]
Rewrite EngMulDiv. svn path=/trunk/; revision=58082
This commit is contained in:
parent
46da747829
commit
5b8a6dd3cc
1 changed files with 42 additions and 38 deletions
|
@ -21,53 +21,57 @@
|
||||||
|
|
||||||
#include <win32k.h>
|
#include <win32k.h>
|
||||||
|
|
||||||
/*
|
INT
|
||||||
* FIXME: Is there a better algorithm, like FT_MulDiv?
|
APIENTRY
|
||||||
*
|
EngMulDiv(
|
||||||
* @implemented
|
_In_ INT iMultiplicand,
|
||||||
*/
|
_In_ INT iMultiplier,
|
||||||
INT APIENTRY EngMulDiv(
|
_In_ INT iDivisor)
|
||||||
INT nMultiplicand,
|
|
||||||
INT nMultiplier,
|
|
||||||
INT nDivisor)
|
|
||||||
{
|
{
|
||||||
#if SIZEOF_LONG_LONG >= 8
|
INT64 i64Multiplied, i64Result;
|
||||||
long long ret;
|
|
||||||
|
|
||||||
if (!nDivisor) return -1;
|
/* Check for divide by zero */
|
||||||
|
if (iDivisor == 0)
|
||||||
/* We want to deal with a positive divisor to simplify the logic. */
|
|
||||||
if (nDivisor < 0)
|
|
||||||
{
|
{
|
||||||
nMultiplicand = - nMultiplicand;
|
/* Quick sign check and return "infinite" */
|
||||||
nDivisor = -nDivisor;
|
return ((iMultiplicand ^ iMultiplier) < 0) ? INT_MIN : INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the result is positive, we "add" to round. else, we subtract to round. */
|
/* We want to deal with a positive divisor to simplify the logic. */
|
||||||
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
|
if (iDivisor < 0)
|
||||||
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
|
{
|
||||||
ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
|
iMultiplicand = -iMultiplicand;
|
||||||
|
iDivisor = -iDivisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
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;
|
i64Multiplied -= (iDivisor / 2);
|
||||||
nDivisor = -nDivisor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the result is positive, we "add" to round. else, we subtract to round. */
|
/* Now do the divide */
|
||||||
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
|
i64Result = i64Multiplied / iDivisor;
|
||||||
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
|
|
||||||
return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
|
|
||||||
|
|
||||||
return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
|
/* Check for positive overflow */
|
||||||
|
if (i64Result > INT_MAX)
|
||||||
#endif
|
{
|
||||||
|
return INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for negative overflow. */
|
||||||
|
if (i64Result < INT_MIN)
|
||||||
|
{
|
||||||
|
return INT_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (INT)i64Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue