Skip to content

Commit 72880ac

Browse files
committed
Cygwin and Mingw floating-point fixes.
Deal with silent-underflow errors in float4 for cygwin and mingw by using our strtof() wrapper; deal with misrounding errors by adding them to the resultmap. Some slight reorganization of declarations was done to avoid duplicating material between cygwin.h and win32_port.h. While here, remove from the resultmap all references to float8-small-is-zero; inspection of cygwin output suggests it's no longer required there, and the freebsd/netbsd/openbsd entries should no longer be necessary (these date back to c. 2000). This commit doesn't remove the file itself nor the documentation references for it; that will happen in a subsequent commit if all goes well.
1 parent 457aef0 commit 72880ac

File tree

7 files changed

+68
-11
lines changed

7 files changed

+68
-11
lines changed

configure

+19
Original file line numberDiff line numberDiff line change
@@ -15828,6 +15828,25 @@ fi
1582815828

1582915829

1583015830

15831+
case $host_os in
15832+
# Cygwin and (apparently, based on test results) Mingw both
15833+
# have a broken strtof(), so substitute the same replacement
15834+
# code we use with VS2013. That's not a perfect fix, since
15835+
# (unlike with VS2013) it doesn't avoid double-rounding, but
15836+
# we have no better options. To get that, though, we have to
15837+
# force the file to be compiled despite HAVE_STRTOF.
15838+
mingw*|cygwin*)
15839+
case " $LIBOBJS " in
15840+
*" strtof.$ac_objext "* ) ;;
15841+
*) LIBOBJS="$LIBOBJS strtof.$ac_objext"
15842+
;;
15843+
esac
15844+
15845+
{ $as_echo "$as_me:${as_lineno-$LINENO}: On $host_os we will use our strtof wrapper." >&5
15846+
$as_echo "$as_me: On $host_os we will use our strtof wrapper." >&6;}
15847+
;;
15848+
esac
15849+
1583115850
case $host_os in
1583215851

1583315852
# Windows uses a specialised env handler

configure.in

+13
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,19 @@ AC_REPLACE_FUNCS(m4_normalize([
17151715
strtof
17161716
]))
17171717

1718+
case $host_os in
1719+
# Cygwin and (apparently, based on test results) Mingw both
1720+
# have a broken strtof(), so substitute the same replacement
1721+
# code we use with VS2013. That's not a perfect fix, since
1722+
# (unlike with VS2013) it doesn't avoid double-rounding, but
1723+
# we have no better options. To get that, though, we have to
1724+
# force the file to be compiled despite HAVE_STRTOF.
1725+
mingw*|cygwin*)
1726+
AC_LIBOBJ([strtof])
1727+
AC_MSG_NOTICE([On $host_os we will use our strtof wrapper.])
1728+
;;
1729+
esac
1730+
17181731
case $host_os in
17191732

17201733
# Windows uses a specialised env handler

src/include/port.h

+5
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,11 @@ extern int isinf(double x);
385385
extern float strtof(const char *nptr, char **endptr);
386386
#endif
387387

388+
#ifdef HAVE_BUGGY_STRTOF
389+
extern float pg_strtof(const char *nptr, char **endptr);
390+
#define strtof(a,b) (pg_strtof((a),(b)))
391+
#endif
392+
388393
#ifndef HAVE_MKDTEMP
389394
extern char *mkdtemp(char *path);
390395
#endif

src/include/port/cygwin.h

+8
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@
1616
#endif
1717

1818
#define PGDLLEXPORT
19+
20+
/*
21+
* Cygwin has a strtof() which is literally just (float)strtod(), which means
22+
* we get misrounding _and_ silent over/underflow. Using our wrapper doesn't
23+
* fix the misrounding but does fix the error checks, which cuts down on the
24+
* number of test variant files needed.
25+
*/
26+
#define HAVE_BUGGY_STRTOF 1

src/include/port/win32_port.h

+12-5
Original file line numberDiff line numberDiff line change
@@ -510,16 +510,23 @@ typedef unsigned short mode_t;
510510
#define isnan(x) _isnan(x)
511511
#endif
512512

513-
#if defined(_MSC_VER) && (_MSC_VER < 1900)
513+
#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || \
514+
defined(__MINGW32__) || defined(__MINGW64__)
514515
/*
515516
* VS2013 has a strtof() that seems to give correct answers for valid input,
516517
* even on the rounding edge cases, but which doesn't handle out-of-range
517518
* input correctly. Work around that.
519+
*
520+
* Mingw claims to have a strtof, and my reading of its source code suggests
521+
* that it ought to work (and not need this hack), but the regression test
522+
* results disagree with me; whether this is a version issue or not is not
523+
* clear. However, using our wrapper (and the misrounded-input variant file,
524+
* already required for supporting ancient systems) can't make things any
525+
* worse, except for a tiny performance loss when reading zeros.
526+
*
527+
* See also cygwin.h for another instance of this.
518528
*/
519-
#define HAVE_BUGGY_WINDOWS_STRTOF 1
520-
extern float pg_strtof(const char *nptr, char **endptr);
521-
#define strtof(a,b) (pg_strtof((a),(b)))
522-
529+
#define HAVE_BUGGY_STRTOF 1
523530
#endif
524531

525532
/* Pulled from Makefile.port in MinGW */

src/port/strtof.c

+9-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ strtof(const char *nptr, char **endptr)
5252
return fresult;
5353
}
5454

55-
#elif HAVE_BUGGY_WINDOWS_STRTOF
55+
#elif HAVE_BUGGY_STRTOF
5656
/*
5757
* On Windows, there's a slightly different problem: VS2013 has a strtof()
5858
* that returns the correct results for valid input, but may fail to report an
@@ -62,6 +62,14 @@ strtof(const char *nptr, char **endptr)
6262
* well, so prefer to round the strtod() result in such cases. (Normally we'd
6363
* just say "too bad" if strtof() doesn't support subnormals, but since we're
6464
* already in here fixing stuff, we might as well do the best fix we can.)
65+
*
66+
* Cygwin has a strtof() which is literally just (float)strtod(), which means
67+
* we can't avoid the double-rounding problem; but using this wrapper does get
68+
* us proper over/underflow checks. (Also, if they fix their strtof(), the
69+
* wrapper doesn't break anything.)
70+
*
71+
* Test results on Mingw suggest that it has the same problem, though looking
72+
* at the code I can't figure out why.
6573
*/
6674
float
6775
pg_strtof(const char *nptr, char **endptr)

src/test/regress/resultmap

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
float8:out:i.86-.*-freebsd=float8-small-is-zero.out
2-
float8:out:i.86-.*-openbsd=float8-small-is-zero.out
3-
float8:out:i.86-.*-netbsd=float8-small-is-zero.out
4-
float8:out:m68k-.*-netbsd=float8-small-is-zero.out
5-
float8:out:i.86-pc-cygwin=float8-small-is-zero.out
1+
float4:out:.*-.*-cygwin.*=float4-misrounded-input.out
2+
float4:out:.*-.*-mingw.*=float4-misrounded-input.out
63
float4:out:hppa.*-hp-hpux10.*=float4-misrounded-input.out

0 commit comments

Comments
 (0)