Вы не можете присвоить матрицы переменного размера матрицам фиксированного размера в сгенерированном коде. Рассмотрите этот пример:
function Y = example_mismatch1(n) %#codegen assert(n < 10); B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B; end Y = A;
Компиляция этой функции производит эту ошибку:
??? Dimension 1 is fixed on the left-hand side but varies on the right ...
Существует несколько способов зафиксировать эту ошибку:
Позвольте матричный A
вырасти путем добавления coder.varsize
построение:
function Y = example_mismatch1_fix1(n) %#codegen coder.varsize('A'); assert(n < 10); B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B; end Y = A;
Явным образом ограничьте размер матричного B
к 3х3 путем изменения assert
оператор:
function Y = example_mismatch1_fix2(n) %#codegen coder.varsize('A'); assert(n == 3) B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B; end Y = A;
Используйте явную индексацию, чтобы сделать B
тот же размер как A
:
function Y = example_mismatch1_fix3(n) %#codegen assert(n < 10); B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B(1:3, 1:3); end Y = A;
Если вы присваиваете пустой матричный []
к данным переменного размера, MATLAB® может тихо изменить данные в сгенерированном коде, чтобы совпадать с a coder.varsize
спецификация. Например:
function Y = test(u) %#codegen Y = []; coder.varsize('Y', [1 10]); if u < 0 Y = [Y u]; end
В этом примере, coder.varsize
задает Y
как вектор-столбец до 10 элементов, таким образом, его первая размерность фиксируется в размере 1. Оператор Y = []
определяет первую размерность Y
как 0, создавая несоответствие. Правая сторона присвоения является пустой матрицей, и левая сторона является вектором переменного размера. В этом случае MATLAB изменяет пустой матричный Y = []
в сгенерированном коде к Y = zeros(1,0)
таким образом, это совпадает с coder.varsize
спецификация.
Если вы присваиваете неявно расширенный выход бинарной операции или функции к переменной различного размера, генератор кода может произвести ошибку. Например:
function out = test(n) %#codegen x = ones(n,1); if mod(n,2) == 1 y = ones(n,n); x = y + x; end out = out + x(2); end
В этом примере, x
неограниченный вектор. Из-за неявного расширения, плюс операция на x
и y
результаты в неограниченной матрице (Inf-by-Inf). Присвоение неограниченной матрицы к x
, то, которое является неограниченным вектором, приводит к ошибке.
Если вы хотите использовать неявно расширенный выход, присвойте выход новой переменной с тем же размером как выход.
Если вы хотите, чтобы x сохранил свой размер и не применил неявное расширение в сгенерированном коде, использовать coder.sameSizeBinaryOp
(MATLAB Coder), чтобы применить операцию. Можно также вызвать coder.noImplicitExpansionInFunction
(MATLAB Coder) в вашем теле функции, чтобы отключить неявное расширение в коде, сгенерированном для этой функции.
Неявное расширение автоматически расширяет операнды, чтобы применить бинарные операции на массивы совместимых размеров. Смотрите Генерируют Код С Неявным расширением, Enabled (MATLAB Coder), Оптимизируют Неявное расширение в Сгенерированном коде (MATLAB Coder) и Совместимые Размеры Массивов для Основных Операций.
Можно задать данные переменного размера путем присвоения переменной матрице с непостоянными размерностями. Например:
function y = dims_vary(u) %#codegen if (u > 0) y = ones(3,u); else y = zeros(3,1); end
Однако компиляция этой функции генерирует ошибку, потому что вы не задавали верхнюю границу для u
.
Существует несколько способов решить проблему:
Включите динамическое выделение памяти и перекомпилируйте. Во время генерации кода MATLAB не проверяет на верхние границы, когда это использует динамическое выделение памяти для данных переменного размера.
Если вы не хотите использовать динамическое выделение памяти, добавьте assert
оператор перед первым использованием u
:
function y = dims_vary_fix(u) %#codegen assert (u < 20); if (u > 0) y = ones(3,u); else y = zeros(3,1); end