固定小数点数学属性の設定
この例では、MATLAB® コードで固定小数点数学属性を設定する方法を説明します。
fimath
オブジェクトを使用して、代入、加算、減算、乗算の固定小数点数学属性を制御します。関数setfimath
を使用して、fimath
オブジェクトをfi
オブジェクトに付加します。関数removefimath
を使用して、fimath
オブジェクトを fi
オブジェクトから削除します。
MATLAB Coder™ ソフトウェアを使用して、以下の例から C コードを生成できます。
固定小数点数学属性の設定と削除
関数 user_written_sum
は、関数 setfimath
および関数 removefimath
を使用して固定小数点演算がグローバルおよびローカル fimath
設定の影響を受けないようにする方法の例を示しています。出力変数に fimath
が付加されていない関数から返すこともできます。これにより、他の関数の設定に影響を与えずに、固定小数点の数学設定をローカル制御できるようになります。
function y = user_written_sum(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB',... 'SumWordLength',32); u = setfimath(u,F); y = fi(0,true,32,get(u,'FractionLength'),F); % Algorithm for i=1:length(u) y(:) = y + u(i); end % Cleanup y = removefimath(y); end
fimath
は関数内の演算を制御しますが、戻り値には fimath
が付加されません。これは、関数 user_written_sum
内で setfimath
と removefimath
を使用するためです。
u = fi(1:10,true,16,11); y = user_written_sum(u)
y = 55 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 11
C コードの生成
MATLAB Coder ライセンスがある場合は、次のコマンドを実行して C コードを生成できます。
u = fi(1:10,true,16,11); codegen user_written_sum -args {u} -config:lib -launchreport
関数 fimath
、setfimath
および removefimath
は固定小数点演算を制御しますが、変数に格納されている元のデータは変わらないため、生成 C コードではデータのコピーが生成されません。
int user_written_sum(const short u[10]) { int i; int y; y = 0; /* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; } /* Cleanup */ return y; }
fimath
の不一致
複数の fi
オブジェクトに対して演算を行う場合、これらの fimath
プロパティは等しくなければなりません。そうでないとエラーが発生します。
A = fi(pi,'ProductMode','KeepLSB'); B = fi(2,'ProductMode','SpecifyPrecision'); try C = A*B catch me disp(me.message) end
The embedded.fimath of both operands must be equal.
このエラーが発生しないようにするには、fimath
を式の変数のいずれかで削除します。次の例では、fimath
が B
自体を変更せずに式のコンテキストで B
から削除されています。A
に付加されている fimath
を使って積が計算されています。
C = A * removefimath(B)
C = 6.2832 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 26 RoundingMethod: Nearest OverflowAction: Saturate ProductMode: KeepLSB ProductWordLength: 32 SumMode: FullPrecision
一時変数での fimath
の変更
fimath
が付加されていない変数があり、特定の演算を制御する場合、変数を変更せずに式のコンテキストで fimath
を付加することができます。
たとえば、F
で定義された fimath
を使用して積を計算します。
F = fimath('ProductMode','KeepLSB',... 'OverflowAction','Wrap',... 'RoundingMethod','Floor'); A = fi(pi); B = fi(2); C = A * setfimath(B,F)
C = 6.2832 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 26 RoundingMethod: Floor OverflowAction: Wrap ProductMode: KeepLSB ProductWordLength: 32 SumMode: FullPrecision
変数 B
は変更されていません。
B
B = 2 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13
ループで競合する fimath
の削除
負方向の丸めとオーバーフローのラップのある DSP アキュムレータに一致するように積と和を計算し、最も近い正の整数方向への丸めと飽和オーバーフローを出力で使用することができます。fimath
の不一致エラーの発生を回避するには、他の変数と計算する場合に fimath
を出力変数から削除します。
関数 setfimath_removefimath_in_a_loop
では、積は 32 ビット、アキュムレータは 40 ビットであり、C のネイティブな整数ルールと同様に、最下位のビットに負方向への丸めとオーバーフローのラップが維持されています。出力は、最も近い正の整数方向への丸めと飽和オーバーフローを使用します。
function [y,z] = setfimath_removefimath_in_a_loop(b,a,x,zi) % Setup F_floor = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'ProductMode','KeepLSB',... 'ProductWordLength',32,... 'SumMode','KeepLSB',... 'SumWordLength',40); F_nearest = fimath('RoundingMethod','Nearest',... 'OverflowAction','Wrap'); % Set fimaths that are local to this function b = setfimath(b,F_floor); a = setfimath(a,F_floor); x = setfimath(x,F_floor); z = setfimath(zi,F_floor); % Create y with nearest rounding y = setfimath(zeros(size(x),'like',zi),F_nearest); % Algorithm for j=1:length(x) % Nearest assignment into y y(j) = b(1)*x(j) + z(1); % Remove y's fimath conflict with other fimaths z(1) = (b(2)*x(j) + z(2)) - a(2) * removefimath(y(j)); z(2) = b(3)*x(j) - a(3) * removefimath(y(j)); end % Cleanup: Remove fimath from outputs y = removefimath(y); z = removefimath(z); end
C コードの生成
MATLAB Coder ライセンスがある場合は、次のコマンドを実行して、指定のハードウェアの特性を使用して C コードを生成できます。
N = 256; t = 1:N; xstep = [ones(N/2,1);-ones(N/2,1)]; num = [0.0299545822080925 0.0599091644161849 0.0299545822080925]; den = [1 -1.4542435862515900 0.5740619150839550];
b = fi(num,true,16); a = fi(den,true,16); x = fi(xstep,true,16,15); zi = fi(zeros(2,1),true,16,14);
B = coder.Constant(b); A = coder.Constant(a);
config_obj = coder.config('lib'); config_obj.GenerateReport = true; config_obj.LaunchReport = true; config_obj.TargetLang = 'C'; config_obj.DataTypeReplacement = 'CoderTypedefs'; config_obj.GenerateComments = true; config_obj.GenCodeOnly = true; config_obj.HardwareImplementation.ProdBitPerChar=8; config_obj.HardwareImplementation.ProdBitPerShort=16; config_obj.HardwareImplementation.ProdBitPerInt=32; config_obj.HardwareImplementation.ProdBitPerLong=40;
codegen -config config_obj setfimath_removefimath_in_a_loop -args {B,A,x,zi}
関数 fimath
、setfimath
および removefimath
は固定小数点演算を制御しますが、変数に格納されている元のデータは変わらないため、生成 C コードではデータのコピーが生成されません。
void setfimath_removefimath_in_a_loop(const int16_T x[256], const int16_T zi[2], int16_T y[256], int16_T z[2]) { int32_T j; int16_T i; int16_T i1; /* Set fimaths that are local to this function */ /* Create y with nearest rounding */ /* Algorithm */ i = zi[0]; i1 = zi[1]; for (j = 0; j < 256; j++) { int64_T i3; int32_T y_tmp; int16_T i2; int16_T i4; /* Nearest assignment into y */ i2 = x[j]; y_tmp = 15705 * i2; i3 = y_tmp + ((int64_T)i << 20); i4 = (int16_T)((i3 >> 20) + ((i3 & 524288L) != 0L)); y[j] = i4; /* Remove y's fimath conflict with other fimaths */ i = (int16_T)(((31410 * i2 + ((int64_T)i1 << 20)) - ((int64_T)(-23826 * i4) << 6)) >> 20); i1 = (int16_T)((y_tmp - ((int64_T)(9405 * i4) << 6)) >> 20); } z[1] = i1; z[0] = i; /* Cleanup: Remove fimath from outputs */ }
ポリモーフィック コード
関数 setfimath
と関数 removefimath
を使って、浮動小数点と固定小数点の両方の型で使用できる MATLAB コードを記述できます。
function y = user_written_function(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB',... 'SumWordLength',32); u = setfimath(u,F); % Algorithm y = u + u; % Cleanup y = removefimath(y); end
固定小数点入力
関数が固定小数点入力で呼び出されて fimath
F
が演算に使用される場合、出力には fimath
が付加されません。
u = fi(pi/8,true,16,15,'RoundingMethod','Convergent'); y = user_written_function(u)
y = 0.7854 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 15
MATLAB Coder ライセンスがある場合は、次のコマンドを実行して C コードを生成できます。
u = fi(pi/8,true,16,15,'RoundingMethod','Convergent'); codegen user_written_function -args {u} -config:lib -launchreport
関数 fimath
、setfimath
および removefimath
は固定小数点演算を制御しますが、変数に格納されている元のデータは変わらないため、生成 C コードではデータのコピーが生成されません。
int user_written_function(short u) { /* Algorithm */ return u + u; /* Cleanup */ }
浮動小数点 double 入力
関数 setfimath
と関数 removefimath
は浮動小数点型にはパススルーであるため、user_written_function
の例は浮動小数点型で機能します。
u = double(pi/8); codegen user_written_function -args {0} -config:lib -launchreport
浮動小数点入力でコンパイルするとき、次の C コードが生成されます。
double user_written_function(double u) { /* Algorithm */ return u + u; /* Cleanup */ }
ポリモーフィック コードの詳細
関数 user_written_sum_polymorphic
は、出力が入力と同じ型で作成されるように記述されています。関数 user_written_sum_polymorphic
では浮動小数点と固定小数点の両方の入力を使用できます。
function y = user_written_sum_polymorphic(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB',... 'SumWordLength',32); u = setfimath(u,F); if isfi(u) y = fi(0,true,32,get(u,'FractionLength'),F); else y = zeros(1,1,class(u)); end % Algorithm for i=1:length(u) y(:) = y + u(i); end % Cleanup y = removefimath(y); end
固定小数点 C コードの生成
MATLAB Coder ライセンスがある場合は、次のコマンドを実行して C コードを生成できます。
u = fi(1:10,true,16,11); codegen user_written_sum_polymorphic -args {u} -config:lib -launchreport
関数 fimath
、setfimath
および removefimath
は固定小数点演算を制御しますが、変数に格納されている元のデータは変わらないため、生成 C コードではデータのコピーが生成されません。
int user_written_sum_polymorphic(const short u[10]) { int i; int y; y = 0; /* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; } /* Cleanup */ return y; }
浮動小数点 C コードの生成
MATLAB Coder ライセンスがある場合は、次のコマンドを実行して C コードを生成できます。
u = 1:10; codegen user_written_sum_polymorphic -args {u} -config:lib -launchreport
double user_written_sum_polymorphic(const double u[10]) { double y; int i; y = 0.0; /* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; } /* Cleanup */ return y; }
整数型の setfimath
fi
オブジェクトのような組み込み整数の確立した処理パターンに従って、setfimath
は fimath
が付加された同等の fi
に整数入力を変換します。
function y = user_written_u_plus_u(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB',... 'SumWordLength',32); u = setfimath(u,F); % Algorithm y = u + u; % Cleanup y = removefimath(y); end
MATLAB Coder ライセンスがある場合は、次のコマンドを実行して C コードを生成できます。
u = int8(5); codegen user_written_u_plus_u -args {u} -config:lib -launchreport
出力型は、fimath
で 32 ビットと指定されています。
int user_written_u_plus_u(signed char u) { /* Algorithm */ return u + u; /* Cleanup */ }
エディターの警告を無効にします。
%#ok<*NASGU>
参考
fi
| fimath
| setfimath
| removefimath