2017-06-30 1 views
0

Ich habe heute ein ziemlich einfaches Problem. Ich habe eine Matrix float gradient[COLS][ROWS]. Wie Sie wahrscheinlich wissen, enthält der float Typ 32 Bits. In meinem Code mache ich 4 verschiedene Prüfungen an einer anderen Tabelle. Für jede von ihnen möchte ich in gradient[][] die Ergebnisse schreiben.C++ schreibe auf spezifische Bits in Matrix

Was ich tun möchte, ist diese Ergebnisse auf 8 Bits in gradient[][] schreiben. Also das LSB würde das Ergebnis der ersten Prüfung enthalten, die 8 folgenden Bits die Ergebnisse der zweiten Prüfung und so weiter.

Der Grund, warum ich das tun möchte, ist, weil ich versuche, diesen Code mit HLS zu synthetisieren und es auf einem Xilinx ZedBoard laufen zu lassen. Es ist jedoch nicht viel Speicher auf dem FPGA verfügbar, und statt die Ergebnisse meiner 4 Funktionen in 4 verschiedenen Matrizen zu speichern, möchte ich sie in der gleichen Matrix unter Verwendung von Bitoperationen speichern.

Ich weiß, ich kann Masken mit einem AND-Operator wie gradient[][]&0xFF verwenden. Was ich allerdings nicht weiß ist wann und wie ich diese Maske anwende?

Als Beispiel hier ist der Code für eine der Prüfungen (sry für den spanischen Namen ich dies nicht schreiben):

void FullCheck(float brightness_tab[COLS][ROWS]){ 
    for(int i=0;i<ROWS;i++){ 
     int previous_point = (int)(brightness_tab[0][i]); 
     for(int j=1;j<COLS-1;j++){ 
      float brightness=brightness_tab[i][j]; 
      int brightnessi=(int)(brightness); 
      gradient[i][j]=brightnessi- previous_point; 
      if(!(gradient[i][j]>VALOR_PENDIENTE || gradient[i][j]<-VALOR_PENDIENTE)){ 
       if(!(gradient[i][j] + gradient[i][j-1] >VALOR_PENDIENTE_TRUNCAR || gradient[i][j] + gradient[i][j+1]<-VALOR_PENDIENTE_TRUNCAR)){ 
        gradient[i][j]=0; 
       } 
      } 
      if(j<2 || i<2 || COLS-1 ==i){gradient[i][j]=0;} 
      previous_point=brightnessi; 
     } 
    } 
} 

Sie für Ihre Antworten im Voraus Dank!

+5

'Wie Sie wahrscheinlich wissen, enthält der Float-Typ 32 Bits." Nein, das wissen wir nicht. Die Größe und das Layout werden nicht von der Sprache festgelegt. Sich auf Annahmen über die Repräsentation zu verlassen, ist eine todsichere Möglichkeit, schlecht geformten Zeitbombencode zu schreiben. –

+4

Ich verstehe immer noch nicht * warum * Sie möchten Bitoperationen auf 'float' durchführen? Was genau soll das Ergebnis dieser Operation sein (und warum muss es im Float gespeichert werden)? – UnholySheep

+0

@underscore_d Nun, ich bin kein Experte, aber: 'Single-Precision Fließkomma-Format ist ein Computer-Nummer-Format, das 4 Bytes (32 Bits) in Computer-Speicher belegt und einen breiten dynamischen Bereich von Werten durch Verwendung eines Gleitkomma darstellt. ' –

Antwort

1

Ausgehend von Ihren Kommentaren nehme ich an, dass gradient als int Array deklariert wird.

In Ihrem Beispielcode gibt es 2 Fälle für das Schreiben von etwas in die Matrix. Im ersten Fall, möchten Sie einen gewissen Wert, wie diese Zeile schreiben:

gradient[i][j] = brightnessi - previous_point; 

Wenn Sie einige Daten zu einem bestimmten Byte schreiben möchten, die Daten, die Sie sollte ein 1-Byte-Daten schreiben wollen selbst .

gradient[i][j] = 0;   // initialize to all zero bits 
int data1 = 0x12;   // 1-byte value 
gradient[i][j] |= data1;  // writing to the 1st byte (LSB) 
int data2 = 0x34; 
gradient[i][j] |= data2 << 8; // writing to the 2nd byte 
int data3 = 0x56; 
gradient[i][j] |= data3 << 16; // writing to the 3rd byte 
int data4 = 0x78; 
gradient[i][j] |= data4 << 24; // writing to the 4th byte 

Nach dem obigen Code ausgeführt wird, wird der Wert von gradient[i][j]0x78563412 sein.

Der zweite Fall klärt, was Sie vor, indem man 0 geschrieben haben, wie diese Zeile:

gradient[i][j] = 0; 

In diesem Fall Sie

gradient[i][j] &= 0xffffff00; // clearing the 1st byte (LSB) 
gradient[i][j] &= 0xffff00ff; // clearing the 2nd byte 
gradient[i][j] &= 0xff00ffff; // clearing the 3rd byte 
gradient[i][j] &= 0x00ffffff; // clearing the 4th byte 
+0

Danke für Ihre Antwort! Also zum Beispiel in meiner ersten Funktion, wenn ich auf die 8 LSB schreiben möchte, benutze ich die Maske mit '0xff'. Wenn ich auf das 3D-Byte schreiben möchte, würde ich '0xff << 16' verwenden? Ich dachte ich müsste eine Maske mit '0xff0000' machen? –

+0

@ValentinDubois Ich habe die Antwort aktualisiert, um einen Beispielfall einzuschließen. Wenn es nicht das ist, was du erreichen willst, lass es mich wissen, damit ich den Beitrag verbessern kann. Außerdem hatte die ursprüngliche Antwort einige Fehler zum Löschen eines bestimmten Bytes, und ich habe es behoben. – nglee

+0

Vielen Dank Ihnen zwei für Ihre Antwort. Ich änderte das Array von 'float' nach' int' basierend auf @underscore_d Ratschlag und prüfte alle Änderungen, fand aber keine, die wichtig sind. Auf diese Weise kann ich die Bit-für-Bit-Operation von @nglee verwenden. Ich muss noch eine Bank in Vivado HLS schreiben, um zu sehen, ob es wirklich funktioniert, aber für den Moment gebe ich es als eine Lösung zu. –

1

tun können Sie auch eine Struktur tun könnten, dass hat das gleiche Speicherlayout

struct Bytes 
{ 
    uint8_t a; 
    uint8_t b; 
    uint8_t c; 
    uint8_t d; 
} ; 

Bytes* g = reinterpret_cast<Bytes*>(&gradient[i][j]); 

Auf diese Weise können Sie die einzelnen Bytes problemlos wiezugreifen

+0

Ja, das wird wahrscheinlich funktionieren, besonders bei einem eingebetteten Compiler, obwohl es formal immer noch UB ist. Ich würde auch hinzufügen, dass "uint8_t" nicht der gleiche Typ wie die kleinste adressierbare Byte-Einheit auf einem System sein muss, das ist "unsigned char", obwohl es in den meisten Fällen wahrscheinlich ein typedef zu dem gleichen ist. –

+0

@underscore_d Ich glaube nicht, dass es formal UB ist, die Struktur hat Standard-Layout, so dass es funktionieren sollte und angesichts der Einschränkungen in Bezug auf Portabilität und Größe von char würde es funktionieren. –

+0

Der Standard berücksichtigt nur das Umwandeln zwischen Objekten mit verwandten Typen, nicht willkürlichen Objekten mit dem gleichen Layout. Alles andere, einschließlich des letzteren, verstößt gegen Regeln für das Casting und striktes Aliasing. Sicher, es wird wahrscheinlich an jedem Compiler arbeiten, der sich nicht bemüht, Sie in den Fuß zu schießen, aber es ist nicht erforderlich, überhaupt zu arbeiten, und es ist ein Zeichen von sprödem Code, der jeden Moment zu versagen beginnen könnte. –