Created
May 17, 2013 04:33
-
-
Save shirosaki/5596940 to your computer and use it in GitHub Desktop.
Fix numeric precision for strtod and dtoa
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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