Main Content

coder.const

Fold expressions into constants in generated code

Description

out = coder.const(expression) evaluates expression and replaces out with the result of the evaluation in generated code.

example

[out1,...,outN] = coder.const(handle,arg1,...,argN) evaluates the multi-output function having handle handle. It then replaces out1,...,outN with the results of the evaluation in the generated code. To learn about the behavior of coder.const when handle accepts zero inputs and returns zero or one outputs, see Tips.

example

Examples

collapse all

This example shows how to specify constants in generated code using coder.const. The code generator folds an expression or a function call in a coder.const statement into a constant in generated code. Because the generated code does not have to evaluate the expression or call the function every time, this optimization reduces the execution time of the generated code.

Write a function AddShift that takes an input Shift and adds it to the elements of a vector. The vector consists of the square of the first 10 natural numbers. AddShift generates this vector.

function y = AddShift(Shift) %#codegen
y = (1:10).^2+Shift;

Generate code for AddShift using the codegen command. Open the Code Generation Report.

codegen -config:lib -launchreport AddShift -args 0

The code generator produces code for creating the vector. It adds Shift to each element of the vector during vector creation. The definition of AddShift in generated code looks as follows:

void AddShift(double Shift, double y[10])
{
  int k;
  for (k = 0; k < 10; k++) {
    y[k] = (double)((1 + k) * (1 + k)) + Shift;
  }
}

Replace the expression (1:10).^2 with coder.const((1:10).^2), and then generate code for AddShift again using the codegen command. Open the Code Generation Report.

codegen -config:lib -launchreport AddShift -args 0

The code generator creates the vector containing the squares of the first 10 natural numbers. In the generated code, it adds Shift to each element of this vector. The definition of AddShift in generated code looks as follows:

void AddShift(double Shift, double y[10])
{
  int i;
  static const signed char iv[10] = { 1, 4, 9, 16, 25, 36, 
                                 49, 64, 81, 100 };

  for (i = 0; i < 10; i++) {
    y[i] = (double)iv[i] + Shift;
  }
}

This example shows how to fold a user-written function into a constant in generated code.

Write a function getsine that takes an input index and returns the element referred to by index from a lookup table of sines. The function getsine creates the lookup table using another function gettable.

function y = getsine(index) %#codegen
  assert(isa(index, 'int32'));
  persistent tbl;
  if isempty(tbl)
           tbl = gettable(1024);
  end
  y = tbl(index);

function y = gettable(n)
      y = zeros(1,n);
      for i = 1:n
         y(i) = sin((i-1)/(2*pi*n));
      end

Generate code for getsine using an argument of type int32. Open the Code Generation Report.

codegen -config:lib -launchreport getsine -args int32(0)

The generated code contains instructions for creating the lookup table.

Replace the statement:

tbl = gettable(1024);

with:

tbl = coder.const(gettable(1024));

Generate code for getsine using an argument of type int32. Open the Code Generation Report.

The generated code contains the lookup table itself. coder.const forces the expression gettable(1024) to be evaluated during code generation. The generated code does not contain instructions for the evaluation. The generated code contains the result of the evaluation itself.

This example shows how to specify constants in generated code using a multi-output function in a coder.const statement.

Write a function MultiplyConst that takes an input factor and multiplies every element of two vectors vec1 and vec2 with factor. The function generates vec1 and vec2 using another function EvalConsts.

function [y1,y2] = MultiplyConst(factor) %#codegen
  [vec1,vec2]=EvalConsts(pi.*(1./2.^(1:10)),2);
  y1=vec1.*factor;
  y2=vec2.*factor;

function [f1,f2]=EvalConsts(z,n)
  f1=z.^(2*n)/factorial(2*n);
  f2=z.^(2*n+1)/factorial(2*n+1);

Generate code for MultiplyConst using the codegen command. Open the Code Generation Report.

codegen -config:lib -launchreport MultiplyConst -args 0

The code generator produces code for creating the vectors.

Replace the statement

[vec1,vec2]=EvalConsts(pi.*(1./2.^(1:10)),2);

with

[vec1,vec2]=coder.const(@EvalConsts,pi.*(1./2.^(1:10)),2);

Generate code for MultiplyConst using the codegen command. Open the Code Generation Report.

codegen -config:lib -launchreport MultiplyConst -args 0
The code generator does not generate code for creating the vectors. Instead, it calculates the vectors and specifies the calculated vectors in generated code.

This example shows how to call an extrinsic function using coder.const.

Write an XML file MyParams.xml containing the following statements:

<params>
    <param name="hello" value="17"/>
    <param name="world" value="42"/>
</params>

Save MyParams.xml in the current folder.

Write a MATLAB® function xml2struct that reads an XML file. The function identifies the XML tag param inside another tag params.

After identifying param, the function assigns the value of its attribute name to the field name of a structure s. The function also assigns the value of attribute value to the value of the field.

function s = xml2struct(file)

s = struct();
doc = xmlread(file);
els = doc.getElementsByTagName('params');
for i = 0:els.getLength-1
    it = els.item(i);
    ps = it.getElementsByTagName('param');
    for j = 0:ps.getLength-1
        param = ps.item(j);
        paramName = char(param.getAttribute('name'));
        paramValue = char(param.getAttribute('value'));
        paramValue = evalin('base', paramValue);
        s.(paramName) = paramValue;        
    end
end

Save xml2struct in the current folder.

Write a MATLAB function MyFunc that reads the XML file MyParams.xml into a structure s using the function xml2struct. Declare xml2struct as extrinsic using coder.extrinsic and call it in a coder.const statement.

function y = MyFunc(u) %#codegen
  assert(isa(u, 'double'));
  coder.extrinsic('xml2struct');
  s = coder.const(xml2struct('MyParams.xml'));
  y = s.hello + s.world + u;

Generate code for MyFunc using the codegen command. Open the Code Generation Report.

codegen -config:dll -launchreport MyFunc -args 0

The code generator executes the call to xml2struct during code generation. It replaces the structure fields s.hello and s.world with the values 17 and 42 in generated code.

Input Arguments

collapse all

MATLAB expression or user-defined single-output function.

The expression must have compile-time constants only. The function must take constant arguments only. For instance, the following code leads to a code generation error, because x is not a compile-time constant.

function y=func(x)
   y=coder.const(log10(x));

To fix the error, assign x to a constant in the MATLAB code. Alternatively, during code generation, you can use coder.Constant to define input type as follows:

codegen -config:lib func -args coder.Constant(10)

Example: 2*pi, factorial(10)

Handle to built-in or user-written function.

Example: @log, @sin

Data Types: function_handle

Arguments to the function with handle handle.

The arguments must be compile-time constants. For instance, the following code leads to a code generation error, because x and y are not compile-time constants.

function y=func(x,y)
   y=coder.const(@nchoosek,x,y);

To fix the error, assign x and y to constants in the MATLAB code. Alternatively, during code generation, you can use coder.Constant to define input type as follows:

codegen -config:lib func -args {coder.Constant(10),coder.Constant(2)}

Output Arguments

collapse all

Value of expression. In the generated code, MATLAB Coder™ replaces occurrences of out with the value of expression.

Outputs of the function with handle handle. MATLAB Coder evaluates the function and replaces occurrences of out1,...,outN with constants in the generated code.

Limitations

  • You cannot use coder.const on dictionaries, dictionary keys, or dictionary values.

Tips

  • When possible, the code generator constant-folds expressions automatically. Typically, automatic constant-folding occurs for expressions with scalars only. Use coder.const when the code generator does not constant-fold expressions on its own.

  • When constant-folding computationally intensive function calls, to reduce code generation time, make the function call extrinsic. The extrinsic function call causes evaluation of the function call by MATLAB instead of by the code generator. For example:

    function j = fcn(z)
    zTable = coder.const(0:0.01:100);
    jTable = coder.const(feval('besselj',3,zTable));
    j = interp1(zTable,jTable,z);
    end

    See Use coder.const with Extrinsic Function Calls.

  • If coder.const is unable to constant-fold a function call, try to force constant-folding by making the function call extrinsic. The extrinsic function call causes evaluation of the function call by MATLAB instead of by the code generator. For example:

    function yi = fcn(xi)
    y = coder.const(feval('rand',1,100));
    yi = interp1(y,xi);
    end

    See Use coder.const with Extrinsic Function Calls.

  • Suppose that you call coder.const on a function handle with zero inputs and zero or one outputs. For example:

    out = coder.const(@fcn);
    In such situations, the code generator does not evaluate fcn, and sets out to the function handle @fcn itself. To force the evaluation of fcn in this special case, call the function explicitly inside the coder.const command. For example:
    out = coder.const(fcn());

Extended Capabilities

C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.

GPU Code Generation
Generate CUDA® code for NVIDIA® GPUs using GPU Coder™.

Version History

Introduced in R2013b