0

I have this time critical code:

#define READBIT(A, B) ((A >> (B & 7)) & 1)
#define SETBIT(T, B, V) (T = V ? T | (1<<B) : T & ~(1<<B))

for (int j = 0; j < 32; j++) {
  bits = 0;
  sc   = seckey[31 - j];
  SETBIT(bits, 0, READBIT(sc, 0));
  SETBIT(bits, 1, READBIT(sc, 1));
  SETBIT(bits, 2, READBIT(sc, 2));
  SETBIT(bits, 3, READBIT(sc, 3));
  SETBIT(bits, 4, READBIT(sc, 4));
  SETBIT(bits, 5, READBIT(sc, 5));
  SETBIT(bits, 6, READBIT(sc, 6));
  SETBIT(bits, 7, READBIT(sc, 7));

  <do something with bits>
}

My question is, if it is possible to transform the READBIT/SETBIT macros further - possibly consolidating them into one macro and lowering computational effort.

If I expand these macros (leaving B as a variable), I get (hopefully correct):

bits = ((sc >> (B & 7)) & 1) ? bits | (1<<B) : bits & ~(1<<B)

Where B can take values 0-7. Am I missing a simpler equivalent logical operation?

Perlator
  • 241
  • 1
  • 2
  • 11
  • 1
    Hint: **always** add parentheses when using macro-arguments: `#define READBIT(A, B) (((A) >> ((B) & 7)) & 1)` (otherwise: `READBIT(x, y+z)` may not do what you intend) – wildplasser Nov 13 '16 at 17:27
  • So you're looking for a COPYBIT macro? – nwellnhof Nov 13 '16 at 17:50
  • Very often there are ways to do an entire permutation in some better way than just moving the bits one by one. For variable permutations that's really hard to code, but if you know the permutation at compile time you can work something out, perhaps with the help of tools such as [this](http://programming.sirrida.de/calcperm.php) and just pen and paper methods. E: your current permutation is trivial of course, I assume that's not a real example. – harold Nov 13 '16 at 17:59
  • The code generator for bit permutations is a fantastic tool. Thanks for the pointer. The presented code actually was a real example (after hours of de-fiddling existing code). Further de-fiddling revealed triviality: copy the lowest 8 bits. Therefore it was replaced with a = b where these two were unsigned chars. – Perlator Nov 14 '16 at 09:17
  • [The need for parentheses in macros in C](http://stackoverflow.com/q/10820340/995714) – phuclv Nov 17 '16 at 02:57

1 Answers1

1

It is not entirely clear what your goal is here. Maybe you want the flexibility of being able to copy the N lowest order bits, or maybe you want to be able to copy a chosen bit from the source to the target.

Here is some code that shows both of these approaches. The macro COPYBITS copies the N lowest order bits, and the macro COPYBIT copies the order N bit.

UPDATE

I have added some macros to simplify the definition of the COPYBIT and COPYBITS macros, and to make their logic more clear:

#include <stdio.h>

#define READBIT(A, B) ((A >> (B & 7)) & 1)
#define SETBIT(T, B, V) (T = V ? T | (1<<B) : T & ~(1<<B))

//#define COPYBITS(T,S,N) ((T) = ((T) & (~0x0ul << (N))) | ((S) & ~(~0x0ul << (N))))

//#define COPYBIT(T, S, N) ((T) = ((T) & ~(0x1ul << (N))) | ((S) & (0x1ul << (N))))

/* A final refinement */
/* CLEARBIT evaluates to T with the order N bit to 0 */
#define CLEARBIT(T,N) ((T) & ~(0x1ul << (N)))

/* CLEARBITS evaluates to T with the N lowest order bits to 0 */
#define CLEARBITS(T,N) ((T) & (~0x0ul << (N)))

/* GETBIT evaluates to S, keeping only the order N bit */
#define GETBIT(S,N) ((S) & (0x1ul << (N)))

/* GETBITS evaluates to S, keeping only the N lowest order bits */
#define GETBITS(S,N) ((S) & ~(~0x0ul << (N)))

/* COPYBIT copies the order N bit of S to T */
#define COPYBIT(T,S,N) ((T) = ((T) & CLEARBIT((T),(N))) | (GETBIT((S),(N))))

/* COPYBITS copies the N lowest order bits of S to T */
#define COPYBITS(T,S,N) ((T) = ((T) & CLEARBITS((T),(N))) | (GETBITS((S),(N))))

int main(void)
{
    unsigned sc;
    unsigned bits2 = 4u;
    unsigned bits3 = 4u;
    
    sc = 0x10Fu;

    printf("sc = %u\n", sc);
    putchar('\n');
    puts("Before copying:");
    printf("bits2 = %u\n", bits2);
    printf("bits3 = %u\n", bits3);
    
    SETBIT(bits2, 0, READBIT(sc, 0));
    SETBIT(bits2, 1, READBIT(sc, 1));
    SETBIT(bits2, 2, READBIT(sc, 2));
    SETBIT(bits2, 3, READBIT(sc, 3));
    SETBIT(bits2, 4, READBIT(sc, 4));
    SETBIT(bits2, 5, READBIT(sc, 5));
    SETBIT(bits2, 6, READBIT(sc, 6));
    SETBIT(bits2, 7, READBIT(sc, 7));

    COPYBITS(bits3, sc, 8);

    putchar('\n');
    puts("After copying the lowest 8 bits of sc:");
    printf("bits2 = %u\n", bits2);
    printf("bits3 = %u\n", bits3);
    
    bits2 = 0u;
    COPYBITS(bits2, sc, 9);

    putchar('\n');
    puts("After copying the lowest 9 bits of sc:");
    printf("bits2 = %u\n", bits2);

    bits2 = 0u;
    COPYBITS(bits2, sc, 1);

    putchar('\n');
    puts("After copying the lowest 1 bit of sc:");
    printf("bits2 = %u\n", bits2);
    
    bits2 = 0u;
    COPYBITS(bits2, sc, 0);

    putchar('\n');
    puts("After copying the lowest 0 bits of sc:");
    printf("bits2 = %u\n", bits2);

    bits2 = 0u;
    for(size_t i = 0; i < 8; i++)
        COPYBIT(bits2, sc, i);

    putchar('\n');
    puts("After copying the lowest 8 bits of sc:");
    printf("bits2 = %u\n", bits2);

    COPYBIT(bits2, 0xFF, 7);
    
    putchar('\n');
    puts("After copying order 7 bit of 0xFF (1) to order 7 bit of bits2:");
    printf("bits2 = %u\n", bits2);

    COPYBIT(bits2, 0x0, 7);
    
    putchar('\n');
    puts("After copying order 7 bit of 0x0 (0) to order 7 bit of bits2:");
    printf("bits2 = %u\n", bits2);
    
    return 0;
}
Community
  • 1
  • 1
ad absurdum
  • 19,498
  • 5
  • 37
  • 60