Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fix numeric precision for strtod and dtoa
diff --git a/include/ruby/util.h b/include/ruby/util.h
index 5be5f2e..a4ac1a7 100644
--- a/include/ruby/util.h
+++ b/include/ruby/util.h
@@ -85,6 +85,21 @@ void ruby_each_words(const char *, void (*)(const char*, int, void*), void *);
RUBY_SYMBOL_EXPORT_END
+#if defined(__MINGW32__) && defined(_X86_) && !defined(__SSE2_MATH__) && defined(_MCW_PC)
+/* double-precision (53-bit) rounding precision is required for strtod and dtoa. */
+static inline double
+rb_w32_ruby_strtod(const char *s00, char **se)
+{
+ double r;
+ unsigned int default_control = _controlfp(0, 0);
+ _control87(_PC_53, _MCW_PC);
+ r = ruby_strtod(s00, se);
+ _control87(default_control, _MCW_PC);
+ return r;
+}
+#define ruby_strtod rb_w32_ruby_strtod
+#endif
+
#if defined(__cplusplus)
#if 0
{ /* satisfy cc-mode */
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index ad43dfc..b4d2b6b 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -811,4 +811,36 @@ rb_w32_pow(double x, double y)
#define pow rb_w32_pow
#endif
+#if defined(__MINGW32__) && defined(_X86_) && !defined(__SSE2_MATH__) && defined(_MCW_PC)
+/* util.c */
+/* double-precision (53-bit) rounding precision is required for strtod and dtoa. */
+static inline char *
+rb_w32_ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve)
+{
+ char *r;
+ char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve);
+ unsigned int default_control = _controlfp(0, 0);
+ _control87(_PC_53, _MCW_PC);
+ r = ruby_dtoa(d_, mode, ndigits, decpt, sign, rve);
+ _control87(default_control, _MCW_PC);
+ return r;
+}
+#define ruby_dtoa rb_w32_ruby_dtoa
+
+static inline char *
+rb_w32_ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ char *r;
+ char *ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt,
+ int *sign, char **rve);
+ unsigned int default_control = _controlfp(0, 0);
+ _control87(_PC_53, _MCW_PC);
+ r = ruby_hdtoa(d, xdigs, ndigits, decpt, sign, rve);
+ _control87(default_control, _MCW_PC);
+ return r;
+}
+#define ruby_hdtoa rb_w32_ruby_hdtoa
+#endif
+
#endif /* RUBY_WIN32_H */
diff --git a/util.c b/util.c
index fb72931..828e6ab 100644
--- a/util.c
+++ b/util.c
@@ -1929,6 +1929,8 @@ hexnan(double *rvp, const char **sp)
#endif /*No_Hex_NaN*/
#endif /* INFNAN_CHECK */
+#undef ruby_strtod
+
double
ruby_strtod(const char *s00, char **se)
{
@@ -3043,6 +3045,8 @@ static const char INFSTR[] = "Infinity";
static const char NANSTR[] = "NaN";
static const char ZEROSTR[] = "0";
+#undef ruby_dtoa
+
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
*
* Inspired by "How to Print Floating-Point Numbers Accurately" by
@@ -3802,6 +3806,7 @@ ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *ar
#define dmanh_get(u) ((uint32_t)(word0(u) & Frac_mask))
#define dmanl_get(u) ((uint32_t)word1(u))
+#undef ruby_hdtoa
/*
* This procedure converts a double-precision number in IEEE format
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.