Using a variable-sized argument in Matlab coder - matlab

I want to generate a c++ code for DCT function using Matlab coder. I wrote this simple function and tried to convert it to c++.
function output_signal = my_dct(input_signal)
output_signal = dct(input_signal);
end
When I use a fixed size type for the input argument (such as double 1x64), there is no problem; however, a variable-sized type (such as double 1x:64) for the input argument results in these errors:
The preceding error is caused by: Non-constant expression..
The input to coder.const cannot be reduced to a constant.
Can anyone please help me?
Thanks in advance.

The documentation is a bit vague for DCT in Coder, but it implies that the input size must be a constant power of 2 along the dimension of the transform. From DCT help:
C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.
Usage notes and limitations:
C and C++ code generation for dct requires DSP System Toolbox™ software.
The length of the transform dimension must be a power of two. If specified, the pad or truncation value must be constant. Expressions or variables are allowed if their values do not change.
It doesn't directly say that the length of the variable (at least along the dimension being transformed) going into the dct function must be a constant, but given how coder works, it really probably has to be. Since that's the error it's returning, it appears that's a limitation.
You could always modify your calling function to zero pad to a known maximum length, thus making the length constant.
For instance, something like this might work:
function output_signal = my_dct(input_signal)
maxlength = 64;
tinput = zeros(1,maxlength);
tinput(1:min(end, numel(input_signal))) = input_signal(1:min(end, maxlength));
output_signal = dct(tinput);
end
That code will cause tinput to always have a size of 1 by 64 elements. Of course, the output will also always be 64 elements long also, which means it'll be scaled and may have a difference frequency scale than you're expecting.

Related

Create constant for specifying array size in MATLAB Coder

How can I create a constant variable in MATLAB (and its results the generated C code), so I can use it later in my code to specify the size of variables.
I want to have an array that its size is not hardcoded via number all over the code.
I want to specify the size at the beginning of the code like how we do in C code using one of the followings:
const int arraySize=5
#define arraysize 5
Later: int array[arraySize];
When I write the following in MATLAB, Coder just replaces arraySize with the actual number which is 5:
arraySize=int8(5);
array=zeros(1,arraySize); % zeros is just used for specifying size
Generated code:
void coder(double A[5])
{
memset(&A[0], 0, sizeof(double) << 16);
}
I tried using the following but it does not allow me to use arraySize in MATLAB calculations:
arraySize=coder.opaque('const int16','5');
A=zeros(1,arraySize);
This may be related to constant folding which I can not disable!
This array size may be repeated throughout the different functions and code many times, so global probably may be related to this
Having a constant variable appear by name (rather than the value) in the sizes of other variables is unfortunately not supported in MATLAB Coder as of MATLAB R2019a. We've made an internal note of your request so we can look at lifting that limitation in the future.

Accuracy error in binomials using MATLAB?

The value is absolute integer, not a floating point to be doubted, also, it is not about an overflow since a double value can hold until 2^1024.
fprintf('%f',realmax)
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The problem I am facing in nchoosek function that it doesn't produce exact values
fprintf('%f\n',nchoosek(55,24));
2488589544741302.000000
While it is a percentage error of 2 regarding that binomian(n,m)=binomial(n-1,m)+binomial(n-1,m-1) as follows
fprintf('%f',nchoosek(55-1,24)+nchoosek(55-1,24-1))
2488589544741301.000000
Ps: The exact value is 2488589544741300
this demo shows
What is wrong with MATLAB?
Your understanding of the realmax function is wrong. It's the maximum value which can be stored, but with such large numbers you have a floating point precision error far above 1. The first integer which can not be stored in a double value is 2^53+1, try 2^53==2^53+1 for a simple example.
If the symbolic toolbox is available, the easiest to implement solution is using it:
>> nchoosek(sym(55),sym(24))
ans =
2488589544741300
There is a difference between something that looks like an integer (55) and something that's actually an integer (in terms of variable type).
The way you're calculating it, your values are stored as floating point (which is what realmax is pointing you to - the largest positive floating point number - check intmax('int64') for the largest possible integer value), so you can get floating point errors. An absolute difference of 2 in a large value is not that unexpected - the actual percentage error is tiny.
Plus, you're using %f in your format string - e.g. asking it to display as floating point.
For nchoosek specifically, from the docs, the output is returned as a nonnegative scalar value, of the same type as inputs n and k, or, if they are different types, of the non-double type (you can only have different input types if one is a double).
In Matlab, when you type a number directly into a function input, it generally defaults to a float. You have to force it to be an integer.
Try instead:
fprintf('%d\n',nchoosek(int64(55),int64(24)));
Note: %d not %f, converting both inputs to specifically integer. The output of nchoosek here should be of type int64.
I don't have access to MATLAB, but since you're obviously okay working with Octave I'll post my observations based on that.
If you look at the Octave source code using edit nchoosek or here you'll see that the equation for calculating the binomial coefficient is quite simple:
A = round (prod ((v-k+1:v)./(1:k)));
As you can see, there are k divisions, each with the possibility of introducing some small error. The next line attempts to be helpful and warn you of the possibility of loss of precision:
if (A*2*k*eps >= 0.5)
warning ("nchoosek", "nchoosek: possible loss of precision");
So, if I may slightly modify your final question, what is wrong with Octave? I would say nothing is wrong. The authors obviously knew of the possibility of imprecision and included a check to warn users when that possibility arises. So the function is working as intended. If you require greater precision for your application than the built-in function provides, it looks as though you'll need to code (or find) something that calculates the intermediate results with greater precision.

Subscripted assignment dimension mismatch. error in matlab

for i=1:30
Name(i,1)=sprintf('String_%i',i);
end
I'm just confused what is not working here, this script seems very straightforward, wnat to build a list of strings with numbering from 1 to 30. getting error
Subscripted assignment dimension mismatch.
Matlab do not really have strings, they have char arrays. As in almost any programming language Matlab cannot define a variable without knowing how much memory to allocate. The java solution would look like this:
String str[] = {"I","am","a","string"};
Similar to the c++ solution:
std::string str[] = {"I","am","another","string"};
The c solution looks different, but is generally the same solution as in c++:
const char* str[] = {"I","am","a","c-type","string"};
However, despite the appearances these are all fundamentally the same in the sense to that they all knows how much data to allocate even though they would not be initiated. In particular you can for example write:
String str[3];
// Initialize element with an any length string.
The reason is that the memory stored in each element is stored by its reference in java and by a pointer in c and c++. So depending on operating system, each element is either 4 (32-bit) or 8 (64-bit) bytes.
However, in Matlab matrices data is stored by value. This makes it impossible to store a N char arrays in a 1xN or Nx1 matrix. Each element in the matrix is only allowed to be of the same size as a char and be of type char. This means that if you work with strings you need to use the data structure cell (as also suggested by Benoit_11) which stores a reference to any Matlab object in each element.
k = 1:30;
Name = cell(length(k),1);
for i=k
Name{i,1}=sprintf('String_%i',i);
end
Hope that the explanation makes sense to you. I assumed that according to your attempt you have at least some programming experience from at least one other language than matlab.

Block Truncation Coding MATLAB

I am trying to implement block truncation coding (BTC) on an image in matlab. In order to do BTW you have to calculate the mean and standard deviation of each 4x4 block of pixels. However, I need to store the mean as a variable number of bits as in the number of bits that the mean will be stored in is passed into the function that calculates the mean. I'm not sure how to do this part, can anyone help?
An easy and clean approach to variable bit lengths-encoding would require the use of the fixed-point toolbox. E.g. as follows
function o = encode1(val, numBits)
o = fi(val, 0, numBits, 0)
If you are rather bound to pure Matlab you could just and them away and 'simulate' the precision loss if you only want to benchmark your encoding.
function o = encode2(val, numBits)
o = bitand(uint8(val), 256 - 2^(8-numBits));
On the other hand, if you're planning to actually encode into a file and not just simulate the encoding, you would need to establish a bit-stream which is not byte-aligned. This can be a bit tiring to do. Trading off efficiency for ease of implementation, you could use dec2bin to work with a string of '0' and '1' characters. Again, toolboxes can be of help here, e.g. the communication systems toolbox provides the de2bi function.

Can you explain this Embedded MATLAB Function error?

I'm having a problem sending a value from a GUI to an Embedded MATLAB Function (EMF) in a Simulink model. I get this value from a slider in my GUI and send it to an EMF block in my model. I can confirm that the value is being transferred correctly from my GUI to my Simulink block, since I can display the value with a display block in my model and see the value change when I change the slider position in my GUI. However I keep getting this error when I run my model:
Could not determine the size of this expression.
Function 'Kastl' (#18.282.283), line 14, column 1:
"f"
This is part of my EMF block code:
function y = input_par(u,fstart)
...
f_end = 1000;
f = fstart:f_end;
...
I believe MikeT is correct: you can't redefine the size of a variable in an embedded function. If you look at this Embedded MATLAB Function documentation page under the subsection Defining Local Variables, it says:
Once you define a variable, you cannot
redefine it to any other type or size
in the function body.
You will have to rework your embedded function such that the variables you declare are not changing size. Since I don't know what you are subsequently doing with the variable f, there's not much more specific help I can give you.
In general, if you absolutely need to use data that changes size, one solution is to pad the data with "garbage" values in order to maintain a constant size. For example:
MAX_ELEMS = 1000; % Define the maximum number of elements in the vector
f = [fstart:MAX_ELEMS nan(1,fstart-1)]; % Create vector and pad with NaNs
In the above example, the variable f will always have 1000 elements (assuming the value of fstart is an integer value less than or equal to 1000). The value NaN is used to pad the vector to the appropriate constant size. Any subsequent code would have to be able to recognize that a value of NaN should be ignored. Depending on what calculations are subsequently done in the embedded function, different pad values might be needed in place of NaN (such as 0, negative values, etc.).
I believe the issue you are running into is that you can't change a parameter during simulation that will cause the dimension of a signal to change. In your example, the code,
f = fstart:f_end;
changes size whenever fstart changes. I think this is what EMF block is complaining about. I don't have any easy workaround for this particular issue, but maybe there's an equivalent way of doing what you want that avoids this issue.