diff --git a/dlls/msvcp100/msvcp100.spec b/dlls/msvcp100/msvcp100.spec index c5d8fcc996e..d2b75f43533 100644 --- a/dlls/msvcp100/msvcp100.spec +++ b/dlls/msvcp100/msvcp100.spec @@ -2894,14 +2894,14 @@ @ cdecl _Dscale(ptr long) @ cdecl _Dtest(ptr) @ extern _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm @ stub _FDnorm @ cdecl _FDscale(ptr long) @ cdecl _FDtest(ptr) @ extern _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf @ extern _FNan # extern _FRteps diff --git a/dlls/msvcp110/msvcp110.spec b/dlls/msvcp110/msvcp110.spec index a3776cf2e35..b8d21eb5963 100644 --- a/dlls/msvcp110/msvcp110.spec +++ b/dlls/msvcp110/msvcp110.spec @@ -3748,7 +3748,7 @@ @ cdecl _Dtest(ptr) @ stub _Dunscale @ extern _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm @ stub _FDint @@ -3758,7 +3758,7 @@ @ cdecl _FDtest(ptr) @ stub _FDunscale @ extern _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf @ extern _FNan # extern _FRteps diff --git a/dlls/msvcp120/msvcp120.spec b/dlls/msvcp120/msvcp120.spec index 2b07f13a05c..0458b0144ea 100644 --- a/dlls/msvcp120/msvcp120.spec +++ b/dlls/msvcp120/msvcp120.spec @@ -3689,7 +3689,7 @@ @ cdecl _Dtest(ptr) @ stub _Dunscale @ extern _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm @ stub _FDint @@ -3699,7 +3699,7 @@ @ cdecl _FDtest(ptr) @ stub _FDunscale @ extern _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf @ extern _FNan @ stub _FPlsw diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c index 358c4087eb6..d754191929d 100644 --- a/dlls/msvcp120/tests/msvcp120.c +++ b/dlls/msvcp120/tests/msvcp120.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "wine/test.h" #include "winbase.h" @@ -65,6 +66,22 @@ enum file_type { type_unknown }; +static BOOL compare_float(float f, float g, unsigned int ulps) +{ + int x = *(int *)&f; + int y = *(int *)&g; + + if (x < 0) + x = INT_MIN - x; + if (y < 0) + y = INT_MIN - y; + + if (abs(x - y) > ulps) + return FALSE; + + return TRUE; +} + static inline const char* debugstr_longlong(ULONGLONG ll) { static char string[17]; @@ -87,6 +104,7 @@ static void (CDECL *p__Call_onceEx)(int *once, void (CDECL *func)(void*), void * static void (CDECL *p__Do_call)(void *this); static short (__cdecl *p__Dtest)(double *d); static short (__cdecl *p__Dscale)(double *d, int exp); +static short (__cdecl *p__FExp)(float *x, float y, int exp); /* filesystem */ static ULONGLONG(__cdecl *p_tr2_sys__File_size)(char const*); @@ -142,6 +160,8 @@ static BOOL init(void) "_Dtest"); SET(p__Dscale, "_Dscale"); + SET(p__FExp, + "_FExp"); if(sizeof(void*) == 8) { /* 64-bit initialization */ SET(p_tr2_sys__File_size, "?_File_size@sys@tr2@std@@YA_KPEBD@Z"); @@ -514,6 +534,61 @@ static void test__Dscale(void) ok(ret == FP_NAN, "ret = %x\n", ret); } +static void test__FExp(void) +{ + float d; + short ret; + + d = 0; + ret = p__FExp(&d, 0, 0); + ok(d == 0, "d = %f\n", d); + ok(ret == FP_ZERO, "ret = %x\n", ret); + + d = 0; + ret = p__FExp(&d, 1, 0); + ok(d == 1.0, "d = %f\n", d); + ok(ret == FP_NORMAL, "ret = %x\n", ret); + + d = 0; + ret = p__FExp(&d, 1, 1); + ok(d == 2.0, "d = %f\n", d); + ok(ret == FP_NORMAL, "ret = %x\n", ret); + + d = 0; + ret = p__FExp(&d, 1, 2); + ok(d == 4.0, "d = %f\n", d); + ok(ret == FP_NORMAL, "ret = %x\n", ret); + + d = 0; + ret = p__FExp(&d, 10, 0); + ok(d == 10.0, "d = %f\n", d); + ok(ret == FP_NORMAL, "ret = %x\n", ret); + + d = 1; + ret = p__FExp(&d, 0, 0); + ok(d == 0, "d = %f\n", d); + ok(ret == FP_ZERO, "ret = %x\n", ret); + + d = 1; + ret = p__FExp(&d, 1, 0); + ok(compare_float(d, 2.7182817, 4), "d = %f\n", d); + ok(ret == FP_NORMAL, "ret = %x\n", ret); + + d = 9e20; + ret = p__FExp(&d, 0, 0); + ok(d == 0, "d = %f\n", d); + ok(ret == FP_ZERO, "ret = %x\n", ret); + + d = 90; + ret = p__FExp(&d, 1, 0); + ok(ret == FP_INFINITE, "ret = %x\n", ret); + + d = 90; + ret = p__FExp(&d, 1, -50); + ok(compare_float(d, 1.0839359e+024, 4), "d = %g\n", d); + ok(ret == FP_NORMAL, "ret = %x\n", ret); +} + static void test_tr2_sys__File_size(void) { ULONGLONG val; @@ -1055,6 +1130,7 @@ START_TEST(msvcp120) test__Do_call(); test__Dtest(); test__Dscale(); + test__FExp(); test_tr2_sys__File_size(); test_tr2_sys__Equivalent(); diff --git a/dlls/msvcp120_app/msvcp120_app.spec b/dlls/msvcp120_app/msvcp120_app.spec index 1470b3c5106..25989046585 100644 --- a/dlls/msvcp120_app/msvcp120_app.spec +++ b/dlls/msvcp120_app/msvcp120_app.spec @@ -3689,7 +3689,7 @@ @ cdecl _Dtest(ptr) msvcp120._Dtest @ stub _Dunscale @ extern _Eps msvcp120._Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) msvcp120._Exp @ stub _FCosh @ extern _FDenorm msvcp120._FDenorm @ stub _FDint @@ -3699,7 +3699,7 @@ @ cdecl _FDtest(ptr) msvcp120._FDtest @ stub _FDunscale @ extern _FEps msvcp120._FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) msvcp120._FExp @ extern _FInf msvcp120._FInf @ extern _FNan msvcp120._FNan @ stub _FPlsw diff --git a/dlls/msvcp60/msvcp60.spec b/dlls/msvcp60/msvcp60.spec index 05d0435ab21..48f1add3fea 100644 --- a/dlls/msvcp60/msvcp60.spec +++ b/dlls/msvcp60/msvcp60.spec @@ -4260,14 +4260,14 @@ @ cdecl _Dscale(ptr long) @ cdecl _Dtest(ptr) @ extern _Eps _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm _FDenorm @ stub _FDnorm @ cdecl _FDscale(ptr long) @ cdecl _FDtest(ptr) @ extern _FEps _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf _FInf @ extern _FNan _FNan # extern _FRteps diff --git a/dlls/msvcp70/msvcp70.spec b/dlls/msvcp70/msvcp70.spec index a6f5ef3b335..f97c87c1f8c 100644 --- a/dlls/msvcp70/msvcp70.spec +++ b/dlls/msvcp70/msvcp70.spec @@ -5046,14 +5046,14 @@ @ cdecl _Dscale(ptr long) @ cdecl _Dtest(ptr) @ extern _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm @ stub _FDnorm @ cdecl _FDscale(ptr long) @ cdecl _FDtest(ptr) @ extern _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf @ extern _FNan # extern _FRteps diff --git a/dlls/msvcp71/msvcp71.spec b/dlls/msvcp71/msvcp71.spec index ba2fcaf0c4f..46e52138986 100644 --- a/dlls/msvcp71/msvcp71.spec +++ b/dlls/msvcp71/msvcp71.spec @@ -5100,14 +5100,14 @@ @ cdecl _Dscale(ptr long) @ cdecl _Dtest(ptr) @ extern _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm @ stub _FDnorm @ cdecl _FDscale(ptr long) @ cdecl _FDtest(ptr) @ extern _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf @ extern _FNan # extern _FRteps diff --git a/dlls/msvcp80/msvcp80.spec b/dlls/msvcp80/msvcp80.spec index d801608e0f4..f6bec69952e 100644 --- a/dlls/msvcp80/msvcp80.spec +++ b/dlls/msvcp80/msvcp80.spec @@ -5708,7 +5708,7 @@ @ cdecl _Dtest(ptr) @ stub _Dunscale @ extern _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm @ stub _FDnorm @@ -5717,7 +5717,7 @@ @ cdecl _FDtest(ptr) @ stub _FDunscale @ extern _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf @ extern _FNan # extern _FRteps diff --git a/dlls/msvcp90/math.c b/dlls/msvcp90/math.c index 2d9996db2d6..6c3a33a7e94 100644 --- a/dlls/msvcp90/math.c +++ b/dlls/msvcp90/math.c @@ -2274,3 +2274,45 @@ short __cdecl _FDscale(float *x, int exp) *x *= pow(2, exp); return dclass(*x); } + +/* _Exp */ +/* computes y * e^(*x) * 2^scale */ +short __cdecl _Exp(double *x, double y, int scale) +{ + double ed; + int e; + + if(y == 0) { + *x = 0; + return FP_ZERO; + } + + *x /= M_LN2; + ed = floor(*x); + *x -= ed; + e = ed; + + if(ed!=e && ed>0) + scale = INT_MAX; + else if(ed!=e && ed<0) + scale = INT_MIN; + else if(scale>0 && e>0 && scale+e<=0) + scale = INT_MAX; + else if(scale<0 && e<0 && scale+e>=0) + scale = INT_MIN; + else + scale += e; + + *x = y * pow(2.0, *x); + return _Dscale(x, scale); +} + +/* _FExp */ +short __cdecl _FExp(float *x, float y, short scale) +{ + double d = *x; + _Exp(&d, y, scale); + *x = d; + + return dclass(*x); +} diff --git a/dlls/msvcp90/msvcp90.spec b/dlls/msvcp90/msvcp90.spec index f2e3a5bca40..a0ba849efb7 100644 --- a/dlls/msvcp90/msvcp90.spec +++ b/dlls/msvcp90/msvcp90.spec @@ -6482,14 +6482,14 @@ @ cdecl _Dscale(ptr long) @ cdecl _Dtest(ptr) @ extern _Eps -@ stub _Exp +@ cdecl _Exp(ptr double long) @ stub _FCosh @ extern _FDenorm @ stub _FDnorm @ cdecl _FDscale(ptr long) @ cdecl _FDtest(ptr) @ extern _FEps -@ stub _FExp +@ cdecl _FExp(ptr float long) @ extern _FInf @ extern _FNan # extern _FRteps