Skip to content

Commit cb3e9e4

Browse files
committed
Put in_range_float4_float8's work in-line.
In commit 8b29e88, I'd dithered about whether to make in_range_float4_float8 be a standalone copy of the float in-range logic or have it punt to in_range_float8_float8. I went with the latter, which saves code space though at the cost of performance and readability. However, it emerges that this tickles a compiler or hardware bug on buildfarm member opossum. Test results from commit 55e0e45 show conclusively that widening a float4 NaN to float8 produces Inf, not NaN, on that machine; which accounts perfectly for the window RANGE test failures it's been showing. We can dodge this problem by making in_range_float4_float8 be an independent function, so that it checks for NaN inputs before widening them. Ordinarily I'd not be very excited about working around such obviously broken functionality; but given that this was a judgment call to begin with, I don't mind reversing it.
1 parent 2f52518 commit cb3e9e4

File tree

1 file changed

+58
-10
lines changed

1 file changed

+58
-10
lines changed

src/backend/utils/adt/float.c

+58-10
Original file line numberDiff line numberDiff line change
@@ -1254,16 +1254,64 @@ in_range_float8_float8(PG_FUNCTION_ARGS)
12541254
Datum
12551255
in_range_float4_float8(PG_FUNCTION_ARGS)
12561256
{
1257-
/* Doesn't seem worth duplicating code for, so just invoke float8_float8 */
1258-
float8 val = (float8) PG_GETARG_FLOAT4(0);
1259-
float8 base = (float8) PG_GETARG_FLOAT4(1);
1260-
1261-
return DirectFunctionCall5(in_range_float8_float8,
1262-
Float8GetDatumFast(val),
1263-
Float8GetDatumFast(base),
1264-
PG_GETARG_DATUM(2),
1265-
PG_GETARG_DATUM(3),
1266-
PG_GETARG_DATUM(4));
1257+
float4 val = PG_GETARG_FLOAT4(0);
1258+
float4 base = PG_GETARG_FLOAT4(1);
1259+
float8 offset = PG_GETARG_FLOAT8(2);
1260+
bool sub = PG_GETARG_BOOL(3);
1261+
bool less = PG_GETARG_BOOL(4);
1262+
float8 sum;
1263+
1264+
/*
1265+
* Reject negative or NaN offset. Negative is per spec, and NaN is
1266+
* because appropriate semantics for that seem non-obvious.
1267+
*/
1268+
if (isnan(offset) || offset < 0)
1269+
ereport(ERROR,
1270+
(errcode(ERRCODE_INVALID_PRECEDING_FOLLOWING_SIZE),
1271+
errmsg("invalid preceding or following size in window function")));
1272+
1273+
/*
1274+
* Deal with cases where val and/or base is NaN, following the rule that
1275+
* NaN sorts after non-NaN (cf float8_cmp_internal). The offset cannot
1276+
* affect the conclusion.
1277+
*/
1278+
if (isnan(val))
1279+
{
1280+
if (isnan(base))
1281+
PG_RETURN_BOOL(true); /* NAN = NAN */
1282+
else
1283+
PG_RETURN_BOOL(!less); /* NAN > non-NAN */
1284+
}
1285+
else if (isnan(base))
1286+
{
1287+
PG_RETURN_BOOL(less); /* non-NAN < NAN */
1288+
}
1289+
1290+
/*
1291+
* Deal with infinite offset (necessarily +inf, at this point). We must
1292+
* special-case this because if base happens to be -inf, their sum would
1293+
* be NaN, which is an overflow-ish condition we should avoid.
1294+
*/
1295+
if (isinf(offset))
1296+
{
1297+
PG_RETURN_BOOL(sub ? !less : less);
1298+
}
1299+
1300+
/*
1301+
* Otherwise it should be safe to compute base +/- offset. We trust the
1302+
* FPU to cope if base is +/-inf or the true sum would overflow, and
1303+
* produce a suitably signed infinity, which will compare properly against
1304+
* val whether or not that's infinity.
1305+
*/
1306+
if (sub)
1307+
sum = base - offset;
1308+
else
1309+
sum = base + offset;
1310+
1311+
if (less)
1312+
PG_RETURN_BOOL(val <= sum);
1313+
else
1314+
PG_RETURN_BOOL(val >= sum);
12671315
}
12681316

12691317

0 commit comments

Comments
 (0)