BUG #19801: atan2d underflow causes equivalent queries to return different results

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.
```

Browse pgsql-bugs by date

  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)