float4out(PG_FUNCTION_ARGS)
 {
        float4          num = PG_GETARG_FLOAT4(0);
-       char       *ascii;
-
-       if (isnan(num))
-               PG_RETURN_CSTRING(pstrdup("NaN"));
-
-       switch (is_infinite(num))
-       {
-               case 1:
-                       ascii = pstrdup("Infinity");
-                       break;
-               case -1:
-                       ascii = pstrdup("-Infinity");
-                       break;
-               default:
-                       {
-                               int                     ndig = FLT_DIG + extra_float_digits;
-
-                               if (ndig < 1)
-                                       ndig = 1;
-
-                               ascii = psprintf("%.*g", ndig, num);
-                       }
-       }
+       char       *ascii = (char *) palloc(32);
+       int                     ndig = FLT_DIG + extra_float_digits;
 
+       (void) pg_strfromd(ascii, 32, ndig, num);
        PG_RETURN_CSTRING(ascii);
 }
 
 char *
 float8out_internal(double num)
 {
-       char       *ascii;
-
-       if (isnan(num))
-               return pstrdup("NaN");
-
-       switch (is_infinite(num))
-       {
-               case 1:
-                       ascii = pstrdup("Infinity");
-                       break;
-               case -1:
-                       ascii = pstrdup("-Infinity");
-                       break;
-               default:
-                       {
-                               int                     ndig = DBL_DIG + extra_float_digits;
-
-                               if (ndig < 1)
-                                       ndig = 1;
-
-                               ascii = psprintf("%.*g", ndig, num);
-                       }
-       }
+       char       *ascii = (char *) palloc(32);
+       int                     ndig = DBL_DIG + extra_float_digits;
 
+       (void) pg_strfromd(ascii, 32, ndig, num);
        return ascii;
 }
 
 
 
 #include "c.h"
 
-#include <ctype.h>
-#include <limits.h>
 #include <math.h>
-#ifndef WIN32
-#include <sys/ioctl.h>
-#endif
-#include <sys/param.h>
 
 /*
  * We used to use the platform's NL_ARGMAX here, but that's a bad idea,
        int                     zeropadlen = 0; /* amount to pad with zeroes */
        int                     padlen;                 /* amount to pad with spaces */
 
-       /* Handle sign (NaNs have no sign) */
-       if (!isnan(value) && adjust_sign((value < 0), forcesign, &signvalue))
-               value = -value;
-
        /*
         * We rely on the regular C library's sprintf to do the basic conversion,
         * then handle padding considerations here.
         * bytes and limit requested precision to 350 digits; this should prevent
         * buffer overrun even with non-IEEE math.  If the original precision
         * request was more than 350, separately pad with zeroes.
+        *
+        * We handle infinities and NaNs specially to ensure platform-independent
+        * output.
         */
        if (precision < 0)                      /* cover possible overflow of "accum" */
                precision = 0;
        prec = Min(precision, 350);
 
-       if (pointflag)
+       if (isnan(value))
        {
-               zeropadlen = precision - prec;
-               fmt[0] = '%';
-               fmt[1] = '.';
-               fmt[2] = '*';
-               fmt[3] = type;
-               fmt[4] = '\0';
-               vallen = sprintf(convert, fmt, prec, value);
+               strcpy(convert, "NaN");
+               vallen = 3;
+               /* no zero padding, regardless of precision spec */
        }
        else
        {
-               fmt[0] = '%';
-               fmt[1] = type;
-               fmt[2] = '\0';
-               vallen = sprintf(convert, fmt, value);
-       }
-       if (vallen < 0)
-               goto fail;
+               /*
+                * Handle sign (NaNs have no sign, so we don't do this in the case
+                * above).  "value < 0.0" will not be true for IEEE minus zero, so we
+                * detect that by looking for the case where value equals 0.0
+                * according to == but not according to memcmp.
+                */
+               static const double dzero = 0.0;
+
+               if (adjust_sign((value < 0.0 ||
+                                                (value == 0.0 &&
+                                                 memcmp(&value, &dzero, sizeof(double)) != 0)),
+                                               forcesign, &signvalue))
+                       value = -value;
 
-       /* If it's infinity or NaN, forget about doing any zero-padding */
-       if (zeropadlen > 0 && !isdigit((unsigned char) convert[vallen - 1]))
-               zeropadlen = 0;
+               if (isinf(value))
+               {
+                       strcpy(convert, "Infinity");
+                       vallen = 8;
+                       /* no zero padding, regardless of precision spec */
+               }
+               else if (pointflag)
+               {
+                       zeropadlen = precision - prec;
+                       fmt[0] = '%';
+                       fmt[1] = '.';
+                       fmt[2] = '*';
+                       fmt[3] = type;
+                       fmt[4] = '\0';
+                       vallen = sprintf(convert, fmt, prec, value);
+               }
+               else
+               {
+                       fmt[0] = '%';
+                       fmt[1] = type;
+                       fmt[2] = '\0';
+                       vallen = sprintf(convert, fmt, value);
+               }
+               if (vallen < 0)
+                       goto fail;
+       }
 
        padlen = compute_padlen(minlen, vallen + zeropadlen, leftjust);
 
        target->failed = true;
 }
 
+/*
+ * Nonstandard entry point to print a double value efficiently.
+ *
+ * This is approximately equivalent to strfromd(), but has an API more
+ * adapted to what float8out() wants.  The behavior is like snprintf()
+ * with a format of "%.ng", where n is the specified precision.
+ * However, the target buffer must be nonempty (i.e. count > 0), and
+ * the precision is silently bounded to a sane range.
+ */
+int
+pg_strfromd(char *str, size_t count, int precision, double value)
+{
+       PrintfTarget target;
+       int                     signvalue = 0;
+       int                     vallen;
+       char            fmt[8];
+       char            convert[64];
+
+       /* Set up the target like pg_snprintf, but require nonempty buffer */
+       Assert(count > 0);
+       target.bufstart = target.bufptr = str;
+       target.bufend = str + count - 1;
+       target.stream = NULL;
+       target.nchars = 0;
+       target.failed = false;
+
+       /*
+        * We bound precision to a reasonable range; the combination of this and
+        * the knowledge that we're using "g" format without padding allows the
+        * convert[] buffer to be reasonably small.
+        */
+       if (precision < 1)
+               precision = 1;
+       else if (precision > 32)
+               precision = 32;
+
+       /*
+        * The rest is just an inlined version of the fmtfloat() logic above,
+        * simplified using the knowledge that no padding is wanted.
+        */
+       if (isnan(value))
+       {
+               strcpy(convert, "NaN");
+               vallen = 3;
+       }
+       else
+       {
+               static const double dzero = 0.0;
+
+               if (value < 0.0 ||
+                       (value == 0.0 &&
+                        memcmp(&value, &dzero, sizeof(double)) != 0))
+               {
+                       signvalue = '-';
+                       value = -value;
+               }
+
+               if (isinf(value))
+               {
+                       strcpy(convert, "Infinity");
+                       vallen = 8;
+               }
+               else
+               {
+                       fmt[0] = '%';
+                       fmt[1] = '.';
+                       fmt[2] = '*';
+                       fmt[3] = 'g';
+                       fmt[4] = '\0';
+                       vallen = sprintf(convert, fmt, precision, value);
+                       if (vallen < 0)
+                       {
+                               target.failed = true;
+                               goto fail;
+                       }
+               }
+       }
+
+       if (signvalue)
+               dopr_outch(signvalue, &target);
+
+       dostr(convert, vallen, &target);
+
+fail:
+       *(target.bufptr) = '\0';
+       return target.failed ? -1 : (target.bufptr - target.bufstart
+                                                                + target.nchars);
+}
+
+
 static void
 dostr(const char *str, int slen, PrintfTarget *target)
 {