oleaut32: Implement VarDecRound.
This commit is contained in:
parent
515af78f6b
commit
87c459ab23
|
@ -455,6 +455,7 @@ static HRESULT (WINAPI *pVarDecDiv)(const DECIMAL*,const DECIMAL*,DECIMAL*);
|
|||
static HRESULT (WINAPI *pVarDecCmp)(const DECIMAL*,const DECIMAL*);
|
||||
static HRESULT (WINAPI *pVarDecCmpR8)(const DECIMAL*,double);
|
||||
static HRESULT (WINAPI *pVarDecNeg)(const DECIMAL*,DECIMAL*);
|
||||
static HRESULT (WINAPI *pVarDecRound)(const DECIMAL*,int,DECIMAL*);
|
||||
|
||||
static HRESULT (WINAPI *pVarBoolFromUI1)(BYTE,VARIANT_BOOL*);
|
||||
static HRESULT (WINAPI *pVarBoolFromI2)(SHORT,VARIANT_BOOL*);
|
||||
|
@ -4545,6 +4546,39 @@ static void test_VarDecCmpR8(void)
|
|||
SETDEC(l,0,DECIMAL_NEG,-1,-1); r = DECIMAL_NEG; MATH3(VarDecCmpR8); EXPECT_LT;
|
||||
}
|
||||
|
||||
#define CLEAR(x) memset(&(x), 0xBB, sizeof(x))
|
||||
|
||||
static void test_VarDecRound(void)
|
||||
{
|
||||
HRESULT hres;
|
||||
DECIMAL l, out;
|
||||
|
||||
CHECKPTR(VarDecRound);
|
||||
|
||||
CLEAR(out); SETDEC(l, 0, 0, 0, 1); hres = pVarDecRound(&l, 3, &out); EXPECTDEC(0, 0, 0, 1);
|
||||
|
||||
CLEAR(out); SETDEC(l, 0, 0, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, 0, 0, 1);
|
||||
CLEAR(out); SETDEC(l, 1, 0, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, 0, 0, 0);
|
||||
CLEAR(out); SETDEC(l, 1, 0, 0, 1); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 1);
|
||||
CLEAR(out); SETDEC(l, 2, 0, 0, 11); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 1);
|
||||
CLEAR(out); SETDEC(l, 2, 0, 0, 15); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 2);
|
||||
CLEAR(out); SETDEC(l, 6, 0, 0, 550001); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 6);
|
||||
|
||||
CLEAR(out); SETDEC(l, 0, DECIMAL_NEG, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, DECIMAL_NEG, 0, 1);
|
||||
CLEAR(out); SETDEC(l, 1, DECIMAL_NEG, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, DECIMAL_NEG, 0, 0);
|
||||
CLEAR(out); SETDEC(l, 1, DECIMAL_NEG, 0, 1); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 1);
|
||||
CLEAR(out); SETDEC(l, 2, DECIMAL_NEG, 0, 11); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 1);
|
||||
CLEAR(out); SETDEC(l, 2, DECIMAL_NEG, 0, 15); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 2);
|
||||
CLEAR(out); SETDEC(l, 6, DECIMAL_NEG, 0, 550001); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 6);
|
||||
|
||||
CLEAR(out); SETDEC64(l, 0, 0, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, 0, 0xffffffff, 0xffffffff, 0xffffffff);
|
||||
CLEAR(out); SETDEC64(l, 28, 0, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, 0, 0, 0, 8);
|
||||
CLEAR(out); SETDEC64(l, 0, DECIMAL_NEG, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, DECIMAL_NEG, 0xffffffff, 0xffffffff, 0xffffffff);
|
||||
CLEAR(out); SETDEC64(l, 28, DECIMAL_NEG, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, DECIMAL_NEG, 0, 0, 8);
|
||||
|
||||
CLEAR(out); SETDEC(l, 2, 0, 0, 0); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* VT_BOOL
|
||||
*/
|
||||
|
@ -6334,6 +6368,7 @@ START_TEST(vartype)
|
|||
test_VarDecCmpR8();
|
||||
test_VarDecMul();
|
||||
test_VarDecDiv();
|
||||
test_VarDecRound();
|
||||
|
||||
test_VarBoolFromI1();
|
||||
test_VarBoolFromUI1();
|
||||
|
|
|
@ -5137,7 +5137,7 @@ static int VARIANT_int_addlossy(
|
|||
in case of quotient overflow.
|
||||
*/
|
||||
static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * divisor,
|
||||
VARIANT_DI * quotient)
|
||||
VARIANT_DI * quotient, BOOL round_remainder)
|
||||
{
|
||||
HRESULT r_overflow = S_OK;
|
||||
|
||||
|
@ -5180,8 +5180,21 @@ static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * di
|
|||
underflow = VARIANT_int_addlossy(
|
||||
quotient->bitsnum, "ientscale, sizeof(quotient->bitsnum) / sizeof(DWORD),
|
||||
remainderplusquotient, &tempquotientscale, 4);
|
||||
VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
|
||||
memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
|
||||
if (round_remainder) {
|
||||
if(remainderplusquotient[4] >= 5){
|
||||
unsigned int i;
|
||||
unsigned char remainder = 1;
|
||||
for (i = 0; i < sizeof(quotient->bitsnum) / sizeof(DWORD) && remainder; i++) {
|
||||
ULONGLONG digit = quotient->bitsnum[i] + 1;
|
||||
remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
|
||||
quotient->bitsnum[i] = digit & 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
|
||||
} else {
|
||||
VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
|
||||
memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
|
||||
}
|
||||
tempquotientscale = ++remainderscale;
|
||||
} while (!underflow && !VARIANT_int_iszero(remainderplusquotient + 4, 4));
|
||||
|
||||
|
@ -5485,31 +5498,16 @@ static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest)
|
|||
return hres;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* VarDecDiv (OLEAUT32.178)
|
||||
*
|
||||
* Divide one DECIMAL by another.
|
||||
*
|
||||
* PARAMS
|
||||
* pDecLeft [I] Source
|
||||
* pDecRight [I] Value to divide by
|
||||
* pDecOut [O] Destination
|
||||
*
|
||||
* RETURNS
|
||||
* Success: S_OK.
|
||||
* Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
|
||||
*/
|
||||
HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
|
||||
static HRESULT VARIANT_do_division(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut,
|
||||
BOOL round)
|
||||
{
|
||||
HRESULT hRet = S_OK;
|
||||
VARIANT_DI di_left, di_right, di_result;
|
||||
HRESULT divresult;
|
||||
|
||||
if (!pDecLeft || !pDecRight || !pDecOut) return E_INVALIDARG;
|
||||
|
||||
VARIANT_DIFromDec(pDecLeft, &di_left);
|
||||
VARIANT_DIFromDec(pDecRight, &di_right);
|
||||
divresult = VARIANT_DI_div(&di_left, &di_right, &di_result);
|
||||
divresult = VARIANT_DI_div(&di_left, &di_right, &di_result, round);
|
||||
if (divresult != S_OK)
|
||||
{
|
||||
/* division actually overflowed */
|
||||
|
@ -5556,6 +5554,27 @@ HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECI
|
|||
return hRet;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* VarDecDiv (OLEAUT32.178)
|
||||
*
|
||||
* Divide one DECIMAL by another.
|
||||
*
|
||||
* PARAMS
|
||||
* pDecLeft [I] Source
|
||||
* pDecRight [I] Value to divide by
|
||||
* pDecOut [O] Destination
|
||||
*
|
||||
* RETURNS
|
||||
* Success: S_OK.
|
||||
* Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
|
||||
*/
|
||||
HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
|
||||
{
|
||||
if (!pDecLeft || !pDecRight || !pDecOut) return E_INVALIDARG;
|
||||
|
||||
return VARIANT_do_division(pDecLeft, pDecRight, pDecOut, FALSE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* VarDecMul (OLEAUT32.179)
|
||||
*
|
||||
|
@ -5765,6 +5784,10 @@ HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
|
|||
*/
|
||||
HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
|
||||
{
|
||||
DECIMAL divisor, tmp;
|
||||
HRESULT hr;
|
||||
unsigned int i;
|
||||
|
||||
if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
|
||||
return E_INVALIDARG;
|
||||
|
||||
|
@ -5774,9 +5797,26 @@ HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOu
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
FIXME("semi-stub!\n");
|
||||
/* truncate significant digits and rescale */
|
||||
memset(&divisor, 0, sizeof(divisor));
|
||||
DEC_LO64(&divisor) = 1;
|
||||
|
||||
return DISP_E_OVERFLOW;
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
DEC_LO64(&tmp) = 10;
|
||||
for (i = 0; i < DEC_SCALE(pDecIn) - cDecimals; ++i)
|
||||
{
|
||||
hr = VarDecMul(&divisor, &tmp, &divisor);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = VARIANT_do_division(pDecIn, &divisor, pDecOut, TRUE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
DEC_SCALE(pDecOut) = cDecimals;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
Loading…
Reference in New Issue