From b78d1bed07d343542a4d295c3113c73a3379ed93 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 26 Jan 2001 22:50:26 +0000 Subject: [PATCH] Change float8-to-int8 conversion to round to nearest, rather than truncating to integer. Remove regress test that checks whether 4567890123456789 can be converted to float without loss; since that's 52 bits, it's on the hairy edge of failing with IEEE float8s, and indeed rint seems to give platform-dependent results for it. --- src/backend/utils/adt/int8.c | 22 +++++++++---------- .../expected/int8-exp-three-digits.out | 10 --------- src/test/regress/expected/int8.out | 10 --------- src/test/regress/sql/int8.sql | 1 - 4 files changed, 11 insertions(+), 32 deletions(-) diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index c02ada56ba4..a7df878c65b 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.27 2001/01/24 19:43:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.28 2001/01/26 22:50:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -693,13 +693,6 @@ i8tod(PG_FUNCTION_ARGS) /* dtoi8() * Convert double float to 8-byte integer. - * Do a range check before the conversion. - * Note that the comparison probably isn't quite right - * since we only have ~52 bits of precision in a double float - * and so subtracting one from a large number gives the large - * number exactly. However, for some reason the comparison below - * does the right thing on my i686/linux-rh4.2 box. - * - thomas 1998-06-16 */ Datum dtoi8(PG_FUNCTION_ARGS) @@ -707,11 +700,18 @@ dtoi8(PG_FUNCTION_ARGS) float8 val = PG_GETARG_FLOAT8(0); int64 result; - if ((val < (-pow(2.0, 63.0) + 1)) || (val > (pow(2.0, 63.0) - 1))) - elog(ERROR, "Floating point conversion to int64 is out of range"); - + /* Round val to nearest integer (but it's still in float form) */ + val = rint(val); + /* + * Does it fit in an int64? Avoid assuming that we have handy constants + * defined for the range boundaries, instead test for overflow by + * reverse-conversion. + */ result = (int64) val; + if ((float8) result != val) + elog(ERROR, "Floating point conversion to int8 is out of range"); + PG_RETURN_INT64(result); } diff --git a/src/test/regress/expected/int8-exp-three-digits.out b/src/test/regress/expected/int8-exp-three-digits.out index 562655bf440..e42d5dfaf2c 100644 --- a/src/test/regress/expected/int8-exp-three-digits.out +++ b/src/test/regress/expected/int8-exp-three-digits.out @@ -87,16 +87,6 @@ SELECT '' AS five, q2, float8(q2) FROM INT8_TBL; | -4567890123456789 | -4.56789012345679e+015 (5 rows) -SELECT '' AS five, q1, int8(float8(q1)) AS "two coercions" FROM INT8_TBL; - five | q1 | two coercions -------+------------------+------------------ - | 123 | 123 - | 123 | 123 - | 4567890123456789 | 4567890123456789 - | 4567890123456789 | 4567890123456789 - | 4567890123456789 | 4567890123456789 -(5 rows) - SELECT '' AS five, 2 * q1 AS "twice int4" FROM INT8_TBL; five | twice int4 ------+------------------ diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out index 30424a3f274..269cd2c0b50 100644 --- a/src/test/regress/expected/int8.out +++ b/src/test/regress/expected/int8.out @@ -87,16 +87,6 @@ SELECT '' AS five, q2, float8(q2) FROM INT8_TBL; | -4567890123456789 | -4.56789012345679e+15 (5 rows) -SELECT '' AS five, q1, int8(float8(q1)) AS "two coercions" FROM INT8_TBL; - five | q1 | two coercions -------+------------------+------------------ - | 123 | 123 - | 123 | 123 - | 4567890123456789 | 4567890123456789 - | 4567890123456789 | 4567890123456789 - | 4567890123456789 | 4567890123456789 -(5 rows) - SELECT '' AS five, 2 * q1 AS "twice int4" FROM INT8_TBL; five | twice int4 ------+------------------ diff --git a/src/test/regress/sql/int8.sql b/src/test/regress/sql/int8.sql index 0014efa220d..b5cb13480be 100644 --- a/src/test/regress/sql/int8.sql +++ b/src/test/regress/sql/int8.sql @@ -22,7 +22,6 @@ SELECT '' AS five, q1, q2, q1 / q2 AS divide FROM INT8_TBL; SELECT '' AS five, q1, float8(q1) FROM INT8_TBL; SELECT '' AS five, q2, float8(q2) FROM INT8_TBL; -SELECT '' AS five, q1, int8(float8(q1)) AS "two coercions" FROM INT8_TBL; SELECT '' AS five, 2 * q1 AS "twice int4" FROM INT8_TBL; SELECT '' AS five, q1 * 2 AS "twice int4" FROM INT8_TBL; -- 2.39.5