2017-06-30 19 views
0

今日はかなり単純な問題がありました。行列はfloat gradient[COLS][ROWS]です。おそらく、floatタイプには32ビットが含まれています。 私のコードでは、別のテーブルで4種類のチェックを行います。それぞれについて、結果をgradient[][]に書きたいと思います。C++マトリックス内の特定のビットに書き込む

私がしたいことは、gradient[][]に8ビットでこれらの結果を書き込むことです。 LSBには、最初のチェックの結果、次の8ビット、2回目のチェックの結果などが含まれます。

私がこれをやりたい理由は、HLSを使ってこのコードを合成し、ザイリンクスZedBoard上で実行しようとしているからです。しかし、FPGA上で利用可能なメモリはそれほど多くありませんので、私の4つの関数の結果を4つの異なる行列に格納するのではなく、ビット演算を使って同じ行列に格納するのが良いでしょう。

私は、gradient[][]&0xFFのようなAND演算子でマスクを使用できます。しかし、私はこのマスクを適用する時期と方法はわかりません。ここでは例として

は、小切手の1(SRYスペイン語の名前のために私はこれを書いていない)のためのコードです:

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; 
     } 
    } 
} 

は、あなたの答えを事前にありがとうございます!

+5

「浮動小数点型には32ビットが含まれていることはご存知のように、わかりません。サイズとレイアウトは言語によって指定されていません。表現についての前提に依拠することは、不正な形式の時限コードを書くための確実な方法です。 –

+4

私はまだ理解していない*なぜ*あなたは 'float'でビット操作を実行したいですか?この操作の結果は正確に何であるべきですか(そしてなぜそれが 'float'の中に格納される必要がありますか)? – UnholySheep

+0

@underscore_d私はエキスパートではありませんが、「単精度浮動小数点フォーマットは、コンピュータメモリで4バイト(32ビット)を占め、浮動小数点を使用して幅広いダイナミックレンジを表現するコンピュータナンバーフォーマットです。 ' –

答えて

1

お客様のご意見を控除して、gradientintの配列として宣言されるものとします。

サンプルコードでは、何かを行列に書き込むケースが2つあります。

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

あなたが特定のバイトにいくつかのデータを書き込みたい場合は、あなたが書きたいデータが1バイトのデータそのものでなければなりません。最初のケースでは、あなたは、このラインなど、いくつかの値を書きたいです。コード上に実行した後

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 

gradient[i][j]の値が0x78563412あろう。

後者の場合は、この行として、あなたは0を書き込むことによって、前に書かれたものをクリアされます。この場合

gradient[i][j] = 0; 

あなたはまた、その構造体を行うことができます

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

あなたの答えをありがとう!たとえば、私の最初の関数では、8 LSBに書きたい場合は、マスクを '0xff'で使います。私が3dバイトで書いたければ、私は '0xff << 16"を使うでしょうか?私は '0xff0000'でマスクを作る必要があると思いましたか? –

+0

@ValentinDuboisサンプルケースを含めるように答えを更新しました。あなたが達成しようとしているものでなければ、私に知らせてください。私は投稿を改善することができます。また、元の答えは、特定のバイトをクリアするためのいくつかのエラーがあった、と私はそれを修正しました。 – nglee

+0

お返事ありがとうございました。 @underscore_dのアドバイスに基づいて配列を 'float'から' int'に変更し、変更をチェックしましたが、それは問題ありませんでした。このようにして、@ngleeによって与えられるbit per bit操作を使用できます。私はまだVivado HLSにベンチを書く必要があります。実際に動作するかどうかを確認する必要がありますが、現在は解決策として認めています。 –

1

を行うことができます同じメモリレイアウトを持っています

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

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

この方法で、のように簡単に個々のバイトにアクセスできます

+0

はい、おそらく組み込みコンパイラではうまくいくでしょうが、正式にはまだUBです。また、 'uint8_t'はシステム上の最小のアドレス指定可能なバイト単位と同じ型である必要はないということを付け加えます。これは' unsigned char'ですが、たいていの場合はおそらくtypedefです。 –

+0

@underscore_d私は正式なUBだとは思わない、構造体は標準レイアウトになっているので、移植性と動作するcharのサイズに関する制約が与えられているはずです。 –

+0

スタンダードでは、同じレイアウトを持つ任意のオブジェクトではなく、関連タイプを持つオブジェクト間でのキャストのみが許可されます。後者を含む他のものは、キャスティングルールと厳密なエイリアシングに違反します。確かに、それは足であなたを撃つために長さに行かないコンパイラではおそらく動作するでしょうが、それはまったく動作する必要はなく、いつでも失敗する可能性のある脆いコードの兆候です。 –

関連する問題