用于代码生成的 matlab 中具有多个匹配项的 switch-case
switch-case with multiple matches in matlab for code generation
以下代码是有效的 matlab 语法,用于检查 b
是否匹配 a
中的任何元素。但是,如果代码用于代码生成(即 simulink),则会出现错误:
'code generation only supports cell operations for varargin and varargout
您可以通过在脚本顶部添加 %#codegen
来检查这一点。)
a={2 3};
b=3;
switch b
case a
disp yay
otherwise
disp boo
end
我应该如何匹配代码生成兼容代码中 case
语句中的多个模式?
以下对我不起作用:
case a(1) || a(2) %//with a=[2, 3] above, since cells not allowed
case a(:)
Matlab 编码器不支持 'cell arrays',并且它可以处理的函数集有限。请记住,C
不如 Matlab 灵活,特别是关于它处理的数据 type
。 C
不做动态类型(一个结构应该被定义一次并且定义不能在代码中改变)。因此 Matlab 不能让您使用类型非常松散的 cell array
,并且您要添加到 cell
数组的下一个元素的类型与其他元素的类型不同。
因此,如果您希望 Matlab 将其转换为可能的 C
语言,那么在某些情况下,您将不得不为 Matlab 明确说明。
对于您的情况,不同的选择:
直接在case
语句中显式列表
如果您不必经常重复使用 a
进行比较,您可以将 case a
替换为一个显式列表,例如 case {2,3,4,5}
:
function test_coder(b)
switch b
case {2,3,4,5}
disp yay
otherwise
disp boo
end
它看起来像元胞数组,但实际上不是。因为它足够明确(变量只包含 4 double
类型)Matlab 将在内部使用数组并将 b
与每个元素进行比较(它将 "expand" 和 case
语句) .事实上,这部分生成的代码看起来像 (pure C
way):
guard1 = FALSE;
switch ((int32_T)emlrtIntegerCheckFastR2012b(b, &emlrtDCI, emlrtRootTLSGlobal))
{
case 2:
guard1 = TRUE;
break;
case 3:
guard1 = TRUE;
break;
case 4:
guard1 = TRUE;
break;
case 5:
guard1 = TRUE;
break;
... // and so on
对数组使用 ismember
。
函数ismember
is supported by the code generator。所以下面的代码也可以工作:
function test_coder(b)
a=[2 3 4 5] ; %// define array "a"
c=[8 9 10] ; %// define array "c"
if ismember(b,a)
disp yay
elseif ismember(b,c)
disp youhou
else
disp boo
end
但是请注意,编码器需要对发送到 ismember
的数组进行排序,否则会引发错误。
如果您需要进行大量比较,这会起作用,但是考虑到生成代码的复杂性,我建议您仅在真正需要时才使用 ismember
。
当您的案例足够简单时,我建议您对 cases
进行显式声明(如果需要,请使用 {...}
"shortcut"。
还请始终注意查看生成的代码:
在你最初的例子中,当你在代码中指定 b=3
时,Matlab 检测到,检测到代码将 always 以这种方式流动,所以它甚至没有编写比较逻辑...生成的代码只是一个快速 disp yay
...
我不得不将 b
作为输入,让 Matlab 实际编写比较逻辑代码。要编译上面的代码,您必须指定输入变量 b
的类型。所以我编译上面使用:
codegen test_coder.m -args {0}
以下代码是有效的 matlab 语法,用于检查 b
是否匹配 a
中的任何元素。但是,如果代码用于代码生成(即 simulink),则会出现错误:
'code generation only supports cell operations for varargin and varargout
您可以通过在脚本顶部添加 %#codegen
来检查这一点。)
a={2 3};
b=3;
switch b
case a
disp yay
otherwise
disp boo
end
我应该如何匹配代码生成兼容代码中 case
语句中的多个模式?
以下对我不起作用:
case a(1) || a(2) %//with a=[2, 3] above, since cells not allowed
case a(:)
Matlab 编码器不支持 'cell arrays',并且它可以处理的函数集有限。请记住,C
不如 Matlab 灵活,特别是关于它处理的数据 type
。 C
不做动态类型(一个结构应该被定义一次并且定义不能在代码中改变)。因此 Matlab 不能让您使用类型非常松散的 cell array
,并且您要添加到 cell
数组的下一个元素的类型与其他元素的类型不同。
因此,如果您希望 Matlab 将其转换为可能的 C
语言,那么在某些情况下,您将不得不为 Matlab 明确说明。
对于您的情况,不同的选择:
直接在case
语句中显式列表
如果您不必经常重复使用 a
进行比较,您可以将 case a
替换为一个显式列表,例如 case {2,3,4,5}
:
function test_coder(b)
switch b
case {2,3,4,5}
disp yay
otherwise
disp boo
end
它看起来像元胞数组,但实际上不是。因为它足够明确(变量只包含 4 double
类型)Matlab 将在内部使用数组并将 b
与每个元素进行比较(它将 "expand" 和 case
语句) .事实上,这部分生成的代码看起来像 (pure C
way):
guard1 = FALSE;
switch ((int32_T)emlrtIntegerCheckFastR2012b(b, &emlrtDCI, emlrtRootTLSGlobal))
{
case 2:
guard1 = TRUE;
break;
case 3:
guard1 = TRUE;
break;
case 4:
guard1 = TRUE;
break;
case 5:
guard1 = TRUE;
break;
... // and so on
对数组使用 ismember
。
函数ismember
is supported by the code generator。所以下面的代码也可以工作:
function test_coder(b)
a=[2 3 4 5] ; %// define array "a"
c=[8 9 10] ; %// define array "c"
if ismember(b,a)
disp yay
elseif ismember(b,c)
disp youhou
else
disp boo
end
但是请注意,编码器需要对发送到 ismember
的数组进行排序,否则会引发错误。
如果您需要进行大量比较,这会起作用,但是考虑到生成代码的复杂性,我建议您仅在真正需要时才使用 ismember
。
当您的案例足够简单时,我建议您对 cases
进行显式声明(如果需要,请使用 {...}
"shortcut"。
还请始终注意查看生成的代码:
在你最初的例子中,当你在代码中指定 b=3
时,Matlab 检测到,检测到代码将 always 以这种方式流动,所以它甚至没有编写比较逻辑...生成的代码只是一个快速 disp yay
...
我不得不将 b
作为输入,让 Matlab 实际编写比较逻辑代码。要编译上面的代码,您必须指定输入变量 b
的类型。所以我编译上面使用:
codegen test_coder.m -args {0}