fmax(), fmaxf(), fmaxl(), fmin(), fminf(), fminl() simplified

Submitted by Stefan Kanthak on Dec. 11, 2019, 9:55 a.m.

Details

Message ID 557979287957451E9255CCBC4CD7CBE5@H270
State New
Series "fmax(), fmaxf(), fmaxl(), fmin(), fminf(), fminl() simplified"
Headers show

Commit Message

Stefan Kanthak Dec. 11, 2019, 9:55 a.m.
Still more optimisations/simplifications in the math subtree.

JFTR: I'm NOT subscribed to your mailing list, so CC: me in replies!

Patch hide | download patch | download mbox

--- -/src/math/fmax.c
+++ +/src/math/fmax.c
@@ -3,11 +3,9 @@ 
 double fmax(double x, double y)
 {
-        if (isnan(x))
+        if (x != x)
                 return y;
-        if (isnan(y))
-                return x;
         /* handle signed zeros, see C99 Annex F.9.9.2 */
-        if (signbit(x) != signbit(y))
+        if (x == y)
                 return signbit(x) ? y : x;
         return x < y ? y : x;
 }

--- -/src/math/fmaxf.c
+++ +/src/math/fmaxf.c
@@ -3,11 +3,9 @@ 
 float fmaxf(float x, float y)
 {
-        if (isnan(x))
+        if (x != x)
                 return y;
-        if (isnan(y))
-                return x;
         /* handle signed zeros, see C99 Annex F.9.9.2 */
-        if (signbit(x) != signbit(y))
+        if (x == y)
                 return signbit(x) ? y : x;
         return x < y ? y : x;
 }

--- -/src/math/fmaxl.c
+++ +/src/math/fmaxl.c
@@ -10,11 +10,9 @@ 
 long double fmaxl(long double x, long double y)
 {
-        if (isnan(x))
+        if (x != x)
                 return y;
-        if (isnan(y))
-                return x;
         /* handle signed zeros, see C99 Annex F.9.9.2 */
-        if (signbit(x) != signbit(y))
+        if (x == y)
                 return signbit(x) ? y : x;
         return x < y ? y : x;
 }

--- -/src/math/fmin.c
+++ +/src/math/fmin.c
@@ -3,11 +3,9 @@ 
 double fmin(double x, double y)
 {
-        if (isnan(x))
+        if (x != x)
                 return y;
-        if (isnan(y))
-                return x;
         /* handle signed zeros, see C99 Annex F.9.9.2 */
-        if (signbit(x) != signbit(y))
+        if (x == y)
                 return signbit(x) ? x : y;
-        return x < y ? x : y;
+        return x > y ? y : x;
 }

--- -/src/math/fminf.c
+++ +/src/math/fminf.c
@@ -3,11 +3,9 @@ 
 float fminf(float x, float y)
 {
-        if (isnan(x))
+        if (x != x)
                 return y;
-        if (isnan(y))
-                return x;
         /* handle signed zeros, see C99 Annex F.9.9.2 */
-        if (signbit(x) != signbit(y))
+        if (x == y)
                 return signbit(x) ? x : y;
-        return x < y ? x : y;
+        return x > y ? y : x;
 }

--- -/src/math/fminl.c
+++ +/src/math/fminl.c
@@ -10,11 +10,9 @@ 
 long double fminl(long double x, long double y)
 {
-        if (isnan(x))
+        if (x != x)
                 return y;
-        if (isnan(y))
-                return x;
         /* handle signed zeros, see C99 Annex F.9.9.2 */
-        if (signbit(x) != signbit(y))
+        if (x == y)
                 return signbit(x) ? x : y;
-        return x < y ? x : y;
+        return x > y ? y : x;
 }

Comments

Szabolcs Nagy Dec. 11, 2019, 10:49 a.m.
* Stefan Kanthak <stefan.kanthak@nexgo.de> [2019-12-11 10:55:29 +0100]:
> Still more optimisations/simplifications in the math subtree.
> 
> JFTR: I'm NOT subscribed to your mailing list, so CC: me in replies!
> 
> --- -/src/math/fmax.c
> +++ +/src/math/fmax.c
> @@ -3,11 +3,9 @@
>  double fmax(double x, double y)
>  {
> -        if (isnan(x))
> +        if (x != x)

these two are not equivalent for snan input, but we dont care
about snan, nor the compiler by default, so the compiler can
optimize one to the other (although musl uses explicit int
arithmetics instead of __builtin_isnan so it's a bit harder).

in any case the two are equivalent for practical purposes and
using isnan better documents the intention, you should change
the isnan definition if you think it's not efficient.

>                  return y;
> -        if (isnan(y))
> -                return x;
>          /* handle signed zeros, see C99 Annex F.9.9.2 */
> -        if (signbit(x) != signbit(y))
> +        if (x == y)
>                  return signbit(x) ? y : x;
>          return x < y ? y : x;

nice trick, but the fenv behaviour is not right.

you should run any such change through libc-test
git://repo.or.cz/libc-test and look for regressions.