5 views (last 30 days)

x = randn(8,1);

z = fft(x);

assert(isreal(z(1)),'First');

y = arrayfun(@isreal,z);

assert(y(1),'Second');

In this snippet, I am trying to create a function which will return those elements in an array that are real.

The first assert passes, the first element of z is real.

The second assert fails as y thinks that every element in the array is not real.

Why?

How do I write a function that check whether each element in an array is real. Do I have to use a loop?

Guillaume
on 7 Aug 2019

Note that the problem you highlight has nothing to do with isreal. I guess that you've uncovered an unexpected implementation detail of arrayfun. When dealing with complex numbers, it is not exactly equivalent to a loop.

First, some non-random testing data:

thetad = (0:90:360)';

z = cosd(thetad) + 1i*sind(thetad)

Simple test, let's extract each number into a cell array with a loop and with arrayfun:

>> carrayfun = arrayfun(@(x) x, z, 'UniformOutput', false)

carrayfun =

5×1 cell array

{[ 1 + 0i]}

{[ 0 + 1i]}

{[-1 + 0i]}

{[ 0 - 1i]}

{[ 1 + 0i]}

As you can see, each element is still complex, even those with imaginary part 0.

Now, with the equivalent loop:

>> cloop = cell(size(z)); for idx = 1:numel(z), cloop{idx} = z(idx); end; cloop

cloop =

5×1 cell array

{[ 1]}

{[0 + 1i]}

{[ -1]}

{[0 - 1i]}

{[ 1]}

The pure real elements are extracted as pure real. Note that num2cell does the same:

>> num2cell(z)

ans =

5×1 cell array

{[ 1]}

{[0 + 1i]}

{[ -1]}

{[0 - 1i]}

{[ 1]}

So, it must be an oddity of arrayfun, probably some optimisation detail. Probably worthy of a bug report to mathworks (if only so that the documentation explains what happens).

Guillaume
on 8 Aug 2019

I didn't even know you could store complex numbers in integer types! I guess why not, a complex is just a pair of numbers. On the other hand, I have a hard time seeing the need for it.

Anyway, I've discussed this with Mathworks support. Whether or not it will lead to any change, nobody knows. It boils down to a difference in implementation, plain indexing and num2cell (and maybe other things) remove the complex part to optimise storage whereas arryafun doesn't. In my opinion, they should behave the same but it's such an edge case that I'm not going to worry about it. It only impacts the rare functions that actually look at how the numbers are stored instead of what the numbers actually are (so pretty much just isreal, but it may also affect people writing mex).

From a mathematical point of view, the result is the same, 1 + 0i, and 1 are the same numbers, and to go back to the original question, Stephen is correct, the proper way to test if elements of an array are pure real is not with isreal. The documentation of isreal actually tells you how to do that:

z == real(z)

which is simpler than arrayfun and is not affected by the way the numbers are stored.

Bruno Luong
on 8 Aug 2019

Well the integer/complex field is a quite interesting math object, you can do operation like any better-known fields, but have some odd (but interesting) properties such as decomposition in prime "numbers" is not unique. I believe Gauss is the first one who are interested in such field.

People writing MEX interested in internal storage, but I think in case I don't care at all about how ARRAYFUN/CELLFUN behaves. I really use them, or when I use thme is by laziness.

I guess the odd effect we are discussing is due to TMW attempt to accelerate at all cost ARRAYFUN. I don't need them to document such special behavior, they are free to do whatevever they like.

James Tursa
on 8 Aug 2019

Bruno Luong
on 7 Aug 2019

Edited: Bruno Luong
on 7 Aug 2019

Guys ISREAL tests whereas the internal storage of an array does not allocated memory for the imaginary part, it is NOT testing the imaginary part is 0.

In recent MATLAB you can do this:

>> a = 1

a =

1

>> isreal(a)

ans =

logical

1

>> b=complex(a)

b =

1.0000 + 0.0000i

>> b==a

ans =

logical

1

>> isreal(b)

ans =

logical

0

Opportunities for recent engineering grads.

Apply Today
## 3 Comments

## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/475262-arrayfun-isreal-fails-how-to-fix#comment_732810

⋮## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/475262-arrayfun-isreal-fails-how-to-fix#comment_732810

## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/475262-arrayfun-isreal-fails-how-to-fix#comment_732834

⋮## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/475262-arrayfun-isreal-fails-how-to-fix#comment_732834

## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/475262-arrayfun-isreal-fails-how-to-fix#comment_733002

⋮## Direct link to this comment

https://es.mathworks.com/matlabcentral/answers/475262-arrayfun-isreal-fails-how-to-fix#comment_733002

Sign in to comment.