Forum: Mikrocontroller und Digitale Elektronik Zahl umdrehen?


von Peter N. (alv)


Lesenswert?

Hi

Ich habe eine 64 Bit Binärzahl, in der steht leider das niederwertigste 
Bit links, das höchstwertige rechts.

Bevor ich jetzt anfange, jedes Bit einzeln umzusortieren, frage ich 
erstmal:
Gibt es eine einfache (mathematische) Möglichkeit, die ganze Zahl um 
180° zu drehen?

: Verschoben durch Moderator
von Christoph db1uq K. (christoph_kessler)


Lesenswert?

In Assembler würde ich es aus einem Register z.B. links herausschieben 
und über das Carryflag in ein anderes Register links reinschieben.
Für 64 Bit sind das allerdings 16 Register, in einem 8-Bitter wie dem 
AVR ist damit schon die Hälfte aller Register belegt.

: Bearbeitet durch User
von Stefan P. (form)


Lesenswert?

Hier werden mehrere Möglichkeiten vorgestellt:
http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious

von Ingo L. (corrtexx)


Lesenswert?

Ingo L. schrieb:
> for ( uint8_t i = 0; i<64; i++ ){
1
for ( uint8_t i = 0; i<=64; i++ ){
selber reingefallen :(

: Bearbeitet durch User
Beitrag #7415276 wurde vom Autor gelöscht.
von Ingo L. (corrtexx)


Lesenswert?

1
uint64_t Flip ( uint64_t Zahl )
2
{
3
  uint64_t Temp = 0;
4
  for ( uint8_t i = 0; i<=64; i++ ){
5
   if ( Zahl & (1ul<<(64-i)) ) // Von links anfangen
6
    Temp |= (1ul<<i); // und rechts einsortieren
7
  }
8
  return Temp;
9
}
Das kann man noch weiter optimieren, aber verständlicher Code ist gut
wartbar

: Bearbeitet durch User
von Norbert (der_norbert)


Lesenswert?

Ingo L. schrieb:
>
1
for ( uint8_t i = 0; i<=64; i++ )

Off by one error!



So vielleicht?
1
uint64_t flip_again(uint64_t in) {
2
  uint64_t out = 0;
3
  for (uint8_t i = 0; i < 64; i++, in >>= 1)
4
      out = in & 1 ? (out << 1) | 1 : out << 1;
5
  return out;
6
}

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

Norbert schrieb:
> So vielleicht?
Geht auch, aber schlecht lesbar und schlecht wartbar.

Norbert schrieb:
> for ( uint8_t i = 0; i<=64; i++ )
>
> Off by one error!
Ja, leider verrissen :(, Informatiker 0-Problem

Hier nochmal in lesbar
1
uint64_t Flip ( uint64_t Zahl )
2
{
3
  uint64_t Temp = 0;
4
  for ( uint8_t i = 0; i<64; i++ ){ // Schleife läuft von 0...63
5
   if ( Zahl & (1ul<<(63-i)) ) // Von links anfangen
6
    Temp |= (1ul<<i); // und rechts einsortieren
7
  }
8
  return Temp;
9
}

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Peter N. schrieb:
> Ich habe eine 64 Bit Binärzahl, in der steht leider das niederwertigste
> Bit links, das höchstwertige rechts.
Woher kommt die?

Oder andersrum: kannst du die nicht gleich beim Einlesen richtig 
sortieren?

: Bearbeitet durch Moderator
von DSGV-Violator (Gast)


Angehängte Dateien:

Lesenswert?

> Gibt es eine einfache (mathematische) Möglichkeit, die ganze Zahl um
> 180° zu drehen?

Klar einfach auf dem karierten Mathepapier die Zahlen in umgekehrter 
Schreibweise (reverse order) hinschreiben ....

Ohne zu wissen, welche Möglichkeiten/Tools du 
hast/kennst/dich_nicht_zierst_zu_benutzen kann man die Frage nicht 
beantworten!

Manche Prozessoren haben einen Maschienenbefehl um die Reihenfolge zu 
tauschen (DSP, Cortex -> RBIT). Siehe Anhang.

Dann kann man sich mit Schiebe/Rotationsbefehlen was basteln, vielleicht 
kann man mit einem Barrel-shifter was beschleunigen

Für PLD schreibt am einfach die Zeile sig_a(31 downto 0) <= sig_b(0 to 
31) und die tools basteln die Umverdrahtung.

Ein Blick in die maschinennahen Bibliotheken (bspw.: CMSIS) kann auch 
nicht schaden.

Also hilf dir selbst, dann hilft dir Gott!

von J. R. (yoc)


Lesenswert?

Christoph db1uq K. schrieb:
> Für 64 Bit sind das allerdings 16 Register, in einem 8-Bitter wie dem
> AVR ist damit schon die Hälfte aller Register belegt.

Man muss ja nicht alles um 64 Bit schieben.
Je nach Architektur und Sprache Byte oder Wordweise und dann 
umsortieren.

von Ingo L. (corrtexx)


Lesenswert?

J. R. schrieb:
> Je nach Architektur
Die ja streng geheim ist...

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Einfach mit einer Lookup-Table arbeiten. Passt genau in 131072 PiByte 
;-)

Gruss
WK

von DSGV-Violator (Gast)


Lesenswert?

Ingo L. schrieb:
> J. R. schrieb:
>> Je nach Architektur
> Die ja streng geheim ist...

Aber mit Architektur kennt sich der TO aus, er weiß was 180° im Bauwesen 
bedeutet ... "... die ganze Zahl um 180° zu drehen ..."

Echt, wo die Grundlage fehlt, ist Hopfen, Malz und guter Rat 
verschwendet.

von Mi N. (msx)


Lesenswert?

Ingo L. schrieb:
>> Je nach Architektur
> Die ja streng geheim ist...

Es geht wohl um PicoMite (BASIC) und den RP2040 ;-)
Beitrag "allgemeine PicoMite Anfängerfragen"

von DSGV-Violator (Gast)


Lesenswert?

Mi N. schrieb:
> Ingo L. schrieb:
>>> Je nach Architektur
>> Die ja streng geheim ist...
>
> Es geht wohl um PicoMite (BASIC) und den RP2040


Na dann ist es doch einfach, weil
"MMBasic allows the embedding of compiled C programs for high 
performance functions"

Also einfach den vorgeschlagenen ARM-maschinenbefehl ("RBIT") als online 
in C einbinden, kompilieren und dem Basic vor die Füße werfen. Ferdsch!
Beitrag "Re: Zahl umdrehen?"

Wobei, der RP2040 als CortexMo doch 32bit lange Register hat?!

von (prx) A. K. (prx)


Lesenswert?

Interessanterweise gibt es im GCC zwar Builtins um Bytes, Halbworte etc 
umzudrehen, nicht aber bei Bits. Genau das wäre aber die sinnvollste 
Stelle, weil viele Architekturen entsprechenden Hardware-Support haben.

von Bruno V. (bruno_v)


Lesenswert?

straight code wenn der Prozessor Byte-Orientiert ist (ungetestet):
1
typedef unsigned char BYTE;
2
3
BYTE revBYTE(BYTE b) 
4
{
5
/*z.B. so. Der Compiler weiss, was er daraus macht */
6
  b = (b & 0xf0)>>4 | (b & 0x0f)<<4;
7
  b = (b & 0xcc)>>2 | (b & 0x33)<<2;
8
  b = (b & 0xaa)>>1 | (b & 0x55)<<1;
9
}
10
11
void foo(void)
12
{
13
BYTE *pIn  = (BYTE*) &DeineZahlIn;
14
BYTE *pOut = (BYTE*) &DeineZahlOut + sizeof(DeineZahlIn);
15
BYTE *pInEnd= pIn                  + sizeof(DeineZahlIn);
16
17
   do {*--pOut = revBYTE(*pIn++);} while(pIn < pEnd);
18
}

: Bearbeitet durch User
von Rbx (rcx)


Lesenswert?

Peter N. schrieb:
> Gibt es eine einfache (mathematische) Möglichkeit, die ganze Zahl um
> 180° zu drehen?

mathematisch nicht, aber gewusst wie.

"Mathematisch" könnte man sich an Haskell versuchen.
https://stackoverflow.com/questions/19725292/how-to-reverse-an-integer-in-haskell
Der grobe Ansatz da ist aber u.a. die "Zahl" in eine Liste zu 
verwandeln, und diese dann umdrehen - was sich leichter automatisieren 
wie auch gezielter angehen lässt.

Ja nach Hardware hat man noch andere Möglichkeiten, Goodies hier, 
Goodies da - nur dann muss man die Hardware kennen.

Kenn man die Hardware nicht, könnte man sich zumindest mal den den 
Asm-Code vom (c-)Compiler (s.o.) genauer ansehen.

Um Verwirrungsalarm aus dem Weg zu gehen, sollte man sich mehrere 
Lösungsansätze ansehen, u.a. auch
https://www.techiedelight.com/de/inplace-rotate-matrix-180-degrees/

von Norbert (der_norbert)


Lesenswert?

DSGV-Violator schrieb:
> Also einfach den vorgeschlagenen ARM-maschinenbefehl ("RBIT") als online
> in C einbinden, kompilieren und dem Basic vor die Füße werfen.

Ich befürchte allerdings das der CortexM0+ ein »RBIT« leider gar nicht 
in seinem Repertoire hat…

Allerdings verfügt er über PIOs samt Assembler, da könnte man mal hinein 
schauen. Aber vorher anschnallen, …

von Norbert (der_norbert)


Lesenswert?

Ingo L. schrieb:
> Geht auch, aber schlecht lesbar…

Na ja, wir reden hier von stattlichen zwei Zeilen mit Gehalt.
Da muss man die beiden halt öfter lesen…

> …und schlecht wartbar.

Na ja, wir reden hier von stattlichen zwei Zeilen mit Gehalt.
Da muss man die beiden halt mal verstehen…

von Wilhelm M. (wimalopaan)


Lesenswert?

Rbx schrieb:
> Ja nach Hardware hat man noch andere Möglichkeiten, Goodies hier,
> Goodies da - nur dann muss man die Hardware kennen

Mit 16 GPIO kannst Du das einzelne Byte per HW spiegeln. Mit 128 GPIO 
auch den ganzen Wert.

von Fritz G. (fritz65)


Lesenswert?

Dergute W. schrieb:
> Einfach mit einer Lookup-Table arbeiten. Passt genau in 131072 PiByte
Wenn man eine Lookup-Tabelle für 8 Bit-Zahlen erstellt, belegt diese 
ganze 256 Bytes. Soviel Platz im ROM sollte sein. Dann kann man die 
64bit-Zahl in 8 Schritten à 1 Byte umdrehen. Das ginge deutlich 
schneller als die 64Bits einzeln zu schieben.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Fritz G. schrieb:
> Dergute W. schrieb:
>> Einfach mit einer Lookup-Table arbeiten. Passt genau in 131072 PiByte
> Wenn man eine Lookup-Tabelle für 8 Bit-Zahlen erstellt, belegt diese
> ganze 256 Bytes. Soviel Platz im ROM sollte sein. Dann kann man die
> 64bit-Zahl in 8 Schritten à 1 Byte umdrehen. Das ginge deutlich
> schneller als die 64Bits einzeln zu schieben.

Ja, wenns ums Platzsparen geht, dann wird man mit einer 1bit LUT noch 
viel mehr sparen koennen...

scnr,
WK

von Gerald K. (geku)


Lesenswert?

Ich würde es mit einer Mischlösung von Tabellenumrechnung und 
Bytevertausch versuchen:
1
#include <stdio.h>
2
#include <stdint.h>
3
4
static const uint8_t bitReverseTable[256] = {
5
  0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 
6
  0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
7
  0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
8
  0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
9
  0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
10
  0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
11
  0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
12
  0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
13
  0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
14
  0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
15
  0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
16
  0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
17
  0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
18
  0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
19
  0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 
20
  0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
21
  0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
22
  0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
23
  0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
24
  0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
25
  0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
26
  0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
27
  0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
28
  0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
29
  0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
30
  0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
31
  0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
32
  0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
33
  0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
34
  0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
35
  0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
36
  0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
37
};
38
39
uint64_t reverse64(uint64_t num) {
40
41
    union RN {
42
      uint64_t val64;
43
      uint8_t val8[8];
44
    }
45
     
46
    RN rn_i,rn_o;
47
 
48
    rn_i.val64 = num;
49
50
    rn_o.val8[0] = bitReverseTable[rn_i.val8[7]];
51
    rn_o.val8[1] = bitReverseTable[rn_i.val8[6]];
52
    rn_o.val8[2] = bitReverseTable[rn_i.val8[5]];
53
    rn_o.val8[3] = bitReverseTable[rn_i.val8[4]];
54
    rn_o.val8[4] = bitReverseTable[rn_i.val8[3]];
55
    rn_o.val8[5] = bitReverseTable[rn_i.val8[2]];
56
    rn_o.val8[6] = bitReverseTable[rn_i.val8[1]];
57
    rn_o.val8[7] = bitReverseTable[rn_i.val8[0]];
58
59
    return rn_o.val64;
60
}

**ACHTUNG**: Bit- und Byteorder kann von der Prozessorplattform abhängig 
sein!

: Bearbeitet durch User
von Bruno V. (bruno_v)


Lesenswert?

Gerald K. schrieb:
> **ACHTUNG**: Bit- und Byteorder kann von der Prozessorplattform abhängig
> sein!

Und welchen Einfluss könnte das auf Deinen Code haben?

von Rainer W. (rawi)


Lesenswert?

Bruno V. schrieb:
> Und welchen Einfluss könnte das auf Deinen Code haben?

Gute Frage. Das wirkt sich natürlich auf die Bytetauscherei aus. Dann 
muss z.B. nicht [0] mit [7], sondern [7] mit [0] getauscht werden. 😀

von C-hater (c-hater)


Lesenswert?

Norbert schrieb:

> Allerdings verfügt er über PIOs samt Assembler, da könnte man mal hinein
> schauen. Aber vorher anschnallen, …

Ach watt, völlig trivial. Das ist ein Fünfzeiler, davon nur drei 
Instruktionen. pull block, mov ISR, OSR (mit Operation "bit-reverse"), 
push noblock.

Sprich: wenn die PIO mit Systemtakt läuft, braucht das Teil drei 
CPU-Takte für die Operation.

von C-hater (c-hater)


Lesenswert?

C-hater schrieb:
> Norbert schrieb:
>
>> Allerdings verfügt er über PIOs samt Assembler, da könnte man mal hinein
>> schauen. Aber vorher anschnallen, …
>
> Ach watt, völlig trivial. Das ist ein Fünfzeiler, davon nur drei
> Instruktionen. pull block, mov ISR, OSR (mit Operation "bit-reverse"),
> push noblock.
>
> Sprich: wenn die PIO mit Systemtakt läuft, braucht das Teil drei
> CPU-Takte für die Operation.

Mist, übersehen: es ging um eine 64Bit-Zahl. Dann wird's doch etwas 
länglicher, dann sind's sieben Operationen (also sieben Takte):

pull block
mov X, Bit-Revers OSR
pull block
mov ISR, Bit-Revers OSR
push noblock
mov ISR, X
push noblock

Beitrag #7415903 wurde von einem Moderator gelöscht.
Beitrag #7415906 wurde von einem Moderator gelöscht.
von Norbert (der_norbert)


Lesenswert?

C-hater schrieb:
> Ach watt, völlig trivial.

Stimmt. Diesen Vorschlag hatte ich nämlich schon vor einigen Tagen auf 
Github in MicroPython Discussions gepostet…

von Falk B. (falk)


Lesenswert?

Peter N. schrieb:
> Bevor ich jetzt anfange, jedes Bit einzeln umzusortieren, frage ich
> erstmal:

Naja. Die Frage ist schlicht, wie schnell es denn WIRKLICH sein muss? Du 
musst sicher NICHT die Zahl in 1us umdrehen und auch nicht 1M davon.

Wenn der triviale Ansatz der Bitschieberei schnell genug ist, nimm ihn 
und wende dich den wirklich wichtigen und interessanten Aufgaben deines 
Projektes zu.

https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Prinzipien_der_Optimierung

Gilt sehr allgemein für viele Dinge, nicht nur in der Elektronik und 
Software.

von C-hater (c-hater)


Lesenswert?

Norbert schrieb:
> C-hater schrieb:
>> Ach watt, völlig trivial.
>
> Stimmt. Diesen Vorschlag hatte ich nämlich schon vor einigen Tagen auf
> Github in MicroPython Discussions gepostet…

Welchen? 32Bit oder 64Bit? Und wo finde ich auf github irgendwelche 
Diskussionsforen?

von Norbert (der_norbert)


Lesenswert?

C-hater schrieb:
> Welchen? 32Bit oder 64Bit? Und wo finde ich auf github irgendwelche
> Diskussionsforen?

github: MicroPython: Discussions
Hab' erst eine recht schnelle Python-Viper Routine geschrieben, danach 
eine Python-Thumb-Assembler Version und dann den schnellsten Vorschlag 
mit PIO Assembler und DMA gemacht. Der war - wie du schon geschrieben 
hattest - so trivial, das ihn nur erwähnt hatte.

War zwar nur 32bit, aber sinngemäß geht's natürlich mit beliebigen 
Bitweiten.

von C-hater (c-hater)


Lesenswert?

Norbert schrieb:

> War zwar nur 32bit, aber sinngemäß geht's natürlich mit beliebigen
> Bitweiten.

Ähem, nö. Mit den einfachen PIO-Programmen ist bei diesem konkreten 
Problem bei 96 Bit Schicht im Schacht. Liegt daran, dass die PIO halt 
nur vier Register hat, davon nur zwei "frei verwendbare" (hier natürlich 
als Cache für das Reverse der Long-Words).

128Bit oder gar 256Bit mit vMax zu reversen braucht eine Kombination aus 
PIO und ARM-Assembler.

Das ist dann schon nicht mehr ganz so trivial...

Beitrag #7415947 wurde vom Autor gelöscht.
von Norbert (der_norbert)


Lesenswert?

Bei max. 2048b:
Eine PIO-SM hat jeweils vier ›WORD‹ FIFO kann also 8*32b = 256b ohne 
weiteres halten. Vier davon sofort verarbeiten und vier im FIFO halten. 
Acht SM können so 2048b entgegen nehmen.

Die Daten müssen ja sowieso irgendwo stehen, bevorzugt in einem array.

Man kann 64 ›WORD‹ aus dem array lesen und ungebremst in die PIO-FIFOs 
schieben. Dann liest man ungebremst 64 ›WORD‹ und schreibt sie rückwärts 
in das array zurück.

Wenn größer 2048b, dann kann man auch noch den Stapel nutzen. Wenn der 
nicht reicht, wird's akademisch… ;-)

von C-hater (c-hater)


Lesenswert?

Norbert schrieb:

> Eine PIO-SM hat jeweils vier ›WORD‹ FIFO kann also 8*32b = 256b ohne
> weiteres halten. Vier davon sofort verarbeiten und vier im FIFO halten.

Die FIFOs sind aber leider aus der PIO heraus nicht wahlfrei zugänglich. 
Deswegen heißen die Befehle für den Zugriff darauf auch PUSH/POP. 
Sprich: die "Drehung" der Daten auf der Ebene von 32Bit-Wörtern ist nur 
über Zwischenspeicherung in der PIO möglich. Deswegen ist deren 
Registerzahl hier der limitierende Faktor.

> Die Daten müssen ja sowieso irgendwo stehen, bevorzugt in einem array.

Die PIO kann eben nicht wahlfrei darauf zugreifen, sondern nur als FIFO. 
Also nix mit Array.

> Acht SM können so 2048b entgegen nehmen.

Ja klar, mit mehr PIO-Instanzen geht natürlich mehr als mit nur einer.

von Norbert (der_norbert)


Lesenswert?

C-hater schrieb:
> Die FIFOs sind aber leider aus der PIO heraus nicht wahlfrei zugänglich.

Wenn du Zahlen größer ›WORD‹ (sagen wir mal 8*32bit) in einem 
Speicherbereich liegen hast, dann müssen die sowieso in 32bit Stücken in 
den FIFO geschoben werden. Geht nicht anders.
Bei einem zu spiegelnden 256bit Wert kann man mit einem
›mov‹ index 0
und acht
›ldr‹ RAM[index]
›add‹ index 1
›str‹ TX_FIFO
Befehlssequenzen ohne zu warten in den (Eingangs-)FIFO schreiben. Die 
ersten vier Werte holt sich das PIO-Programm direkt ab, reversiert und 
schreibt sie in den (Ausgangs-)FIFO. Der ›stalled‹ dann, weil voll. Die 
letzen vier Werte stehen jetzt noch im (Eingangs-)FIFO. Alles ist 
randvoll.

Jetzt müssen die Werte gelesen werden und zurück in's RAM. Also wieder:
›mov‹ index 0
Acht mal
›ldr‹ RX_FIFO
›add‹ index 1
›str‹ RAM[index]

Sobald ein Wert aus dem RX_FIFO gelesen wird, rutscht den nächste 
automatisch aus dem TX_FIFO, wird gespiegelt und in den RX_FIFO 
geschoben.
Damit sind schließlich die acht ›WORD‹ sowohl gespiegelt als auch (im 
RAM) vertauscht.
Da braucht man noch nicht mal X und Y, ISR und OSR reichen aus.
Und nur einen einzigen PIO-Assembler Befehl.

: Bearbeitet durch User
von Norbert (der_norbert)


Lesenswert?

Dem aufmerksamen Beobachter wird nicht entgangen sein, das die ›add‹ und 
›str‹ Befehle im zweiten Teil getauscht werden müssen. Verfluchtes 
copy'n'paste. ;-)
Leider kann man bei der momentanen Boardsoftware Beiträge nicht sinnvoll 
ändern.

: Bearbeitet durch User
von Max H. (nilsp)


Lesenswert?

Wir wissen ja leider die Architektur nicht, aber zum Bit Reversal wurde 
in Hackers Delight meiner Meinung nach alles gesagt:

https://github.com/hcs0/Hackers-Delight/blob/master/reverse.c.txt

von C-hater (c-hater)


Lesenswert?

Max H. schrieb:

> Wir wissen ja leider die Architektur nicht

Stimmt auffallend. Der TO hat dazu rein garnix gesagt. Und sich im 
Verlauf des Threads auch nie wieder zu Wort gemeldet.

Also offensichtlich: TROLL. Aber sowas von.

von Norbert (der_norbert)


Lesenswert?

Max H. schrieb:
> Wir wissen ja leider die Architektur nicht,

Peter hatte bereits einige Male Fragen zu Picomite Basic gestellt. Es 
darf mit einiger Wahrscheinlichkeit angenommen werden, das ein Pi Pico 
mit RP2040 (also ARM Cortex-M0plus) zum Einsatz kommt.

von Rbx (rcx)


Lesenswert?

C-hater schrieb:
> Also offensichtlich: TROLL. Aber sowas von.

Und vermutlich noch nicht mal das Handbuch der CPU gelesen.
Naja, er dachte wohl, es gib irgendeinen mathematischen Trick.

Tatsächlich beziehen sich 180 Grad eher auf eine Kreisvorstellung. Wenn 
man das auf eine Uhr anwendet, braucht man praktisch nur die 12 nach 
unten ziehen.
Wenn man 64 Bit kreisförmig anordnet, kann man das auch machen - per 
Rotation. In diesem Fall in 32 Schritten.
Da wäre dann aber nur der obere Teil mit dem unteren vertauscht.
Möglicherweise nicht das gesuchte Ergebnis
Ganz abgesehen davon, dass das nicht die schnellste Methode wäre (s.o.).

Gestern hatte ich noch zwei Links gefunden, die nur die Grundlagen 
bearbeiten, und deswegen hatte ich mir die erspart. Aber nach den vielen 
guten Hinweisen oben ist mir das jetzt auch egal ;)

https://www.youtube.com/watch?v=wXGZ7o9HNss
https://www.geeksforgeeks.org/c-program-for-program-for-array-rotation-2/

: Bearbeitet durch User
von Peter N. (alv)


Lesenswert?

Ich hätte nie gedacht, daß so eine für mich einfache Frage, soviele 
Reaktionen hervorruft...

Norbert schrieb:
> Es
> darf mit einiger Wahrscheinlichkeit angenommen werden, das ein Pi Pico
> mit RP2040 (also ARM Cortex-M0plus) zum Einsatz kommt.

Genau so ist es.
Aber ich wollte allgemeine und einfache Antworten, die ich in PicoMite 
umsetzten kann, deshalb keine näheren Angaben. Mit den Kernen des RP2040 
kann ich (noch lange) nichts anfangen...

Ich habe das Problem auf die unelegante Weise gelöst:
Zahl in String umgewandelt und Zeichen für Zeichen umgekehrt in einen 
zweiten String kopiert.

von C-hater (c-hater)


Lesenswert?

Peter N. schrieb:

> Ich habe das Problem auf die unelegante Weise gelöst:
> Zahl in String umgewandelt und Zeichen für Zeichen umgekehrt in einen
> zweiten String kopiert.

LOL. Ja geht so auch. Ist nur "ein wenig" suboptimal, was die 
Performance betrifft. Aber wenn's für dich langt: drauf geschissen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter N. schrieb:
> Ich habe das Problem auf die unelegante Weise gelöst:
> Zahl in String umgewandelt und Zeichen für Zeichen umgekehrt in einen
> zweiten String kopiert.

Und warum dann nicht noch komplizierter?
Du weisst doch, daß nix langsamer ist, als hantieren mit Strings?
Und 64 Mal ein integer schieben ist immer noch um ein vielfacher 
schneller.
1
#include <stdio.h>
2
#include <stdint.h>
3
4
uint64_t DreheBitsUm(uint64_t zahl) {
5
    uint64_t umgedreht = 0;
6
    uint64_t nn = zahl;
7
    for(;nn;nn >>= 1) {
8
        umgedreht <<= 1;
9
        umgedreht += (nn & 1);
10
    }
11
    return umgedreht;
12
}
13
14
int main() {
15
uint64_t xx;
16
  xx = DreheBitsUm(0xdeadbeef);
17
  printf("Umgedreht = 0x%X", xx);
18
  return 0;
19
}

Und dann vergleiche mal um wieviel schneller das ist...

: Bearbeitet durch User
von Mario M. (thelonging)


Lesenswert?

Marc V. schrieb:
> for(;nn;nn >>= 1) {
>
>         umgedreht <<= 1;
>
>         umgedreht += (nn & 1);
>
>     }

Schnell aber falsch. Wenn man 0x1 rein schickt kommt kein 0x80000000 
raus.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Mario M. schrieb:
> Marc V. schrieb:
>> for(;nn;nn >>= 1) {
>>
>>         umgedreht <<= 1;
>>
>>         umgedreht += (nn & 1);
>>
>>     }
>
> Schnell aber falsch. Wenn man 0x1 rein schickt kommt kein 0x80000000
> raus.

Lol.
1
uint64_t DreheBitsUm(uint64_t zahl) {
2
//*********************************
3
    if (zahl == 1) return 0x80000000;
4
//*********************************
5
    uint64_t umgedreht = 0;
6
    uint64_t nn = zahl;
7
    for(;nn;nn >>= 1) {
8
        umgedreht <<= 1;
9
        umgedreht += (nn & 1);
10
    }
11
    return umgedreht;
12
}
Zufrieden?

: Bearbeitet durch User
Beitrag #7416530 wurde vom Autor gelöscht.
von Abdul K. (ehydra) Benutzerseite


Lesenswert?

In der Form eines Sonntagsrätsels brauchbar.

Wozu Algorithmus-Beschreibung oder sinnvolle Kommentare. Völlig 
überflüssig.

Ist ja Freitag, das paßt.

---
(Bezog sich auf den mittlerweile gelöschten Beitrag. Aber generell ist 
es auch meistens richtig)

: Bearbeitet durch User
Beitrag #7416542 wurde vom Autor gelöscht.
von Mi N. (msx)


Lesenswert?

Marc V. schrieb:
> Peter N. schrieb:
>> Ich habe das Problem auf die unelegante Weise gelöst:
>> Zahl in String umgewandelt und Zeichen für Zeichen umgekehrt in einen
>> zweiten String kopiert.
>
> Und warum dann nicht noch komplizierter?

Daß es beim TO um PicoMite geht, sollte mittlerweile jedem klar sein. 
Dann gib ihm bitte auch ein Beispiel in BASIC, damit er etwas damit 
anfangen kann.
Daß irgendetwas ganz schnell gehen müßte, war nicht die Frage. Nur 
steigert man sich hier gerne dahin, daß maximal ein CPU-Takt zulässig 
sei.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.