I have a problem with data type in MATLAB. It's a simple code of converting binary to decimal. For my further task, those should be integer 64 bit. How can I do it?
This code converts those value into double. And, type casting isn't helpful; for example, for the first value, sum is 4.0265e+09 but after casting via Y = typecast(sum, 'int64'); it generates 4750734656922451968 which is not correct value.
example.png:
I = imread('example.png');
level = graythresh(I);
img = im2bw(I,level);
sz=size(img);
for i=1:sz(1)
sum=0;
p=1;
for j=sz(2):-1:1
sum=sum+img(i,j)*p;
p=p*2;
end
disp(sum);
end
You should use cast instead of typecast
>> s = 4.0265e+09;
>> cast(s, 'int64')
ans =
4026500000
typecast converts data without altering the underlying byte values whereas cast converts data and attempts to keep the same value. typecast as you have found can change the value of data as it does not alter the underlying byte values. typecast simply changes the type that MATLAB uses to interpret the underlying byte values.
Alternatively you could simply use int64
>> int64(s)
ans =
4026500000
to convert data whilst attempting to keep the same value.
Aside: sum is a built-in MATLAB function. It is not recommended that you call a variable sum as you will overwrite the built-in MATLAB function.
Related
I am trying to use the MATLAB Coder toolbox to convert the following code into C:
function [idx] = list_iterator(compare, list)
idx = nan(length(list));
for j = 1:length(list)
idx(j) = strcmp(compare, list{j});
end
list is an N x 1 cell array of strings and compare is a string. The code basically compares each element of list to compare and returns 1 if the two are the same and 0 otherwise. (I'm doing this to speed up execution because N can be quite large - around 10 to 20 million elements.)
When I run codegen list_iterator in the Command Window, I get the following error:
Type of input argument 'compare' for function 'list_iterator'
not specified. Use -args or preconditioning statements to specify
input types.
More information
Error in ==> list_iterator Line: 1
Column: 18
Code generation failed: View Error Report
Error using codegen
I know I'm supposed to specify the types of the inputs when using codegen, but I'm not sure how to do this for a cell array of strings, the elements of which can be of different length. The string compare can also have different lengths depending on the function call.
You can use the function coder.typeof to specify variable-size inputs to codegen. From what I've understood of your example, something like:
>> compare = coder.typeof('a',[1,Inf])
compare =
coder.PrimitiveType
1×:inf char
>> list = coder.typeof({compare}, [Inf,1])
list =
coder.CellType
:inf×1 homogeneous cell
base: 1×:inf char
>> codegen list_iterator.m -args {compare, list}
seems appropriate.
If you check out the MATLAB Coder App, that provides a graphical means of specifying these complicated inputs. From there you can export this to a build script to see the corresponding command line APIs:
https://www.mathworks.com/help/coder/ug/generate-a-matlab-script-to-build-a-project.html?searchHighlight=build%20script&s_tid=doc_srchtitle
Note that when I tried this example with codegen, the resulting MEX was not faster than MATLAB. One reason this can happen is because the body of the function is fairly simple but a large amount of data is transferred from MATLAB to the generated code and back. As a result, this data transfer overhead can dominate the execution time. Moving more of your code to generated MEX may improve this.
Thinking about the performance unrelated to codegen, should you use idx = false(length(list),1); rather than idx = nan(length(list));? The former is a Nx1 logical vector while the latter is an NxN double matrix where we only write the fist column in list_iterator.
With your original code and the inputs compare = 'abcd'; list = repmat({'abcd';'a';'b'},1000,1); this gives the time:
>> timeit(#()list_iterator(compareIn, listIn))
ans =
0.0257
Modifying your code to return a vector scales that down:
function [idx] = list_iterator(compare, list)
idx = false(length(list),1);
for j = 1:length(list)
idx(j) = strcmp(compare, list{j});
end
>> timeit(#()list_iterator(compareIn, listIn))
ans =
0.0014
You can also call strcmp with a cell and char array which makes the code faster still:
function [idx] = list_iterator(compare, list)
idx = strcmp(compare, list);
>> timeit(#()list_iterator(compareIn, listIn))
ans =
2.1695e-05
I want to use the stats::swGOFT function in MuPAD. I have a numerical vector called r. I used
feval(symengine, 'stats::swGOFT', r);
The error was
Error using mupadengine/feval (line 157)
MuPAD error: Error: Some data are of invalid type.
So I tried a more direct way, which worked:
feval(symengine, 'stats::swGOFT', 1,2,3,4);
But this didn't work:
feval(symengine, 'stats::swGOFT', [1,2,3,4]);
My variable r is a 1146-by-1 double vector. Obviously I can't manually input all the numbers. So, how to pass the vector variable r to the MuPAD function stats::swGOFT?
MuPAD is not Matlab. From the current version documentation for stats::swGOFT, it appears that this function requires a list, as opposed to an array (what Matlab uses). Many MuPAD functions automatically coerce inputs to the desired format, but that doesn't seem to occur in this case. You have several options if you want to call this function from Matlab using numeric values – here's a simple one that will work for both floating point and symbolic numeric values:
r = randn(1146,1);
rStr = char(sym(r(:).'));
feval(symengine, 'stats::swGOFT', rStr(9:end-2))
This one should perform the string conversion more quickly for large datasets of floating point values using sprintf:
r = randn(1146,1);
rStr = ['[' sprintf('%.17g', r(1)) sprintf(',%.17g', r(2:end)) ']'];
feval(symengine, 'stats::swGOFT', rStr)
Since you're converting to a string yourself, you might as well convert the above to use evalin directly:
r = randn(1146,1);
rStr = [ sprintf('%.17g', r(1)) sprintf(',%.17g', r(2:end)) ];
evalin(symengine, ['stats::swGOFT([' rStr '])'])
I have a symbolic and numeric mixed expression:
(3145495418313256125*sin(11334310783410932061962315977/17437937757178560512000000000)*cos(theta))/85568392920039424
where theta is a symbolic variable. I want to simplify this expression such that all the numeric numbers and their math operation results are changed to double.
In terms of data types, you can't mix floating point and symbolic values. However, you can use variable precision arithmetic so that the values are represented in decimal form. Using vpa:
syms theta
y1 = (3145495418313256125*sin(11334310783410932061962315977/17437937757178560512000000000)*cos(theta))/85568392920039424
y2 = vpa(y1)
which returns
y2 =
22.24607614528243677915796931637*cos(theta)
The data type (class) of y2 is still sym. See the digits function to adjust the number of significant digits.
If you want to work in actual floating point you'll need to convert your symbolic expression into a function. You can automate that procedure by using the confusingly-named matlabFunction:
thetafun = matlabFunction(y1)
which returns a function using double precision variables:
thetafun =
#(theta)cos(theta).*2.224607614528244e1
The anonymous function thetafun can then be called just like any function, e.g., thetafun(0.5).
You can make use of coeffs command to achieve the desired:
f=2*cos(theta)/3+5*sin(theta)/19
c_f=coeffs(f);
fraction_c_f=double(c_f);
ans = [0.2632 0.6667]
I'm having some problems with MATLAB and 64-bit integers. I want to have a mask equivalent to 2^63-1 (all ones except the MSB), but MATLAB just seems to round everything.
>> mask_fraction = uint64(9223372036854775807)
mask_fraction = 9223372036854775808 % This is 2^63 again, not 2^63-1!
Similarly,
>> uint64(2^63)
ans = 9223372036854775808
>> uint64(2^63-1)
ans = 9223372036854775808
Another one of my attempts simply doesn't work:
>> uint64(2^63) - 1
??? Undefined function or method 'minus' for input arguments of type 'uint64'.
Thoughts?
#BasSwinckels correctly points out one issue. I'll address another.
The first non-exactly representable double-precision floating point integer is 2^53+1. When you pass in expressions to the uint64 function they are evaluated as doubles before being cast to uint64. If these expressions evaluate to a double precision integer that is not exactly representable, you'll see behavior like you described. This is exactly why uint64(2^63-1) and uint64(2^63) both return 9223372036854775808. All powers of two can be safely represented in double precision, so uint64(2^63)-1 or uint64(2^63)-uint64(1) are what you should use (once you figure out your other issue).
I don't see the problems you report. On my computer (Matlab R2012b on 64-bit Ubuntu12.04):
>> mask_fraction = uint64(9223372036854775807)
mask_fraction =
9223372036854775807
>> uint64(2^63) - 1
ans =
9223372036854775807
Do you maybe run an older Matlab version?
I also find the 'undefined function or method minus ...' error a bit suspicious. Do you have uint64 aliased to some other function? Try clear uint64 first ...
It seems from the other comments that Matlab does not implement the minus method for class uint64 in some older versions. The ugly workaround below works for me in R2011b:
>> bitset(intmax('uint64'), 64, 0)
ans =
9223372036854775807
I don't know if it is supported by the version of MATLAB you are using but this might help
mask_fraction = uint64(intmax('int64'))
which returns
mask_fraction =
9223372036854775807
2^63-1 is the maximum value for int64.
I used MATLAB coder to covert M-file to cpp-file.
There generated problem when is building.
Expected either a logical, char, int, fi, single, or double. Found an
mxArray. MxArrays are returned from calls to the MATLAB
interpreter and are not supported inside expressions. They may only be
used on the right-hand side of assignments and as arguments to
extrinsic functions.
MATLAB code :
nms = sum(transpose(X).^2);
nms0=-1 * nms;
nms2=transpose(nms0);
nms3=transpose(X);
nms4=nms2*ones(1,n);
nms5=ones(n,1)*nms;
nms6=2*X*nms3;
nms7=zeros(150,150);
nms7=nms4-nms5; //This line is wrong
nms8=nms7 + nms6;
K = exp(nms8);
I want to know why code has been run correct in MATLAB,but it has error when is building
This error happens when you try to use result of extrinsic functions in expressions. In the code you provided is "n" or "X" the result of an extrinsic function? Even if they are not directly a result of an extrinsic function, they may have been computed based on data from other extrinsic functions.
One way to fix the problem is to help MATLAB coder convert these extrinsic data to known types. You can do that by pre-defining them with known data. For example,
coder.extrinsic('some_extrinsic_fcn');
y = zeros(10,1);
y = some_extrinsic_fcn();
y = y * 2;
In this case some_extrinsic_fcn should return a double precision vector with 10 elements. This resulting mxArray will be auto-converted and stored in y. Without the line "y = zeros(10,1);" y will be of mxArray type and the line "y = y * 2;" will cause an error.