fimath の ProductMode と SumMode
例の設定
このトピックの節の例では、ProductMode
プロパティと SumMode
プロパティの以下の 4 つの設定の差異を示します。
FullPrecision
KeepLSB
KeepMSB
SpecifyPrecision
最初に以下の基本設定を行い、順に進めてください。
p = fipref; p.NumericTypeDisplay = 'short'; p.FimathDisplay = 'none'; p.LoggingMode = 'on'; F = fimath('OverflowAction','Wrap','RoundingMethod','Floor',... 'CastBeforeSum',false); warning off format compact
次に、fi
オブジェクト a
と b
を定義します。両者のデータ型は符号付き 8 ビットです。各 fi
オブジェクトに対して小数部の長さが自動的に選択され、可能な最大精度に設定されます。
a = fi(pi, true, 8)
a = 3.1562 numerictype(1,8,5)
b = fi(exp(1), true, 8)
b = 2.7188 numerictype(1,8,5)
FullPrecision
a
と b
に対する ProductMode
と SumMode
を FullPrecision
に設定し、いくつか結果を調べてみましょう。
F.ProductMode = 'FullPrecision'; F.SumMode = 'FullPrecision'; a.fimath = F; b.fimath = F; a
a = 3.1562 numerictype(1,8,5)
b
b = 2.7188 numerictype(1,8,5)
a*b
ans = 8.5811 numerictype(1,16,10)
a+b
ans = 5.8750 numerictype(1,9,5)
FullPrecision
モードでは、乗算の語長はオペランドの語長の和に等しくなります。この場合、各オペランドは 8 ビットのため乗算の語長は 16 ビットになります。乗算の小数部の長さはオペランドの小数部の長さの和になり、この場合、5 + 5 = 10 ビットです。
加算の語長は一方の最上位ビットまで拡大され、起こりうるキャリー ビットに対応します。加算の小数部の長さはオペランドの小数部の長さと同じで、小数部のビットはすべて完全精度に維持されます。この場合、両方のオペランドの小数部は 5 ビットのため、加算の小数部も 5 ビットになります。
KeepLSB
a
と b
に対する ProductMode
と SumMode
を KeepLSB
に設定し、いくつか結果を調べてみましょう。
F.ProductMode = 'KeepLSB'; F.ProductWordLength = 12; F.SumMode = 'KeepLSB'; F.SumWordLength = 12; a.fimath = F; b.fimath = F; a
a = 3.1562 numerictype(1,8,5)
b
b = 2.7188 numerictype(1,8,5)
a*b
ans = 0.5811 numerictype(1,12,10)
a+b
ans = 5.8750 numerictype(1,12,5)
KeepLSB
モードでは、語長を指定し、結果の最下位ビットが自動的に維持されます。このモードは C 言語の整数演算の動作をモデル化します。
乗算の小数部の長さはオペランドの小数部の長さの和になります。この場合、各オペランドの小数部は 5
ビットのため乗算の小数部の長さは 10
ビットになります。このモードでは小数部 10 ビットのすべてが維持されます。完全精度の結果には 6
整数ビットが必要で、積には 2
整数ビットしかないため、オーバーフローが発生します。
加算の小数部の長さはオペランドの小数部の長さと同じで、このモデルでは、最下位ビットがすべて維持されます。この場合、両方のオペランドの小数部は 5
ビットのため、加算の小数部も 5
ビットになります。完全精度の結果には 4
整数ビットが必要で、和には 7
整数ビットあるため、和でオーバーフローは発生しません。
KeepMSB
a
と b
に対する ProductMode
と SumMode
を KeepMSB
に設定し、いくつか結果を調べてみましょう。
F.ProductMode = 'KeepMSB'; F.ProductWordLength = 12; F.SumMode = 'KeepMSB'; F.SumWordLength = 12; a.fimath = F; b.fimath = F; a
a = 3.1562 numerictype(1,8,5)
b
b = 2.7188 numerictype(1,8,5)
a*b
ans = 8.5781 numerictype(1,12,6)
a+b
ans = 5.8750 numerictype(1,12,8)
KeepMSB
モードでは、語長を指定し、和と乗算の結果の最上位ビットが自動的に維持されます。このモードは多くの DSP デバイスの動作をモデル化するもので、積と和は double 幅レジスタに保持され、プログラマは演算ごとにレジスタからメモリに最上位ビットを転送するよう選択します。
完全精度の積には 6
整数ビットが必要で、このモードでは、乗算の小数部の長さはすべての 6
整数ビットに対応するように調整されます。オーバーフローは発生しません。しかし、完全精度の乗算の小数部には 10
ビット必要ですが、6
ビットしか使用できません。したがって、精度が低下します。
完全精度の和には 4
整数ビットが必要で、このモードでは、加算の小数部の長さはすべての 4
整数ビットに対応するように調整されます。完全精度の加算の小数部に必要なビット数は 5
ビットで、この場合は 8
ビットあるため、精度の低下は起こりません。
この例では、オーバーフローの発生の有無にかかわらず、KeepMSB
モードでは小数部の長さが変化することを説明します。小数部の長さは、両方の項が最大値を使用する場合を考慮して、積を表現するのに必要な長さに設定されます (この例では 18+18-16=20)。
F = fimath('SumMode','KeepMSB','ProductMode','KeepMSB',... 'ProductWordLength',16,'SumWordLength',16); a = fi(100,1,16,-2,'fimath',F); a*a
ans = 0 numerictype(1,16,-20)
SpecifyPrecision
a
と b
に対する ProductMode
と SumMode
を SpecifyPrecision
に設定し、いくつか結果を調べてみましょう。
F.ProductMode = 'SpecifyPrecision'; F.ProductWordLength = 8; F.ProductFractionLength = 7; F.SumMode = 'SpecifyPrecision'; F.SumWordLength = 8; F.SumFractionLength = 7; a.fimath = F; b.fimath = F; a
a = 3.1562 numerictype(1,8,5)
b
b = 2.7188 numerictype(1,8,5)
a*b
ans = 0.5781 numerictype(1,8,7)
a+b
ans = -0.1250 numerictype(1,8,7)
SpecifyPrecision
モードでは、和と積に対する語長と小数部の長さの両方を指定しなければなりません。これは積と加算の小数部の形式の不適切な使用例で、語長に 8
ビット、小数部の長さに 7
ビットを使用しています。
完全精度の積には 6
整数ビットが必要ですが、この例では 1
ビットしか指定していないため、積はオーバーフローします。完全精度の乗算の小数部には 10
ビットが必要ですが、この例では 7
ビットしか指定していないため、乗算で桁落ちが発生します。
完全精度の和には 4
整数ビットが必要ですが、この例では 1
ビットしか指定していないため、和はオーバーフローします。完全精度の加算の小数部には 5
ビットが必要ですが、この例では 7
ビットを指定しているため、加算の精度は低下しません。
fimath
オブジェクトとそのプロパティについての詳細は、fimath オブジェクト プロパティを参照してください。