[PATCH] msvcr120: Implement more C99 math functions.

Martin Storsjo martin at martin.st
Sat Dec 6 10:07:10 CST 2014


Implement the cbrt, exp2, log2, *rint, *round and trunc
function families.

Add configure tests for all the used host libc functions, use
simple fallback implementations in case they aren't available.

The -l suffixed versions (for long doubles, which in the windows
environment are equal to normal doubles) simply call the corresponding
normal double version. (Or should these just be mapped to the normal
double functions in the spec file?)

The float versions fall back on the double version if the correct
float version of the function isn't available in the host libc.
---
 configure.ac                |  23 ++++
 dlls/msvcr120/msvcr120.spec |  60 ++++-----
 dlls/msvcrt/math.c          | 321 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 374 insertions(+), 30 deletions(-)

diff --git a/configure.ac b/configure.ac
index 87ce48c..ce1821a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2572,6 +2572,29 @@ if test "$ac_cv_have_isnan" = "yes"
 then
     AC_DEFINE(HAVE_ISNAN, 1, [Define to 1 if you have the `isnan' function.])
 fi
+
+AC_CHECK_FUNCS(\
+	cbrt \
+	cbrtf \
+	exp2 \
+	exp2f \
+	llrint \
+	llrintf \
+	llround \
+	llroundf \
+	log2 \
+	log2f \
+	lrint \
+	lrintf \
+	lround \
+	lroundf \
+	rint \
+	rintf \
+	round \
+	roundf \
+	trunc \
+	truncf
+)
 LIBS="$ac_save_LIBS"
 
 dnl *** check for the need to define platform-specific symbols
diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec
index d0ba290..e0e4661 100644
--- a/dlls/msvcr120/msvcr120.spec
+++ b/dlls/msvcr120/msvcr120.spec
@@ -2058,9 +2058,9 @@
 @ stub catanhf
 @ stub catanhl
 @ stub catanl
-@ stub cbrt
-@ stub cbrtf
-@ stub cbrtl
+@ cdecl cbrt(double) MSVCR120_cbrt
+@ cdecl cbrtf(float) MSVCR120_cbrtf
+@ cdecl cbrtl(double) MSVCR120_cbrtl
 @ stub ccos
 @ stub ccosf
 @ stub ccosh
@@ -2127,9 +2127,9 @@
 @ stub erfl
 @ cdecl exit(long) MSVCRT_exit
 @ cdecl exp(double) MSVCRT_exp
-@ stub exp2
-@ stub exp2f
-@ stub exp2l
+@ cdecl exp2(double) MSVCR120_exp2
+@ cdecl exp2f(float) MSVCR120_exp2f
+@ cdecl exp2l(double) MSVCR120_exp2l
 @ cdecl -arch=arm,x86_64 expf(float) MSVCRT_expf
 @ stub expm1
 @ stub expm1f
@@ -2245,12 +2245,12 @@
 @ stub lgammal
 @ cdecl -ret64 llabs(int64) MSVCRT_llabs
 @ stub lldiv
-@ stub llrint
-@ stub llrintf
-@ stub llrintl
-@ stub llround
-@ stub llroundf
-@ stub llroundl
+@ cdecl -ret64 llrint(double) MSVCR120_llrint
+@ cdecl -ret64 llrintf(float) MSVCR120_llrintf
+@ cdecl -ret64 llrintl(double) MSVCR120_llrintl
+@ cdecl -ret64 llround(double) MSVCR120_llround
+@ cdecl -ret64 llroundf(float) MSVCR120_llroundf
+@ cdecl -ret64 llroundl(double) MSVCR120_llroundl
 @ cdecl localeconv() MSVCRT_localeconv
 @ cdecl log(double) MSVCRT_log
 @ cdecl -arch=arm,x86_64 logf(float) MSVCRT_logf
@@ -2259,19 +2259,19 @@
 @ stub log1p
 @ stub log1pf
 @ stub log1pl
-@ stub log2
-@ stub log2f
-@ stub log2l
+@ cdecl log2(double) MSVCR120_log2
+@ cdecl log2f(float) MSVCR120_log2f
+@ cdecl log2l(double) MSVCR120_log2l
 @ stub logb
 @ stub logbf
 @ stub logbl
 @ cdecl -arch=i386,x86_64,arm longjmp(ptr long) MSVCRT_longjmp
-@ stub lrint
-@ stub lrintf
-@ stub lrintl
-@ stub lround
-@ stub lroundf
-@ stub lroundl
+@ cdecl lrint(double) MSVCR120_lrint
+@ cdecl lrintf(float) MSVCR120_lrintf
+@ cdecl lrintl(double) MSVCR120_lrintl
+@ cdecl lround(double) MSVCR120_lround
+@ cdecl lroundf(float) MSVCR120_lroundf
+@ cdecl lroundl(double) MSVCR120_lroundl
 @ cdecl malloc(long) MSVCRT_malloc
 @ cdecl mblen(ptr long) MSVCRT_mblen
 @ cdecl mbrlen(ptr long ptr) MSVCRT_mbrlen
@@ -2330,12 +2330,12 @@
 @ stub remquol
 @ cdecl rename(str str) MSVCRT_rename
 @ cdecl rewind(ptr) MSVCRT_rewind
-@ stub rint
-@ stub rintf
-@ stub rintl
-@ stub round
-@ stub roundf
-@ stub roundl
+@ cdecl rint(double) MSVCR120_rint
+@ cdecl rintf(float) MSVCR120_rintf
+@ cdecl rintl(double) MSVCR120_rintl
+@ cdecl round(double) MSVCR120_round
+@ cdecl roundf(float) MSVCR120_roundf
+@ cdecl roundl(double) MSVCR120_roundl
 @ stub scalbln
 @ stub scalblnf
 @ stub scalblnl
@@ -2414,9 +2414,9 @@
 @ stub towctrans
 @ cdecl towlower(long) MSVCRT_towlower
 @ cdecl towupper(long) MSVCRT_towupper
-@ stub trunc
-@ stub truncf
-@ stub truncl
+@ cdecl trunc(double) MSVCR120_trunc
+@ cdecl truncf(float) MSVCR120_truncf
+@ cdecl truncl(double) MSVCR120_truncl
 @ cdecl ungetc(long ptr) MSVCRT_ungetc
 @ cdecl ungetwc(long ptr) MSVCRT_ungetwc
 @ cdecl vfprintf(ptr str ptr) MSVCRT_vfprintf
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index d67b2e8..e74b714 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -39,6 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 #endif
 
 typedef int (CDECL *MSVCRT_matherr_func)(struct MSVCRT__exception *);
+typedef double LDOUBLE;  /* long double is just a double */
 
 static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
 
@@ -2205,3 +2206,323 @@ void __cdecl __libm_sse2_sqrt_precise(void)
 }
 
 #endif  /* __i386__ */
+
+/*********************************************************************
+ *      cbrt (MSVCR120.@)
+ */
+double CDECL MSVCR120_cbrt(double x)
+{
+#ifdef HAVE_CBRT
+    return cbrt(x);
+#else
+    return x < 0 ? -powf(-x, 1.0 / 3.0) : powf(x, 1.0 / 3.0);
+#endif
+}
+
+/*********************************************************************
+ *      cbrtf (MSVCR120.@)
+ */
+float CDECL MSVCR120_cbrtf(float x)
+{
+#ifdef HAVE_CBRTF
+    return cbrtf(x);
+#else
+    return MSVCR120_cbrt(x);
+#endif
+}
+
+/*********************************************************************
+ *      cbrtl (MSVCR120.@)
+ */
+LDOUBLE CDECL MSVCR120_cbrtl(LDOUBLE x)
+{
+    return MSVCR120_cbrt(x);
+}
+
+/*********************************************************************
+ *      exp2 (MSVCR120.@)
+ */
+double CDECL MSVCR120_exp2(double x)
+{
+#ifdef HAVE_EXP2
+    return exp2(x);
+#else
+    return pow(2, x);
+#endif
+}
+
+/*********************************************************************
+ *      exp2f (MSVCR120.@)
+ */
+float CDECL MSVCR120_exp2f(float x)
+{
+#ifdef HAVE_EXP2F
+    return exp2f(x);
+#else
+    return MSVCR120_exp2(x);
+#endif
+}
+
+/*********************************************************************
+ *      exp2l (MSVCR120.@)
+ */
+LDOUBLE CDECL MSVCR120_exp2l(LDOUBLE x)
+{
+    return MSVCR120_exp2(x);
+}
+
+/*********************************************************************
+ *      log2 (MSVCR120.@)
+ */
+double CDECL MSVCR120_log2(double x)
+{
+#ifdef HAVE_LOG2
+    return log2(x);
+#else
+    return log(x) / log(2);
+#endif
+}
+
+/*********************************************************************
+ *      log2f (MSVCR120.@)
+ */
+float CDECL MSVCR120_log2f(float x)
+{
+#ifdef HAVE_LOG2F
+    return log2f(x);
+#else
+    return MSVCR120_log2(x);
+#endif
+}
+
+/*********************************************************************
+ *      log2l (MSVCR120.@)
+ */
+LDOUBLE CDECL MSVCR120_log2l(LDOUBLE x)
+{
+    return MSVCR120_log2(x);
+}
+
+/*********************************************************************
+ *      rint (MSVCR120.@)
+ */
+double CDECL MSVCR120_rint(double x)
+{
+#ifdef HAVE_RINT
+    return rint(x);
+#else
+    return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5);
+#endif
+}
+
+/*********************************************************************
+ *      rintf (MSVCR120.@)
+ */
+float CDECL MSVCR120_rintf(float x)
+{
+#ifdef HAVE_RINTF
+    return rintf(x);
+#else
+    return MSVCR120_rint(x);
+#endif
+}
+
+/*********************************************************************
+ *      rintl (MSVCR120.@)
+ */
+LDOUBLE CDECL MSVCR120_rintl(LDOUBLE x)
+{
+    return MSVCR120_rint(x);
+}
+
+/*********************************************************************
+ *      lrint (MSVCR120.@)
+ */
+MSVCRT_long CDECL MSVCR120_lrint(double x)
+{
+#ifdef HAVE_LRINT
+    return lrint(x);
+#else
+    return MSVCR120_rint(x);
+#endif
+}
+
+/*********************************************************************
+ *      lrintf (MSVCR120.@)
+ */
+MSVCRT_long CDECL MSVCR120_lrintf(float x)
+{
+#ifdef HAVE_LRINTF
+    return lrintf(x);
+#else
+    return MSVCR120_lrint(x);
+#endif
+}
+
+/*********************************************************************
+ *      lrintl (MSVCR120.@)
+ */
+MSVCRT_long CDECL MSVCR120_lrintl(LDOUBLE x)
+{
+    return MSVCR120_lrint(x);
+}
+
+/*********************************************************************
+ *      llrint (MSVCR120.@)
+ */
+MSVCRT_longlong CDECL MSVCR120_llrint(double x)
+{
+#ifdef HAVE_LLRINT
+    return llrint(x);
+#else
+    return MSVCR120_rint(x);
+#endif
+}
+
+/*********************************************************************
+ *      llrintf (MSVCR120.@)
+ */
+MSVCRT_longlong CDECL MSVCR120_llrintf(float x)
+{
+#ifdef HAVE_LLRINTF
+    return llrintf(x);
+#else
+    return MSVCR120_llrint(x);
+#endif
+}
+
+/*********************************************************************
+ *      rintl (MSVCR120.@)
+ */
+MSVCRT_longlong CDECL MSVCR120_llrintl(LDOUBLE x)
+{
+    return MSVCR120_llrint(x);
+}
+
+/*********************************************************************
+ *      round (MSVCR120.@)
+ */
+double CDECL MSVCR120_round(double x)
+{
+#ifdef HAVE_ROUND
+    return round(x);
+#else
+    return MSVCR120_rint(x);
+#endif
+}
+
+/*********************************************************************
+ *      roundf (MSVCR120.@)
+ */
+float CDECL MSVCR120_roundf(float x)
+{
+#ifdef HAVE_ROUNDF
+    return roundf(x);
+#else
+    return MSVCR120_round(x);
+#endif
+}
+
+/*********************************************************************
+ *      roundl (MSVCR120.@)
+ */
+LDOUBLE CDECL MSVCR120_roundl(LDOUBLE x)
+{
+    return MSVCR120_round(x);
+}
+
+/*********************************************************************
+ *      lround (MSVCR120.@)
+ */
+MSVCRT_long CDECL MSVCR120_lround(double x)
+{
+#ifdef HAVE_LROUND
+    return lround(x);
+#else
+    return MSVCR120_round(x);
+#endif
+}
+
+/*********************************************************************
+ *      lroundf (MSVCR120.@)
+ */
+MSVCRT_long CDECL MSVCR120_lroundf(float x)
+{
+#ifdef HAVE_LROUNDF
+    return lroundf(x);
+#else
+    return MSVCR120_lround(x);
+#endif
+}
+
+/*********************************************************************
+ *      lroundl (MSVCR120.@)
+ */
+MSVCRT_long CDECL MSVCR120_lroundl(LDOUBLE x)
+{
+    return MSVCR120_lround(x);
+}
+
+/*********************************************************************
+ *      llround (MSVCR120.@)
+ */
+MSVCRT_longlong CDECL MSVCR120_llround(double x)
+{
+#ifdef HAVE_LLROUND
+    return llround(x);
+#else
+    return MSVCR120_round(x);
+#endif
+}
+
+/*********************************************************************
+ *      llroundf (MSVCR120.@)
+ */
+MSVCRT_longlong CDECL MSVCR120_llroundf(float x)
+{
+#ifdef HAVE_LLROUNDF
+    return llroundf(x);
+#else
+    return MSVCR120_llround(x);
+#endif
+}
+
+/*********************************************************************
+ *      roundl (MSVCR120.@)
+ */
+MSVCRT_longlong CDECL MSVCR120_llroundl(LDOUBLE x)
+{
+    return MSVCR120_llround(x);
+}
+
+/*********************************************************************
+ *      trunc (MSVCR120.@)
+ */
+double CDECL MSVCR120_trunc(double x)
+{
+#ifdef HAVE_TRUNC
+    return trunc(x);
+#else
+    return (x > 0) ? floor(x) : ceil(x);
+#endif
+}
+
+/*********************************************************************
+ *      truncf (MSVCR120.@)
+ */
+float CDECL MSVCR120_truncf(float x)
+{
+#ifdef HAVE_TRUNCF
+    return truncf(x);
+#else
+    return MSVCR120_trunc(x);
+#endif
+}
+
+/*********************************************************************
+ *      truncl (MSVCR120.@)
+ */
+LDOUBLE CDECL MSVCR120_truncl(LDOUBLE x)
+{
+    return MSVCR120_trunc(x);
+}
-- 
1.8.1.2




More information about the wine-patches mailing list