Zahl bitweise spreizen
- Schrompf
- Moderator
- Beiträge: 5163
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Zahl bitweise spreizen
Moin,
ich habe die Frage jetzt ein paar gelöscht, um sie jetzt doch mal zu Ende zu tippen und abzuschicken. Ich suche eine einfache Möglichkeit, eine Zahl bitweise zu spreizen. Also aus der Bitfolge
000000000000JKLM
will ich bekommen
000000000J0K0L0M
oder gern auch
0000 00J0 0K00 L00M
Nach meinem Verständnis kommt das einer Potenzierung gleich, aber mir fällt keine einfache Operation ein, das hinzubekommen, ohne die Bits zu vereinzeln und zurechtzuschieben.
Hintergrund: wenn man ein 2D- oder 3D-Array nicht banal zeilen- und schichtenweise linearisiert, sondern räumlich lokale Bereiche auch im Speicher lokal haben will, bekommt man solche Rechenschritte. Ich würde zum Beispiel gern einen 16x16x16-Cluster speichern, indem ich die 8 Subcluster von je 8x8x8 Größe hintereinander speichere, und jeden 8x8x8-Cluster wieder als 8 4x4x4-Cluster, usw. Wenn ich also aus einem XYZ-Index einen Arrayindex berechnen will, muss ich die Bits der drei Größen genau so interleaven wie im letzten Beispiel oben. Und daher suche ich eine schnelle Bit-Operation, um die Bits einer Zahl so zu spreizen.
ich habe die Frage jetzt ein paar gelöscht, um sie jetzt doch mal zu Ende zu tippen und abzuschicken. Ich suche eine einfache Möglichkeit, eine Zahl bitweise zu spreizen. Also aus der Bitfolge
000000000000JKLM
will ich bekommen
000000000J0K0L0M
oder gern auch
0000 00J0 0K00 L00M
Nach meinem Verständnis kommt das einer Potenzierung gleich, aber mir fällt keine einfache Operation ein, das hinzubekommen, ohne die Bits zu vereinzeln und zurechtzuschieben.
Hintergrund: wenn man ein 2D- oder 3D-Array nicht banal zeilen- und schichtenweise linearisiert, sondern räumlich lokale Bereiche auch im Speicher lokal haben will, bekommt man solche Rechenschritte. Ich würde zum Beispiel gern einen 16x16x16-Cluster speichern, indem ich die 8 Subcluster von je 8x8x8 Größe hintereinander speichere, und jeden 8x8x8-Cluster wieder als 8 4x4x4-Cluster, usw. Wenn ich also aus einem XYZ-Index einen Arrayindex berechnen will, muss ich die Bits der drei Größen genau so interleaven wie im letzten Beispiel oben. Und daher suche ich eine schnelle Bit-Operation, um die Bits einer Zahl so zu spreizen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
-
- Moderator
- Beiträge: 2157
- Registriert: 25.02.2009, 13:37
Re: Zahl bitweise spreizen
Ja wie willst du auch die Bits einzeln zurechtschieben, ohne sie einzeln zurechtzuschieben?Schrompf hat geschrieben: Nach meinem Verständnis kommt das einer Potenzierung gleich, aber mir fällt keine einfache Operation ein, das hinzubekommen, ohne die Bits zu vereinzeln und zurechtzuschieben.
EDIT: Musste nochmal nachdenken:
du brauchst 4 AND 4 SHIFT und 4 OR um das hinzubekommen, oder? Wieviel besser soll es noch gehen?
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Zahl bitweise spreizen
Es gibt iirc SSE2 Instructions die den Inhalt zweier Register interleaven können. Ansonsten würd ich das auf die Schnelle wohl einfach mit ein bisschen Bitgeschubse erledigen...
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Zahl bitweise spreizen
Das was du da generieren willst nennt sich Morton Code (mehrere Zahlen bit-interleaved, z.B. um Positionen in Cache-freundliches Z-order/morton-order Layout zu sortieren). Für Encoding & Decoding ohne spezielle Instruktionen klicke hier.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- Schrompf
- Moderator
- Beiträge: 5163
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Zahl bitweise spreizen
Morton Code! Ein Stichwort zum Belesen! Danke.
Bitgeschubse geht natürlich immer. Aber da bräuchte ich pro Bit und pro Teilnehmer mindestens ein AND und ein Shift. Ich dachte, ich frage mal, ob es was Besseres als das gibt.
Bitgeschubse geht natürlich immer. Aber da bräuchte ich pro Bit und pro Teilnehmer mindestens ein AND und ein Shift. Ich dachte, ich frage mal, ob es was Besseres als das gibt.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Zahl bitweise spreizen
Siehe Link, für 16 Bits brauchst du 4 Ands und 4 Shifts pro Teilnehmer, fortgesetzt für 32 Bits jeweils nur eine Operation mehr.Schrompf hat geschrieben:Bitgeschubse geht natürlich immer. Aber da bräuchte ich pro Bit und pro Teilnehmer mindestens ein AND und ein Shift. Ich dachte, ich frage mal, ob es was Besseres als das gibt.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- Schrompf
- Moderator
- Beiträge: 5163
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Zahl bitweise spreizen
Ich weiß! Daher mein "Danke" :-)CodingCat hat geschrieben:Siehe Link, für 16 Bits brauchst du 4 Ands und 4 Shifts pro Teilnehmer, fortgesetzt für 32 Bits jeweils nur eine Operation mehr.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Zahl bitweise spreizen
OK, wollte nur sichergehen, dass du das gefunden hast. :)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Re: Zahl bitweise spreizen
Wenn es vom Code her kürzer sein soll:
Damit machst du z.B. aus "00001111" -> "10101010".
Wenn du "01010101" haben willst musst du halt result >>= 2; schreiben. ;)
n gibt die Anzahl der Bits an die du berücksichtigen willst. Im Beispiel z.B. 4.
Prinzipiell ist das Ergebnis Bit0 * 2 + Bit1 * 4 + Bit2 * 8 + ...
Wenn die Bits gesetzt sind also quasi 1 * 2 + 2 * 4 + 4 * 8 + ...
Zur Einfachheit verdopple ich die Bit-Werte, sodass ich Potenzen nutzen kann: 2 * 2 + 4 * 4 + 8 * 8 + ... bzw. Bit0 * 2 + Bit1 * 4 + Bit2 * 8 + ...
Dann muss man am Ende das Ergebnis nur wieder durch 2 teilen und hat das Ergebnis. So hab ichs im Beispiel gemacht.
Code: Alles auswählen
int result = 0;
for (int i = 0; i < n; ++i)
{
int val = (bits & (1 << i)) << 1;
result += val * val;
}
result >>= 1;
Wenn du "01010101" haben willst musst du halt result >>= 2; schreiben. ;)
n gibt die Anzahl der Bits an die du berücksichtigen willst. Im Beispiel z.B. 4.
Prinzipiell ist das Ergebnis Bit0 * 2 + Bit1 * 4 + Bit2 * 8 + ...
Wenn die Bits gesetzt sind also quasi 1 * 2 + 2 * 4 + 4 * 8 + ...
Zur Einfachheit verdopple ich die Bit-Werte, sodass ich Potenzen nutzen kann: 2 * 2 + 4 * 4 + 8 * 8 + ... bzw. Bit0 * 2 + Bit1 * 4 + Bit2 * 8 + ...
Dann muss man am Ende das Ergebnis nur wieder durch 2 teilen und hat das Ergebnis. So hab ichs im Beispiel gemacht.
Zuletzt geändert von BeRsErKeR am 24.01.2013, 11:00, insgesamt 1-mal geändert.
Ohne Input kein Output.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Zahl bitweise spreizen
Ich schätze, Leistung ist ihm gerade wichtiger als deutlicher Quelltext. Außerdem: unsigned bei Bitgeschichten! ;)
Re: Zahl bitweise spreizen
Das war eben zum Test reingehackt. unsigned ist schon klar. ;)Krishty hat geschrieben:Ich schätze, Leistung ist ihm gerade wichtiger als deutlicher Quelltext. Außerdem: unsigned bei Bitgeschichten! ;)
Übrigens kann man das Beispiel vielleicht auch auf relativ einfache Bitoperationen reduzieren.
Ohne Input kein Output.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Zahl bitweise spreizen
Evtl. auch interessant: http://graphics.stanford.edu/~seander/b ... ve64bitOps ;)
Re: Zahl bitweise spreizen
Wirklich sehr interessant. Auf Schrompfs Beispiel bezogen kann er das dann einfach mit folgendem Code machen:dot hat geschrieben:Evtl. auch interessant: http://graphics.stanford.edu/~seander/b ... ve64bitOps ;)
Code: Alles auswählen
unsigned int bits = 15; // should be lower than 2^16
bits = (bits | (bits << 8)) & 0x00FF00FF;
bits = (bits | (bits << 4)) & 0x0F0F0F0F;
bits = (bits | (bits << 2)) & 0x33333333;
bits = (bits | (bits << 1)) & 0x55555555;
Ohne Input kein Output.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Zahl bitweise spreizen
Hm? Bezog sich dot nicht eher darauf, das via Multiplikation zu lösen?
- Schrompf
- Moderator
- Beiträge: 5163
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Zahl bitweise spreizen
Aber sehr coole Seite, die Du da verlinkt hast, dot! Danke, die speichere ich mir gleich mal.
Aus meinem Bauchgefühl heraus sollte das in bestenfalls O(log n) mit n als Bitanzahl möglich sein. Aber vielleicht hätte es dafür ja auch eine Intrinsic Function gegeben... ich hatte da Hoffnung, nachdem ich jetzt _BitScanForward und _BitScanReverse für mich entdeckt habe. Aber nuja, die Bit Twiddling Hacks sind auch sehr cool.
Aus meinem Bauchgefühl heraus sollte das in bestenfalls O(log n) mit n als Bitanzahl möglich sein. Aber vielleicht hätte es dafür ja auch eine Intrinsic Function gegeben... ich hatte da Hoffnung, nachdem ich jetzt _BitScanForward und _BitScanReverse für mich entdeckt habe. Aber nuja, die Bit Twiddling Hacks sind auch sehr cool.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Zahl bitweise spreizen
Mich wundert ja, wieso ich die Seite nicht gleich verlinkt hab; mein Problem war wohl dass ich bei deinem Beispiel sofort die Ziffern einer Zahl in Hex gesehen und an Nibbles gedacht hab und das Wort "Bitfolge" irgendwie an meinem Hirn vorbeigezogen ist. ^^
Über ein entsprechendes Intrinsic wär ich noch nicht gestolpert, die SSE2 Instructions an die ich gedacht hab, können nur ganze Bytes interleaven, nicht einzelne Bits.
Aber rein prinzipiell brauchst du ja eigentlich einfach nur die geraden und ungeraden Bits beider Operanden maskieren und entsprechend geshiftet zusammen ORen, was ja wohl genau ist, was der bereits gepostete Beispielcode macht...
Über ein entsprechendes Intrinsic wär ich noch nicht gestolpert, die SSE2 Instructions an die ich gedacht hab, können nur ganze Bytes interleaven, nicht einzelne Bits.
Aber rein prinzipiell brauchst du ja eigentlich einfach nur die geraden und ungeraden Bits beider Operanden maskieren und entsprechend geshiftet zusammen ORen, was ja wohl genau ist, was der bereits gepostete Beispielcode macht...