This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/3] Optimize trunc() and truncf().


By creating a mask of non-fractional bits from the exponent.
---

Joseph suggested an SSE 4.1 implementation of trunc/truncf, so I thought
now would be a good time to send these patches even sans benchmarking data.

I do not believe the other two generic trunc* implementations (ldbl-128,
dbl-64) would benefit from the change made in this patch

Suggestions for ChangeLog entries welcome. Guidance for generating benchmark
data requested.

 sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c | 32 +++++++++++-----------------
 sysdeps/ieee754/flt-32/s_truncf.c            | 32 +++++++++++-----------------
 2 files changed, 26 insertions(+), 38 deletions(-)

diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c
index 81ac55e..e4cba3b 100644
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c
+++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c
@@ -1,7 +1,6 @@
 /* Truncate argument to nearest integral value not larger than the argument.
    Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -21,31 +20,26 @@
 
 #include <math_private.h>
 
+static int64_t
+max (int64_t x, int64_t y)
+{
+  return x > y ? x : y;
+}
 
 double
 __trunc (double x)
 {
-  int64_t i0, j0;
-  int64_t sx;
+  int64_t i0;
 
   EXTRACT_WORDS64 (i0, x);
-  sx = i0 & UINT64_C(0x8000000000000000);
-  j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
-  if (j0 < 52)
-    {
-      if (j0 < 0)
-	/* The magnitude of the number is < 1 so the result is +-0.  */
-	INSERT_WORDS64 (x, sx);
-      else
-	INSERT_WORDS64 (x, sx | (i0 & ~(UINT64_C(0x000fffffffffffff) >> j0)));
-    }
-  else
-    {
-      if (j0 == 0x400)
-	/* x is inf or NaN.  */
-	return x + x;
-    }
+  int64_t exp = (i0 >> 52) & 0x7ff;
+  int64_t mask = UINT64_C(-1) << max(52 - (exp - 1023), 0);
+
+  if (exp < 1023)
+    mask = UINT64_C(0x8000000000000000);
 
+  i0 &= mask;
+  INSERT_WORDS64(x, i0);
   return x;
 }
 weak_alias (__trunc, trunc)
diff --git a/sysdeps/ieee754/flt-32/s_truncf.c b/sysdeps/ieee754/flt-32/s_truncf.c
index 43d35c7..67fdcc8 100644
--- a/sysdeps/ieee754/flt-32/s_truncf.c
+++ b/sysdeps/ieee754/flt-32/s_truncf.c
@@ -1,7 +1,6 @@
 /* Truncate argument to nearest integral value not larger than the argument.
    Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -21,31 +20,26 @@
 
 #include <math_private.h>
 
+static int32_t
+max (int32_t x, int32_t y)
+{
+  return x > y ? x : y;
+}
 
 float
 __truncf (float x)
 {
-  int32_t i0, j0;
-  int sx;
+  int32_t i0;
 
   GET_FLOAT_WORD (i0, x);
-  sx = i0 & 0x80000000;
-  j0 = ((i0 >> 23) & 0xff) - 0x7f;
-  if (j0 < 23)
-    {
-      if (j0 < 0)
-	/* The magnitude of the number is < 1 so the result is +-0.  */
-	SET_FLOAT_WORD (x, sx);
-      else
-	SET_FLOAT_WORD (x, sx | (i0 & ~(0x007fffff >> j0)));
-    }
-  else
-    {
-      if (j0 == 0x80)
-	/* x is inf or NaN.  */
-	return x + x;
-    }
+  int32_t exp = (i0 >> 23) & 0xff;
+  int32_t mask = ~0u << max(23 - (exp - 127), 0);
+
+  if (exp < 127)
+    mask = 0x80000000;
 
+  i0 &= mask;
+  SET_FLOAT_WORD (x, i0);
   return x;
 }
 weak_alias (__truncf, truncf)
-- 
2.7.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]