Matlab separate output into 2 variables - matlab

I have two float variables:
x = 0.5;
y = 1.5;
I would like to floor them:
x = floor(x);
y = floor(y);
Can i do it in a single command? this raises an error:
[x y] = floor([x y]);

You can write your own wrapper for floor:
function varargout = myFloor(varargin)
for k = 1:nargin
varargout{k} = floor(varargin{k});
end
This function shows the required behavior if you provide x and y as two separated arguments
[a, b] = myFloor(x,y)
This results in
a =
0
b =
1
If you want to use the concatenated array [x y] as input (like in your example) you can use the following function:
function varargout = myFloor(x)
for k = 1:numel(x)
varargout{k} = floor(x(k));
end
Then you would call
[a, b] = myFloor([x y])
This results in
a =
0
b =
1

Just adding a random idea here...
Building on H.Muster solution, you might want to define a personalized deal function, which is like deal but also applies a function to each argument:
function varargout = myDeal(fun, varargin)
if nargin == 2
varargout(1:nargout) = {feval(fun, varargin{1})};
elseif nargin-1 == nargout
for k = 1:nargout
varargout{k} = feval(fun, varargin{k}); end
else
error('Argument count mismatch.');
end
end
This way, you can multi-assign any function:
>> [x,y,z] = myDeal(#floor, 0.5, 0.6, 2.7)
x =
0
y =
0
z =
2
>> [x,y,z] = myDeal(#sin, pi/6)
x =
4.999999999999999e-01
y =
4.999999999999999e-01
z =
4.999999999999999e-01
>> [a, b] = myDeal(#fix, 10*rand(2), 8*rand(5))
a =
7 2
7 6
b =
5 2 4 1 6
1 4 5 1 1
0 1 7 2 7
3 6 7 6 2
7 2 4 2 1

No it is not possible.
Floor can only accept one argument as it can be seen from the syntax. You can see the reference below to verify:
http://www.mathworks.in/help/symbolic/mupad_ref/floor.html

if
A = [0.5 1.5]
then you can do
floor(A)
that would result in
ans = [0 1]
Here's an example: http://www.matlabtutorials.com/functions/floor.html

Related

How to overload a Matlab operator in order for it to apply element wise to object arrays

I'm trying to define a new class with the fields object.DeltaI and object.E, and I want to define the - operator for two object as:
new_obj.E=first_obj.E
new_obj.DeltaI = first_object.DeltaI - second_obj.DeltaI
My problem is that I want this operator to work on a array of my class element wise. How do I define the operator to work element wise?
This is the class method function I wrote:
function r = minus(a,b)
if length(a.E)==length(b.E) && sum(abs(a.E-b.E)<(10^-3))==length(a.E)
r = [a];
r.DeltaI = a.DeltaI - b.DeltaI;
else
error('a.E and b.E is not in the same size or E diffrance of more than 10^-3')
end
end
simple example:
the class definition is:
classdef IV_class
properties
E
I
end
methods
function r = minus(a,b)
r = a;
r.I = a.I-b.I;
end
end
end
now when I run this code:
a(1) = IV_class;
a(1).E = [1 2 3 4];
a(1).I = [3 3 3 3];
a(2) = IV_class;
a(2).E = [1 2 3 4];
a(2).I = [1 2 1 2];
b(1) = IV_class;
b(1).E = [1 2 3 4];
b(1).I = [2 2 2 2];
b(2) = IV_class;
b(2).E = [1 2 3 4];
b(2).I = [1 1 1 1];
a(1)-b(1)
% i get the proper answer:
% ans =
%IV_class with properties:
%E: [1 2 3 4]
%I: [1 1 1 1]
a-b
% i get error:
% Error using -
%Too many input arguments.
%
%Error in - (line 13)
% r.I = a.I-b.I;
its works when i'm doing a(1)-b(1)
but not in the case of a-b
You could do it like this:
classdef IV_class
properties
E
I
end
methods (Static)
function r = minus_(a,b)
r = a;
r.I = a.I-b.I;
end
end
methods
function r = minus(a,b)
for c = 1:numel(a)
r(c) = IV_class.minus_(a(c),b(c));
end
end
end
end
Of course, you should add tests to check whether a and b have the same length, you should allocate r and so on.

Summation of cell array of function handles

I have a cell array with size (n,1) that includes a function handle. Every cell has to include specific function handle and the summation of function handles in the previous cells. How can I perform this operation? To clarify this is an illustration.
A = cell(size(ones(n,1)));
for i = 1 : n
A{i,1} = #(x) A{i-1,1} + i .* x;
end
How to get A{n,1} at x = 2 (for example)
You are actually pretty close, but you need to add a special case for i = 1 and you need to call the function:
n = 10;
A = cell(size(ones(n,1)));
A{1,1} = #(x) 1 .* x;
for ii = 2 : n
A{ii,1} = #(x) A{ii-1,1}(x) + ii .* x;
end
I replaced i with ii, to avoid confusion with complex numbers. For the case n = 10:
>> A{n}(2)
ans =
110
Recalling #gnovice comment, you can also just make a cell array of the handles, and then call a function that sums them up to n:
N = 10;
A = cell(N,1);
A{1} = #(x) 1.*x;
for k = 2:N
A{k} = #(x) k.*x;
end
% the following function sums the output of A{1}(x) to A{n}(x):
f = #(n,x) sum(cellfun(#(c) c(x),A(1:n)));
The result:
>> f(5,2)
ans =
30
>> f(N,2)
ans =
110
This way, every change of the functions in A will have an immediate effect upon redefining f:
>> A{3} = #(x) -x;
>> f = #(n,x) sum(cellfun(#(c) c(x),A(1:n)));
>> f(N,2)
ans =
102
>> f(5,2)
ans =
22

Addition of two integer in binary representation

I would like to implement code which will add two integers by their binary representation.
For instance:
a = [1 1 1 0];
and
b = [1 0 1 1];
So I implemented the following algorithm:
function s=add_binary(a,b)
m=length(a);
s=zeros(m+1,0);
n=length(a);
c=0;
for ii=n:-1:1
d=floor((a(ii)+b(ii)+c)/2);
s(ii)=a(ii)+b(ii)+c-2*d;
c=d;
end
s(1)=c;
end
However, it returns this as a result:
s=add_binary(a,b)
s =
1 0 0 1
Here, there should be an additional 1 on the left, such that it would read:
1 1 0 0 1
Where am I making a mistake?
Since you're dealing with binary numbers, why not use logical operators?
function s = add_binary(a, b)
a = [0 a];
b = [0 b];
c = a&b;
while any(c)
b = xor(a, b);
a = circshift(c, -1);
c = a&b;
end
s = a+b;
end
And a test:
>> a = randi([0 1], [1 6])
a =
0 1 0 1 0 1
>> b = randi([0 1], [1 6])
b =
1 1 0 0 0 1
>> s = add_binary(a, b)
s =
1 0 0 0 1 1 0
here is my solution
function s=add_binary(a,b)
m=length(a);
s=zeros(m+1,1);
n=length(a);
c=0;
for ii=n:-1:1
d=floor((a(ii)+b(ii)+c)/2);
s(ii+1)=a(ii)+b(ii)+c-2*d;
c=d;
end
s(1)=c;
s=s';
end
>> s=add_binary(a,b)
s =
1 1 0 0 1
This problem was discussed in a 2011 question on MATLAB Answers. I'd like to mention 2 more solutions:
If you have the Communications System Toolbox, you can use bi2de and de2bi:
de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb')
If the amount of "digits" in the input is known (and reasonable), one solution could be to store all possible input combinations in some data-structure, which would facilitate rapid access. One such example is the MapN class (though it can just as easily be done with regular numeric arrays). I will provide a small example to show this idea (including a benchmark):
function allResults = q43095156(allResults)
if nargin == 0
% Let's store all combinations of 8 binary digits:
in = uint8(0:255);
out = uint16(in)+uint16(in.');
outB = logical(de2bi(out(:),'left-msb'));
[in1,in2] = meshgrid(in,in);
allResults = MapN(...
num2cell([num2cell(in1(:),2),num2cell(in2(:),2)],2),...
num2cell(outB,2));
end
benchmark(allResults);
end
function benchmark(allResults)
rng(43095156);
a = logical(randi([0 1],10,8,'uint8'));
b = logical(randi([0 1],10,8,'uint8'));
% Test:
R{5} = de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb');
R{4} = add_a_bunch_gnovice(a,b);
R{3} = add_a_bunch_Sardar(a,b);
R{2} = add_a_bunch_dato(a,b);
R{1} = getFromMap(a, b, allResults);
assert(isequal(R{:}));
% Benchmark:
a = logical(randi([0 1],1000,8,'uint8'));
b = logical(randi([0 1],1000,8,'uint8'));
fprintf(1,'\nSardar''s method:\t%f',timeit(#() add_a_bunch_Sardar(a, b) ));
fprintf(1,'\nDev-iL''s method:\t%f',timeit(#() getFromMap(a, b, allResults) ));
fprintf(1,'\ngnovice''s method:\t%f',timeit(#() add_a_bunch_gnovice(a, b) ));
fprintf(1,'\ndato''s method:\t\t%f',timeit(#() add_a_bunch_dato(a, b) ));
fprintf(1,'\nbi2de method:\t\t%f',timeit(#() de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb')));
end
function out = getFromMap(a,b,map)
out = cell2mat(values(map, num2cell([ num2cell(bi2de(a,'left-msb'),2),...
num2cell(bi2de(b,'left-msb'),2)],2)));
end
function out = add_a_bunch_gnovice(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_gnovice(a(ind1,:), b(ind1,:));
end
end
function out = add_a_bunch_Sardar(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_Sardar(a(ind1,:), b(ind1,:));
end
end
function out = add_a_bunch_dato(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_dato(a(ind1,:), b(ind1,:));
end
end
function s = add_binary_gnovice(a, b)
a = [0 a];
b = [0 b];
c = a&b;
while any(c)
b = xor(a, b);
a = circshift(c, -1);
c = a&b;
end
s = a+b;
end
function s = add_binary_Sardar(a,b)
s = logical(str2double(num2cell(dec2bin(bin2dec(num2str(a)) +...
bin2dec(num2str(b)), numel(a)+1))));
end
function s = add_binary_dato(a,b)
m = length(a);
s = zeros(m+1,1);
n = length(a);
c = 0;
for ii = n:-1:1
d = floor((a(ii)+b(ii)+c)/2);
s(ii+1) = a(ii)+b(ii)+c-2*d;
c = d;
end
s(1) = c;
s = logical(s.');
end
And the results with my x64 MATLAB R2017a # Win10 are:
Sardar's method: 0.336414
Dev-iL's method: 0.061656
gnovice's method: 0.022031
dato's method: 0.002123
bi2de method: 0.000356
So this should give us an idea which methods are faster (unless I messed the wrapper functions up greatly)...
The advantage of the MapN method would be noticeable if the computation of the sum was some other, costlier operation.
Use num2str to convert a and b to strings and use bin2dec to convert them to decimal. Then add them and convert the sum back to binary using dec2bin. Use num2cell to split the string and finally use str2double to get the desired result.
s=str2double(num2cell(dec2bin(bin2dec(num2str(a))+bin2dec(num2‌​str(b)))))
% Output for given a and b
%---------------------------
% s =
% 1 1 0 0 1

Obtain matrix of indices in octave / matlab

Given some multidimensional matrix A in Octave / Matlab,
What's the easiest way to get a matrix of the same size as A where all elements are replaced by their index along the k'th dimension
ie for the matrix
A =
ans(:,:,1) =
0.095287 0.191905
0.226278 0.749100
ans(:,:,2) =
0.076826 0.131639
0.862747 0.699016
I want a function f such that
f(A,1) =
ans(:,:,1) =
1 1
2 2
ans(:,:,2) =
1 1
2 2
f(A,2) =
ans(:,:,1) =
1 2
1 2
ans(:,:,2) =
1 2
1 2
and
f(A, 3) =
ans(:,:,1) =
1 1
1 1
ans(:,:,2) =
2 2
2 2
Also, given a sparse matrix B
What's the easiest way to get another sparse matrix of the same size where the nonzero elements are replaced by their index along the k'th dimension? (so same problem as above, but for only the nonzero elements)
Ideally I'm looking for a way which is well-vectorized for octave (meaning it doesn't explicitly loop over anything)
CLARIFICATION: For the sparse matrix one, I'm looking for a solution which does not involve creating a full size(B) matrix at any point
ndgrid() does what you want, although not in the format you are looking for. If you know the dims of the input A beforehand, you can use the following line to create the N-dimentional mesh grid:
% for matrix a where ndims(a) == 3
[x, y, z] = ndgrid (1:size(a,1), 1:size(a,2), 1:size(a,3));
% x is like f(a, 1)
% y is like f(a, 2)
% z is like f(a, 3)
You may be able to write a custom wrapper around ndgrid() to convert it to the function format you are looking for.
In case anyone's curious, since I didn't know about ndgrid, here's the answer I came up with:
function [y] = indices(a,k)
s = size(a);
n = s(k);
D = length(s);
x = permute(a,[k,1:(k-1),(k+1):D]);
y = reshape(x,n,[]);
y = diag(1:n) * ones(size(y));
y = reshape(y,size(x));
y = permute(y,[(2:k),1,(k+1):D]);
endfunction
function [y] = spindices(a,k)
s = size(a);
n = s(k);
D = length(s);
x = permute(a,[k,1:(k-1),(k+1):D]);
y = reshape(x,n,[]);
y = spdiag(1:n) * spones(y);
y = reshape(y,size(x));
y = permute(y,[(2:k),1,(k+1):D]);
endfunction

Píxel loop of a multispectral image

I have a multispectral image with 6 bands.
imagen1=imread('re_2008.tif')
size2=size(imagen1);
nrow= size2(1);
ncol= size2(2);
nband= size2(3);
What I want to do is get every pixel of every band (in the same position) with their value, do an interpolation and with a new value located in other wavelength, replace it. Maybe you understand me more if I show you the code.
imagen3_2 = zeros(nrow, ncol, nband);
var1= [1 2 3 4 5 6]'; %'
for row=1:nrow;
for column=1:ncol;
for band=1:nband;
v = imagen1(nrow(1),nband(2),:); v = v(:);
t= 0:100;
interplan= interp1(var1, v, t,'cubic');
y5 = interplan(5); % I get the value of the interpolation on this position
y12 = interplan(12);
y20 = interplan(20);
y50 = interplan(50);
y80 = interplan(80);
y90 = interplan(90);
imagen3_2(:,:,1)= (y5); % and I replace it
imagen3_2(:,:,2)= (y12);
imagen3_2(:,:,3)= (y20);
imagen3_2(:,:,4)= (y50);
imagen3_2(:,:,5)= (y80);
imagen3_2(:,:,6)= (y90);
end
end
end
I get the same value as a result, not for every pixel.
Thanks in advance,
How about
imagen3_2 = zeros(nrow, ncol, nband);
var1= [1 2 3 4 5 6]'; %'
for row=1:nrow;
for column=1:ncol;
v = imagen1(row, column, :); v = v(:);
t= 0:100;
interplan= interp1(var1, v, t,'cubic');
y5 = interplan(5); % I get the value of the interpolation on this position
y12 = interplan(12);
y20 = interplan(20);
y50 = interplan(50);
y80 = interplan(80);
y90 = interplan(90);
imagen3_2(row,column,1)= (y5); % and I replace it
imagen3_2(row,column,2)= (y12);
imagen3_2(row,column,3)= (y20);
imagen3_2(row,column,4)= (y50);
imagen3_2(row,column,5)= (y80);
imagen3_2(row,column,6)= (y90);
end
end
I see that Shai already answered your question, however if you are not really interested in variables y5, y12 etc. there is a way to make the code compacter and easier to maintain:
imagen3_2 = zeros(nrow, ncol, nband);
var1= [1 2 3 4 5 6]'; %'
for row=1:nrow;
for column=1:ncol;
v = imagen1(row, column, :); v = v(:);
t= 0:100;
interplan= interp1(var1, v, t,'cubic');
y = [5 12 20 50 80 90];
for i = 1:length(y)
imagen3_2(row,column, i)= interplan(y(i));% repace interpolation value
end
end
end
For efficiency, try to avoid loops in Matlab, you can try something like this:
x = [1 2 3 4 5 6];
y = imread('re_2008.tif');
y_size = size((y(:,:,1)));
xi = 0:100;
yi = zeros([y_size,numel(xi)]);
for i_pix=1:prod(y_size)
[aux_x,aux_y] = ind2sub(y_size,i_pix);
yi(aux_x,aux_y,:) = interp1(x,squeeze(y(aux_x,aux_y,:)),xi,'cubic');
end
Or even like this:
x = [1 2 3 4 5 6];
y = imread('re_2008.tif');
xi = 0:100;
yi = arrayfun(#(y1,y2,y3,y4,y5,y6) interp1(x,[y1,y2,y3,y4,y5,y6],xi,'cubic'), ...
y(:,:,1), y(:,:,2), y(:,:,3), y(:,:,4), y(:,:,5), y(:,:,6))
I couldn't check the code, so there could be errors; but it is just to give ideas about other kinds of implementation.