Скалярное расширение является методом преобразования скалярных данных, чтобы совпадать с размерностями векторных или матричных данных. Если один операнд является скаляром, и другой не, скалярное расширение применяет скаляр к каждому элементу другого операнда.
Во время генерации кода скалярные правила расширения применяются кроме тех случаев, когда, работая с двумя выражениями переменного размера. В этом случае оба операнда должны быть одного размера. Сгенерированный код не выполняет скалярное расширение, даже если одно из выражений переменного размера оказывается скаляром во время выполнения. Поэтому, когда проверки ошибки времени выполнения включены, ошибка времени выполнения может произойти.
Рассмотрите эту функцию:
function y = scalar_exp_test_err1(u) %#codegen y = ones(3); switch u case 0 z = 0; case 1 z = 1; otherwise z = zeros(3); end y(:) = z;
Когда вы генерируете код для этой функции, генератор кода решает, что z
является переменным размером с верхней границей 3
.
Если при запуске MEX-функцию с u
, равным 0 или 1, сгенерированный код не выполняет скалярное расширение, даже при том, что z
является скаляром во время выполнения. Поэтому, когда проверки ошибки времени выполнения включены, ошибка времени выполнения может произойти.
scalar_exp_test_err1_mex(0) Subscripted assignment dimension mismatch: [9] ~= [1]. Error in scalar_exp_test_err1 (line 11) y(:) = z;
Чтобы избежать этой проблемы, используйте индексацию, чтобы обеспечить z
, чтобы быть скалярным значением.
function y = scalar_exp_test_err1(u) %#codegen y = ones(3); switch u case 0 z = 0; case 1 z = 1; otherwise z = zeros(3); end y(:) = z(1);
Для переменного размера массивы N-D функция size
может возвратить различный результат в сгенерированном коде, чем в MATLAB®. В сгенерированном коде size(A)
возвращает фиксированную длину вывод, потому что это не пропускает запаздывание одноэлементных размерностей переменного размера массивы N-D. В отличие от этого, size(A)
в MATLAB возвращает переменную длину вывод, потому что это пропускает запаздывание одноэлементных размерностей.
Например, если форма массива, A
является :?x:?x:?
и size(A,3)==1
, size(A)
, возвращается:
Трехэлементный вектор в сгенерированном коде
Двухэлементный вектор в коде MATLAB
Если ваше приложение требует, чтобы сгенерированный код возвратил тот же размер переменного размера массивы N-D как код MATLAB, рассмотрите одно из этих обходных решений:
Используйте форму двух-аргумента size
.
Например, size(A,n)
дает тот же ответ в сгенерированном коде и код MATLAB.
Перезапись size(A)
:
B = size(A); X = B(1:ndims(A));
Эта версия возвращает X
с переменной длиной вывод. Однако вы не можете передать переменный размер X
матричным конструкторам, таким как zeros
, которые требуют аргумента фиксированного размера.
Размер пустого массива в сгенерированном коде может отличаться от его размера в исходном коде MATLAB. Размером может быть 1x0
или 0x1
в сгенерированном коде, но 0x0
в MATLAB. Поэтому вы не должны писать код, который полагается на определенный размер пустых матриц.
Например, рассмотрите следующий код:
function y = foo(n) %#codegen x = []; i = 0; while (i < 10) x = [5 x]; i = i + 1; end if n > 0 x = []; end y = size(x); end
Конкатенация требует, чтобы ее операнды соответствовали на размере размерности, которая не конкатенируется. В предыдущей конкатенации скалярное значение имеет размер, 1x1
и x
имеют размер 0x0
. Чтобы поддержать этот вариант использования, генератор кода определяет размер для x
как [1 x :?]
. Поскольку существует другое присвоение x = []
после конкатенации, размером x
в сгенерированном коде является 1x0
вместо 0x0
.
Для несовместимостей с MATLAB в определении размера пустого массива, который следует из удаления элементов массива, смотрите Размер Пустого массива Который Результаты Удаления Элементов Массива.
Если ваше приложение проверяет, пуста ли матрица, используйте одно из этих обходных решений:
Перепишите свой код, чтобы использовать функцию isempty
вместо функции size
.
Вместо того, чтобы использовать x=[]
, чтобы создать пустые массивы, создайте пустые массивы определенного размера с помощью zeros
. Например:
function y = test_empty(n) %#codegen x = zeros(1,0); i=0; while (i < 10) x = [5 x]; i = i + 1; end if n > 0 x = zeros(1,0); end y=size(x); end
Класс пустого массива в сгенерированном коде может отличаться от его класса в исходном коде MATLAB. Поэтому не пишите код, который полагается на класс пустых матриц.
Например, рассмотрите следующий код:
function y = fun(n) x = []; if n > 1 x = ['a' x]; end y=class(x); end
fun(0)
возвращает double
в MATLAB, но char
в сгенерированном коде. Когда оператор n > 1
является ложным, MATLAB не выполняет x = ['a' x]
. Классом x
является double
, класс пустого массива. Однако генератор кода рассматривает все пути к выполнению. Это решает, что на основе оператора x = ['a' x]
, классом x
является char
.Вместо того, чтобы использовать x=[]
, чтобы создать пустой массив, создайте пустой массив определенного класса. Например, используйте blanks(0)
, чтобы создать пустой массив символов.
function y = fun(n) x = blanks(0); if n > 1 x = ['a' x]; end y=class(x); end
В матричном индексировании матриц вы используете одну матрицу, чтобы индексировать в другую матрицу. В MATLAB общее правило для матричного индексирования матриц состоит в том, что размер и ориентация результата совпадают с размером и ориентацией индексной матрицы. Например, если A
и B
являются матрицами, size(A(B))
равняется size(B)
. Когда A
и B
являются векторами, MATLAB применяет специальное правило. Специальное правило индексации векторного вектора состоит в том, что ориентация результата является ориентацией матрицы данных. Например, iA
1 на 5, и B
3 на 1, затем A(B)
1 3.
Генератор кода применяет те же правила матричного индексирования матриц как MATLAB. Если A
и B
являются матрицами переменного размера, чтобы применить правила матричного индексирования матриц, генератор кода принимает, что size(A(B))
равняется size(B)
. Если во время выполнения A
и B
становятся векторами и имеют различные ориентации, то предположение является неправильным. Поэтому, когда проверки ошибки времени выполнения включены, ошибка может произойти.
Чтобы избежать этой проблемы, обеспечьте свои данные, чтобы быть вектором при помощи оператора двоеточия для индексации. Например, предположите, что ваш код намеренно переключается между векторами и обычными матрицами во время выполнения. Можно сделать явную проверку на векторно-векторную индексацию.
... if isvector(A) && isvector(B) C = A(:); D = C(B(:)); else D = A(B); end ...
Индексация в первом ответвлении указывает, что C
и B(:)
являются векторами времени компиляции. Поэтому генератор кода применяет правило индексации для индексации одного вектора с другим вектором. Ориентация результата является ориентацией вектора данных, C
.
В MATLAB специальное правило для векторно-векторной индексации состоит в том, что ориентация результата является ориентацией вектора данных. Например, если A
1 на 5, и B
3 на 1, то A(B)
1 3. Если, однако, вектор данных A
является скаляром, то ориентация A(B)
является ориентацией индексного вектора B
.
Генератор кода применяет те же правила индексации векторного вектора как MATLAB. Если A
и B
являются векторами переменного размера, чтобы применить правила индексации, генератор кода принимает, что ориентация B
совпадает с ориентацией A
. Во время выполнения, если A
является скаляром и ориентацией A
и B
, не соответствуют, то предположение является неправильным. Поэтому, когда проверки ошибки времени выполнения включены, ошибка времени выполнения может произойти.
Чтобы избежать этой проблемы, сделайте ориентации соответствия векторов. Также индексируйте единственные элементы путем определения строки и столбца. Например, A(row, column)
.
Следующее ограничение применяется к операциям индексирования матриц за генерацию кода:
Инициализация следующего стиля:
for i = 1:10 M(i) = 5; end
В этом случае размер изменений M
как цикл выполняется. Генерация кода не поддерживает увеличение размера массива в зависимости от времени.
Для генерации кода предварительно выделите M
.
M = zeros(1,10); for i = 1:10 M(i) = 5; end
Следующее ограничение применяется к операциям индексирования матриц за генерацию кода, когда динамическое выделение памяти отключено:
M(i:j)
, где i
и j
изменяются в цикле
Во время генерации кода память динамически не выделяется для размера выражений, которые изменяются, когда программа выполняется. Чтобы реализовать это поведение, используйте циклы for-
как показано:
... M = ones(10,10); for i=1:10 for j = i:10 M(i,j) = 2*M(i,j); end end ...
Матричный M
должен быть задан прежде, чем ввести цикл.
Для генерации кода, когда вы конкатенируете массивы переменного размера, размерности, которые не конкатенируются, должны соответствовать точно.
Предположим что:
c
является массивом ячеек переменного размера.
Вы получаете доступ к содержимому c
при помощи фигурных скобок. Например, c{2:4}
.
Вы включаете результаты в конкатенацию. Например, [a c{2:4} b]
.
c{I}
не возвращает элементов. Или c
пуст или индексация в фигурных скобках, приводит к пустому результату.
Для этих условий MATLAB не использует c{I}
от конкатенации. Например, [a c{I} b]
становится [a b]
. Генератор кода обрабатывает c{I}
как пустой массив [c{I}]
. Конкатенация становится [...[c{i}]...]
. Эта конкатенация затем не использует массив [c{I}]
. Так, чтобы свойства [c{I}]
были совместимы с конкатенацией [...[c{i}]...]
, генератор кода присваивает класс, размер и сложность [c{I}]
согласно этим правилам:
Класс и сложность совпадают с базовым типом массива ячеек.
Размер второго измерения всегда 0.
Для остальной части размерностей размер Ni
зависит от того, фиксируется ли соответствующая размерность в базовом типе или переменный размер.
Если соответствующая размерность в базовом типе является переменным размером, размерность имеет размер 0 в результате.
Если соответствующая размерность в базовом типе является фиксированным размером, размерность имеет тот размер в результате.
Предположим, что c
имеет базовый тип с классом int8
и size:10x7x8x:?
. В сгенерированном коде классом [c{I}]
является int8
. Размером [c{I}]
является 0x0x8x0
. Второе измерение 0. Первые и последние размерности 0, потому что те размерности являются переменным размером в базовом типе. Третья размерность равняется 8, потому что размер третьей размерности базового типа является фиксированным размером 8.
В конкатенации, если индексация курчавой фигурной скобки массива ячеек переменного размера не возвращает элементов, сгенерированный код может иметь следующие различия от MATLAB:
Класс [...c{i}...]
в сгенерированном коде может отличаться от класса в MATLAB.
Когда c{I}
не возвращает элементов, MATLAB удаляет c{I}
из конкатенации. Поэтому c{I}
не влияет на класс результата. MATLAB определяет класс результата на основе классов остающихся массивов, согласно приоритету классов. Смотрите Допустимые Комбинации в отличие от Классов (MATLAB). В сгенерированном коде класс [c{I}]
влияет на класс результата полной конкатенации [...[c{I}]...]
, потому что генератор кода обрабатывает c{I}
как [c{I}]
. Ранее описанные правила определяют класс [c{I}]
.
В сгенерированном коде размер [c{I}]
может отличаться от размера в MATLAB.
В MATLAB конкатенация [c{I}]
является 0x0 дважды. В сгенерированном коде ранее описанные правила определяют размер [c{I}]
.