Для создания кода перед использованием переменных в операциях или возвращением их в качестве выходных данных необходимо назначить им определенный класс, размер и сложность. Как правило, после первоначального присвоения невозможно переназначить свойства переменных. Поэтому после назначения фиксированного размера переменной или структурному полю попытки увеличить переменную или структурное поле могут привести к ошибке компиляции. В этих случаях необходимо явно определить данные как переменные размеры с помощью одного из этих методов.
| Метод | Посмотрите |
|---|---|
Назначьте данные из конструктора матрицы переменного размера, например: | Использование конструктора матрицы с непостоянными размерами |
| Перед использованием (считыванием) переменной назначьте ей несколько постоянных размеров. | Назначение нескольких размеров одной и той же переменной |
| Определите все экземпляры переменной с переменным размером. | Явное определение данных переменного размера с помощью coder.varsize |
Матрицу переменного размера можно определить с помощью конструктора с непостоянными размерами. Например:
function s = var_by_assign(u) %#codegen y = ones(3,u); s = numel(y);
Если динамическое выделение памяти не используется, необходимо также добавить assert для обеспечения верхних границ размеров. Например:
function s = var_by_assign(u) %#codegen assert (u < 20); y = ones(3,u); s = numel(y);
Прежде чем использовать (читать) переменную в коде, можно сделать ее переменной размера, назначив ей несколько постоянных размеров. Когда генератор кода использует статическое распределение в стеке, он выводит верхние границы из наибольшего размера, заданного для каждого измерения. При назначении одного и того же размера заданному измерению во всех назначениях генератор кода предполагает, что измерение фиксировано с таким размером. Назначения могут определять различные формы и размеры.
Когда генератор кода использует динамическое выделение памяти, он не проверяет верхние границы. Предполагается, что данные переменного размера являются неограниченными.
function s = var_by_multiassign(u) %#codegen if (u > 0) y = ones(3,4,5); else y = zeros(3,1); end s = numel(y);
Когда генератор кода использует статическое распределение, он делает вывод, что y является матрицей с тремя измерениями:
Первый размер фиксируется размером 3
Второй размер является переменным с верхней границей 4
Третье измерение является переменным размером с верхней границей 5
Когда генератор кода использует динамическое распределение, он анализирует размеры y по-разному:
Первый размер фиксируется на размере 3.
Второе и третье измерения безграничны.
Для явного определения данных переменного размера используйте функцию coder.varsize. При необходимости можно также указать, какие размеры изменяются вместе с их верхними границами. Например:
Определить B как двумерный массив переменного размера, где каждый размер имеет верхнюю границу 64.
coder.varsize('B', [64 64]);Определить B как массив переменного размера:
coder.varsize('B');При вводе только первого аргумента coder.varsize предполагает, что все измерения B может изменяться, и что верхняя граница size(B).
Можно использовать функцию coder.varsize чтобы указать, какие размеры изменяются. Например, следующий оператор определяет B как массив, первый размер которого зафиксирован в 2, но второй размер которого может увеличиться до размера 16:
coder.varsize('B',[2, 16],[0 1])Третий аргумент указывает, какие размеры различаются. Этот аргумент должен быть логическим вектором или двойным вектором, содержащим только нули и единицы. Размеры, соответствующие нулям или false имеют фиксированный размер. Размеры, соответствующие размерам или true различаются по размеру. coder.varsize Обычно размеры размера 1 рассматриваются как фиксированные. См. раздел Определение матриц переменного размера с одиночными размерами.
Функция var_by_if определяет матрицу Y с фиксированными измерениями 2 на 2 перед первым использованием (где Y = Y + u читает из Y). Однако coder.varsize определяет Y как матрица переменного размера, позволяющая изменять размер на основе логики принятия решений в else пункт:
function Y = var_by_if(u) %#codegen if (u > 0) Y = zeros(2,2); coder.varsize('Y'); if (u < 10) Y = Y + u; end else Y = zeros(5,5); end
Без coder.varsize, генератор кода выводит Y является матрицей фиксированного размера 2 на 2. Это приводит к ошибке несоответствия размеров.
Одиночное измерение - это измерение, для которого size(A,dim) = 1. Размеры одиночки фиксируются по размеру при:
Задается размер с верхней границей 1 в coder.varsize выражения.
Например, в этой функции Y ведет себя как вектор с одним размером переменного размера:
function Y = dim_singleton(u) %#codegen Y = [1 2]; coder.varsize('Y', [1 10]); if (u > 0) Y = [Y 3]; else Y = [Y u]; end
Данные переменного размера инициализируются одиночными измерениями с помощью выражений конструктора матрицы или матричных функций.
Например, в этой функции X и Y вести себя как векторы, где только их вторые размеры являются переменными.
function [X,Y] = dim_singleton_vects(u) %#codegen Y = ones(1,3); X = [1 4]; coder.varsize('Y','X'); if (u > 0) Y = [Y u]; else X = [X u]; end
Это поведение можно переопределить с помощью coder.varsize явным образом указывает, что размеры одиночных элементов различаются. Например:
function Y = dim_singleton_vary(u) %#codegen Y = [1 2]; coder.varsize('Y', [1 10], [1 1]); if (u > 0) Y = [Y Y+u]; else Y = [Y Y*u]; end
В этом примере третий аргумент coder.varsize - вектор единиц, указывающий, что каждая размерность Y изменяется в размерах.
Чтобы определить поля структуры как массивы переменного размера, используйте двоеточие (:) в качестве индексного выражения. Двоеточие (:) указывает, что все элементы массива имеют переменный размер. Например:
function y=struct_example() %#codegen d = struct('values', zeros(1,0), 'color', 0); data = repmat(d, [3 3]); coder.varsize('data(:).values'); for i = 1:numel(data) data(i).color = rand-0.5; data(i).values = 1:i; end y = 0; for i = 1:numel(data) if data(i).color > 0 y = y + sum(data(i).values); end end
Выражение coder.varsize('data(:).values') определяет поле values внутри каждого элемента матрицы data должен быть переменного размера.
Вот другие примеры:
coder.varsize('data.A(:).B')
В этом примере: data - скалярная переменная, содержащая матрицу A. Каждый элемент матрицы A содержит поле переменного размера B.
coder.varsize('data(:).A(:).B')
Это выражение определяет поле B внутри каждого элемента матрицы A внутри каждого элемента матрицы data должен быть переменного размера.