| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | 2320415112(at)qq(dot)com |
| Subject: | BUG #19801: atan2d underflow causes equivalent queries to return different results |
| Date: | 2026-10-28 08:43:45 |
| Message-ID: | 19801-980bafdd39d7e3c5@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19801
Logged by: cl hl
Email address: 2320415112(at)qq(dot)com
PostgreSQL version: 18.6
Operating system: Linux LAPTOP-2SQAVLB0 6.6.87.2-microsoft-standard-
Description:
## Description
`atan2d('5e-324'::float8, 2::float8)` returns `0`, although the correctly
rounded angle is the representable positive value `1.43e-322`.
The FPMT oracle uses the function's monotonicity around zero:
```text
y > 0
<=>
atan2d(y, x) > atan2d(0, x)
```
Inputs are restricted to finite positive `y` and `0 < x <= 32`, ensuring the
correct angle remains positive after binary64 rounding. Replacing the first
predicate with the second should preserve the result set, but the reproducer
produces different row counts.
## How to repeat
### 1. Complete schema and input data
Run the following statements in one PostgreSQL session. No extensions or
existing application tables are required.
```sql
CREATE TEMPORARY TABLE fpmt_atan2d_repro (
y DOUBLE PRECISION NOT NULL,
x DOUBLE PRECISION NOT NULL
);
INSERT INTO fpmt_atan2d_repro (y, x)
VALUES ('5e-324'::float8, 2::float8);
```
### 2. Original query Q1
```sql
WITH t(y, x) AS (
SELECT y, x
FROM pg_temp.fpmt_atan2d_repro
)
SELECT y, x
FROM t
WHERE y > 0;
```
Result: **1 row**, containing the inserted `(y, x)` pair.
### 3. Property-mutated query Q2
Keep the same input and projection, and replace the predicate using the
function property:
```sql
WITH t(y, x) AS (
SELECT y, x
FROM pg_temp.fpmt_atan2d_repro
)
SELECT y, x
FROM t
WHERE atan2d(y, x) > atan2d(0::float8, x);
```
Expected result: **the same 1 row as Q1**.
With the observed PostgreSQL 18.6 function results, the predicate evaluates
to `0 > 0`, and Q2 returns **0 rows**.
### 4. Self-contained query pair
The same oracle can also be expressed entirely with `VALUES`, without
creating a table:
```sql
-- Original query: returns 1 row.
WITH t(y, x) AS (
VALUES ('5e-324'::float8, 2::float8)
)
SELECT y, x FROM t
WHERE y > 0;
```
```sql
-- Property-mutated query: returns 0 rows with the observed PG 18.6 results.
WITH t(y, x) AS (
VALUES ('5e-324'::float8, 2::float8)
)
SELECT y, x FROM t
WHERE atan2d(y, x) > atan2d(0::float8, x);
```
### Oracle criterion
Both queries should return identical result sets under the stated input
constraints. A difference in their result sets, including their row counts,
triggers the oracle:
```text
Expected: result(Q1) = result(Q2)
Q1: 1 row
Q2: 0 rows
Result: function-property violation.
```
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Eric Laquer | 2026-10-28 09:07:05 | pg_trgm: GiST index scan misses rows at the default word_similarity_threshold |
| Previous Message | Chao Li | 2026-10-28 08:41:05 | Re: Streaming decoding fails with "unexpected table_index_fetch_tuple call during logical decoding" when a relation has a TOASTed conbin (follow-up to BUG #18641) |