在matlab中具有多个匹配的switch-case用于代码生成

cra*_*raq 3 matlab code-generation simulink switch-statement matlab-coder

以下代码是有效的matlab sytax,用于检查是否b匹配中的任何元素a.但是,如果代码用于代码生成(即simulink),那么我得到错误:

'code generation only supports cell operations for varargin and varargout  
Run Code Online (Sandbox Code Playgroud)

您可以通过%#codegen在脚本顶部添加来检查这一点.)

a={2 3};
b=3;
switch b
    case a
        disp yay
    otherwise
        disp boo
end
Run Code Online (Sandbox Code Playgroud)

case在代码生成兼容代码中,我应该如何匹配语句中的多个模式?

以下内容对我不起作用:

case a(1) || a(2) %//with a=[2, 3] above, since cells not allowed

case a(:)
Run Code Online (Sandbox Code Playgroud)

Hok*_*oki 6

Matlab编码器不支持"单元阵列",并且具有一组有限的功能.请记住,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
Run Code Online (Sandbox Code Playgroud)

它看起来像一个单元阵列,但事实并非如此.因为它足够明确(变量只保持4 double种类型)Matlab将在内部使用数组并与b每个元素进行比较(它将"扩展" case语句).实际上,这部分生成的代码看起来像(纯粹的C方式):

  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
Run Code Online (Sandbox Code Playgroud)

ismember与数组一起使用.

该功能ismember由代码生成的支持.所以下面的代码也适用:

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
Run Code Online (Sandbox Code Playgroud)

但请注意,编码器要求对发送的数组ismember进行排序,否则会引发错误.

如果你有很多比较,这是有效的,但是考虑到生成的代码的复杂性,我建议ismember只在你真正需要的时候使用它.
当你的案例足够简单时我会建议你明确声明你的cases({...}如果你需要的话,使用"快捷方式").


另外要小心,看看你生成的代码:
在你的初始例子中,当你b=3在代码中指定时,Matlab检测到,检测到代码将始终以这种方式流动,因此它甚至不编码比较逻辑......生成的代码只是一个快速disp yay...

我不得不将其b作为输入来让Matlab实际编写比较逻辑.要编译上面的代码,您必须指定输入变量的类型b.所以我用以下方法编译了上面

codegen test_coder.m -args {0}
Run Code Online (Sandbox Code Playgroud)