* [PATCH] range-op-float: frange_arithmetic tweaks for MODE_COMPOSITE_P @ 2022-12-07 12:10 Jakub Jelinek 2022-12-07 15:21 ` Aldy Hernandez 0 siblings, 1 reply; 6+ messages in thread From: Jakub Jelinek @ 2022-12-07 12:10 UTC (permalink / raw) To: Aldy Hernandez; +Cc: gcc-patches Hi! As mentioned in PR107967, ibm-ldouble-format documents that +- has 1ulp accuracy, * 2ulps and / 3ulps. So, even if the result is exact, we need to widen the range a little bit. The following patch does that. I just wonder what it means for reverse division (the op1_range case), which we implement through multiplication, when division has 3ulps error and multiplication just 2ulps. In any case, this format is a mess and for non-default rounding modes can't be trusted at all, instead of +inf or something close to it it happily computes -inf. 2022-12-07 Jakub Jelinek <jakub@redhat.com> * range-op-float.cc (frange_arithmetic): For mode_composite, on top of rounding in the right direction accept extra 1ulp error for PLUS/MINUS_EXPR, extra 2ulps error for MULT_EXPR and extra 3ulps error for RDIV_EXPR. --- gcc/range-op-float.cc.jj 2022-12-07 12:46:01.536123757 +0100 +++ gcc/range-op-float.cc 2022-12-07 12:50:40.812085139 +0100 @@ -344,22 +344,70 @@ frange_arithmetic (enum tree_code code, } } } - if (round && (inexact || !real_identical (&result, &value))) + if (!inexact && !real_identical (&result, &value)) + inexact = true; + if (round && (inexact || mode_composite)) { if (mode_composite) { - if (real_isdenormal (&result, mode) - || real_iszero (&result)) + if (real_isdenormal (&result, mode) || real_iszero (&result)) { // IBM extended denormals only have DFmode precision. REAL_VALUE_TYPE tmp; real_convert (&tmp, DFmode, &value); - frange_nextafter (DFmode, tmp, inf); + if (inexact) + frange_nextafter (DFmode, tmp, inf); + switch (code) + { + case PLUS_EXPR: + case MINUS_EXPR: + // ibm-ldouble-format documents 1ulp for + and -. + frange_nextafter (DFmode, tmp, inf); + break; + case MULT_EXPR: + // ibm-ldouble-format documents 2ulps for *. + frange_nextafter (DFmode, tmp, inf); + frange_nextafter (DFmode, tmp, inf); + break; + case RDIV_EXPR: + // ibm-ldouble-format documents 3ulps for /. + frange_nextafter (DFmode, tmp, inf); + frange_nextafter (DFmode, tmp, inf); + frange_nextafter (DFmode, tmp, inf); + break; + default: + if (!inexact) + return; + break; + } real_convert (&result, mode, &tmp); return; } } - frange_nextafter (mode, result, inf); + if (inexact) + frange_nextafter (mode, result, inf); + if (mode_composite) + switch (code) + { + case PLUS_EXPR: + case MINUS_EXPR: + // ibm-ldouble-format documents 1ulp for + and -. + frange_nextafter (mode, result, inf); + break; + case MULT_EXPR: + // ibm-ldouble-format documents 2ulps for *. + frange_nextafter (mode, result, inf); + frange_nextafter (mode, result, inf); + break; + case RDIV_EXPR: + // ibm-ldouble-format documents 3ulps for /. + frange_nextafter (mode, result, inf); + frange_nextafter (mode, result, inf); + frange_nextafter (mode, result, inf); + break; + default: + break; + } } } Jakub ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] range-op-float: frange_arithmetic tweaks for MODE_COMPOSITE_P 2022-12-07 12:10 [PATCH] range-op-float: frange_arithmetic tweaks for MODE_COMPOSITE_P Jakub Jelinek @ 2022-12-07 15:21 ` Aldy Hernandez 2022-12-07 15:31 ` Jakub Jelinek 0 siblings, 1 reply; 6+ messages in thread From: Aldy Hernandez @ 2022-12-07 15:21 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, Andrew MacLeod On 12/7/22 13:10, Jakub Jelinek wrote: > Hi! > > As mentioned in PR107967, ibm-ldouble-format documents that > +- has 1ulp accuracy, * 2ulps and / 3ulps. > So, even if the result is exact, we need to widen the range a little bit. > > The following patch does that. I just wonder what it means for reverse > division (the op1_range case), which we implement through multiplication, > when division has 3ulps error and multiplication just 2ulps. In any case, > this format is a mess and for non-default rounding modes can't be trusted > at all, instead of +inf or something close to it it happily computes -inf. > > 2022-12-07 Jakub Jelinek <jakub@redhat.com> > > * range-op-float.cc (frange_arithmetic): For mode_composite, > on top of rounding in the right direction accept extra 1ulp > error for PLUS/MINUS_EXPR, extra 2ulps error for MULT_EXPR > and extra 3ulps error for RDIV_EXPR. > > --- gcc/range-op-float.cc.jj 2022-12-07 12:46:01.536123757 +0100 > +++ gcc/range-op-float.cc 2022-12-07 12:50:40.812085139 +0100 > @@ -344,22 +344,70 @@ frange_arithmetic (enum tree_code code, > } > } > } > - if (round && (inexact || !real_identical (&result, &value))) > + if (!inexact && !real_identical (&result, &value)) > + inexact = true; > + if (round && (inexact || mode_composite)) > { > if (mode_composite) > { > - if (real_isdenormal (&result, mode) > - || real_iszero (&result)) > + if (real_isdenormal (&result, mode) || real_iszero (&result)) > { > // IBM extended denormals only have DFmode precision. > REAL_VALUE_TYPE tmp; > real_convert (&tmp, DFmode, &value); > - frange_nextafter (DFmode, tmp, inf); > + if (inexact) > + frange_nextafter (DFmode, tmp, inf); > + switch (code) > + { > + case PLUS_EXPR: > + case MINUS_EXPR: > + // ibm-ldouble-format documents 1ulp for + and -. > + frange_nextafter (DFmode, tmp, inf); > + break; > + case MULT_EXPR: > + // ibm-ldouble-format documents 2ulps for *. > + frange_nextafter (DFmode, tmp, inf); > + frange_nextafter (DFmode, tmp, inf); > + break; > + case RDIV_EXPR: > + // ibm-ldouble-format documents 3ulps for /. > + frange_nextafter (DFmode, tmp, inf); > + frange_nextafter (DFmode, tmp, inf); > + frange_nextafter (DFmode, tmp, inf); > + break; > + default: > + if (!inexact) > + return; > + break; It looks like this chunk... > + } > real_convert (&result, mode, &tmp); > return; > } > } > - frange_nextafter (mode, result, inf); > + if (inexact) > + frange_nextafter (mode, result, inf); > + if (mode_composite) > + switch (code) > + { > + case PLUS_EXPR: > + case MINUS_EXPR: > + // ibm-ldouble-format documents 1ulp for + and -. > + frange_nextafter (mode, result, inf); > + break; > + case MULT_EXPR: > + // ibm-ldouble-format documents 2ulps for *. > + frange_nextafter (mode, result, inf); > + frange_nextafter (mode, result, inf); > + break; > + case RDIV_EXPR: > + // ibm-ldouble-format documents 3ulps for /. > + frange_nextafter (mode, result, inf); > + frange_nextafter (mode, result, inf); > + frange_nextafter (mode, result, inf); > + break; > + default: > + break; > + } ...is the same as this chunk. Plus, all this mode composite stuff is polluting what was a rather clean function. Would it be possible to abstract this into an inline function, and then we could do: if (mode_composite) frange_composite_nextafter (...); else frange_nextafter (...); or perhaps abstract the whole nextafter in frange_arithmetic into: frange_arithmetic_nextafter () { if (mode_composite) { do ugly stuff } else frange_nextafter (...) } I'm most worried about maintainability, not correctness here, cause you obviously know what you're doing ;-). Aldy > } > } > > > Jakub > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] range-op-float: frange_arithmetic tweaks for MODE_COMPOSITE_P 2022-12-07 15:21 ` Aldy Hernandez @ 2022-12-07 15:31 ` Jakub Jelinek 2022-12-07 15:38 ` Aldy Hernandez 0 siblings, 1 reply; 6+ messages in thread From: Jakub Jelinek @ 2022-12-07 15:31 UTC (permalink / raw) To: Aldy Hernandez; +Cc: gcc-patches, Andrew MacLeod On Wed, Dec 07, 2022 at 04:21:09PM +0100, Aldy Hernandez wrote: > On 12/7/22 13:10, Jakub Jelinek wrote: > > + switch (code) > > + { > > + case PLUS_EXPR: > > + case MINUS_EXPR: > > + // ibm-ldouble-format documents 1ulp for + and -. > > + frange_nextafter (DFmode, tmp, inf); > > + break; > > + case MULT_EXPR: > > + // ibm-ldouble-format documents 2ulps for *. > > + frange_nextafter (DFmode, tmp, inf); > > + frange_nextafter (DFmode, tmp, inf); > > + break; > > + case RDIV_EXPR: > > + // ibm-ldouble-format documents 3ulps for /. > > + frange_nextafter (DFmode, tmp, inf); > > + frange_nextafter (DFmode, tmp, inf); > > + frange_nextafter (DFmode, tmp, inf); > > + break; > > + default: > > + if (!inexact) > > + return; > > + break; > > It looks like this chunk... > > > > + switch (code) > > + { > > + case PLUS_EXPR: > > + case MINUS_EXPR: > > + // ibm-ldouble-format documents 1ulp for + and -. > > + frange_nextafter (mode, result, inf); > > + break; > > + case MULT_EXPR: > > + // ibm-ldouble-format documents 2ulps for *. > > + frange_nextafter (mode, result, inf); > > + frange_nextafter (mode, result, inf); > > + break; > > + case RDIV_EXPR: > > + // ibm-ldouble-format documents 3ulps for /. > > + frange_nextafter (mode, result, inf); > > + frange_nextafter (mode, result, inf); > > + frange_nextafter (mode, result, inf); > > + break; > > + default: > > + break; > > + } > > ...is the same as this chunk. Plus, all this mode composite stuff is It is not the same, there is the DFmode, tmp vs. mode, result difference. But sure, we could either add an inline function which for (code, mode, result, inf) set of options (or (code, DFmode, tmp, inf)) do those 0, 1, 2, 3 frange_nextafter calls (and return bool if it did any - there is also the if (!inexact) return; case), or as you suggest perhaps change frange_nextafter to handle MODE_COMPOSITE_P differently and do there if (mode_composite && (real_isdenormal (&result, mode) || real_iszero (&result))) { // IBM extended denormals only have DFmode precision. REAL_VALUE_TYPE tmp; real_convert (&tmp, DFmode, &result); frange_nextafter (DFmode, tmp, inf); real_convert (&result, mode, &tmp); } else frange_nextafter (mode, result, inf); Though, that somewhat changes behavior, it will convert to DFmode and back for every nextafter rather than just once (just slower compile time), but also right now we start from value rather than result. So, perhaps a combination of that, change frange_nextafter to do the above and change frange_arithmetic for the initial inexact rounding only to do it by hand using range_nextafter and starting from value. Anyway, this patch is far less important than the previous one... Jakub ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] range-op-float: frange_arithmetic tweaks for MODE_COMPOSITE_P 2022-12-07 15:31 ` Jakub Jelinek @ 2022-12-07 15:38 ` Aldy Hernandez 2022-12-07 16:05 ` [PATCH] range-op-float, v2: " Jakub Jelinek 0 siblings, 1 reply; 6+ messages in thread From: Aldy Hernandez @ 2022-12-07 15:38 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, Andrew MacLeod On 12/7/22 16:31, Jakub Jelinek wrote: > On Wed, Dec 07, 2022 at 04:21:09PM +0100, Aldy Hernandez wrote: >> On 12/7/22 13:10, Jakub Jelinek wrote: >>> + switch (code) >>> + { >>> + case PLUS_EXPR: >>> + case MINUS_EXPR: >>> + // ibm-ldouble-format documents 1ulp for + and -. >>> + frange_nextafter (DFmode, tmp, inf); >>> + break; >>> + case MULT_EXPR: >>> + // ibm-ldouble-format documents 2ulps for *. >>> + frange_nextafter (DFmode, tmp, inf); >>> + frange_nextafter (DFmode, tmp, inf); >>> + break; >>> + case RDIV_EXPR: >>> + // ibm-ldouble-format documents 3ulps for /. >>> + frange_nextafter (DFmode, tmp, inf); >>> + frange_nextafter (DFmode, tmp, inf); >>> + frange_nextafter (DFmode, tmp, inf); >>> + break; >>> + default: >>> + if (!inexact) >>> + return; >>> + break; >> >> It looks like this chunk... >> >> >>> + switch (code) >>> + { >>> + case PLUS_EXPR: >>> + case MINUS_EXPR: >>> + // ibm-ldouble-format documents 1ulp for + and -. >>> + frange_nextafter (mode, result, inf); >>> + break; >>> + case MULT_EXPR: >>> + // ibm-ldouble-format documents 2ulps for *. >>> + frange_nextafter (mode, result, inf); >>> + frange_nextafter (mode, result, inf); >>> + break; >>> + case RDIV_EXPR: >>> + // ibm-ldouble-format documents 3ulps for /. >>> + frange_nextafter (mode, result, inf); >>> + frange_nextafter (mode, result, inf); >>> + frange_nextafter (mode, result, inf); >>> + break; >>> + default: >>> + break; >>> + } >> >> ...is the same as this chunk. Plus, all this mode composite stuff is > > It is not the same, there is the DFmode, tmp vs. mode, result difference. > But sure, we could either add an inline function which for > (code, mode, result, inf) set of options (or (code, DFmode, tmp, inf)) > do those 0, 1, 2, 3 frange_nextafter calls (and return bool if it did any > - there is also the if (!inexact) return; case), or as you suggest > perhaps change frange_nextafter to handle MODE_COMPOSITE_P differently > and do there > if (mode_composite && (real_isdenormal (&result, mode) || real_iszero (&result))) > { > // IBM extended denormals only have DFmode precision. > REAL_VALUE_TYPE tmp; > real_convert (&tmp, DFmode, &result); > frange_nextafter (DFmode, tmp, inf); > real_convert (&result, mode, &tmp); > } > else > frange_nextafter (mode, result, inf); > Though, that somewhat changes behavior, it will convert to DFmode and back > for every nextafter rather than just once (just slower compile time), > but also right now we start from value rather than result. > > So, perhaps a combination of that, change frange_nextafter to do the above > and change frange_arithmetic for the initial inexact rounding only to > do it by hand using range_nextafter and starting from value. Either way is fine. Whatever is cleaner. Aldy > > Anyway, this patch is far less important than the previous one... > > Jakub > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] range-op-float, v2: frange_arithmetic tweaks for MODE_COMPOSITE_P 2022-12-07 15:38 ` Aldy Hernandez @ 2022-12-07 16:05 ` Jakub Jelinek 2022-12-07 17:41 ` Aldy Hernandez 0 siblings, 1 reply; 6+ messages in thread From: Jakub Jelinek @ 2022-12-07 16:05 UTC (permalink / raw) To: Aldy Hernandez; +Cc: gcc-patches, Andrew MacLeod On Wed, Dec 07, 2022 at 04:38:14PM +0100, Aldy Hernandez wrote: > > So, perhaps a combination of that, change frange_nextafter to do the above > > and change frange_arithmetic for the initial inexact rounding only to > > do it by hand using range_nextafter and starting from value. > > Either way is fine. Whatever is cleaner. Now in patch form: 2022-12-07 Jakub Jelinek <jakub@redhat.com> * range-op-float.cc (frange_nextafter): For MODE_COMPOSITE_P from denormal or zero, use real_nextafter on DFmode with conversions around it. (frange_arithmetic): For mode_composite, on top of rounding in the right direction accept extra 1ulp error for PLUS/MINUS_EXPR, extra 2ulps error for MULT_EXPR and extra 3ulps error for RDIV_EXPR. --- gcc/range-op-float.cc.jj 2022-12-07 12:46:01.536123757 +0100 +++ gcc/range-op-float.cc 2022-12-07 16:58:02.406062286 +0100 @@ -254,10 +254,21 @@ frange_nextafter (enum machine_mode mode REAL_VALUE_TYPE &value, const REAL_VALUE_TYPE &inf) { - const real_format *fmt = REAL_MODE_FORMAT (mode); - REAL_VALUE_TYPE tmp; - real_nextafter (&tmp, fmt, &value, &inf); - value = tmp; + if (MODE_COMPOSITE_P (mode) + && (real_isdenormal (&value, mode) || real_iszero (&value))) + { + // IBM extended denormals only have DFmode precision. + REAL_VALUE_TYPE tmp, tmp2; + real_convert (&tmp2, DFmode, &value); + real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf); + real_convert (&value, mode, &tmp); + } + else + { + REAL_VALUE_TYPE tmp; + real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf); + value = tmp; + } } // Like real_arithmetic, but round the result to INF if the operation @@ -324,21 +335,40 @@ frange_arithmetic (enum tree_code code, } if (round && (inexact || !real_identical (&result, &value))) { - if (mode_composite) + if (mode_composite + && (real_isdenormal (&result, mode) || real_iszero (&result))) { - if (real_isdenormal (&result, mode) - || real_iszero (&result)) - { - // IBM extended denormals only have DFmode precision. - REAL_VALUE_TYPE tmp; - real_convert (&tmp, DFmode, &value); - frange_nextafter (DFmode, tmp, inf); - real_convert (&result, mode, &tmp); - return; - } + // IBM extended denormals only have DFmode precision. + REAL_VALUE_TYPE tmp, tmp2; + real_convert (&tmp2, DFmode, &value); + real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf); + real_convert (&result, mode, &tmp); } - frange_nextafter (mode, result, inf); + else + frange_nextafter (mode, result, inf); } + if (mode_composite) + switch (code) + { + case PLUS_EXPR: + case MINUS_EXPR: + // ibm-ldouble-format documents 1ulp for + and -. + frange_nextafter (mode, result, inf); + break; + case MULT_EXPR: + // ibm-ldouble-format documents 2ulps for *. + frange_nextafter (mode, result, inf); + frange_nextafter (mode, result, inf); + break; + case RDIV_EXPR: + // ibm-ldouble-format documents 3ulps for /. + frange_nextafter (mode, result, inf); + frange_nextafter (mode, result, inf); + frange_nextafter (mode, result, inf); + break; + default: + break; + } } // Crop R to [-INF, MAX] where MAX is the maximum representable number Jakub ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] range-op-float, v2: frange_arithmetic tweaks for MODE_COMPOSITE_P 2022-12-07 16:05 ` [PATCH] range-op-float, v2: " Jakub Jelinek @ 2022-12-07 17:41 ` Aldy Hernandez 0 siblings, 0 replies; 6+ messages in thread From: Aldy Hernandez @ 2022-12-07 17:41 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, Andrew MacLeod OK, thanks. Aldy On 12/7/22 17:05, Jakub Jelinek wrote: > On Wed, Dec 07, 2022 at 04:38:14PM +0100, Aldy Hernandez wrote: >>> So, perhaps a combination of that, change frange_nextafter to do the above >>> and change frange_arithmetic for the initial inexact rounding only to >>> do it by hand using range_nextafter and starting from value. >> >> Either way is fine. Whatever is cleaner. > > Now in patch form: > > 2022-12-07 Jakub Jelinek <jakub@redhat.com> > > * range-op-float.cc (frange_nextafter): For MODE_COMPOSITE_P from > denormal or zero, use real_nextafter on DFmode with conversions > around it. > (frange_arithmetic): For mode_composite, on top of rounding in the > right direction accept extra 1ulp error for PLUS/MINUS_EXPR, extra > 2ulps error for MULT_EXPR and extra 3ulps error for RDIV_EXPR. > > --- gcc/range-op-float.cc.jj 2022-12-07 12:46:01.536123757 +0100 > +++ gcc/range-op-float.cc 2022-12-07 16:58:02.406062286 +0100 > @@ -254,10 +254,21 @@ frange_nextafter (enum machine_mode mode > REAL_VALUE_TYPE &value, > const REAL_VALUE_TYPE &inf) > { > - const real_format *fmt = REAL_MODE_FORMAT (mode); > - REAL_VALUE_TYPE tmp; > - real_nextafter (&tmp, fmt, &value, &inf); > - value = tmp; > + if (MODE_COMPOSITE_P (mode) > + && (real_isdenormal (&value, mode) || real_iszero (&value))) > + { > + // IBM extended denormals only have DFmode precision. > + REAL_VALUE_TYPE tmp, tmp2; > + real_convert (&tmp2, DFmode, &value); > + real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf); > + real_convert (&value, mode, &tmp); > + } > + else > + { > + REAL_VALUE_TYPE tmp; > + real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf); > + value = tmp; > + } > } > > // Like real_arithmetic, but round the result to INF if the operation > @@ -324,21 +335,40 @@ frange_arithmetic (enum tree_code code, > } > if (round && (inexact || !real_identical (&result, &value))) > { > - if (mode_composite) > + if (mode_composite > + && (real_isdenormal (&result, mode) || real_iszero (&result))) > { > - if (real_isdenormal (&result, mode) > - || real_iszero (&result)) > - { > - // IBM extended denormals only have DFmode precision. > - REAL_VALUE_TYPE tmp; > - real_convert (&tmp, DFmode, &value); > - frange_nextafter (DFmode, tmp, inf); > - real_convert (&result, mode, &tmp); > - return; > - } > + // IBM extended denormals only have DFmode precision. > + REAL_VALUE_TYPE tmp, tmp2; > + real_convert (&tmp2, DFmode, &value); > + real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf); > + real_convert (&result, mode, &tmp); > } > - frange_nextafter (mode, result, inf); > + else > + frange_nextafter (mode, result, inf); > } > + if (mode_composite) > + switch (code) > + { > + case PLUS_EXPR: > + case MINUS_EXPR: > + // ibm-ldouble-format documents 1ulp for + and -. > + frange_nextafter (mode, result, inf); > + break; > + case MULT_EXPR: > + // ibm-ldouble-format documents 2ulps for *. > + frange_nextafter (mode, result, inf); > + frange_nextafter (mode, result, inf); > + break; > + case RDIV_EXPR: > + // ibm-ldouble-format documents 3ulps for /. > + frange_nextafter (mode, result, inf); > + frange_nextafter (mode, result, inf); > + frange_nextafter (mode, result, inf); > + break; > + default: > + break; > + } > } > > // Crop R to [-INF, MAX] where MAX is the maximum representable number > > > Jakub > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-12-07 17:41 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-12-07 12:10 [PATCH] range-op-float: frange_arithmetic tweaks for MODE_COMPOSITE_P Jakub Jelinek 2022-12-07 15:21 ` Aldy Hernandez 2022-12-07 15:31 ` Jakub Jelinek 2022-12-07 15:38 ` Aldy Hernandez 2022-12-07 16:05 ` [PATCH] range-op-float, v2: " Jakub Jelinek 2022-12-07 17:41 ` Aldy Hernandez
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).