public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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).