0

-1、1、1.31 の形式の fract32 を持つ blackfin533 のコードを見つけました。

複素数 (re、img) の振幅を計算するためにプリシフトが必要な理由がわかりません。1.31 を 1.31 の小数形式で乗算する場合は、右に 31 ビットシフトする必要があることを知っています。

GO_coil_D[0].reGO_coil_D[0].imは 2 つのfract32です。

次のコードが何をしているのかわかりません:

 norm[0] = norm_fr1x32(GO_coil_D[0].re);
 norm[1] = norm_fr1x32(GO_coil_D[0].im);
 shift = (norm[0] < norm[1]) ? (norm[0] - 1) : (norm[1] - 1);
 vectorFundamentalStored.im = shl_fr1x32(GO_coil_D[0].im,shift);     
 vectorFundamentalStored.re = shl_fr1x32(GO_coil_D[0].re,shift);
 vectorFundamentalStored.im = mult_fr1x32x32(vectorFundamentalStored.im, vectorFundamentalStored.im);
 vectorFundamentalStored.re = mult_fr1x32x32(vectorFundamentalStored.re, vectorFundamentalStored.re);  
 amplitudeFundamentalStored = sqrt_fr16(round_fr1x32(add_fr1x32(vectorFundamentalStored.re,vectorFundamentalStored.im))) << 16;
 amplitudeFundamentalStored = shr_fr1x32(amplitudeFundamentalStored,shift);

round_fr1x32` (fract32 f1) fract16 バイアス丸めを使用して、32 ビットの端数を 16 ビットの端数に丸めます。

norm_fr1x32 norm_fr1x32 (fract32) int 入力変数が 0x40000000 から 0x7ffffffff の間隔、または 0x80000000 から 0xc0000000 の間隔になるように正規化するために必要な左シフトの数を返します。つまり、fract32 x; shl_fr1x32(x,norm_fr1x32(x)); 0x40000000 から 0x7ffffffff の範囲、または 0x80000000 から 0xc0000000 の範囲の値を返します

4

1 に答える 1

1

1) 小数部分の最上位nビットがすべて「0」ビットで、その後に「1」ビットが続く場合、nは値nの浮動小数点バイナリ指数のように動作し、残りの 31- nビットは仮数のように振る舞います。数値を 2 乗すると、先頭の「0」ビットの数が 2* nに倍増し、仮数のサイズが 31-2* nビットに縮小されます。これにより、二乗演算の結果の精度が失われる可能性があります。

2) round_fr1x321.31 の分数を 1.15 の分数に変換し、最大 16 ビットの精度が失われます。

うまくいけば、ステップ 1 と 2 によって数値の精度が大幅に低下することがわかります。数値を事前にスケーリングすると、先頭の「0」ビットnの数が可能な限り減少するため、ステップ 1 で失われる精度が少なくなります。 ' ビットnはゼロになるため、その数値を 2 乗しても、他の数値に加算される前に最大 31 ビットの精度が残ります。(ステップ 2 では、その精度を 15 ビットに減らします。)

最後に、2 つの 1.31 分数形式の数値を乗算した結果について、あなたは間違っています。結果は 62 ビットではなく、31 ビットだけ右にシフトする必要があります。

作業例:

10進数で実数部が3/1024、虚数部が4/1024だとすると、絶対値はピタゴラスで5/1024になるはずです。

プリスケーリングなしでは、バイナリ分数は re=0.0000000011₂、im=0.0000000100₂ です。それらを 2 乗すると、re²=0.00000000000000001001₂、im²=0.00000000000000010000₂ となります。2 乗を加算すると、abs²=0.00000000000000011001₂ が得られます。小数部の 15 ビットに丸めると、abs²=0.000000000000001₂ になります。平方根を取ると abs=0.000000010110101₂ となります。これは、正確な結果 0.0000000101₂ とは 0.000000000010101₂ 異なります。

プリスケーリングすると、両方の分数が 6 ビット左にシフトされ、sre=0.0011₂、sim=0.0100₂ になります (接頭辞 's' は、'スケーリングされた' という意味です)。それらを 2 乗すると、sre²=0.00001001₂、sim²=0.00010000₂ となります。正方形を追加すると、sabs²=0.00011001₂ が得られます。小数部を 15 ビットに丸めても、値は変わりません。平方根を取ると、sabs=0.01010000₂ が得られます。それを 1.31 形式に変換し、6 ビット右にシフトすると、abs=0.0000000101₂ が得られます。これは正確に正しい (10 進数で 5/1024)。

于 2016-10-03T16:32:58.777 に答える