Andrew Eikum : msvcrt: Implement fma and fmaf.

Alexandre Julliard julliard at winehq.org
Wed May 22 15:52:06 CDT 2019


Module: wine
Branch: master
Commit: fa54e895a784038e56a62ef7515429f6610dc2b6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=fa54e895a784038e56a62ef7515429f6610dc2b6

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Tue May 21 16:50:42 2019 -0500

msvcrt: Implement fma and fmaf.

Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 configure                                          |  3 +-
 configure.ac                                       |  2 +
 .../api-ms-win-crt-math-l1-1-0.spec                |  4 +-
 dlls/msvcr120/msvcr120.spec                        |  4 +-
 dlls/msvcr120_app/msvcr120_app.spec                |  4 +-
 dlls/msvcrt/math.c                                 | 32 ++++++++++++
 dlls/msvcrt/msvcrt.spec                            |  2 +
 dlls/ucrtbase/tests/misc.c                         | 60 ++++++++++++++++++++++
 dlls/ucrtbase/ucrtbase.spec                        |  4 +-
 include/config.h.in                                |  6 +++
 10 files changed, 112 insertions(+), 9 deletions(-)

diff --git a/configure b/configure
index 69d085c..c206e8d 100755
--- a/configure
+++ b/configure
@@ -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 \
diff --git a/configure.ac b/configure.ac
index 0490b53..83a8181 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2634,6 +2634,8 @@ AC_CHECK_FUNCS(\
 	exp2f \
 	expm1 \
 	expm1f \
+	fma \
+	fmaf \
 	ilogb \
 	ilogbf \
 	j0 \
diff --git a/dlls/api-ms-win-crt-math-l1-1-0/api-ms-win-crt-math-l1-1-0.spec b/dlls/api-ms-win-crt-math-l1-1-0/api-ms-win-crt-math-l1-1-0.spec
index 75ecaf1..3a5991f 100644
--- a/dlls/api-ms-win-crt-math-l1-1-0/api-ms-win-crt-math-l1-1-0.spec
+++ b/dlls/api-ms-win-crt-math-l1-1-0/api-ms-win-crt-math-l1-1-0.spec
@@ -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
diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec
index 92ac324..63dc44d 100644
--- a/dlls/msvcr120/msvcr120.spec
+++ b/dlls/msvcr120/msvcr120.spec
@@ -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
diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec
index af6b0fe..9b7727e 100644
--- a/dlls/msvcr120_app/msvcr120_app.spec
+++ b/dlls/msvcr120_app/msvcr120_app.spec
@@ -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
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 049c340..63744e3 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -388,6 +388,22 @@ float CDECL MSVCRT_floorf( float 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.@)
  */
 float CDECL MSVCRT_frexpf( float x, int *exp )
@@ -864,6 +880,22 @@ double CDECL MSVCRT_floor( double 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.@)
  */
 double CDECL MSVCRT_fabs( double x )
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 952de55..f464db2 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -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
diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c
index ddb7938..7559ede 100644
--- a/dlls/ucrtbase/tests/misc.c
+++ b/dlls/ucrtbase/tests/misc.c
@@ -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
@@ -750,6 +769,30 @@ static void test_math_errors(void)
     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;
         long b;
         int error;
         int exception;
@@ -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;
diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec
index b7f814a..c64fee2 100644
--- a/dlls/ucrtbase/ucrtbase.spec
+++ b/dlls/ucrtbase/ucrtbase.spec
@@ -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
diff --git a/include/config.h.in b/include/config.h.in
index 7998764..774e9ee 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -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
 




More information about the wine-cvs mailing list