Thread

  1. Re: [PATCH] Fix overflow and underflow in regr_r2()

    Dean Rasheed <dean.a.rasheed@gmail.com> — 2026-05-16T20:34:25Z

    On Sat, 16 May 2026 at 19:43, Tom Lane <tgl@sss.pgh.pa.us> wrote:
    >
    > Dean Rasheed <dean.a.rasheed@gmail.com> writes:
    > > On Sat, 16 May 2026 at 17:45, Tom Lane <tgl@sss.pgh.pa.us> wrote:
    > >> One simple change that might make things better is to compute
    > >>      PG_RETURN_FLOAT8((Sy - Sx * (Sxy / Sxx)) / N);
    > >> on the theory that the sums of products are likely to both be large.
    >
    > > Hmm, that isn't necessarily better.
    >
    > True.  We could do something like
    >
    >         (Sy - exp(log(Sx) + log(Sxy) - log(Sxx))) / N
    >
    > but this'd require additional special-case code to deal with zero
    > or negative Sx and Sxy, so it's feeling rather tedious.
    
    I just had a thought: a simpler (and probably faster and more
    accurate) solution would be to use frexp() and ldexp(), which are both
    part of C99, so ought to be OK.
    
    I don't think we can ignore underflow, because Sy might be exactly
    zero, in which case the second term gives the whole result.
    
    So, in rough terms, I'm thinking of something like this:
    
      offset = Sx * Sxy / Sxx
      if (offset == 0 || isinf(offset))
      {
        double m_Sx, m_Sxy, m_Sxx, m_offset;
        int n_Sx, n_Sxy, n_Sxx, n_offset;
    
        m_Sx = frexp(Sx, &n_Sx);
        m_Sxy = frexp(Sxy, &n_Sxy);
        m_Sxx = frexp(Sxx, &n_Sxx);
    
        m_offset = m_Sx * m_Sxy / m_Sxx;
        n_offset = n_Sx + n_Sxy - n_Sxx;
        offset = ldexp(m_offset, n_offset);
      }
    
      PG_RETURN_FLOAT8((Sy - offset) / N);
    
    Regards,
    Dean