XOR on rising edge of two arrays
1 view (last 30 days)
Show older comments
Mohammad Zulqarnain
on 26 Dec 2020
Commented: Bruno Luong
on 27 Dec 2020
Hello,
I have two arrays containing 0's & 1's. I want to find xor of the two arrays with two additional conditions:
- The xor has to be done only in the case of rising edges.
- To distinguish which array is having rising edge first, I have assigned outputs as 3 levels i.e. 1, 0, -1
Considering an example, if 'a' and 'b' are input arrays and PWM3 is the output array;
a = [0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1]
b = [0,0,0,1,1,1,1,0,0,1,1,1,1,0,1,1,1]
So, the output has be ;
PWM3 = [0,1,1,0,0,0,0,0,1,0,0,0,0,0,-1,-1,0] , so if 'a' has rising edge first output is '1', if 'b' has rising edge first output is '-1', else the output is '0'.
I am trying as given below, but I can't figure out how to take into consideration rising edges only. If someone has any idea about it, please let me know.
Thanks
for p= 1:length(a)
if(a(p)== 1 && b(p)== 0)
PWM3(p) = 1;
elseif (a(p)== 0 && b(p)== 1)
PWM3(p) = -1;
else
PWM3(p) = 0;
end
end
2 Comments
KALYAN ACHARJYA
on 27 Dec 2020
If inputs are a and b
a = [0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1]
b = [0,0,0,1,1,1,1,0,0,1,1,1,1,0,1,1,1]
What would be expected output?
Accepted Answer
Bruno Luong
on 27 Dec 2020
Edited: Bruno Luong
on 27 Dec 2020
a = [0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1];
b = [0,0,0,1,1,1,1,0,0,1,1,1,1,0,1,1,1];
a0 = [0; a(:)];
b0 = [0; b(:)];
i = find(diff(a0) | diff(b0));
js = find(~a0(i) & ~b0(i));
c = a(i)-b(i);
c = c(:);
i(end+1) = 0;
i = [i(js); i(js+1)];
c = [c(js); -c(js)];
k = i > 0;
PWM3 = cumsum(accumarray(i(k), c(k), [length(a),1])).'
3 Comments
Bruno Luong
on 27 Dec 2020
Jan, same old receipt after all this years. Glad you enjoy the meal as I do. Thanks.
More Answers (3)
Jan
on 27 Dec 2020
Edited: Jan
on 27 Dec 2020
a = [0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1];
b = [0,0,0,1,1,1,1,0,0,1,1,1,1,0,1,1,1];
ab = a + b;
[v, n, p] = RunLength(ab == 1);
rise = strfind(ab, [0, 1]) + 1;
v((v == 1) & ~ismember(p, rise)) = 0;
PWM3 = RunLength(v, n) .* sign(a - b)
If runtime is less important or you do not have a C compiler installed, use:
% [EDITED: Function adjusted to reply row vectors]
function [out1, out2, out3] = RunLength(in1, in2)
% RUNLENGTH - RLE coding as M-function
% Author: Jan Simon, Heidelberg, (C) 2013-2020
% $License: BSD (use/copy/change/redistribute on own risk, mention the author) $
if (nargin == 1) % Encoding: [x] -> [b, n, p] --------------------
x = in1(:).';
d = [true, diff(x) ~= 0]; % TRUE if values change
b = x(d); % Elements without repetitions
k = find([d, true]); % Indices of changes
n = diff(k); % Number of repetitions
out1 = b;
out2 = n;
out3 = k(1:length(k) - 1);
else % Decoding: [b, n] -> [x] =======================
b = in1(:).'; % More convenient names for inputs
n = in2;
len = length(n); % Number of bins
d = cumsum(n); % Cummulated run lengths
index = zeros(1, d(len)); % Pre-allocate
index(d(1:len-1)+1) = 1; % Get the indices where the value changes
index(1) = 1; % First element is treated as "changed" also
index = cumsum(index); % Cummulated indices
out1 = b(index);
end
end
2 Comments
Jan
on 27 Dec 2020
A second approach:
a = [0,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1];
b = [0,0,0,1,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,1];
want = [0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,-1,-1,0] % correct?
raise = strfind(or(a,b), [false, true]) + 1;
fall = strfind(xor(a,b), [true, false]) + 1;
[v, p] = sort([raise, fall]);
m = strfind(p > numel(raise), [false, true]);
q = zeros(size(a));
q(v(m)) = 1;
q(v(m + 1)) = -1;
PWM3 = cumsum(q) .* sign(a - b)
Walter Roberson
on 27 Dec 2020
if state == S_rising_A
if A(K) == 0
if B(K) == 0
state = S_zero %A was up, has fallen, B is not up, we are all 0
out(K) = 0
else
state = S_rising_B %A was up but fell, B just rose
out(K) = -1
end
elseif B(K) == 0
state = S_rising_A %A is still up, B is still down
out(K) = 1
else
state = S_clearing %A is up, B just rose, time to clear trailing edge
out(K) = 0
end
elseif state == S_rising_B
if A(K) == 0
if B(K) == 0
state = S_zero %A is not up, B was up but fell, we are all 0
out(K) = 0
else
state = S_rising_B %A is still down, B is still up
out(K) = -1
end
elseif B(K) == 0
state = S_rising_A %A just rose, B was up but just fell
out(K) = 1
else
state = S_clearing %A just rose, B is up, time to clear trailing edge
out(K) = 0
end
elseif state == S_zero
if A(K) == 0
if B(K) == 0
state = S_zero %both were down and stayed down
out(K) = 0
else
state = S_rising_B %both were down but B rose
out(K) = -1
end
elseif B(K) == 0
state = S_rising_A %both were down but A rose
out(K) = 1
else
state = S_clearing %both were down but both rose, time to clear trailing edge
out(K) = 0
end
elseif state == S_clearing
if A(I) == 0
if B(K) == 0
state = S_zero %clearing trailing edge but both were zero, stop clearing
out(K) = 0
else
state = S_clearing %clearing continuation of trailing edge
out(K) = 0
end
elseif B(K) == 0
state = S_clearing %clearing continuation of trailing edge
out(K) = 0
else
state = S_clearing %clearing continuou of trailing edge
out(K) = 0
end
end
.... Actually the above has problems.
I had to decide what to do in a case such as
1 1 1 1 0 0 0
0 0 0 0 1 1 1
which I decided should be output 1 1 1 1 -1 -1 -1 -1 -- that is, that the end of the A is considered to be "before" the beginning of the B and so the edge has ended for the first and just started for the second. So that logic is in place.
But at the same time, I had to decide what to do for
1 1 1 1 0 0 0
0 1 0 0 1 1 1
I coded the initial part as initial 1 for the A, then because both were 1 that we need to go into clearing mode, so 0 0 0 to clear the rest of the A edge. Then while we are in that clearing mode dealing with the trailing A, we ended A and started B at the same time. For consistency with the above decision that this is two distinct events with no overlap, we should stop clearing and say that we are inside a B edge, for an overall output of [1 0 0 0 -1 -1 -1] -- but the logic I implemented does not keep track of which edge(s) we are removing the trailing part of, so it just thinks "Oh, we haven't seen a clear break yet, so we must still be in clearing mode". That is arguably a bug. There should probably be an S_clearing_A state, an S_clearing_B state, and an S_clearing_both state .
.... I suspect the entire logic could be made a lot shorter by referring to the previous entries in the array. I happen to have a background in Finite State Machines, where you encode what is happening as different states without any explicit lookbacks.
... I bet it could be all coded as regular expressions...
Question for you: if the input starts with a 1, is that to be counted as a rising edge? Is there an implicit 0 before all the inputs? Or is there an implicit "we came in in the middle of something and we won't assume any rising edges until we have seen a definite absense of edges" ?
2 Comments
Walter Roberson
on 27 Dec 2020
S_* are arbitrary unique scalar values, such as categoricals or enumerations or plain 1, 2, etc. state would be initialized to S_clearing for the case where there is no implied 0.
If only one value can change at a time then the code can be simpler. I will work it out later.
See Also
Categories
Find more on Linear Programming and Mixed-Integer Linear Programming in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!