Permalink
Browse files

Faster reverse() in model.c.

This also precipitated a change to limit word_t to 8 bytes.
  • Loading branch information...
1 parent 7284fbf commit 137e669f10a9c13d1b80f40ba2444b2b6e0caf34 @madler committed Jul 26, 2016
Showing with 45 additions and 14 deletions.
  1. +43 −10 model.c
  2. +2 −4 model.h
View
@@ -412,17 +412,50 @@ int read_model(model_t *model, char *str)
/* See model.h. */
word_t reverse(word_t x, unsigned n)
{
- unsigned bits = WORDBITS;
- while ((bits >> 1) >= n)
- bits >>= 1;
- word_t mask = (((word_t)1 << (bits - 1)) << 1) - 1;
- unsigned dist = bits;
- word_t pick = mask;
- while (x &= mask, dist >>= 1) {
- pick ^= pick << dist;
- x = ((x >> dist) & pick) + ((x << dist) & ~pick);
+ if (n == 1)
+ return x & 1;
+ if (n == 2)
+ return ((x >> 1) & 1) + ((x << 1) & 2);
+ if (n <= 4) {
+ x = ((x >> 2) & 3) + ((x << 2) & 0xc);
+ x = ((x >> 1) & 5) + ((x << 1) & 0xa);
+ return x >> (4 - n);
}
- return x >> (bits - n);
+ if (n <= 8) {
+ x = ((x >> 4) & 0xf) + ((x << 4) & 0xf0);
+ x = ((x >> 2) & 0x33) + ((x << 2) & 0xcc);
+ x = ((x >> 1) & 0x55) + ((x << 1) & 0xaa);
+ return x >> (8 - n);
+ }
+ if (n <= 16) {
+ x = ((x >> 8) & 0xff) + ((x << 8) & 0xff00);
+ x = ((x >> 4) & 0xf0f) + ((x << 4) & 0xf0f0);
+ x = ((x >> 2) & 0x3333) + ((x << 2) & 0xcccc);
+ x = ((x >> 1) & 0x5555) + ((x << 1) & 0xaaaa);
+ return x >> (16 - n);
+ }
+#if WORDBITS >= 32
+ if (n <= 32) {
+ x = ((x >> 16) & 0xffff) + ((x << 16) & 0xffff0000);
+ x = ((x >> 8) & 0xff00ff) + ((x << 8) & 0xff00ff00);
+ x = ((x >> 4) & 0xf0f0f0f) + ((x << 4) & 0xf0f0f0f0);
+ x = ((x >> 2) & 0x33333333) + ((x << 2) & 0xcccccccc);
+ x = ((x >> 1) & 0x55555555) + ((x << 1) & 0xaaaaaaaa);
+ return x >> (32 - n);
+ }
+# if WORDBITS >= 64
+ if (n <= 64) {
+ x = ((x >> 32) & 0xffffffff) + ((x << 32) & 0xffffffff00000000);
+ x = ((x >> 16) & 0xffff0000ffff) + ((x << 16) & 0xffff0000ffff0000);
+ x = ((x >> 8) & 0xff00ff00ff00ff) + ((x << 8) & 0xff00ff00ff00ff00);
+ x = ((x >> 4) & 0xf0f0f0f0f0f0f0f) + ((x << 4) & 0xf0f0f0f0f0f0f0f0);
+ x = ((x >> 2) & 0x3333333333333333) + ((x << 2) & 0xcccccccccccccccc);
+ x = ((x >> 1) & 0x5555555555555555) + ((x << 1) & 0xaaaaaaaaaaaaaaaa);
+ return x >> (64 - n);
+ }
+# endif
+#endif
+ return n < 2*WORDBITS ? reverse(x, WORDBITS) << (n - WORDBITS) : 0;
}
/* See model.h. */
View
@@ -30,17 +30,15 @@ typedef uintmax_t word_t;
/* Determine the size of uintmax_t at pre-processor time. (sizeof is not
evaluated at pre-processor time.) If word_t is instead set to an explicit
size above, e.g. uint64_t, then #define WORDCHARS appropriately, e.g. as 8.
- WORDCHARS must be 2, 4, 8, or 16. */
+ WORDCHARS must be 2, 4, or 8. */
#if UINTMAX_MAX == UINT16_MAX
# define WORDCHARS 2
#elif UINTMAX_MAX == UINT32_MAX
# define WORDCHARS 4
#elif UINTMAX_MAX == UINT64_MAX
# define WORDCHARS 8
-#elif UINTMAX_MAX == UINT128_MAX
-# define WORDCHARS 16
#else
-# error uintmax_t must be 2, 4, 8, or 16 bytes for this code.
+# error uintmax_t must be 2, 4, or 8 bytes for this code.
#endif
/* The number of bits in a word_t (assumes CHAR_BIT is 8). */

0 comments on commit 137e669

Please sign in to comment.