Установите математические атрибуты фиксированной точки

Этот пример показывает, как установить математические атрибуты фиксированной точки в коде MATLAB®.

Можно управлять математическими атрибутами фиксированной точки для присвоения, сложения, вычитания и умножения с помощью объекта fimath. Можно присоединить объект fimath к объекту fi с помощью setfimath. Можно удалить объект fimath из объекта fi с помощью removefimath.

Можно сгенерировать код С от примеров, если у вас есть программное обеспечение MATLAB Coder™.

Установите и удалите математические атрибуты фиксированной точки

Можно изолировать операции фиксированной точки от глобальных и локальных настроек fimath при помощи функций removefimath и setfimath. Можно также возвратиться из функций без fimath, присоединенного к выходным переменным. Это дает вам локальный контроль над математическими настройками фиксированной точки, не вмешиваясь в настройки в других функциях.

КОД MATLAB

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 управляет арифметикой в функции, но возвращаемое значение присоединило не fimath. Это происходит из-за использования setfimath и removefimath в функциональном user_written_sum.

>> 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, можно сгенерировать код С с помощью следующих команд.

>> u = fi(1:10,true,16,11);
>> codegen user_written_sum -args {u} -config:lib -launchreport

Функции fimath, setfimath и removefimath управляют математикой фиксированной точки, но базовые данные, содержавшиеся в переменных, не изменяются и так сгенерированный код C, не производят копий данных.

int32_T user_written_sum(const int16_T u[10])
{
  int32_T y;
  int32_T i;
  /* Setup */
  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');
>> C = A * B
Error using embedded.fi/mtimes
The embedded.fimath of both operands must be equal.

Чтобы избежать этой ошибки, можно удалить fimath из одной из переменных в выражении. В этом примере fimath удален из B в контексте выражения, не изменяя сам B, и продукт вычисляется с помощью fimath, присоединенного к A.

>> C = A * removefimath(B)
C =
                6.283203125
           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 в контексте выражения, не изменяя переменные.

Например, продукт вычисляется с fimath, заданным F.

>> 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
       MaxSumWordLength: 128

Обратите внимание на то, что переменная B не изменяется.

>> B
B =
      2
           DataTypeMode: Fixed-point: binary point scaling
             Signedness: Signed
             WordLength: 16
         FractionLength: 13

Удаление конфликта FIMATH в цикле

Можно вычислить продукты и суммы, чтобы совпадать с аккумулятором DSP с округлением пола и перенести переполнение, и использовать самое близкое округление и насыщать переполнение на выводе. Чтобы избежать ошибок fimath, которым не соответствуют, можно удалить fimath на выходной переменной, когда это используется в вычислении с другими переменными.

КОД MATLAB

В этом примере продукты составляют 32 бита, и аккумулятор составляет 40 битов, сохраняя наименьшее-количество-значимые-биты с округлением пола, и перенесите переполнение как нативные целочисленные правила К. Вывод использует самое близкое округление, и насыщайте переполнение.

function [y,z] = setfimath_removefimath_in_a_loop(b,a,x,z)
    % 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(z,F_floor);
    % Create y with nearest rounding
    y = coder.nullcopy(fi(zeros(size(x)),true,16,14,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

Инструкции генерации кода

Если у вас есть программное обеспечение MATLAB Coder, можно сгенерировать код С с заданными характеристиками оборудования с помощью следующих команд.

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.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} -launchreport

Сгенерированный код C

Функции fimath, setfimath и removefimath управляют математикой фиксированной точки, но базовые данные, содержавшиеся в переменных, не изменяются и так сгенерированный код C, не производят копий данных.

void setfimath_removefimath_in_a_loop(const int16_T x[256], int16_T z[2],
  int16_T y[256])
{
  int32_T j;
  int40_T i0;
  int16_T b_y;
  /* Setup */
  /* Set fimaths that are local to this function */
  /* Create y with nearest rounding */
  /* Algorithm */
  for (j = 0; j < 256; j++) {
    /* Nearest assignment into y */
    i0 = 15705 * x[j] + ((int40_T)z[0] << 20);
    b_y = (int16_T)((int32_T)(i0 >> 20) + ((i0 & 524288L) != 0L));
    /* Remove y's fimath conflict with other fimaths */
    z[0] = (int16_T)(((31410 * x[j] + ((int40_T)z[1] << 20)) - ((int40_T)(-23826
      * b_y) << 6)) >> 20);
    z[1] = (int16_T)((15705 * x[j] - ((int40_T)(9405 * b_y) << 6)) >> 20);
    y[j] = b_y;
  }
  /* Cleanup: Remove fimath from outputs */
}

Полиморфный код

Можно записать код MATLAB, который может использоваться и для с плавающей точкой и для фиксированные точки с помощью setfimath и removefimath.

function y = user_written_function(u)
    % Setup
    F = fimath('RoundingMethod','Floor',...
        'OverflowAction','Wrap',...
        'SumMode','KeepLSB');
    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.785400390625
           DataTypeMode: Fixed-point: binary point scaling
             Signedness: Signed
             WordLength: 32
         FractionLength: 15

Сгенерированный код C для фиксированной точки

Если у вас есть программное обеспечение MATLAB Coder, можно сгенерировать код С с помощью следующих команд.

>> u = fi(pi/8,true,16,15,'RoundingMethod','Convergent');
>> codegen user_written_function -args {u} -config:lib -launchreport

Функции fimath, setfimath и removefimath управляют математикой фиксированной точки, но базовые данные, содержавшиеся в переменных, не изменяются и так сгенерированный код C, не производят копий данных.

int32_T user_written_function(int16_T u)
{
  /* Setup */
  /* Algorithm */
  /* Cleanup */
  return u + u;
}

Двойные входные параметры

Поскольку setfimath и removefimath являются передачей для типов с плавающей точкой, пример user_written_function работает с типами с плавающей точкой, также.

function y = user_written_function(u)
    % Setup
    F = fimath('RoundingMethod','Floor',...
        'OverflowAction','Wrap',...
        'SumMode','KeepLSB');
    u = setfimath(u,F);
    % Algorithm
    y = u + u;
    % Cleanup
    y = removefimath(y);
end

Сгенерированный код C для дважды

Когда скомпилировано с входом с плавающей точкой, вы получаете следующий сгенерированный код C.

>> codegen user_written_function -args {0} -config:lib -launchreport
real_T user_written_function(real_T u)
{
  return u + u;
}

Где тип real_T задан как double:

typedef double real_T;

Больше полиморфного кода

Эта функция записана так, чтобы вывод был создан, чтобы быть тем же типом как вход, таким образом, и и фиксированная точка с плавающей точкой может использоваться с ним.

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, можно сгенерировать код С фиксированной точки с помощью следующих команд.

>> u = fi(1:10,true,16,11);
>> codegen user_written_sum_polymorphic -args {u} -config:lib -launchreport

Функции fimath, setfimath и removefimath управляют математикой фиксированной точки, но базовые данные, содержавшиеся в переменных, не изменяются и так сгенерированный код C, не производят копий данных.

int32_T user_written_sum_polymorphic(const int16_T u[10])
{
  int32_T y;
  int32_T i;
  /* Setup */
  y = 0;
  /* Algorithm */
  for (i = 0; i < 10; i++) {
    y += u[i];
  }
  /* Cleanup */
  return y;
}

Сгенерированный код C с плавающей точкой

Если у вас есть программное обеспечение MATLAB Coder, можно сгенерировать код С с плавающей точкой с помощью следующих команд.

>> u = 1:10;
>> codegen user_written_sum_polymorphic -args {u} -config:lib -launchreport
real_T user_written_sum_polymorphic(const real_T u[10])
{
  real_T y;
  int32_T i;
  /* Setup */
  y = 0.0;
  /* Algorithm */
  for (i = 0; i < 10; i++) {
    y += u[i];
  }
  /* Cleanup */
  return y;
}

Где тип real_T задан как double:

typedef double real_T;

SETFIMATH на целочисленных типах

После установленного шаблона обработки встроенных целых чисел как объекты fi setfimath преобразовывает целочисленный вход в эквивалентный fi с присоединенным fimath.

>> u = int8(5);
>> codegen user_written_u_plus_u -args {u} -config:lib -launchreport
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

Выходной тип был задан fimath, чтобы быть 32-битным.

int32_T user_written_u_plus_u(int8_T u)
{
  /* Setup */
  /* Algorithm */
  /* Cleanup */
  return u + u;
}