Behavior of "unique" with mixed complex numbers

I have a large set of complex number that I want to map to an integer grid on the complex plane, removing redundant values. A small subset of the data looks like:
Atest=[-12.9753 - 0.8003i;
-12.9938 - 0.4003i;
-13.0000 + 0.0000i;
-12.9938 + 0.4003i;
12.9938 + 0.4003i;
13.0000 + 0.0000i;
12.9938 - 0.4003i;];
I use round to map to the grid:
Around=round(Atest)
Around =
-13.0000 - 1.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
13.0000 + 0.0000i
13.0000 + 0.0000i
13.0000 + 0.0000i
I then use unique to remove the redundant values:
Aunique=unique(Around,'stable')
Aunique =
-13.0000 - 1.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
13.0000 + 0.0000i
Clearly, the result is not unique: the value -13 appears twice. If I apply unique to just the las 6 values of Around (the real values) I obtain the expected results:
Aunique=unique(Around(2:end),'stable')
Aunique =
-13
13
I would appreciate any suggestions for getting the unique values of an array with mixed real and complex values.

11 Comments

"Clearly, the result is not unique: the value -13 appears twice"
Learn more about floating point comparison and uniquetol function
I looked at uniquetol, but it does not work on complex numbers. Round is supposed to convert floating point to integer, and if you look at the real and imaginary components separately they are integers (see response from Marco Riani). Apparently, integers in a complex number are treated differently. Interestingly, I have only seen this behavior when the imaginary component rounds to zero. For other values, unique has worked for complex numbers.
Hmmm you are right. I apologize.
I though unique should work as intended with complex numbers, obviously it's not.
And the doc of uniquetol doesn't say anything about requirement of input array to be real.
To me it's a design flaw.
Could this have something to do with how the round function leaves the sign bit? I'm not sure, but I did notice that:
>> Around
Around =
-13.0000 - 1.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
13.0000 + 0.0000i
13.0000 + 0.0000i
13.0000 + 0.0000i
>> format hex
>> Around
Around =
c02a000000000000 bff0000000000000i
c02a000000000000 8000000000000000i
c02a000000000000 0000000000000000i
c02a000000000000 0000000000000000i
402a000000000000 0000000000000000i
402a000000000000 0000000000000000i
402a000000000000 8000000000000000i
>> Aunique
Aunique =
c02a000000000000 bff0000000000000i
c02a000000000000 8000000000000000i
c02a000000000000 0000000000000000i
402a000000000000 0000000000000000i
>> format short
>> Aunique
Aunique =
-13.0000 - 1.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
13.0000 + 0.0000i
So it appears that the Around(2) and Around(3) might not be unique because of the sign bit on the imaginary part?
But, looking at Marco's answer I'm not sure that's the case:
>> [real(Around) imag(Around)]
ans =
c02a000000000000 bff0000000000000
c02a000000000000 8000000000000000
c02a000000000000 0000000000000000
c02a000000000000 0000000000000000
402a000000000000 0000000000000000
402a000000000000 0000000000000000
402a000000000000 8000000000000000
So imag preserves the sign bit on the imaginary part of Around(2), but unique doesn't seem to care about that using Marco's answer:
>> unique([real(Around) imag(Around)],'rows')
ans =
-13 -1
-13 0
13 0
>> format hex
>> ans
ans =
c02a000000000000 bff0000000000000
c02a000000000000 8000000000000000
402a000000000000 0000000000000000
Maybe unique works differently for complex and real inputs wrt to how it treats the sign bit on a value of zero?
Ah, I believe in Paul's explanation.
>> Around=round(Atest)
Around =
-13.0000 - 1.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
13.0000 + 0.0000i
13.0000 + 0.0000i
13.0000 + 0.0000i
>> Aunique=unique(Around,'stable')
Aunique =
-13.0000 - 1.0000i
-13.0000 + 0.0000i
-13.0000 + 0.0000i
13.0000 + 0.0000i
>> Aunique_c=-1i*unique(1i*Around,'stable')
Aunique_c =
-13.0000 - 1.0000i
-13.0000 + 0.0000i
13.0000 + 0.0000i
>>
In which case I call it a bug of UNIQUE, since it should NOT considere the sign bit whereas it's on real or imag part.
I play a little more and it seems the result depend on other thing beside the sign bit. I'm stumped.
FYI I report the bug.
I'm confused as to why Around(2) and Around(3:4) are not unique, but Around(7) and Around(5:6) are unique? Shouldn't the same rule apply?
Around =
c02a000000000000 bff0000000000000i
c02a000000000000 8000000000000000i
c02a000000000000 0000000000000000i
c02a000000000000 0000000000000000i
402a000000000000 0000000000000000i
402a000000000000 0000000000000000i
402a000000000000 8000000000000000i
Maybe this is one other thing that you already noticed, but flipping the matrix not only changes which entries are selected as unique, but also changes the number of unique entries?
>> Aunique=unique(Around,'stable')
Aunique =
c02a000000000000 bff0000000000000i
c02a000000000000 8000000000000000i
c02a000000000000 0000000000000000i
402a000000000000 0000000000000000i
>> Aunique=unique(flipud(Around),'stable')
Aunique =
402a000000000000 8000000000000000i
c02a000000000000 0000000000000000i
c02a000000000000 bff0000000000000i
Very troubling that the numel of the result depends on the order of input.
Will you post back here when you get a response from tech support?
"I'm confused as to why Around(2) and Around(3:4) are not unique, but Around(7) and Around(5:6) are unique? Shouldn't the same rule apply?"
When I wanted to construct a MWE for bug reporting, that's what I find out as well.
Thus I wrote "it seems the result depend on other thing beside the sign bit". It depends on globally on the array itself, and not only on the elements with zero sign bit.
Pretty much a nasty bug.
Bruno, Paul, thank you for delving into this deeper than I have. I, too, will be interested in knowing what tech support has to say.
Here is the reply from tech support
"Thank you for your inquiry and provided clear reproduction examples. It does appear as though this is a bug with the unique function executed on rounded complex arrays. The Development team has been informed of this bug and will investigate further.
Given the information above, I will close this case as 'Bug/Enhancement Submitted'. From a Technical Support perspective the case is now closed. From a Development standpoint, on the other hand, the matter is still open. It is being investigated and will be considered for a future Release or Update. Should this bug be fixed, you will be personally notified via email. Then, the status of this service request will be automatically changed to 'Bug Fixed/Enhancement Complete'. "
So obviously it's abug and they will fix it in future release.
Another mail from tech:
"I just wanted to offer you a follow up email regarding a workaround for your use case. If you add complex(0)to 'Around', then call unique, it will give the right answer. For example:"
A = [-12.9753 - 0.8003i; -12.9938 - 0.4003i; -12.9938 + 0.4003i; 12.9938 + 0.4003i];
B = round(A) + complex(0);
C = unique(B);
But we already knew this solution from the cross-thread of atan2 and sign bit.

Sign in to comment.

 Accepted Answer

Please let me know if I understood correctly your qestion
Atest=[-12.9753 - 0.8003i;
-12.9938 - 0.4003i;
-13.0000 + 0.0000i;
-12.9938 + 0.4003i;
12.9938 + 0.4003i;
13.0000 + 0.0000i;
12.9938 - 0.4003i;];
Around=round(Atest);
A=[real(Around) imag(Around)];
unique(A,'rows')
ans =
-13 -1
-13 0
13 0

2 Comments

Marco, thank you, this works as I had hoped. I would be interested to know why the round function appears to be outputting integers for the real and imaginary components, but they are treated as floating point when combined into a complex number.

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2016b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!