Resolve Error: Unable to Produce Column Vector from Scalar
Issue
When you assign a value to the end+1 element of a scalar,
MATLAB® produces a two-element row vector. However, if you generate code for a
function that uses (end+1) to grow an array and specify that the
array is a variable-length column vector, the generated MEX function produces this error
if the array is a scalar at run time:
Unable to produce column
vector from scalar by using end+1 indexing.
Note
If you use {end+1} to grow a cell array that is a variable-size
column vector at code generation time and a scalar at run time, the generated MEX
function does not produce an error. Instead, it produces a two-element column
vector, which means that the output of the generated code differs from the
MATLAB output. See Growing Variable-Size Column Cell Array That Is Initialized as Scalar at Run Time.
Possible Solutions
This MATLAB function takes two input arguments, A and
x, and assigns x to the
end+1 element of A. If A is
a row or column vector, MATLAB returns a row or column vector, respectively. When A is
a scalar, MATLAB returns a two-element row vector.
function out = grow(A,x) A(end+1) = x; out = A; end
Suppose that you generate code for this function and specify that A
is a variable-length column vector and x is a
scalar.
codegen grow -args {coder.typeof(0,[Inf 1]),0}
Code generation successful.
If you pass the generated MEX function a column vector with at least two elements, the MEX function produces a column vector with an additional element. However, if you pass the generated MEX function a scalar, the MEX function generates an error.
To resolve this error, try one of these solutions.
Pass Column Vector to MEX Function
Make sure that A is not a scalar at run time. Pass the
generated MEX function a column vector with at least two
elements.
grow_mex((1:5)',1)
ans =
1
2
3
4
5
1Specify That Array is Scalar at Code Generation Time
If A is always a scalar at
run time, specify that A is a scalar at code generation
time:
codegen grow -args {0,0}
Code generation successful.
grow_mex(10,1)
ans =
10 1Grow Row Vector by Using Temporary Variable
If you want to return a column vector even if the input is a scalar, rewrite your
MATLAB function to use a temporary variable that grows a row vector by using
end+1. Then, transpose the temporary variable to return a
column vector. For example, this function assigns the transpose of the input array
A to a temporary variable, temp. This
means that temp(end+1) is
always a row vector. The function then assigns the
transpose of the row vector to out to produce a column
vector.
function out = growRow(A,x) temp = A'; temp(end+1) = x; out = temp'; end
Generate code for growRow and specify that A
is a variable-length column
vector.
codegen growRow -args {coder.typeof(0,[Inf 1]),1}
Code generation successful.
The generated MEX function returns a column vector even if the input is scalar.
growRow_mex(10,1)
ans =
10
1Use Concatenation Operator
Rewrite your MATLAB function to use vertical concatenation instead of
end+1. This approach returns a column vector if the input is
a scalar at run time. For example, this function vertically concatenates
A and x. If A is a
scalar, the function returns a two-element column vector. If A is
a column vector, the function returns a column vector with one additional
row.
function out = growCat(A,x) out = [A;x]; end
Generate code for growRow and specify that A
is a variable-length column
vector.
codegen growCat -args {coder.typeof(0,[Inf 1]),1}
Code generation successful.
The generated MEX function returns a column vector even if the input is scalar.
growCat_mex(10,1)
ans =
10
1Explicitly Check for Scalar Input
To return a two-element row vector if the input array is a scalar and a column
vector if the input array is a column vector, rewrite your MATLAB code to check for scalar input. This approach replicates MATLAB behavior for scalar inputs. For example, this function checks whether
the input array is scalar by using the isscalar function. If the input
is scalar, the function horizontally concatenates x to
A and returns a two-element row vector. Otherwise,
A must be a column vector and the function uses
end+1 to append x to A
as an additional
row.
function out = growMat(A,x) if isscalar(A) out = [A x]; else A(end+1) = x; out = A; end end
Generate code for growMat and specify that A
is a variable-length column
vector.
codegen growMat -args {coder.typeof(0,[Inf 1]),1}
Code generation successful.
The generated MEX function returns a row vector if A is scalar
and a column vector if A is a column
vector.
growMat_mex(10,1)
ans =
10 1growMat_mex((1:5)',1)
ans =
1
2
3
4
5
1See Also
codegen | coder.typeof | isscalar