Skip to content

[C++][Parquet] Min Max stats are wrong when the value of a column are both infinity or -infinity #47426

Closed

Description

@PingLiuPing

Describe the bug, including details regarding any error messages, version, and platform.

When writing parquet files, if the value of a float or double column are both infinity or -infinity, the min and max stats of this column is wrong.
For example, suppose the column is float, and all values are -std::numeric_limits::infinity(), the min and max collected in TypeStatisticsImpl are [-Inf, std::numeric_limits::lowest()].
But the actual result should be [-Inf, -Inf].

Component(s)

C++

Activity

  1. changed the title [-][C++] Min Max stats are wrong when the value of a column are both infinity or -infinity[/-] [+][C++][Parquet] Min Max stats are wrong when the value of a column are both infinity or -infinity[/+] on Dec 3, 2025
  2. stackedsax commented on Oct 4, 2026

    @stackedsax

    This was fixed by #50183 (GH-50182), released in Arrow 25.0.0. DefaultMin()/DefaultMax() in cpp/src/parquet/statistics.cc now seed the running min/max with +Inf/-Inf for floating-point types (including FLOAT16) instead of numeric_limits<T>::max()/lowest(), so an all--Inf column now reports [-Inf, -Inf] as expected. TestFloatStatistics.Infinities in statistics_test.cc covers FLOAT, DOUBLE and FLOAT16.

    Quick check on 25.0.0 or later:

    import io, pyarrow as pa, pyarrow.parquet as pq
    inf = float("inf")
    buf = io.BytesIO()
    pq.write_table(pa.table({"c": pa.array([-inf, -inf, -inf])}), buf)
    st = pq.ParquetFile(buf).metadata.row_group(0).column(0).statistics
    print(st.min, st.max)  # -inf -inf

    Note for anyone arriving from facebookincubator/velox#14603: Velox vendors a copy of this file under velox/dwio/parquet/writer/arrow/Statistics.cpp, so it needs to pick up the equivalent change separately.

    @thisisnic I think this can be closed as a duplicate of #50182

    Note: I used Claude Code to help research this, but I read the ticket, the code and the linked commits myself and the conclusion here is mine, not the tool's.

  3. thisisnic commented on Oct 4, 2026

    @thisisnic
    Member

    Looks good to me; this code is where it was fixed; closing.

    // For floating point, seed the running min/max with +/-infinity rather than
    // the largest/smallest finite value: a finite seed is not an identity for
    // min/max once the data contains infinities, so an all-+Inf (resp. all--Inf)
    // column would otherwise never displace the seed and report a finite bound.
    constexpr static T DefaultMin() {
    if constexpr (std::is_floating_point_v<T>) {
    return std::numeric_limits<T>::infinity();
    } else {
    return std::numeric_limits<T>::max();
    }
    }
    constexpr static T DefaultMax() {
    if constexpr (std::is_floating_point_v<T>) {
    return -std::numeric_limits<T>::infinity();
    } else {
    return std::numeric_limits<T>::lowest();
    }
    }

  4. PingLiuPing commented on Oct 8, 2026

    @PingLiuPing
    Author

    Thank you for the fix and summary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions