msvcrt: Implement fma and fmaf.
Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ef07087f47
commit
fa54e895a7
|
@ -631,7 +631,6 @@ RT_LIBS
|
|||
POLL_LIBS
|
||||
DL_LIBS
|
||||
TOOLSEXT
|
||||
UNWINDFLAGS
|
||||
MSVCRTFLAGS
|
||||
EXCESS_PRECISION_CFLAGS
|
||||
EXTRACFLAGS
|
||||
|
@ -19147,6 +19146,8 @@ for ac_func in \
|
|||
exp2f \
|
||||
expm1 \
|
||||
expm1f \
|
||||
fma \
|
||||
fmaf \
|
||||
ilogb \
|
||||
ilogbf \
|
||||
j0 \
|
||||
|
|
|
@ -2634,6 +2634,8 @@ AC_CHECK_FUNCS(\
|
|||
exp2f \
|
||||
expm1 \
|
||||
expm1f \
|
||||
fma \
|
||||
fmaf \
|
||||
ilogb \
|
||||
ilogbf \
|
||||
j0 \
|
||||
|
|
|
@ -241,8 +241,8 @@
|
|||
@ stub fdiml
|
||||
@ cdecl floor(double) ucrtbase.floor
|
||||
@ cdecl -arch=arm,x86_64,arm64 floorf(float) ucrtbase.floorf
|
||||
@ stub fma
|
||||
@ stub fmaf
|
||||
@ cdecl fma(double double double) ucrtbase.fma
|
||||
@ cdecl -arch=arm,x86_64,arm64 fmaf(float float float) ucrtbase.fmaf
|
||||
@ stub fmal
|
||||
@ cdecl fmax(double double) ucrtbase.fmax
|
||||
@ cdecl fmaxf(float float) ucrtbase.fmaxf
|
||||
|
|
|
@ -2164,8 +2164,8 @@
|
|||
@ cdecl fgetws(ptr long ptr) MSVCRT_fgetws
|
||||
@ cdecl floor(double) MSVCRT_floor
|
||||
@ cdecl -arch=arm,x86_64,arm64 floorf(float) MSVCRT_floorf
|
||||
@ stub fma
|
||||
@ stub fmaf
|
||||
@ cdecl fma(double double double) MSVCRT_fma
|
||||
@ cdecl -arch=arm,x86_64,arm64 fmaf(float float float) MSVCRT_fmaf
|
||||
@ stub fmal
|
||||
@ cdecl fmax(double double) MSVCR120_fmax
|
||||
@ cdecl fmaxf(float float) MSVCR120_fmaxf
|
||||
|
|
|
@ -1830,8 +1830,8 @@
|
|||
@ cdecl fgetws(ptr long ptr) msvcr120.fgetws
|
||||
@ cdecl floor(double) msvcr120.floor
|
||||
@ cdecl -arch=arm,x86_64,arm64 floorf(float) msvcr120.floorf
|
||||
@ stub fma
|
||||
@ stub fmaf
|
||||
@ cdecl fma(double double double) msvcr120.fma
|
||||
@ cdecl -arch=arm,x86_64,arm64 fmaf(float float float) msvcr120.fmaf
|
||||
@ stub fmal
|
||||
@ cdecl fmax(double double) msvcr120.fmax
|
||||
@ cdecl fmaxf(float float) msvcr120.fmaxf
|
||||
|
|
|
@ -387,6 +387,22 @@ float CDECL MSVCRT_floorf( float x )
|
|||
return floorf(x);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* fmaf (MSVCRT.@)
|
||||
*/
|
||||
float CDECL MSVCRT_fmaf( float x, float y, float z )
|
||||
{
|
||||
#ifdef HAVE_FMAF
|
||||
float w = fmaf(x, y, z);
|
||||
#else
|
||||
float w = x * y + z;
|
||||
#endif
|
||||
if ((isinf(x) && y == 0) || (x == 0 && isinf(y))) *MSVCRT__errno() = MSVCRT_EDOM;
|
||||
else if (isinf(x) && isinf(z) && x != z) *MSVCRT__errno() = MSVCRT_EDOM;
|
||||
else if (isinf(y) && isinf(z) && y != z) *MSVCRT__errno() = MSVCRT_EDOM;
|
||||
return w;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* frexpf (MSVCRT.@)
|
||||
*/
|
||||
|
@ -863,6 +879,22 @@ double CDECL MSVCRT_floor( double x )
|
|||
return floor(x);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* fma (MSVCRT.@)
|
||||
*/
|
||||
double CDECL MSVCRT_fma( double x, double y, double z )
|
||||
{
|
||||
#ifdef HAVE_FMA
|
||||
double w = fma(x, y, z);
|
||||
#else
|
||||
double w = x * y + z;
|
||||
#endif
|
||||
if ((isinf(x) && y == 0) || (x == 0 && isinf(y))) *MSVCRT__errno() = MSVCRT_EDOM;
|
||||
else if (isinf(x) && isinf(z) && x != z) *MSVCRT__errno() = MSVCRT_EDOM;
|
||||
else if (isinf(y) && isinf(z) && y != z) *MSVCRT__errno() = MSVCRT_EDOM;
|
||||
return w;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* fabs (MSVCRT.@)
|
||||
*/
|
||||
|
|
|
@ -1288,6 +1288,8 @@
|
|||
@ cdecl fgetws(ptr long ptr) MSVCRT_fgetws
|
||||
@ cdecl floor(double) MSVCRT_floor
|
||||
@ cdecl -arch=arm,x86_64,arm64 floorf(float) MSVCRT_floorf
|
||||
@ cdecl fma(double double double) MSVCRT_fma
|
||||
@ cdecl -arch=arm,x86_64,arm64 fmaf(float float float) MSVCRT_fmaf
|
||||
@ cdecl fmod(double double) MSVCRT_fmod
|
||||
@ cdecl -arch=arm,x86_64,arm64 fmodf(float float) MSVCRT_fmodf
|
||||
@ cdecl fopen(str str) MSVCRT_fopen
|
||||
|
|
|
@ -64,6 +64,25 @@ static inline float __port_infinity(void)
|
|||
}
|
||||
#define INFINITY __port_infinity()
|
||||
|
||||
static inline float __port_nan(void)
|
||||
{
|
||||
static const unsigned __nan_bytes = 0x7fc00000;
|
||||
return *(const float *)&__nan_bytes;
|
||||
}
|
||||
#define NAN __port_nan()
|
||||
|
||||
static inline double __port_min_pos_double(void)
|
||||
{
|
||||
static const UINT64 __min_pos_double = 0x10000000000000;
|
||||
return *(const double *)&__min_pos_double;
|
||||
}
|
||||
|
||||
static inline double __port_max_double(void)
|
||||
{
|
||||
static const UINT64 __max_double = 0x7FEFFFFFFFFFFFFF;
|
||||
return *(const double *)&__max_double;
|
||||
}
|
||||
|
||||
#define M_PI_2 1.57079632679489661923
|
||||
|
||||
#define FE_TONEAREST 0
|
||||
|
@ -747,6 +766,30 @@ static void test_math_errors(void)
|
|||
{"pow", INFINITY, 1, -1, -1},
|
||||
{"pow", INFINITY, 2, -1, -1},
|
||||
};
|
||||
const struct {
|
||||
char func[16];
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
int error;
|
||||
int exception;
|
||||
} tests3d[] = {
|
||||
/* 0 * inf --> EDOM */
|
||||
{"fma", INFINITY, 0, 0, EDOM, -1},
|
||||
{"fma", 0, INFINITY, 0, EDOM, -1},
|
||||
/* inf - inf -> EDOM */
|
||||
{"fma", INFINITY, 1, -INFINITY, EDOM, -1},
|
||||
{"fma", -INFINITY, 1, INFINITY, EDOM, -1},
|
||||
{"fma", 1, INFINITY, -INFINITY, EDOM, -1},
|
||||
{"fma", 1, -INFINITY, INFINITY, EDOM, -1},
|
||||
/* NaN */
|
||||
{"fma", NAN, 0, 0, -1, -1},
|
||||
{"fma", 0, NAN, 0, -1, -1},
|
||||
{"fma", 0, 0, NAN, -1, -1},
|
||||
/* over/underflow */
|
||||
{"fma", __port_max_double(), __port_max_double(), __port_max_double(), -1, -1},
|
||||
{"fma", __port_min_pos_double(), __port_min_pos_double(), 1, -1, -1},
|
||||
};
|
||||
const struct {
|
||||
char func[16];
|
||||
double a;
|
||||
|
@ -770,6 +813,7 @@ static void test_math_errors(void)
|
|||
};
|
||||
double (CDECL *p_funcd)(double);
|
||||
double (CDECL *p_func2d)(double, double);
|
||||
double (CDECL *p_func3d)(double, double, double);
|
||||
double (CDECL *p_funcdl)(double, long);
|
||||
int i;
|
||||
|
||||
|
@ -808,6 +852,22 @@ static void test_math_errors(void)
|
|||
"%s(%f, %f) got exception arg2 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg2);
|
||||
}
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(tests3d); i++) {
|
||||
p_func3d = (void*)GetProcAddress(module, tests3d[i].func);
|
||||
*p_errno() = -1;
|
||||
exception.type = -1;
|
||||
p_func3d(tests3d[i].a, tests3d[i].b, tests3d[i].c);
|
||||
ok(*p_errno() == tests3d[i].error,
|
||||
"%s(%f, %f, %f) got errno %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, *p_errno());
|
||||
ok(exception.type == tests3d[i].exception,
|
||||
"%s(%f, %f, %f) got exception type %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.type);
|
||||
if(exception.type == -1) continue;
|
||||
ok(exception.arg1 == tests3d[i].a,
|
||||
"%s(%f, %f, %f) got exception arg1 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg1);
|
||||
ok(exception.arg2 == tests3d[i].b,
|
||||
"%s(%f, %f, %f) got exception arg2 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg2);
|
||||
}
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(testsdl); i++) {
|
||||
p_funcdl = (void*)GetProcAddress(module, testsdl[i].func);
|
||||
*p_errno() = -1;
|
||||
|
|
|
@ -2305,8 +2305,8 @@
|
|||
@ cdecl fgetws(ptr long ptr) MSVCRT_fgetws
|
||||
@ cdecl floor(double) MSVCRT_floor
|
||||
@ cdecl -arch=arm,x86_64,arm64 floorf(float) MSVCRT_floorf
|
||||
@ stub fma
|
||||
@ stub fmaf
|
||||
@ cdecl fma(double double double) MSVCRT_fma
|
||||
@ cdecl -arch=arm,x86_64,arm64 fmaf(float float float) MSVCRT_fmaf
|
||||
@ stub fmal
|
||||
@ cdecl fmax(double double) MSVCR120_fmax
|
||||
@ cdecl fmaxf(float float) MSVCR120_fmaxf
|
||||
|
|
|
@ -161,6 +161,12 @@
|
|||
/* Define to 1 if you have the <float.h> header file. */
|
||||
#undef HAVE_FLOAT_H
|
||||
|
||||
/* Define to 1 if you have the `fma' function. */
|
||||
#undef HAVE_FMA
|
||||
|
||||
/* Define to 1 if you have the `fmaf' function. */
|
||||
#undef HAVE_FMAF
|
||||
|
||||
/* Define to 1 if you have the `fnmatch' function. */
|
||||
#undef HAVE_FNMATCH
|
||||
|
||||
|
|
Loading…
Reference in New Issue