diff --git a/configure b/configure
index ddb3c8b1ba..378860e9ce 100755
--- a/configure
+++ b/configure
@@ -15812,6 +15812,19 @@ esac
 
 fi
 
+ac_fn_c_check_func "$LINENO" "strtof" "ac_cv_func_strtof"
+if test "x$ac_cv_func_strtof" = xyes; then :
+  $as_echo "#define HAVE_STRTOF 1" >>confdefs.h
+
+else
+  case " $LIBOBJS " in
+  *" strtof.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strtof.$ac_objext"
+ ;;
+esac
+
+fi
+
 
 
 case $host_os in
diff --git a/configure.in b/configure.in
index 3d8888805c..08fc8fd1bf 100644
--- a/configure.in
+++ b/configure.in
@@ -1705,6 +1705,7 @@ AC_REPLACE_FUNCS(m4_normalize([
 	strlcat
 	strlcpy
 	strnlen
+	strtof
 ]))
 
 case $host_os in
diff --git a/contrib/btree_gist/expected/float4.out b/contrib/btree_gist/expected/float4.out
index abbd9eef4e..dfe732049e 100644
--- a/contrib/btree_gist/expected/float4.out
+++ b/contrib/btree_gist/expected/float4.out
@@ -33,11 +33,11 @@ SELECT count(*) FROM float4tmp WHERE a >  -179.0;
 (1 row)
 
 SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
-    a     | ?column? 
-----------+----------
-     -179 |        0
- -189.024 |  10.0239
- -158.177 |  20.8226
+     a      | ?column?  
+------------+-----------
+       -179 |         0
+ -189.02386 | 10.023865
+ -158.17741 | 20.822586
 (3 rows)
 
 CREATE INDEX float4idx ON float4tmp USING gist ( a );
@@ -82,10 +82,10 @@ SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
 (3 rows)
 
 SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
-    a     | ?column? 
-----------+----------
-     -179 |        0
- -189.024 |  10.0239
- -158.177 |  20.8226
+     a      | ?column?  
+------------+-----------
+       -179 |         0
+ -189.02386 | 10.023865
+ -158.17741 | 20.822586
 (3 rows)
 
diff --git a/contrib/btree_gist/expected/float8.out b/contrib/btree_gist/expected/float8.out
index 5111dbdfae..ebd0ef3d68 100644
--- a/contrib/btree_gist/expected/float8.out
+++ b/contrib/btree_gist/expected/float8.out
@@ -33,11 +33,11 @@ SELECT count(*) FROM float8tmp WHERE a >  -1890.0;
 (1 row)
 
 SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
-      a       |  ?column?  
---------------+------------
-        -1890 |          0
- -2003.634512 | 113.634512
-  -1769.73634 |  120.26366
+      a       |      ?column?      
+--------------+--------------------
+        -1890 |                  0
+ -2003.634512 | 113.63451200000009
+  -1769.73634 | 120.26366000000007
 (3 rows)
 
 CREATE INDEX float8idx ON float8tmp USING gist ( a );
@@ -82,10 +82,10 @@ SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
 (3 rows)
 
 SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
-      a       |  ?column?  
---------------+------------
-        -1890 |          0
- -2003.634512 | 113.634512
-  -1769.73634 |  120.26366
+      a       |      ?column?      
+--------------+--------------------
+        -1890 |                  0
+ -2003.634512 | 113.63451200000009
+  -1769.73634 | 120.26366000000007
 (3 rows)
 
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 1a65e6944a..5b89cb1a26 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -81,21 +81,21 @@ SELECT 'NaN'::cube AS cube;
 (1 row)
 
 SELECT '.1234567890123456'::cube AS cube;
-        cube         
----------------------
- (0.123456789012346)
+         cube         
+----------------------
+ (0.1234567890123456)
 (1 row)
 
 SELECT '+.1234567890123456'::cube AS cube;
-        cube         
----------------------
- (0.123456789012346)
+         cube         
+----------------------
+ (0.1234567890123456)
 (1 row)
 
 SELECT '-.1234567890123456'::cube AS cube;
-         cube         
-----------------------
- (-0.123456789012346)
+         cube          
+-----------------------
+ (-0.1234567890123456)
 (1 row)
 
 -- simple lists (points)
@@ -943,9 +943,9 @@ SELECT cube_distance('(42,42,42,42)'::cube,'(137,137,137,137)'::cube);
 (1 row)
 
 SELECT cube_distance('(42,42,42)'::cube,'(137,137)'::cube);
-  cube_distance   
-------------------
- 140.762210837994
+   cube_distance    
+--------------------
+ 140.76221083799445
 (1 row)
 
 -- Test of cube function (text to cube)
@@ -1356,8 +1356,9 @@ SELECT cube_size('(42,137)'::cube);
          0
 (1 row)
 
--- Test of distances
+-- Test of distances (euclidean distance may not be bit-exact)
 --
+SET extra_float_digits = 0;
 SELECT cube_distance('(1,1)'::cube, '(4,5)'::cube);
  cube_distance 
 ---------------
@@ -1370,6 +1371,7 @@ SELECT '(1,1)'::cube <-> '(4,5)'::cube as d_e;
    5
 (1 row)
 
+RESET extra_float_digits;
 SELECT distance_chebyshev('(1,1)'::cube, '(4,5)'::cube);
  distance_chebyshev 
 --------------------
@@ -1557,6 +1559,7 @@ RESET enable_bitmapscan;
 INSERT INTO test_cube VALUES ('(1,1)'), ('(100000)'), ('(0, 100000)'); -- Some corner cases
 SET enable_seqscan = false;
 -- Test different metrics
+SET extra_float_digits = 0;
 SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
             c            |       dist       
 -------------------------+------------------
@@ -1567,6 +1570,7 @@ SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c
  (1444, 403),(1346, 344) |              846
 (5 rows)
 
+RESET extra_float_digits;
 SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
             c            | dist 
 -------------------------+------
@@ -1751,6 +1755,7 @@ SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upp
 -- Same queries with sequential scan (should give the same results as above)
 RESET enable_seqscan;
 SET enable_indexscan = OFF;
+SET extra_float_digits = 0;
 SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
             c            |       dist       
 -------------------------+------------------
@@ -1761,6 +1766,7 @@ SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c
  (1444, 403),(1346, 344) |              846
 (5 rows)
 
+RESET extra_float_digits;
 SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
             c            | dist 
 -------------------------+------
diff --git a/contrib/cube/expected/cube_sci.out b/contrib/cube/expected/cube_sci.out
index 1e8269cdf0..488499ac8e 100644
--- a/contrib/cube/expected/cube_sci.out
+++ b/contrib/cube/expected/cube_sci.out
@@ -87,20 +87,20 @@ SELECT '-1e-300'::cube AS cube;
 (1 row)
 
 SELECT '1234567890123456'::cube AS cube;
-          cube          
-------------------------
- (1.23456789012346e+15)
+          cube           
+-------------------------
+ (1.234567890123456e+15)
 (1 row)
 
 SELECT '+1234567890123456'::cube AS cube;
-          cube          
-------------------------
- (1.23456789012346e+15)
+          cube           
+-------------------------
+ (1.234567890123456e+15)
 (1 row)
 
 SELECT '-1234567890123456'::cube AS cube;
-          cube           
--------------------------
- (-1.23456789012346e+15)
+           cube           
+--------------------------
+ (-1.234567890123456e+15)
 (1 row)
 
diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql
index 59e7e4159d..7f8b2e3979 100644
--- a/contrib/cube/sql/cube.sql
+++ b/contrib/cube/sql/cube.sql
@@ -336,10 +336,12 @@ SELECT cube_inter('(1,2,3)'::cube, '(5,6,3)'::cube); -- point args
 SELECT cube_size('(4,8),(15,16)'::cube);
 SELECT cube_size('(42,137)'::cube);
 
--- Test of distances
+-- Test of distances (euclidean distance may not be bit-exact)
 --
+SET extra_float_digits = 0;
 SELECT cube_distance('(1,1)'::cube, '(4,5)'::cube);
 SELECT '(1,1)'::cube <-> '(4,5)'::cube as d_e;
+RESET extra_float_digits;
 SELECT distance_chebyshev('(1,1)'::cube, '(4,5)'::cube);
 SELECT '(1,1)'::cube <=> '(4,5)'::cube as d_c;
 SELECT distance_taxicab('(1,1)'::cube, '(4,5)'::cube);
@@ -395,7 +397,9 @@ INSERT INTO test_cube VALUES ('(1,1)'), ('(100000)'), ('(0, 100000)'); -- Some c
 SET enable_seqscan = false;
 
 -- Test different metrics
+SET extra_float_digits = 0;
 SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
+RESET extra_float_digits;
 SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
 SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
 
@@ -412,7 +416,9 @@ SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upp
 -- Same queries with sequential scan (should give the same results as above)
 RESET enable_seqscan;
 SET enable_indexscan = OFF;
+SET extra_float_digits = 0;
 SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
+RESET extra_float_digits;
 SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
 SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
 SELECT c~>1, c FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by left bound
diff --git a/contrib/pg_trgm/expected/pg_strict_word_trgm.out b/contrib/pg_trgm/expected/pg_strict_word_trgm.out
index 43898a3b98..1e1ee16ce9 100644
--- a/contrib/pg_trgm/expected/pg_strict_word_trgm.out
+++ b/contrib/pg_trgm/expected/pg_strict_word_trgm.out
@@ -1,6 +1,8 @@
 DROP INDEX trgm_idx2;
 \copy test_trgm3 from 'data/trgm2.data'
 ERROR:  relation "test_trgm3" does not exist
+-- reduce noise
+set extra_float_digits = 0;
 select t,strict_word_similarity('Baykal',t) as sml from test_trgm2 where 'Baykal' <<% t order by sml desc, t;
                   t                  |   sml    
 -------------------------------------+----------
diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expected/pg_trgm.out
index 6efc54356a..b3e709f496 100644
--- a/contrib/pg_trgm/expected/pg_trgm.out
+++ b/contrib/pg_trgm/expected/pg_trgm.out
@@ -10,6 +10,8 @@ WHERE opc.oid >= 16384 AND NOT amvalidate(opc.oid);
 --backslash is used in tests below, installcheck will fail if
 --standard_conforming_string is off
 set standard_conforming_strings=on;
+-- reduce noise
+set extra_float_digits = 0;
 select show_trgm('');
  show_trgm 
 -----------
diff --git a/contrib/pg_trgm/expected/pg_word_trgm.out b/contrib/pg_trgm/expected/pg_word_trgm.out
index bed61c4922..936d489390 100644
--- a/contrib/pg_trgm/expected/pg_word_trgm.out
+++ b/contrib/pg_trgm/expected/pg_word_trgm.out
@@ -1,5 +1,7 @@
 CREATE TABLE test_trgm2(t text COLLATE "C");
 \copy test_trgm2 from 'data/trgm2.data'
+-- reduce noise
+set extra_float_digits = 0;
 select t,word_similarity('Baykal',t) as sml from test_trgm2 where 'Baykal' <% t order by sml desc, t;
                   t                  |   sml    
 -------------------------------------+----------
diff --git a/contrib/pg_trgm/sql/pg_strict_word_trgm.sql b/contrib/pg_trgm/sql/pg_strict_word_trgm.sql
index 98e0d379f8..ce0791f29b 100644
--- a/contrib/pg_trgm/sql/pg_strict_word_trgm.sql
+++ b/contrib/pg_trgm/sql/pg_strict_word_trgm.sql
@@ -2,6 +2,9 @@ DROP INDEX trgm_idx2;
 
 \copy test_trgm3 from 'data/trgm2.data'
 
+-- reduce noise
+set extra_float_digits = 0;
+
 select t,strict_word_similarity('Baykal',t) as sml from test_trgm2 where 'Baykal' <<% t order by sml desc, t;
 select t,strict_word_similarity('Kabankala',t) as sml from test_trgm2 where 'Kabankala' <<% t order by sml desc, t;
 select t,strict_word_similarity('Baykal',t) as sml from test_trgm2 where t %>> 'Baykal' order by sml desc, t;
diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm.sql
index 96ae542320..08459e64c3 100644
--- a/contrib/pg_trgm/sql/pg_trgm.sql
+++ b/contrib/pg_trgm/sql/pg_trgm.sql
@@ -9,6 +9,9 @@ WHERE opc.oid >= 16384 AND NOT amvalidate(opc.oid);
 --standard_conforming_string is off
 set standard_conforming_strings=on;
 
+-- reduce noise
+set extra_float_digits = 0;
+
 select show_trgm('');
 select show_trgm('(*&^$@%@');
 select show_trgm('a b c');
diff --git a/contrib/pg_trgm/sql/pg_word_trgm.sql b/contrib/pg_trgm/sql/pg_word_trgm.sql
index 4b1db9706a..d9fa1c55e5 100644
--- a/contrib/pg_trgm/sql/pg_word_trgm.sql
+++ b/contrib/pg_trgm/sql/pg_word_trgm.sql
@@ -2,6 +2,9 @@ CREATE TABLE test_trgm2(t text COLLATE "C");
 
 \copy test_trgm2 from 'data/trgm2.data'
 
+-- reduce noise
+set extra_float_digits = 0;
+
 select t,word_similarity('Baykal',t) as sml from test_trgm2 where 'Baykal' <% t order by sml desc, t;
 select t,word_similarity('Kabankala',t) as sml from test_trgm2 where 'Kabankala' <% t order by sml desc, t;
 select t,word_similarity('Baykal',t) as sml from test_trgm2 where t %> 'Baykal' order by sml desc, t;
diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out
index a289dbe5f9..80b0bca156 100644
--- a/contrib/seg/expected/seg.out
+++ b/contrib/seg/expected/seg.out
@@ -1127,7 +1127,7 @@ FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
        2.1 |       6.95 |      11.8
        2.3 |   Infinity |  Infinity
        2.3 |   Infinity |  Infinity
-       2.4 |       6.85 |      11.3
+       2.4 |  6.8500004 |      11.3
        2.5 |          7 |      11.5
        2.5 |       7.15 |      11.8
        2.6 |   Infinity |  Infinity
@@ -1155,7 +1155,7 @@ FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
        4.5 |      59.75 |       115
        4.7 |       8.25 |      11.8
        4.8 |       8.15 |      11.5
-       4.8 |        8.2 |      11.6
+       4.8 |   8.200001 |      11.6
        4.8 |       8.65 |      12.5
        4.8 |   Infinity |  Infinity
        4.9 |       8.45 |        12
@@ -1244,7 +1244,7 @@ FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
          9 |       10.5 |        12
          9 |   Infinity |  Infinity
        9.2 |       10.6 |        12
-       9.4 |       10.8 |      12.2
+       9.4 |  10.799999 |      12.2
        9.5 |      10.75 |        12
        9.5 |      10.85 |      12.2
        9.5 |   Infinity |  Infinity
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index b6f5822b84..340b5ad478 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -7833,16 +7833,37 @@ SET XML OPTION { DOCUMENT | CONTENT };
       </term>
       <listitem>
        <para>
-        This parameter adjusts the number of digits displayed for
+        This parameter adjusts the number of digits used for textual output of
         floating-point values, including <type>float4</type>, <type>float8</type>,
-        and geometric data types.  The parameter value is added to the
-        standard number of digits (<literal>FLT_DIG</literal> or <literal>DBL_DIG</literal>
-        as appropriate).  The value can be set as high as 3, to include
-        partially-significant digits; this is especially useful for dumping
-        float data that needs to be restored exactly.  Or it can be set
-        negative to suppress unwanted digits.
-        See also <xref linkend="datatype-float"/>.
+        and geometric data types.
        </para>
+       <para>
+        If the value is 1 (the default) or above, float values are output in
+        shortest-precise format; see <xref linkend="datatype-float"/>. The
+        actual number of digits generated depends only on the value being
+        output, not on the value of this parameter. At most 17 digits are
+        required for <type>float8</type> values, and 9 for <type>float4</type>
+        values. This format is both fast and precise, preserving the original
+        binary float value exactly when correctly read. For historical
+        compatibility, values up to 3 are permitted.
+       </para>
+       <para>
+        If the value is zero or negative, then the output is rounded to a
+        given decimal precision. The precision used is the standard number of
+        digits for the type (<literal>FLT_DIG</literal>
+        or <literal>DBL_DIG</literal> as appropriate) reduced according to the
+        value of this parameter. (For example, specifying -1 will cause float4
+        values to be output rounded to 5 significant digits, and float8 values
+        rounded to 14 digits.) This format is slower and does not preserve all
+        the bits of the binary float value, but may be more human-readable.
+       </para>
+       <note>
+        <para>
+         The meaning of this parameter, and its default value, changed
+         in <productname>PostgreSQL</productname> 12;
+         see <xref linkend="datatype-float"/> for further discussion.
+        </para>
+       </note>
       </listitem>
      </varlistentry>
 
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index ed0ee584c9..da0d887623 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -671,13 +671,12 @@ FROM generate_series(-3.5, 3.5, 1) as x;
     </indexterm>
 
     <para>
-     The data types <type>real</type> and <type>double
-     precision</type> are inexact, variable-precision numeric types.
-     In practice, these types are usually implementations of
-     <acronym>IEEE</acronym> Standard 754 for Binary Floating-Point
-     Arithmetic (single and double precision, respectively), to the
-     extent that the underlying processor, operating system, and
-     compiler support it.
+     The data types <type>real</type> and <type>double precision</type> are
+     inexact, variable-precision numeric types. On all currently supported
+     platforms, these types are implementations of <acronym>IEEE</acronym>
+     Standard 754 for Binary Floating-Point Arithmetic (single and double
+     precision, respectively), to the extent that the underlying processor,
+     operating system, and compiler support it.
     </para>
 
     <para>
@@ -715,24 +714,57 @@ FROM generate_series(-3.5, 3.5, 1) as x;
     </para>
 
     <para>
-     On most platforms, the <type>real</type> type has a range of at least
-     1E-37 to 1E+37 with a precision of at least 6 decimal digits.  The
-     <type>double precision</type> type typically has a range of around
-     1E-307 to 1E+308 with a precision of at least 15 digits.  Values that
-     are too large or too small will cause an error.  Rounding might
-     take place if the precision of an input number is too high.
-     Numbers too close to zero that are not representable as distinct
-     from zero will cause an underflow error.
+     On all currently supported platforms, the <type>real</type> type has a
+     range of around 1E-37 to 1E+37 with a precision of at least 6 decimal
+     digits. The <type>double precision</type> type has a range of around
+     1E-307 to 1E+308 with a precision of at least 15 digits. Values that are
+     too large or too small will cause an error. Rounding might take place if
+     the precision of an input number is too high. Numbers too close to zero
+     that are not representable as distinct from zero will cause an underflow
+     error.
+    </para>
+
+    <para>
+     By default, floating point values are output in text form in their
+     shortest precise decimal representation; the decimal value produced is
+     closer to the true stored binary value than to any other value
+     representable in the same binary precision. (However, the output value is
+     currently never <emphasis>exactly</emphasis> midway between two
+     representable values, in order to avoid a widespread bug where input
+     routines do not properly respect the round-to-even rule.) This value will
+     use at most 17 significant decimal digits for <type>float8</type>
+     values, and at most 9 digits for <type>float4</type> values.
     </para>
 
     <note>
      <para>
-      The <xref linkend="guc-extra-float-digits"/> setting controls the
-      number of extra significant digits included when a floating point
-      value is converted to text for output.  With the default value of
-      <literal>0</literal>, the output is the same on every platform
-      supported by PostgreSQL.  Increasing it will produce output that
-      more accurately represents the stored value, but may be unportable.
+      This shortest-precise output format is much faster to generate than the
+      historical rounded format.
+     </para>
+    </note>
+
+    <para>
+     For compatibility with output generated by older versions
+     of <productname>PostgreSQL</productname>, and to allow the output
+     precision to be reduced, the <xref linkend="guc-extra-float-digits"/>
+     parameter can be used to select rounded decimal output instead. Setting a
+     value of 0 restores the previous default of rounding the value to 6
+     (for <type>float4</type>) or 15 (for <type>float8</type>)
+     significant decimal digits. Setting a negative value reduces the number
+     of digits further; for example -2 would round output to 4 or 13 digits
+     respectively.
+    </para>
+
+    <para>
+     Any value of <xref linkend="guc-extra-float-digits"/> greater than 0
+     selects the shortest-precise format.
+    </para>
+
+    <note>
+     <para>
+      Applications that wanted precise values have historically had to set
+      <xref linkend="guc-extra-float-digits"/> to 3 obtain them. For maximum
+      compatibility between versions, they should continue to do so.
      </para>
     </note>
 
@@ -751,9 +783,7 @@ FROM generate_series(-3.5, 3.5, 1) as x;
 </literallayout>
      These represent the IEEE 754 special values
      <quote>infinity</quote>, <quote>negative infinity</quote>, and
-     <quote>not-a-number</quote>, respectively.  (On a machine whose
-     floating-point arithmetic does not follow IEEE 754, these values
-     will probably not work as expected.)  When writing these values
+     <quote>not-a-number</quote>, respectively. When writing these values
      as constants in an SQL command, you must put quotes around them,
      for example <literal>UPDATE table SET x = '-Infinity'</literal>.  On input,
      these strings are recognized in a case-insensitive manner.
@@ -786,17 +816,6 @@ FROM generate_series(-3.5, 3.5, 1) as x;
      <type>double precision</type>.
     </para>
 
-    <note>
-     <para>
-      The assumption that <type>real</type> and
-      <type>double precision</type> have exactly 24 and 53 bits in the
-      mantissa respectively is correct for IEEE-standard floating point
-      implementations.  On non-IEEE platforms it might be off a little, but
-      for simplicity the same ranges of <replaceable>p</replaceable> are used
-      on all platforms.
-     </para>
-    </note>
-
    </sect2>
 
    <sect2 id="datatype-serial">
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 117ded8d1d..37c202d21c 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -21,6 +21,7 @@
 
 #include "catalog/pg_type.h"
 #include "common/int.h"
+#include "common/shortest_dec.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "utils/array.h"
@@ -30,8 +31,15 @@
 #include "utils/timestamp.h"
 
 
-/* Configurable GUC parameter */
-int			extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */
+/*
+ * Configurable GUC parameter
+ *
+ * If >0, use shortest-decimal format for output; this is both the default and
+ * allows for compatibility with clients that explicitly set a value here to
+ * get round-trip-accurate results. If 0 or less, then use the old, slow,
+ * decimal rounding method.
+ */
+int			extra_float_digits = 1;
 
 /* Cached constants for degree-based trig functions */
 static bool degree_consts_set = false;
@@ -104,13 +112,39 @@ is_infinite(double val)
 
 /*
  *		float4in		- converts "num" to float4
+ *
+ * Note that this code now uses strtof(), where it used to use strtod().
+ *
+ * The motivation for using strtof() is to avoid a double-rounding problem:
+ * for certain decimal inputs, if you round the input correctly to a double,
+ * and then round the double to a float, the result is incorrect in that it
+ * does not match the result of rounding the decimal value to float directly.
+ *
+ * One of the best examples is 7.038531e-26:
+ *
+ * 0xAE43FDp-107 = 7.03853069185120912085...e-26
+ *      midpoint   7.03853100000000022281...e-26
+ * 0xAE43FEp-107 = 7.03853130814879132477...e-26
+ *
+ * making 0xAE43FDp-107 the correct float result, but if you do the conversion
+ * via a double, you get
+ *
+ * 0xAE43FD.7FFFFFF8p-107 = 7.03853099999999907487...e-26
+ *               midpoint   7.03853099999999964884...e-26
+ * 0xAE43FD.80000000p-107 = 7.03853100000000022281...e-26
+ * 0xAE43FD.80000008p-107 = 7.03853100000000137076...e-26
+ *
+ * so the value rounds to the double exactly on the midpoint between the two
+ * nearest floats, and then rounding again to a float gives the incorrect
+ * result of 0xAE43FEp-107.
+ *
  */
 Datum
 float4in(PG_FUNCTION_ARGS)
 {
 	char	   *num = PG_GETARG_CSTRING(0);
 	char	   *orig_num;
-	double		val;
+	float		val;
 	char	   *endptr;
 
 	/*
@@ -135,7 +169,7 @@ float4in(PG_FUNCTION_ARGS)
 						"real", orig_num)));
 
 	errno = 0;
-	val = strtod(num, &endptr);
+	val = strtof(num, &endptr);
 
 	/* did we not see anything that looks like a double? */
 	if (endptr == num || errno != 0)
@@ -143,14 +177,14 @@ float4in(PG_FUNCTION_ARGS)
 		int			save_errno = errno;
 
 		/*
-		 * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
+		 * C99 requires that strtof() accept NaN, [+-]Infinity, and [+-]Inf,
 		 * but not all platforms support all of these (and some accept them
 		 * but set ERANGE anyway...)  Therefore, we check for these inputs
-		 * ourselves if strtod() fails.
+		 * ourselves if strtof() fails.
 		 *
 		 * Note: C99 also requires hexadecimal input as well as some extended
 		 * forms of NaN, but we consider these forms unportable and don't try
-		 * to support them.  You can use 'em if your strtod() takes 'em.
+		 * to support them.  You can use 'em if your strtof() takes 'em.
 		 */
 		if (pg_strncasecmp(num, "NaN", 3) == 0)
 		{
@@ -195,8 +229,18 @@ float4in(PG_FUNCTION_ARGS)
 			 * precision).  We'd prefer not to throw error for that, so try to
 			 * detect whether it's a "real" out-of-range condition by checking
 			 * to see if the result is zero or huge.
+			 *
+			 * Use isinf() rather than HUGE_VALF on VS2013 because it generates
+			 * a spurious overflow warning for -HUGE_VALF. Also use isinf() if
+			 * HUGE_VALF is missing.
 			 */
-			if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
+			if (val == 0.0 ||
+#if !defined(HUGE_VALF) || (defined(_MSC_VER) && (_MSC_VER < 1900))
+				isinf(val)
+#else
+				(val >= HUGE_VALF || val <= -HUGE_VALF)
+#endif
+				)
 				ereport(ERROR,
 						(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 						 errmsg("\"%s\" is out of range for type real",
@@ -232,13 +276,7 @@ float4in(PG_FUNCTION_ARGS)
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"real", orig_num)));
 
-	/*
-	 * if we get here, we have a legal double, still need to check to see if
-	 * it's a legal float4
-	 */
-	check_float4_val((float4) val, isinf(val), val == 0);
-
-	PG_RETURN_FLOAT4((float4) val);
+	PG_RETURN_FLOAT4(val);
 }
 
 /*
@@ -252,6 +290,12 @@ float4out(PG_FUNCTION_ARGS)
 	char	   *ascii = (char *) palloc(32);
 	int			ndig = FLT_DIG + extra_float_digits;
 
+	if (extra_float_digits > 0)
+	{
+		float_to_shortest_decimal_buf(num, ascii);
+		PG_RETURN_CSTRING(ascii);
+	}
+
 	(void) pg_strfromd(ascii, 32, ndig, num);
 	PG_RETURN_CSTRING(ascii);
 }
@@ -468,6 +512,12 @@ float8out_internal(double num)
 	char	   *ascii = (char *) palloc(32);
 	int			ndig = DBL_DIG + extra_float_digits;
 
+	if (extra_float_digits > 0)
+	{
+		double_to_shortest_decimal_buf(num, ascii);
+		return ascii;
+	}
+
 	(void) pg_strfromd(ascii, 32, ndig, num);
 	return ascii;
 }
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 98d75be292..56e7ceff46 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2654,11 +2654,12 @@ static struct config_int ConfigureNamesInt[] =
 		{"extra_float_digits", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the number of digits displayed for floating-point values."),
 			gettext_noop("This affects real, double precision, and geometric data types. "
-						 "The parameter value is added to the standard number of digits "
-						 "(FLT_DIG or DBL_DIG as appropriate).")
+						 "A zero or negative parameter value is added to the standard "
+						 "number of digits (FLT_DIG or DBL_DIG as appropriate). "
+						 "Any value greater than zero selects precise output mode.")
 		},
 		&extra_float_digits,
-		0, -15, 3,
+		1, -15, 3,
 		NULL, NULL, NULL
 	},
 
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index a21865a77f..13d7436b42 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -649,7 +649,8 @@
 					#   India
 					# You can create your own file in
 					# share/timezonesets/.
-#extra_float_digits = 0			# min -15, max 3
+#extra_float_digits = 1			# min -15, max 3; any value >0 actually
+					# selects precise output mode
 #client_encoding = sql_ascii		# actually, defaults to database
 					# encoding
 
diff --git a/src/common/Makefile b/src/common/Makefile
index d0c2b970eb..bd3a506f9e 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -44,9 +44,11 @@ override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\""
 override CPPFLAGS := -DFRONTEND -I. -I$(top_srcdir)/src/common $(CPPFLAGS)
 LIBS += $(PTHREAD_LIBS)
 
-OBJS_COMMON = base64.o config_info.o controldata_utils.o exec.o file_perm.o \
-	ip.o keywords.o kwlookup.o link-canary.o md5.o pg_lzcompress.o \
-	pgfnames.o psprintf.o relpath.o \
+# If you add objects here, see also src/tools/msvc/Mkvcbuild.pm
+
+OBJS_COMMON = base64.o config_info.o controldata_utils.o d2s.o exec.o f2s.o \
+	file_perm.o ip.o keywords.o kwlookup.o link-canary.o md5.o \
+	pg_lzcompress.o pgfnames.o psprintf.o relpath.o \
 	rmtree.o saslprep.o scram-common.o string.o unicode_norm.o \
 	username.o wait_error.o
 
@@ -130,6 +132,13 @@ kwlist_d.h: $(top_srcdir)/src/include/parser/kwlist.h $(GEN_KEYWORDLIST_DEPS)
 # that you don't get broken parsing code, even in a non-enable-depend build.
 keywords.o keywords_shlib.o keywords_srv.o: kwlist_d.h
 
+# The code imported from Ryu gets a pass on declaration-after-statement,
+# in order to keep it more closely aligned with its upstream.
+RYU_FILES = d2s.o f2s.o
+RYU_OBJS = $(RYU_FILES) $(RYU_FILES:%.o=%_shlib.o) $(RYU_FILES:%.o=%_srv.o)
+
+$(RYU_OBJS): override CFLAGS := $(filter-out -Wdeclaration-after-statement,$(CFLAGS))
+
 # kwlist_d.h is in the distribution tarball, so it is not cleaned here.
 clean distclean:
 	rm -f libpgcommon.a libpgcommon_shlib.a libpgcommon_srv.a
diff --git a/src/common/d2s.c b/src/common/d2s.c
new file mode 100644
index 0000000000..58f91523e7
--- /dev/null
+++ b/src/common/d2s.c
@@ -0,0 +1,1041 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for double precision.
+ *
+ * Portions Copyright (c) 2018-2019, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/common/d2s.c
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ *     (See accompanying file LICENSE-Apache or copy at
+ *      http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ *     (See accompanying file LICENSE-Boost or copy at
+ *      https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*
+ *  Runtime compiler options:
+ *
+ *  -DRYU_ONLY_64_BIT_OPS Avoid using uint128 or 64-bit intrinsics. Slower,
+ *      depending on your compiler.
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/shortest_dec.h"
+
+/*
+ * For consistency, we use 128-bit types if and only if the rest of PG also
+ * does, even though we could use them here without worrying about the
+ * alignment concerns that apply elsewhere.
+ */
+#if !defined(HAVE_INT128) && defined(_MSC_VER) \
+	&& !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
+#define HAS_64_BIT_INTRINSICS
+#endif
+
+#include "ryu_common.h"
+#include "digit_table.h"
+#include "d2s_full_table.h"
+#include "d2s_intrinsics.h"
+
+#define DOUBLE_MANTISSA_BITS 52
+#define DOUBLE_EXPONENT_BITS 11
+#define DOUBLE_BIAS 1023
+
+#define DOUBLE_POW5_INV_BITCOUNT 122
+#define DOUBLE_POW5_BITCOUNT 121
+
+
+static inline uint32
+pow5Factor(uint64 value)
+{
+	uint32		count = 0;
+
+	for (;;)
+	{
+		Assert(value != 0);
+		const uint64 q = div5(value);
+		const uint32 r = (uint32) (value - 5 * q);
+
+		if (r != 0)
+			break;
+
+		value = q;
+		++count;
+	}
+	return count;
+}
+
+/*  Returns true if value is divisible by 5^p. */
+static inline bool
+multipleOfPowerOf5(const uint64 value, const uint32 p)
+{
+	/*
+	 * I tried a case distinction on p, but there was no performance
+	 * difference.
+	 */
+	return pow5Factor(value) >= p;
+}
+
+/*  Returns true if value is divisible by 2^p. */
+static inline bool
+multipleOfPowerOf2(const uint64 value, const uint32 p)
+{
+	/* return __builtin_ctzll(value) >= p; */
+	return (value & ((UINT64CONST(1) << p) - 1)) == 0;
+}
+
+/*
+ * We need a 64x128-bit multiplication and a subsequent 128-bit shift.
+ *
+ * Multiplication:
+ *
+ *    The 64-bit factor is variable and passed in, the 128-bit factor comes
+ *    from a lookup table. We know that the 64-bit factor only has 55
+ *    significant bits (i.e., the 9 topmost bits are zeros). The 128-bit
+ *    factor only has 124 significant bits (i.e., the 4 topmost bits are
+ *    zeros).
+ *
+ * Shift:
+ *
+ *    In principle, the multiplication result requires 55 + 124 = 179 bits to
+ *    represent. However, we then shift this value to the right by j, which is
+ *    at least j >= 115, so the result is guaranteed to fit into 179 - 115 =
+ *    64 bits. This means that we only need the topmost 64 significant bits of
+ *    the 64x128-bit multiplication.
+ *
+ * There are several ways to do this:
+ *
+ *  1. Best case: the compiler exposes a 128-bit type.
+ *     We perform two 64x64-bit multiplications, add the higher 64 bits of the
+ *     lower result to the higher result, and shift by j - 64 bits.
+ *
+ *     We explicitly cast from 64-bit to 128-bit, so the compiler can tell
+ *     that these are only 64-bit inputs, and can map these to the best
+ *     possible sequence of assembly instructions. x86-64 machines happen to
+ *     have matching assembly instructions for 64x64-bit multiplications and
+ *     128-bit shifts.
+ *
+ *  2. Second best case: the compiler exposes intrinsics for the x86-64
+ *     assembly instructions mentioned in 1.
+ *
+ *  3. We only have 64x64 bit instructions that return the lower 64 bits of
+ *     the result, i.e., we have to use plain C.
+ *
+ *     Our inputs are less than the full width, so we have three options:
+ *     a. Ignore this fact and just implement the intrinsics manually.
+ *     b. Split both into 31-bit pieces, which guarantees no internal
+ *        overflow, but requires extra work upfront (unless we change the
+ *        lookup table).
+ *     c. Split only the first factor into 31-bit pieces, which also
+ *        guarantees no internal overflow, but requires extra work since the
+ *        intermediate results are not perfectly aligned.
+ */
+#if defined(HAVE_UINT128)
+
+/*  Best case: use 128-bit type. */
+static inline uint64
+mulShift(const uint64 m, const uint64 *const mul, const int32 j)
+{
+	const uint128 b0 = ((uint128) m) * mul[0];
+	const uint128 b2 = ((uint128) m) * mul[1];
+
+	return (uint64) (((b0 >> 64) + b2) >> (j - 64));
+}
+
+static inline uint64
+mulShiftAll(const uint64 m, const uint64 *const mul, const int32 j,
+			uint64 *const vp, uint64 *const vm, const uint32 mmShift)
+{
+	*vp = mulShift(4 * m + 2, mul, j);
+	*vm = mulShift(4 * m - 1 - mmShift, mul, j);
+	return mulShift(4 * m, mul, j);
+}
+
+#elif defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64
+mulShift(const uint64 m, const uint64 *const mul, const int32 j)
+{
+	/* m is maximum 55 bits */
+	uint64		high1;
+
+	/* 128 */
+	const uint64 low1 = umul128(m, mul[1], &high1);
+
+	/* 64 */
+	uint64		high0;
+	uint64		sum;
+
+	/* 64 */
+	umul128(m, mul[0], &high0);
+	/* 0 */
+	sum = high0 + low1;
+
+	if (sum < high0)
+	{
+		++high1;
+		/* overflow into high1 */
+	}
+	return shiftright128(sum, high1, j - 64);
+}
+
+static inline uint64
+mulShiftAll(const uint64 m, const uint64 *const mul, const int32 j,
+			uint64 *const vp, uint64 *const vm, const uint32 mmShift)
+{
+	*vp = mulShift(4 * m + 2, mul, j);
+	*vm = mulShift(4 * m - 1 - mmShift, mul, j);
+	return mulShift(4 * m, mul, j);
+}
+
+#else							/* // !defined(HAVE_UINT128) &&
+								 * !defined(HAS_64_BIT_INTRINSICS) */
+
+static inline uint64
+mulShiftAll(uint64 m, const uint64 *const mul, const int32 j,
+			uint64 *const vp, uint64 *const vm, const uint32 mmShift)
+{
+	m <<= 1;					/* m is maximum 55 bits */
+
+	uint64		tmp;
+	const uint64 lo = umul128(m, mul[0], &tmp);
+	uint64		hi;
+	const uint64 mid = tmp + umul128(m, mul[1], &hi);
+
+	hi += mid < tmp;			/* overflow into hi */
+
+	const uint64 lo2 = lo + mul[0];
+	const uint64 mid2 = mid + mul[1] + (lo2 < lo);
+	const uint64 hi2 = hi + (mid2 < mid);
+
+	*vp = shiftright128(mid2, hi2, j - 64 - 1);
+
+	if (mmShift == 1)
+	{
+		const uint64 lo3 = lo - mul[0];
+		const uint64 mid3 = mid - mul[1] - (lo3 > lo);
+		const uint64 hi3 = hi - (mid3 > mid);
+
+		*vm = shiftright128(mid3, hi3, j - 64 - 1);
+	}
+	else
+	{
+		const uint64 lo3 = lo + lo;
+		const uint64 mid3 = mid + mid + (lo3 < lo);
+		const uint64 hi3 = hi + hi + (mid3 < mid);
+		const uint64 lo4 = lo3 - mul[0];
+		const uint64 mid4 = mid3 - mul[1] - (lo4 > lo3);
+		const uint64 hi4 = hi3 - (mid4 > mid3);
+
+		*vm = shiftright128(mid4, hi4, j - 64);
+	}
+
+	return shiftright128(mid, hi, j - 64 - 1);
+}
+
+#endif							/* // HAS_64_BIT_INTRINSICS */
+
+static inline uint32
+decimalLength(const uint64 v)
+{
+	/* This is slightly faster than a loop. */
+	/* The average output length is 16.38 digits, so we check high-to-low. */
+	/* Function precondition: v is not an 18, 19, or 20-digit number. */
+	/* (17 digits are sufficient for round-tripping.) */
+	Assert(v < 100000000000000000L);
+	if (v >= 10000000000000000L)
+	{
+		return 17;
+	}
+	if (v >= 1000000000000000L)
+	{
+		return 16;
+	}
+	if (v >= 100000000000000L)
+	{
+		return 15;
+	}
+	if (v >= 10000000000000L)
+	{
+		return 14;
+	}
+	if (v >= 1000000000000L)
+	{
+		return 13;
+	}
+	if (v >= 100000000000L)
+	{
+		return 12;
+	}
+	if (v >= 10000000000L)
+	{
+		return 11;
+	}
+	if (v >= 1000000000L)
+	{
+		return 10;
+	}
+	if (v >= 100000000L)
+	{
+		return 9;
+	}
+	if (v >= 10000000L)
+	{
+		return 8;
+	}
+	if (v >= 1000000L)
+	{
+		return 7;
+	}
+	if (v >= 100000L)
+	{
+		return 6;
+	}
+	if (v >= 10000L)
+	{
+		return 5;
+	}
+	if (v >= 1000L)
+	{
+		return 4;
+	}
+	if (v >= 100L)
+	{
+		return 3;
+	}
+	if (v >= 10L)
+	{
+		return 2;
+	}
+	return 1;
+}
+
+/*  A floating decimal representing m * 10^e. */
+typedef struct floating_decimal_64
+{
+	uint64		mantissa;
+	int32		exponent;
+} floating_decimal_64;
+
+static inline floating_decimal_64
+d2d(const uint64 ieeeMantissa, const uint32 ieeeExponent)
+{
+	int32		e2;
+	uint64		m2;
+
+	if (ieeeExponent == 0)
+	{
+		/* We subtract 2 so that the bounds computation has 2 additional bits. */
+		e2 = 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+		m2 = ieeeMantissa;
+	}
+	else
+	{
+		e2 = ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+		m2 = (UINT64CONST(1) << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+	}
+
+#if STRICTLY_SHORTEST
+	const bool	even = (m2 & 1) == 0;
+	const bool	acceptBounds = even;
+#else
+	const bool	acceptBounds = false;
+#endif
+
+	/* Step 2: Determine the interval of legal decimal representations. */
+	const uint64 mv = 4 * m2;
+
+	/* Implicit bool -> int conversion. True is 1, false is 0. */
+	const uint32 mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
+
+	/* We would compute mp and mm like this: */
+	/* uint64 mp = 4 * m2 + 2; */
+	/* uint64 mm = mv - 1 - mmShift; */
+
+	/* Step 3: Convert to a decimal power base using 128-bit arithmetic. */
+	uint64		vr,
+				vp,
+				vm;
+	int32		e10;
+	bool		vmIsTrailingZeros = false;
+	bool		vrIsTrailingZeros = false;
+
+	if (e2 >= 0)
+	{
+		/*
+		 * I tried special-casing q == 0, but there was no effect on
+		 * performance.
+		 *
+		 * This expr is slightly faster than max(0, log10Pow2(e2) - 1).
+		 */
+		const uint32 q = log10Pow2(e2) - (e2 > 3);
+		const int32 k = DOUBLE_POW5_INV_BITCOUNT + pow5bits(q) - 1;
+		const int32 i = -e2 + q + k;
+
+		e10 = q;
+
+		vr = mulShiftAll(m2, DOUBLE_POW5_INV_SPLIT[q], i, &vp, &vm, mmShift);
+
+		if (q <= 21)
+		{
+			/*
+			 * This should use q <= 22, but I think 21 is also safe. Smaller
+			 * values may still be safe, but it's more difficult to reason
+			 * about them.
+			 *
+			 * Only one of mp, mv, and mm can be a multiple of 5, if any.
+			 */
+			const uint32 mvMod5 = (uint32) (mv - 5 * div5(mv));
+
+			if (mvMod5 == 0)
+			{
+				vrIsTrailingZeros = multipleOfPowerOf5(mv, q);
+			}
+			else if (acceptBounds)
+			{
+				/*----
+				 * Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q
+				 * <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
+				 * <=> true && pow5Factor(mm) >= q, since e2 >= q.
+				 *----
+				 */
+				vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q);
+			}
+			else
+			{
+				/* Same as min(e2 + 1, pow5Factor(mp)) >= q. */
+				vp -= multipleOfPowerOf5(mv + 2, q);
+			}
+		}
+	}
+	else
+	{
+		/*
+		 * This expression is slightly faster than max(0, log10Pow5(-e2) - 1).
+		 */
+		const uint32 q = log10Pow5(-e2) - (-e2 > 1);
+		const int32 i = -e2 - q;
+		const int32 k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
+		const int32 j = q - k;
+
+		e10 = q + e2;
+
+		vr = mulShiftAll(m2, DOUBLE_POW5_SPLIT[i], j, &vp, &vm, mmShift);
+
+		if (q <= 1)
+		{
+			/*
+			 * {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q
+			 * trailing 0 bits.
+			 */
+			/* mv = 4 * m2, so it always has at least two trailing 0 bits. */
+			vrIsTrailingZeros = true;
+			if (acceptBounds)
+			{
+				/*
+				 * mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff
+				 * mmShift == 1.
+				 */
+				vmIsTrailingZeros = mmShift == 1;
+			}
+			else
+			{
+				/*
+				 * mp = mv + 2, so it always has at least one trailing 0 bit.
+				 */
+				--vp;
+			}
+		}
+		else if (q < 63)
+		{
+			/* TODO(ulfjack):Use a tighter bound here. */
+			/*
+			 * We need to compute min(ntz(mv), pow5Factor(mv) - e2) >= q - 1
+			 */
+			/* <=> ntz(mv) >= q - 1 && pow5Factor(mv) - e2 >= q - 1 */
+			/* <=> ntz(mv) >= q - 1 (e2 is negative and -e2 >= q) */
+			/* <=> (mv & ((1 << (q - 1)) - 1)) == 0 */
+
+			/*
+			 * We also need to make sure that the left shift does not
+			 * overflow.
+			 */
+			vrIsTrailingZeros = multipleOfPowerOf2(mv, q - 1);
+		}
+	}
+
+	/*
+	 * Step 4: Find the shortest decimal representation in the interval of
+	 * legal representations.
+	 */
+	uint32		removed = 0;
+	uint8		lastRemovedDigit = 0;
+	uint64		output;
+
+	/* On average, we remove ~2 digits. */
+	if (vmIsTrailingZeros || vrIsTrailingZeros)
+	{
+		/* General case, which happens rarely (~0.7%). */
+		for (;;)
+		{
+			const uint64 vpDiv10 = div10(vp);
+			const uint64 vmDiv10 = div10(vm);
+
+			if (vpDiv10 <= vmDiv10)
+				break;
+
+			const uint32 vmMod10 = (uint32) (vm - 10 * vmDiv10);
+			const uint64 vrDiv10 = div10(vr);
+			const uint32 vrMod10 = (uint32) (vr - 10 * vrDiv10);
+
+			vmIsTrailingZeros &= vmMod10 == 0;
+			vrIsTrailingZeros &= lastRemovedDigit == 0;
+			lastRemovedDigit = (uint8) vrMod10;
+			vr = vrDiv10;
+			vp = vpDiv10;
+			vm = vmDiv10;
+			++removed;
+		}
+
+		if (vmIsTrailingZeros)
+		{
+			for (;;)
+			{
+				const uint64 vmDiv10 = div10(vm);
+				const uint32 vmMod10 = (uint32) (vm - 10 * vmDiv10);
+
+				if (vmMod10 != 0)
+					break;
+
+				const uint64 vpDiv10 = div10(vp);
+				const uint64 vrDiv10 = div10(vr);
+				const uint32 vrMod10 = (uint32) (vr - 10 * vrDiv10);
+
+				vrIsTrailingZeros &= lastRemovedDigit == 0;
+				lastRemovedDigit = (uint8) vrMod10;
+				vr = vrDiv10;
+				vp = vpDiv10;
+				vm = vmDiv10;
+				++removed;
+			}
+		}
+
+		if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0)
+		{
+			/* Round even if the exact number is .....50..0. */
+			lastRemovedDigit = 4;
+		}
+
+		/*
+		 * We need to take vr + 1 if vr is outside bounds or we need to round
+		 * up.
+		 */
+		output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
+	}
+	else
+	{
+		/*
+		 * Specialized for the common case (~99.3%). Percentages below are
+		 * relative to this.
+		 */
+		bool		roundUp = false;
+		const uint64 vpDiv100 = div100(vp);
+		const uint64 vmDiv100 = div100(vm);
+
+		if (vpDiv100 > vmDiv100)
+		{
+			/* Optimization:remove two digits at a time(~86.2 %). */
+			const uint64 vrDiv100 = div100(vr);
+			const uint32 vrMod100 = (uint32) (vr - 100 * vrDiv100);
+
+			roundUp = vrMod100 >= 50;
+			vr = vrDiv100;
+			vp = vpDiv100;
+			vm = vmDiv100;
+			removed += 2;
+		}
+
+		/*----
+		 * Loop iterations below (approximately), without optimization
+		 * above:
+		 *
+		 * 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%,
+		 * 6+: 0.02%
+		 *
+		 * Loop iterations below (approximately), with optimization
+		 * above:
+		 *
+		 * 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
+		 *----
+		 */
+		for (;;)
+		{
+			const uint64 vpDiv10 = div10(vp);
+			const uint64 vmDiv10 = div10(vm);
+
+			if (vpDiv10 <= vmDiv10)
+				break;
+
+			const uint64 vrDiv10 = div10(vr);
+			const uint32 vrMod10 = (uint32) (vr - 10 * vrDiv10);
+
+			roundUp = vrMod10 >= 5;
+			vr = vrDiv10;
+			vp = vpDiv10;
+			vm = vmDiv10;
+			++removed;
+		}
+
+		/*
+		 * We need to take vr + 1 if vr is outside bounds or we need to round
+		 * up.
+		 */
+		output = vr + (vr == vm || roundUp);
+	}
+
+	const int32 exp = e10 + removed;
+
+	floating_decimal_64 fd;
+
+	fd.exponent = exp;
+	fd.mantissa = output;
+	return fd;
+}
+
+static inline int
+to_chars_df(const floating_decimal_64 v, const uint32 olength, char *const result)
+{
+	/* Step 5: Print the decimal representation. */
+	int			index = 0;
+
+	uint64		output = v.mantissa;
+	int32		exp = v.exponent;
+
+	/*----
+	 *
+	 * On entry, mantissa * 10^exp is the result to be output.
+	 * Caller has already done the - sign if needed.
+	 *
+	 * We want to insert the point somewhere else, which might mean
+	 * adding zeros:
+	 *
+	 *            exp  | format
+	 *            1+   |  ddddddddd000000
+	 *            0    |  ddddddddd
+	 *  -1 .. -len+1   |  dddddddd.d to d.ddddddddd
+	 *  -len ...       |  0.ddddddddd to 0.000dddddd
+	 */
+	uint32		i = 0;
+	int32		nexp = exp + olength;
+
+	if (nexp <= 0)
+	{
+		/* 0.0000ddddd */
+		index = 2 - nexp;
+		/* won't need more than this many 0s */
+		memcpy(result, "0.000000", 8);
+	}
+	else if (exp < 0)
+	{
+		/*
+		 * dddd.dddd; leave space at the start and move the '.' in after
+		 */
+		index = 1;
+	}
+
+	/*
+	 * We prefer 32-bit operations, even on 64-bit platforms. We have at most
+	 * 17 digits, and uint32 can store 9 digits. If output doesn't fit into
+	 * uint32, we cut off 8 digits, so the rest will fit into uint32.
+	 */
+	if ((output >> 32) != 0)
+	{
+		/* Expensive 64-bit division. */
+		const uint64 q = div1e8(output);
+		uint32		output2 = (uint32) (output - 100000000 * q);
+		const uint32 c = output2 % 10000;
+
+		output = q;
+		output2 /= 10000;
+
+		const uint32 d = output2 % 10000;
+		const uint32 c0 = (c % 100) << 1;
+		const uint32 c1 = (c / 100) << 1;
+		const uint32 d0 = (d % 100) << 1;
+		const uint32 d1 = (d / 100) << 1;
+
+		memcpy(result + index + olength - i - 2, DIGIT_TABLE + c0, 2);
+		memcpy(result + index + olength - i - 4, DIGIT_TABLE + c1, 2);
+		memcpy(result + index + olength - i - 6, DIGIT_TABLE + d0, 2);
+		memcpy(result + index + olength - i - 8, DIGIT_TABLE + d1, 2);
+		i += 8;
+	}
+
+	uint32		output2 = (uint32) output;
+
+	while (output2 >= 10000)
+	{
+		const uint32 c = output2 - 10000 * (output2 / 10000);
+		const uint32 c0 = (c % 100) << 1;
+		const uint32 c1 = (c / 100) << 1;
+
+		output2 /= 10000;
+		memcpy(result + index + olength - i - 2, DIGIT_TABLE + c0, 2);
+		memcpy(result + index + olength - i - 4, DIGIT_TABLE + c1, 2);
+		i += 4;
+	}
+	if (output2 >= 100)
+	{
+		const uint32 c = (output2 % 100) << 1;
+
+		output2 /= 100;
+		memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+		i += 2;
+	}
+	if (output2 >= 10)
+	{
+		const uint32 c = output2 << 1;
+
+		memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+	}
+	else
+	{
+		result[index] = (char) ('0' + output2);
+	}
+
+	if (index == 1)
+	{
+		/* nexp is 1..16 */
+		/* gcc only seems to want to optimize memmove for small 2^n */
+		if (nexp >= 16)
+		{
+			memmove(result, result + 1, 16);
+		}
+		else
+		{
+			if (nexp & 8)
+			{
+				memmove(result + index - 1, result + index, 8);
+				index += 8;
+			}
+			if (nexp & 4)
+			{
+				memmove(result + index - 1, result + index, 4);
+				index += 4;
+			}
+			if (nexp & 2)
+			{
+				memmove(result + index - 1, result + index, 2);
+				index += 2;
+			}
+			if (nexp & 1)
+			{
+				result[index - 1] = result[index];
+			}
+		}
+		result[nexp] = '.';
+		index = olength + 1;
+	}
+	else if (exp >= 0)
+	{
+		for (int i = 0; i < exp; ++i)
+			result[olength + i] = '0';
+		index = olength + exp;
+	}
+	else
+	{
+		index = olength + (2 - nexp);
+	}
+
+	return index;
+}
+
+static inline int
+to_chars(floating_decimal_64 v, const bool sign, char *const result)
+{
+	/* Step 5: Print the decimal representation. */
+	int			index = 0;
+
+	uint64		output = v.mantissa;
+	uint32		olength = decimalLength(output);
+	int32		exp = v.exponent + olength - 1;
+
+	if (sign)
+	{
+		result[index++] = '-';
+	}
+
+	if (exp >= -4 && exp < 15)
+		return to_chars_df(v, olength, result + index) + sign;
+
+	/*
+	 * If v.exponent is exactly 0, we might have reached here via the small
+	 * integer fast path, in which case v.mantissa might contain trailing
+	 * (decimal) zeros. For scientific notation we need to move these zeros
+	 * into the exponent. (For fixed point this doesn't matter, which is why
+	 * we do this here rather than above.)
+	 *
+	 * Since we already calculated the display exponent (exp) above based on
+	 * the old decimal length, that value does not change here. Instead, we
+	 * just reduce the display length for each digit removed.
+	 *
+	 * If we didn't get here via the fast path, the raw exponent will not
+	 * usually be 0, and there will be no trailing zeros, so we pay no more
+	 * than one div10/multiply extra cost. We claw back half of that by
+	 * checking for divisibility by 2 before dividing by 10.
+	 */
+	if (v.exponent == 0)
+	{
+		while ((output & 1) == 0)
+		{
+			const uint64 q = div10(output);
+			const uint32 r = (uint32) (output - 10 * q);
+
+			if (r != 0)
+				break;
+			output = q;
+			--olength;
+		}
+	}
+
+	/*----
+	 * Print the decimal digits.
+	 *
+	 * The following code is equivalent to:
+	 *
+	 * for (uint32 i = 0; i < olength - 1; ++i) {
+	 *   const uint32 c = output % 10; output /= 10;
+	 *   result[index + olength - i] = (char) ('0' + c);
+	 * }
+	 * result[index] = '0' + output % 10;
+	 *----
+	 */
+
+	uint32		i = 0;
+
+	/*
+	 * We prefer 32-bit operations, even on 64-bit platforms. We have at most
+	 * 17 digits, and uint32 can store 9 digits. If output doesn't fit into
+	 * uint32, we cut off 8 digits, so the rest will fit into uint32.
+	 */
+	if ((output >> 32) != 0)
+	{
+		/* Expensive 64-bit division. */
+		const uint64 q = div1e8(output);
+		uint32		output2 = (uint32) (output - 100000000 * q);
+
+		output = q;
+
+		const uint32 c = output2 % 10000;
+
+		output2 /= 10000;
+
+		const uint32 d = output2 % 10000;
+		const uint32 c0 = (c % 100) << 1;
+		const uint32 c1 = (c / 100) << 1;
+		const uint32 d0 = (d % 100) << 1;
+		const uint32 d1 = (d / 100) << 1;
+
+		memcpy(result + index + olength - i - 1, DIGIT_TABLE + c0, 2);
+		memcpy(result + index + olength - i - 3, DIGIT_TABLE + c1, 2);
+		memcpy(result + index + olength - i - 5, DIGIT_TABLE + d0, 2);
+		memcpy(result + index + olength - i - 7, DIGIT_TABLE + d1, 2);
+		i += 8;
+	}
+
+	uint32		output2 = (uint32) output;
+
+	while (output2 >= 10000)
+	{
+		const uint32 c = output2 - 10000 * (output2 / 10000);
+
+		output2 /= 10000;
+
+		const uint32 c0 = (c % 100) << 1;
+		const uint32 c1 = (c / 100) << 1;
+
+		memcpy(result + index + olength - i - 1, DIGIT_TABLE + c0, 2);
+		memcpy(result + index + olength - i - 3, DIGIT_TABLE + c1, 2);
+		i += 4;
+	}
+	if (output2 >= 100)
+	{
+		const uint32 c = (output2 % 100) << 1;
+
+		output2 /= 100;
+		memcpy(result + index + olength - i - 1, DIGIT_TABLE + c, 2);
+		i += 2;
+	}
+	if (output2 >= 10)
+	{
+		const uint32 c = output2 << 1;
+
+		/*
+		 * We can't use memcpy here: the decimal dot goes between these two
+		 * digits.
+		 */
+		result[index + olength - i] = DIGIT_TABLE[c + 1];
+		result[index] = DIGIT_TABLE[c];
+	}
+	else
+	{
+		result[index] = (char) ('0' + output2);
+	}
+
+	/* Print decimal point if needed. */
+	if (olength > 1)
+	{
+		result[index + 1] = '.';
+		index += olength + 1;
+	}
+	else
+	{
+		++index;
+	}
+
+	/* Print the exponent. */
+	result[index++] = 'e';
+	if (exp < 0)
+	{
+		result[index++] = '-';
+		exp = -exp;
+	}
+	else
+		result[index++] = '+';
+
+	if (exp >= 100)
+	{
+		const int32 c = exp % 10;
+
+		memcpy(result + index, DIGIT_TABLE + 2 * (exp / 10), 2);
+		result[index + 2] = (char) ('0' + c);
+		index += 3;
+	}
+	else
+	{
+		memcpy(result + index, DIGIT_TABLE + 2 * exp, 2);
+		index += 2;
+	}
+
+	return index;
+}
+
+static inline bool
+d2d_small_int(const uint64 ieeeMantissa,
+			  const uint32 ieeeExponent,
+			  floating_decimal_64 *v)
+{
+	const int32 e2 = (int32) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS;
+
+	/*
+	 * Avoid using multiple "return false;" here since it tends to provoke the
+	 * compiler into inlining multiple copies of d2s, which is undesirable.
+	 */
+
+	if (e2 >= -DOUBLE_MANTISSA_BITS && e2 <= 0)
+	{
+		/*----
+		 * Since 2^52 <= m2 < 2^53 and 0 <= -e2 <= 52:
+		 *   1 <= f = m2 / 2^-e2 < 2^53.
+		 *
+		 * Test if the lower -e2 bits of the significand are 0, i.e. whether
+		 * the fraction is 0. We can use ieeeMantissa here, since the implied
+		 * 1 bit can never be tested by this; the implied 1 can only be part
+		 * of a fraction if e2 < -DOUBLE_MANTISSA_BITS which we already
+		 * checked. (e.g. 0.5 gives ieeeMantissa == 0 and e2 == -53)
+		 */
+		const uint64 mask = (UINT64CONST(1) << -e2) - 1;
+		const uint64 fraction = ieeeMantissa & mask;
+
+		if (fraction == 0)
+		{
+			/*----
+			 * f is an integer in the range [1, 2^53).
+			 * Note: mantissa might contain trailing (decimal) 0's.
+			 * Note: since 2^53 < 10^16, there is no need to adjust
+			 * decimalLength().
+			 */
+			const uint64 m2 = (UINT64CONST(1) << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+
+			v->mantissa = m2 >> -e2;
+			v->exponent = 0;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+int
+double_to_shortest_decimal_bufn(double f, char *result)
+{
+	/*
+	 * Step 1: Decode the floating-point number, and unify normalized and
+	 * subnormal cases.
+	 */
+	const uint64 bits = double_to_bits(f);
+
+	/* Decode bits into sign, mantissa, and exponent. */
+	const bool	ieeeSign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
+	const uint64 ieeeMantissa = bits & ((UINT64CONST(1) << DOUBLE_MANTISSA_BITS) - 1);
+	const uint32 ieeeExponent = (uint32) ((bits >> DOUBLE_MANTISSA_BITS) & ((1u << DOUBLE_EXPONENT_BITS) - 1));
+
+	/* Case distinction; exit early for the easy cases. */
+	if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0))
+	{
+		return copy_special_str(result, ieeeSign, ieeeExponent, ieeeMantissa);
+	}
+
+	floating_decimal_64 v;
+	const bool	isSmallInt = d2d_small_int(ieeeMantissa, ieeeExponent, &v);
+
+	if (!isSmallInt)
+	{
+		v = d2d(ieeeMantissa, ieeeExponent);
+	}
+
+	return to_chars(v, ieeeSign, result);
+}
+
+void
+double_to_shortest_decimal_buf(double f, char *result)
+{
+	const int	index = double_to_shortest_decimal_bufn(f, result);
+
+	/* Terminate the string. */
+	result[index] = '\0';
+}
+
+char *
+double_to_shortest_decimal(double f)
+{
+	char	   *const result = (char *) palloc(25);
+
+	double_to_shortest_decimal_buf(f, result);
+	return result;
+}
diff --git a/src/common/d2s_full_table.h b/src/common/d2s_full_table.h
new file mode 100644
index 0000000000..d6520b437b
--- /dev/null
+++ b/src/common/d2s_full_table.h
@@ -0,0 +1,358 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for double precision.
+ *
+ * Portions Copyright (c) 2018-2019, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/common/d2s_full_table.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ *     (See accompanying file LICENSE-Apache or copy at
+ *      http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ *     (See accompanying file LICENSE-Boost or copy at
+ *      https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef RYU_D2S_FULL_TABLE_H
+#define RYU_D2S_FULL_TABLE_H
+
+/*
+ * These tables are generated (by the upstream) using PrintDoubleLookupTable
+ * from the upstream sources at github.com/ulfjack/ryu, and then modified (by
+ * us) by adding UINT64CONST.
+ */
+static const uint64 DOUBLE_POW5_INV_SPLIT[292][2] = {
+	{UINT64CONST(1), UINT64CONST(288230376151711744)}, {UINT64CONST(3689348814741910324), UINT64CONST(230584300921369395)},
+	{UINT64CONST(2951479051793528259), UINT64CONST(184467440737095516)}, {UINT64CONST(17118578500402463900), UINT64CONST(147573952589676412)},
+	{UINT64CONST(12632330341676300947), UINT64CONST(236118324143482260)}, {UINT64CONST(10105864273341040758), UINT64CONST(188894659314785808)},
+	{UINT64CONST(15463389048156653253), UINT64CONST(151115727451828646)}, {UINT64CONST(17362724847566824558), UINT64CONST(241785163922925834)},
+	{UINT64CONST(17579528692795369969), UINT64CONST(193428131138340667)}, {UINT64CONST(6684925324752475329), UINT64CONST(154742504910672534)},
+	{UINT64CONST(18074578149087781173), UINT64CONST(247588007857076054)}, {UINT64CONST(18149011334012135262), UINT64CONST(198070406285660843)},
+	{UINT64CONST(3451162622983977240), UINT64CONST(158456325028528675)}, {UINT64CONST(5521860196774363583), UINT64CONST(253530120045645880)},
+	{UINT64CONST(4417488157419490867), UINT64CONST(202824096036516704)}, {UINT64CONST(7223339340677503017), UINT64CONST(162259276829213363)},
+	{UINT64CONST(7867994130342094503), UINT64CONST(259614842926741381)}, {UINT64CONST(2605046489531765280), UINT64CONST(207691874341393105)},
+	{UINT64CONST(2084037191625412224), UINT64CONST(166153499473114484)}, {UINT64CONST(10713157136084480204), UINT64CONST(265845599156983174)},
+	{UINT64CONST(12259874523609494487), UINT64CONST(212676479325586539)}, {UINT64CONST(13497248433629505913), UINT64CONST(170141183460469231)},
+	{UINT64CONST(14216899864323388813), UINT64CONST(272225893536750770)}, {UINT64CONST(11373519891458711051), UINT64CONST(217780714829400616)},
+	{UINT64CONST(5409467098425058518), UINT64CONST(174224571863520493)}, {UINT64CONST(4965798542738183305), UINT64CONST(278759314981632789)},
+	{UINT64CONST(7661987648932456967), UINT64CONST(223007451985306231)}, {UINT64CONST(2440241304404055250), UINT64CONST(178405961588244985)},
+	{UINT64CONST(3904386087046488400), UINT64CONST(285449538541191976)}, {UINT64CONST(17880904128604832013), UINT64CONST(228359630832953580)},
+	{UINT64CONST(14304723302883865611), UINT64CONST(182687704666362864)}, {UINT64CONST(15133127457049002812), UINT64CONST(146150163733090291)},
+	{UINT64CONST(16834306301794583852), UINT64CONST(233840261972944466)}, {UINT64CONST(9778096226693756759), UINT64CONST(187072209578355573)},
+	{UINT64CONST(15201174610838826053), UINT64CONST(149657767662684458)}, {UINT64CONST(2185786488890659746), UINT64CONST(239452428260295134)},
+	{UINT64CONST(5437978005854438120), UINT64CONST(191561942608236107)}, {UINT64CONST(15418428848909281466), UINT64CONST(153249554086588885)},
+	{UINT64CONST(6222742084545298729), UINT64CONST(245199286538542217)}, {UINT64CONST(16046240111861969953), UINT64CONST(196159429230833773)},
+	{UINT64CONST(1768945645263844993), UINT64CONST(156927543384667019)}, {UINT64CONST(10209010661905972635), UINT64CONST(251084069415467230)},
+	{UINT64CONST(8167208529524778108), UINT64CONST(200867255532373784)}, {UINT64CONST(10223115638361732810), UINT64CONST(160693804425899027)},
+	{UINT64CONST(1599589762411131202), UINT64CONST(257110087081438444)}, {UINT64CONST(4969020624670815285), UINT64CONST(205688069665150755)},
+	{UINT64CONST(3975216499736652228), UINT64CONST(164550455732120604)}, {UINT64CONST(13739044029062464211), UINT64CONST(263280729171392966)},
+	{UINT64CONST(7301886408508061046), UINT64CONST(210624583337114373)}, {UINT64CONST(13220206756290269483), UINT64CONST(168499666669691498)},
+	{UINT64CONST(17462981995322520850), UINT64CONST(269599466671506397)}, {UINT64CONST(6591687966774196033), UINT64CONST(215679573337205118)},
+	{UINT64CONST(12652048002903177473), UINT64CONST(172543658669764094)}, {UINT64CONST(9175230360419352987), UINT64CONST(276069853871622551)},
+	{UINT64CONST(3650835473593572067), UINT64CONST(220855883097298041)}, {UINT64CONST(17678063637842498946), UINT64CONST(176684706477838432)},
+	{UINT64CONST(13527506561580357021), UINT64CONST(282695530364541492)}, {UINT64CONST(3443307619780464970), UINT64CONST(226156424291633194)},
+	{UINT64CONST(6443994910566282300), UINT64CONST(180925139433306555)}, {UINT64CONST(5155195928453025840), UINT64CONST(144740111546645244)},
+	{UINT64CONST(15627011115008661990), UINT64CONST(231584178474632390)}, {UINT64CONST(12501608892006929592), UINT64CONST(185267342779705912)},
+	{UINT64CONST(2622589484121723027), UINT64CONST(148213874223764730)}, {UINT64CONST(4196143174594756843), UINT64CONST(237142198758023568)},
+	{UINT64CONST(10735612169159626121), UINT64CONST(189713759006418854)}, {UINT64CONST(12277838550069611220), UINT64CONST(151771007205135083)},
+	{UINT64CONST(15955192865369467629), UINT64CONST(242833611528216133)}, {UINT64CONST(1696107848069843133), UINT64CONST(194266889222572907)},
+	{UINT64CONST(12424932722681605476), UINT64CONST(155413511378058325)}, {UINT64CONST(1433148282581017146), UINT64CONST(248661618204893321)},
+	{UINT64CONST(15903913885032455010), UINT64CONST(198929294563914656)}, {UINT64CONST(9033782293284053685), UINT64CONST(159143435651131725)},
+	{UINT64CONST(14454051669254485895), UINT64CONST(254629497041810760)}, {UINT64CONST(11563241335403588716), UINT64CONST(203703597633448608)},
+	{UINT64CONST(16629290697806691620), UINT64CONST(162962878106758886)}, {UINT64CONST(781423413297334329), UINT64CONST(260740604970814219)},
+	{UINT64CONST(4314487545379777786), UINT64CONST(208592483976651375)}, {UINT64CONST(3451590036303822229), UINT64CONST(166873987181321100)},
+	{UINT64CONST(5522544058086115566), UINT64CONST(266998379490113760)}, {UINT64CONST(4418035246468892453), UINT64CONST(213598703592091008)},
+	{UINT64CONST(10913125826658934609), UINT64CONST(170878962873672806)}, {UINT64CONST(10082303693170474728), UINT64CONST(273406340597876490)},
+	{UINT64CONST(8065842954536379782), UINT64CONST(218725072478301192)}, {UINT64CONST(17520720807854834795), UINT64CONST(174980057982640953)},
+	{UINT64CONST(5897060404116273733), UINT64CONST(279968092772225526)}, {UINT64CONST(1028299508551108663), UINT64CONST(223974474217780421)},
+	{UINT64CONST(15580034865808528224), UINT64CONST(179179579374224336)}, {UINT64CONST(17549358155809824511), UINT64CONST(286687326998758938)},
+	{UINT64CONST(2971440080422128639), UINT64CONST(229349861599007151)}, {UINT64CONST(17134547323305344204), UINT64CONST(183479889279205720)},
+	{UINT64CONST(13707637858644275364), UINT64CONST(146783911423364576)}, {UINT64CONST(14553522944347019935), UINT64CONST(234854258277383322)},
+	{UINT64CONST(4264120725993795302), UINT64CONST(187883406621906658)}, {UINT64CONST(10789994210278856888), UINT64CONST(150306725297525326)},
+	{UINT64CONST(9885293106962350374), UINT64CONST(240490760476040522)}, {UINT64CONST(529536856086059653), UINT64CONST(192392608380832418)},
+	{UINT64CONST(7802327114352668369), UINT64CONST(153914086704665934)}, {UINT64CONST(1415676938738538420), UINT64CONST(246262538727465495)},
+	{UINT64CONST(1132541550990830736), UINT64CONST(197010030981972396)}, {UINT64CONST(15663428499760305882), UINT64CONST(157608024785577916)},
+	{UINT64CONST(17682787970132668764), UINT64CONST(252172839656924666)}, {UINT64CONST(10456881561364224688), UINT64CONST(201738271725539733)},
+	{UINT64CONST(15744202878575200397), UINT64CONST(161390617380431786)}, {UINT64CONST(17812026976236499989), UINT64CONST(258224987808690858)},
+	{UINT64CONST(3181575136763469022), UINT64CONST(206579990246952687)}, {UINT64CONST(13613306553636506187), UINT64CONST(165263992197562149)},
+	{UINT64CONST(10713244041592678929), UINT64CONST(264422387516099439)}, {UINT64CONST(12259944048016053467), UINT64CONST(211537910012879551)},
+	{UINT64CONST(6118606423670932450), UINT64CONST(169230328010303641)}, {UINT64CONST(2411072648389671274), UINT64CONST(270768524816485826)},
+	{UINT64CONST(16686253377679378312), UINT64CONST(216614819853188660)}, {UINT64CONST(13349002702143502650), UINT64CONST(173291855882550928)},
+	{UINT64CONST(17669055508687693916), UINT64CONST(277266969412081485)}, {UINT64CONST(14135244406950155133), UINT64CONST(221813575529665188)},
+	{UINT64CONST(240149081334393137), UINT64CONST(177450860423732151)}, {UINT64CONST(11452284974360759988), UINT64CONST(283921376677971441)},
+	{UINT64CONST(5472479164746697667), UINT64CONST(227137101342377153)}, {UINT64CONST(11756680961281178780), UINT64CONST(181709681073901722)},
+	{UINT64CONST(2026647139541122378), UINT64CONST(145367744859121378)}, {UINT64CONST(18000030682233437097), UINT64CONST(232588391774594204)},
+	{UINT64CONST(18089373360528660001), UINT64CONST(186070713419675363)}, {UINT64CONST(3403452244197197031), UINT64CONST(148856570735740291)},
+	{UINT64CONST(16513570034941246220), UINT64CONST(238170513177184465)}, {UINT64CONST(13210856027952996976), UINT64CONST(190536410541747572)},
+	{UINT64CONST(3189987192878576934), UINT64CONST(152429128433398058)}, {UINT64CONST(1414630693863812771), UINT64CONST(243886605493436893)},
+	{UINT64CONST(8510402184574870864), UINT64CONST(195109284394749514)}, {UINT64CONST(10497670562401807014), UINT64CONST(156087427515799611)},
+	{UINT64CONST(9417575270359070576), UINT64CONST(249739884025279378)}, {UINT64CONST(14912757845771077107), UINT64CONST(199791907220223502)},
+	{UINT64CONST(4551508647133041040), UINT64CONST(159833525776178802)}, {UINT64CONST(10971762650154775986), UINT64CONST(255733641241886083)},
+	{UINT64CONST(16156107749607641435), UINT64CONST(204586912993508866)}, {UINT64CONST(9235537384944202825), UINT64CONST(163669530394807093)},
+	{UINT64CONST(11087511001168814197), UINT64CONST(261871248631691349)}, {UINT64CONST(12559357615676961681), UINT64CONST(209496998905353079)},
+	{UINT64CONST(13736834907283479668), UINT64CONST(167597599124282463)}, {UINT64CONST(18289587036911657145), UINT64CONST(268156158598851941)},
+	{UINT64CONST(10942320814787415393), UINT64CONST(214524926879081553)}, {UINT64CONST(16132554281313752961), UINT64CONST(171619941503265242)},
+	{UINT64CONST(11054691591134363444), UINT64CONST(274591906405224388)}, {UINT64CONST(16222450902391311402), UINT64CONST(219673525124179510)},
+	{UINT64CONST(12977960721913049122), UINT64CONST(175738820099343608)}, {UINT64CONST(17075388340318968271), UINT64CONST(281182112158949773)},
+	{UINT64CONST(2592264228029443648), UINT64CONST(224945689727159819)}, {UINT64CONST(5763160197165465241), UINT64CONST(179956551781727855)},
+	{UINT64CONST(9221056315464744386), UINT64CONST(287930482850764568)}, {UINT64CONST(14755542681855616155), UINT64CONST(230344386280611654)},
+	{UINT64CONST(15493782960226403247), UINT64CONST(184275509024489323)}, {UINT64CONST(1326979923955391628), UINT64CONST(147420407219591459)},
+	{UINT64CONST(9501865507812447252), UINT64CONST(235872651551346334)}, {UINT64CONST(11290841220991868125), UINT64CONST(188698121241077067)},
+	{UINT64CONST(1653975347309673853), UINT64CONST(150958496992861654)}, {UINT64CONST(10025058185179298811), UINT64CONST(241533595188578646)},
+	{UINT64CONST(4330697733401528726), UINT64CONST(193226876150862917)}, {UINT64CONST(14532604630946953951), UINT64CONST(154581500920690333)},
+	{UINT64CONST(1116074521063664381), UINT64CONST(247330401473104534)}, {UINT64CONST(4582208431592841828), UINT64CONST(197864321178483627)},
+	{UINT64CONST(14733813189500004432), UINT64CONST(158291456942786901)}, {UINT64CONST(16195403473716186445), UINT64CONST(253266331108459042)},
+	{UINT64CONST(5577625149489128510), UINT64CONST(202613064886767234)}, {UINT64CONST(8151448934333213131), UINT64CONST(162090451909413787)},
+	{UINT64CONST(16731667109675051333), UINT64CONST(259344723055062059)}, {UINT64CONST(17074682502481951390), UINT64CONST(207475778444049647)},
+	{UINT64CONST(6281048372501740465), UINT64CONST(165980622755239718)}, {UINT64CONST(6360328581260874421), UINT64CONST(265568996408383549)},
+	{UINT64CONST(8777611679750609860), UINT64CONST(212455197126706839)}, {UINT64CONST(10711438158542398211), UINT64CONST(169964157701365471)},
+	{UINT64CONST(9759603424184016492), UINT64CONST(271942652322184754)}, {UINT64CONST(11497031554089123517), UINT64CONST(217554121857747803)},
+	{UINT64CONST(16576322872755119460), UINT64CONST(174043297486198242)}, {UINT64CONST(11764721337440549842), UINT64CONST(278469275977917188)},
+	{UINT64CONST(16790474699436260520), UINT64CONST(222775420782333750)}, {UINT64CONST(13432379759549008416), UINT64CONST(178220336625867000)},
+	{UINT64CONST(3045063541568861850), UINT64CONST(285152538601387201)}, {UINT64CONST(17193446092222730773), UINT64CONST(228122030881109760)},
+	{UINT64CONST(13754756873778184618), UINT64CONST(182497624704887808)}, {UINT64CONST(18382503128506368341), UINT64CONST(145998099763910246)},
+	{UINT64CONST(3586563302416817083), UINT64CONST(233596959622256395)}, {UINT64CONST(2869250641933453667), UINT64CONST(186877567697805116)},
+	{UINT64CONST(17052795772514404226), UINT64CONST(149502054158244092)}, {UINT64CONST(12527077977055405469), UINT64CONST(239203286653190548)},
+	{UINT64CONST(17400360011128145022), UINT64CONST(191362629322552438)}, {UINT64CONST(2852241564676785048), UINT64CONST(153090103458041951)},
+	{UINT64CONST(15631632947708587046), UINT64CONST(244944165532867121)}, {UINT64CONST(8815957543424959314), UINT64CONST(195955332426293697)},
+	{UINT64CONST(18120812478965698421), UINT64CONST(156764265941034957)}, {UINT64CONST(14235904707377476180), UINT64CONST(250822825505655932)},
+	{UINT64CONST(4010026136418160298), UINT64CONST(200658260404524746)}, {UINT64CONST(17965416168102169531), UINT64CONST(160526608323619796)},
+	{UINT64CONST(2919224165770098987), UINT64CONST(256842573317791675)}, {UINT64CONST(2335379332616079190), UINT64CONST(205474058654233340)},
+	{UINT64CONST(1868303466092863352), UINT64CONST(164379246923386672)}, {UINT64CONST(6678634360490491686), UINT64CONST(263006795077418675)},
+	{UINT64CONST(5342907488392393349), UINT64CONST(210405436061934940)}, {UINT64CONST(4274325990713914679), UINT64CONST(168324348849547952)},
+	{UINT64CONST(10528270399884173809), UINT64CONST(269318958159276723)}, {UINT64CONST(15801313949391159694), UINT64CONST(215455166527421378)},
+	{UINT64CONST(1573004715287196786), UINT64CONST(172364133221937103)}, {UINT64CONST(17274202803427156150), UINT64CONST(275782613155099364)},
+	{UINT64CONST(17508711057483635243), UINT64CONST(220626090524079491)}, {UINT64CONST(10317620031244997871), UINT64CONST(176500872419263593)},
+	{UINT64CONST(12818843235250086271), UINT64CONST(282401395870821749)}, {UINT64CONST(13944423402941979340), UINT64CONST(225921116696657399)},
+	{UINT64CONST(14844887537095493795), UINT64CONST(180736893357325919)}, {UINT64CONST(15565258844418305359), UINT64CONST(144589514685860735)},
+	{UINT64CONST(6457670077359736959), UINT64CONST(231343223497377177)}, {UINT64CONST(16234182506113520537), UINT64CONST(185074578797901741)},
+	{UINT64CONST(9297997190148906106), UINT64CONST(148059663038321393)}, {UINT64CONST(11187446689496339446), UINT64CONST(236895460861314229)},
+	{UINT64CONST(12639306166338981880), UINT64CONST(189516368689051383)}, {UINT64CONST(17490142562555006151), UINT64CONST(151613094951241106)},
+	{UINT64CONST(2158786396894637579), UINT64CONST(242580951921985771)}, {UINT64CONST(16484424376483351356), UINT64CONST(194064761537588616)},
+	{UINT64CONST(9498190686444770762), UINT64CONST(155251809230070893)}, {UINT64CONST(11507756283569722895), UINT64CONST(248402894768113429)},
+	{UINT64CONST(12895553841597688639), UINT64CONST(198722315814490743)}, {UINT64CONST(17695140702761971558), UINT64CONST(158977852651592594)},
+	{UINT64CONST(17244178680193423523), UINT64CONST(254364564242548151)}, {UINT64CONST(10105994129412828495), UINT64CONST(203491651394038521)},
+	{UINT64CONST(4395446488788352473), UINT64CONST(162793321115230817)}, {UINT64CONST(10722063196803274280), UINT64CONST(260469313784369307)},
+	{UINT64CONST(1198952927958798777), UINT64CONST(208375451027495446)}, {UINT64CONST(15716557601334680315), UINT64CONST(166700360821996356)},
+	{UINT64CONST(17767794532651667857), UINT64CONST(266720577315194170)}, {UINT64CONST(14214235626121334286), UINT64CONST(213376461852155336)},
+	{UINT64CONST(7682039686155157106), UINT64CONST(170701169481724269)}, {UINT64CONST(1223217053622520399), UINT64CONST(273121871170758831)},
+	{UINT64CONST(15735968901865657612), UINT64CONST(218497496936607064)}, {UINT64CONST(16278123936234436413), UINT64CONST(174797997549285651)},
+	{UINT64CONST(219556594781725998), UINT64CONST(279676796078857043)}, {UINT64CONST(7554342905309201445), UINT64CONST(223741436863085634)},
+	{UINT64CONST(9732823138989271479), UINT64CONST(178993149490468507)}, {UINT64CONST(815121763415193074), UINT64CONST(286389039184749612)},
+	{UINT64CONST(11720143854957885429), UINT64CONST(229111231347799689)}, {UINT64CONST(13065463898708218666), UINT64CONST(183288985078239751)},
+	{UINT64CONST(6763022304224664610), UINT64CONST(146631188062591801)}, {UINT64CONST(3442138057275642729), UINT64CONST(234609900900146882)},
+	{UINT64CONST(13821756890046245153), UINT64CONST(187687920720117505)}, {UINT64CONST(11057405512036996122), UINT64CONST(150150336576094004)},
+	{UINT64CONST(6623802375033462826), UINT64CONST(240240538521750407)}, {UINT64CONST(16367088344252501231), UINT64CONST(192192430817400325)},
+	{UINT64CONST(13093670675402000985), UINT64CONST(153753944653920260)}, {UINT64CONST(2503129006933649959), UINT64CONST(246006311446272417)},
+	{UINT64CONST(13070549649772650937), UINT64CONST(196805049157017933)}, {UINT64CONST(17835137349301941396), UINT64CONST(157444039325614346)},
+	{UINT64CONST(2710778055689733971), UINT64CONST(251910462920982955)}, {UINT64CONST(2168622444551787177), UINT64CONST(201528370336786364)},
+	{UINT64CONST(5424246770383340065), UINT64CONST(161222696269429091)}, {UINT64CONST(1300097203129523457), UINT64CONST(257956314031086546)},
+	{UINT64CONST(15797473021471260058), UINT64CONST(206365051224869236)}, {UINT64CONST(8948629602435097724), UINT64CONST(165092040979895389)},
+	{UINT64CONST(3249760919670425388), UINT64CONST(264147265567832623)}, {UINT64CONST(9978506365220160957), UINT64CONST(211317812454266098)},
+	{UINT64CONST(15361502721659949412), UINT64CONST(169054249963412878)}, {UINT64CONST(2442311466204457120), UINT64CONST(270486799941460606)},
+	{UINT64CONST(16711244431931206989), UINT64CONST(216389439953168484)}, {UINT64CONST(17058344360286875914), UINT64CONST(173111551962534787)},
+	{UINT64CONST(12535955717491360170), UINT64CONST(276978483140055660)}, {UINT64CONST(10028764573993088136), UINT64CONST(221582786512044528)},
+	{UINT64CONST(15401709288678291155), UINT64CONST(177266229209635622)}, {UINT64CONST(9885339602917624555), UINT64CONST(283625966735416996)},
+	{UINT64CONST(4218922867592189321), UINT64CONST(226900773388333597)}, {UINT64CONST(14443184738299482427), UINT64CONST(181520618710666877)},
+	{UINT64CONST(4175850161155765295), UINT64CONST(145216494968533502)}, {UINT64CONST(10370709072591134795), UINT64CONST(232346391949653603)},
+	{UINT64CONST(15675264887556728482), UINT64CONST(185877113559722882)}, {UINT64CONST(5161514280561562140), UINT64CONST(148701690847778306)},
+	{UINT64CONST(879725219414678777), UINT64CONST(237922705356445290)}, {UINT64CONST(703780175531743021), UINT64CONST(190338164285156232)},
+	{UINT64CONST(11631070584651125387), UINT64CONST(152270531428124985)}, {UINT64CONST(162968861732249003), UINT64CONST(243632850284999977)},
+	{UINT64CONST(11198421533611530172), UINT64CONST(194906280227999981)}, {UINT64CONST(5269388412147313814), UINT64CONST(155925024182399985)},
+	{UINT64CONST(8431021459435702103), UINT64CONST(249480038691839976)}, {UINT64CONST(3055468352806651359), UINT64CONST(199584030953471981)},
+	{UINT64CONST(17201769941212962380), UINT64CONST(159667224762777584)}, {UINT64CONST(16454785461715008838), UINT64CONST(255467559620444135)},
+	{UINT64CONST(13163828369372007071), UINT64CONST(204374047696355308)}, {UINT64CONST(17909760324981426303), UINT64CONST(163499238157084246)},
+	{UINT64CONST(2830174816776909822), UINT64CONST(261598781051334795)}, {UINT64CONST(2264139853421527858), UINT64CONST(209279024841067836)},
+	{UINT64CONST(16568707141704863579), UINT64CONST(167423219872854268)}, {UINT64CONST(4373838538276319787), UINT64CONST(267877151796566830)},
+	{UINT64CONST(3499070830621055830), UINT64CONST(214301721437253464)}, {UINT64CONST(6488605479238754987), UINT64CONST(171441377149802771)},
+	{UINT64CONST(3003071137298187333), UINT64CONST(274306203439684434)}, {UINT64CONST(6091805724580460189), UINT64CONST(219444962751747547)},
+	{UINT64CONST(15941491023890099121), UINT64CONST(175555970201398037)}, {UINT64CONST(10748990379256517301), UINT64CONST(280889552322236860)},
+	{UINT64CONST(8599192303405213841), UINT64CONST(224711641857789488)}, {UINT64CONST(14258051472207991719), UINT64CONST(179769313486231590)}
+};
+
+static const uint64 DOUBLE_POW5_SPLIT[326][2] = {
+	{UINT64CONST(0), UINT64CONST(72057594037927936)}, {UINT64CONST(0), UINT64CONST(90071992547409920)},
+	{UINT64CONST(0), UINT64CONST(112589990684262400)}, {UINT64CONST(0), UINT64CONST(140737488355328000)},
+	{UINT64CONST(0), UINT64CONST(87960930222080000)}, {UINT64CONST(0), UINT64CONST(109951162777600000)},
+	{UINT64CONST(0), UINT64CONST(137438953472000000)}, {UINT64CONST(0), UINT64CONST(85899345920000000)},
+	{UINT64CONST(0), UINT64CONST(107374182400000000)}, {UINT64CONST(0), UINT64CONST(134217728000000000)},
+	{UINT64CONST(0), UINT64CONST(83886080000000000)}, {UINT64CONST(0), UINT64CONST(104857600000000000)},
+	{UINT64CONST(0), UINT64CONST(131072000000000000)}, {UINT64CONST(0), UINT64CONST(81920000000000000)},
+	{UINT64CONST(0), UINT64CONST(102400000000000000)}, {UINT64CONST(0), UINT64CONST(128000000000000000)},
+	{UINT64CONST(0), UINT64CONST(80000000000000000)}, {UINT64CONST(0), UINT64CONST(100000000000000000)},
+	{UINT64CONST(0), UINT64CONST(125000000000000000)}, {UINT64CONST(0), UINT64CONST(78125000000000000)},
+	{UINT64CONST(0), UINT64CONST(97656250000000000)}, {UINT64CONST(0), UINT64CONST(122070312500000000)},
+	{UINT64CONST(0), UINT64CONST(76293945312500000)}, {UINT64CONST(0), UINT64CONST(95367431640625000)},
+	{UINT64CONST(0), UINT64CONST(119209289550781250)}, {UINT64CONST(4611686018427387904), UINT64CONST(74505805969238281)},
+	{UINT64CONST(10376293541461622784), UINT64CONST(93132257461547851)}, {UINT64CONST(8358680908399640576), UINT64CONST(116415321826934814)},
+	{UINT64CONST(612489549322387456), UINT64CONST(72759576141834259)}, {UINT64CONST(14600669991935148032), UINT64CONST(90949470177292823)},
+	{UINT64CONST(13639151471491547136), UINT64CONST(113686837721616029)}, {UINT64CONST(3213881284082270208), UINT64CONST(142108547152020037)},
+	{UINT64CONST(4314518811765112832), UINT64CONST(88817841970012523)}, {UINT64CONST(781462496279003136), UINT64CONST(111022302462515654)},
+	{UINT64CONST(10200200157203529728), UINT64CONST(138777878078144567)}, {UINT64CONST(13292654125893287936), UINT64CONST(86736173798840354)},
+	{UINT64CONST(7392445620511834112), UINT64CONST(108420217248550443)}, {UINT64CONST(4628871007212404736), UINT64CONST(135525271560688054)},
+	{UINT64CONST(16728102434789916672), UINT64CONST(84703294725430033)}, {UINT64CONST(7075069988205232128), UINT64CONST(105879118406787542)},
+	{UINT64CONST(18067209522111315968), UINT64CONST(132348898008484427)}, {UINT64CONST(8986162942105878528), UINT64CONST(82718061255302767)},
+	{UINT64CONST(6621017659204960256), UINT64CONST(103397576569128459)}, {UINT64CONST(3664586055578812416), UINT64CONST(129246970711410574)},
+	{UINT64CONST(16125424340018921472), UINT64CONST(80779356694631608)}, {UINT64CONST(1710036351314100224), UINT64CONST(100974195868289511)},
+	{UINT64CONST(15972603494424788992), UINT64CONST(126217744835361888)}, {UINT64CONST(9982877184015493120), UINT64CONST(78886090522101180)},
+	{UINT64CONST(12478596480019366400), UINT64CONST(98607613152626475)}, {UINT64CONST(10986559581596820096), UINT64CONST(123259516440783094)},
+	{UINT64CONST(2254913720070624656), UINT64CONST(77037197775489434)}, {UINT64CONST(12042014186943056628), UINT64CONST(96296497219361792)},
+	{UINT64CONST(15052517733678820785), UINT64CONST(120370621524202240)}, {UINT64CONST(9407823583549262990), UINT64CONST(75231638452626400)},
+	{UINT64CONST(11759779479436578738), UINT64CONST(94039548065783000)}, {UINT64CONST(14699724349295723422), UINT64CONST(117549435082228750)},
+	{UINT64CONST(4575641699882439235), UINT64CONST(73468396926392969)}, {UINT64CONST(10331238143280436948), UINT64CONST(91835496157991211)},
+	{UINT64CONST(8302361660673158281), UINT64CONST(114794370197489014)}, {UINT64CONST(1154580038986672043), UINT64CONST(143492962746861268)},
+	{UINT64CONST(9944984561221445835), UINT64CONST(89683101716788292)}, {UINT64CONST(12431230701526807293), UINT64CONST(112103877145985365)},
+	{UINT64CONST(1703980321626345405), UINT64CONST(140129846432481707)}, {UINT64CONST(17205888765512323542), UINT64CONST(87581154020301066)},
+	{UINT64CONST(12283988920035628619), UINT64CONST(109476442525376333)}, {UINT64CONST(1519928094762372062), UINT64CONST(136845553156720417)},
+	{UINT64CONST(12479170105294952299), UINT64CONST(85528470722950260)}, {UINT64CONST(15598962631618690374), UINT64CONST(106910588403687825)},
+	{UINT64CONST(5663645234241199255), UINT64CONST(133638235504609782)}, {UINT64CONST(17374836326682913246), UINT64CONST(83523897190381113)},
+	{UINT64CONST(7883487353071477846), UINT64CONST(104404871487976392)}, {UINT64CONST(9854359191339347308), UINT64CONST(130506089359970490)},
+	{UINT64CONST(10770660513014479971), UINT64CONST(81566305849981556)}, {UINT64CONST(13463325641268099964), UINT64CONST(101957882312476945)},
+	{UINT64CONST(2994098996302961243), UINT64CONST(127447352890596182)}, {UINT64CONST(15706369927971514489), UINT64CONST(79654595556622613)},
+	{UINT64CONST(5797904354682229399), UINT64CONST(99568244445778267)}, {UINT64CONST(2635694424925398845), UINT64CONST(124460305557222834)},
+	{UINT64CONST(6258995034005762182), UINT64CONST(77787690973264271)}, {UINT64CONST(3212057774079814824), UINT64CONST(97234613716580339)},
+	{UINT64CONST(17850130272881932242), UINT64CONST(121543267145725423)}, {UINT64CONST(18073860448192289507), UINT64CONST(75964541966078389)},
+	{UINT64CONST(8757267504958198172), UINT64CONST(94955677457597987)}, {UINT64CONST(6334898362770359811), UINT64CONST(118694596821997484)},
+	{UINT64CONST(13182683513586250689), UINT64CONST(74184123013748427)}, {UINT64CONST(11866668373555425458), UINT64CONST(92730153767185534)},
+	{UINT64CONST(5609963430089506015), UINT64CONST(115912692208981918)}, {UINT64CONST(17341285199088104971), UINT64CONST(72445432630613698)},
+	{UINT64CONST(12453234462005355406), UINT64CONST(90556790788267123)}, {UINT64CONST(10954857059079306353), UINT64CONST(113195988485333904)},
+	{UINT64CONST(13693571323849132942), UINT64CONST(141494985606667380)}, {UINT64CONST(17781854114260483896), UINT64CONST(88434366004167112)},
+	{UINT64CONST(3780573569116053255), UINT64CONST(110542957505208891)}, {UINT64CONST(114030942967678664), UINT64CONST(138178696881511114)},
+	{UINT64CONST(4682955357782187069), UINT64CONST(86361685550944446)}, {UINT64CONST(15077066234082509644), UINT64CONST(107952106938680557)},
+	{UINT64CONST(5011274737320973344), UINT64CONST(134940133673350697)}, {UINT64CONST(14661261756894078100), UINT64CONST(84337583545844185)},
+	{UINT64CONST(4491519140835433913), UINT64CONST(105421979432305232)}, {UINT64CONST(5614398926044292391), UINT64CONST(131777474290381540)},
+	{UINT64CONST(12732371365632458552), UINT64CONST(82360921431488462)}, {UINT64CONST(6692092170185797382), UINT64CONST(102951151789360578)},
+	{UINT64CONST(17588487249587022536), UINT64CONST(128688939736700722)}, {UINT64CONST(15604490549419276989), UINT64CONST(80430587335437951)},
+	{UINT64CONST(14893927168346708332), UINT64CONST(100538234169297439)}, {UINT64CONST(14005722942005997511), UINT64CONST(125672792711621799)},
+	{UINT64CONST(15671105866394830300), UINT64CONST(78545495444763624)}, {UINT64CONST(1142138259283986260), UINT64CONST(98181869305954531)},
+	{UINT64CONST(15262730879387146537), UINT64CONST(122727336632443163)}, {UINT64CONST(7233363790403272633), UINT64CONST(76704585395276977)},
+	{UINT64CONST(13653390756431478696), UINT64CONST(95880731744096221)}, {UINT64CONST(3231680390257184658), UINT64CONST(119850914680120277)},
+	{UINT64CONST(4325643253124434363), UINT64CONST(74906821675075173)}, {UINT64CONST(10018740084832930858), UINT64CONST(93633527093843966)},
+	{UINT64CONST(3300053069186387764), UINT64CONST(117041908867304958)}, {UINT64CONST(15897591223523656064), UINT64CONST(73151193042065598)},
+	{UINT64CONST(10648616992549794273), UINT64CONST(91438991302581998)}, {UINT64CONST(4087399203832467033), UINT64CONST(114298739128227498)},
+	{UINT64CONST(14332621041645359599), UINT64CONST(142873423910284372)}, {UINT64CONST(18181260187883125557), UINT64CONST(89295889943927732)},
+	{UINT64CONST(4279831161144355331), UINT64CONST(111619862429909666)}, {UINT64CONST(14573160988285219972), UINT64CONST(139524828037387082)},
+	{UINT64CONST(13719911636105650386), UINT64CONST(87203017523366926)}, {UINT64CONST(7926517508277287175), UINT64CONST(109003771904208658)},
+	{UINT64CONST(684774848491833161), UINT64CONST(136254714880260823)}, {UINT64CONST(7345513307948477581), UINT64CONST(85159196800163014)},
+	{UINT64CONST(18405263671790372785), UINT64CONST(106448996000203767)}, {UINT64CONST(18394893571310578077), UINT64CONST(133061245000254709)},
+	{UINT64CONST(13802651491282805250), UINT64CONST(83163278125159193)}, {UINT64CONST(3418256308821342851), UINT64CONST(103954097656448992)},
+	{UINT64CONST(4272820386026678563), UINT64CONST(129942622070561240)}, {UINT64CONST(2670512741266674102), UINT64CONST(81214138794100775)},
+	{UINT64CONST(17173198981865506339), UINT64CONST(101517673492625968)}, {UINT64CONST(3019754653622331308), UINT64CONST(126897091865782461)},
+	{UINT64CONST(4193189667727651020), UINT64CONST(79310682416114038)}, {UINT64CONST(14464859121514339583), UINT64CONST(99138353020142547)},
+	{UINT64CONST(13469387883465536574), UINT64CONST(123922941275178184)}, {UINT64CONST(8418367427165960359), UINT64CONST(77451838296986365)},
+	{UINT64CONST(15134645302384838353), UINT64CONST(96814797871232956)}, {UINT64CONST(471562554271496325), UINT64CONST(121018497339041196)},
+	{UINT64CONST(9518098633274461011), UINT64CONST(75636560836900747)}, {UINT64CONST(7285937273165688360), UINT64CONST(94545701046125934)},
+	{UINT64CONST(18330793628311886258), UINT64CONST(118182126307657417)}, {UINT64CONST(4539216990053847055), UINT64CONST(73863828942285886)},
+	{UINT64CONST(14897393274422084627), UINT64CONST(92329786177857357)}, {UINT64CONST(4786683537745442072), UINT64CONST(115412232722321697)},
+	{UINT64CONST(14520892257159371055), UINT64CONST(72132645451451060)}, {UINT64CONST(18151115321449213818), UINT64CONST(90165806814313825)},
+	{UINT64CONST(8853836096529353561), UINT64CONST(112707258517892282)}, {UINT64CONST(1843923083806916143), UINT64CONST(140884073147365353)},
+	{UINT64CONST(12681666973447792349), UINT64CONST(88052545717103345)}, {UINT64CONST(2017025661527576725), UINT64CONST(110065682146379182)},
+	{UINT64CONST(11744654113764246714), UINT64CONST(137582102682973977)}, {UINT64CONST(422879793461572340), UINT64CONST(85988814176858736)},
+	{UINT64CONST(528599741826965425), UINT64CONST(107486017721073420)}, {UINT64CONST(660749677283706782), UINT64CONST(134357522151341775)},
+	{UINT64CONST(7330497575943398595), UINT64CONST(83973451344588609)}, {UINT64CONST(13774807988356636147), UINT64CONST(104966814180735761)},
+	{UINT64CONST(3383451930163631472), UINT64CONST(131208517725919702)}, {UINT64CONST(15949715511634433382), UINT64CONST(82005323578699813)},
+	{UINT64CONST(6102086334260878016), UINT64CONST(102506654473374767)}, {UINT64CONST(3015921899398709616), UINT64CONST(128133318091718459)},
+	{UINT64CONST(18025852251620051174), UINT64CONST(80083323807324036)}, {UINT64CONST(4085571240815512351), UINT64CONST(100104154759155046)},
+	{UINT64CONST(14330336087874166247), UINT64CONST(125130193448943807)}, {UINT64CONST(15873989082562435760), UINT64CONST(78206370905589879)},
+	{UINT64CONST(15230800334775656796), UINT64CONST(97757963631987349)}, {UINT64CONST(5203442363187407284), UINT64CONST(122197454539984187)},
+	{UINT64CONST(946308467778435600), UINT64CONST(76373409087490117)}, {UINT64CONST(5794571603150432404), UINT64CONST(95466761359362646)},
+	{UINT64CONST(16466586540792816313), UINT64CONST(119333451699203307)}, {UINT64CONST(7985773578781816244), UINT64CONST(74583407312002067)},
+	{UINT64CONST(5370530955049882401), UINT64CONST(93229259140002584)}, {UINT64CONST(6713163693812353001), UINT64CONST(116536573925003230)},
+	{UINT64CONST(18030785363914884337), UINT64CONST(72835358703127018)}, {UINT64CONST(13315109668038829614), UINT64CONST(91044198378908773)},
+	{UINT64CONST(2808829029766373305), UINT64CONST(113805247973635967)}, {UINT64CONST(17346094342490130344), UINT64CONST(142256559967044958)},
+	{UINT64CONST(6229622945628943561), UINT64CONST(88910349979403099)}, {UINT64CONST(3175342663608791547), UINT64CONST(111137937474253874)},
+	{UINT64CONST(13192550366365765242), UINT64CONST(138922421842817342)}, {UINT64CONST(3633657960551215372), UINT64CONST(86826513651760839)},
+	{UINT64CONST(18377130505971182927), UINT64CONST(108533142064701048)}, {UINT64CONST(4524669058754427043), UINT64CONST(135666427580876311)},
+	{UINT64CONST(9745447189362598758), UINT64CONST(84791517238047694)}, {UINT64CONST(2958436949848472639), UINT64CONST(105989396547559618)},
+	{UINT64CONST(12921418224165366607), UINT64CONST(132486745684449522)}, {UINT64CONST(12687572408530742033), UINT64CONST(82804216052780951)},
+	{UINT64CONST(11247779492236039638), UINT64CONST(103505270065976189)}, {UINT64CONST(224666310012885835), UINT64CONST(129381587582470237)},
+	{UINT64CONST(2446259452971747599), UINT64CONST(80863492239043898)}, {UINT64CONST(12281196353069460307), UINT64CONST(101079365298804872)},
+	{UINT64CONST(15351495441336825384), UINT64CONST(126349206623506090)}, {UINT64CONST(14206370669262903769), UINT64CONST(78968254139691306)},
+	{UINT64CONST(8534591299723853903), UINT64CONST(98710317674614133)}, {UINT64CONST(15279925143082205283), UINT64CONST(123387897093267666)},
+	{UINT64CONST(14161639232853766206), UINT64CONST(77117435683292291)}, {UINT64CONST(13090363022639819853), UINT64CONST(96396794604115364)},
+	{UINT64CONST(16362953778299774816), UINT64CONST(120495993255144205)}, {UINT64CONST(12532689120651053212), UINT64CONST(75309995784465128)},
+	{UINT64CONST(15665861400813816515), UINT64CONST(94137494730581410)}, {UINT64CONST(10358954714162494836), UINT64CONST(117671868413226763)},
+	{UINT64CONST(4168503687137865320), UINT64CONST(73544917758266727)}, {UINT64CONST(598943590494943747), UINT64CONST(91931147197833409)},
+	{UINT64CONST(5360365506546067587), UINT64CONST(114913933997291761)}, {UINT64CONST(11312142901609972388), UINT64CONST(143642417496614701)},
+	{UINT64CONST(9375932322719926695), UINT64CONST(89776510935384188)}, {UINT64CONST(11719915403399908368), UINT64CONST(112220638669230235)},
+	{UINT64CONST(10038208235822497557), UINT64CONST(140275798336537794)}, {UINT64CONST(10885566165816448877), UINT64CONST(87672373960336121)},
+	{UINT64CONST(18218643725697949000), UINT64CONST(109590467450420151)}, {UINT64CONST(18161618638695048346), UINT64CONST(136988084313025189)},
+	{UINT64CONST(13656854658398099168), UINT64CONST(85617552695640743)}, {UINT64CONST(12459382304570236056), UINT64CONST(107021940869550929)},
+	{UINT64CONST(1739169825430631358), UINT64CONST(133777426086938662)}, {UINT64CONST(14922039196176308311), UINT64CONST(83610891304336663)},
+	{UINT64CONST(14040862976792997485), UINT64CONST(104513614130420829)}, {UINT64CONST(3716020665709083144), UINT64CONST(130642017663026037)},
+	{UINT64CONST(4628355925281870917), UINT64CONST(81651261039391273)}, {UINT64CONST(10397130925029726550), UINT64CONST(102064076299239091)},
+	{UINT64CONST(8384727637859770284), UINT64CONST(127580095374048864)}, {UINT64CONST(5240454773662356427), UINT64CONST(79737559608780540)},
+	{UINT64CONST(6550568467077945534), UINT64CONST(99671949510975675)}, {UINT64CONST(3576524565420044014), UINT64CONST(124589936888719594)},
+	{UINT64CONST(6847013871814915412), UINT64CONST(77868710555449746)}, {UINT64CONST(17782139376623420074), UINT64CONST(97335888194312182)},
+	{UINT64CONST(13004302183924499284), UINT64CONST(121669860242890228)}, {UINT64CONST(17351060901807587860), UINT64CONST(76043662651806392)},
+	{UINT64CONST(3242082053549933210), UINT64CONST(95054578314757991)}, {UINT64CONST(17887660622219580224), UINT64CONST(118818222893447488)},
+	{UINT64CONST(11179787888887237640), UINT64CONST(74261389308404680)}, {UINT64CONST(13974734861109047050), UINT64CONST(92826736635505850)},
+	{UINT64CONST(8245046539531533005), UINT64CONST(116033420794382313)}, {UINT64CONST(16682369133275677888), UINT64CONST(72520887996488945)},
+	{UINT64CONST(7017903361312433648), UINT64CONST(90651109995611182)}, {UINT64CONST(17995751238495317868), UINT64CONST(113313887494513977)},
+	{UINT64CONST(8659630992836983623), UINT64CONST(141642359368142472)}, {UINT64CONST(5412269370523114764), UINT64CONST(88526474605089045)},
+	{UINT64CONST(11377022731581281359), UINT64CONST(110658093256361306)}, {UINT64CONST(4997906377621825891), UINT64CONST(138322616570451633)},
+	{UINT64CONST(14652906532082110942), UINT64CONST(86451635356532270)}, {UINT64CONST(9092761128247862869), UINT64CONST(108064544195665338)},
+	{UINT64CONST(2142579373455052779), UINT64CONST(135080680244581673)}, {UINT64CONST(12868327154477877747), UINT64CONST(84425425152863545)},
+	{UINT64CONST(2250350887815183471), UINT64CONST(105531781441079432)}, {UINT64CONST(2812938609768979339), UINT64CONST(131914726801349290)},
+	{UINT64CONST(6369772649532999991), UINT64CONST(82446704250843306)}, {UINT64CONST(17185587848771025797), UINT64CONST(103058380313554132)},
+	{UINT64CONST(3035240737254230630), UINT64CONST(128822975391942666)}, {UINT64CONST(6508711479211282048), UINT64CONST(80514359619964166)},
+	{UINT64CONST(17359261385868878368), UINT64CONST(100642949524955207)}, {UINT64CONST(17087390713908710056), UINT64CONST(125803686906194009)},
+	{UINT64CONST(3762090168551861929), UINT64CONST(78627304316371256)}, {UINT64CONST(4702612710689827411), UINT64CONST(98284130395464070)},
+	{UINT64CONST(15101637925217060072), UINT64CONST(122855162994330087)}, {UINT64CONST(16356052730901744401), UINT64CONST(76784476871456304)},
+	{UINT64CONST(1998321839917628885), UINT64CONST(95980596089320381)}, {UINT64CONST(7109588318324424010), UINT64CONST(119975745111650476)},
+	{UINT64CONST(13666864735807540814), UINT64CONST(74984840694781547)}, {UINT64CONST(12471894901332038114), UINT64CONST(93731050868476934)},
+	{UINT64CONST(6366496589810271835), UINT64CONST(117163813585596168)}, {UINT64CONST(3979060368631419896), UINT64CONST(73227383490997605)},
+	{UINT64CONST(9585511479216662775), UINT64CONST(91534229363747006)}, {UINT64CONST(2758517312166052660), UINT64CONST(114417786704683758)},
+	{UINT64CONST(12671518677062341634), UINT64CONST(143022233380854697)}, {UINT64CONST(1002170145522881665), UINT64CONST(89388895863034186)},
+	{UINT64CONST(10476084718758377889), UINT64CONST(111736119828792732)}, {UINT64CONST(13095105898447972362), UINT64CONST(139670149785990915)},
+	{UINT64CONST(5878598177316288774), UINT64CONST(87293843616244322)}, {UINT64CONST(16571619758500136775), UINT64CONST(109117304520305402)},
+	{UINT64CONST(11491152661270395161), UINT64CONST(136396630650381753)}, {UINT64CONST(264441385652915120), UINT64CONST(85247894156488596)},
+	{UINT64CONST(330551732066143900), UINT64CONST(106559867695610745)}, {UINT64CONST(5024875683510067779), UINT64CONST(133199834619513431)},
+	{UINT64CONST(10058076329834874218), UINT64CONST(83249896637195894)}, {UINT64CONST(3349223375438816964), UINT64CONST(104062370796494868)},
+	{UINT64CONST(4186529219298521205), UINT64CONST(130077963495618585)}, {UINT64CONST(14145795808130045513), UINT64CONST(81298727184761615)},
+	{UINT64CONST(13070558741735168987), UINT64CONST(101623408980952019)}, {UINT64CONST(11726512408741573330), UINT64CONST(127029261226190024)},
+	{UINT64CONST(7329070255463483331), UINT64CONST(79393288266368765)}, {UINT64CONST(13773023837756742068), UINT64CONST(99241610332960956)},
+	{UINT64CONST(17216279797195927585), UINT64CONST(124052012916201195)}, {UINT64CONST(8454331864033760789), UINT64CONST(77532508072625747)},
+	{UINT64CONST(5956228811614813082), UINT64CONST(96915635090782184)}, {UINT64CONST(7445286014518516353), UINT64CONST(121144543863477730)},
+	{UINT64CONST(9264989777501460624), UINT64CONST(75715339914673581)}, {UINT64CONST(16192923240304213684), UINT64CONST(94644174893341976)},
+	{UINT64CONST(1794409976670715490), UINT64CONST(118305218616677471)}, {UINT64CONST(8039035263060279037), UINT64CONST(73940761635423419)},
+	{UINT64CONST(5437108060397960892), UINT64CONST(92425952044279274)}, {UINT64CONST(16019757112352226923), UINT64CONST(115532440055349092)},
+	{UINT64CONST(788976158365366019), UINT64CONST(72207775034593183)}, {UINT64CONST(14821278253238871236), UINT64CONST(90259718793241478)},
+	{UINT64CONST(9303225779693813237), UINT64CONST(112824648491551848)}, {UINT64CONST(11629032224617266546), UINT64CONST(141030810614439810)},
+	{UINT64CONST(11879831158813179495), UINT64CONST(88144256634024881)}, {UINT64CONST(1014730893234310657), UINT64CONST(110180320792531102)},
+	{UINT64CONST(10491785653397664129), UINT64CONST(137725400990663877)}, {UINT64CONST(8863209042587234033), UINT64CONST(86078375619164923)},
+	{UINT64CONST(6467325284806654637), UINT64CONST(107597969523956154)}, {UINT64CONST(17307528642863094104), UINT64CONST(134497461904945192)},
+	{UINT64CONST(10817205401789433815), UINT64CONST(84060913690590745)}, {UINT64CONST(18133192770664180173), UINT64CONST(105076142113238431)},
+	{UINT64CONST(18054804944902837312), UINT64CONST(131345177641548039)}, {UINT64CONST(18201782118205355176), UINT64CONST(82090736025967524)},
+	{UINT64CONST(4305483574047142354), UINT64CONST(102613420032459406)}, {UINT64CONST(14605226504413703751), UINT64CONST(128266775040574257)},
+	{UINT64CONST(2210737537617482988), UINT64CONST(80166734400358911)}, {UINT64CONST(16598479977304017447), UINT64CONST(100208418000448638)},
+	{UINT64CONST(11524727934775246001), UINT64CONST(125260522500560798)}, {UINT64CONST(2591268940807140847), UINT64CONST(78287826562850499)},
+	{UINT64CONST(17074144231291089770), UINT64CONST(97859783203563123)}, {UINT64CONST(16730994270686474309), UINT64CONST(122324729004453904)},
+	{UINT64CONST(10456871419179046443), UINT64CONST(76452955627783690)}, {UINT64CONST(3847717237119032246), UINT64CONST(95566194534729613)},
+	{UINT64CONST(9421332564826178211), UINT64CONST(119457743168412016)}, {UINT64CONST(5888332853016361382), UINT64CONST(74661089480257510)},
+	{UINT64CONST(16583788103125227536), UINT64CONST(93326361850321887)}, {UINT64CONST(16118049110479146516), UINT64CONST(116657952312902359)},
+	{UINT64CONST(16991309721690548428), UINT64CONST(72911220195563974)}, {UINT64CONST(12015765115258409727), UINT64CONST(91139025244454968)},
+	{UINT64CONST(15019706394073012159), UINT64CONST(113923781555568710)}, {UINT64CONST(9551260955736489391), UINT64CONST(142404726944460888)},
+	{UINT64CONST(5969538097335305869), UINT64CONST(89002954340288055)}, {UINT64CONST(2850236603241744433), UINT64CONST(111253692925360069)}
+};
+
+#endif							/* RYU_D2S_FULL_TABLE_H */
diff --git a/src/common/d2s_intrinsics.h b/src/common/d2s_intrinsics.h
new file mode 100644
index 0000000000..248889e649
--- /dev/null
+++ b/src/common/d2s_intrinsics.h
@@ -0,0 +1,202 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for double precision.
+ *
+ * Portions Copyright (c) 2018-2019, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/common/d2s_intrinsics.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ *     (See accompanying file LICENSE-Apache or copy at
+ *      http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ *     (See accompanying file LICENSE-Boost or copy at
+ *      https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+#ifndef RYU_D2S_INTRINSICS_H
+#define RYU_D2S_INTRINSICS_H
+
+#if defined(HAS_64_BIT_INTRINSICS)
+
+#include <intrin.h>
+
+static inline uint64
+umul128(const uint64 a, const uint64 b, uint64 *const productHi)
+{
+	return _umul128(a, b, productHi);
+}
+
+static inline uint64
+shiftright128(const uint64 lo, const uint64 hi, const uint32 dist)
+{
+	/*
+	 * For the __shiftright128 intrinsic, the shift value is always modulo 64.
+	 * In the current implementation of the double-precision version of Ryu,
+	 * the shift value is always < 64. (In the case RYU_OPTIMIZE_SIZE == 0,
+	 * the shift value is in the range [49, 58]. Otherwise in the range [2,
+	 * 59].) Check this here in case a future change requires larger shift
+	 * values. In this case this function needs to be adjusted.
+	 */
+	Assert(dist < 64);
+	return __shiftright128(lo, hi, (unsigned char) dist);
+}
+
+#else							/* defined(HAS_64_BIT_INTRINSICS) */
+
+static inline uint64
+umul128(const uint64 a, const uint64 b, uint64 *const productHi)
+{
+	/*
+	 * The casts here help MSVC to avoid calls to the __allmul library
+	 * function.
+	 */
+	const uint32 aLo = (uint32) a;
+	const uint32 aHi = (uint32) (a >> 32);
+	const uint32 bLo = (uint32) b;
+	const uint32 bHi = (uint32) (b >> 32);
+
+	const uint64 b00 = (uint64) aLo * bLo;
+	const uint64 b01 = (uint64) aLo * bHi;
+	const uint64 b10 = (uint64) aHi * bLo;
+	const uint64 b11 = (uint64) aHi * bHi;
+
+	const uint32 b00Lo = (uint32) b00;
+	const uint32 b00Hi = (uint32) (b00 >> 32);
+
+	const uint64 mid1 = b10 + b00Hi;
+	const uint32 mid1Lo = (uint32) (mid1);
+	const uint32 mid1Hi = (uint32) (mid1 >> 32);
+
+	const uint64 mid2 = b01 + mid1Lo;
+	const uint32 mid2Lo = (uint32) (mid2);
+	const uint32 mid2Hi = (uint32) (mid2 >> 32);
+
+	const uint64 pHi = b11 + mid1Hi + mid2Hi;
+	const uint64 pLo = ((uint64) mid2Lo << 32) + b00Lo;
+
+	*productHi = pHi;
+	return pLo;
+}
+
+static inline uint64
+shiftright128(const uint64 lo, const uint64 hi, const uint32 dist)
+{
+	/* We don't need to handle the case dist >= 64 here (see above). */
+	Assert(dist < 64);
+#if !defined(RYU_32_BIT_PLATFORM)
+	Assert(dist > 0);
+	return (hi << (64 - dist)) | (lo >> dist);
+#else
+	/* Avoid a 64-bit shift by taking advantage of the range of shift values. */
+	Assert(dist >= 32);
+	return (hi << (64 - dist)) | ((uint32) (lo >> 32) >> (dist - 32));
+#endif
+}
+
+#endif							/* // defined(HAS_64_BIT_INTRINSICS) */
+
+#ifdef RYU_32_BIT_PLATFORM
+
+/*  Returns the high 64 bits of the 128-bit product of a and b. */
+static inline uint64
+umulh(const uint64 a, const uint64 b)
+{
+	/*
+	 * Reuse the umul128 implementation. Optimizers will likely eliminate the
+	 * instructions used to compute the low part of the product.
+	 */
+	uint64		hi;
+
+	umul128(a, b, &hi);
+	return hi;
+}
+
+/*----
+ *  On 32-bit platforms, compilers typically generate calls to library
+ *  functions for 64-bit divisions, even if the divisor is a constant.
+ *
+ *  E.g.:
+ *  https://bugs.llvm.org/show_bug.cgi?id=37932
+ *  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17958
+ *  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37443
+ *
+ *  The functions here perform division-by-constant using multiplications
+ *  in the same way as 64-bit compilers would do.
+ *
+ *  NB:
+ *  The multipliers and shift values are the ones generated by clang x64
+ *  for expressions like x/5, x/10, etc.
+ *----
+ */
+
+static inline uint64
+div5(const uint64 x)
+{
+	return umulh(x, UINT64CONST(0xCCCCCCCCCCCCCCCD)) >> 2;
+}
+
+static inline uint64
+div10(const uint64 x)
+{
+	return umulh(x, UINT64CONST(0xCCCCCCCCCCCCCCCD)) >> 3;
+}
+
+static inline uint64
+div100(const uint64 x)
+{
+	return umulh(x >> 2, UINT64CONST(0x28F5C28F5C28F5C3)) >> 2;
+}
+
+static inline uint64
+div1e8(const uint64 x)
+{
+	return umulh(x, UINT64CONST(0xABCC77118461CEFD)) >> 26;
+}
+
+#else							/* RYU_32_BIT_PLATFORM */
+
+static inline uint64
+div5(const uint64 x)
+{
+	return x / 5;
+}
+
+static inline uint64
+div10(const uint64 x)
+{
+	return x / 10;
+}
+
+static inline uint64
+div100(const uint64 x)
+{
+	return x / 100;
+}
+
+static inline uint64
+div1e8(const uint64 x)
+{
+	return x / 100000000;
+}
+
+#endif							/* RYU_32_BIT_PLATFORM */
+
+#endif							/* RYU_D2S_INTRINSICS_H */
diff --git a/src/common/digit_table.h b/src/common/digit_table.h
new file mode 100644
index 0000000000..483aa17142
--- /dev/null
+++ b/src/common/digit_table.h
@@ -0,0 +1,21 @@
+#ifndef RYU_DIGIT_TABLE_H
+#define RYU_DIGIT_TABLE_H
+
+/*
+ * A table of all two-digit numbers. This is used to speed up decimal digit
+ * generation by copying pairs of digits into the final output.
+ */
+static const char DIGIT_TABLE[200] = {
+	'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
+	'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
+	'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
+	'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
+	'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
+	'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
+	'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
+	'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
+	'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
+	'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
+};
+
+#endif							/* RYU_DIGIT_TABLE_H */
diff --git a/src/common/f2s.c b/src/common/f2s.c
new file mode 100644
index 0000000000..59fc5267a0
--- /dev/null
+++ b/src/common/f2s.c
@@ -0,0 +1,768 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for single precision.
+ *
+ * Portions Copyright (c) 2018-2019, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/common/f2s.c
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ *     (See accompanying file LICENSE-Apache or copy at
+ *      http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ *     (See accompanying file LICENSE-Boost or copy at
+ *      https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/shortest_dec.h"
+
+#include "ryu_common.h"
+#include "digit_table.h"
+
+#define FLOAT_MANTISSA_BITS 23
+#define FLOAT_EXPONENT_BITS 8
+#define FLOAT_BIAS 127
+
+/*
+ * This table is generated (by the upstream) by PrintFloatLookupTable,
+ * and modified (by us) to add UINT64CONST.
+ */
+#define FLOAT_POW5_INV_BITCOUNT 59
+static const uint64 FLOAT_POW5_INV_SPLIT[31] = {
+	UINT64CONST(576460752303423489), UINT64CONST(461168601842738791), UINT64CONST(368934881474191033), UINT64CONST(295147905179352826),
+	UINT64CONST(472236648286964522), UINT64CONST(377789318629571618), UINT64CONST(302231454903657294), UINT64CONST(483570327845851670),
+	UINT64CONST(386856262276681336), UINT64CONST(309485009821345069), UINT64CONST(495176015714152110), UINT64CONST(396140812571321688),
+	UINT64CONST(316912650057057351), UINT64CONST(507060240091291761), UINT64CONST(405648192073033409), UINT64CONST(324518553658426727),
+	UINT64CONST(519229685853482763), UINT64CONST(415383748682786211), UINT64CONST(332306998946228969), UINT64CONST(531691198313966350),
+	UINT64CONST(425352958651173080), UINT64CONST(340282366920938464), UINT64CONST(544451787073501542), UINT64CONST(435561429658801234),
+	UINT64CONST(348449143727040987), UINT64CONST(557518629963265579), UINT64CONST(446014903970612463), UINT64CONST(356811923176489971),
+	UINT64CONST(570899077082383953), UINT64CONST(456719261665907162), UINT64CONST(365375409332725730)
+};
+#define FLOAT_POW5_BITCOUNT 61
+static const uint64 FLOAT_POW5_SPLIT[47] = {
+	UINT64CONST(1152921504606846976), UINT64CONST(1441151880758558720), UINT64CONST(1801439850948198400), UINT64CONST(2251799813685248000),
+	UINT64CONST(1407374883553280000), UINT64CONST(1759218604441600000), UINT64CONST(2199023255552000000), UINT64CONST(1374389534720000000),
+	UINT64CONST(1717986918400000000), UINT64CONST(2147483648000000000), UINT64CONST(1342177280000000000), UINT64CONST(1677721600000000000),
+	UINT64CONST(2097152000000000000), UINT64CONST(1310720000000000000), UINT64CONST(1638400000000000000), UINT64CONST(2048000000000000000),
+	UINT64CONST(1280000000000000000), UINT64CONST(1600000000000000000), UINT64CONST(2000000000000000000), UINT64CONST(1250000000000000000),
+	UINT64CONST(1562500000000000000), UINT64CONST(1953125000000000000), UINT64CONST(1220703125000000000), UINT64CONST(1525878906250000000),
+	UINT64CONST(1907348632812500000), UINT64CONST(1192092895507812500), UINT64CONST(1490116119384765625), UINT64CONST(1862645149230957031),
+	UINT64CONST(1164153218269348144), UINT64CONST(1455191522836685180), UINT64CONST(1818989403545856475), UINT64CONST(2273736754432320594),
+	UINT64CONST(1421085471520200371), UINT64CONST(1776356839400250464), UINT64CONST(2220446049250313080), UINT64CONST(1387778780781445675),
+	UINT64CONST(1734723475976807094), UINT64CONST(2168404344971008868), UINT64CONST(1355252715606880542), UINT64CONST(1694065894508600678),
+	UINT64CONST(2117582368135750847), UINT64CONST(1323488980084844279), UINT64CONST(1654361225106055349), UINT64CONST(2067951531382569187),
+	UINT64CONST(1292469707114105741), UINT64CONST(1615587133892632177), UINT64CONST(2019483917365790221)
+};
+
+static inline uint32
+pow5Factor(uint32 value)
+{
+	uint32		count = 0;
+
+	for (;;)
+	{
+		Assert(value != 0);
+		const uint32 q = value / 5;
+		const uint32 r = value % 5;
+
+		if (r != 0)
+			break;
+
+		value = q;
+		++count;
+	}
+	return count;
+}
+
+/*  Returns true if value is divisible by 5^p. */
+static inline bool
+multipleOfPowerOf5(const uint32 value, const uint32 p)
+{
+	return pow5Factor(value) >= p;
+}
+
+/*  Returns true if value is divisible by 2^p. */
+static inline bool
+multipleOfPowerOf2(const uint32 value, const uint32 p)
+{
+	/* return __builtin_ctz(value) >= p; */
+	return (value & ((1u << p) - 1)) == 0;
+}
+
+/*
+ * It seems to be slightly faster to avoid uint128_t here, although the
+ * generated code for uint128_t looks slightly nicer.
+ */
+static inline uint32
+mulShift(const uint32 m, const uint64 factor, const int32 shift)
+{
+	/*
+	 * The casts here help MSVC to avoid calls to the __allmul library
+	 * function.
+	 */
+	const uint32 factorLo = (uint32) (factor);
+	const uint32 factorHi = (uint32) (factor >> 32);
+	const uint64 bits0 = (uint64) m * factorLo;
+	const uint64 bits1 = (uint64) m * factorHi;
+
+	Assert(shift > 32);
+
+#ifdef RYU_32_BIT_PLATFORM
+
+	/*
+	 * On 32-bit platforms we can avoid a 64-bit shift-right since we only
+	 * need the upper 32 bits of the result and the shift value is > 32.
+	 */
+	const uint32 bits0Hi = (uint32) (bits0 >> 32);
+	uint32		bits1Lo = (uint32) (bits1);
+	uint32		bits1Hi = (uint32) (bits1 >> 32);
+
+	bits1Lo += bits0Hi;
+	bits1Hi += (bits1Lo < bits0Hi);
+
+	const int32 s = shift - 32;
+
+	return (bits1Hi << (32 - s)) | (bits1Lo >> s);
+
+#else							/* RYU_32_BIT_PLATFORM */
+
+	const uint64 sum = (bits0 >> 32) + bits1;
+	const uint64 shiftedSum = sum >> (shift - 32);
+
+	Assert(shiftedSum <= UINT32_MAX);
+	return (uint32) shiftedSum;
+
+#endif							/* RYU_32_BIT_PLATFORM */
+}
+
+static inline uint32
+mulPow5InvDivPow2(const uint32 m, const uint32 q, const int32 j)
+{
+	return mulShift(m, FLOAT_POW5_INV_SPLIT[q], j);
+}
+
+static inline uint32
+mulPow5divPow2(const uint32 m, const uint32 i, const int32 j)
+{
+	return mulShift(m, FLOAT_POW5_SPLIT[i], j);
+}
+
+static inline uint32
+decimalLength(const uint32 v)
+{
+	/* Function precondition: v is not a 10-digit number. */
+	/* (9 digits are sufficient for round-tripping.) */
+	Assert(v < 1000000000);
+	if (v >= 100000000)
+	{
+		return 9;
+	}
+	if (v >= 10000000)
+	{
+		return 8;
+	}
+	if (v >= 1000000)
+	{
+		return 7;
+	}
+	if (v >= 100000)
+	{
+		return 6;
+	}
+	if (v >= 10000)
+	{
+		return 5;
+	}
+	if (v >= 1000)
+	{
+		return 4;
+	}
+	if (v >= 100)
+	{
+		return 3;
+	}
+	if (v >= 10)
+	{
+		return 2;
+	}
+	return 1;
+}
+
+/*  A floating decimal representing m * 10^e. */
+typedef struct floating_decimal_32
+{
+	uint32		mantissa;
+	int32		exponent;
+} floating_decimal_32;
+
+static inline floating_decimal_32
+f2d(const uint32 ieeeMantissa, const uint32 ieeeExponent)
+{
+	int32		e2;
+	uint32		m2;
+
+	if (ieeeExponent == 0)
+	{
+		/* We subtract 2 so that the bounds computation has 2 additional bits. */
+		e2 = 1 - FLOAT_BIAS - FLOAT_MANTISSA_BITS - 2;
+		m2 = ieeeMantissa;
+	}
+	else
+	{
+		e2 = ieeeExponent - FLOAT_BIAS - FLOAT_MANTISSA_BITS - 2;
+		m2 = (1u << FLOAT_MANTISSA_BITS) | ieeeMantissa;
+	}
+
+#if STRICTLY_SHORTEST
+	const bool	even = (m2 & 1) == 0;
+	const bool	acceptBounds = even;
+#else
+	const bool	acceptBounds = false;
+#endif
+
+	/* Step 2: Determine the interval of legal decimal representations. */
+	const uint32 mv = 4 * m2;
+	const uint32 mp = 4 * m2 + 2;
+
+	/* Implicit bool -> int conversion. True is 1, false is 0. */
+	const uint32 mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
+	const uint32 mm = 4 * m2 - 1 - mmShift;
+
+	/* Step 3: Convert to a decimal power base using 64-bit arithmetic. */
+	uint32		vr,
+				vp,
+				vm;
+	int32		e10;
+	bool		vmIsTrailingZeros = false;
+	bool		vrIsTrailingZeros = false;
+	uint8		lastRemovedDigit = 0;
+
+	if (e2 >= 0)
+	{
+		const uint32 q = log10Pow2(e2);
+
+		e10 = q;
+
+		const int32 k = FLOAT_POW5_INV_BITCOUNT + pow5bits(q) - 1;
+		const int32 i = -e2 + q + k;
+
+		vr = mulPow5InvDivPow2(mv, q, i);
+		vp = mulPow5InvDivPow2(mp, q, i);
+		vm = mulPow5InvDivPow2(mm, q, i);
+
+		if (q != 0 && (vp - 1) / 10 <= vm / 10)
+		{
+			/*
+			 * We need to know one removed digit even if we are not going to
+			 * loop below. We could use q = X - 1 above, except that would
+			 * require 33 bits for the result, and we've found that 32-bit
+			 * arithmetic is faster even on 64-bit machines.
+			 */
+			const int32 l = FLOAT_POW5_INV_BITCOUNT + pow5bits(q - 1) - 1;
+
+			lastRemovedDigit = (uint8) (mulPow5InvDivPow2(mv, q - 1, -e2 + q - 1 + l) % 10);
+		}
+		if (q <= 9)
+		{
+			/*
+			 * The largest power of 5 that fits in 24 bits is 5^10, but q <= 9
+			 * seems to be safe as well.
+			 *
+			 * Only one of mp, mv, and mm can be a multiple of 5, if any.
+			 */
+			if (mv % 5 == 0)
+			{
+				vrIsTrailingZeros = multipleOfPowerOf5(mv, q);
+			}
+			else if (acceptBounds)
+			{
+				vmIsTrailingZeros = multipleOfPowerOf5(mm, q);
+			}
+			else
+			{
+				vp -= multipleOfPowerOf5(mp, q);
+			}
+		}
+	}
+	else
+	{
+		const uint32 q = log10Pow5(-e2);
+
+		e10 = q + e2;
+
+		const int32 i = -e2 - q;
+		const int32 k = pow5bits(i) - FLOAT_POW5_BITCOUNT;
+		int32		j = q - k;
+
+		vr = mulPow5divPow2(mv, i, j);
+		vp = mulPow5divPow2(mp, i, j);
+		vm = mulPow5divPow2(mm, i, j);
+
+		if (q != 0 && (vp - 1) / 10 <= vm / 10)
+		{
+			j = q - 1 - (pow5bits(i + 1) - FLOAT_POW5_BITCOUNT);
+			lastRemovedDigit = (uint8) (mulPow5divPow2(mv, i + 1, j) % 10);
+		}
+		if (q <= 1)
+		{
+			/*
+			 * {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q
+			 * trailing 0 bits.
+			 */
+			/* mv = 4 * m2, so it always has at least two trailing 0 bits. */
+			vrIsTrailingZeros = true;
+			if (acceptBounds)
+			{
+				/*
+				 * mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff
+				 * mmShift == 1.
+				 */
+				vmIsTrailingZeros = mmShift == 1;
+			}
+			else
+			{
+				/*
+				 * mp = mv + 2, so it always has at least one trailing 0 bit.
+				 */
+				--vp;
+			}
+		}
+		else if (q < 31)
+		{
+			/* TODO(ulfjack):Use a tighter bound here. */
+			vrIsTrailingZeros = multipleOfPowerOf2(mv, q - 1);
+		}
+	}
+
+	/*
+	 * Step 4: Find the shortest decimal representation in the interval of
+	 * legal representations.
+	 */
+	uint32		removed = 0;
+	uint32		output;
+
+	if (vmIsTrailingZeros || vrIsTrailingZeros)
+	{
+		/* General case, which happens rarely (~4.0%). */
+		while (vp / 10 > vm / 10)
+		{
+			vmIsTrailingZeros &= vm - (vm / 10) * 10 == 0;
+			vrIsTrailingZeros &= lastRemovedDigit == 0;
+			lastRemovedDigit = (uint8) (vr % 10);
+			vr /= 10;
+			vp /= 10;
+			vm /= 10;
+			++removed;
+		}
+		if (vmIsTrailingZeros)
+		{
+			while (vm % 10 == 0)
+			{
+				vrIsTrailingZeros &= lastRemovedDigit == 0;
+				lastRemovedDigit = (uint8) (vr % 10);
+				vr /= 10;
+				vp /= 10;
+				vm /= 10;
+				++removed;
+			}
+		}
+
+		if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0)
+		{
+			/* Round even if the exact number is .....50..0. */
+			lastRemovedDigit = 4;
+		}
+
+		/*
+		 * We need to take vr + 1 if vr is outside bounds or we need to round
+		 * up.
+		 */
+		output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
+	}
+	else
+	{
+		/*
+		 * Specialized for the common case (~96.0%). Percentages below are
+		 * relative to this.
+		 *
+		 * Loop iterations below (approximately): 0: 13.6%, 1: 70.7%, 2:
+		 * 14.1%, 3: 1.39%, 4: 0.14%, 5+: 0.01%
+		 */
+		while (vp / 10 > vm / 10)
+		{
+			lastRemovedDigit = (uint8) (vr % 10);
+			vr /= 10;
+			vp /= 10;
+			vm /= 10;
+			++removed;
+		}
+
+		/*
+		 * We need to take vr + 1 if vr is outside bounds or we need to round
+		 * up.
+		 */
+		output = vr + (vr == vm || lastRemovedDigit >= 5);
+	}
+
+	const int32 exp = e10 + removed;
+
+	floating_decimal_32 fd;
+
+	fd.exponent = exp;
+	fd.mantissa = output;
+	return fd;
+}
+
+static inline int
+to_chars_f(const floating_decimal_32 v, const uint32 olength, char *const result)
+{
+	/* Step 5: Print the decimal representation. */
+	int			index = 0;
+
+	uint32		output = v.mantissa;
+	int32		exp = v.exponent;
+
+	/*----
+	 *
+	 * On entry, mantissa * 10^exp is the result to be output.
+	 * Caller has already done the - sign if needed.
+	 *
+	 * We want to insert the point somewhere else, which might mean
+	 * adding zeros:
+	 *
+	 *            exp  | format
+	 *            1+   |  ddddddddd000000
+	 *            0    |  ddddddddd
+	 *  -1 .. -len+1   |  dddddddd.d to d.ddddddddd
+	 *  -len ...       |  0.ddddddddd to 0.0000dddddd
+	 */
+	uint32		i = 0;
+	int32		nexp = exp + olength;
+
+	if (nexp <= 0)
+	{
+		/* 0.0000ddddd */
+		index = 2 - nexp;
+		/* won't need more than this many 0s */
+		memcpy(result, "0.000000", 8);
+	}
+	else if (exp < 0)
+	{
+		/*
+		 * dddd.dddd; leave space at the start and move the '.' in after
+		 */
+		index = 1;
+	}
+
+	while (output >= 10000)
+	{
+		const uint32 c = output - 10000 * (output / 10000);
+		const uint32 c0 = (c % 100) << 1;
+		const uint32 c1 = (c / 100) << 1;
+
+		output /= 10000;
+
+		memcpy(result + index + olength - i - 2, DIGIT_TABLE + c0, 2);
+		memcpy(result + index + olength - i - 4, DIGIT_TABLE + c1, 2);
+		i += 4;
+	}
+	if (output >= 100)
+	{
+		const uint32 c = (output % 100) << 1;
+
+		output /= 100;
+		memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+		i += 2;
+	}
+	if (output >= 10)
+	{
+		const uint32 c = output << 1;
+
+		memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+	}
+	else
+	{
+		result[index] = (char) ('0' + output);
+	}
+
+	if (index == 1)
+	{
+		/* nexp is 1..8 */
+		/* gcc only seems to want to optimize memmove for small 2^n */
+		if (nexp >= 8)
+		{
+			memmove(result, result + 1, 8);
+		}
+		else
+		{
+			if (nexp & 4)
+			{
+				memmove(result + index - 1, result + index, 4);
+				index += 4;
+			}
+			if (nexp & 2)
+			{
+				memmove(result + index - 1, result + index, 2);
+				index += 2;
+			}
+			if (nexp & 1)
+			{
+				result[index - 1] = result[index];
+			}
+		}
+		result[nexp] = '.';
+		index = olength + 1;
+	}
+	else if (exp >= 0)
+	{
+		if (exp > 0)
+			memset(result + olength, '0', exp);
+		index = olength + exp;
+	}
+	else
+	{
+		index = olength + (2 - nexp);
+	}
+
+	return index;
+}
+
+static inline int
+to_chars(const floating_decimal_32 v, const bool sign, char *const result)
+{
+	/* Step 5: Print the decimal representation. */
+	int			index = 0;
+
+	uint32		output = v.mantissa;
+	uint32		olength = decimalLength(output);
+	int32		exp = v.exponent + olength - 1;
+
+	if (sign)
+		result[index++] = '-';
+
+	if (exp >= -4 && exp < 6)
+		return to_chars_f(v, olength, result + index) + sign;
+
+	/*
+	 * If v.exponent is exactly 0, we might have reached here via the small
+	 * integer fast path, in which case v.mantissa might contain trailing
+	 * (decimal) zeros. For scientific notation we need to move these zeros
+	 * into the exponent. (For fixed point this doesn't matter, which is why
+	 * we do this here rather than above.)
+	 *
+	 * Since we already calculated the display exponent (exp) above based on
+	 * the old decimal length, that value does not change here. Instead, we
+	 * just reduce the display length for each digit removed.
+	 *
+	 * If we didn't get here via the fast path, the raw exponent will not
+	 * usually be 0, and there will be no trailing zeros, so we pay no more
+	 * than one div10/multiply extra cost. We claw back half of that by
+	 * checking for divisibility by 2 before dividing by 10.
+	 */
+	if (v.exponent == 0)
+	{
+		while ((output & 1) == 0)
+		{
+			const uint32 q = output / 10;
+			const uint32 r = output - 10 * q;
+
+			if (r != 0)
+				break;
+			output = q;
+			--olength;
+		}
+	}
+
+	/*----
+	 * Print the decimal digits.
+	 * The following code is equivalent to:
+	 *
+	 * for (uint32 i = 0; i < olength - 1; ++i) {
+	 *   const uint32 c = output % 10; output /= 10;
+	 *   result[index + olength - i] = (char) ('0' + c);
+	 * }
+	 * result[index] = '0' + output % 10;
+	 */
+	uint32		i = 0;
+
+	while (output >= 10000)
+	{
+		const uint32 c = output - 10000 * (output / 10000);
+		const uint32 c0 = (c % 100) << 1;
+		const uint32 c1 = (c / 100) << 1;
+
+		output /= 10000;
+
+		memcpy(result + index + olength - i - 1, DIGIT_TABLE + c0, 2);
+		memcpy(result + index + olength - i - 3, DIGIT_TABLE + c1, 2);
+		i += 4;
+	}
+	if (output >= 100)
+	{
+		const uint32 c = (output % 100) << 1;
+
+		output /= 100;
+		memcpy(result + index + olength - i - 1, DIGIT_TABLE + c, 2);
+		i += 2;
+	}
+	if (output >= 10)
+	{
+		const uint32 c = output << 1;
+
+		/*
+		 * We can't use memcpy here: the decimal dot goes between these two
+		 * digits.
+		 */
+		result[index + olength - i] = DIGIT_TABLE[c + 1];
+		result[index] = DIGIT_TABLE[c];
+	}
+	else
+	{
+		result[index] = (char) ('0' + output);
+	}
+
+	/* Print decimal point if needed. */
+	if (olength > 1)
+	{
+		result[index + 1] = '.';
+		index += olength + 1;
+	}
+	else
+	{
+		++index;
+	}
+
+	/* Print the exponent. */
+	result[index++] = 'e';
+	if (exp < 0)
+	{
+		result[index++] = '-';
+		exp = -exp;
+	}
+	else
+		result[index++] = '+';
+
+	memcpy(result + index, DIGIT_TABLE + 2 * exp, 2);
+	index += 2;
+
+	return index;
+}
+
+static inline bool
+f2d_small_int(const uint32 ieeeMantissa,
+			  const uint32 ieeeExponent,
+			  floating_decimal_32 *v)
+{
+	const int32 e2 = (int32) ieeeExponent - FLOAT_BIAS - FLOAT_MANTISSA_BITS;
+
+	/*
+	 * Avoid using multiple "return false;" here since it tends to provoke the
+	 * compiler into inlining multiple copies of f2s, which is undesirable.
+	 */
+
+	if (e2 >= -FLOAT_MANTISSA_BITS && e2 <= 0)
+	{
+		/*----
+		 * Since 2^23 <= m2 < 2^24 and 0 <= -e2 <= 23:
+		 *   1 <= f = m2 / 2^-e2 < 2^24.
+		 *
+		 * Test if the lower -e2 bits of the significand are 0, i.e. whether
+		 * the fraction is 0. We can use ieeeMantissa here, since the implied
+		 * 1 bit can never be tested by this; the implied 1 can only be part
+		 * of a fraction if e2 < -FLOAT_MANTISSA_BITS which we already
+		 * checked. (e.g. 0.5 gives ieeeMantissa == 0 and e2 == -24)
+		 */
+		const uint32 mask = (1U << -e2) - 1;
+		const uint32 fraction = ieeeMantissa & mask;
+
+		if (fraction == 0)
+		{
+			/*----
+			 * f is an integer in the range [1, 2^24).
+			 * Note: mantissa might contain trailing (decimal) 0's.
+			 * Note: since 2^24 < 10^9, there is no need to adjust
+			 * decimalLength().
+			 */
+			const uint32 m2 = (1U << FLOAT_MANTISSA_BITS) | ieeeMantissa;
+
+			v->mantissa = m2 >> -e2;
+			v->exponent = 0;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+int
+float_to_shortest_decimal_bufn(float f, char *result)
+{
+	/*
+	 * Step 1: Decode the floating-point number, and unify normalized and
+	 * subnormal cases.
+	 */
+	const uint32 bits = float_to_bits(f);
+
+	/* Decode bits into sign, mantissa, and exponent. */
+	const bool	ieeeSign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
+	const uint32 ieeeMantissa = bits & ((1u << FLOAT_MANTISSA_BITS) - 1);
+	const uint32 ieeeExponent = (bits >> FLOAT_MANTISSA_BITS) & ((1u << FLOAT_EXPONENT_BITS) - 1);
+
+	/* Case distinction; exit early for the easy cases. */
+	if (ieeeExponent == ((1u << FLOAT_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0))
+	{
+		return copy_special_str(result, ieeeSign, ieeeExponent, ieeeMantissa);
+	}
+
+	floating_decimal_32 v;
+	const bool	isSmallInt = f2d_small_int(ieeeMantissa, ieeeExponent, &v);
+
+	if (!isSmallInt)
+	{
+		v = f2d(ieeeMantissa, ieeeExponent);
+	}
+
+	return to_chars(v, ieeeSign, result);
+}
+
+void
+float_to_shortest_decimal_buf(float f, char *result)
+{
+	const int	index = float_to_shortest_decimal_bufn(f, result);
+
+	/* Terminate the string. */
+	result[index] = '\0';
+}
+
+char *
+float_to_shortest_decimal(float f)
+{
+	char	   *const result = (char *) palloc(16);
+
+	float_to_shortest_decimal_buf(f, result);
+	return result;
+}
diff --git a/src/common/ryu_common.h b/src/common/ryu_common.h
new file mode 100644
index 0000000000..14639aff9c
--- /dev/null
+++ b/src/common/ryu_common.h
@@ -0,0 +1,133 @@
+/*---------------------------------------------------------------------------
+ *
+ * Common routines for Ryu floating-point output.
+ *
+ * Portions Copyright (c) 2018-2019, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/common/ryu_common.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ *     (See accompanying file LICENSE-Apache or copy at
+ *      http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ *     (See accompanying file LICENSE-Boost or copy at
+ *      https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+#ifndef RYU_COMMON_H
+#define RYU_COMMON_H
+
+/*
+ * Upstream Ryu's output is always the shortest possible. But we adjust that
+ * slightly to improve portability: we avoid outputting the exact midpoint
+ * value between two representable floats, since that relies on the reader
+ * getting the round-to-even rule correct, which seems to be the common
+ * failure mode.
+ *
+ * Defining this to 1 would restore the upstream behavior.
+ */
+#define STRICTLY_SHORTEST 0
+
+#if SIZEOF_SIZE_T < 8
+#define RYU_32_BIT_PLATFORM
+#endif
+
+/*  Returns e == 0 ? 1 : ceil(log_2(5^e)). */
+static inline uint32
+pow5bits(const int32 e)
+{
+	/*
+	 * This approximation works up to the point that the multiplication
+	 * overflows at e = 3529.
+	 *
+	 * If the multiplication were done in 64 bits, it would fail at 5^4004
+	 * which is just greater than 2^9297.
+	 */
+	Assert(e >= 0);
+	Assert(e <= 3528);
+	return ((((uint32) e) * 1217359) >> 19) + 1;
+}
+
+/*  Returns floor(log_10(2^e)). */
+static inline int32
+log10Pow2(const int32 e)
+{
+	/*
+	 * The first value this approximation fails for is 2^1651 which is just
+	 * greater than 10^297.
+	 */
+	Assert(e >= 0);
+	Assert(e <= 1650);
+	return (int32) ((((uint32) e) * 78913) >> 18);
+}
+
+/*  Returns floor(log_10(5^e)). */
+static inline int32
+log10Pow5(const int32 e)
+{
+	/*
+	 * The first value this approximation fails for is 5^2621 which is just
+	 * greater than 10^1832.
+	 */
+	Assert(e >= 0);
+	Assert(e <= 2620);
+	return (int32) ((((uint32) e) * 732923) >> 20);
+}
+
+static inline int
+copy_special_str(char *const result, const bool sign, const bool exponent, const bool mantissa)
+{
+	if (mantissa)
+	{
+		memcpy(result, "NaN", 3);
+		return 3;
+	}
+	if (sign)
+	{
+		result[0] = '-';
+	}
+	if (exponent)
+	{
+		memcpy(result + sign, "Infinity", 8);
+		return sign + 8;
+	}
+	result[sign] = '0';
+	return sign + 1;
+}
+
+static inline uint32
+float_to_bits(const float f)
+{
+	uint32		bits = 0;
+
+	memcpy(&bits, &f, sizeof(float));
+	return bits;
+}
+
+static inline uint64
+double_to_bits(const double d)
+{
+	uint64		bits = 0;
+
+	memcpy(&bits, &d, sizeof(double));
+	return bits;
+}
+
+#endif							/* RYU_COMMON_H */
diff --git a/src/include/common/shortest_dec.h b/src/include/common/shortest_dec.h
new file mode 100644
index 0000000000..5e881c982f
--- /dev/null
+++ b/src/include/common/shortest_dec.h
@@ -0,0 +1,45 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output.
+ *
+ * Portions Copyright (c) 2018-2019, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/include/common/shortest_dec.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ *     (See accompanying file LICENSE-Apache or copy at
+ *      http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ *     (See accompanying file LICENSE-Boost or copy at
+ *      https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+#ifndef SHORTEST_DEC_H
+#define SHORTEST_DEC_H
+
+int			double_to_shortest_decimal_bufn(double f, char *result);
+void		double_to_shortest_decimal_buf(double f, char *result);
+char	   *double_to_shortest_decimal(double f);
+
+int			float_to_shortest_decimal_bufn(float f, char *result);
+void		float_to_shortest_decimal_buf(float f, char *result);
+char	   *float_to_shortest_decimal(float f);
+
+#endif							/* SHORTEST_DEC_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 82547f321f..b38b0ae189 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -555,6 +555,9 @@
 /* Define to 1 if you have the `strsignal' function. */
 #undef HAVE_STRSIGNAL
 
+/* Define to 1 if you have the `strtof' function. */
+#undef HAVE_STRTOF
+
 /* Define to 1 if you have the `strtoll' function. */
 #undef HAVE_STRTOLL
 
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index a3c44f0fd8..160fa1279e 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -139,6 +139,9 @@
    don't. */
 #define HAVE_DECL_STRNLEN 1
 
+/* Define to 1 if you have the `strtof' function. */
+#define HAVE_STRTOF 1
+
 /* Define to 1 if you have the declaration of `strtoll', and to 0 if you
    don't. */
 #define HAVE_DECL_STRTOLL 1
diff --git a/src/include/port.h b/src/include/port.h
index 485e771f99..436bc83fe3 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -381,6 +381,10 @@ extern int	isinf(double x);
 #endif							/* __clang__ && !__cplusplus */
 #endif							/* !HAVE_ISINF */
 
+#ifndef HAVE_STRTOF
+extern float strtof(const char *nptr, char **endptr);
+#endif
+
 #ifndef HAVE_MKDTEMP
 extern char *mkdtemp(char *path);
 #endif
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index fdd8b2d3b1..9bab75d5da 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -510,6 +510,18 @@ typedef unsigned short mode_t;
 #define isnan(x) _isnan(x)
 #endif
 
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+/*
+ * VS2013 has a strtof() that seems to give correct answers for valid input,
+ * even on the rounding edge cases, but which doesn't handle out-of-range
+ * input correctly. Work around that.
+ */
+#define HAVE_BUGGY_WINDOWS_STRTOF 1
+extern float pg_strtof(const char *nptr, char **endptr);
+#define strtof(a,b) (pg_strtof((a),(b)))
+
+#endif
+
 /* Pulled from Makefile.port in MinGW */
 #define DLSUFFIX ".dll"
 
diff --git a/src/port/strtof.c b/src/port/strtof.c
new file mode 100644
index 0000000000..34f85638c9
--- /dev/null
+++ b/src/port/strtof.c
@@ -0,0 +1,121 @@
+/*-------------------------------------------------------------------------
+ *
+ * strtof.c
+ *
+ * Portions Copyright (c) 2019, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  src/port/strtof.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <float.h>
+#include <math.h>
+
+#ifndef HAVE_STRTOF
+/*
+ * strtof() is part of C99; this version is only for the benefit of obsolete
+ * platforms. As such, it is known to return incorrect values for edge cases,
+ * which have to be allowed for in variant files for regression test results
+ * for any such platform.
+ */
+
+float
+strtof(const char *nptr, char **endptr)
+{
+	int			caller_errno = errno;
+	double		dresult;
+	float		fresult;
+
+	errno = 0;
+	dresult = strtod(nptr, endptr);
+	fresult = (float) dresult;
+
+	if (errno == 0)
+	{
+		/*
+		 * Value might be in-range for double but not float.
+		 */
+		if (dresult != 0 && fresult == 0)
+			caller_errno = ERANGE;			  /* underflow */
+		if (!isinf(dresult) && isinf(fresult))
+			caller_errno = ERANGE;			  /* overflow */
+	}
+	else
+		caller_errno = errno;
+
+	errno = caller_errno;
+	return fresult;
+}
+
+#elif HAVE_BUGGY_WINDOWS_STRTOF
+/*
+ * On Windows, there's a slightly different problem: VS2013 has a strtof()
+ * that returns the correct results for valid input, but may fail to report an
+ * error for underflow or overflow, returning 0 instead. Work around that by
+ * trying strtod() when strtof() returns 0.0 or [+-]Inf, and calling it an
+ * error if the result differs. Also, strtof() doesn't handle subnormal input
+ * well, so prefer to round the strtod() result in such cases. (Normally we'd
+ * just say "too bad" if strtof() doesn't support subnormals, but since we're
+ * already in here fixing stuff, we might as well do the best fix we can.)
+ */
+float
+pg_strtof(const char *nptr, char **endptr)
+{
+	int			caller_errno = errno;
+	float		fresult;
+
+	errno = 0;
+	fresult = (strtof)(nptr, endptr);
+	if (errno)
+	{
+		/* On error, just return the error to the caller. */
+		return fresult;
+	}
+	else if ((*endptr == nptr) ||
+			 ((fresult >= FLT_MIN || fresult <= -FLT_MIN) && !isinf(fresult)))
+	{
+		/*
+		 * If we got nothing parseable, or if we got a non-0 non-subnormal
+		 * finite value (or NaN) without error, then return that to the caller
+		 * without error.
+		 */
+		errno = caller_errno;
+		return fresult;
+	}
+	else
+	{
+		/*
+		 * Try again.
+		 */
+		double	dresult = strtod(nptr, NULL);
+		if (errno)
+		{
+			/* On error, just return the error */
+			return fresult;
+		}
+		else if ((dresult == 0.0 && fresult == 0.0) ||
+				 (isinf(dresult) && isinf(fresult) && (fresult == dresult)))
+		{
+			/* both values are 0 or infinities of the same sign */
+			errno = caller_errno;
+			return fresult;
+		}
+		else if ((dresult > 0 && dresult <= FLT_MIN && (float)dresult != 0.0) ||
+				 (dresult < 0 && dresult >= -FLT_MIN && (float)dresult != 0.0))
+		{
+			return (float) dresult;
+		}
+		else
+		{
+			errno = ERANGE;
+			return fresult;
+		}
+	}
+}
+
+#endif
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 918db6cb67..129c1e5075 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -1,6 +1,8 @@
 --
 -- AGGREGATES
 --
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
 SELECT avg(four) AS avg_1 FROM onek;
        avg_1        
 --------------------
diff --git a/src/test/regress/expected/circle.out b/src/test/regress/expected/circle.out
index 2ed74cc6aa..756c7e37ef 100644
--- a/src/test/regress/expected/circle.out
+++ b/src/test/regress/expected/circle.out
@@ -1,6 +1,8 @@
 --
 -- CIRCLE
 --
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
 CREATE TABLE CIRCLE_TBL (f1 circle);
 INSERT INTO CIRCLE_TBL VALUES ('<(5,1),3>');
 INSERT INTO CIRCLE_TBL VALUES ('<(1,2),100>');
diff --git a/src/test/regress/expected/float4-misrounded-input.out b/src/test/regress/expected/float4-misrounded-input.out
new file mode 100644
index 0000000000..54de939a6e
--- /dev/null
+++ b/src/test/regress/expected/float4-misrounded-input.out
@@ -0,0 +1,940 @@
+--
+-- FLOAT4
+--
+CREATE TABLE FLOAT4_TBL (f1  float4);
+INSERT INTO FLOAT4_TBL(f1) VALUES ('    0.0');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('1004.30   ');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('     -34.84    ');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20');
+-- test for over and under flow
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
+ERROR:  "10e70" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
+ERROR:  "-10e70" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
+ERROR:  "10e-70" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
+ERROR:  "-10e-70" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e400');
+ERROR:  "10e400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e400');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e400');
+ERROR:  "-10e400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e400');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-400');
+ERROR:  "10e-400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-400');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-400');
+ERROR:  "-10e-400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-400');
+                                           ^
+-- bad input
+INSERT INTO FLOAT4_TBL(f1) VALUES ('');
+ERROR:  invalid input syntax for type real: ""
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('       ');
+ERROR:  invalid input syntax for type real: "       "
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('       ');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
+ERROR:  invalid input syntax for type real: "xyz"
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
+ERROR:  invalid input syntax for type real: "5.0.0"
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
+ERROR:  invalid input syntax for type real: "5 . 0"
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('5.   0');
+ERROR:  invalid input syntax for type real: "5.   0"
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('5.   0');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('     - 3.0');
+ERROR:  invalid input syntax for type real: "     - 3.0"
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('     - 3.0');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('123            5');
+ERROR:  invalid input syntax for type real: "123            5"
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('123            5');
+                                           ^
+-- special inputs
+SELECT 'NaN'::float4;
+ float4 
+--------
+    NaN
+(1 row)
+
+SELECT 'nan'::float4;
+ float4 
+--------
+    NaN
+(1 row)
+
+SELECT '   NAN  '::float4;
+ float4 
+--------
+    NaN
+(1 row)
+
+SELECT 'infinity'::float4;
+  float4  
+----------
+ Infinity
+(1 row)
+
+SELECT '          -INFINiTY   '::float4;
+  float4   
+-----------
+ -Infinity
+(1 row)
+
+-- bad special inputs
+SELECT 'N A N'::float4;
+ERROR:  invalid input syntax for type real: "N A N"
+LINE 1: SELECT 'N A N'::float4;
+               ^
+SELECT 'NaN x'::float4;
+ERROR:  invalid input syntax for type real: "NaN x"
+LINE 1: SELECT 'NaN x'::float4;
+               ^
+SELECT ' INFINITY    x'::float4;
+ERROR:  invalid input syntax for type real: " INFINITY    x"
+LINE 1: SELECT ' INFINITY    x'::float4;
+               ^
+SELECT 'Infinity'::float4 + 100.0;
+ ?column? 
+----------
+ Infinity
+(1 row)
+
+SELECT 'Infinity'::float4 / 'Infinity'::float4;
+ ?column? 
+----------
+      NaN
+(1 row)
+
+SELECT 'nan'::float4 / 'nan'::float4;
+ ?column? 
+----------
+      NaN
+(1 row)
+
+SELECT 'nan'::numeric::float4;
+ float4 
+--------
+    NaN
+(1 row)
+
+SELECT '' AS five, * FROM FLOAT4_TBL;
+ five |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e+20
+      | 1.2345679e-20
+(5 rows)
+
+SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <> '1004.3';
+ four |      f1       
+------+---------------
+      |             0
+      |        -34.84
+      | 1.2345679e+20
+      | 1.2345679e-20
+(4 rows)
+
+SELECT '' AS one, f.* FROM FLOAT4_TBL f WHERE f.f1 = '1004.3';
+ one |   f1   
+-----+--------
+     | 1004.3
+(1 row)
+
+SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE '1004.3' > f.f1;
+ three |      f1       
+-------+---------------
+       |             0
+       |        -34.84
+       | 1.2345679e-20
+(3 rows)
+
+SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE  f.f1 < '1004.3';
+ three |      f1       
+-------+---------------
+       |             0
+       |        -34.84
+       | 1.2345679e-20
+(3 rows)
+
+SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE '1004.3' >= f.f1;
+ four |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e-20
+(4 rows)
+
+SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE  f.f1 <= '1004.3';
+ four |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e-20
+(4 rows)
+
+SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f
+   WHERE f.f1 > '0.0';
+ three |      f1       |       x        
+-------+---------------+----------------
+       |        1004.3 |         -10043
+       | 1.2345679e+20 | -1.2345678e+21
+       | 1.2345679e-20 | -1.2345678e-19
+(3 rows)
+
+SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f
+   WHERE f.f1 > '0.0';
+ three |      f1       |       x       
+-------+---------------+---------------
+       |        1004.3 |         994.3
+       | 1.2345679e+20 | 1.2345679e+20
+       | 1.2345679e-20 |           -10
+(3 rows)
+
+SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f
+   WHERE f.f1 > '0.0';
+ three |      f1       |       x        
+-------+---------------+----------------
+       |        1004.3 |        -100.43
+       | 1.2345679e+20 | -1.2345679e+19
+       | 1.2345679e-20 | -1.2345679e-21
+(3 rows)
+
+SELECT '' AS three, f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f
+   WHERE f.f1 > '0.0';
+ three |      f1       |       x       
+-------+---------------+---------------
+       |        1004.3 |        1014.3
+       | 1.2345679e+20 | 1.2345679e+20
+       | 1.2345679e-20 |            10
+(3 rows)
+
+-- test divide by zero
+SELECT '' AS bad, f.f1 / '0.0' from FLOAT4_TBL f;
+ERROR:  division by zero
+SELECT '' AS five, * FROM FLOAT4_TBL;
+ five |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e+20
+      | 1.2345679e-20
+(5 rows)
+
+-- test the unary float4abs operator
+SELECT '' AS five, f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f;
+ five |      f1       |    abs_f1     
+------+---------------+---------------
+      |             0 |             0
+      |        1004.3 |        1004.3
+      |        -34.84 |         34.84
+      | 1.2345679e+20 | 1.2345679e+20
+      | 1.2345679e-20 | 1.2345679e-20
+(5 rows)
+
+UPDATE FLOAT4_TBL
+   SET f1 = FLOAT4_TBL.f1 * '-1'
+   WHERE FLOAT4_TBL.f1 > '0.0';
+SELECT '' AS five, * FROM FLOAT4_TBL;
+ five |       f1       
+------+----------------
+      |              0
+      |         -34.84
+      |        -1004.3
+      | -1.2345679e+20
+      | -1.2345679e-20
+(5 rows)
+
+-- test edge-case coercions to integer
+SELECT '32767.4'::float4::int2;
+ int2  
+-------
+ 32767
+(1 row)
+
+SELECT '32767.6'::float4::int2;
+ERROR:  smallint out of range
+SELECT '-32768.4'::float4::int2;
+  int2  
+--------
+ -32768
+(1 row)
+
+SELECT '-32768.6'::float4::int2;
+ERROR:  smallint out of range
+SELECT '2147483520'::float4::int4;
+    int4    
+------------
+ 2147483520
+(1 row)
+
+SELECT '2147483647'::float4::int4;
+ERROR:  integer out of range
+SELECT '-2147483648.5'::float4::int4;
+    int4     
+-------------
+ -2147483648
+(1 row)
+
+SELECT '-2147483900'::float4::int4;
+ERROR:  integer out of range
+SELECT '9223369837831520256'::float4::int8;
+        int8         
+---------------------
+ 9223369837831520256
+(1 row)
+
+SELECT '9223372036854775807'::float4::int8;
+ERROR:  bigint out of range
+SELECT '-9223372036854775808.5'::float4::int8;
+         int8         
+----------------------
+ -9223372036854775808
+(1 row)
+
+SELECT '-9223380000000000000'::float4::int8;
+ERROR:  bigint out of range
+-- Test for correct input rounding in edge cases.
+-- These lists are from Paxson 1991, excluding subnormals and
+-- inputs of over 9 sig. digits.
+SELECT float4send('5e-20'::float4);
+ float4send 
+------------
+ \x1f6c1e4a
+(1 row)
+
+SELECT float4send('67e14'::float4);
+ float4send 
+------------
+ \x59be6cea
+(1 row)
+
+SELECT float4send('985e15'::float4);
+ float4send 
+------------
+ \x5d5ab6c4
+(1 row)
+
+SELECT float4send('55895e-16'::float4);
+ float4send 
+------------
+ \x2cc4a9bd
+(1 row)
+
+SELECT float4send('7038531e-32'::float4);
+ float4send 
+------------
+ \x15ae43fe
+(1 row)
+
+SELECT float4send('702990899e-20'::float4);
+ float4send 
+------------
+ \x2cf757ca
+(1 row)
+
+SELECT float4send('3e-23'::float4);
+ float4send 
+------------
+ \x1a111234
+(1 row)
+
+SELECT float4send('57e18'::float4);
+ float4send 
+------------
+ \x6045c22c
+(1 row)
+
+SELECT float4send('789e-35'::float4);
+ float4send 
+------------
+ \x0a23de70
+(1 row)
+
+SELECT float4send('2539e-18'::float4);
+ float4send 
+------------
+ \x2736f449
+(1 row)
+
+SELECT float4send('76173e28'::float4);
+ float4send 
+------------
+ \x7616398a
+(1 row)
+
+SELECT float4send('887745e-11'::float4);
+ float4send 
+------------
+ \x3714f05c
+(1 row)
+
+SELECT float4send('5382571e-37'::float4);
+ float4send 
+------------
+ \x0d2eaca7
+(1 row)
+
+SELECT float4send('82381273e-35'::float4);
+ float4send 
+------------
+ \x128289d0
+(1 row)
+
+SELECT float4send('750486563e-38'::float4);
+ float4send 
+------------
+ \x0f18377e
+(1 row)
+
+-- Test that the smallest possible normalized input value inputs
+-- correctly, either in 9-significant-digit or shortest-decimal
+-- format.
+--
+-- exact val is             1.1754943508...
+-- shortest val is          1.1754944000
+-- midpoint to next val is  1.1754944208...
+SELECT float4send('1.17549435e-38'::float4);
+ float4send 
+------------
+ \x00800000
+(1 row)
+
+SELECT float4send('1.1754944e-38'::float4);
+ float4send 
+------------
+ \x00800000
+(1 row)
+
+-- test output (and round-trip safety) of various values.
+-- To ensure we're testing what we think we're testing, start with
+-- float values specified by bit patterns (as a useful side effect,
+-- this means we'll fail on non-IEEE platforms).
+create type xfloat4;
+create function xfloat4in(cstring) returns xfloat4 immutable strict
+  language internal as 'int4in';
+NOTICE:  return type xfloat4 is only a shell
+create function xfloat4out(xfloat4) returns cstring immutable strict
+  language internal as 'int4out';
+NOTICE:  argument type xfloat4 is only a shell
+create type xfloat4 (input = xfloat4in, output = xfloat4out, like = float4);
+create cast (xfloat4 as float4) without function;
+create cast (float4 as xfloat4) without function;
+create cast (xfloat4 as integer) without function;
+create cast (integer as xfloat4) without function;
+-- float4: seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
+-- we don't care to assume the platform's strtod() handles subnormals
+-- correctly; those are "use at your own risk". However we do test
+-- subnormal outputs, since those are under our control.
+with testdata(bits) as (values
+  -- small subnormals
+  (x'00000001'),
+  (x'00000002'), (x'00000003'),
+  (x'00000010'), (x'00000011'), (x'00000100'), (x'00000101'),
+  (x'00004000'), (x'00004001'), (x'00080000'), (x'00080001'),
+  -- stress values
+  (x'0053c4f4'),  -- 7693e-42
+  (x'006c85c4'),  -- 996622e-44
+  (x'0041ca76'),  -- 60419369e-46
+  (x'004b7678'),  -- 6930161142e-48
+  -- taken from upstream testsuite
+  (x'00000007'),
+  (x'00424fe2'),
+  -- borderline between subnormal and normal
+  (x'007ffff0'), (x'007ffff1'), (x'007ffffe'), (x'007fffff'))
+select float4send(flt) as ibits,
+       flt
+  from (select bits::integer::xfloat4::float4 as flt
+          from testdata
+	offset 0) s;
+   ibits    |      flt      
+------------+---------------
+ \x00000001 |         1e-45
+ \x00000002 |         3e-45
+ \x00000003 |         4e-45
+ \x00000010 |       2.2e-44
+ \x00000011 |       2.4e-44
+ \x00000100 |      3.59e-43
+ \x00000101 |       3.6e-43
+ \x00004000 |    2.2959e-41
+ \x00004001 |     2.296e-41
+ \x00080000 |   7.34684e-40
+ \x00080001 |   7.34685e-40
+ \x0053c4f4 |     7.693e-39
+ \x006c85c4 |   9.96622e-39
+ \x0041ca76 |  6.041937e-39
+ \x004b7678 |  6.930161e-39
+ \x00000007 |         1e-44
+ \x00424fe2 |    6.0898e-39
+ \x007ffff0 | 1.1754921e-38
+ \x007ffff1 | 1.1754922e-38
+ \x007ffffe | 1.1754941e-38
+ \x007fffff | 1.1754942e-38
+(21 rows)
+
+with testdata(bits) as (values
+  (x'00000000'),
+  -- smallest normal values
+  (x'00800000'), (x'00800001'), (x'00800004'), (x'00800005'),
+  (x'00800006'),
+  -- small normal values chosen for short vs. long output
+  (x'008002f1'), (x'008002f2'), (x'008002f3'),
+  (x'00800e17'), (x'00800e18'), (x'00800e19'),
+  -- assorted values (random mantissae)
+  (x'01000001'), (x'01102843'), (x'01a52c98'),
+  (x'0219c229'), (x'02e4464d'), (x'037343c1'), (x'03a91b36'),
+  (x'047ada65'), (x'0496fe87'), (x'0550844f'), (x'05999da3'),
+  (x'060ea5e2'), (x'06e63c45'), (x'07f1e548'), (x'0fc5282b'),
+  (x'1f850283'), (x'2874a9d6'),
+  -- values around 5e-08
+  (x'3356bf94'), (x'3356bf95'), (x'3356bf96'),
+  -- around 1e-07
+  (x'33d6bf94'), (x'33d6bf95'), (x'33d6bf96'),
+  -- around 3e-07 .. 1e-04
+  (x'34a10faf'), (x'34a10fb0'), (x'34a10fb1'),
+  (x'350637bc'), (x'350637bd'), (x'350637be'),
+  (x'35719786'), (x'35719787'), (x'35719788'),
+  (x'358637bc'), (x'358637bd'), (x'358637be'),
+  (x'36a7c5ab'), (x'36a7c5ac'), (x'36a7c5ad'),
+  (x'3727c5ab'), (x'3727c5ac'), (x'3727c5ad'),
+  -- format crossover at 1e-04
+  (x'38d1b714'), (x'38d1b715'), (x'38d1b716'),
+  (x'38d1b717'), (x'38d1b718'), (x'38d1b719'),
+  (x'38d1b71a'), (x'38d1b71b'), (x'38d1b71c'),
+  (x'38d1b71d'),
+  --
+  (x'38dffffe'), (x'38dfffff'), (x'38e00000'),
+  (x'38efffff'), (x'38f00000'), (x'38f00001'),
+  (x'3a83126e'), (x'3a83126f'), (x'3a831270'),
+  (x'3c23d709'), (x'3c23d70a'), (x'3c23d70b'),
+  (x'3dcccccc'), (x'3dcccccd'), (x'3dccccce'),
+  -- chosen to need 9 digits for 3dcccd70
+  (x'3dcccd6f'), (x'3dcccd70'), (x'3dcccd71'),
+  --
+  (x'3effffff'), (x'3f000000'), (x'3f000001'),
+  (x'3f333332'), (x'3f333333'), (x'3f333334'),
+  -- approach 1.0 with increasing numbers of 9s
+  (x'3f666665'), (x'3f666666'), (x'3f666667'),
+  (x'3f7d70a3'), (x'3f7d70a4'), (x'3f7d70a5'),
+  (x'3f7fbe76'), (x'3f7fbe77'), (x'3f7fbe78'),
+  (x'3f7ff971'), (x'3f7ff972'), (x'3f7ff973'),
+  (x'3f7fff57'), (x'3f7fff58'), (x'3f7fff59'),
+  (x'3f7fffee'), (x'3f7fffef'),
+  -- values very close to 1
+  (x'3f7ffff0'), (x'3f7ffff1'), (x'3f7ffff2'),
+  (x'3f7ffff3'), (x'3f7ffff4'), (x'3f7ffff5'),
+  (x'3f7ffff6'), (x'3f7ffff7'), (x'3f7ffff8'),
+  (x'3f7ffff9'), (x'3f7ffffa'), (x'3f7ffffb'),
+  (x'3f7ffffc'), (x'3f7ffffd'), (x'3f7ffffe'),
+  (x'3f7fffff'),
+  (x'3f800000'),
+  (x'3f800001'), (x'3f800002'), (x'3f800003'),
+  (x'3f800004'), (x'3f800005'), (x'3f800006'),
+  (x'3f800007'), (x'3f800008'), (x'3f800009'),
+  -- values 1 to 1.1
+  (x'3f80000f'), (x'3f800010'), (x'3f800011'),
+  (x'3f800012'), (x'3f800013'), (x'3f800014'),
+  (x'3f800017'), (x'3f800018'), (x'3f800019'),
+  (x'3f80001a'), (x'3f80001b'), (x'3f80001c'),
+  (x'3f800029'), (x'3f80002a'), (x'3f80002b'),
+  (x'3f800053'), (x'3f800054'), (x'3f800055'),
+  (x'3f800346'), (x'3f800347'), (x'3f800348'),
+  (x'3f8020c4'), (x'3f8020c5'), (x'3f8020c6'),
+  (x'3f8147ad'), (x'3f8147ae'), (x'3f8147af'),
+  (x'3f8ccccc'), (x'3f8ccccd'), (x'3f8cccce'),
+  --
+  (x'3fc90fdb'), -- pi/2
+  (x'402df854'), -- e
+  (x'40490fdb'), -- pi
+  --
+  (x'409fffff'), (x'40a00000'), (x'40a00001'),
+  (x'40afffff'), (x'40b00000'), (x'40b00001'),
+  (x'411fffff'), (x'41200000'), (x'41200001'),
+  (x'42c7ffff'), (x'42c80000'), (x'42c80001'),
+  (x'4479ffff'), (x'447a0000'), (x'447a0001'),
+  (x'461c3fff'), (x'461c4000'), (x'461c4001'),
+  (x'47c34fff'), (x'47c35000'), (x'47c35001'),
+  (x'497423ff'), (x'49742400'), (x'49742401'),
+  (x'4b18967f'), (x'4b189680'), (x'4b189681'),
+  (x'4cbebc1f'), (x'4cbebc20'), (x'4cbebc21'),
+  (x'4e6e6b27'), (x'4e6e6b28'), (x'4e6e6b29'),
+  (x'501502f8'), (x'501502f9'), (x'501502fa'),
+  (x'51ba43b6'), (x'51ba43b7'), (x'51ba43b8'),
+  -- stress values
+  (x'1f6c1e4a'),  -- 5e-20
+  (x'59be6cea'),  -- 67e14
+  (x'5d5ab6c4'),  -- 985e15
+  (x'2cc4a9bd'),  -- 55895e-16
+  (x'15ae43fd'),  -- 7038531e-32
+  (x'2cf757ca'),  -- 702990899e-20
+  (x'665ba998'),  -- 25933168707e13
+  (x'743c3324'),  -- 596428896559e20
+  -- exercise fixed-point memmoves
+  (x'47f1205a'),
+  (x'4640e6ae'),
+  (x'449a5225'),
+  (x'42f6e9d5'),
+  (x'414587dd'),
+  (x'3f9e064b'),
+  -- these cases come from the upstream's testsuite
+  -- BoundaryRoundEven
+  (x'4c000004'),
+  (x'50061c46'),
+  (x'510006a8'),
+  -- ExactValueRoundEven
+  (x'48951f84'),
+  (x'45fd1840'),
+  -- LotsOfTrailingZeros
+  (x'39800000'),
+  (x'3b200000'),
+  (x'3b900000'),
+  (x'3bd00000'),
+  -- Regression
+  (x'63800000'),
+  (x'4b000000'),
+  (x'4b800000'),
+  (x'4c000001'),
+  (x'4c800b0d'),
+  (x'00d24584'),
+  (x'800000b0'),
+  (x'00d90b88'),
+  (x'45803f34'),
+  (x'4f9f24f7'),
+  (x'3a8722c3'),
+  (x'5c800041'),
+  (x'15ae43fd'),
+  (x'5d4cccfb'),
+  (x'4c800001'),
+  (x'57800ed8'),
+  (x'5f000000'),
+  (x'700000f0'),
+  (x'5f23e9ac'),
+  (x'5e9502f9'),
+  (x'5e8012b1'),
+  (x'3c000028'),
+  (x'60cde861'),
+  (x'03aa2a50'),
+  (x'43480000'),
+  (x'4c000000'),
+  -- LooksLikePow5
+  (x'5D1502F9'),
+  (x'5D9502F9'),
+  (x'5E1502F9'),
+  -- OutputLength
+  (x'3f99999a'),
+  (x'3f9d70a4'),
+  (x'3f9df3b6'),
+  (x'3f9e0419'),
+  (x'3f9e0610'),
+  (x'3f9e064b'),
+  (x'3f9e0651'),
+  (x'03d20cfe')
+)
+select float4send(flt) as ibits,
+       flt,
+       flt::text::float4 as r_flt,
+       float4send(flt::text::float4) as obits,
+       float4send(flt::text::float4) = float4send(flt) as correct
+  from (select bits::integer::xfloat4::float4 as flt
+          from testdata
+	offset 0) s;
+   ibits    |      flt       |     r_flt      |   obits    | correct 
+------------+----------------+----------------+------------+---------
+ \x00000000 |              0 |              0 | \x00000000 | t
+ \x00800000 |  1.1754944e-38 |  1.1754944e-38 | \x00800000 | t
+ \x00800001 |  1.1754945e-38 |  1.1754945e-38 | \x00800001 | t
+ \x00800004 |  1.1754949e-38 |  1.1754949e-38 | \x00800004 | t
+ \x00800005 |   1.175495e-38 |   1.175495e-38 | \x00800005 | t
+ \x00800006 |  1.1754952e-38 |  1.1754952e-38 | \x00800006 | t
+ \x008002f1 |  1.1755999e-38 |  1.1755999e-38 | \x008002f1 | t
+ \x008002f2 |     1.1756e-38 |     1.1756e-38 | \x008002f2 | t
+ \x008002f3 |  1.1756001e-38 |  1.1756001e-38 | \x008002f3 | t
+ \x00800e17 |  1.1759998e-38 |  1.1759998e-38 | \x00800e17 | t
+ \x00800e18 |      1.176e-38 |      1.176e-38 | \x00800e18 | t
+ \x00800e19 |  1.1760001e-38 |  1.1760001e-38 | \x00800e19 | t
+ \x01000001 |   2.350989e-38 |   2.350989e-38 | \x01000001 | t
+ \x01102843 |   2.647751e-38 |   2.647751e-38 | \x01102843 | t
+ \x01a52c98 |  6.0675416e-38 |  6.0675416e-38 | \x01a52c98 | t
+ \x0219c229 |  1.1296386e-37 |  1.1296386e-37 | \x0219c229 | t
+ \x02e4464d |   3.354194e-37 |   3.354194e-37 | \x02e4464d | t
+ \x037343c1 |   7.148906e-37 |   7.148906e-37 | \x037343c1 | t
+ \x03a91b36 |   9.939175e-37 |   9.939175e-37 | \x03a91b36 | t
+ \x047ada65 |   2.948764e-36 |   2.948764e-36 | \x047ada65 | t
+ \x0496fe87 |  3.5498577e-36 |  3.5498577e-36 | \x0496fe87 | t
+ \x0550844f |   9.804414e-36 |   9.804414e-36 | \x0550844f | t
+ \x05999da3 |  1.4445957e-35 |  1.4445957e-35 | \x05999da3 | t
+ \x060ea5e2 |  2.6829103e-35 |  2.6829103e-35 | \x060ea5e2 | t
+ \x06e63c45 |   8.660494e-35 |   8.660494e-35 | \x06e63c45 | t
+ \x07f1e548 |   3.639641e-34 |   3.639641e-34 | \x07f1e548 | t
+ \x0fc5282b |  1.9441172e-29 |  1.9441172e-29 | \x0fc5282b | t
+ \x1f850283 |  5.6331846e-20 |  5.6331846e-20 | \x1f850283 | t
+ \x2874a9d6 |  1.3581548e-14 |  1.3581548e-14 | \x2874a9d6 | t
+ \x3356bf94 |  4.9999997e-08 |  4.9999997e-08 | \x3356bf94 | t
+ \x3356bf95 |          5e-08 |          5e-08 | \x3356bf95 | t
+ \x3356bf96 |  5.0000004e-08 |  5.0000004e-08 | \x3356bf96 | t
+ \x33d6bf94 |  9.9999994e-08 |  9.9999994e-08 | \x33d6bf94 | t
+ \x33d6bf95 |          1e-07 |          1e-07 | \x33d6bf95 | t
+ \x33d6bf96 |  1.0000001e-07 |  1.0000001e-07 | \x33d6bf96 | t
+ \x34a10faf |  2.9999998e-07 |  2.9999998e-07 | \x34a10faf | t
+ \x34a10fb0 |          3e-07 |          3e-07 | \x34a10fb0 | t
+ \x34a10fb1 |  3.0000004e-07 |  3.0000004e-07 | \x34a10fb1 | t
+ \x350637bc |  4.9999994e-07 |  4.9999994e-07 | \x350637bc | t
+ \x350637bd |          5e-07 |          5e-07 | \x350637bd | t
+ \x350637be |  5.0000006e-07 |  5.0000006e-07 | \x350637be | t
+ \x35719786 |   8.999999e-07 |   8.999999e-07 | \x35719786 | t
+ \x35719787 |          9e-07 |          9e-07 | \x35719787 | t
+ \x35719788 |  9.0000003e-07 |  9.0000003e-07 | \x35719788 | t
+ \x358637bc |   9.999999e-07 |   9.999999e-07 | \x358637bc | t
+ \x358637bd |          1e-06 |          1e-06 | \x358637bd | t
+ \x358637be |  1.0000001e-06 |  1.0000001e-06 | \x358637be | t
+ \x36a7c5ab |  4.9999994e-06 |  4.9999994e-06 | \x36a7c5ab | t
+ \x36a7c5ac |          5e-06 |          5e-06 | \x36a7c5ac | t
+ \x36a7c5ad |  5.0000003e-06 |  5.0000003e-06 | \x36a7c5ad | t
+ \x3727c5ab |   9.999999e-06 |   9.999999e-06 | \x3727c5ab | t
+ \x3727c5ac |          1e-05 |          1e-05 | \x3727c5ac | t
+ \x3727c5ad |  1.0000001e-05 |  1.0000001e-05 | \x3727c5ad | t
+ \x38d1b714 |  9.9999976e-05 |  9.9999976e-05 | \x38d1b714 | t
+ \x38d1b715 |   9.999998e-05 |   9.999998e-05 | \x38d1b715 | t
+ \x38d1b716 |   9.999999e-05 |   9.999999e-05 | \x38d1b716 | t
+ \x38d1b717 |         0.0001 |         0.0001 | \x38d1b717 | t
+ \x38d1b718 | 0.000100000005 | 0.000100000005 | \x38d1b718 | t
+ \x38d1b719 |  0.00010000001 |  0.00010000001 | \x38d1b719 | t
+ \x38d1b71a |  0.00010000002 |  0.00010000002 | \x38d1b71a | t
+ \x38d1b71b |  0.00010000003 |  0.00010000003 | \x38d1b71b | t
+ \x38d1b71c | 0.000100000034 | 0.000100000034 | \x38d1b71c | t
+ \x38d1b71d |  0.00010000004 |  0.00010000004 | \x38d1b71d | t
+ \x38dffffe |  0.00010681151 |  0.00010681151 | \x38dffffe | t
+ \x38dfffff | 0.000106811516 | 0.000106811516 | \x38dfffff | t
+ \x38e00000 |  0.00010681152 |  0.00010681152 | \x38e00000 | t
+ \x38efffff |  0.00011444091 |  0.00011444091 | \x38efffff | t
+ \x38f00000 |  0.00011444092 |  0.00011444092 | \x38f00000 | t
+ \x38f00001 | 0.000114440925 | 0.000114440925 | \x38f00001 | t
+ \x3a83126e |   0.0009999999 |   0.0009999999 | \x3a83126e | t
+ \x3a83126f |          0.001 |          0.001 | \x3a83126f | t
+ \x3a831270 |   0.0010000002 |   0.0010000002 | \x3a831270 | t
+ \x3c23d709 |    0.009999999 |    0.009999999 | \x3c23d709 | t
+ \x3c23d70a |           0.01 |           0.01 | \x3c23d70a | t
+ \x3c23d70b |    0.010000001 |    0.010000001 | \x3c23d70b | t
+ \x3dcccccc |    0.099999994 |    0.099999994 | \x3dcccccc | t
+ \x3dcccccd |            0.1 |            0.1 | \x3dcccccd | t
+ \x3dccccce |     0.10000001 |     0.10000001 | \x3dccccce | t
+ \x3dcccd6f |     0.10000121 |     0.10000121 | \x3dcccd6f | t
+ \x3dcccd70 |    0.100001216 |    0.100001216 | \x3dcccd70 | t
+ \x3dcccd71 |     0.10000122 |     0.10000122 | \x3dcccd71 | t
+ \x3effffff |     0.49999997 |     0.49999997 | \x3effffff | t
+ \x3f000000 |            0.5 |            0.5 | \x3f000000 | t
+ \x3f000001 |     0.50000006 |     0.50000006 | \x3f000001 | t
+ \x3f333332 |      0.6999999 |      0.6999999 | \x3f333332 | t
+ \x3f333333 |            0.7 |            0.7 | \x3f333333 | t
+ \x3f333334 |     0.70000005 |     0.70000005 | \x3f333334 | t
+ \x3f666665 |      0.8999999 |      0.8999999 | \x3f666665 | t
+ \x3f666666 |            0.9 |            0.9 | \x3f666666 | t
+ \x3f666667 |     0.90000004 |     0.90000004 | \x3f666667 | t
+ \x3f7d70a3 |     0.98999995 |     0.98999995 | \x3f7d70a3 | t
+ \x3f7d70a4 |           0.99 |           0.99 | \x3f7d70a4 | t
+ \x3f7d70a5 |     0.99000007 |     0.99000007 | \x3f7d70a5 | t
+ \x3f7fbe76 |     0.99899995 |     0.99899995 | \x3f7fbe76 | t
+ \x3f7fbe77 |          0.999 |          0.999 | \x3f7fbe77 | t
+ \x3f7fbe78 |      0.9990001 |      0.9990001 | \x3f7fbe78 | t
+ \x3f7ff971 |      0.9998999 |      0.9998999 | \x3f7ff971 | t
+ \x3f7ff972 |         0.9999 |         0.9999 | \x3f7ff972 | t
+ \x3f7ff973 |     0.99990004 |     0.99990004 | \x3f7ff973 | t
+ \x3f7fff57 |      0.9999899 |      0.9999899 | \x3f7fff57 | t
+ \x3f7fff58 |        0.99999 |        0.99999 | \x3f7fff58 | t
+ \x3f7fff59 |     0.99999005 |     0.99999005 | \x3f7fff59 | t
+ \x3f7fffee |      0.9999989 |      0.9999989 | \x3f7fffee | t
+ \x3f7fffef |       0.999999 |       0.999999 | \x3f7fffef | t
+ \x3f7ffff0 |     0.99999905 |     0.99999905 | \x3f7ffff0 | t
+ \x3f7ffff1 |      0.9999991 |      0.9999991 | \x3f7ffff1 | t
+ \x3f7ffff2 |     0.99999917 |     0.99999917 | \x3f7ffff2 | t
+ \x3f7ffff3 |      0.9999992 |      0.9999992 | \x3f7ffff3 | t
+ \x3f7ffff4 |      0.9999993 |      0.9999993 | \x3f7ffff4 | t
+ \x3f7ffff5 |     0.99999934 |     0.99999934 | \x3f7ffff5 | t
+ \x3f7ffff6 |      0.9999994 |      0.9999994 | \x3f7ffff6 | t
+ \x3f7ffff7 |     0.99999946 |     0.99999946 | \x3f7ffff7 | t
+ \x3f7ffff8 |      0.9999995 |      0.9999995 | \x3f7ffff8 | t
+ \x3f7ffff9 |      0.9999996 |      0.9999996 | \x3f7ffff9 | t
+ \x3f7ffffa |     0.99999964 |     0.99999964 | \x3f7ffffa | t
+ \x3f7ffffb |      0.9999997 |      0.9999997 | \x3f7ffffb | t
+ \x3f7ffffc |     0.99999976 |     0.99999976 | \x3f7ffffc | t
+ \x3f7ffffd |      0.9999998 |      0.9999998 | \x3f7ffffd | t
+ \x3f7ffffe |      0.9999999 |      0.9999999 | \x3f7ffffe | t
+ \x3f7fffff |     0.99999994 |     0.99999994 | \x3f7fffff | t
+ \x3f800000 |              1 |              1 | \x3f800000 | t
+ \x3f800001 |      1.0000001 |      1.0000001 | \x3f800001 | t
+ \x3f800002 |      1.0000002 |      1.0000002 | \x3f800002 | t
+ \x3f800003 |      1.0000004 |      1.0000004 | \x3f800003 | t
+ \x3f800004 |      1.0000005 |      1.0000005 | \x3f800004 | t
+ \x3f800005 |      1.0000006 |      1.0000006 | \x3f800005 | t
+ \x3f800006 |      1.0000007 |      1.0000007 | \x3f800006 | t
+ \x3f800007 |      1.0000008 |      1.0000008 | \x3f800007 | t
+ \x3f800008 |       1.000001 |       1.000001 | \x3f800008 | t
+ \x3f800009 |      1.0000011 |      1.0000011 | \x3f800009 | t
+ \x3f80000f |      1.0000018 |      1.0000018 | \x3f80000f | t
+ \x3f800010 |      1.0000019 |      1.0000019 | \x3f800010 | t
+ \x3f800011 |       1.000002 |       1.000002 | \x3f800011 | t
+ \x3f800012 |      1.0000021 |      1.0000021 | \x3f800012 | t
+ \x3f800013 |      1.0000023 |      1.0000023 | \x3f800013 | t
+ \x3f800014 |      1.0000024 |      1.0000024 | \x3f800014 | t
+ \x3f800017 |      1.0000027 |      1.0000027 | \x3f800017 | t
+ \x3f800018 |      1.0000029 |      1.0000029 | \x3f800018 | t
+ \x3f800019 |       1.000003 |       1.000003 | \x3f800019 | t
+ \x3f80001a |      1.0000031 |      1.0000031 | \x3f80001a | t
+ \x3f80001b |      1.0000032 |      1.0000032 | \x3f80001b | t
+ \x3f80001c |      1.0000033 |      1.0000033 | \x3f80001c | t
+ \x3f800029 |      1.0000049 |      1.0000049 | \x3f800029 | t
+ \x3f80002a |       1.000005 |       1.000005 | \x3f80002a | t
+ \x3f80002b |      1.0000051 |      1.0000051 | \x3f80002b | t
+ \x3f800053 |      1.0000099 |      1.0000099 | \x3f800053 | t
+ \x3f800054 |        1.00001 |        1.00001 | \x3f800054 | t
+ \x3f800055 |      1.0000101 |      1.0000101 | \x3f800055 | t
+ \x3f800346 |      1.0000999 |      1.0000999 | \x3f800346 | t
+ \x3f800347 |         1.0001 |         1.0001 | \x3f800347 | t
+ \x3f800348 |      1.0001001 |      1.0001001 | \x3f800348 | t
+ \x3f8020c4 |      1.0009999 |      1.0009999 | \x3f8020c4 | t
+ \x3f8020c5 |          1.001 |          1.001 | \x3f8020c5 | t
+ \x3f8020c6 |      1.0010002 |      1.0010002 | \x3f8020c6 | t
+ \x3f8147ad |      1.0099999 |      1.0099999 | \x3f8147ad | t
+ \x3f8147ae |           1.01 |           1.01 | \x3f8147ae | t
+ \x3f8147af |      1.0100001 |      1.0100001 | \x3f8147af | t
+ \x3f8ccccc |      1.0999999 |      1.0999999 | \x3f8ccccc | t
+ \x3f8ccccd |            1.1 |            1.1 | \x3f8ccccd | t
+ \x3f8cccce |      1.1000001 |      1.1000001 | \x3f8cccce | t
+ \x3fc90fdb |      1.5707964 |      1.5707964 | \x3fc90fdb | t
+ \x402df854 |      2.7182817 |      2.7182817 | \x402df854 | t
+ \x40490fdb |      3.1415927 |      3.1415927 | \x40490fdb | t
+ \x409fffff |      4.9999995 |      4.9999995 | \x409fffff | t
+ \x40a00000 |              5 |              5 | \x40a00000 | t
+ \x40a00001 |      5.0000005 |      5.0000005 | \x40a00001 | t
+ \x40afffff |      5.4999995 |      5.4999995 | \x40afffff | t
+ \x40b00000 |            5.5 |            5.5 | \x40b00000 | t
+ \x40b00001 |      5.5000005 |      5.5000005 | \x40b00001 | t
+ \x411fffff |       9.999999 |       9.999999 | \x411fffff | t
+ \x41200000 |             10 |             10 | \x41200000 | t
+ \x41200001 |      10.000001 |      10.000001 | \x41200001 | t
+ \x42c7ffff |       99.99999 |       99.99999 | \x42c7ffff | t
+ \x42c80000 |            100 |            100 | \x42c80000 | t
+ \x42c80001 |      100.00001 |      100.00001 | \x42c80001 | t
+ \x4479ffff |      999.99994 |      999.99994 | \x4479ffff | t
+ \x447a0000 |           1000 |           1000 | \x447a0000 | t
+ \x447a0001 |     1000.00006 |     1000.00006 | \x447a0001 | t
+ \x461c3fff |       9999.999 |       9999.999 | \x461c3fff | t
+ \x461c4000 |          10000 |          10000 | \x461c4000 | t
+ \x461c4001 |      10000.001 |      10000.001 | \x461c4001 | t
+ \x47c34fff |       99999.99 |       99999.99 | \x47c34fff | t
+ \x47c35000 |         100000 |         100000 | \x47c35000 | t
+ \x47c35001 |      100000.01 |      100000.01 | \x47c35001 | t
+ \x497423ff |      999999.94 |      999999.94 | \x497423ff | t
+ \x49742400 |          1e+06 |          1e+06 | \x49742400 | t
+ \x49742401 | 1.00000006e+06 | 1.00000006e+06 | \x49742401 | t
+ \x4b18967f |   9.999999e+06 |   9.999999e+06 | \x4b18967f | t
+ \x4b189680 |          1e+07 |          1e+07 | \x4b189680 | t
+ \x4b189681 |  1.0000001e+07 |  1.0000001e+07 | \x4b189681 | t
+ \x4cbebc1f |   9.999999e+07 |   9.999999e+07 | \x4cbebc1f | t
+ \x4cbebc20 |          1e+08 |          1e+08 | \x4cbebc20 | t
+ \x4cbebc21 |  1.0000001e+08 |  1.0000001e+08 | \x4cbebc21 | t
+ \x4e6e6b27 |  9.9999994e+08 |  9.9999994e+08 | \x4e6e6b27 | t
+ \x4e6e6b28 |          1e+09 |          1e+09 | \x4e6e6b28 | t
+ \x4e6e6b29 | 1.00000006e+09 | 1.00000006e+09 | \x4e6e6b29 | t
+ \x501502f8 |   9.999999e+09 |   9.999999e+09 | \x501502f8 | t
+ \x501502f9 |          1e+10 |          1e+10 | \x501502f9 | t
+ \x501502fa |  1.0000001e+10 |  1.0000001e+10 | \x501502fa | t
+ \x51ba43b6 |   9.999999e+10 |   9.999999e+10 | \x51ba43b6 | t
+ \x51ba43b7 |          1e+11 |          1e+11 | \x51ba43b7 | t
+ \x51ba43b8 |  1.0000001e+11 |  1.0000001e+11 | \x51ba43b8 | t
+ \x1f6c1e4a |          5e-20 |          5e-20 | \x1f6c1e4a | t
+ \x59be6cea |        6.7e+15 |        6.7e+15 | \x59be6cea | t
+ \x5d5ab6c4 |       9.85e+17 |       9.85e+17 | \x5d5ab6c4 | t
+ \x2cc4a9bd |     5.5895e-12 |     5.5895e-12 | \x2cc4a9bd | t
+ \x15ae43fd |   7.038531e-26 |  7.0385313e-26 | \x15ae43fe | f
+ \x2cf757ca |  7.0299088e-12 |  7.0299088e-12 | \x2cf757ca | t
+ \x665ba998 |  2.5933168e+23 |  2.5933168e+23 | \x665ba998 | t
+ \x743c3324 |  5.9642887e+31 |  5.9642887e+31 | \x743c3324 | t
+ \x47f1205a |       123456.7 |       123456.7 | \x47f1205a | t
+ \x4640e6ae |       12345.67 |       12345.67 | \x4640e6ae | t
+ \x449a5225 |       1234.567 |       1234.567 | \x449a5225 | t
+ \x42f6e9d5 |       123.4567 |       123.4567 | \x42f6e9d5 | t
+ \x414587dd |       12.34567 |       12.34567 | \x414587dd | t
+ \x3f9e064b |       1.234567 |       1.234567 | \x3f9e064b | t
+ \x4c000004 |  3.3554448e+07 |  3.3554448e+07 | \x4c000004 | t
+ \x50061c46 |   8.999999e+09 |   8.999999e+09 | \x50061c46 | t
+ \x510006a8 |  3.4366718e+10 |  3.4366718e+10 | \x510006a8 | t
+ \x48951f84 |      305404.12 |      305404.12 | \x48951f84 | t
+ \x45fd1840 |      8099.0312 |      8099.0312 | \x45fd1840 | t
+ \x39800000 |  0.00024414062 |  0.00024414062 | \x39800000 | t
+ \x3b200000 |   0.0024414062 |   0.0024414062 | \x3b200000 | t
+ \x3b900000 |   0.0043945312 |   0.0043945312 | \x3b900000 | t
+ \x3bd00000 |   0.0063476562 |   0.0063476562 | \x3bd00000 | t
+ \x63800000 |  4.7223665e+21 |  4.7223665e+21 | \x63800000 | t
+ \x4b000000 |   8.388608e+06 |   8.388608e+06 | \x4b000000 | t
+ \x4b800000 |  1.6777216e+07 |  1.6777216e+07 | \x4b800000 | t
+ \x4c000001 |  3.3554436e+07 |  3.3554436e+07 | \x4c000001 | t
+ \x4c800b0d |  6.7131496e+07 |  6.7131496e+07 | \x4c800b0d | t
+ \x00d24584 |  1.9310392e-38 |  1.9310392e-38 | \x00d24584 | t
+ \x800000b0 |      -2.47e-43 |      -2.47e-43 | \x800000b0 | t
+ \x00d90b88 |   1.993244e-38 |   1.993244e-38 | \x00d90b88 | t
+ \x45803f34 |      4103.9004 |      4103.9004 | \x45803f34 | t
+ \x4f9f24f7 |  5.3399997e+09 |  5.3399997e+09 | \x4f9f24f7 | t
+ \x3a8722c3 |   0.0010310042 |   0.0010310042 | \x3a8722c3 | t
+ \x5c800041 |   2.882326e+17 |   2.882326e+17 | \x5c800041 | t
+ \x15ae43fd |   7.038531e-26 |  7.0385313e-26 | \x15ae43fe | f
+ \x5d4cccfb |   9.223404e+17 |   9.223404e+17 | \x5d4cccfb | t
+ \x4c800001 |   6.710887e+07 |   6.710887e+07 | \x4c800001 | t
+ \x57800ed8 |   2.816025e+14 |   2.816025e+14 | \x57800ed8 | t
+ \x5f000000 |   9.223372e+18 |   9.223372e+18 | \x5f000000 | t
+ \x700000f0 |  1.5846086e+29 |  1.5846086e+29 | \x700000f0 | t
+ \x5f23e9ac |  1.1811161e+19 |  1.1811161e+19 | \x5f23e9ac | t
+ \x5e9502f9 |   5.368709e+18 |   5.368709e+18 | \x5e9502f9 | t
+ \x5e8012b1 |  4.6143166e+18 |  4.6143166e+18 | \x5e8012b1 | t
+ \x3c000028 |    0.007812537 |    0.007812537 | \x3c000028 | t
+ \x60cde861 | 1.18697725e+20 | 1.18697725e+20 | \x60cde861 | t
+ \x03aa2a50 | 1.00014165e-36 | 1.00014165e-36 | \x03aa2a50 | t
+ \x43480000 |            200 |            200 | \x43480000 | t
+ \x4c000000 |  3.3554432e+07 |  3.3554432e+07 | \x4c000000 | t
+ \x5d1502f9 |  6.7108864e+17 |  6.7108864e+17 | \x5d1502f9 | t
+ \x5d9502f9 |  1.3421773e+18 |  1.3421773e+18 | \x5d9502f9 | t
+ \x5e1502f9 |  2.6843546e+18 |  2.6843546e+18 | \x5e1502f9 | t
+ \x3f99999a |            1.2 |            1.2 | \x3f99999a | t
+ \x3f9d70a4 |           1.23 |           1.23 | \x3f9d70a4 | t
+ \x3f9df3b6 |          1.234 |          1.234 | \x3f9df3b6 | t
+ \x3f9e0419 |         1.2345 |         1.2345 | \x3f9e0419 | t
+ \x3f9e0610 |        1.23456 |        1.23456 | \x3f9e0610 | t
+ \x3f9e064b |       1.234567 |       1.234567 | \x3f9e064b | t
+ \x3f9e0651 |      1.2345678 |      1.2345678 | \x3f9e0651 | t
+ \x03d20cfe | 1.23456735e-36 | 1.23456735e-36 | \x03d20cfe | t
+(262 rows)
+
+-- clean up, lest opr_sanity complain
+\set VERBOSITY terse
+drop type xfloat4 cascade;
+NOTICE:  drop cascades to 6 other objects
+\set VERBOSITY default
+--
diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out
index 2f47e1c202..dff1921944 100644
--- a/src/test/regress/expected/float4.out
+++ b/src/test/regress/expected/float4.out
@@ -9,21 +9,37 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20');
 INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20');
 -- test for over and under flow
 INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
-ERROR:  value out of range: overflow
+ERROR:  "10e70" is out of range for type real
 LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
                                            ^
 INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
-ERROR:  value out of range: overflow
+ERROR:  "-10e70" is out of range for type real
 LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
                                            ^
 INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
-ERROR:  value out of range: underflow
+ERROR:  "10e-70" is out of range for type real
 LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
                                            ^
 INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
-ERROR:  value out of range: underflow
+ERROR:  "-10e-70" is out of range for type real
 LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
                                            ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e400');
+ERROR:  "10e400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e400');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e400');
+ERROR:  "-10e400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e400');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-400');
+ERROR:  "10e-400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-400');
+                                           ^
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-400');
+ERROR:  "-10e-400" is out of range for type real
+LINE 1: INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-400');
+                                           ^
 -- bad input
 INSERT INTO FLOAT4_TBL(f1) VALUES ('');
 ERROR:  invalid input syntax for type real: ""
@@ -126,22 +142,22 @@ SELECT 'nan'::numeric::float4;
 (1 row)
 
 SELECT '' AS five, * FROM FLOAT4_TBL;
- five |     f1      
-------+-------------
-      |           0
-      |      1004.3
-      |      -34.84
-      | 1.23457e+20
-      | 1.23457e-20
+ five |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e+20
+      | 1.2345679e-20
 (5 rows)
 
 SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <> '1004.3';
- four |     f1      
-------+-------------
-      |           0
-      |      -34.84
-      | 1.23457e+20
-      | 1.23457e-20
+ four |      f1       
+------+---------------
+      |             0
+      |        -34.84
+      | 1.2345679e+20
+      | 1.2345679e-20
 (4 rows)
 
 SELECT '' AS one, f.* FROM FLOAT4_TBL f WHERE f.f1 = '1004.3';
@@ -151,110 +167,110 @@ SELECT '' AS one, f.* FROM FLOAT4_TBL f WHERE f.f1 = '1004.3';
 (1 row)
 
 SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE '1004.3' > f.f1;
- three |     f1      
--------+-------------
-       |           0
-       |      -34.84
-       | 1.23457e-20
+ three |      f1       
+-------+---------------
+       |             0
+       |        -34.84
+       | 1.2345679e-20
 (3 rows)
 
 SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE  f.f1 < '1004.3';
- three |     f1      
--------+-------------
-       |           0
-       |      -34.84
-       | 1.23457e-20
+ three |      f1       
+-------+---------------
+       |             0
+       |        -34.84
+       | 1.2345679e-20
 (3 rows)
 
 SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE '1004.3' >= f.f1;
- four |     f1      
-------+-------------
-      |           0
-      |      1004.3
-      |      -34.84
-      | 1.23457e-20
+ four |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e-20
 (4 rows)
 
 SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE  f.f1 <= '1004.3';
- four |     f1      
-------+-------------
-      |           0
-      |      1004.3
-      |      -34.84
-      | 1.23457e-20
+ four |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e-20
 (4 rows)
 
 SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f
    WHERE f.f1 > '0.0';
- three |     f1      |      x       
--------+-------------+--------------
-       |      1004.3 |       -10043
-       | 1.23457e+20 | -1.23457e+21
-       | 1.23457e-20 | -1.23457e-19
+ three |      f1       |       x        
+-------+---------------+----------------
+       |        1004.3 |         -10043
+       | 1.2345679e+20 | -1.2345678e+21
+       | 1.2345679e-20 | -1.2345678e-19
 (3 rows)
 
 SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f
    WHERE f.f1 > '0.0';
- three |     f1      |      x      
--------+-------------+-------------
-       |      1004.3 |       994.3
-       | 1.23457e+20 | 1.23457e+20
-       | 1.23457e-20 |         -10
+ three |      f1       |       x       
+-------+---------------+---------------
+       |        1004.3 |         994.3
+       | 1.2345679e+20 | 1.2345679e+20
+       | 1.2345679e-20 |           -10
 (3 rows)
 
 SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f
    WHERE f.f1 > '0.0';
- three |     f1      |      x       
--------+-------------+--------------
-       |      1004.3 |      -100.43
-       | 1.23457e+20 | -1.23457e+19
-       | 1.23457e-20 | -1.23457e-21
+ three |      f1       |       x        
+-------+---------------+----------------
+       |        1004.3 |        -100.43
+       | 1.2345679e+20 | -1.2345679e+19
+       | 1.2345679e-20 | -1.2345679e-21
 (3 rows)
 
 SELECT '' AS three, f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f
    WHERE f.f1 > '0.0';
- three |     f1      |      x      
--------+-------------+-------------
-       |      1004.3 |      1014.3
-       | 1.23457e+20 | 1.23457e+20
-       | 1.23457e-20 |          10
+ three |      f1       |       x       
+-------+---------------+---------------
+       |        1004.3 |        1014.3
+       | 1.2345679e+20 | 1.2345679e+20
+       | 1.2345679e-20 |            10
 (3 rows)
 
 -- test divide by zero
 SELECT '' AS bad, f.f1 / '0.0' from FLOAT4_TBL f;
 ERROR:  division by zero
 SELECT '' AS five, * FROM FLOAT4_TBL;
- five |     f1      
-------+-------------
-      |           0
-      |      1004.3
-      |      -34.84
-      | 1.23457e+20
-      | 1.23457e-20
+ five |      f1       
+------+---------------
+      |             0
+      |        1004.3
+      |        -34.84
+      | 1.2345679e+20
+      | 1.2345679e-20
 (5 rows)
 
 -- test the unary float4abs operator
 SELECT '' AS five, f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f;
- five |     f1      |   abs_f1    
-------+-------------+-------------
-      |           0 |           0
-      |      1004.3 |      1004.3
-      |      -34.84 |       34.84
-      | 1.23457e+20 | 1.23457e+20
-      | 1.23457e-20 | 1.23457e-20
+ five |      f1       |    abs_f1     
+------+---------------+---------------
+      |             0 |             0
+      |        1004.3 |        1004.3
+      |        -34.84 |         34.84
+      | 1.2345679e+20 | 1.2345679e+20
+      | 1.2345679e-20 | 1.2345679e-20
 (5 rows)
 
 UPDATE FLOAT4_TBL
    SET f1 = FLOAT4_TBL.f1 * '-1'
    WHERE FLOAT4_TBL.f1 > '0.0';
 SELECT '' AS five, * FROM FLOAT4_TBL;
- five |      f1      
-------+--------------
-      |            0
-      |       -34.84
-      |      -1004.3
-      | -1.23457e+20
-      | -1.23457e-20
+ five |       f1       
+------+----------------
+      |              0
+      |         -34.84
+      |        -1004.3
+      | -1.2345679e+20
+      | -1.2345679e-20
 (5 rows)
 
 -- test edge-case coercions to integer
@@ -306,3 +322,619 @@ SELECT '-9223372036854775808.5'::float4::int8;
 
 SELECT '-9223380000000000000'::float4::int8;
 ERROR:  bigint out of range
+-- Test for correct input rounding in edge cases.
+-- These lists are from Paxson 1991, excluding subnormals and
+-- inputs of over 9 sig. digits.
+SELECT float4send('5e-20'::float4);
+ float4send 
+------------
+ \x1f6c1e4a
+(1 row)
+
+SELECT float4send('67e14'::float4);
+ float4send 
+------------
+ \x59be6cea
+(1 row)
+
+SELECT float4send('985e15'::float4);
+ float4send 
+------------
+ \x5d5ab6c4
+(1 row)
+
+SELECT float4send('55895e-16'::float4);
+ float4send 
+------------
+ \x2cc4a9bd
+(1 row)
+
+SELECT float4send('7038531e-32'::float4);
+ float4send 
+------------
+ \x15ae43fd
+(1 row)
+
+SELECT float4send('702990899e-20'::float4);
+ float4send 
+------------
+ \x2cf757ca
+(1 row)
+
+SELECT float4send('3e-23'::float4);
+ float4send 
+------------
+ \x1a111234
+(1 row)
+
+SELECT float4send('57e18'::float4);
+ float4send 
+------------
+ \x6045c22c
+(1 row)
+
+SELECT float4send('789e-35'::float4);
+ float4send 
+------------
+ \x0a23de70
+(1 row)
+
+SELECT float4send('2539e-18'::float4);
+ float4send 
+------------
+ \x2736f449
+(1 row)
+
+SELECT float4send('76173e28'::float4);
+ float4send 
+------------
+ \x7616398a
+(1 row)
+
+SELECT float4send('887745e-11'::float4);
+ float4send 
+------------
+ \x3714f05c
+(1 row)
+
+SELECT float4send('5382571e-37'::float4);
+ float4send 
+------------
+ \x0d2eaca7
+(1 row)
+
+SELECT float4send('82381273e-35'::float4);
+ float4send 
+------------
+ \x128289d1
+(1 row)
+
+SELECT float4send('750486563e-38'::float4);
+ float4send 
+------------
+ \x0f18377e
+(1 row)
+
+-- Test that the smallest possible normalized input value inputs
+-- correctly, either in 9-significant-digit or shortest-decimal
+-- format.
+--
+-- exact val is             1.1754943508...
+-- shortest val is          1.1754944000
+-- midpoint to next val is  1.1754944208...
+SELECT float4send('1.17549435e-38'::float4);
+ float4send 
+------------
+ \x00800000
+(1 row)
+
+SELECT float4send('1.1754944e-38'::float4);
+ float4send 
+------------
+ \x00800000
+(1 row)
+
+-- test output (and round-trip safety) of various values.
+-- To ensure we're testing what we think we're testing, start with
+-- float values specified by bit patterns (as a useful side effect,
+-- this means we'll fail on non-IEEE platforms).
+create type xfloat4;
+create function xfloat4in(cstring) returns xfloat4 immutable strict
+  language internal as 'int4in';
+NOTICE:  return type xfloat4 is only a shell
+create function xfloat4out(xfloat4) returns cstring immutable strict
+  language internal as 'int4out';
+NOTICE:  argument type xfloat4 is only a shell
+create type xfloat4 (input = xfloat4in, output = xfloat4out, like = float4);
+create cast (xfloat4 as float4) without function;
+create cast (float4 as xfloat4) without function;
+create cast (xfloat4 as integer) without function;
+create cast (integer as xfloat4) without function;
+-- float4: seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
+-- we don't care to assume the platform's strtod() handles subnormals
+-- correctly; those are "use at your own risk". However we do test
+-- subnormal outputs, since those are under our control.
+with testdata(bits) as (values
+  -- small subnormals
+  (x'00000001'),
+  (x'00000002'), (x'00000003'),
+  (x'00000010'), (x'00000011'), (x'00000100'), (x'00000101'),
+  (x'00004000'), (x'00004001'), (x'00080000'), (x'00080001'),
+  -- stress values
+  (x'0053c4f4'),  -- 7693e-42
+  (x'006c85c4'),  -- 996622e-44
+  (x'0041ca76'),  -- 60419369e-46
+  (x'004b7678'),  -- 6930161142e-48
+  -- taken from upstream testsuite
+  (x'00000007'),
+  (x'00424fe2'),
+  -- borderline between subnormal and normal
+  (x'007ffff0'), (x'007ffff1'), (x'007ffffe'), (x'007fffff'))
+select float4send(flt) as ibits,
+       flt
+  from (select bits::integer::xfloat4::float4 as flt
+          from testdata
+	offset 0) s;
+   ibits    |      flt      
+------------+---------------
+ \x00000001 |         1e-45
+ \x00000002 |         3e-45
+ \x00000003 |         4e-45
+ \x00000010 |       2.2e-44
+ \x00000011 |       2.4e-44
+ \x00000100 |      3.59e-43
+ \x00000101 |       3.6e-43
+ \x00004000 |    2.2959e-41
+ \x00004001 |     2.296e-41
+ \x00080000 |   7.34684e-40
+ \x00080001 |   7.34685e-40
+ \x0053c4f4 |     7.693e-39
+ \x006c85c4 |   9.96622e-39
+ \x0041ca76 |  6.041937e-39
+ \x004b7678 |  6.930161e-39
+ \x00000007 |         1e-44
+ \x00424fe2 |    6.0898e-39
+ \x007ffff0 | 1.1754921e-38
+ \x007ffff1 | 1.1754922e-38
+ \x007ffffe | 1.1754941e-38
+ \x007fffff | 1.1754942e-38
+(21 rows)
+
+with testdata(bits) as (values
+  (x'00000000'),
+  -- smallest normal values
+  (x'00800000'), (x'00800001'), (x'00800004'), (x'00800005'),
+  (x'00800006'),
+  -- small normal values chosen for short vs. long output
+  (x'008002f1'), (x'008002f2'), (x'008002f3'),
+  (x'00800e17'), (x'00800e18'), (x'00800e19'),
+  -- assorted values (random mantissae)
+  (x'01000001'), (x'01102843'), (x'01a52c98'),
+  (x'0219c229'), (x'02e4464d'), (x'037343c1'), (x'03a91b36'),
+  (x'047ada65'), (x'0496fe87'), (x'0550844f'), (x'05999da3'),
+  (x'060ea5e2'), (x'06e63c45'), (x'07f1e548'), (x'0fc5282b'),
+  (x'1f850283'), (x'2874a9d6'),
+  -- values around 5e-08
+  (x'3356bf94'), (x'3356bf95'), (x'3356bf96'),
+  -- around 1e-07
+  (x'33d6bf94'), (x'33d6bf95'), (x'33d6bf96'),
+  -- around 3e-07 .. 1e-04
+  (x'34a10faf'), (x'34a10fb0'), (x'34a10fb1'),
+  (x'350637bc'), (x'350637bd'), (x'350637be'),
+  (x'35719786'), (x'35719787'), (x'35719788'),
+  (x'358637bc'), (x'358637bd'), (x'358637be'),
+  (x'36a7c5ab'), (x'36a7c5ac'), (x'36a7c5ad'),
+  (x'3727c5ab'), (x'3727c5ac'), (x'3727c5ad'),
+  -- format crossover at 1e-04
+  (x'38d1b714'), (x'38d1b715'), (x'38d1b716'),
+  (x'38d1b717'), (x'38d1b718'), (x'38d1b719'),
+  (x'38d1b71a'), (x'38d1b71b'), (x'38d1b71c'),
+  (x'38d1b71d'),
+  --
+  (x'38dffffe'), (x'38dfffff'), (x'38e00000'),
+  (x'38efffff'), (x'38f00000'), (x'38f00001'),
+  (x'3a83126e'), (x'3a83126f'), (x'3a831270'),
+  (x'3c23d709'), (x'3c23d70a'), (x'3c23d70b'),
+  (x'3dcccccc'), (x'3dcccccd'), (x'3dccccce'),
+  -- chosen to need 9 digits for 3dcccd70
+  (x'3dcccd6f'), (x'3dcccd70'), (x'3dcccd71'),
+  --
+  (x'3effffff'), (x'3f000000'), (x'3f000001'),
+  (x'3f333332'), (x'3f333333'), (x'3f333334'),
+  -- approach 1.0 with increasing numbers of 9s
+  (x'3f666665'), (x'3f666666'), (x'3f666667'),
+  (x'3f7d70a3'), (x'3f7d70a4'), (x'3f7d70a5'),
+  (x'3f7fbe76'), (x'3f7fbe77'), (x'3f7fbe78'),
+  (x'3f7ff971'), (x'3f7ff972'), (x'3f7ff973'),
+  (x'3f7fff57'), (x'3f7fff58'), (x'3f7fff59'),
+  (x'3f7fffee'), (x'3f7fffef'),
+  -- values very close to 1
+  (x'3f7ffff0'), (x'3f7ffff1'), (x'3f7ffff2'),
+  (x'3f7ffff3'), (x'3f7ffff4'), (x'3f7ffff5'),
+  (x'3f7ffff6'), (x'3f7ffff7'), (x'3f7ffff8'),
+  (x'3f7ffff9'), (x'3f7ffffa'), (x'3f7ffffb'),
+  (x'3f7ffffc'), (x'3f7ffffd'), (x'3f7ffffe'),
+  (x'3f7fffff'),
+  (x'3f800000'),
+  (x'3f800001'), (x'3f800002'), (x'3f800003'),
+  (x'3f800004'), (x'3f800005'), (x'3f800006'),
+  (x'3f800007'), (x'3f800008'), (x'3f800009'),
+  -- values 1 to 1.1
+  (x'3f80000f'), (x'3f800010'), (x'3f800011'),
+  (x'3f800012'), (x'3f800013'), (x'3f800014'),
+  (x'3f800017'), (x'3f800018'), (x'3f800019'),
+  (x'3f80001a'), (x'3f80001b'), (x'3f80001c'),
+  (x'3f800029'), (x'3f80002a'), (x'3f80002b'),
+  (x'3f800053'), (x'3f800054'), (x'3f800055'),
+  (x'3f800346'), (x'3f800347'), (x'3f800348'),
+  (x'3f8020c4'), (x'3f8020c5'), (x'3f8020c6'),
+  (x'3f8147ad'), (x'3f8147ae'), (x'3f8147af'),
+  (x'3f8ccccc'), (x'3f8ccccd'), (x'3f8cccce'),
+  --
+  (x'3fc90fdb'), -- pi/2
+  (x'402df854'), -- e
+  (x'40490fdb'), -- pi
+  --
+  (x'409fffff'), (x'40a00000'), (x'40a00001'),
+  (x'40afffff'), (x'40b00000'), (x'40b00001'),
+  (x'411fffff'), (x'41200000'), (x'41200001'),
+  (x'42c7ffff'), (x'42c80000'), (x'42c80001'),
+  (x'4479ffff'), (x'447a0000'), (x'447a0001'),
+  (x'461c3fff'), (x'461c4000'), (x'461c4001'),
+  (x'47c34fff'), (x'47c35000'), (x'47c35001'),
+  (x'497423ff'), (x'49742400'), (x'49742401'),
+  (x'4b18967f'), (x'4b189680'), (x'4b189681'),
+  (x'4cbebc1f'), (x'4cbebc20'), (x'4cbebc21'),
+  (x'4e6e6b27'), (x'4e6e6b28'), (x'4e6e6b29'),
+  (x'501502f8'), (x'501502f9'), (x'501502fa'),
+  (x'51ba43b6'), (x'51ba43b7'), (x'51ba43b8'),
+  -- stress values
+  (x'1f6c1e4a'),  -- 5e-20
+  (x'59be6cea'),  -- 67e14
+  (x'5d5ab6c4'),  -- 985e15
+  (x'2cc4a9bd'),  -- 55895e-16
+  (x'15ae43fd'),  -- 7038531e-32
+  (x'2cf757ca'),  -- 702990899e-20
+  (x'665ba998'),  -- 25933168707e13
+  (x'743c3324'),  -- 596428896559e20
+  -- exercise fixed-point memmoves
+  (x'47f1205a'),
+  (x'4640e6ae'),
+  (x'449a5225'),
+  (x'42f6e9d5'),
+  (x'414587dd'),
+  (x'3f9e064b'),
+  -- these cases come from the upstream's testsuite
+  -- BoundaryRoundEven
+  (x'4c000004'),
+  (x'50061c46'),
+  (x'510006a8'),
+  -- ExactValueRoundEven
+  (x'48951f84'),
+  (x'45fd1840'),
+  -- LotsOfTrailingZeros
+  (x'39800000'),
+  (x'3b200000'),
+  (x'3b900000'),
+  (x'3bd00000'),
+  -- Regression
+  (x'63800000'),
+  (x'4b000000'),
+  (x'4b800000'),
+  (x'4c000001'),
+  (x'4c800b0d'),
+  (x'00d24584'),
+  (x'800000b0'),
+  (x'00d90b88'),
+  (x'45803f34'),
+  (x'4f9f24f7'),
+  (x'3a8722c3'),
+  (x'5c800041'),
+  (x'15ae43fd'),
+  (x'5d4cccfb'),
+  (x'4c800001'),
+  (x'57800ed8'),
+  (x'5f000000'),
+  (x'700000f0'),
+  (x'5f23e9ac'),
+  (x'5e9502f9'),
+  (x'5e8012b1'),
+  (x'3c000028'),
+  (x'60cde861'),
+  (x'03aa2a50'),
+  (x'43480000'),
+  (x'4c000000'),
+  -- LooksLikePow5
+  (x'5D1502F9'),
+  (x'5D9502F9'),
+  (x'5E1502F9'),
+  -- OutputLength
+  (x'3f99999a'),
+  (x'3f9d70a4'),
+  (x'3f9df3b6'),
+  (x'3f9e0419'),
+  (x'3f9e0610'),
+  (x'3f9e064b'),
+  (x'3f9e0651'),
+  (x'03d20cfe')
+)
+select float4send(flt) as ibits,
+       flt,
+       flt::text::float4 as r_flt,
+       float4send(flt::text::float4) as obits,
+       float4send(flt::text::float4) = float4send(flt) as correct
+  from (select bits::integer::xfloat4::float4 as flt
+          from testdata
+	offset 0) s;
+   ibits    |      flt       |     r_flt      |   obits    | correct 
+------------+----------------+----------------+------------+---------
+ \x00000000 |              0 |              0 | \x00000000 | t
+ \x00800000 |  1.1754944e-38 |  1.1754944e-38 | \x00800000 | t
+ \x00800001 |  1.1754945e-38 |  1.1754945e-38 | \x00800001 | t
+ \x00800004 |  1.1754949e-38 |  1.1754949e-38 | \x00800004 | t
+ \x00800005 |   1.175495e-38 |   1.175495e-38 | \x00800005 | t
+ \x00800006 |  1.1754952e-38 |  1.1754952e-38 | \x00800006 | t
+ \x008002f1 |  1.1755999e-38 |  1.1755999e-38 | \x008002f1 | t
+ \x008002f2 |     1.1756e-38 |     1.1756e-38 | \x008002f2 | t
+ \x008002f3 |  1.1756001e-38 |  1.1756001e-38 | \x008002f3 | t
+ \x00800e17 |  1.1759998e-38 |  1.1759998e-38 | \x00800e17 | t
+ \x00800e18 |      1.176e-38 |      1.176e-38 | \x00800e18 | t
+ \x00800e19 |  1.1760001e-38 |  1.1760001e-38 | \x00800e19 | t
+ \x01000001 |   2.350989e-38 |   2.350989e-38 | \x01000001 | t
+ \x01102843 |   2.647751e-38 |   2.647751e-38 | \x01102843 | t
+ \x01a52c98 |  6.0675416e-38 |  6.0675416e-38 | \x01a52c98 | t
+ \x0219c229 |  1.1296386e-37 |  1.1296386e-37 | \x0219c229 | t
+ \x02e4464d |   3.354194e-37 |   3.354194e-37 | \x02e4464d | t
+ \x037343c1 |   7.148906e-37 |   7.148906e-37 | \x037343c1 | t
+ \x03a91b36 |   9.939175e-37 |   9.939175e-37 | \x03a91b36 | t
+ \x047ada65 |   2.948764e-36 |   2.948764e-36 | \x047ada65 | t
+ \x0496fe87 |  3.5498577e-36 |  3.5498577e-36 | \x0496fe87 | t
+ \x0550844f |   9.804414e-36 |   9.804414e-36 | \x0550844f | t
+ \x05999da3 |  1.4445957e-35 |  1.4445957e-35 | \x05999da3 | t
+ \x060ea5e2 |  2.6829103e-35 |  2.6829103e-35 | \x060ea5e2 | t
+ \x06e63c45 |   8.660494e-35 |   8.660494e-35 | \x06e63c45 | t
+ \x07f1e548 |   3.639641e-34 |   3.639641e-34 | \x07f1e548 | t
+ \x0fc5282b |  1.9441172e-29 |  1.9441172e-29 | \x0fc5282b | t
+ \x1f850283 |  5.6331846e-20 |  5.6331846e-20 | \x1f850283 | t
+ \x2874a9d6 |  1.3581548e-14 |  1.3581548e-14 | \x2874a9d6 | t
+ \x3356bf94 |  4.9999997e-08 |  4.9999997e-08 | \x3356bf94 | t
+ \x3356bf95 |          5e-08 |          5e-08 | \x3356bf95 | t
+ \x3356bf96 |  5.0000004e-08 |  5.0000004e-08 | \x3356bf96 | t
+ \x33d6bf94 |  9.9999994e-08 |  9.9999994e-08 | \x33d6bf94 | t
+ \x33d6bf95 |          1e-07 |          1e-07 | \x33d6bf95 | t
+ \x33d6bf96 |  1.0000001e-07 |  1.0000001e-07 | \x33d6bf96 | t
+ \x34a10faf |  2.9999998e-07 |  2.9999998e-07 | \x34a10faf | t
+ \x34a10fb0 |          3e-07 |          3e-07 | \x34a10fb0 | t
+ \x34a10fb1 |  3.0000004e-07 |  3.0000004e-07 | \x34a10fb1 | t
+ \x350637bc |  4.9999994e-07 |  4.9999994e-07 | \x350637bc | t
+ \x350637bd |          5e-07 |          5e-07 | \x350637bd | t
+ \x350637be |  5.0000006e-07 |  5.0000006e-07 | \x350637be | t
+ \x35719786 |   8.999999e-07 |   8.999999e-07 | \x35719786 | t
+ \x35719787 |          9e-07 |          9e-07 | \x35719787 | t
+ \x35719788 |  9.0000003e-07 |  9.0000003e-07 | \x35719788 | t
+ \x358637bc |   9.999999e-07 |   9.999999e-07 | \x358637bc | t
+ \x358637bd |          1e-06 |          1e-06 | \x358637bd | t
+ \x358637be |  1.0000001e-06 |  1.0000001e-06 | \x358637be | t
+ \x36a7c5ab |  4.9999994e-06 |  4.9999994e-06 | \x36a7c5ab | t
+ \x36a7c5ac |          5e-06 |          5e-06 | \x36a7c5ac | t
+ \x36a7c5ad |  5.0000003e-06 |  5.0000003e-06 | \x36a7c5ad | t
+ \x3727c5ab |   9.999999e-06 |   9.999999e-06 | \x3727c5ab | t
+ \x3727c5ac |          1e-05 |          1e-05 | \x3727c5ac | t
+ \x3727c5ad |  1.0000001e-05 |  1.0000001e-05 | \x3727c5ad | t
+ \x38d1b714 |  9.9999976e-05 |  9.9999976e-05 | \x38d1b714 | t
+ \x38d1b715 |   9.999998e-05 |   9.999998e-05 | \x38d1b715 | t
+ \x38d1b716 |   9.999999e-05 |   9.999999e-05 | \x38d1b716 | t
+ \x38d1b717 |         0.0001 |         0.0001 | \x38d1b717 | t
+ \x38d1b718 | 0.000100000005 | 0.000100000005 | \x38d1b718 | t
+ \x38d1b719 |  0.00010000001 |  0.00010000001 | \x38d1b719 | t
+ \x38d1b71a |  0.00010000002 |  0.00010000002 | \x38d1b71a | t
+ \x38d1b71b |  0.00010000003 |  0.00010000003 | \x38d1b71b | t
+ \x38d1b71c | 0.000100000034 | 0.000100000034 | \x38d1b71c | t
+ \x38d1b71d |  0.00010000004 |  0.00010000004 | \x38d1b71d | t
+ \x38dffffe |  0.00010681151 |  0.00010681151 | \x38dffffe | t
+ \x38dfffff | 0.000106811516 | 0.000106811516 | \x38dfffff | t
+ \x38e00000 |  0.00010681152 |  0.00010681152 | \x38e00000 | t
+ \x38efffff |  0.00011444091 |  0.00011444091 | \x38efffff | t
+ \x38f00000 |  0.00011444092 |  0.00011444092 | \x38f00000 | t
+ \x38f00001 | 0.000114440925 | 0.000114440925 | \x38f00001 | t
+ \x3a83126e |   0.0009999999 |   0.0009999999 | \x3a83126e | t
+ \x3a83126f |          0.001 |          0.001 | \x3a83126f | t
+ \x3a831270 |   0.0010000002 |   0.0010000002 | \x3a831270 | t
+ \x3c23d709 |    0.009999999 |    0.009999999 | \x3c23d709 | t
+ \x3c23d70a |           0.01 |           0.01 | \x3c23d70a | t
+ \x3c23d70b |    0.010000001 |    0.010000001 | \x3c23d70b | t
+ \x3dcccccc |    0.099999994 |    0.099999994 | \x3dcccccc | t
+ \x3dcccccd |            0.1 |            0.1 | \x3dcccccd | t
+ \x3dccccce |     0.10000001 |     0.10000001 | \x3dccccce | t
+ \x3dcccd6f |     0.10000121 |     0.10000121 | \x3dcccd6f | t
+ \x3dcccd70 |    0.100001216 |    0.100001216 | \x3dcccd70 | t
+ \x3dcccd71 |     0.10000122 |     0.10000122 | \x3dcccd71 | t
+ \x3effffff |     0.49999997 |     0.49999997 | \x3effffff | t
+ \x3f000000 |            0.5 |            0.5 | \x3f000000 | t
+ \x3f000001 |     0.50000006 |     0.50000006 | \x3f000001 | t
+ \x3f333332 |      0.6999999 |      0.6999999 | \x3f333332 | t
+ \x3f333333 |            0.7 |            0.7 | \x3f333333 | t
+ \x3f333334 |     0.70000005 |     0.70000005 | \x3f333334 | t
+ \x3f666665 |      0.8999999 |      0.8999999 | \x3f666665 | t
+ \x3f666666 |            0.9 |            0.9 | \x3f666666 | t
+ \x3f666667 |     0.90000004 |     0.90000004 | \x3f666667 | t
+ \x3f7d70a3 |     0.98999995 |     0.98999995 | \x3f7d70a3 | t
+ \x3f7d70a4 |           0.99 |           0.99 | \x3f7d70a4 | t
+ \x3f7d70a5 |     0.99000007 |     0.99000007 | \x3f7d70a5 | t
+ \x3f7fbe76 |     0.99899995 |     0.99899995 | \x3f7fbe76 | t
+ \x3f7fbe77 |          0.999 |          0.999 | \x3f7fbe77 | t
+ \x3f7fbe78 |      0.9990001 |      0.9990001 | \x3f7fbe78 | t
+ \x3f7ff971 |      0.9998999 |      0.9998999 | \x3f7ff971 | t
+ \x3f7ff972 |         0.9999 |         0.9999 | \x3f7ff972 | t
+ \x3f7ff973 |     0.99990004 |     0.99990004 | \x3f7ff973 | t
+ \x3f7fff57 |      0.9999899 |      0.9999899 | \x3f7fff57 | t
+ \x3f7fff58 |        0.99999 |        0.99999 | \x3f7fff58 | t
+ \x3f7fff59 |     0.99999005 |     0.99999005 | \x3f7fff59 | t
+ \x3f7fffee |      0.9999989 |      0.9999989 | \x3f7fffee | t
+ \x3f7fffef |       0.999999 |       0.999999 | \x3f7fffef | t
+ \x3f7ffff0 |     0.99999905 |     0.99999905 | \x3f7ffff0 | t
+ \x3f7ffff1 |      0.9999991 |      0.9999991 | \x3f7ffff1 | t
+ \x3f7ffff2 |     0.99999917 |     0.99999917 | \x3f7ffff2 | t
+ \x3f7ffff3 |      0.9999992 |      0.9999992 | \x3f7ffff3 | t
+ \x3f7ffff4 |      0.9999993 |      0.9999993 | \x3f7ffff4 | t
+ \x3f7ffff5 |     0.99999934 |     0.99999934 | \x3f7ffff5 | t
+ \x3f7ffff6 |      0.9999994 |      0.9999994 | \x3f7ffff6 | t
+ \x3f7ffff7 |     0.99999946 |     0.99999946 | \x3f7ffff7 | t
+ \x3f7ffff8 |      0.9999995 |      0.9999995 | \x3f7ffff8 | t
+ \x3f7ffff9 |      0.9999996 |      0.9999996 | \x3f7ffff9 | t
+ \x3f7ffffa |     0.99999964 |     0.99999964 | \x3f7ffffa | t
+ \x3f7ffffb |      0.9999997 |      0.9999997 | \x3f7ffffb | t
+ \x3f7ffffc |     0.99999976 |     0.99999976 | \x3f7ffffc | t
+ \x3f7ffffd |      0.9999998 |      0.9999998 | \x3f7ffffd | t
+ \x3f7ffffe |      0.9999999 |      0.9999999 | \x3f7ffffe | t
+ \x3f7fffff |     0.99999994 |     0.99999994 | \x3f7fffff | t
+ \x3f800000 |              1 |              1 | \x3f800000 | t
+ \x3f800001 |      1.0000001 |      1.0000001 | \x3f800001 | t
+ \x3f800002 |      1.0000002 |      1.0000002 | \x3f800002 | t
+ \x3f800003 |      1.0000004 |      1.0000004 | \x3f800003 | t
+ \x3f800004 |      1.0000005 |      1.0000005 | \x3f800004 | t
+ \x3f800005 |      1.0000006 |      1.0000006 | \x3f800005 | t
+ \x3f800006 |      1.0000007 |      1.0000007 | \x3f800006 | t
+ \x3f800007 |      1.0000008 |      1.0000008 | \x3f800007 | t
+ \x3f800008 |       1.000001 |       1.000001 | \x3f800008 | t
+ \x3f800009 |      1.0000011 |      1.0000011 | \x3f800009 | t
+ \x3f80000f |      1.0000018 |      1.0000018 | \x3f80000f | t
+ \x3f800010 |      1.0000019 |      1.0000019 | \x3f800010 | t
+ \x3f800011 |       1.000002 |       1.000002 | \x3f800011 | t
+ \x3f800012 |      1.0000021 |      1.0000021 | \x3f800012 | t
+ \x3f800013 |      1.0000023 |      1.0000023 | \x3f800013 | t
+ \x3f800014 |      1.0000024 |      1.0000024 | \x3f800014 | t
+ \x3f800017 |      1.0000027 |      1.0000027 | \x3f800017 | t
+ \x3f800018 |      1.0000029 |      1.0000029 | \x3f800018 | t
+ \x3f800019 |       1.000003 |       1.000003 | \x3f800019 | t
+ \x3f80001a |      1.0000031 |      1.0000031 | \x3f80001a | t
+ \x3f80001b |      1.0000032 |      1.0000032 | \x3f80001b | t
+ \x3f80001c |      1.0000033 |      1.0000033 | \x3f80001c | t
+ \x3f800029 |      1.0000049 |      1.0000049 | \x3f800029 | t
+ \x3f80002a |       1.000005 |       1.000005 | \x3f80002a | t
+ \x3f80002b |      1.0000051 |      1.0000051 | \x3f80002b | t
+ \x3f800053 |      1.0000099 |      1.0000099 | \x3f800053 | t
+ \x3f800054 |        1.00001 |        1.00001 | \x3f800054 | t
+ \x3f800055 |      1.0000101 |      1.0000101 | \x3f800055 | t
+ \x3f800346 |      1.0000999 |      1.0000999 | \x3f800346 | t
+ \x3f800347 |         1.0001 |         1.0001 | \x3f800347 | t
+ \x3f800348 |      1.0001001 |      1.0001001 | \x3f800348 | t
+ \x3f8020c4 |      1.0009999 |      1.0009999 | \x3f8020c4 | t
+ \x3f8020c5 |          1.001 |          1.001 | \x3f8020c5 | t
+ \x3f8020c6 |      1.0010002 |      1.0010002 | \x3f8020c6 | t
+ \x3f8147ad |      1.0099999 |      1.0099999 | \x3f8147ad | t
+ \x3f8147ae |           1.01 |           1.01 | \x3f8147ae | t
+ \x3f8147af |      1.0100001 |      1.0100001 | \x3f8147af | t
+ \x3f8ccccc |      1.0999999 |      1.0999999 | \x3f8ccccc | t
+ \x3f8ccccd |            1.1 |            1.1 | \x3f8ccccd | t
+ \x3f8cccce |      1.1000001 |      1.1000001 | \x3f8cccce | t
+ \x3fc90fdb |      1.5707964 |      1.5707964 | \x3fc90fdb | t
+ \x402df854 |      2.7182817 |      2.7182817 | \x402df854 | t
+ \x40490fdb |      3.1415927 |      3.1415927 | \x40490fdb | t
+ \x409fffff |      4.9999995 |      4.9999995 | \x409fffff | t
+ \x40a00000 |              5 |              5 | \x40a00000 | t
+ \x40a00001 |      5.0000005 |      5.0000005 | \x40a00001 | t
+ \x40afffff |      5.4999995 |      5.4999995 | \x40afffff | t
+ \x40b00000 |            5.5 |            5.5 | \x40b00000 | t
+ \x40b00001 |      5.5000005 |      5.5000005 | \x40b00001 | t
+ \x411fffff |       9.999999 |       9.999999 | \x411fffff | t
+ \x41200000 |             10 |             10 | \x41200000 | t
+ \x41200001 |      10.000001 |      10.000001 | \x41200001 | t
+ \x42c7ffff |       99.99999 |       99.99999 | \x42c7ffff | t
+ \x42c80000 |            100 |            100 | \x42c80000 | t
+ \x42c80001 |      100.00001 |      100.00001 | \x42c80001 | t
+ \x4479ffff |      999.99994 |      999.99994 | \x4479ffff | t
+ \x447a0000 |           1000 |           1000 | \x447a0000 | t
+ \x447a0001 |     1000.00006 |     1000.00006 | \x447a0001 | t
+ \x461c3fff |       9999.999 |       9999.999 | \x461c3fff | t
+ \x461c4000 |          10000 |          10000 | \x461c4000 | t
+ \x461c4001 |      10000.001 |      10000.001 | \x461c4001 | t
+ \x47c34fff |       99999.99 |       99999.99 | \x47c34fff | t
+ \x47c35000 |         100000 |         100000 | \x47c35000 | t
+ \x47c35001 |      100000.01 |      100000.01 | \x47c35001 | t
+ \x497423ff |      999999.94 |      999999.94 | \x497423ff | t
+ \x49742400 |          1e+06 |          1e+06 | \x49742400 | t
+ \x49742401 | 1.00000006e+06 | 1.00000006e+06 | \x49742401 | t
+ \x4b18967f |   9.999999e+06 |   9.999999e+06 | \x4b18967f | t
+ \x4b189680 |          1e+07 |          1e+07 | \x4b189680 | t
+ \x4b189681 |  1.0000001e+07 |  1.0000001e+07 | \x4b189681 | t
+ \x4cbebc1f |   9.999999e+07 |   9.999999e+07 | \x4cbebc1f | t
+ \x4cbebc20 |          1e+08 |          1e+08 | \x4cbebc20 | t
+ \x4cbebc21 |  1.0000001e+08 |  1.0000001e+08 | \x4cbebc21 | t
+ \x4e6e6b27 |  9.9999994e+08 |  9.9999994e+08 | \x4e6e6b27 | t
+ \x4e6e6b28 |          1e+09 |          1e+09 | \x4e6e6b28 | t
+ \x4e6e6b29 | 1.00000006e+09 | 1.00000006e+09 | \x4e6e6b29 | t
+ \x501502f8 |   9.999999e+09 |   9.999999e+09 | \x501502f8 | t
+ \x501502f9 |          1e+10 |          1e+10 | \x501502f9 | t
+ \x501502fa |  1.0000001e+10 |  1.0000001e+10 | \x501502fa | t
+ \x51ba43b6 |   9.999999e+10 |   9.999999e+10 | \x51ba43b6 | t
+ \x51ba43b7 |          1e+11 |          1e+11 | \x51ba43b7 | t
+ \x51ba43b8 |  1.0000001e+11 |  1.0000001e+11 | \x51ba43b8 | t
+ \x1f6c1e4a |          5e-20 |          5e-20 | \x1f6c1e4a | t
+ \x59be6cea |        6.7e+15 |        6.7e+15 | \x59be6cea | t
+ \x5d5ab6c4 |       9.85e+17 |       9.85e+17 | \x5d5ab6c4 | t
+ \x2cc4a9bd |     5.5895e-12 |     5.5895e-12 | \x2cc4a9bd | t
+ \x15ae43fd |   7.038531e-26 |   7.038531e-26 | \x15ae43fd | t
+ \x2cf757ca |  7.0299088e-12 |  7.0299088e-12 | \x2cf757ca | t
+ \x665ba998 |  2.5933168e+23 |  2.5933168e+23 | \x665ba998 | t
+ \x743c3324 |  5.9642887e+31 |  5.9642887e+31 | \x743c3324 | t
+ \x47f1205a |       123456.7 |       123456.7 | \x47f1205a | t
+ \x4640e6ae |       12345.67 |       12345.67 | \x4640e6ae | t
+ \x449a5225 |       1234.567 |       1234.567 | \x449a5225 | t
+ \x42f6e9d5 |       123.4567 |       123.4567 | \x42f6e9d5 | t
+ \x414587dd |       12.34567 |       12.34567 | \x414587dd | t
+ \x3f9e064b |       1.234567 |       1.234567 | \x3f9e064b | t
+ \x4c000004 |  3.3554448e+07 |  3.3554448e+07 | \x4c000004 | t
+ \x50061c46 |   8.999999e+09 |   8.999999e+09 | \x50061c46 | t
+ \x510006a8 |  3.4366718e+10 |  3.4366718e+10 | \x510006a8 | t
+ \x48951f84 |      305404.12 |      305404.12 | \x48951f84 | t
+ \x45fd1840 |      8099.0312 |      8099.0312 | \x45fd1840 | t
+ \x39800000 |  0.00024414062 |  0.00024414062 | \x39800000 | t
+ \x3b200000 |   0.0024414062 |   0.0024414062 | \x3b200000 | t
+ \x3b900000 |   0.0043945312 |   0.0043945312 | \x3b900000 | t
+ \x3bd00000 |   0.0063476562 |   0.0063476562 | \x3bd00000 | t
+ \x63800000 |  4.7223665e+21 |  4.7223665e+21 | \x63800000 | t
+ \x4b000000 |   8.388608e+06 |   8.388608e+06 | \x4b000000 | t
+ \x4b800000 |  1.6777216e+07 |  1.6777216e+07 | \x4b800000 | t
+ \x4c000001 |  3.3554436e+07 |  3.3554436e+07 | \x4c000001 | t
+ \x4c800b0d |  6.7131496e+07 |  6.7131496e+07 | \x4c800b0d | t
+ \x00d24584 |  1.9310392e-38 |  1.9310392e-38 | \x00d24584 | t
+ \x800000b0 |      -2.47e-43 |      -2.47e-43 | \x800000b0 | t
+ \x00d90b88 |   1.993244e-38 |   1.993244e-38 | \x00d90b88 | t
+ \x45803f34 |      4103.9004 |      4103.9004 | \x45803f34 | t
+ \x4f9f24f7 |  5.3399997e+09 |  5.3399997e+09 | \x4f9f24f7 | t
+ \x3a8722c3 |   0.0010310042 |   0.0010310042 | \x3a8722c3 | t
+ \x5c800041 |   2.882326e+17 |   2.882326e+17 | \x5c800041 | t
+ \x15ae43fd |   7.038531e-26 |   7.038531e-26 | \x15ae43fd | t
+ \x5d4cccfb |   9.223404e+17 |   9.223404e+17 | \x5d4cccfb | t
+ \x4c800001 |   6.710887e+07 |   6.710887e+07 | \x4c800001 | t
+ \x57800ed8 |   2.816025e+14 |   2.816025e+14 | \x57800ed8 | t
+ \x5f000000 |   9.223372e+18 |   9.223372e+18 | \x5f000000 | t
+ \x700000f0 |  1.5846086e+29 |  1.5846086e+29 | \x700000f0 | t
+ \x5f23e9ac |  1.1811161e+19 |  1.1811161e+19 | \x5f23e9ac | t
+ \x5e9502f9 |   5.368709e+18 |   5.368709e+18 | \x5e9502f9 | t
+ \x5e8012b1 |  4.6143166e+18 |  4.6143166e+18 | \x5e8012b1 | t
+ \x3c000028 |    0.007812537 |    0.007812537 | \x3c000028 | t
+ \x60cde861 | 1.18697725e+20 | 1.18697725e+20 | \x60cde861 | t
+ \x03aa2a50 | 1.00014165e-36 | 1.00014165e-36 | \x03aa2a50 | t
+ \x43480000 |            200 |            200 | \x43480000 | t
+ \x4c000000 |  3.3554432e+07 |  3.3554432e+07 | \x4c000000 | t
+ \x5d1502f9 |  6.7108864e+17 |  6.7108864e+17 | \x5d1502f9 | t
+ \x5d9502f9 |  1.3421773e+18 |  1.3421773e+18 | \x5d9502f9 | t
+ \x5e1502f9 |  2.6843546e+18 |  2.6843546e+18 | \x5e1502f9 | t
+ \x3f99999a |            1.2 |            1.2 | \x3f99999a | t
+ \x3f9d70a4 |           1.23 |           1.23 | \x3f9d70a4 | t
+ \x3f9df3b6 |          1.234 |          1.234 | \x3f9df3b6 | t
+ \x3f9e0419 |         1.2345 |         1.2345 | \x3f9e0419 | t
+ \x3f9e0610 |        1.23456 |        1.23456 | \x3f9e0610 | t
+ \x3f9e064b |       1.234567 |       1.234567 | \x3f9e064b | t
+ \x3f9e0651 |      1.2345678 |      1.2345678 | \x3f9e0651 | t
+ \x03d20cfe | 1.23456735e-36 | 1.23456735e-36 | \x03d20cfe | t
+(262 rows)
+
+-- clean up, lest opr_sanity complain
+\set VERBOSITY terse
+drop type xfloat4 cascade;
+NOTICE:  drop cascades to 6 other objects
+\set VERBOSITY default
+--
diff --git a/src/test/regress/expected/float8-small-is-zero.out b/src/test/regress/expected/float8-small-is-zero.out
index 1c3bbae6b8..f67c22e9fa 100644
--- a/src/test/regress/expected/float8-small-is-zero.out
+++ b/src/test/regress/expected/float8-small-is-zero.out
@@ -28,6 +28,13 @@ SELECT '-10e-400'::float8;
      -0
 (1 row)
 
+-- test smallest normalized input
+SELECT float8send('2.2250738585072014E-308'::float8);
+     float8send     
+--------------------
+ \x0010000000000000
+(1 row)
+
 -- bad input
 INSERT INTO FLOAT8_TBL(f1) VALUES ('');
 ERROR:  invalid input syntax for type double precision: ""
@@ -213,7 +220,7 @@ SELECT '' AS three, f.f1, f.f1 / '-10' AS x
    WHERE f.f1 > '0.0';
  three |          f1          |           x           
 -------+----------------------+-----------------------
-       |               1004.3 |               -100.43
+       |               1004.3 |   -100.42999999999999
        | 1.2345678901234e+200 | -1.2345678901234e+199
        | 1.2345678901234e-200 | -1.2345678901234e-201
 (3 rows)
@@ -230,9 +237,9 @@ SELECT '' AS three, f.f1, f.f1 - '-10' AS x
 
 SELECT '' AS one, f.f1 ^ '2.0' AS square_f1
    FROM FLOAT8_TBL f where f.f1 = '1004.3';
- one | square_f1  
------+------------
-     | 1008618.49
+ one |     square_f1      
+-----+--------------------
+     | 1008618.4899999999
 (1 row)
 
 -- absolute value
@@ -314,6 +321,8 @@ select sign(f1) as sign_f1 from float8_tbl f;
        1
 (5 rows)
 
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
 -- square root
 SELECT sqrt(float8 '64') AS eight;
  eight 
@@ -449,6 +458,7 @@ SELECT '' AS five, * FROM FLOAT8_TBL;
       | -1.2345678901234e-200
 (5 rows)
 
+RESET extra_float_digits;
 -- test for over- and underflow
 INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
 ERROR:  "10e400" is out of range for type double precision
@@ -528,7 +538,6 @@ SELECT '-9223372036854775808.5'::float8::int8;
 SELECT '-9223372036854780000'::float8::int8;
 ERROR:  bigint out of range
 -- test exact cases for trigonometric functions in degrees
-SET extra_float_digits = 3;
 SELECT x,
        sind(x),
        sind(x) IN (-1,-0.5,0,0.5,1) AS sind_exact
@@ -630,4 +639,432 @@ FROM (SELECT 10*cosd(a), 10*sind(a)
   10 |   0 |      0 | t
 (5 rows)
 
-RESET extra_float_digits;
+--
+-- test output (and round-trip safety) of various values.
+-- To ensure we're testing what we think we're testing, start with
+-- float values specified by bit patterns (as a useful side effect,
+-- this means we'll fail on non-IEEE platforms).
+create type xfloat8;
+create function xfloat8in(cstring) returns xfloat8 immutable strict
+  language internal as 'int8in';
+NOTICE:  return type xfloat8 is only a shell
+create function xfloat8out(xfloat8) returns cstring immutable strict
+  language internal as 'int8out';
+NOTICE:  argument type xfloat8 is only a shell
+create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8);
+create cast (xfloat8 as float8) without function;
+create cast (float8 as xfloat8) without function;
+create cast (xfloat8 as bigint) without function;
+create cast (bigint as xfloat8) without function;
+-- float8: seeeeeee eeeeeeee eeeeeeee mmmmmmmm mmmmmmmm(x4)
+-- we don't care to assume the platform's strtod() handles subnormals
+-- correctly; those are "use at your own risk". However we do test
+-- subnormal outputs, since those are under our control.
+with testdata(bits) as (values
+  -- small subnormals
+  (x'0000000000000001'),
+  (x'0000000000000002'), (x'0000000000000003'),
+  (x'0000000000001000'), (x'0000000100000000'),
+  (x'0000010000000000'), (x'0000010100000000'),
+  (x'0000400000000000'), (x'0000400100000000'),
+  (x'0000800000000000'), (x'0000800000000001'),
+  -- these values taken from upstream testsuite
+  (x'00000000000f4240'),
+  (x'00000000016e3600'),
+  (x'0000008cdcdea440'),
+  -- borderline between subnormal and normal
+  (x'000ffffffffffff0'), (x'000ffffffffffff1'),
+  (x'000ffffffffffffe'), (x'000fffffffffffff'))
+select float8send(flt) as ibits,
+       flt
+  from (select bits::bigint::xfloat8::float8 as flt
+          from testdata
+	offset 0) s;
+       ibits        |           flt           
+--------------------+-------------------------
+ \x0000000000000001 |                  5e-324
+ \x0000000000000002 |                  1e-323
+ \x0000000000000003 |                1.5e-323
+ \x0000000000001000 |             2.0237e-320
+ \x0000000100000000 |        2.121995791e-314
+ \x0000010000000000 |      5.43230922487e-312
+ \x0000010100000000 |      5.45352918278e-312
+ \x0000400000000000 |    3.4766779039175e-310
+ \x0000400100000000 |    3.4768901034966e-310
+ \x0000800000000000 |     6.953355807835e-310
+ \x0000800000000001 |   6.95335580783505e-310
+ \x00000000000f4240 |           4.940656e-318
+ \x00000000016e3600 |         1.18575755e-316
+ \x0000008cdcdea440 |     2.989102097996e-312
+ \x000ffffffffffff0 | 2.2250738585071935e-308
+ \x000ffffffffffff1 |  2.225073858507194e-308
+ \x000ffffffffffffe | 2.2250738585072004e-308
+ \x000fffffffffffff |  2.225073858507201e-308
+(18 rows)
+
+-- round-trip tests
+with testdata(bits) as (values
+  (x'0000000000000000'),
+  -- smallest normal values
+  (x'0010000000000000'), (x'0010000000000001'),
+  (x'0010000000000002'), (x'0018000000000000'),
+  --
+  (x'3ddb7cdfd9d7bdba'), (x'3ddb7cdfd9d7bdbb'), (x'3ddb7cdfd9d7bdbc'),
+  (x'3e112e0be826d694'), (x'3e112e0be826d695'), (x'3e112e0be826d696'),
+  (x'3e45798ee2308c39'), (x'3e45798ee2308c3a'), (x'3e45798ee2308c3b'),
+  (x'3e7ad7f29abcaf47'), (x'3e7ad7f29abcaf48'), (x'3e7ad7f29abcaf49'),
+  (x'3eb0c6f7a0b5ed8c'), (x'3eb0c6f7a0b5ed8d'), (x'3eb0c6f7a0b5ed8e'),
+  (x'3ee4f8b588e368ef'), (x'3ee4f8b588e368f0'), (x'3ee4f8b588e368f1'),
+  (x'3f1a36e2eb1c432c'), (x'3f1a36e2eb1c432d'), (x'3f1a36e2eb1c432e'),
+  (x'3f50624dd2f1a9fb'), (x'3f50624dd2f1a9fc'), (x'3f50624dd2f1a9fd'),
+  (x'3f847ae147ae147a'), (x'3f847ae147ae147b'), (x'3f847ae147ae147c'),
+  (x'3fb9999999999999'), (x'3fb999999999999a'), (x'3fb999999999999b'),
+  -- values very close to 1
+  (x'3feffffffffffff0'), (x'3feffffffffffff1'), (x'3feffffffffffff2'),
+  (x'3feffffffffffff3'), (x'3feffffffffffff4'), (x'3feffffffffffff5'),
+  (x'3feffffffffffff6'), (x'3feffffffffffff7'), (x'3feffffffffffff8'),
+  (x'3feffffffffffff9'), (x'3feffffffffffffa'), (x'3feffffffffffffb'),
+  (x'3feffffffffffffc'), (x'3feffffffffffffd'), (x'3feffffffffffffe'),
+  (x'3fefffffffffffff'),
+  (x'3ff0000000000000'),
+  (x'3ff0000000000001'), (x'3ff0000000000002'), (x'3ff0000000000003'),
+  (x'3ff0000000000004'), (x'3ff0000000000005'), (x'3ff0000000000006'),
+  (x'3ff0000000000007'), (x'3ff0000000000008'), (x'3ff0000000000009'),
+  --
+  (x'3ff921fb54442d18'),
+  (x'4005bf0a8b14576a'),
+  (x'400921fb54442d18'),
+  --
+  (x'4023ffffffffffff'), (x'4024000000000000'), (x'4024000000000001'),
+  (x'4058ffffffffffff'), (x'4059000000000000'), (x'4059000000000001'),
+  (x'408f3fffffffffff'), (x'408f400000000000'), (x'408f400000000001'),
+  (x'40c387ffffffffff'), (x'40c3880000000000'), (x'40c3880000000001'),
+  (x'40f869ffffffffff'), (x'40f86a0000000000'), (x'40f86a0000000001'),
+  (x'412e847fffffffff'), (x'412e848000000000'), (x'412e848000000001'),
+  (x'416312cfffffffff'), (x'416312d000000000'), (x'416312d000000001'),
+  (x'4197d783ffffffff'), (x'4197d78400000000'), (x'4197d78400000001'),
+  (x'41cdcd64ffffffff'), (x'41cdcd6500000000'), (x'41cdcd6500000001'),
+  (x'4202a05f1fffffff'), (x'4202a05f20000000'), (x'4202a05f20000001'),
+  (x'42374876e7ffffff'), (x'42374876e8000000'), (x'42374876e8000001'),
+  (x'426d1a94a1ffffff'), (x'426d1a94a2000000'), (x'426d1a94a2000001'),
+  (x'42a2309ce53fffff'), (x'42a2309ce5400000'), (x'42a2309ce5400001'),
+  (x'42d6bcc41e8fffff'), (x'42d6bcc41e900000'), (x'42d6bcc41e900001'),
+  (x'430c6bf52633ffff'), (x'430c6bf526340000'), (x'430c6bf526340001'),
+  (x'4341c37937e07fff'), (x'4341c37937e08000'), (x'4341c37937e08001'),
+  (x'4376345785d89fff'), (x'4376345785d8a000'), (x'4376345785d8a001'),
+  (x'43abc16d674ec7ff'), (x'43abc16d674ec800'), (x'43abc16d674ec801'),
+  (x'43e158e460913cff'), (x'43e158e460913d00'), (x'43e158e460913d01'),
+  (x'4415af1d78b58c3f'), (x'4415af1d78b58c40'), (x'4415af1d78b58c41'),
+  (x'444b1ae4d6e2ef4f'), (x'444b1ae4d6e2ef50'), (x'444b1ae4d6e2ef51'),
+  (x'4480f0cf064dd591'), (x'4480f0cf064dd592'), (x'4480f0cf064dd593'),
+  (x'44b52d02c7e14af5'), (x'44b52d02c7e14af6'), (x'44b52d02c7e14af7'),
+  (x'44ea784379d99db3'), (x'44ea784379d99db4'), (x'44ea784379d99db5'),
+  (x'45208b2a2c280290'), (x'45208b2a2c280291'), (x'45208b2a2c280292'),
+  --
+  (x'7feffffffffffffe'), (x'7fefffffffffffff'),
+  -- round to even tests (+ve)
+  (x'4350000000000002'),
+  (x'4350000000002e06'),
+  (x'4352000000000003'),
+  (x'4352000000000004'),
+  (x'4358000000000003'),
+  (x'4358000000000004'),
+  (x'435f000000000020'),
+  -- round to even tests (-ve)
+  (x'c350000000000002'),
+  (x'c350000000002e06'),
+  (x'c352000000000003'),
+  (x'c352000000000004'),
+  (x'c358000000000003'),
+  (x'c358000000000004'),
+  (x'c35f000000000020'),
+  -- exercise fixed-point memmoves
+  (x'42dc12218377de66'),
+  (x'42a674e79c5fe51f'),
+  (x'4271f71fb04cb74c'),
+  (x'423cbe991a145879'),
+  (x'4206fee0e1a9e061'),
+  (x'41d26580b487e6b4'),
+  (x'419d6f34540ca453'),
+  (x'41678c29dcd6e9dc'),
+  (x'4132d687e3df217d'),
+  (x'40fe240c9fcb68c8'),
+  (x'40c81cd6e63c53d3'),
+  (x'40934a4584fd0fdc'),
+  (x'405edd3c07fb4c93'),
+  (x'4028b0fcd32f7076'),
+  (x'3ff3c0ca428c59f8'),
+  -- these cases come from the upstream's testsuite
+  -- LotsOfTrailingZeros)
+  (x'3e60000000000000'),
+  -- Regression
+  (x'c352bd2668e077c4'),
+  (x'434018601510c000'),
+  (x'43d055dc36f24000'),
+  (x'43e052961c6f8000'),
+  (x'3ff3c0ca2a5b1d5d'),
+  -- LooksLikePow5
+  (x'4830f0cf064dd592'),
+  (x'4840f0cf064dd592'),
+  (x'4850f0cf064dd592'),
+  -- OutputLength
+  (x'3ff3333333333333'),
+  (x'3ff3ae147ae147ae'),
+  (x'3ff3be76c8b43958'),
+  (x'3ff3c083126e978d'),
+  (x'3ff3c0c1fc8f3238'),
+  (x'3ff3c0c9539b8887'),
+  (x'3ff3c0ca2a5b1d5d'),
+  (x'3ff3c0ca4283de1b'),
+  (x'3ff3c0ca43db770a'),
+  (x'3ff3c0ca428abd53'),
+  (x'3ff3c0ca428c1d2b'),
+  (x'3ff3c0ca428c51f2'),
+  (x'3ff3c0ca428c58fc'),
+  (x'3ff3c0ca428c59dd'),
+  (x'3ff3c0ca428c59f8'),
+  (x'3ff3c0ca428c59fb'),
+  -- 32-bit chunking
+  (x'40112e0be8047a7d'),
+  (x'40112e0be815a889'),
+  (x'40112e0be826d695'),
+  (x'40112e0be83804a1'),
+  (x'40112e0be84932ad'),
+  -- MinMaxShift
+  (x'0040000000000000'),
+  (x'007fffffffffffff'),
+  (x'0290000000000000'),
+  (x'029fffffffffffff'),
+  (x'4350000000000000'),
+  (x'435fffffffffffff'),
+  (x'1330000000000000'),
+  (x'133fffffffffffff'),
+  (x'3a6fa7161a4d6e0c')
+)
+select float8send(flt) as ibits,
+       flt,
+       flt::text::float8 as r_flt,
+       float8send(flt::text::float8) as obits,
+       float8send(flt::text::float8) = float8send(flt) as correct
+  from (select bits::bigint::xfloat8::float8 as flt
+          from testdata
+	offset 0) s;
+       ibits        |           flt           |          r_flt          |       obits        | correct 
+--------------------+-------------------------+-------------------------+--------------------+---------
+ \x0000000000000000 |                       0 |                       0 | \x0000000000000000 | t
+ \x0010000000000000 | 2.2250738585072014e-308 | 2.2250738585072014e-308 | \x0010000000000000 | t
+ \x0010000000000001 |  2.225073858507202e-308 |  2.225073858507202e-308 | \x0010000000000001 | t
+ \x0010000000000002 | 2.2250738585072024e-308 | 2.2250738585072024e-308 | \x0010000000000002 | t
+ \x0018000000000000 |  3.337610787760802e-308 |  3.337610787760802e-308 | \x0018000000000000 | t
+ \x3ddb7cdfd9d7bdba |   9.999999999999999e-11 |   9.999999999999999e-11 | \x3ddb7cdfd9d7bdba | t
+ \x3ddb7cdfd9d7bdbb |                   1e-10 |                   1e-10 | \x3ddb7cdfd9d7bdbb | t
+ \x3ddb7cdfd9d7bdbc |  1.0000000000000002e-10 |  1.0000000000000002e-10 | \x3ddb7cdfd9d7bdbc | t
+ \x3e112e0be826d694 |   9.999999999999999e-10 |   9.999999999999999e-10 | \x3e112e0be826d694 | t
+ \x3e112e0be826d695 |                   1e-09 |                   1e-09 | \x3e112e0be826d695 | t
+ \x3e112e0be826d696 |  1.0000000000000003e-09 |  1.0000000000000003e-09 | \x3e112e0be826d696 | t
+ \x3e45798ee2308c39 |   9.999999999999999e-09 |   9.999999999999999e-09 | \x3e45798ee2308c39 | t
+ \x3e45798ee2308c3a |                   1e-08 |                   1e-08 | \x3e45798ee2308c3a | t
+ \x3e45798ee2308c3b |  1.0000000000000002e-08 |  1.0000000000000002e-08 | \x3e45798ee2308c3b | t
+ \x3e7ad7f29abcaf47 |   9.999999999999998e-08 |   9.999999999999998e-08 | \x3e7ad7f29abcaf47 | t
+ \x3e7ad7f29abcaf48 |                   1e-07 |                   1e-07 | \x3e7ad7f29abcaf48 | t
+ \x3e7ad7f29abcaf49 |  1.0000000000000001e-07 |  1.0000000000000001e-07 | \x3e7ad7f29abcaf49 | t
+ \x3eb0c6f7a0b5ed8c |   9.999999999999997e-07 |   9.999999999999997e-07 | \x3eb0c6f7a0b5ed8c | t
+ \x3eb0c6f7a0b5ed8d |                   1e-06 |                   1e-06 | \x3eb0c6f7a0b5ed8d | t
+ \x3eb0c6f7a0b5ed8e |  1.0000000000000002e-06 |  1.0000000000000002e-06 | \x3eb0c6f7a0b5ed8e | t
+ \x3ee4f8b588e368ef |   9.999999999999997e-06 |   9.999999999999997e-06 | \x3ee4f8b588e368ef | t
+ \x3ee4f8b588e368f0 |   9.999999999999999e-06 |   9.999999999999999e-06 | \x3ee4f8b588e368f0 | t
+ \x3ee4f8b588e368f1 |                   1e-05 |                   1e-05 | \x3ee4f8b588e368f1 | t
+ \x3f1a36e2eb1c432c |   9.999999999999999e-05 |   9.999999999999999e-05 | \x3f1a36e2eb1c432c | t
+ \x3f1a36e2eb1c432d |                  0.0001 |                  0.0001 | \x3f1a36e2eb1c432d | t
+ \x3f1a36e2eb1c432e |  0.00010000000000000002 |  0.00010000000000000002 | \x3f1a36e2eb1c432e | t
+ \x3f50624dd2f1a9fb |   0.0009999999999999998 |   0.0009999999999999998 | \x3f50624dd2f1a9fb | t
+ \x3f50624dd2f1a9fc |                   0.001 |                   0.001 | \x3f50624dd2f1a9fc | t
+ \x3f50624dd2f1a9fd |   0.0010000000000000002 |   0.0010000000000000002 | \x3f50624dd2f1a9fd | t
+ \x3f847ae147ae147a |    0.009999999999999998 |    0.009999999999999998 | \x3f847ae147ae147a | t
+ \x3f847ae147ae147b |                    0.01 |                    0.01 | \x3f847ae147ae147b | t
+ \x3f847ae147ae147c |    0.010000000000000002 |    0.010000000000000002 | \x3f847ae147ae147c | t
+ \x3fb9999999999999 |     0.09999999999999999 |     0.09999999999999999 | \x3fb9999999999999 | t
+ \x3fb999999999999a |                     0.1 |                     0.1 | \x3fb999999999999a | t
+ \x3fb999999999999b |     0.10000000000000002 |     0.10000000000000002 | \x3fb999999999999b | t
+ \x3feffffffffffff0 |      0.9999999999999982 |      0.9999999999999982 | \x3feffffffffffff0 | t
+ \x3feffffffffffff1 |      0.9999999999999983 |      0.9999999999999983 | \x3feffffffffffff1 | t
+ \x3feffffffffffff2 |      0.9999999999999984 |      0.9999999999999984 | \x3feffffffffffff2 | t
+ \x3feffffffffffff3 |      0.9999999999999986 |      0.9999999999999986 | \x3feffffffffffff3 | t
+ \x3feffffffffffff4 |      0.9999999999999987 |      0.9999999999999987 | \x3feffffffffffff4 | t
+ \x3feffffffffffff5 |      0.9999999999999988 |      0.9999999999999988 | \x3feffffffffffff5 | t
+ \x3feffffffffffff6 |      0.9999999999999989 |      0.9999999999999989 | \x3feffffffffffff6 | t
+ \x3feffffffffffff7 |       0.999999999999999 |       0.999999999999999 | \x3feffffffffffff7 | t
+ \x3feffffffffffff8 |      0.9999999999999991 |      0.9999999999999991 | \x3feffffffffffff8 | t
+ \x3feffffffffffff9 |      0.9999999999999992 |      0.9999999999999992 | \x3feffffffffffff9 | t
+ \x3feffffffffffffa |      0.9999999999999993 |      0.9999999999999993 | \x3feffffffffffffa | t
+ \x3feffffffffffffb |      0.9999999999999994 |      0.9999999999999994 | \x3feffffffffffffb | t
+ \x3feffffffffffffc |      0.9999999999999996 |      0.9999999999999996 | \x3feffffffffffffc | t
+ \x3feffffffffffffd |      0.9999999999999997 |      0.9999999999999997 | \x3feffffffffffffd | t
+ \x3feffffffffffffe |      0.9999999999999998 |      0.9999999999999998 | \x3feffffffffffffe | t
+ \x3fefffffffffffff |      0.9999999999999999 |      0.9999999999999999 | \x3fefffffffffffff | t
+ \x3ff0000000000000 |                       1 |                       1 | \x3ff0000000000000 | t
+ \x3ff0000000000001 |      1.0000000000000002 |      1.0000000000000002 | \x3ff0000000000001 | t
+ \x3ff0000000000002 |      1.0000000000000004 |      1.0000000000000004 | \x3ff0000000000002 | t
+ \x3ff0000000000003 |      1.0000000000000007 |      1.0000000000000007 | \x3ff0000000000003 | t
+ \x3ff0000000000004 |      1.0000000000000009 |      1.0000000000000009 | \x3ff0000000000004 | t
+ \x3ff0000000000005 |       1.000000000000001 |       1.000000000000001 | \x3ff0000000000005 | t
+ \x3ff0000000000006 |      1.0000000000000013 |      1.0000000000000013 | \x3ff0000000000006 | t
+ \x3ff0000000000007 |      1.0000000000000016 |      1.0000000000000016 | \x3ff0000000000007 | t
+ \x3ff0000000000008 |      1.0000000000000018 |      1.0000000000000018 | \x3ff0000000000008 | t
+ \x3ff0000000000009 |       1.000000000000002 |       1.000000000000002 | \x3ff0000000000009 | t
+ \x3ff921fb54442d18 |      1.5707963267948966 |      1.5707963267948966 | \x3ff921fb54442d18 | t
+ \x4005bf0a8b14576a |      2.7182818284590455 |      2.7182818284590455 | \x4005bf0a8b14576a | t
+ \x400921fb54442d18 |       3.141592653589793 |       3.141592653589793 | \x400921fb54442d18 | t
+ \x4023ffffffffffff |       9.999999999999998 |       9.999999999999998 | \x4023ffffffffffff | t
+ \x4024000000000000 |                      10 |                      10 | \x4024000000000000 | t
+ \x4024000000000001 |      10.000000000000002 |      10.000000000000002 | \x4024000000000001 | t
+ \x4058ffffffffffff |       99.99999999999999 |       99.99999999999999 | \x4058ffffffffffff | t
+ \x4059000000000000 |                     100 |                     100 | \x4059000000000000 | t
+ \x4059000000000001 |      100.00000000000001 |      100.00000000000001 | \x4059000000000001 | t
+ \x408f3fffffffffff |       999.9999999999999 |       999.9999999999999 | \x408f3fffffffffff | t
+ \x408f400000000000 |                    1000 |                    1000 | \x408f400000000000 | t
+ \x408f400000000001 |      1000.0000000000001 |      1000.0000000000001 | \x408f400000000001 | t
+ \x40c387ffffffffff |       9999.999999999998 |       9999.999999999998 | \x40c387ffffffffff | t
+ \x40c3880000000000 |                   10000 |                   10000 | \x40c3880000000000 | t
+ \x40c3880000000001 |      10000.000000000002 |      10000.000000000002 | \x40c3880000000001 | t
+ \x40f869ffffffffff |       99999.99999999999 |       99999.99999999999 | \x40f869ffffffffff | t
+ \x40f86a0000000000 |                  100000 |                  100000 | \x40f86a0000000000 | t
+ \x40f86a0000000001 |      100000.00000000001 |      100000.00000000001 | \x40f86a0000000001 | t
+ \x412e847fffffffff |       999999.9999999999 |       999999.9999999999 | \x412e847fffffffff | t
+ \x412e848000000000 |                 1000000 |                 1000000 | \x412e848000000000 | t
+ \x412e848000000001 |      1000000.0000000001 |      1000000.0000000001 | \x412e848000000001 | t
+ \x416312cfffffffff |       9999999.999999998 |       9999999.999999998 | \x416312cfffffffff | t
+ \x416312d000000000 |                10000000 |                10000000 | \x416312d000000000 | t
+ \x416312d000000001 |      10000000.000000002 |      10000000.000000002 | \x416312d000000001 | t
+ \x4197d783ffffffff |       99999999.99999999 |       99999999.99999999 | \x4197d783ffffffff | t
+ \x4197d78400000000 |               100000000 |               100000000 | \x4197d78400000000 | t
+ \x4197d78400000001 |      100000000.00000001 |      100000000.00000001 | \x4197d78400000001 | t
+ \x41cdcd64ffffffff |       999999999.9999999 |       999999999.9999999 | \x41cdcd64ffffffff | t
+ \x41cdcd6500000000 |              1000000000 |              1000000000 | \x41cdcd6500000000 | t
+ \x41cdcd6500000001 |      1000000000.0000001 |      1000000000.0000001 | \x41cdcd6500000001 | t
+ \x4202a05f1fffffff |       9999999999.999998 |       9999999999.999998 | \x4202a05f1fffffff | t
+ \x4202a05f20000000 |             10000000000 |             10000000000 | \x4202a05f20000000 | t
+ \x4202a05f20000001 |      10000000000.000002 |      10000000000.000002 | \x4202a05f20000001 | t
+ \x42374876e7ffffff |       99999999999.99998 |       99999999999.99998 | \x42374876e7ffffff | t
+ \x42374876e8000000 |            100000000000 |            100000000000 | \x42374876e8000000 | t
+ \x42374876e8000001 |      100000000000.00002 |      100000000000.00002 | \x42374876e8000001 | t
+ \x426d1a94a1ffffff |       999999999999.9999 |       999999999999.9999 | \x426d1a94a1ffffff | t
+ \x426d1a94a2000000 |           1000000000000 |           1000000000000 | \x426d1a94a2000000 | t
+ \x426d1a94a2000001 |      1000000000000.0001 |      1000000000000.0001 | \x426d1a94a2000001 | t
+ \x42a2309ce53fffff |       9999999999999.998 |       9999999999999.998 | \x42a2309ce53fffff | t
+ \x42a2309ce5400000 |          10000000000000 |          10000000000000 | \x42a2309ce5400000 | t
+ \x42a2309ce5400001 |      10000000000000.002 |      10000000000000.002 | \x42a2309ce5400001 | t
+ \x42d6bcc41e8fffff |       99999999999999.98 |       99999999999999.98 | \x42d6bcc41e8fffff | t
+ \x42d6bcc41e900000 |         100000000000000 |         100000000000000 | \x42d6bcc41e900000 | t
+ \x42d6bcc41e900001 |      100000000000000.02 |      100000000000000.02 | \x42d6bcc41e900001 | t
+ \x430c6bf52633ffff |       999999999999999.9 |       999999999999999.9 | \x430c6bf52633ffff | t
+ \x430c6bf526340000 |                   1e+15 |                   1e+15 | \x430c6bf526340000 | t
+ \x430c6bf526340001 |  1.0000000000000001e+15 |  1.0000000000000001e+15 | \x430c6bf526340001 | t
+ \x4341c37937e07fff |   9.999999999999998e+15 |   9.999999999999998e+15 | \x4341c37937e07fff | t
+ \x4341c37937e08000 |                   1e+16 |                   1e+16 | \x4341c37937e08000 | t
+ \x4341c37937e08001 |  1.0000000000000002e+16 |  1.0000000000000002e+16 | \x4341c37937e08001 | t
+ \x4376345785d89fff |   9.999999999999998e+16 |   9.999999999999998e+16 | \x4376345785d89fff | t
+ \x4376345785d8a000 |                   1e+17 |                   1e+17 | \x4376345785d8a000 | t
+ \x4376345785d8a001 |  1.0000000000000002e+17 |  1.0000000000000002e+17 | \x4376345785d8a001 | t
+ \x43abc16d674ec7ff |   9.999999999999999e+17 |   9.999999999999999e+17 | \x43abc16d674ec7ff | t
+ \x43abc16d674ec800 |                   1e+18 |                   1e+18 | \x43abc16d674ec800 | t
+ \x43abc16d674ec801 |  1.0000000000000001e+18 |  1.0000000000000001e+18 | \x43abc16d674ec801 | t
+ \x43e158e460913cff |   9.999999999999998e+18 |   9.999999999999998e+18 | \x43e158e460913cff | t
+ \x43e158e460913d00 |                   1e+19 |                   1e+19 | \x43e158e460913d00 | t
+ \x43e158e460913d01 |  1.0000000000000002e+19 |  1.0000000000000002e+19 | \x43e158e460913d01 | t
+ \x4415af1d78b58c3f |   9.999999999999998e+19 |   9.999999999999998e+19 | \x4415af1d78b58c3f | t
+ \x4415af1d78b58c40 |                   1e+20 |                   1e+20 | \x4415af1d78b58c40 | t
+ \x4415af1d78b58c41 |  1.0000000000000002e+20 |  1.0000000000000002e+20 | \x4415af1d78b58c41 | t
+ \x444b1ae4d6e2ef4f |   9.999999999999999e+20 |   9.999999999999999e+20 | \x444b1ae4d6e2ef4f | t
+ \x444b1ae4d6e2ef50 |                   1e+21 |                   1e+21 | \x444b1ae4d6e2ef50 | t
+ \x444b1ae4d6e2ef51 |  1.0000000000000001e+21 |  1.0000000000000001e+21 | \x444b1ae4d6e2ef51 | t
+ \x4480f0cf064dd591 |   9.999999999999998e+21 |   9.999999999999998e+21 | \x4480f0cf064dd591 | t
+ \x4480f0cf064dd592 |                   1e+22 |                   1e+22 | \x4480f0cf064dd592 | t
+ \x4480f0cf064dd593 |  1.0000000000000002e+22 |  1.0000000000000002e+22 | \x4480f0cf064dd593 | t
+ \x44b52d02c7e14af5 |   9.999999999999997e+22 |   9.999999999999997e+22 | \x44b52d02c7e14af5 | t
+ \x44b52d02c7e14af6 |   9.999999999999999e+22 |   9.999999999999999e+22 | \x44b52d02c7e14af6 | t
+ \x44b52d02c7e14af7 |  1.0000000000000001e+23 |  1.0000000000000001e+23 | \x44b52d02c7e14af7 | t
+ \x44ea784379d99db3 |   9.999999999999998e+23 |   9.999999999999998e+23 | \x44ea784379d99db3 | t
+ \x44ea784379d99db4 |                   1e+24 |                   1e+24 | \x44ea784379d99db4 | t
+ \x44ea784379d99db5 |  1.0000000000000001e+24 |  1.0000000000000001e+24 | \x44ea784379d99db5 | t
+ \x45208b2a2c280290 |   9.999999999999999e+24 |   9.999999999999999e+24 | \x45208b2a2c280290 | t
+ \x45208b2a2c280291 |                   1e+25 |                   1e+25 | \x45208b2a2c280291 | t
+ \x45208b2a2c280292 |  1.0000000000000003e+25 |  1.0000000000000003e+25 | \x45208b2a2c280292 | t
+ \x7feffffffffffffe | 1.7976931348623155e+308 | 1.7976931348623155e+308 | \x7feffffffffffffe | t
+ \x7fefffffffffffff | 1.7976931348623157e+308 | 1.7976931348623157e+308 | \x7fefffffffffffff | t
+ \x4350000000000002 |  1.8014398509481992e+16 |  1.8014398509481992e+16 | \x4350000000000002 | t
+ \x4350000000002e06 |  1.8014398509529112e+16 |  1.8014398509529112e+16 | \x4350000000002e06 | t
+ \x4352000000000003 |  2.0266198323167244e+16 |  2.0266198323167244e+16 | \x4352000000000003 | t
+ \x4352000000000004 |  2.0266198323167248e+16 |  2.0266198323167248e+16 | \x4352000000000004 | t
+ \x4358000000000003 |  2.7021597764222988e+16 |  2.7021597764222988e+16 | \x4358000000000003 | t
+ \x4358000000000004 |  2.7021597764222992e+16 |  2.7021597764222992e+16 | \x4358000000000004 | t
+ \x435f000000000020 |  3.4902897112121472e+16 |  3.4902897112121472e+16 | \x435f000000000020 | t
+ \xc350000000000002 | -1.8014398509481992e+16 | -1.8014398509481992e+16 | \xc350000000000002 | t
+ \xc350000000002e06 | -1.8014398509529112e+16 | -1.8014398509529112e+16 | \xc350000000002e06 | t
+ \xc352000000000003 | -2.0266198323167244e+16 | -2.0266198323167244e+16 | \xc352000000000003 | t
+ \xc352000000000004 | -2.0266198323167248e+16 | -2.0266198323167248e+16 | \xc352000000000004 | t
+ \xc358000000000003 | -2.7021597764222988e+16 | -2.7021597764222988e+16 | \xc358000000000003 | t
+ \xc358000000000004 | -2.7021597764222992e+16 | -2.7021597764222992e+16 | \xc358000000000004 | t
+ \xc35f000000000020 | -3.4902897112121472e+16 | -3.4902897112121472e+16 | \xc35f000000000020 | t
+ \x42dc12218377de66 |       123456789012345.6 |       123456789012345.6 | \x42dc12218377de66 | t
+ \x42a674e79c5fe51f |       12345678901234.56 |       12345678901234.56 | \x42a674e79c5fe51f | t
+ \x4271f71fb04cb74c |       1234567890123.456 |       1234567890123.456 | \x4271f71fb04cb74c | t
+ \x423cbe991a145879 |       123456789012.3456 |       123456789012.3456 | \x423cbe991a145879 | t
+ \x4206fee0e1a9e061 |       12345678901.23456 |       12345678901.23456 | \x4206fee0e1a9e061 | t
+ \x41d26580b487e6b4 |       1234567890.123456 |       1234567890.123456 | \x41d26580b487e6b4 | t
+ \x419d6f34540ca453 |       123456789.0123456 |       123456789.0123456 | \x419d6f34540ca453 | t
+ \x41678c29dcd6e9dc |       12345678.90123456 |       12345678.90123456 | \x41678c29dcd6e9dc | t
+ \x4132d687e3df217d |       1234567.890123456 |       1234567.890123456 | \x4132d687e3df217d | t
+ \x40fe240c9fcb68c8 |       123456.7890123456 |       123456.7890123456 | \x40fe240c9fcb68c8 | t
+ \x40c81cd6e63c53d3 |       12345.67890123456 |       12345.67890123456 | \x40c81cd6e63c53d3 | t
+ \x40934a4584fd0fdc |       1234.567890123456 |       1234.567890123456 | \x40934a4584fd0fdc | t
+ \x405edd3c07fb4c93 |       123.4567890123456 |       123.4567890123456 | \x405edd3c07fb4c93 | t
+ \x4028b0fcd32f7076 |       12.34567890123456 |       12.34567890123456 | \x4028b0fcd32f7076 | t
+ \x3ff3c0ca428c59f8 |       1.234567890123456 |       1.234567890123456 | \x3ff3c0ca428c59f8 | t
+ \x3e60000000000000 |  2.9802322387695312e-08 |  2.9802322387695312e-08 | \x3e60000000000000 | t
+ \xc352bd2668e077c4 | -2.1098088986959632e+16 | -2.1098088986959632e+16 | \xc352bd2668e077c4 | t
+ \x434018601510c000 |     9.0608011534336e+15 |     9.0608011534336e+15 | \x434018601510c000 | t
+ \x43d055dc36f24000 |   4.708356024711512e+18 |   4.708356024711512e+18 | \x43d055dc36f24000 | t
+ \x43e052961c6f8000 |   9.409340012568248e+18 |   9.409340012568248e+18 | \x43e052961c6f8000 | t
+ \x3ff3c0ca2a5b1d5d |               1.2345678 |               1.2345678 | \x3ff3c0ca2a5b1d5d | t
+ \x4830f0cf064dd592 |   5.764607523034235e+39 |   5.764607523034235e+39 | \x4830f0cf064dd592 | t
+ \x4840f0cf064dd592 |   1.152921504606847e+40 |   1.152921504606847e+40 | \x4840f0cf064dd592 | t
+ \x4850f0cf064dd592 |   2.305843009213694e+40 |   2.305843009213694e+40 | \x4850f0cf064dd592 | t
+ \x3ff3333333333333 |                     1.2 |                     1.2 | \x3ff3333333333333 | t
+ \x3ff3ae147ae147ae |                    1.23 |                    1.23 | \x3ff3ae147ae147ae | t
+ \x3ff3be76c8b43958 |                   1.234 |                   1.234 | \x3ff3be76c8b43958 | t
+ \x3ff3c083126e978d |                  1.2345 |                  1.2345 | \x3ff3c083126e978d | t
+ \x3ff3c0c1fc8f3238 |                 1.23456 |                 1.23456 | \x3ff3c0c1fc8f3238 | t
+ \x3ff3c0c9539b8887 |                1.234567 |                1.234567 | \x3ff3c0c9539b8887 | t
+ \x3ff3c0ca2a5b1d5d |               1.2345678 |               1.2345678 | \x3ff3c0ca2a5b1d5d | t
+ \x3ff3c0ca4283de1b |              1.23456789 |              1.23456789 | \x3ff3c0ca4283de1b | t
+ \x3ff3c0ca43db770a |             1.234567895 |             1.234567895 | \x3ff3c0ca43db770a | t
+ \x3ff3c0ca428abd53 |            1.2345678901 |            1.2345678901 | \x3ff3c0ca428abd53 | t
+ \x3ff3c0ca428c1d2b |           1.23456789012 |           1.23456789012 | \x3ff3c0ca428c1d2b | t
+ \x3ff3c0ca428c51f2 |          1.234567890123 |          1.234567890123 | \x3ff3c0ca428c51f2 | t
+ \x3ff3c0ca428c58fc |         1.2345678901234 |         1.2345678901234 | \x3ff3c0ca428c58fc | t
+ \x3ff3c0ca428c59dd |        1.23456789012345 |        1.23456789012345 | \x3ff3c0ca428c59dd | t
+ \x3ff3c0ca428c59f8 |       1.234567890123456 |       1.234567890123456 | \x3ff3c0ca428c59f8 | t
+ \x3ff3c0ca428c59fb |      1.2345678901234567 |      1.2345678901234567 | \x3ff3c0ca428c59fb | t
+ \x40112e0be8047a7d |             4.294967294 |             4.294967294 | \x40112e0be8047a7d | t
+ \x40112e0be815a889 |             4.294967295 |             4.294967295 | \x40112e0be815a889 | t
+ \x40112e0be826d695 |             4.294967296 |             4.294967296 | \x40112e0be826d695 | t
+ \x40112e0be83804a1 |             4.294967297 |             4.294967297 | \x40112e0be83804a1 | t
+ \x40112e0be84932ad |             4.294967298 |             4.294967298 | \x40112e0be84932ad | t
+ \x0040000000000000 | 1.7800590868057611e-307 | 1.7800590868057611e-307 | \x0040000000000000 | t
+ \x007fffffffffffff | 2.8480945388892175e-306 | 2.8480945388892175e-306 | \x007fffffffffffff | t
+ \x0290000000000000 |  2.446494580089078e-296 |  2.446494580089078e-296 | \x0290000000000000 | t
+ \x029fffffffffffff | 4.8929891601781557e-296 | 4.8929891601781557e-296 | \x029fffffffffffff | t
+ \x4350000000000000 |  1.8014398509481984e+16 |  1.8014398509481984e+16 | \x4350000000000000 | t
+ \x435fffffffffffff |  3.6028797018963964e+16 |  3.6028797018963964e+16 | \x435fffffffffffff | t
+ \x1330000000000000 |  2.900835519859558e-216 |  2.900835519859558e-216 | \x1330000000000000 | t
+ \x133fffffffffffff |  5.801671039719115e-216 |  5.801671039719115e-216 | \x133fffffffffffff | t
+ \x3a6fa7161a4d6e0c |   3.196104012172126e-27 |   3.196104012172126e-27 | \x3a6fa7161a4d6e0c | t
+(209 rows)
+
+-- clean up, lest opr_sanity complain
+\set VERBOSITY terse
+drop type xfloat8 cascade;
+NOTICE:  drop cascades to 6 other objects
+\set VERBOSITY default
+--
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index 75c0bf389b..c3a6f5331f 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -24,6 +24,13 @@ SELECT '-10e-400'::float8;
 ERROR:  "-10e-400" is out of range for type double precision
 LINE 1: SELECT '-10e-400'::float8;
                ^
+-- test smallest normalized input
+SELECT float8send('2.2250738585072014E-308'::float8);
+     float8send     
+--------------------
+ \x0010000000000000
+(1 row)
+
 -- bad input
 INSERT INTO FLOAT8_TBL(f1) VALUES ('');
 ERROR:  invalid input syntax for type double precision: ""
@@ -209,7 +216,7 @@ SELECT '' AS three, f.f1, f.f1 / '-10' AS x
    WHERE f.f1 > '0.0';
  three |          f1          |           x           
 -------+----------------------+-----------------------
-       |               1004.3 |               -100.43
+       |               1004.3 |   -100.42999999999999
        | 1.2345678901234e+200 | -1.2345678901234e+199
        | 1.2345678901234e-200 | -1.2345678901234e-201
 (3 rows)
@@ -226,9 +233,9 @@ SELECT '' AS three, f.f1, f.f1 - '-10' AS x
 
 SELECT '' AS one, f.f1 ^ '2.0' AS square_f1
    FROM FLOAT8_TBL f where f.f1 = '1004.3';
- one | square_f1  
------+------------
-     | 1008618.49
+ one |     square_f1      
+-----+--------------------
+     | 1008618.4899999999
 (1 row)
 
 -- absolute value
@@ -310,6 +317,8 @@ select sign(f1) as sign_f1 from float8_tbl f;
        1
 (5 rows)
 
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
 -- square root
 SELECT sqrt(float8 '64') AS eight;
  eight 
@@ -445,6 +454,7 @@ SELECT '' AS five, * FROM FLOAT8_TBL;
       | -1.2345678901234e-200
 (5 rows)
 
+RESET extra_float_digits;
 -- test for over- and underflow
 INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
 ERROR:  "10e400" is out of range for type double precision
@@ -530,7 +540,6 @@ SELECT '-9223372036854775808.5'::float8::int8;
 SELECT '-9223372036854780000'::float8::int8;
 ERROR:  bigint out of range
 -- test exact cases for trigonometric functions in degrees
-SET extra_float_digits = 3;
 SELECT x,
        sind(x),
        sind(x) IN (-1,-0.5,0,0.5,1) AS sind_exact
@@ -632,4 +641,432 @@ FROM (SELECT 10*cosd(a), 10*sind(a)
   10 |   0 |      0 | t
 (5 rows)
 
-RESET extra_float_digits;
+--
+-- test output (and round-trip safety) of various values.
+-- To ensure we're testing what we think we're testing, start with
+-- float values specified by bit patterns (as a useful side effect,
+-- this means we'll fail on non-IEEE platforms).
+create type xfloat8;
+create function xfloat8in(cstring) returns xfloat8 immutable strict
+  language internal as 'int8in';
+NOTICE:  return type xfloat8 is only a shell
+create function xfloat8out(xfloat8) returns cstring immutable strict
+  language internal as 'int8out';
+NOTICE:  argument type xfloat8 is only a shell
+create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8);
+create cast (xfloat8 as float8) without function;
+create cast (float8 as xfloat8) without function;
+create cast (xfloat8 as bigint) without function;
+create cast (bigint as xfloat8) without function;
+-- float8: seeeeeee eeeeeeee eeeeeeee mmmmmmmm mmmmmmmm(x4)
+-- we don't care to assume the platform's strtod() handles subnormals
+-- correctly; those are "use at your own risk". However we do test
+-- subnormal outputs, since those are under our control.
+with testdata(bits) as (values
+  -- small subnormals
+  (x'0000000000000001'),
+  (x'0000000000000002'), (x'0000000000000003'),
+  (x'0000000000001000'), (x'0000000100000000'),
+  (x'0000010000000000'), (x'0000010100000000'),
+  (x'0000400000000000'), (x'0000400100000000'),
+  (x'0000800000000000'), (x'0000800000000001'),
+  -- these values taken from upstream testsuite
+  (x'00000000000f4240'),
+  (x'00000000016e3600'),
+  (x'0000008cdcdea440'),
+  -- borderline between subnormal and normal
+  (x'000ffffffffffff0'), (x'000ffffffffffff1'),
+  (x'000ffffffffffffe'), (x'000fffffffffffff'))
+select float8send(flt) as ibits,
+       flt
+  from (select bits::bigint::xfloat8::float8 as flt
+          from testdata
+	offset 0) s;
+       ibits        |           flt           
+--------------------+-------------------------
+ \x0000000000000001 |                  5e-324
+ \x0000000000000002 |                  1e-323
+ \x0000000000000003 |                1.5e-323
+ \x0000000000001000 |             2.0237e-320
+ \x0000000100000000 |        2.121995791e-314
+ \x0000010000000000 |      5.43230922487e-312
+ \x0000010100000000 |      5.45352918278e-312
+ \x0000400000000000 |    3.4766779039175e-310
+ \x0000400100000000 |    3.4768901034966e-310
+ \x0000800000000000 |     6.953355807835e-310
+ \x0000800000000001 |   6.95335580783505e-310
+ \x00000000000f4240 |           4.940656e-318
+ \x00000000016e3600 |         1.18575755e-316
+ \x0000008cdcdea440 |     2.989102097996e-312
+ \x000ffffffffffff0 | 2.2250738585071935e-308
+ \x000ffffffffffff1 |  2.225073858507194e-308
+ \x000ffffffffffffe | 2.2250738585072004e-308
+ \x000fffffffffffff |  2.225073858507201e-308
+(18 rows)
+
+-- round-trip tests
+with testdata(bits) as (values
+  (x'0000000000000000'),
+  -- smallest normal values
+  (x'0010000000000000'), (x'0010000000000001'),
+  (x'0010000000000002'), (x'0018000000000000'),
+  --
+  (x'3ddb7cdfd9d7bdba'), (x'3ddb7cdfd9d7bdbb'), (x'3ddb7cdfd9d7bdbc'),
+  (x'3e112e0be826d694'), (x'3e112e0be826d695'), (x'3e112e0be826d696'),
+  (x'3e45798ee2308c39'), (x'3e45798ee2308c3a'), (x'3e45798ee2308c3b'),
+  (x'3e7ad7f29abcaf47'), (x'3e7ad7f29abcaf48'), (x'3e7ad7f29abcaf49'),
+  (x'3eb0c6f7a0b5ed8c'), (x'3eb0c6f7a0b5ed8d'), (x'3eb0c6f7a0b5ed8e'),
+  (x'3ee4f8b588e368ef'), (x'3ee4f8b588e368f0'), (x'3ee4f8b588e368f1'),
+  (x'3f1a36e2eb1c432c'), (x'3f1a36e2eb1c432d'), (x'3f1a36e2eb1c432e'),
+  (x'3f50624dd2f1a9fb'), (x'3f50624dd2f1a9fc'), (x'3f50624dd2f1a9fd'),
+  (x'3f847ae147ae147a'), (x'3f847ae147ae147b'), (x'3f847ae147ae147c'),
+  (x'3fb9999999999999'), (x'3fb999999999999a'), (x'3fb999999999999b'),
+  -- values very close to 1
+  (x'3feffffffffffff0'), (x'3feffffffffffff1'), (x'3feffffffffffff2'),
+  (x'3feffffffffffff3'), (x'3feffffffffffff4'), (x'3feffffffffffff5'),
+  (x'3feffffffffffff6'), (x'3feffffffffffff7'), (x'3feffffffffffff8'),
+  (x'3feffffffffffff9'), (x'3feffffffffffffa'), (x'3feffffffffffffb'),
+  (x'3feffffffffffffc'), (x'3feffffffffffffd'), (x'3feffffffffffffe'),
+  (x'3fefffffffffffff'),
+  (x'3ff0000000000000'),
+  (x'3ff0000000000001'), (x'3ff0000000000002'), (x'3ff0000000000003'),
+  (x'3ff0000000000004'), (x'3ff0000000000005'), (x'3ff0000000000006'),
+  (x'3ff0000000000007'), (x'3ff0000000000008'), (x'3ff0000000000009'),
+  --
+  (x'3ff921fb54442d18'),
+  (x'4005bf0a8b14576a'),
+  (x'400921fb54442d18'),
+  --
+  (x'4023ffffffffffff'), (x'4024000000000000'), (x'4024000000000001'),
+  (x'4058ffffffffffff'), (x'4059000000000000'), (x'4059000000000001'),
+  (x'408f3fffffffffff'), (x'408f400000000000'), (x'408f400000000001'),
+  (x'40c387ffffffffff'), (x'40c3880000000000'), (x'40c3880000000001'),
+  (x'40f869ffffffffff'), (x'40f86a0000000000'), (x'40f86a0000000001'),
+  (x'412e847fffffffff'), (x'412e848000000000'), (x'412e848000000001'),
+  (x'416312cfffffffff'), (x'416312d000000000'), (x'416312d000000001'),
+  (x'4197d783ffffffff'), (x'4197d78400000000'), (x'4197d78400000001'),
+  (x'41cdcd64ffffffff'), (x'41cdcd6500000000'), (x'41cdcd6500000001'),
+  (x'4202a05f1fffffff'), (x'4202a05f20000000'), (x'4202a05f20000001'),
+  (x'42374876e7ffffff'), (x'42374876e8000000'), (x'42374876e8000001'),
+  (x'426d1a94a1ffffff'), (x'426d1a94a2000000'), (x'426d1a94a2000001'),
+  (x'42a2309ce53fffff'), (x'42a2309ce5400000'), (x'42a2309ce5400001'),
+  (x'42d6bcc41e8fffff'), (x'42d6bcc41e900000'), (x'42d6bcc41e900001'),
+  (x'430c6bf52633ffff'), (x'430c6bf526340000'), (x'430c6bf526340001'),
+  (x'4341c37937e07fff'), (x'4341c37937e08000'), (x'4341c37937e08001'),
+  (x'4376345785d89fff'), (x'4376345785d8a000'), (x'4376345785d8a001'),
+  (x'43abc16d674ec7ff'), (x'43abc16d674ec800'), (x'43abc16d674ec801'),
+  (x'43e158e460913cff'), (x'43e158e460913d00'), (x'43e158e460913d01'),
+  (x'4415af1d78b58c3f'), (x'4415af1d78b58c40'), (x'4415af1d78b58c41'),
+  (x'444b1ae4d6e2ef4f'), (x'444b1ae4d6e2ef50'), (x'444b1ae4d6e2ef51'),
+  (x'4480f0cf064dd591'), (x'4480f0cf064dd592'), (x'4480f0cf064dd593'),
+  (x'44b52d02c7e14af5'), (x'44b52d02c7e14af6'), (x'44b52d02c7e14af7'),
+  (x'44ea784379d99db3'), (x'44ea784379d99db4'), (x'44ea784379d99db5'),
+  (x'45208b2a2c280290'), (x'45208b2a2c280291'), (x'45208b2a2c280292'),
+  --
+  (x'7feffffffffffffe'), (x'7fefffffffffffff'),
+  -- round to even tests (+ve)
+  (x'4350000000000002'),
+  (x'4350000000002e06'),
+  (x'4352000000000003'),
+  (x'4352000000000004'),
+  (x'4358000000000003'),
+  (x'4358000000000004'),
+  (x'435f000000000020'),
+  -- round to even tests (-ve)
+  (x'c350000000000002'),
+  (x'c350000000002e06'),
+  (x'c352000000000003'),
+  (x'c352000000000004'),
+  (x'c358000000000003'),
+  (x'c358000000000004'),
+  (x'c35f000000000020'),
+  -- exercise fixed-point memmoves
+  (x'42dc12218377de66'),
+  (x'42a674e79c5fe51f'),
+  (x'4271f71fb04cb74c'),
+  (x'423cbe991a145879'),
+  (x'4206fee0e1a9e061'),
+  (x'41d26580b487e6b4'),
+  (x'419d6f34540ca453'),
+  (x'41678c29dcd6e9dc'),
+  (x'4132d687e3df217d'),
+  (x'40fe240c9fcb68c8'),
+  (x'40c81cd6e63c53d3'),
+  (x'40934a4584fd0fdc'),
+  (x'405edd3c07fb4c93'),
+  (x'4028b0fcd32f7076'),
+  (x'3ff3c0ca428c59f8'),
+  -- these cases come from the upstream's testsuite
+  -- LotsOfTrailingZeros)
+  (x'3e60000000000000'),
+  -- Regression
+  (x'c352bd2668e077c4'),
+  (x'434018601510c000'),
+  (x'43d055dc36f24000'),
+  (x'43e052961c6f8000'),
+  (x'3ff3c0ca2a5b1d5d'),
+  -- LooksLikePow5
+  (x'4830f0cf064dd592'),
+  (x'4840f0cf064dd592'),
+  (x'4850f0cf064dd592'),
+  -- OutputLength
+  (x'3ff3333333333333'),
+  (x'3ff3ae147ae147ae'),
+  (x'3ff3be76c8b43958'),
+  (x'3ff3c083126e978d'),
+  (x'3ff3c0c1fc8f3238'),
+  (x'3ff3c0c9539b8887'),
+  (x'3ff3c0ca2a5b1d5d'),
+  (x'3ff3c0ca4283de1b'),
+  (x'3ff3c0ca43db770a'),
+  (x'3ff3c0ca428abd53'),
+  (x'3ff3c0ca428c1d2b'),
+  (x'3ff3c0ca428c51f2'),
+  (x'3ff3c0ca428c58fc'),
+  (x'3ff3c0ca428c59dd'),
+  (x'3ff3c0ca428c59f8'),
+  (x'3ff3c0ca428c59fb'),
+  -- 32-bit chunking
+  (x'40112e0be8047a7d'),
+  (x'40112e0be815a889'),
+  (x'40112e0be826d695'),
+  (x'40112e0be83804a1'),
+  (x'40112e0be84932ad'),
+  -- MinMaxShift
+  (x'0040000000000000'),
+  (x'007fffffffffffff'),
+  (x'0290000000000000'),
+  (x'029fffffffffffff'),
+  (x'4350000000000000'),
+  (x'435fffffffffffff'),
+  (x'1330000000000000'),
+  (x'133fffffffffffff'),
+  (x'3a6fa7161a4d6e0c')
+)
+select float8send(flt) as ibits,
+       flt,
+       flt::text::float8 as r_flt,
+       float8send(flt::text::float8) as obits,
+       float8send(flt::text::float8) = float8send(flt) as correct
+  from (select bits::bigint::xfloat8::float8 as flt
+          from testdata
+	offset 0) s;
+       ibits        |           flt           |          r_flt          |       obits        | correct 
+--------------------+-------------------------+-------------------------+--------------------+---------
+ \x0000000000000000 |                       0 |                       0 | \x0000000000000000 | t
+ \x0010000000000000 | 2.2250738585072014e-308 | 2.2250738585072014e-308 | \x0010000000000000 | t
+ \x0010000000000001 |  2.225073858507202e-308 |  2.225073858507202e-308 | \x0010000000000001 | t
+ \x0010000000000002 | 2.2250738585072024e-308 | 2.2250738585072024e-308 | \x0010000000000002 | t
+ \x0018000000000000 |  3.337610787760802e-308 |  3.337610787760802e-308 | \x0018000000000000 | t
+ \x3ddb7cdfd9d7bdba |   9.999999999999999e-11 |   9.999999999999999e-11 | \x3ddb7cdfd9d7bdba | t
+ \x3ddb7cdfd9d7bdbb |                   1e-10 |                   1e-10 | \x3ddb7cdfd9d7bdbb | t
+ \x3ddb7cdfd9d7bdbc |  1.0000000000000002e-10 |  1.0000000000000002e-10 | \x3ddb7cdfd9d7bdbc | t
+ \x3e112e0be826d694 |   9.999999999999999e-10 |   9.999999999999999e-10 | \x3e112e0be826d694 | t
+ \x3e112e0be826d695 |                   1e-09 |                   1e-09 | \x3e112e0be826d695 | t
+ \x3e112e0be826d696 |  1.0000000000000003e-09 |  1.0000000000000003e-09 | \x3e112e0be826d696 | t
+ \x3e45798ee2308c39 |   9.999999999999999e-09 |   9.999999999999999e-09 | \x3e45798ee2308c39 | t
+ \x3e45798ee2308c3a |                   1e-08 |                   1e-08 | \x3e45798ee2308c3a | t
+ \x3e45798ee2308c3b |  1.0000000000000002e-08 |  1.0000000000000002e-08 | \x3e45798ee2308c3b | t
+ \x3e7ad7f29abcaf47 |   9.999999999999998e-08 |   9.999999999999998e-08 | \x3e7ad7f29abcaf47 | t
+ \x3e7ad7f29abcaf48 |                   1e-07 |                   1e-07 | \x3e7ad7f29abcaf48 | t
+ \x3e7ad7f29abcaf49 |  1.0000000000000001e-07 |  1.0000000000000001e-07 | \x3e7ad7f29abcaf49 | t
+ \x3eb0c6f7a0b5ed8c |   9.999999999999997e-07 |   9.999999999999997e-07 | \x3eb0c6f7a0b5ed8c | t
+ \x3eb0c6f7a0b5ed8d |                   1e-06 |                   1e-06 | \x3eb0c6f7a0b5ed8d | t
+ \x3eb0c6f7a0b5ed8e |  1.0000000000000002e-06 |  1.0000000000000002e-06 | \x3eb0c6f7a0b5ed8e | t
+ \x3ee4f8b588e368ef |   9.999999999999997e-06 |   9.999999999999997e-06 | \x3ee4f8b588e368ef | t
+ \x3ee4f8b588e368f0 |   9.999999999999999e-06 |   9.999999999999999e-06 | \x3ee4f8b588e368f0 | t
+ \x3ee4f8b588e368f1 |                   1e-05 |                   1e-05 | \x3ee4f8b588e368f1 | t
+ \x3f1a36e2eb1c432c |   9.999999999999999e-05 |   9.999999999999999e-05 | \x3f1a36e2eb1c432c | t
+ \x3f1a36e2eb1c432d |                  0.0001 |                  0.0001 | \x3f1a36e2eb1c432d | t
+ \x3f1a36e2eb1c432e |  0.00010000000000000002 |  0.00010000000000000002 | \x3f1a36e2eb1c432e | t
+ \x3f50624dd2f1a9fb |   0.0009999999999999998 |   0.0009999999999999998 | \x3f50624dd2f1a9fb | t
+ \x3f50624dd2f1a9fc |                   0.001 |                   0.001 | \x3f50624dd2f1a9fc | t
+ \x3f50624dd2f1a9fd |   0.0010000000000000002 |   0.0010000000000000002 | \x3f50624dd2f1a9fd | t
+ \x3f847ae147ae147a |    0.009999999999999998 |    0.009999999999999998 | \x3f847ae147ae147a | t
+ \x3f847ae147ae147b |                    0.01 |                    0.01 | \x3f847ae147ae147b | t
+ \x3f847ae147ae147c |    0.010000000000000002 |    0.010000000000000002 | \x3f847ae147ae147c | t
+ \x3fb9999999999999 |     0.09999999999999999 |     0.09999999999999999 | \x3fb9999999999999 | t
+ \x3fb999999999999a |                     0.1 |                     0.1 | \x3fb999999999999a | t
+ \x3fb999999999999b |     0.10000000000000002 |     0.10000000000000002 | \x3fb999999999999b | t
+ \x3feffffffffffff0 |      0.9999999999999982 |      0.9999999999999982 | \x3feffffffffffff0 | t
+ \x3feffffffffffff1 |      0.9999999999999983 |      0.9999999999999983 | \x3feffffffffffff1 | t
+ \x3feffffffffffff2 |      0.9999999999999984 |      0.9999999999999984 | \x3feffffffffffff2 | t
+ \x3feffffffffffff3 |      0.9999999999999986 |      0.9999999999999986 | \x3feffffffffffff3 | t
+ \x3feffffffffffff4 |      0.9999999999999987 |      0.9999999999999987 | \x3feffffffffffff4 | t
+ \x3feffffffffffff5 |      0.9999999999999988 |      0.9999999999999988 | \x3feffffffffffff5 | t
+ \x3feffffffffffff6 |      0.9999999999999989 |      0.9999999999999989 | \x3feffffffffffff6 | t
+ \x3feffffffffffff7 |       0.999999999999999 |       0.999999999999999 | \x3feffffffffffff7 | t
+ \x3feffffffffffff8 |      0.9999999999999991 |      0.9999999999999991 | \x3feffffffffffff8 | t
+ \x3feffffffffffff9 |      0.9999999999999992 |      0.9999999999999992 | \x3feffffffffffff9 | t
+ \x3feffffffffffffa |      0.9999999999999993 |      0.9999999999999993 | \x3feffffffffffffa | t
+ \x3feffffffffffffb |      0.9999999999999994 |      0.9999999999999994 | \x3feffffffffffffb | t
+ \x3feffffffffffffc |      0.9999999999999996 |      0.9999999999999996 | \x3feffffffffffffc | t
+ \x3feffffffffffffd |      0.9999999999999997 |      0.9999999999999997 | \x3feffffffffffffd | t
+ \x3feffffffffffffe |      0.9999999999999998 |      0.9999999999999998 | \x3feffffffffffffe | t
+ \x3fefffffffffffff |      0.9999999999999999 |      0.9999999999999999 | \x3fefffffffffffff | t
+ \x3ff0000000000000 |                       1 |                       1 | \x3ff0000000000000 | t
+ \x3ff0000000000001 |      1.0000000000000002 |      1.0000000000000002 | \x3ff0000000000001 | t
+ \x3ff0000000000002 |      1.0000000000000004 |      1.0000000000000004 | \x3ff0000000000002 | t
+ \x3ff0000000000003 |      1.0000000000000007 |      1.0000000000000007 | \x3ff0000000000003 | t
+ \x3ff0000000000004 |      1.0000000000000009 |      1.0000000000000009 | \x3ff0000000000004 | t
+ \x3ff0000000000005 |       1.000000000000001 |       1.000000000000001 | \x3ff0000000000005 | t
+ \x3ff0000000000006 |      1.0000000000000013 |      1.0000000000000013 | \x3ff0000000000006 | t
+ \x3ff0000000000007 |      1.0000000000000016 |      1.0000000000000016 | \x3ff0000000000007 | t
+ \x3ff0000000000008 |      1.0000000000000018 |      1.0000000000000018 | \x3ff0000000000008 | t
+ \x3ff0000000000009 |       1.000000000000002 |       1.000000000000002 | \x3ff0000000000009 | t
+ \x3ff921fb54442d18 |      1.5707963267948966 |      1.5707963267948966 | \x3ff921fb54442d18 | t
+ \x4005bf0a8b14576a |      2.7182818284590455 |      2.7182818284590455 | \x4005bf0a8b14576a | t
+ \x400921fb54442d18 |       3.141592653589793 |       3.141592653589793 | \x400921fb54442d18 | t
+ \x4023ffffffffffff |       9.999999999999998 |       9.999999999999998 | \x4023ffffffffffff | t
+ \x4024000000000000 |                      10 |                      10 | \x4024000000000000 | t
+ \x4024000000000001 |      10.000000000000002 |      10.000000000000002 | \x4024000000000001 | t
+ \x4058ffffffffffff |       99.99999999999999 |       99.99999999999999 | \x4058ffffffffffff | t
+ \x4059000000000000 |                     100 |                     100 | \x4059000000000000 | t
+ \x4059000000000001 |      100.00000000000001 |      100.00000000000001 | \x4059000000000001 | t
+ \x408f3fffffffffff |       999.9999999999999 |       999.9999999999999 | \x408f3fffffffffff | t
+ \x408f400000000000 |                    1000 |                    1000 | \x408f400000000000 | t
+ \x408f400000000001 |      1000.0000000000001 |      1000.0000000000001 | \x408f400000000001 | t
+ \x40c387ffffffffff |       9999.999999999998 |       9999.999999999998 | \x40c387ffffffffff | t
+ \x40c3880000000000 |                   10000 |                   10000 | \x40c3880000000000 | t
+ \x40c3880000000001 |      10000.000000000002 |      10000.000000000002 | \x40c3880000000001 | t
+ \x40f869ffffffffff |       99999.99999999999 |       99999.99999999999 | \x40f869ffffffffff | t
+ \x40f86a0000000000 |                  100000 |                  100000 | \x40f86a0000000000 | t
+ \x40f86a0000000001 |      100000.00000000001 |      100000.00000000001 | \x40f86a0000000001 | t
+ \x412e847fffffffff |       999999.9999999999 |       999999.9999999999 | \x412e847fffffffff | t
+ \x412e848000000000 |                 1000000 |                 1000000 | \x412e848000000000 | t
+ \x412e848000000001 |      1000000.0000000001 |      1000000.0000000001 | \x412e848000000001 | t
+ \x416312cfffffffff |       9999999.999999998 |       9999999.999999998 | \x416312cfffffffff | t
+ \x416312d000000000 |                10000000 |                10000000 | \x416312d000000000 | t
+ \x416312d000000001 |      10000000.000000002 |      10000000.000000002 | \x416312d000000001 | t
+ \x4197d783ffffffff |       99999999.99999999 |       99999999.99999999 | \x4197d783ffffffff | t
+ \x4197d78400000000 |               100000000 |               100000000 | \x4197d78400000000 | t
+ \x4197d78400000001 |      100000000.00000001 |      100000000.00000001 | \x4197d78400000001 | t
+ \x41cdcd64ffffffff |       999999999.9999999 |       999999999.9999999 | \x41cdcd64ffffffff | t
+ \x41cdcd6500000000 |              1000000000 |              1000000000 | \x41cdcd6500000000 | t
+ \x41cdcd6500000001 |      1000000000.0000001 |      1000000000.0000001 | \x41cdcd6500000001 | t
+ \x4202a05f1fffffff |       9999999999.999998 |       9999999999.999998 | \x4202a05f1fffffff | t
+ \x4202a05f20000000 |             10000000000 |             10000000000 | \x4202a05f20000000 | t
+ \x4202a05f20000001 |      10000000000.000002 |      10000000000.000002 | \x4202a05f20000001 | t
+ \x42374876e7ffffff |       99999999999.99998 |       99999999999.99998 | \x42374876e7ffffff | t
+ \x42374876e8000000 |            100000000000 |            100000000000 | \x42374876e8000000 | t
+ \x42374876e8000001 |      100000000000.00002 |      100000000000.00002 | \x42374876e8000001 | t
+ \x426d1a94a1ffffff |       999999999999.9999 |       999999999999.9999 | \x426d1a94a1ffffff | t
+ \x426d1a94a2000000 |           1000000000000 |           1000000000000 | \x426d1a94a2000000 | t
+ \x426d1a94a2000001 |      1000000000000.0001 |      1000000000000.0001 | \x426d1a94a2000001 | t
+ \x42a2309ce53fffff |       9999999999999.998 |       9999999999999.998 | \x42a2309ce53fffff | t
+ \x42a2309ce5400000 |          10000000000000 |          10000000000000 | \x42a2309ce5400000 | t
+ \x42a2309ce5400001 |      10000000000000.002 |      10000000000000.002 | \x42a2309ce5400001 | t
+ \x42d6bcc41e8fffff |       99999999999999.98 |       99999999999999.98 | \x42d6bcc41e8fffff | t
+ \x42d6bcc41e900000 |         100000000000000 |         100000000000000 | \x42d6bcc41e900000 | t
+ \x42d6bcc41e900001 |      100000000000000.02 |      100000000000000.02 | \x42d6bcc41e900001 | t
+ \x430c6bf52633ffff |       999999999999999.9 |       999999999999999.9 | \x430c6bf52633ffff | t
+ \x430c6bf526340000 |                   1e+15 |                   1e+15 | \x430c6bf526340000 | t
+ \x430c6bf526340001 |  1.0000000000000001e+15 |  1.0000000000000001e+15 | \x430c6bf526340001 | t
+ \x4341c37937e07fff |   9.999999999999998e+15 |   9.999999999999998e+15 | \x4341c37937e07fff | t
+ \x4341c37937e08000 |                   1e+16 |                   1e+16 | \x4341c37937e08000 | t
+ \x4341c37937e08001 |  1.0000000000000002e+16 |  1.0000000000000002e+16 | \x4341c37937e08001 | t
+ \x4376345785d89fff |   9.999999999999998e+16 |   9.999999999999998e+16 | \x4376345785d89fff | t
+ \x4376345785d8a000 |                   1e+17 |                   1e+17 | \x4376345785d8a000 | t
+ \x4376345785d8a001 |  1.0000000000000002e+17 |  1.0000000000000002e+17 | \x4376345785d8a001 | t
+ \x43abc16d674ec7ff |   9.999999999999999e+17 |   9.999999999999999e+17 | \x43abc16d674ec7ff | t
+ \x43abc16d674ec800 |                   1e+18 |                   1e+18 | \x43abc16d674ec800 | t
+ \x43abc16d674ec801 |  1.0000000000000001e+18 |  1.0000000000000001e+18 | \x43abc16d674ec801 | t
+ \x43e158e460913cff |   9.999999999999998e+18 |   9.999999999999998e+18 | \x43e158e460913cff | t
+ \x43e158e460913d00 |                   1e+19 |                   1e+19 | \x43e158e460913d00 | t
+ \x43e158e460913d01 |  1.0000000000000002e+19 |  1.0000000000000002e+19 | \x43e158e460913d01 | t
+ \x4415af1d78b58c3f |   9.999999999999998e+19 |   9.999999999999998e+19 | \x4415af1d78b58c3f | t
+ \x4415af1d78b58c40 |                   1e+20 |                   1e+20 | \x4415af1d78b58c40 | t
+ \x4415af1d78b58c41 |  1.0000000000000002e+20 |  1.0000000000000002e+20 | \x4415af1d78b58c41 | t
+ \x444b1ae4d6e2ef4f |   9.999999999999999e+20 |   9.999999999999999e+20 | \x444b1ae4d6e2ef4f | t
+ \x444b1ae4d6e2ef50 |                   1e+21 |                   1e+21 | \x444b1ae4d6e2ef50 | t
+ \x444b1ae4d6e2ef51 |  1.0000000000000001e+21 |  1.0000000000000001e+21 | \x444b1ae4d6e2ef51 | t
+ \x4480f0cf064dd591 |   9.999999999999998e+21 |   9.999999999999998e+21 | \x4480f0cf064dd591 | t
+ \x4480f0cf064dd592 |                   1e+22 |                   1e+22 | \x4480f0cf064dd592 | t
+ \x4480f0cf064dd593 |  1.0000000000000002e+22 |  1.0000000000000002e+22 | \x4480f0cf064dd593 | t
+ \x44b52d02c7e14af5 |   9.999999999999997e+22 |   9.999999999999997e+22 | \x44b52d02c7e14af5 | t
+ \x44b52d02c7e14af6 |   9.999999999999999e+22 |   9.999999999999999e+22 | \x44b52d02c7e14af6 | t
+ \x44b52d02c7e14af7 |  1.0000000000000001e+23 |  1.0000000000000001e+23 | \x44b52d02c7e14af7 | t
+ \x44ea784379d99db3 |   9.999999999999998e+23 |   9.999999999999998e+23 | \x44ea784379d99db3 | t
+ \x44ea784379d99db4 |                   1e+24 |                   1e+24 | \x44ea784379d99db4 | t
+ \x44ea784379d99db5 |  1.0000000000000001e+24 |  1.0000000000000001e+24 | \x44ea784379d99db5 | t
+ \x45208b2a2c280290 |   9.999999999999999e+24 |   9.999999999999999e+24 | \x45208b2a2c280290 | t
+ \x45208b2a2c280291 |                   1e+25 |                   1e+25 | \x45208b2a2c280291 | t
+ \x45208b2a2c280292 |  1.0000000000000003e+25 |  1.0000000000000003e+25 | \x45208b2a2c280292 | t
+ \x7feffffffffffffe | 1.7976931348623155e+308 | 1.7976931348623155e+308 | \x7feffffffffffffe | t
+ \x7fefffffffffffff | 1.7976931348623157e+308 | 1.7976931348623157e+308 | \x7fefffffffffffff | t
+ \x4350000000000002 |  1.8014398509481992e+16 |  1.8014398509481992e+16 | \x4350000000000002 | t
+ \x4350000000002e06 |  1.8014398509529112e+16 |  1.8014398509529112e+16 | \x4350000000002e06 | t
+ \x4352000000000003 |  2.0266198323167244e+16 |  2.0266198323167244e+16 | \x4352000000000003 | t
+ \x4352000000000004 |  2.0266198323167248e+16 |  2.0266198323167248e+16 | \x4352000000000004 | t
+ \x4358000000000003 |  2.7021597764222988e+16 |  2.7021597764222988e+16 | \x4358000000000003 | t
+ \x4358000000000004 |  2.7021597764222992e+16 |  2.7021597764222992e+16 | \x4358000000000004 | t
+ \x435f000000000020 |  3.4902897112121472e+16 |  3.4902897112121472e+16 | \x435f000000000020 | t
+ \xc350000000000002 | -1.8014398509481992e+16 | -1.8014398509481992e+16 | \xc350000000000002 | t
+ \xc350000000002e06 | -1.8014398509529112e+16 | -1.8014398509529112e+16 | \xc350000000002e06 | t
+ \xc352000000000003 | -2.0266198323167244e+16 | -2.0266198323167244e+16 | \xc352000000000003 | t
+ \xc352000000000004 | -2.0266198323167248e+16 | -2.0266198323167248e+16 | \xc352000000000004 | t
+ \xc358000000000003 | -2.7021597764222988e+16 | -2.7021597764222988e+16 | \xc358000000000003 | t
+ \xc358000000000004 | -2.7021597764222992e+16 | -2.7021597764222992e+16 | \xc358000000000004 | t
+ \xc35f000000000020 | -3.4902897112121472e+16 | -3.4902897112121472e+16 | \xc35f000000000020 | t
+ \x42dc12218377de66 |       123456789012345.6 |       123456789012345.6 | \x42dc12218377de66 | t
+ \x42a674e79c5fe51f |       12345678901234.56 |       12345678901234.56 | \x42a674e79c5fe51f | t
+ \x4271f71fb04cb74c |       1234567890123.456 |       1234567890123.456 | \x4271f71fb04cb74c | t
+ \x423cbe991a145879 |       123456789012.3456 |       123456789012.3456 | \x423cbe991a145879 | t
+ \x4206fee0e1a9e061 |       12345678901.23456 |       12345678901.23456 | \x4206fee0e1a9e061 | t
+ \x41d26580b487e6b4 |       1234567890.123456 |       1234567890.123456 | \x41d26580b487e6b4 | t
+ \x419d6f34540ca453 |       123456789.0123456 |       123456789.0123456 | \x419d6f34540ca453 | t
+ \x41678c29dcd6e9dc |       12345678.90123456 |       12345678.90123456 | \x41678c29dcd6e9dc | t
+ \x4132d687e3df217d |       1234567.890123456 |       1234567.890123456 | \x4132d687e3df217d | t
+ \x40fe240c9fcb68c8 |       123456.7890123456 |       123456.7890123456 | \x40fe240c9fcb68c8 | t
+ \x40c81cd6e63c53d3 |       12345.67890123456 |       12345.67890123456 | \x40c81cd6e63c53d3 | t
+ \x40934a4584fd0fdc |       1234.567890123456 |       1234.567890123456 | \x40934a4584fd0fdc | t
+ \x405edd3c07fb4c93 |       123.4567890123456 |       123.4567890123456 | \x405edd3c07fb4c93 | t
+ \x4028b0fcd32f7076 |       12.34567890123456 |       12.34567890123456 | \x4028b0fcd32f7076 | t
+ \x3ff3c0ca428c59f8 |       1.234567890123456 |       1.234567890123456 | \x3ff3c0ca428c59f8 | t
+ \x3e60000000000000 |  2.9802322387695312e-08 |  2.9802322387695312e-08 | \x3e60000000000000 | t
+ \xc352bd2668e077c4 | -2.1098088986959632e+16 | -2.1098088986959632e+16 | \xc352bd2668e077c4 | t
+ \x434018601510c000 |     9.0608011534336e+15 |     9.0608011534336e+15 | \x434018601510c000 | t
+ \x43d055dc36f24000 |   4.708356024711512e+18 |   4.708356024711512e+18 | \x43d055dc36f24000 | t
+ \x43e052961c6f8000 |   9.409340012568248e+18 |   9.409340012568248e+18 | \x43e052961c6f8000 | t
+ \x3ff3c0ca2a5b1d5d |               1.2345678 |               1.2345678 | \x3ff3c0ca2a5b1d5d | t
+ \x4830f0cf064dd592 |   5.764607523034235e+39 |   5.764607523034235e+39 | \x4830f0cf064dd592 | t
+ \x4840f0cf064dd592 |   1.152921504606847e+40 |   1.152921504606847e+40 | \x4840f0cf064dd592 | t
+ \x4850f0cf064dd592 |   2.305843009213694e+40 |   2.305843009213694e+40 | \x4850f0cf064dd592 | t
+ \x3ff3333333333333 |                     1.2 |                     1.2 | \x3ff3333333333333 | t
+ \x3ff3ae147ae147ae |                    1.23 |                    1.23 | \x3ff3ae147ae147ae | t
+ \x3ff3be76c8b43958 |                   1.234 |                   1.234 | \x3ff3be76c8b43958 | t
+ \x3ff3c083126e978d |                  1.2345 |                  1.2345 | \x3ff3c083126e978d | t
+ \x3ff3c0c1fc8f3238 |                 1.23456 |                 1.23456 | \x3ff3c0c1fc8f3238 | t
+ \x3ff3c0c9539b8887 |                1.234567 |                1.234567 | \x3ff3c0c9539b8887 | t
+ \x3ff3c0ca2a5b1d5d |               1.2345678 |               1.2345678 | \x3ff3c0ca2a5b1d5d | t
+ \x3ff3c0ca4283de1b |              1.23456789 |              1.23456789 | \x3ff3c0ca4283de1b | t
+ \x3ff3c0ca43db770a |             1.234567895 |             1.234567895 | \x3ff3c0ca43db770a | t
+ \x3ff3c0ca428abd53 |            1.2345678901 |            1.2345678901 | \x3ff3c0ca428abd53 | t
+ \x3ff3c0ca428c1d2b |           1.23456789012 |           1.23456789012 | \x3ff3c0ca428c1d2b | t
+ \x3ff3c0ca428c51f2 |          1.234567890123 |          1.234567890123 | \x3ff3c0ca428c51f2 | t
+ \x3ff3c0ca428c58fc |         1.2345678901234 |         1.2345678901234 | \x3ff3c0ca428c58fc | t
+ \x3ff3c0ca428c59dd |        1.23456789012345 |        1.23456789012345 | \x3ff3c0ca428c59dd | t
+ \x3ff3c0ca428c59f8 |       1.234567890123456 |       1.234567890123456 | \x3ff3c0ca428c59f8 | t
+ \x3ff3c0ca428c59fb |      1.2345678901234567 |      1.2345678901234567 | \x3ff3c0ca428c59fb | t
+ \x40112e0be8047a7d |             4.294967294 |             4.294967294 | \x40112e0be8047a7d | t
+ \x40112e0be815a889 |             4.294967295 |             4.294967295 | \x40112e0be815a889 | t
+ \x40112e0be826d695 |             4.294967296 |             4.294967296 | \x40112e0be826d695 | t
+ \x40112e0be83804a1 |             4.294967297 |             4.294967297 | \x40112e0be83804a1 | t
+ \x40112e0be84932ad |             4.294967298 |             4.294967298 | \x40112e0be84932ad | t
+ \x0040000000000000 | 1.7800590868057611e-307 | 1.7800590868057611e-307 | \x0040000000000000 | t
+ \x007fffffffffffff | 2.8480945388892175e-306 | 2.8480945388892175e-306 | \x007fffffffffffff | t
+ \x0290000000000000 |  2.446494580089078e-296 |  2.446494580089078e-296 | \x0290000000000000 | t
+ \x029fffffffffffff | 4.8929891601781557e-296 | 4.8929891601781557e-296 | \x029fffffffffffff | t
+ \x4350000000000000 |  1.8014398509481984e+16 |  1.8014398509481984e+16 | \x4350000000000000 | t
+ \x435fffffffffffff |  3.6028797018963964e+16 |  3.6028797018963964e+16 | \x435fffffffffffff | t
+ \x1330000000000000 |  2.900835519859558e-216 |  2.900835519859558e-216 | \x1330000000000000 | t
+ \x133fffffffffffff |  5.801671039719115e-216 |  5.801671039719115e-216 | \x133fffffffffffff | t
+ \x3a6fa7161a4d6e0c |   3.196104012172126e-27 |   3.196104012172126e-27 | \x3a6fa7161a4d6e0c | t
+(209 rows)
+
+-- clean up, lest opr_sanity complain
+\set VERBOSITY terse
+drop type xfloat8 cascade;
+NOTICE:  drop cascades to 6 other objects
+\set VERBOSITY default
+--
diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out
index 35e3b3ff81..8447a28c3d 100644
--- a/src/test/regress/expected/int8.out
+++ b/src/test/regress/expected/int8.out
@@ -329,23 +329,23 @@ SELECT '' AS five, q1, q2, q1 / q2 AS divide, q1 % q2 AS mod FROM INT8_TBL;
 (5 rows)
 
 SELECT '' AS five, q1, float8(q1) FROM INT8_TBL;
- five |        q1        |        float8        
-------+------------------+----------------------
-      |              123 |                  123
-      |              123 |                  123
-      | 4567890123456789 | 4.56789012345679e+15
-      | 4567890123456789 | 4.56789012345679e+15
-      | 4567890123456789 | 4.56789012345679e+15
+ five |        q1        |        float8         
+------+------------------+-----------------------
+      |              123 |                   123
+      |              123 |                   123
+      | 4567890123456789 | 4.567890123456789e+15
+      | 4567890123456789 | 4.567890123456789e+15
+      | 4567890123456789 | 4.567890123456789e+15
 (5 rows)
 
 SELECT '' AS five, q2, float8(q2) FROM INT8_TBL;
- five |        q2         |        float8         
-------+-------------------+-----------------------
-      |               456 |                   456
-      |  4567890123456789 |  4.56789012345679e+15
-      |               123 |                   123
-      |  4567890123456789 |  4.56789012345679e+15
-      | -4567890123456789 | -4.56789012345679e+15
+ five |        q2         |         float8         
+------+-------------------+------------------------
+      |               456 |                    456
+      |  4567890123456789 |  4.567890123456789e+15
+      |               123 |                    123
+      |  4567890123456789 |  4.567890123456789e+15
+      | -4567890123456789 | -4.567890123456789e+15
 (5 rows)
 
 SELECT 37 + q1 AS plus4 FROM INT8_TBL;
@@ -726,13 +726,13 @@ SELECT CAST('42'::int2 AS int8), CAST('-37'::int2 AS int8);
 (1 row)
 
 SELECT CAST(q1 AS float4), CAST(q2 AS float8) FROM INT8_TBL;
-     q1      |          q2           
--------------+-----------------------
-         123 |                   456
-         123 |  4.56789012345679e+15
- 4.56789e+15 |                   123
- 4.56789e+15 |  4.56789012345679e+15
- 4.56789e+15 | -4.56789012345679e+15
+     q1      |           q2           
+-------------+------------------------
+         123 |                    456
+         123 |  4.567890123456789e+15
+ 4.56789e+15 |                    123
+ 4.56789e+15 |  4.567890123456789e+15
+ 4.56789e+15 | -4.567890123456789e+15
 (5 rows)
 
 SELECT CAST('36854775807.0'::float4 AS int8);
diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out
index 0ac47fcaee..8dcdaf5602 100644
--- a/src/test/regress/expected/jsonb.out
+++ b/src/test/regress/expected/jsonb.out
@@ -4376,9 +4376,9 @@ select '12345.05'::jsonb::numeric;
 (1 row)
 
 select '12345.05'::jsonb::float4;
- float4 
---------
-  12345
+  float4  
+----------
+ 12345.05
 (1 row)
 
 select '12345.05'::jsonb::float8;
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
index bf780daa2c..fe106589c6 100644
--- a/src/test/regress/expected/line.out
+++ b/src/test/regress/expected/line.out
@@ -64,14 +64,14 @@ LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,2),(1,2)]');
 INSERT INTO LINE_TBL VALUES (line(point '(1,0)', point '(1,0)'));
 ERROR:  invalid line specification: must be two distinct points
 select * from LINE_TBL;
-                      s                      
----------------------------------------------
+                       s                        
+------------------------------------------------
  {0,-1,5}
  {1,0,5}
  {0,3,0}
  {1,-1,0}
  {-0.4,-1,-6}
- {-0.000184615384615385,-1,15.3846153846154}
+ {-0.0001846153846153846,-1,15.384615384615387}
  {3,NaN,5}
  {NaN,NaN,NaN}
  {0,-1,3}
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index c18e865370..15e3b83b37 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -1,6 +1,8 @@
 --
 -- POINT
 --
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
 CREATE TABLE POINT_TBL(f1 point);
 INSERT INTO POINT_TBL(f1) VALUES ('(0.0,0.0)');
 INSERT INTO POINT_TBL(f1) VALUES ('(-10.0,0.0)');
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 2c8e21baa7..b31594a7b5 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -910,24 +910,24 @@ insert into rtest_comp values ('p4', 'cm', 15.0);
 insert into rtest_comp values ('p5', 'inch', 7.0);
 insert into rtest_comp values ('p6', 'inch', 4.4);
 select * from rtest_vcomp order by part;
- part | size_in_cm 
-------+------------
- p1   |        500
- p2   |        300
- p3   |          5
- p4   |         15
- p5   |      17.78
- p6   |     11.176
+ part |     size_in_cm     
+------+--------------------
+ p1   |                500
+ p2   |                300
+ p3   |                  5
+ p4   |                 15
+ p5   |              17.78
+ p6   | 11.176000000000002
 (6 rows)
 
 select * from rtest_vcomp where size_in_cm > 10.0 order by size_in_cm using >;
- part | size_in_cm 
-------+------------
- p1   |        500
- p2   |        300
- p5   |      17.78
- p4   |         15
- p6   |     11.176
+ part |     size_in_cm     
+------+--------------------
+ p1   |                500
+ p2   |                300
+ p5   |              17.78
+ p4   |                 15
+ p6   | 11.176000000000002
 (5 rows)
 
 --
diff --git a/src/test/regress/expected/tsearch.out b/src/test/regress/expected/tsearch.out
index b088ff0d4f..6f61acc1ed 100644
--- a/src/test/regress/expected/tsearch.out
+++ b/src/test/regress/expected/tsearch.out
@@ -970,9 +970,9 @@ Water, water, every where,
   Nor any drop to drink.
 S. T. Coleridge (1772-1834)
 '), to_tsquery('english', 'breath&motion&water'));
- ts_rank_cd 
-------------
- 0.00833333
+ ts_rank_cd  
+-------------
+ 0.008333334
 (1 row)
 
 SELECT ts_rank_cd(to_tsvector('english', '
diff --git a/src/test/regress/expected/tstypes.out b/src/test/regress/expected/tstypes.out
index 6272e70e09..87a36ca329 100644
--- a/src/test/regress/expected/tstypes.out
+++ b/src/test/regress/expected/tstypes.out
@@ -787,57 +787,57 @@ select to_tsvector('simple', '') @@ '!foo' AS "true";
 
 --ranking
 SELECT ts_rank(' a:1 s:2C d g'::tsvector, 'a | s');
-  ts_rank  
------------
- 0.0911891
+   ts_rank   
+-------------
+ 0.091189064
 (1 row)
 
 SELECT ts_rank(' a:1 sa:2C d g'::tsvector, 'a | s');
-  ts_rank  
------------
- 0.0303964
+   ts_rank   
+-------------
+ 0.030396355
 (1 row)
 
 SELECT ts_rank(' a:1 sa:2C d g'::tsvector, 'a | s:*');
-  ts_rank  
------------
- 0.0911891
+   ts_rank   
+-------------
+ 0.091189064
 (1 row)
 
 SELECT ts_rank(' a:1 sa:2C d g'::tsvector, 'a | sa:*');
-  ts_rank  
------------
- 0.0911891
+   ts_rank   
+-------------
+ 0.091189064
 (1 row)
 
 SELECT ts_rank(' a:1 s:2B d g'::tsvector, 'a | s');
- ts_rank  
-----------
- 0.151982
+  ts_rank   
+------------
+ 0.15198177
 (1 row)
 
 SELECT ts_rank(' a:1 s:2 d g'::tsvector, 'a | s');
-  ts_rank  
------------
- 0.0607927
+  ts_rank   
+------------
+ 0.06079271
 (1 row)
 
 SELECT ts_rank(' a:1 s:2C d g'::tsvector, 'a & s');
- ts_rank  
-----------
- 0.140153
+  ts_rank   
+------------
+ 0.14015312
 (1 row)
 
 SELECT ts_rank(' a:1 s:2B d g'::tsvector, 'a & s');
- ts_rank  
-----------
- 0.198206
+  ts_rank   
+------------
+ 0.19820644
 (1 row)
 
 SELECT ts_rank(' a:1 s:2 d g'::tsvector, 'a & s');
-  ts_rank  
------------
- 0.0991032
+  ts_rank   
+------------
+ 0.09910322
 (1 row)
 
 SELECT ts_rank_cd(' a:1 s:2C d g'::tsvector, 'a | s');
@@ -885,7 +885,7 @@ SELECT ts_rank_cd(' a:1 s:2 d g'::tsvector, 'a | s');
 SELECT ts_rank_cd(' a:1 s:2C d g'::tsvector, 'a & s');
  ts_rank_cd 
 ------------
-   0.133333
+ 0.13333334
 (1 row)
 
 SELECT ts_rank_cd(' a:1 s:2B d g'::tsvector, 'a & s');
@@ -903,13 +903,13 @@ SELECT ts_rank_cd(' a:1 s:2 d g'::tsvector, 'a & s');
 SELECT ts_rank_cd(' a:1 s:2A d g'::tsvector, 'a <-> s');
  ts_rank_cd 
 ------------
-   0.181818
+ 0.18181819
 (1 row)
 
 SELECT ts_rank_cd(' a:1 s:2C d g'::tsvector, 'a <-> s');
  ts_rank_cd 
 ------------
-   0.133333
+ 0.13333334
 (1 row)
 
 SELECT ts_rank_cd(' a:1 s:2 d g'::tsvector, 'a <-> s');
@@ -927,13 +927,13 @@ SELECT ts_rank_cd(' a:1 s:2 d:2A g'::tsvector, 'a <-> s');
 SELECT ts_rank_cd(' a:1 s:2,3A d:2A g'::tsvector, 'a <2> s:A');
  ts_rank_cd 
 ------------
-  0.0909091
+ 0.09090909
 (1 row)
 
 SELECT ts_rank_cd(' a:1 b:2 s:3A d:2A g'::tsvector, 'a <2> s:A');
  ts_rank_cd 
 ------------
-  0.0909091
+ 0.09090909
 (1 row)
 
 SELECT ts_rank_cd(' a:1 sa:2D sb:2A g'::tsvector, 'a <-> s:*');
diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out
index 420c5a54f2..8b13ef3a09 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -1,6 +1,8 @@
 --
 -- UPDATABLE VIEWS
 --
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
 -- check that non-updatable views and columns are rejected with useful error
 -- messages
 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
diff --git a/src/test/regress/expected/window.out b/src/test/regress/expected/window.out
index 662d348653..edc93d5729 100644
--- a/src/test/regress/expected/window.out
+++ b/src/test/regress/expected/window.out
@@ -204,33 +204,33 @@ SELECT dense_rank() OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1
 (10 rows)
 
 SELECT percent_rank() OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
-   percent_rank    | ten | four 
--------------------+-----+------
-                 0 |   0 |    0
-                 0 |   0 |    0
-                 1 |   4 |    0
-                 0 |   1 |    1
-                 0 |   1 |    1
- 0.666666666666667 |   7 |    1
-                 1 |   9 |    1
-                 0 |   0 |    2
-                 0 |   1 |    3
-                 1 |   3 |    3
+    percent_rank    | ten | four 
+--------------------+-----+------
+                  0 |   0 |    0
+                  0 |   0 |    0
+                  1 |   4 |    0
+                  0 |   1 |    1
+                  0 |   1 |    1
+ 0.6666666666666666 |   7 |    1
+                  1 |   9 |    1
+                  0 |   0 |    2
+                  0 |   1 |    3
+                  1 |   3 |    3
 (10 rows)
 
 SELECT cume_dist() OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
-     cume_dist     | ten | four 
--------------------+-----+------
- 0.666666666666667 |   0 |    0
- 0.666666666666667 |   0 |    0
-                 1 |   4 |    0
-               0.5 |   1 |    1
-               0.5 |   1 |    1
-              0.75 |   7 |    1
-                 1 |   9 |    1
-                 1 |   0 |    2
-               0.5 |   1 |    3
-                 1 |   3 |    3
+     cume_dist      | ten | four 
+--------------------+-----+------
+ 0.6666666666666666 |   0 |    0
+ 0.6666666666666666 |   0 |    0
+                  1 |   4 |    0
+                0.5 |   1 |    1
+                0.5 |   1 |    1
+               0.75 |   7 |    1
+                  1 |   9 |    1
+                  1 |   0 |    2
+                0.5 |   1 |    3
+                  1 |   3 |    3
 (10 rows)
 
 SELECT ntile(3) OVER (ORDER BY ten, four), ten, four FROM tenk1 WHERE unique2 < 10;
diff --git a/src/test/regress/resultmap b/src/test/regress/resultmap
index 46ca5639c2..3bd1585a35 100644
--- a/src/test/regress/resultmap
+++ b/src/test/regress/resultmap
@@ -3,3 +3,4 @@ float8:out:i.86-.*-openbsd=float8-small-is-zero.out
 float8:out:i.86-.*-netbsd=float8-small-is-zero.out
 float8:out:m68k-.*-netbsd=float8-small-is-zero.out
 float8:out:i.86-pc-cygwin=float8-small-is-zero.out
+float4:out:hppa.*-hp-hpux10.*=float4-misrounded-input.out
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index a09fa47ae4..d4fd657188 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -2,6 +2,9 @@
 -- AGGREGATES
 --
 
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
+
 SELECT avg(four) AS avg_1 FROM onek;
 
 SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100;
diff --git a/src/test/regress/sql/circle.sql b/src/test/regress/sql/circle.sql
index 46c96e1400..10e51d780e 100644
--- a/src/test/regress/sql/circle.sql
+++ b/src/test/regress/sql/circle.sql
@@ -2,6 +2,9 @@
 -- CIRCLE
 --
 
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
+
 CREATE TABLE CIRCLE_TBL (f1 circle);
 
 INSERT INTO CIRCLE_TBL VALUES ('<(5,1),3>');
diff --git a/src/test/regress/sql/float4.sql b/src/test/regress/sql/float4.sql
index 46a9166d13..d606e7787b 100644
--- a/src/test/regress/sql/float4.sql
+++ b/src/test/regress/sql/float4.sql
@@ -16,6 +16,11 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
 INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
 INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
 
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e400');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e400');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-400');
+INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-400');
+
 -- bad input
 INSERT INTO FLOAT4_TBL(f1) VALUES ('');
 INSERT INTO FLOAT4_TBL(f1) VALUES ('       ');
@@ -95,3 +100,254 @@ SELECT '9223369837831520256'::float4::int8;
 SELECT '9223372036854775807'::float4::int8;
 SELECT '-9223372036854775808.5'::float4::int8;
 SELECT '-9223380000000000000'::float4::int8;
+
+-- Test for correct input rounding in edge cases.
+-- These lists are from Paxson 1991, excluding subnormals and
+-- inputs of over 9 sig. digits.
+
+SELECT float4send('5e-20'::float4);
+SELECT float4send('67e14'::float4);
+SELECT float4send('985e15'::float4);
+SELECT float4send('55895e-16'::float4);
+SELECT float4send('7038531e-32'::float4);
+SELECT float4send('702990899e-20'::float4);
+
+SELECT float4send('3e-23'::float4);
+SELECT float4send('57e18'::float4);
+SELECT float4send('789e-35'::float4);
+SELECT float4send('2539e-18'::float4);
+SELECT float4send('76173e28'::float4);
+SELECT float4send('887745e-11'::float4);
+SELECT float4send('5382571e-37'::float4);
+SELECT float4send('82381273e-35'::float4);
+SELECT float4send('750486563e-38'::float4);
+
+-- Test that the smallest possible normalized input value inputs
+-- correctly, either in 9-significant-digit or shortest-decimal
+-- format.
+--
+-- exact val is             1.1754943508...
+-- shortest val is          1.1754944000
+-- midpoint to next val is  1.1754944208...
+
+SELECT float4send('1.17549435e-38'::float4);
+SELECT float4send('1.1754944e-38'::float4);
+
+-- test output (and round-trip safety) of various values.
+-- To ensure we're testing what we think we're testing, start with
+-- float values specified by bit patterns (as a useful side effect,
+-- this means we'll fail on non-IEEE platforms).
+
+create type xfloat4;
+create function xfloat4in(cstring) returns xfloat4 immutable strict
+  language internal as 'int4in';
+create function xfloat4out(xfloat4) returns cstring immutable strict
+  language internal as 'int4out';
+create type xfloat4 (input = xfloat4in, output = xfloat4out, like = float4);
+create cast (xfloat4 as float4) without function;
+create cast (float4 as xfloat4) without function;
+create cast (xfloat4 as integer) without function;
+create cast (integer as xfloat4) without function;
+
+-- float4: seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
+
+-- we don't care to assume the platform's strtod() handles subnormals
+-- correctly; those are "use at your own risk". However we do test
+-- subnormal outputs, since those are under our control.
+
+with testdata(bits) as (values
+  -- small subnormals
+  (x'00000001'),
+  (x'00000002'), (x'00000003'),
+  (x'00000010'), (x'00000011'), (x'00000100'), (x'00000101'),
+  (x'00004000'), (x'00004001'), (x'00080000'), (x'00080001'),
+  -- stress values
+  (x'0053c4f4'),  -- 7693e-42
+  (x'006c85c4'),  -- 996622e-44
+  (x'0041ca76'),  -- 60419369e-46
+  (x'004b7678'),  -- 6930161142e-48
+  -- taken from upstream testsuite
+  (x'00000007'),
+  (x'00424fe2'),
+  -- borderline between subnormal and normal
+  (x'007ffff0'), (x'007ffff1'), (x'007ffffe'), (x'007fffff'))
+select float4send(flt) as ibits,
+       flt
+  from (select bits::integer::xfloat4::float4 as flt
+          from testdata
+	offset 0) s;
+
+with testdata(bits) as (values
+  (x'00000000'),
+  -- smallest normal values
+  (x'00800000'), (x'00800001'), (x'00800004'), (x'00800005'),
+  (x'00800006'),
+  -- small normal values chosen for short vs. long output
+  (x'008002f1'), (x'008002f2'), (x'008002f3'),
+  (x'00800e17'), (x'00800e18'), (x'00800e19'),
+  -- assorted values (random mantissae)
+  (x'01000001'), (x'01102843'), (x'01a52c98'),
+  (x'0219c229'), (x'02e4464d'), (x'037343c1'), (x'03a91b36'),
+  (x'047ada65'), (x'0496fe87'), (x'0550844f'), (x'05999da3'),
+  (x'060ea5e2'), (x'06e63c45'), (x'07f1e548'), (x'0fc5282b'),
+  (x'1f850283'), (x'2874a9d6'),
+  -- values around 5e-08
+  (x'3356bf94'), (x'3356bf95'), (x'3356bf96'),
+  -- around 1e-07
+  (x'33d6bf94'), (x'33d6bf95'), (x'33d6bf96'),
+  -- around 3e-07 .. 1e-04
+  (x'34a10faf'), (x'34a10fb0'), (x'34a10fb1'),
+  (x'350637bc'), (x'350637bd'), (x'350637be'),
+  (x'35719786'), (x'35719787'), (x'35719788'),
+  (x'358637bc'), (x'358637bd'), (x'358637be'),
+  (x'36a7c5ab'), (x'36a7c5ac'), (x'36a7c5ad'),
+  (x'3727c5ab'), (x'3727c5ac'), (x'3727c5ad'),
+  -- format crossover at 1e-04
+  (x'38d1b714'), (x'38d1b715'), (x'38d1b716'),
+  (x'38d1b717'), (x'38d1b718'), (x'38d1b719'),
+  (x'38d1b71a'), (x'38d1b71b'), (x'38d1b71c'),
+  (x'38d1b71d'),
+  --
+  (x'38dffffe'), (x'38dfffff'), (x'38e00000'),
+  (x'38efffff'), (x'38f00000'), (x'38f00001'),
+  (x'3a83126e'), (x'3a83126f'), (x'3a831270'),
+  (x'3c23d709'), (x'3c23d70a'), (x'3c23d70b'),
+  (x'3dcccccc'), (x'3dcccccd'), (x'3dccccce'),
+  -- chosen to need 9 digits for 3dcccd70
+  (x'3dcccd6f'), (x'3dcccd70'), (x'3dcccd71'),
+  --
+  (x'3effffff'), (x'3f000000'), (x'3f000001'),
+  (x'3f333332'), (x'3f333333'), (x'3f333334'),
+  -- approach 1.0 with increasing numbers of 9s
+  (x'3f666665'), (x'3f666666'), (x'3f666667'),
+  (x'3f7d70a3'), (x'3f7d70a4'), (x'3f7d70a5'),
+  (x'3f7fbe76'), (x'3f7fbe77'), (x'3f7fbe78'),
+  (x'3f7ff971'), (x'3f7ff972'), (x'3f7ff973'),
+  (x'3f7fff57'), (x'3f7fff58'), (x'3f7fff59'),
+  (x'3f7fffee'), (x'3f7fffef'),
+  -- values very close to 1
+  (x'3f7ffff0'), (x'3f7ffff1'), (x'3f7ffff2'),
+  (x'3f7ffff3'), (x'3f7ffff4'), (x'3f7ffff5'),
+  (x'3f7ffff6'), (x'3f7ffff7'), (x'3f7ffff8'),
+  (x'3f7ffff9'), (x'3f7ffffa'), (x'3f7ffffb'),
+  (x'3f7ffffc'), (x'3f7ffffd'), (x'3f7ffffe'),
+  (x'3f7fffff'),
+  (x'3f800000'),
+  (x'3f800001'), (x'3f800002'), (x'3f800003'),
+  (x'3f800004'), (x'3f800005'), (x'3f800006'),
+  (x'3f800007'), (x'3f800008'), (x'3f800009'),
+  -- values 1 to 1.1
+  (x'3f80000f'), (x'3f800010'), (x'3f800011'),
+  (x'3f800012'), (x'3f800013'), (x'3f800014'),
+  (x'3f800017'), (x'3f800018'), (x'3f800019'),
+  (x'3f80001a'), (x'3f80001b'), (x'3f80001c'),
+  (x'3f800029'), (x'3f80002a'), (x'3f80002b'),
+  (x'3f800053'), (x'3f800054'), (x'3f800055'),
+  (x'3f800346'), (x'3f800347'), (x'3f800348'),
+  (x'3f8020c4'), (x'3f8020c5'), (x'3f8020c6'),
+  (x'3f8147ad'), (x'3f8147ae'), (x'3f8147af'),
+  (x'3f8ccccc'), (x'3f8ccccd'), (x'3f8cccce'),
+  --
+  (x'3fc90fdb'), -- pi/2
+  (x'402df854'), -- e
+  (x'40490fdb'), -- pi
+  --
+  (x'409fffff'), (x'40a00000'), (x'40a00001'),
+  (x'40afffff'), (x'40b00000'), (x'40b00001'),
+  (x'411fffff'), (x'41200000'), (x'41200001'),
+  (x'42c7ffff'), (x'42c80000'), (x'42c80001'),
+  (x'4479ffff'), (x'447a0000'), (x'447a0001'),
+  (x'461c3fff'), (x'461c4000'), (x'461c4001'),
+  (x'47c34fff'), (x'47c35000'), (x'47c35001'),
+  (x'497423ff'), (x'49742400'), (x'49742401'),
+  (x'4b18967f'), (x'4b189680'), (x'4b189681'),
+  (x'4cbebc1f'), (x'4cbebc20'), (x'4cbebc21'),
+  (x'4e6e6b27'), (x'4e6e6b28'), (x'4e6e6b29'),
+  (x'501502f8'), (x'501502f9'), (x'501502fa'),
+  (x'51ba43b6'), (x'51ba43b7'), (x'51ba43b8'),
+  -- stress values
+  (x'1f6c1e4a'),  -- 5e-20
+  (x'59be6cea'),  -- 67e14
+  (x'5d5ab6c4'),  -- 985e15
+  (x'2cc4a9bd'),  -- 55895e-16
+  (x'15ae43fd'),  -- 7038531e-32
+  (x'2cf757ca'),  -- 702990899e-20
+  (x'665ba998'),  -- 25933168707e13
+  (x'743c3324'),  -- 596428896559e20
+  -- exercise fixed-point memmoves
+  (x'47f1205a'),
+  (x'4640e6ae'),
+  (x'449a5225'),
+  (x'42f6e9d5'),
+  (x'414587dd'),
+  (x'3f9e064b'),
+  -- these cases come from the upstream's testsuite
+  -- BoundaryRoundEven
+  (x'4c000004'),
+  (x'50061c46'),
+  (x'510006a8'),
+  -- ExactValueRoundEven
+  (x'48951f84'),
+  (x'45fd1840'),
+  -- LotsOfTrailingZeros
+  (x'39800000'),
+  (x'3b200000'),
+  (x'3b900000'),
+  (x'3bd00000'),
+  -- Regression
+  (x'63800000'),
+  (x'4b000000'),
+  (x'4b800000'),
+  (x'4c000001'),
+  (x'4c800b0d'),
+  (x'00d24584'),
+  (x'800000b0'),
+  (x'00d90b88'),
+  (x'45803f34'),
+  (x'4f9f24f7'),
+  (x'3a8722c3'),
+  (x'5c800041'),
+  (x'15ae43fd'),
+  (x'5d4cccfb'),
+  (x'4c800001'),
+  (x'57800ed8'),
+  (x'5f000000'),
+  (x'700000f0'),
+  (x'5f23e9ac'),
+  (x'5e9502f9'),
+  (x'5e8012b1'),
+  (x'3c000028'),
+  (x'60cde861'),
+  (x'03aa2a50'),
+  (x'43480000'),
+  (x'4c000000'),
+  -- LooksLikePow5
+  (x'5D1502F9'),
+  (x'5D9502F9'),
+  (x'5E1502F9'),
+  -- OutputLength
+  (x'3f99999a'),
+  (x'3f9d70a4'),
+  (x'3f9df3b6'),
+  (x'3f9e0419'),
+  (x'3f9e0610'),
+  (x'3f9e064b'),
+  (x'3f9e0651'),
+  (x'03d20cfe')
+)
+select float4send(flt) as ibits,
+       flt,
+       flt::text::float4 as r_flt,
+       float4send(flt::text::float4) as obits,
+       float4send(flt::text::float4) = float4send(flt) as correct
+  from (select bits::integer::xfloat4::float4 as flt
+          from testdata
+	offset 0) s;
+
+-- clean up, lest opr_sanity complain
+
+\set VERBOSITY terse
+drop type xfloat4 cascade;
+\set VERBOSITY default
+
+--
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
index 6595fd2b95..a33321811d 100644
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -16,6 +16,9 @@ SELECT '-10e400'::float8;
 SELECT '10e-400'::float8;
 SELECT '-10e-400'::float8;
 
+-- test smallest normalized input
+SELECT float8send('2.2250738585072014E-308'::float8);
+
 -- bad input
 INSERT INTO FLOAT8_TBL(f1) VALUES ('');
 INSERT INTO FLOAT8_TBL(f1) VALUES ('     ');
@@ -97,6 +100,9 @@ select floor(f1) as floor_f1 from float8_tbl f;
 -- sign
 select sign(f1) as sign_f1 from float8_tbl f;
 
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
+
 -- square root
 SELECT sqrt(float8 '64') AS eight;
 
@@ -148,6 +154,8 @@ SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
 
 SELECT '' AS five, * FROM FLOAT8_TBL;
 
+RESET extra_float_digits;
+
 -- test for over- and underflow
 INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
 
@@ -189,7 +197,6 @@ SELECT '-9223372036854775808.5'::float8::int8;
 SELECT '-9223372036854780000'::float8::int8;
 
 -- test exact cases for trigonometric functions in degrees
-SET extra_float_digits = 3;
 
 SELECT x,
        sind(x),
@@ -232,4 +239,203 @@ SELECT x, y,
 FROM (SELECT 10*cosd(a), 10*sind(a)
       FROM generate_series(0, 360, 90) AS t(a)) AS t(x,y);
 
-RESET extra_float_digits;
+--
+-- test output (and round-trip safety) of various values.
+-- To ensure we're testing what we think we're testing, start with
+-- float values specified by bit patterns (as a useful side effect,
+-- this means we'll fail on non-IEEE platforms).
+
+create type xfloat8;
+create function xfloat8in(cstring) returns xfloat8 immutable strict
+  language internal as 'int8in';
+create function xfloat8out(xfloat8) returns cstring immutable strict
+  language internal as 'int8out';
+create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8);
+create cast (xfloat8 as float8) without function;
+create cast (float8 as xfloat8) without function;
+create cast (xfloat8 as bigint) without function;
+create cast (bigint as xfloat8) without function;
+
+-- float8: seeeeeee eeeeeeee eeeeeeee mmmmmmmm mmmmmmmm(x4)
+
+-- we don't care to assume the platform's strtod() handles subnormals
+-- correctly; those are "use at your own risk". However we do test
+-- subnormal outputs, since those are under our control.
+
+with testdata(bits) as (values
+  -- small subnormals
+  (x'0000000000000001'),
+  (x'0000000000000002'), (x'0000000000000003'),
+  (x'0000000000001000'), (x'0000000100000000'),
+  (x'0000010000000000'), (x'0000010100000000'),
+  (x'0000400000000000'), (x'0000400100000000'),
+  (x'0000800000000000'), (x'0000800000000001'),
+  -- these values taken from upstream testsuite
+  (x'00000000000f4240'),
+  (x'00000000016e3600'),
+  (x'0000008cdcdea440'),
+  -- borderline between subnormal and normal
+  (x'000ffffffffffff0'), (x'000ffffffffffff1'),
+  (x'000ffffffffffffe'), (x'000fffffffffffff'))
+select float8send(flt) as ibits,
+       flt
+  from (select bits::bigint::xfloat8::float8 as flt
+          from testdata
+	offset 0) s;
+
+-- round-trip tests
+
+with testdata(bits) as (values
+  (x'0000000000000000'),
+  -- smallest normal values
+  (x'0010000000000000'), (x'0010000000000001'),
+  (x'0010000000000002'), (x'0018000000000000'),
+  --
+  (x'3ddb7cdfd9d7bdba'), (x'3ddb7cdfd9d7bdbb'), (x'3ddb7cdfd9d7bdbc'),
+  (x'3e112e0be826d694'), (x'3e112e0be826d695'), (x'3e112e0be826d696'),
+  (x'3e45798ee2308c39'), (x'3e45798ee2308c3a'), (x'3e45798ee2308c3b'),
+  (x'3e7ad7f29abcaf47'), (x'3e7ad7f29abcaf48'), (x'3e7ad7f29abcaf49'),
+  (x'3eb0c6f7a0b5ed8c'), (x'3eb0c6f7a0b5ed8d'), (x'3eb0c6f7a0b5ed8e'),
+  (x'3ee4f8b588e368ef'), (x'3ee4f8b588e368f0'), (x'3ee4f8b588e368f1'),
+  (x'3f1a36e2eb1c432c'), (x'3f1a36e2eb1c432d'), (x'3f1a36e2eb1c432e'),
+  (x'3f50624dd2f1a9fb'), (x'3f50624dd2f1a9fc'), (x'3f50624dd2f1a9fd'),
+  (x'3f847ae147ae147a'), (x'3f847ae147ae147b'), (x'3f847ae147ae147c'),
+  (x'3fb9999999999999'), (x'3fb999999999999a'), (x'3fb999999999999b'),
+  -- values very close to 1
+  (x'3feffffffffffff0'), (x'3feffffffffffff1'), (x'3feffffffffffff2'),
+  (x'3feffffffffffff3'), (x'3feffffffffffff4'), (x'3feffffffffffff5'),
+  (x'3feffffffffffff6'), (x'3feffffffffffff7'), (x'3feffffffffffff8'),
+  (x'3feffffffffffff9'), (x'3feffffffffffffa'), (x'3feffffffffffffb'),
+  (x'3feffffffffffffc'), (x'3feffffffffffffd'), (x'3feffffffffffffe'),
+  (x'3fefffffffffffff'),
+  (x'3ff0000000000000'),
+  (x'3ff0000000000001'), (x'3ff0000000000002'), (x'3ff0000000000003'),
+  (x'3ff0000000000004'), (x'3ff0000000000005'), (x'3ff0000000000006'),
+  (x'3ff0000000000007'), (x'3ff0000000000008'), (x'3ff0000000000009'),
+  --
+  (x'3ff921fb54442d18'),
+  (x'4005bf0a8b14576a'),
+  (x'400921fb54442d18'),
+  --
+  (x'4023ffffffffffff'), (x'4024000000000000'), (x'4024000000000001'),
+  (x'4058ffffffffffff'), (x'4059000000000000'), (x'4059000000000001'),
+  (x'408f3fffffffffff'), (x'408f400000000000'), (x'408f400000000001'),
+  (x'40c387ffffffffff'), (x'40c3880000000000'), (x'40c3880000000001'),
+  (x'40f869ffffffffff'), (x'40f86a0000000000'), (x'40f86a0000000001'),
+  (x'412e847fffffffff'), (x'412e848000000000'), (x'412e848000000001'),
+  (x'416312cfffffffff'), (x'416312d000000000'), (x'416312d000000001'),
+  (x'4197d783ffffffff'), (x'4197d78400000000'), (x'4197d78400000001'),
+  (x'41cdcd64ffffffff'), (x'41cdcd6500000000'), (x'41cdcd6500000001'),
+  (x'4202a05f1fffffff'), (x'4202a05f20000000'), (x'4202a05f20000001'),
+  (x'42374876e7ffffff'), (x'42374876e8000000'), (x'42374876e8000001'),
+  (x'426d1a94a1ffffff'), (x'426d1a94a2000000'), (x'426d1a94a2000001'),
+  (x'42a2309ce53fffff'), (x'42a2309ce5400000'), (x'42a2309ce5400001'),
+  (x'42d6bcc41e8fffff'), (x'42d6bcc41e900000'), (x'42d6bcc41e900001'),
+  (x'430c6bf52633ffff'), (x'430c6bf526340000'), (x'430c6bf526340001'),
+  (x'4341c37937e07fff'), (x'4341c37937e08000'), (x'4341c37937e08001'),
+  (x'4376345785d89fff'), (x'4376345785d8a000'), (x'4376345785d8a001'),
+  (x'43abc16d674ec7ff'), (x'43abc16d674ec800'), (x'43abc16d674ec801'),
+  (x'43e158e460913cff'), (x'43e158e460913d00'), (x'43e158e460913d01'),
+  (x'4415af1d78b58c3f'), (x'4415af1d78b58c40'), (x'4415af1d78b58c41'),
+  (x'444b1ae4d6e2ef4f'), (x'444b1ae4d6e2ef50'), (x'444b1ae4d6e2ef51'),
+  (x'4480f0cf064dd591'), (x'4480f0cf064dd592'), (x'4480f0cf064dd593'),
+  (x'44b52d02c7e14af5'), (x'44b52d02c7e14af6'), (x'44b52d02c7e14af7'),
+  (x'44ea784379d99db3'), (x'44ea784379d99db4'), (x'44ea784379d99db5'),
+  (x'45208b2a2c280290'), (x'45208b2a2c280291'), (x'45208b2a2c280292'),
+  --
+  (x'7feffffffffffffe'), (x'7fefffffffffffff'),
+  -- round to even tests (+ve)
+  (x'4350000000000002'),
+  (x'4350000000002e06'),
+  (x'4352000000000003'),
+  (x'4352000000000004'),
+  (x'4358000000000003'),
+  (x'4358000000000004'),
+  (x'435f000000000020'),
+  -- round to even tests (-ve)
+  (x'c350000000000002'),
+  (x'c350000000002e06'),
+  (x'c352000000000003'),
+  (x'c352000000000004'),
+  (x'c358000000000003'),
+  (x'c358000000000004'),
+  (x'c35f000000000020'),
+  -- exercise fixed-point memmoves
+  (x'42dc12218377de66'),
+  (x'42a674e79c5fe51f'),
+  (x'4271f71fb04cb74c'),
+  (x'423cbe991a145879'),
+  (x'4206fee0e1a9e061'),
+  (x'41d26580b487e6b4'),
+  (x'419d6f34540ca453'),
+  (x'41678c29dcd6e9dc'),
+  (x'4132d687e3df217d'),
+  (x'40fe240c9fcb68c8'),
+  (x'40c81cd6e63c53d3'),
+  (x'40934a4584fd0fdc'),
+  (x'405edd3c07fb4c93'),
+  (x'4028b0fcd32f7076'),
+  (x'3ff3c0ca428c59f8'),
+  -- these cases come from the upstream's testsuite
+  -- LotsOfTrailingZeros)
+  (x'3e60000000000000'),
+  -- Regression
+  (x'c352bd2668e077c4'),
+  (x'434018601510c000'),
+  (x'43d055dc36f24000'),
+  (x'43e052961c6f8000'),
+  (x'3ff3c0ca2a5b1d5d'),
+  -- LooksLikePow5
+  (x'4830f0cf064dd592'),
+  (x'4840f0cf064dd592'),
+  (x'4850f0cf064dd592'),
+  -- OutputLength
+  (x'3ff3333333333333'),
+  (x'3ff3ae147ae147ae'),
+  (x'3ff3be76c8b43958'),
+  (x'3ff3c083126e978d'),
+  (x'3ff3c0c1fc8f3238'),
+  (x'3ff3c0c9539b8887'),
+  (x'3ff3c0ca2a5b1d5d'),
+  (x'3ff3c0ca4283de1b'),
+  (x'3ff3c0ca43db770a'),
+  (x'3ff3c0ca428abd53'),
+  (x'3ff3c0ca428c1d2b'),
+  (x'3ff3c0ca428c51f2'),
+  (x'3ff3c0ca428c58fc'),
+  (x'3ff3c0ca428c59dd'),
+  (x'3ff3c0ca428c59f8'),
+  (x'3ff3c0ca428c59fb'),
+  -- 32-bit chunking
+  (x'40112e0be8047a7d'),
+  (x'40112e0be815a889'),
+  (x'40112e0be826d695'),
+  (x'40112e0be83804a1'),
+  (x'40112e0be84932ad'),
+  -- MinMaxShift
+  (x'0040000000000000'),
+  (x'007fffffffffffff'),
+  (x'0290000000000000'),
+  (x'029fffffffffffff'),
+  (x'4350000000000000'),
+  (x'435fffffffffffff'),
+  (x'1330000000000000'),
+  (x'133fffffffffffff'),
+  (x'3a6fa7161a4d6e0c')
+)
+select float8send(flt) as ibits,
+       flt,
+       flt::text::float8 as r_flt,
+       float8send(flt::text::float8) as obits,
+       float8send(flt::text::float8) = float8send(flt) as correct
+  from (select bits::bigint::xfloat8::float8 as flt
+          from testdata
+	offset 0) s;
+
+-- clean up, lest opr_sanity complain
+
+\set VERBOSITY terse
+drop type xfloat8 cascade;
+\set VERBOSITY default
+
+--
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index a209f3bfeb..7f8504dbd1 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -2,6 +2,9 @@
 -- POINT
 --
 
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
+
 CREATE TABLE POINT_TBL(f1 point);
 
 INSERT INTO POINT_TBL(f1) VALUES ('(0.0,0.0)');
diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql
index dc6d5cbe35..2ecc386238 100644
--- a/src/test/regress/sql/updatable_views.sql
+++ b/src/test/regress/sql/updatable_views.sql
@@ -2,6 +2,9 @@
 -- UPDATABLE VIEWS
 --
 
+-- avoid bit-exact output here because operations may not be bit-exact.
+SET extra_float_digits = 0;
+
 -- check that non-updatable views and columns are rejected with useful error
 -- messages
 
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 56192f1b20..5251a21d34 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -105,6 +105,8 @@ sub mkvcbuild
 
 	push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
 
+	push(@pgportfiles, 'strtof.c') if ($vsVersion < '14.00');
+
 	if ($vsVersion >= '9.00')
 	{
 		push(@pgportfiles, 'pg_crc32c_sse42_choose.c');
@@ -117,7 +119,7 @@ sub mkvcbuild
 	}
 
 	our @pgcommonallfiles = qw(
-	  base64.c config_info.c controldata_utils.c exec.c file_perm.c ip.c
+	  base64.c config_info.c controldata_utils.c d2s.c exec.c f2s.c file_perm.c ip.c
 	  keywords.c kwlookup.c link-canary.c md5.c
 	  pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
 	  saslprep.c scram-common.c string.c unicode_norm.c username.c
