Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1piEaS-0000Ys-85 for pgsql-bugs@arkaria.postgresql.org; Fri, 31 Mar 2023 13:14:36 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1piEaQ-0000TA-OT for pgsql-bugs@arkaria.postgresql.org; Fri, 31 Mar 2023 13:14:34 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1piEaQ-0000T1-G5 for pgsql-bugs@lists.postgresql.org; Fri, 31 Mar 2023 13:14:34 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1piEaO-0004ac-4p for pgsql-bugs@lists.postgresql.org; Fri, 31 Mar 2023 13:14:33 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 32VDEUjh391416; Fri, 31 Mar 2023 09:14:30 -0400 From: Tom Lane To: Mats Kindahl cc: pgsql-bugs@lists.postgresql.org Subject: Re: BUG #17876: Function width_bucket() for float8 input returns value out of range In-reply-to: References: <17876-61f280d1601f978d@postgresql.org> <3807420.1680093217@sss.pgh.pa.us> <186575.1680190503@sss.pgh.pa.us> Comments: In-reply-to Mats Kindahl message dated "Fri, 31 Mar 2023 11:30:45 +0200" MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-ID: <391414.1680268470.1@sss.pgh.pa.us> Content-Transfer-Encoding: quoted-printable Date: Fri, 31 Mar 2023 09:14:30 -0400 Message-ID: <391415.1680268470@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Mats Kindahl writes: > On Thu, Mar 30, 2023 at 5:35=E2=80=AFPM Tom Lane wro= te: >> * It seems at least possible that, for an operand just slightly less >> than bound2, the quotient ((operand - bound1) / (bound2 - bound1)) >> could round to exactly 1, even though it should theoretically always >> be in [0, 1). If that did happen, and count is INT_MAX, then the final >> addition of 1 would create its own possibility of integer overflow. >> We have code to check that but it's only applied in the operand >=3D bo= und2 >> case. I fixed that by moving the overflow-aware addition of 1 to the >> bottom of the function so it's done in all cases, and adjusting the oth= er >> code paths to account for that. I realized that it's actually not too hard to make that happen: regression=3D# select width_bucket(0, -1e100::float8, 1, 10); width_bucket = -------------- 11 (1 row) While I'm not bothered too much if rounding affects which internal bucket a value lands in, it's a bit more annoying if that causes it to be reported as being in the end bucket, when we know positively that the value is less than bound2. Is it worth expending more cycles to prevent this? It'd need to be something like /* Result of division is surely in [0,1], so this can't overfl= ow */ result =3D count * ((operand - bound1) / (bound2 - bound1)); + /* ... but the quotient could round to 1, which would be a lie= */ + if (result >=3D count) + result =3D count - 1; and we'd need two or four copies of that depending on whether we want to refactor some more. Curiously, width_bucket_numeric has this problem too: regression=3D# select width_bucket(0, -1e100::numeric, 1, 10); width_bucket = -------------- 11 (1 row) I suppose it's also rounding somewhere in there. regards, tom lane