Verteilung am wenigsten signifikanten Bits von einem 4-Byte-Array zu einem Knabber
-
25-10-2019 - |
Frage
Ich möchte Bits 0,8,16,24 eines 32-Bit-Wertes auf Bits 0,1,2,3 verschieben. Alle anderen Bits in der Eingabe und Ausgabe sind Null.
Offensichtlich kann ich das so machen:
c = c>>21 + c>>14 + c>>7 + c;
c &= 0xF;
Aber gibt es eine schnellere (weniger Anweisungen) Weg?
Lösung
c = (((c&BITS_0_8_16_24) * BITS_0_7_14_21) >> 21) & 0xF;
Oder warten Sie auf den Intel -Haswell -Prozessor und erledigen Sie dies alles in genau einem Anweisungen (Pext).
Aktualisieren
Berücksichtigen clarified constraints
und übernehmen 32-bit unsigned values
, Der Code kann darauf vereinfacht werden:
c = (c * BITS_7_14_21_28) >> 28;
Andere Tipps
Wenn Sie sich nicht für die Portabilität interessieren und SSE -Anweisungen verwenden können, schauen Sie sich das an die PMOVMSKB Anweisung und sein Compiler intrinsisch. [Ich habe festgestellt, dass Ihre Bitpositionen die wichtigsten (Zeichen-) Bits der 4 Bytes sind, die das 32-Bit-Wort umfassen.
Anstatt einige verschleierte One-Line-Goo zu schreiben, würde ich den folgenden Code schreiben, um eine maximale Portabilität und Wartbarkeit zu erzielen. Ich würde den Optimierer Sorgen machen lassen, ob er der effektivste Code ist oder nicht.
#include <stdint.h>
#include <limits.h>
#include <stdio.h>
#define BITS_TO_MOVE 4
static const uint32_t OLD_MASK [BITS_TO_MOVE] =
{
0x0008u,
0x0080u,
0x0800u,
0x8000u
};
static const uint32_t NEW_MASK [BITS_TO_MOVE] =
{
0x1000u,
0x2000u,
0x4000u,
0x8000u
};
int main()
{
uint32_t c = 0xAAAAu;
uint32_t new_c = 0;
uint8_t i;
printf("%.4X\n", c);
for(i=0; i<BITS_TO_MOVE; i++)
{
if ( (c & OLD_MASK[i]) > 0 )
{
new_c |= NEW_MASK[i];
}
}
printf("%.4X\n", new_c);
getchar();
return 0;
}