Скалярное расширение является методом преобразования скалярных данных, чтобы совпадать с размерностями векторных или матричных данных. Если один операнд является скаляром, и другой не, скалярное расширение применяет скаляр к каждому элементу другого операнда.
Во время генерации кода скалярные правила расширения применяются кроме тех случаев, когда, работая с двумя выражениями переменного размера. В этом случае оба операнда должны быть одного размера. Сгенерированный код не выполняет скалярное расширение, даже если одно из выражений переменного размера оказывается скаляром во время выполнения. Поэтому, когда проверки ошибки времени выполнения включены, ошибка времени выполнения может произойти.
Рассмотрите эту функцию:
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
sizeA
возвращается:
Трехэлементный вектор в сгенерированном коде
Двухэлементный вектор в коде MATLAB
Если ваше приложение требует, чтобы сгенерированный код возвратил тот же размер переменного размера массивы N-D как код MATLAB, рассмотрите одно из этих обходных решений:
Используйте форму 2D аргумента 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
.
Это поведение сохраняется при определении размера пустых символьных векторов, которые обозначаются как ''
. Например, рассмотрите следующий код:
function out = string_size out = size(''); end
Здесь, значение out
может быть 1x0
или 0x1
в сгенерированном коде, но 0x0
в MATLAB.
Для несовместимостей с 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
ischar
.Вместо того, чтобы использовать 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 определяет класс результата на основе классов остающихся массивов, согласно приоритету классов. Смотрите Допустимые Комбинации в отличие от Классов. В сгенерированном коде, классе [c{I}]
влияет на класс результата полной конкатенации [...[c{I}]...]
потому что генератор кода обрабатывает c{I}
как [c{I}]
. Ранее описанные правила определяют класс [c{I}]
.
В сгенерированном коде, размере [c{I}]
может отличаться от размера в MATLAB.
В MATLAB, конкатенация [c{I}]
0x0 дважды. В сгенерированном коде ранее описанные правила определяют размер [c{I}]
.