Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Schnelle SwapByte Routine - Bits swappen (https://www.delphipraxis.net/188343-schnelle-swapbyte-routine-bits-swappen.html)

bytecook 23. Feb 2016 09:31

Schnelle SwapByte Routine - Bits swappen
 
Hi Leute,

anbei eine kleine "Lookup" Tabelle, die die Bitreihenfolge innerhalb eines Bytes mittels Case-Anweisung swapt. Gegebenenfalls spart sich so jemand Tipparbeit :)

Delphi-Quellcode:
function SwapByte (Const Value : Byte) : Byte;

  begin
    case Value of
      $00 : Result := $00;
      $01 : Result := $80;
      $02 : Result := $40;
      $03 : Result := $C0;
      $04 : Result := $20;
      $05 : Result := $A0;
      $06 : Result := $60;
      $07 : Result := $E0;
      $08 : Result := $10;
      $09 : Result := $90;
      $0A : Result := $50;
      $0B : Result := $D0;
      $0C : Result := $30;
      $0D : Result := $B0;
      $0E : Result := $70;
      $0F : Result := $F0;
      $10 : Result := $08;
      $11 : Result := $88;
      $12 : Result := $48;
      $13 : Result := $C8;
      $14 : Result := $28;
      $15 : Result := $A8;
      $16 : Result := $68;
      $17 : Result := $E8;
      $18 : Result := $18;
      $19 : Result := $98;
      $1A : Result := $58;
      $1B : Result := $D8;
      $1C : Result := $38;
      $1D : Result := $B8;
      $1E : Result := $78;
      $1F : Result := $F8;
      $20 : Result := $04;
      $21 : Result := $84;
      $22 : Result := $44;
      $23 : Result := $C4;
      $24 : Result := $24;
      $25 : Result := $A4;
      $26 : Result := $64;
      $27 : Result := $E4;
      $28 : Result := $14;
      $29 : Result := $94;
      $2A : Result := $54;
      $2B : Result := $D4;
      $2C : Result := $34;
      $2D : Result := $B4;
      $2E : Result := $74;
      $2F : Result := $F4;
      $30 : Result := $0C;
      $31 : Result := $8C;
      $32 : Result := $4C;
      $33 : Result := $CC;
      $34 : Result := $2C;
      $35 : Result := $AC;
      $36 : Result := $6C;
      $37 : Result := $EC;
      $38 : Result := $1C;
      $39 : Result := $9C;
      $3A : Result := $5C;
      $3B : Result := $DC;
      $3C : Result := $3C;
      $3D : Result := $BC;
      $3E : Result := $7C;
      $3F : Result := $FC;
      $40 : Result := $02;
      $41 : Result := $82;
      $42 : Result := $42;
      $43 : Result := $C2;
      $44 : Result := $22;
      $45 : Result := $A2;
      $46 : Result := $62;
      $47 : Result := $E2;
      $48 : Result := $12;
      $49 : Result := $92;
      $4A : Result := $52;
      $4B : Result := $D2;
      $4C : Result := $32;
      $4D : Result := $B2;
      $4E : Result := $72;
      $4F : Result := $F2;
      $50 : Result := $0A;
      $51 : Result := $8A;
      $52 : Result := $4A;
      $53 : Result := $CA;
      $54 : Result := $2A;
      $55 : Result := $AA;
      $56 : Result := $6A;
      $57 : Result := $EA;
      $58 : Result := $1A;
      $59 : Result := $9A;
      $5A : Result := $5A;
      $5B : Result := $DA;
      $5C : Result := $3A;
      $5D : Result := $BA;
      $5E : Result := $7A;
      $5F : Result := $FA;
      $60 : Result := $06;
      $61 : Result := $86;
      $62 : Result := $46;
      $63 : Result := $C6;
      $64 : Result := $26;
      $65 : Result := $A6;
      $66 : Result := $66;
      $67 : Result := $E6;
      $68 : Result := $16;
      $69 : Result := $96;
      $6A : Result := $56;
      $6B : Result := $D6;
      $6C : Result := $36;
      $6D : Result := $B6;
      $6E : Result := $76;
      $6F : Result := $F6;
      $70 : Result := $0E;
      $71 : Result := $8E;
      $72 : Result := $4E;
      $73 : Result := $CE;
      $74 : Result := $2E;
      $75 : Result := $AE;
      $76 : Result := $6E;
      $77 : Result := $EE;
      $78 : Result := $1E;
      $79 : Result := $9E;
      $7A : Result := $5E;
      $7B : Result := $DE;
      $7C : Result := $3E;
      $7D : Result := $BE;
      $7E : Result := $7E;
      $7F : Result := $FE;
      $80 : Result := $01;
      $81 : Result := $81;
      $82 : Result := $41;
      $83 : Result := $C1;
      $84 : Result := $21;
      $85 : Result := $A1;
      $86 : Result := $61;
      $87 : Result := $E1;
      $88 : Result := $11;
      $89 : Result := $91;
      $8A : Result := $51;
      $8B : Result := $D1;
      $8C : Result := $31;
      $8D : Result := $B1;
      $8E : Result := $71;
      $8F : Result := $F1;
      $90 : Result := $09;
      $91 : Result := $89;
      $92 : Result := $49;
      $93 : Result := $C9;
      $94 : Result := $29;
      $95 : Result := $A9;
      $96 : Result := $69;
      $97 : Result := $E9;
      $98 : Result := $19;
      $99 : Result := $99;
      $9A : Result := $59;
      $9B : Result := $D9;
      $9C : Result := $39;
      $9D : Result := $B9;
      $9E : Result := $79;
      $9F : Result := $F9;
      $A0 : Result := $05;
      $A1 : Result := $85;
      $A2 : Result := $45;
      $A3 : Result := $C5;
      $A4 : Result := $25;
      $A5 : Result := $A5;
      $A6 : Result := $65;
      $A7 : Result := $E5;
      $A8 : Result := $15;
      $A9 : Result := $95;
      $AA : Result := $55;
      $AB : Result := $D5;
      $AC : Result := $35;
      $AD : Result := $B5;
      $AE : Result := $75;
      $AF : Result := $F5;
      $B0 : Result := $0D;
      $B1 : Result := $8D;
      $B2 : Result := $4D;
      $B3 : Result := $CD;
      $B4 : Result := $2D;
      $B5 : Result := $AD;
      $B6 : Result := $6D;
      $B7 : Result := $ED;
      $B8 : Result := $1D;
      $B9 : Result := $9D;
      $BA : Result := $5D;
      $BB : Result := $DD;
      $BC : Result := $3D;
      $BD : Result := $BD;
      $BE : Result := $7D;
      $BF : Result := $FD;
      $C0 : Result := $03;
      $C1 : Result := $83;
      $C2 : Result := $43;
      $C3 : Result := $C3;
      $C4 : Result := $23;
      $C5 : Result := $A3;
      $C6 : Result := $63;
      $C7 : Result := $E3;
      $C8 : Result := $13;
      $C9 : Result := $93;
      $CA : Result := $53;
      $CB : Result := $D3;
      $CC : Result := $33;
      $CD : Result := $B3;
      $CE : Result := $73;
      $CF : Result := $F3;
      $D0 : Result := $0B;
      $D1 : Result := $8B;
      $D2 : Result := $4B;
      $D3 : Result := $CB;
      $D4 : Result := $2B;
      $D5 : Result := $AB;
      $D6 : Result := $6B;
      $D7 : Result := $EB;
      $D8 : Result := $1B;
      $D9 : Result := $9B;
      $DA : Result := $5B;
      $DB : Result := $DB;
      $DC : Result := $3B;
      $DD : Result := $BB;
      $DE : Result := $7B;
      $DF : Result := $FB;
      $E0 : Result := $07;
      $E1 : Result := $87;
      $E2 : Result := $47;
      $E3 : Result := $C7;
      $E4 : Result := $27;
      $E5 : Result := $A7;
      $E6 : Result := $67;
      $E7 : Result := $E7;
      $E8 : Result := $17;
      $E9 : Result := $97;
      $EA : Result := $57;
      $EB : Result := $D7;
      $EC : Result := $37;
      $ED : Result := $B7;
      $EE : Result := $77;
      $EF : Result := $F7;
      $F0 : Result := $0F;
      $F1 : Result := $8F;
      $F2 : Result := $4F;
      $F3 : Result := $CF;
      $F4 : Result := $2F;
      $F5 : Result := $AF;
      $F6 : Result := $6F;
      $F7 : Result := $EF;
      $F8 : Result := $1F;
      $F9 : Result := $9F;
      $FA : Result := $5F;
      $FB : Result := $DF;
      $FC : Result := $3F;
      $FD : Result := $BF;
      $FE : Result := $7F;
      $FF : Result := $FF;
    end;
  end;
Gruß,

Peter

Neutral General 23. Feb 2016 10:15

AW: Schnelle SwapByte Routine - Bits swappen
 
Oder man spart sich die Tipparbeit auf andere Weise:
Delphi-Quellcode:
function SwapByte(B: Byte): Byte;
var i: Integer;
begin
  Result := 0;
  for i:= 0 to 7 do
    Result := Result or (((b shr i) and 1) shl (7-i));
end;

gammatester 23. Feb 2016 10:42

AW: Schnelle SwapByte Routine - Bits swappen
 
Oder definiere und benutze
Delphi-Quellcode:
const
  swapbyte: array[byte] of byte = (
              $00, $80, $40, $C0, $20, $A0, $60, $E0,
              $10, $90, $50, $D0, $30, $B0, $70, $F0,
              $08, $88, $48, $C8, $28, $A8, $68, $E8,
              $18, $98, $58, $D8, $38, $B8, $78, $F8,
              $04, $84, $44, $C4, $24, $A4, $64, $E4,
              $14, $94, $54, $D4, $34, $B4, $74, $F4,
              $0C, $8C, $4C, $CC, $2C, $AC, $6C, $EC,
              $1C, $9C, $5C, $DC, $3C, $BC, $7C, $FC,
              $02, $82, $42, $C2, $22, $A2, $62, $E2,
              $12, $92, $52, $D2, $32, $B2, $72, $F2,
              $0A, $8A, $4A, $CA, $2A, $AA, $6A, $EA,
              $1A, $9A, $5A, $DA, $3A, $BA, $7A, $FA,
              $06, $86, $46, $C6, $26, $A6, $66, $E6,
              $16, $96, $56, $D6, $36, $B6, $76, $F6,
              $0E, $8E, $4E, $CE, $2E, $AE, $6E, $EE,
              $1E, $9E, $5E, $DE, $3E, $BE, $7E, $FE,
              $01, $81, $41, $C1, $21, $A1, $61, $E1,
              $11, $91, $51, $D1, $31, $B1, $71, $F1,
              $09, $89, $49, $C9, $29, $A9, $69, $E9,
              $19, $99, $59, $D9, $39, $B9, $79, $F9,
              $05, $85, $45, $C5, $25, $A5, $65, $E5,
              $15, $95, $55, $D5, $35, $B5, $75, $F5,
              $0D, $8D, $4D, $CD, $2D, $AD, $6D, $ED,
              $1D, $9D, $5D, $DD, $3D, $BD, $7D, $FD,
              $03, $83, $43, $C3, $23, $A3, $63, $E3,
              $13, $93, $53, $D3, $33, $B3, $73, $F3,
              $0B, $8B, $4B, $CB, $2B, $AB, $6B, $EB,
              $1B, $9B, $5B, $DB, $3B, $BB, $7B, $FB,
              $07, $87, $47, $C7, $27, $A7, $67, $E7,
              $17, $97, $57, $D7, $37, $B7, $77, $F7,
              $0F, $8F, $4F, $CF, $2F, $AF, $6F, $EF,
              $1F, $9F, $5F, $DF, $3F, $BF, $7F, $FF);

Mavarik 23. Feb 2016 11:09

AW: Schnelle SwapByte Routine - Bits swappen
 
Ich finde "den" richtig nice...:

Delphi-Quellcode:
procedure MirrorByte(A : byte) : byte;
var
  B,C,D,F : Uint64;
begin
  B := $0080200802;
  C := $0884422110;
  D := $0101010101;
  F := A;
  F := F * B;
  F := F and C;
  F := F * D;
  F := F shr 32;
  Result := F and $FF;
end;

Kann man natürlich in eine Zeile schreiben aber so sieht man die Bits wandern...

Mavarik

Rollo62 23. Feb 2016 11:12

AW: Schnelle SwapByte Routine - Bits swappen
 
@Mavarik

+1

Darüber muss ich mal nachdenken :-)

BigAl 23. Feb 2016 11:20

AW: Schnelle SwapByte Routine - Bits swappen
 
Verstehe ich da was nicht richtig?

Delphi-Quellcode:
Result := (Value shl 4) or (Value shr 4);
????

noisy_master 23. Feb 2016 11:55

AW: Schnelle SwapByte Routine - Bits swappen
 
Zitat:

Zitat von BigAl (Beitrag 1331077)
Verstehe ich da was nicht richtig?

Delphi-Quellcode:
Result := (Value shl 4) or (Value shr 4);
????

Das verstehst du tatsächlich falsch: Du vertauscht nur die Nibbles, der TE hätte gerne das byte gespiegelt...

noisy_master 23. Feb 2016 12:18

AW: Schnelle SwapByte Routine - Bits swappen
 
In richtig kurz hätte ich noch einen zu bieten:

b := ((b * $0202020202) and $010884422010) mod 1023;

dürfte aber wegen 64bit und modulo relativ langsam sein.

dann hätte ich noch den:

b := (((b and $aa) shr 1) + ((b and $55) shl 1));
b := (((b and $cc) shr 2) + ((b and $33) shl 2));
b := ((b shr 4) + (b shl 4));

ser sollte in Summe eigentlich recht schnell sein(natürlich nicht so schnell wie das Look-Up) und sollte auch recht speichersparend sein(okay, ich gebe es ja zu: ist auf nem PC nicht nötig, aber....)

himitsu 23. Feb 2016 12:33

AW: Schnelle SwapByte Routine - Bits swappen
 
Wirklich
Delphi-Quellcode:
+
und nicht
Delphi-Quellcode:
or
?

bytecook 23. Feb 2016 13:47

AW: Schnelle SwapByte Routine - Bits swappen
 
Hi Leute, danke für die Rückmeldungen :)

sollte nicht die Case hier den höchsten Speed liefern? Mir ist klar, dass ich shiften kann, und das es semantisch "elegantere" Konstrukte gibt.... :-D

Neutral General 23. Feb 2016 13:49

AW: Schnelle SwapByte Routine - Bits swappen
 
Das Array ist wahrscheinlich noch schneller als das case, aber sonst ist alles was berechnet werden muss natürlich langsamer.

bytecook 23. Feb 2016 14:12

AW: Schnelle SwapByte Routine - Bits swappen
 
Zitat:

Zitat von Neutral General (Beitrag 1331110)
Das Array ist wahrscheinlich noch schneller als das case, aber sonst ist alles was berechnet werden muss natürlich langsamer.


Kann durchwegs sein, mal sehen wie sich das auf die Laufzeit / generierten Code auswirkt. Habe dieses Uralt-Beispiel heute mal meinem jungen Mitarbeiter (IT Azubi und zudem Sohn) gezeigt,
als Antwort auf die Frage, wozu Case eigentlich gut sei ....

himitsu 23. Feb 2016 14:37

AW: Schnelle SwapByte Routine - Bits swappen
 
Beim Case wird jeder einzelne Wert verglichen, bis etwas getroffen wird.
Beim Array wird der Eingabewert direkt als Index/Offset verwendet.

Neutral General 23. Feb 2016 15:03

AW: Schnelle SwapByte Routine - Bits swappen
 
Zitat:

Zitat von himitsu (Beitrag 1331118)
Beim Case wird jeder einzelne Wert verglichen, bis etwas getroffen wird.
Beim Array wird der Eingabewert direkt als Index/Offset verwendet.

Das stimmt so auch nicht. Der Compiler legt oft Sprungtabellen an wodurch das case-of selbst eine Art Array auf Assemblerebene wird. (Und gerade bei diesem case-of bietet es sich mehr als an)
Da gibts dann auch keinen so großen Unterschied zu einem direkten Zugriff auf ein Array. Wobei der direkte Zugriff sicherlich immernoch ein Stückchen schneller (und in meinen Augen) schöner zu lesen ist als das gigantische case-of.

Notwendig ist ein case-of nicht, aber für Aufzählungswerte oder oft auch für Zahlenwerte ist es manchmal eine etwas übersichtlichere Alternative zu einer endlosen if-then-else Verkettung.

Mikkey 26. Feb 2016 21:16

AW: Schnelle SwapByte Routine - Bits swappen
 
Hätte noch etwas vermutlich ganz schnelles:

Code:
MOVZX AX, BYTE PTR[a]
RCR AL,1
RCL AH,1
RCR AL,1
RCL AH,1
RCR AL,1
RCL AH,1
RCR AL,1
RCL AH,1
RCR AL,1
RCL AH,1
RCR AL,1
RCL AH,1
RCR AL,1
RCL AH,1
RCR AL,1
RCL AH,1
MOV BYTE PTR[a],AH


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz