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

Lines changed: 19 additions & 0 deletions
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

Lines changed: 13 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 12 additions & 5 deletions
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

Lines changed: 9 additions & 1 deletion
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

Lines changed: 2 additions & 5 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy