Got Questions? Get Answers.
Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Arrayfun bug?

Subject: Arrayfun bug?

From: Oleg Komarov

Date: 22 Jan, 2010 23:49:06

Message: 1 of 24

Is this a bug or an expected behaviour?

% Vector with one imaginary element
In = rand(10,1);
In(1) = sqrt(-1);
isreal(In)

ans =
     0

>> arrayfun(@isreal,In)
ans =
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0

>> IDX = false(numel(In),1);
for n = 1:numel(In)
    IDX(n) = isreal(In(n));
end
disp(IDX)
     0
     1
     1
     1
     1
     1
     1
     1
     1
     1

Oleg

Subject: Arrayfun bug?

From: Matt J

Date: 23 Jan, 2010 00:50:21

Message: 2 of 24

"Oleg Komarov" <oleg.komarovRemove.this@hotmail.it> wrote in message <hjddhi$p6n$1@fred.mathworks.com>...
> Is this a bug or an expected behaviour?

I don't know if it's intended, but I think I understand the subtlety. Consider, the following for example

>> arrayfun(@(x) isreal(x(1)),In)

ans =

     0
     1
     1
     1
     1
     1
     1
     1
     1
     1



Basically, the idea is that when a piece of data is stored in an array, it undergoes a conversion to a class that is common to the rest of the elements of the array, with certain accompanying attributes, e.g., complex or non-complex. Therefore, because In contains some strictly complex elements, all other elements of In must be internally represented this way as well. Accordingly, arrayfun() considers all components of In to be complex.

However, when you extract an element of In and copy it to a separate scalar variable, MATLAB can convert the data to the most sensible representation for that scalar. That's why my version above, which pre-extracts the elements to a separate variable before applying the isreal() test, gives the expected result, as does the 3rd in your series of tests.



ll elements of an array have to have certain attributes in common, e.g. double or single, logical or numeric, complex or nrot-ca omplex
Consequenctly, even when a piece of data is stored


all elements of an array are considered by MATLAB to be either complex or not.

Subject: Arrayfun bug?

From: Matt J

Date: 23 Jan, 2010 00:58:05

Message: 3 of 24

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <hjdh4d$8ka$1@fred.mathworks.com>...

>
> ll elements of an array have to have certain attributes in common, e.g. double or single, logical or numeric, complex or nrot-ca omplex
> Consequenctly, even when a piece of data is stored
>
>
> all elements of an array are considered by MATLAB to be either complex or not.

The above bit, by the way, was scrap text that I inadvertently left in my post :-)

Subject: Arrayfun bug?

From: Matt Fig

Date: 23 Jan, 2010 01:03:02

Message: 4 of 24

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message
> I don't know if it's intended, but I think I understand the subtlety. Consider, the following for example
>
> >> arrayfun(@(x) isreal(x(1)),In)
>
> ans =
>
> 0
> 1
> 1
> 1
> 1
> 1
> 1
> 1
> 1
> 1
>
>
>
> Basically, the idea is that when a piece of data is stored in an array, it undergoes a conversion to a class that is common to the rest of the elements of the array, with certain accompanying attributes, e.g., complex or non-complex. Therefore, because In contains some strictly complex elements, all other elements of In must be internally represented this way as well. Accordingly, arrayfun() considers all components of In to be complex.
>
> However, when you extract an element of In and copy it to a separate scalar variable, MATLAB can convert the data to the most sensible representation for that scalar. That's why my version above, which pre-extracts the elements to a separate variable before applying the isreal() test, gives the expected result, as does the 3rd in your series of tests.
>
>
>
> ll elements of an array have to have certain attributes in common, e.g. double or single, logical or numeric, complex or nrot-ca omplex
> Consequenctly, even when a piece of data is stored
>
>
> all elements of an array are considered by MATLAB to be either complex or not.



To me this does seem like a bug because of this line in the doc:

"A = arrayfun(fun, S) applies the
function specified by fun to each element of array S,
and returns the results in array A. The value A returned
by arrayfun is the same size as S, and
the (I,J,...)th element of A is equal
to fun(S(I,J,...))"

I read this as
>> S = rand(3,1);
>> S(1) = sqrt(-1);
>> A = arrayfun(@isreal,S);
>> B = [isreal(S(1));isreal(S(2));isreal(S(3))]; % Or the FOR loop.

Now A and B should be equal. They are not.

Subject: Arrayfun bug?

From: Matt J

Date: 23 Jan, 2010 01:18:02

Message: 5 of 24

"Matt Fig" <spamanon@yahoo.com> wrote in message <hjdhs6$np1$1@fred.mathworks.com>...

> To me this does seem like a bug because of this line in the doc:
>
> "A = arrayfun(fun, S) applies the
> function specified by fun to each element of array S,
> and returns the results in array A. The value A returned
> by arrayfun is the same size as S, and
> the (I,J,...)th element of A is equal
> to fun(S(I,J,...))"
================

That is a genuine inconsistency, but one could equally well suppose the documentation, and not the software, is in error. I guess we'll have to let Steve L. or someone else of authority make the official pronouncement.

Subject: Arrayfun bug?

From: Matt J

Date: 23 Jan, 2010 02:12:21

Message: 6 of 24

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <hjdioa$glq$1@fred.mathworks.com>...

Here's another example, perhaps similarly counter-intuitive:



>> a=sparse([1,2,3])

a =

   (1,1) 1
   (1,2) 2
   (1,3) 3


>> spfun(@(ai) issparse(ai),a)

ans =

   All zero sparse: 1-by-3

Subject: Arrayfun bug?

From: James Tursa

Date: 23 Jan, 2010 06:29:03

Message: 7 of 24

"Matt Fig" <spamanon@yahoo.com> wrote in message <hjdhs6$np1$1@fred.mathworks.com>...
>
> To me this does seem like a bug because of this line in the doc:
>
> "A = arrayfun(fun, S) applies the
> function specified by fun to each element of array S,
> and returns the results in array A. The value A returned
> by arrayfun is the same size as S, and
> the (I,J,...)th element of A is equal
> to fun(S(I,J,...))"

MATLAB considers a variable to be complex if the imaginary part is physically present in memory, whether or not the imaginary part is zero. Whenever you do an operation with a complex variable, MATLAB examines the result and if all the imaginary parts are zero, then it physically deletes them from memory and the variable becomes "real". So for the first example that started this thread:

>> format debug
>> In = rand(1,2) % In starts out real, with no imaginary part
In =
Structure address = f66d6a0
m = 1
n = 2
pr = fd79890
pi = 0 % The address of the imaginary part is NULL, nothing is physically there
    0.6068 0.4860
>> In(1) = i % make one of the elements complex
In =
Structure address = f66d6a0
m = 1
n = 2
pr = fd79890
pi = fd795f0 % Now there is physically an imaginary part for *all* elements
        0 + 1.0000i 0.4860
>> format short
>> isreal(In) % Imaginary part is physically present, so variable is not real
ans =
     0
>> In1 = In(1)
In1 =
Structure address = fd66e20
m = 1
n = 1
pr = 1cda240
pi = 1cda260
        0 + 1.0000i
>> isreal(In1)
ans =
     0

The operation of In1 = In(1) takes this element and copies it into a new variable. In the act of copying MATLAB examines the imaginary part and sees that the imaginary part is non-zero, so it physically stores the imaginary part (pi address is not NULL). Then the isreal function returns the expected result.

>> In2 = In(2)
In2 =
Structure address = fd6c320
m = 1
n = 1
pr = 1cda268
pi = 0
    0.4860
>> isreal(In2)
ans =
     1

The operation of In2 = In(2) takes this element and copies it into a new variable. In the act of copying MATLAB examines the imaginary part and sees that the imaginary part is zero, so it does not physically store an imaginary part. Hence the variable becomes "real".

>> arrayfun(@isreal,In)
ans =
     0 0

This is somewhat of an inconsistency, based on the description above, since the result is *not* the same as doing isreal on each of the elements individually. My obvious conclusion would be that MATLAB is not actually creating the individual elements as separate variables (that would be a tremendous waste of time), but is just doing the operation directly on the memory associated with In, hence everything is seen as complex.

Interestingly, MATLAB does *not* check the results of a mex routine, so if I use this file to create a complex variable with both parts zero:

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxCOMPLEX);
}

And run it you get the following:

>> z = zerocomplex
z =
Structure address = feaf220
m = 1
n = 1
pr = 1cda3b8
pi = 1cdaa88
     0
>> isreal(z)
ans =
     0

So z physically has both real and imaginary parts stored in memory, hence the isreal function returns 0 even though the imaginary part is 0. But do any operation with z on the MATLAB side that results in a pure real result and then MATLAB will check the result and NULL out the imaginary part:

>> z + 0
ans =
Structure address = f66d3a0
m = 1
n = 1
pr = 1cda9b8
pi = 0 % Imaginary part has been NULLed out
     0
     0
>> isreal(ans)
ans =
     1

James Tursa

Subject: Arrayfun bug?

From: Oleg Komarov

Date: 23 Jan, 2010 13:16:03

Message: 8 of 24

I brought to your attention those examples (1st msg) because of the inconsistency found in the help of arrayfun.
Generally I don't work with imaginary numbers but it happened to come accross some unexpected results. I tried to identify which part of my large dataset (more than 10e6 units of analysis) caused the entire set of results to become imaginary and I couldn't find but with a loop...
As you all pointed out it makes sense according to memory storage principles...still it doesn't help.

Oleg

Subject: Arrayfun bug?

From: Bruno Luong

Date: 23 Jan, 2010 13:45:05

Message: 9 of 24

"Oleg Komarov" <oleg.komarovRemove.this@hotmail.it> wrote in message <hjesqj$iu6$1@fred.mathworks.com>...
> I brought to your attention those examples (1st msg) because of the inconsistency found in the help of arrayfun.
> Generally I don't work with imaginary numbers but it happened to come accross some unexpected results. I tried to identify which part of my large dataset (more than 10e6 units of analysis) caused the entire set of results to become imaginary and I couldn't find but with a loop...
> As you all pointed out it makes sense according to memory storage principles...still it doesn't help.

Well in principle there is no reason to apply ISREAL on individual elements of an array. If they are gather in the same array they should belong to the same "space". If the complex part of one of them is not zero, then all of them should be considered as complex number.

In the same token, we cannot gather [int32(1:10) pi] and expect they have different discrete/continuous nature.

But if you insist, why not do a simple test:

imag(In)==0

This is fast because no calling of ARRAYFUN.

Bruno

Subject: Arrayfun bug?

From: Oleg Komarov

Date: 23 Jan, 2010 15:11:03

Message: 10 of 24

"Bruno Luong"
> "Oleg Komarov"
> > I brought to your attention those examples (1st msg) because of the inconsistency found in the help of arrayfun.
> > Generally I don't work with imaginary numbers but it happened to come accross some unexpected results. I tried to identify which part of my large dataset (more than 10e6 units of analysis) caused the entire set of results to become imaginary and I couldn't find but with a loop...
> > As you all pointed out it makes sense according to memory storage principles...still it doesn't help.
>
> Well in principle there is no reason to apply ISREAL on individual elements of an array. If they are gather in the same array they should belong to the same "space". If the complex part of one of them is not zero, then all of them should be considered as complex number.
>
> In the same token, we cannot gather [int32(1:10) pi] and expect they have different discrete/continuous nature.
>
> But if you insist, why not do a simple test:
>
> imag(In)==0
>
> This is fast because no calling of ARRAYFUN.
>
> Bruno
"Well in principle there is no reason to apply ISREAL on individual elements of an array."
Real numbers as all of you know are a subset of complex numbers but i won't go far in the discussion since this is merely a practical problem.
In fact, I agree that gathering different classes cannot be done without a rule of dominance (for example: int8 upon double) but this doesn't mean that if the help of a function says that every element undergoes the same treatement the for loop should behave differently (or is the arrayfun that is behaving differently, to cut on speed and memory allocation?!).

Btw Bruno,
thanks for this hint:
imag(In)==0

Oleg

Subject: Arrayfun bug?

From: Matt J

Date: 23 Jan, 2010 15:34:02

Message: 11 of 24

"Oleg Komarov" <oleg.komarovRemove.this@hotmail.it> wrote in message <hjf3i6$nn5$1@fred.mathworks.com>...

> In fact, I agree that gathering different classes cannot be done without a rule of dominance (for example: int8 upon double) but this doesn't mean that if the help of a function says that every element undergoes the same treatement the for loop should behave differently (or is the arrayfun that is behaving differently, to cut on speed and memory allocation?!).
=======================

If it's intentional behavior, the documentation does need to be clarified, as we said earlier. However, for arrayfun to truly behave like the for-loop, there would have to be an additional call to subsref(), for each element, and that would indeed slow things down. Still, if that's what it takes to achieve certain expected behavior...

Perhaps they should add an additional parameter to let you force this, e.g.

arrayfun(@isreal,In,'ProcessAsScalars',1);

Subject: Arrayfun bug?

From: James Tursa

Date: 23 Jan, 2010 22:30:06

Message: 12 of 24

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <hjf4ta$ii5$1@fred.mathworks.com>...
> "Oleg Komarov" <oleg.komarovRemove.this@hotmail.it> wrote in message <hjf3i6$nn5$1@fred.mathworks.com>...
>
> > In fact, I agree that gathering different classes cannot be done without a rule of dominance (for example: int8 upon double) but this doesn't mean that if the help of a function says that every element undergoes the same treatement the for loop should behave differently (or is the arrayfun that is behaving differently, to cut on speed and memory allocation?!).
> =======================
>
> If it's intentional behavior, the documentation does need to be clarified, as we said earlier. However, for arrayfun to truly behave like the for-loop, there would have to be an additional call to subsref(), for each element, and that would indeed slow things down. Still, if that's what it takes to achieve certain expected behavior...
>
> Perhaps they should add an additional parameter to let you force this, e.g.
>
> arrayfun(@isreal,In,'ProcessAsScalars',1);

My preference would be to leave arrayfun alone ... I wouldn't want to slow it down by creating potentially a huge number of temporary 1-element variables (each with 100+ bytes of overhead). I would rather fix isreal so that it actually looks at the imaginary part to see if it is zero or not. Maybe overload the intrinsic isreal with something akin to Bruno's suggestion, or with a mex routine.

James Tursa

Subject: Arrayfun bug?

From: Matt J

Date: 23 Jan, 2010 23:08:03

Message: 13 of 24

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hjft9e$nhi$1@fred.mathworks.com>...
> "Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <hjf4ta$ii5$1@fred.mathworks.com>...
> > "Oleg Komarov" <oleg.komarovRemove.this@hotmail.it> wrote in message <hjf3i6$nn5$1@fred.mathworks.com>...
> >
> > > In fact, I agree that gathering different classes cannot be done without a rule of dominance (for example: int8 upon double) but this doesn't mean that if the help of a function says that every element undergoes the same treatement the for loop should behave differently (or is the arrayfun that is behaving differently, to cut on speed and memory allocation?!).
> > =======================
> >
> > If it's intentional behavior, the documentation does need to be clarified, as we said earlier. However, for arrayfun to truly behave like the for-loop, there would have to be an additional call to subsref(), for each element, and that would indeed slow things down. Still, if that's what it takes to achieve certain expected behavior...
> >
> > Perhaps they should add an additional parameter to let you force this, e.g.
> >
> > arrayfun(@isreal,In,'ProcessAsScalars',1);
>
> My preference would be to leave arrayfun alone ... I wouldn't want to slow it down by creating potentially a huge number of temporary 1-element variables (each with 100+ bytes of overhead).
=========================

I don't see how that would be the result. arrayfun would simply loop through the array x, perform the scalar assignment y=x(i) at each iteration i, and then process y. The variable y could be recycled of course as the loop proceeded, so you wouldn't have a huge number of instances of y floating around.


++++++++++++++++++++++++
I would rather fix isreal so that it actually looks at the imaginary part to see if it is zero or not. Maybe overload the intrinsic isreal with something akin to Bruno's suggestion, or with a mex routine.
================

I think that would go against a prevalent MATLAB convention of reserviing is* functions as ways of testing for class/attributes. It's the same reason why the following statement returns false even though 0 clearly is an integer

>> isinteger(0)

ans =

     0

Subject: Arrayfun bug?

From: James Tursa

Date: 23 Jan, 2010 23:36:03

Message: 14 of 24

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <hjfvgj$dup$1@fred.mathworks.com>...
> "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hjft9e$nhi$1@fred.mathworks.com>...
> >
> > My preference would be to leave arrayfun alone ... I wouldn't want to slow it down by creating potentially a huge number of temporary 1-element variables (each with 100+ bytes of overhead).
> =========================
>
> I don't see how that would be the result. arrayfun would simply loop through the array x, perform the scalar assignment y=x(i) at each iteration i, and then process y. The variable y could be recycled of course as the loop proceeded, so you wouldn't have a huge number of instances of y floating around.

Doing y = x(i) creates a 100+ byte overhead structure every time you do it. To get around that I think you would have to do something like y(1) = x(i) which would probably only invoke a data copy and not a variable structure creation each time. Either that or do something special behind the scenes ala mex ect. Other than that, there is no such thing as "recycling y" in normal MATLAB programming that I am aware of for avoiding the 100+ byte overhead. Would be glad to learn more if there is ...

> ++++++++++++++++++++++++
> I would rather fix isreal so that it actually looks at the imaginary part to see if it is zero or not. Maybe overload the intrinsic isreal with something akin to Bruno's suggestion, or with a mex routine.
> ================
>
> I think that would go against a prevalent MATLAB convention of reserviing is* functions as ways of testing for class/attributes. It's the same reason why the following statement returns false even though 0 clearly is an integer
>
> >> isinteger(0)
>
> ans =
>
> 0

I don't see it this way at all. 0 is a double class variable and isinteger is testing for the class itself, not anything to do with the data in the variable. isreal is *not* testing for the class itself, it is testing for some result based on the data of the variable. I don't see how the two are related to each other in this context and the comparison is not a good one. Plus I simply think it makes more sense to test for a zero imaginary part for the isreal test instead of being based solely on whether the imaginary memory is present or not. I don't think it is reasonable to ask users to understand the subtleties of whether the imaginary memory is physically present or not for them to be able to tell what isreal is going to return. The result should be value based regardless of that fact, IMO.

James Tursa

Subject: Arrayfun bug?

From: Matt J

Date: 24 Jan, 2010 00:23:02

Message: 15 of 24

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hjg153$qsh$1@fred.mathworks.com>...

> I don't see it this way at all. 0 is a double class variable and isinteger is testing for the class itself, not anything to do with the data in the variable. isreal is *not* testing for the class itself, it is testing for some result based on the data of the variable.
=============================

The evidence we've seen strongly suggests that isreal() is testing the class type (or rather its attributes) and doesn't inspect the contents of the data at all when it executes. That's quite consistent with the counter-intuitive things Oleg was seeing along with all the other tests by the different posters. If I had to guess, I'd say it's implemented something like this:

function out=isreal(x)

 s=whos('x');
 out=~s.complex;

end


Now, you could argue, and I'd probably agree, that this is a poor name for this function, if this is what it meant to do, and that it should really be called
isrealDataType() to avoid confusion. However, that must be what it is intended to do since other similarly named functions (e.g., isinteger) perform the same kind of test.

Finally, if you think that the more intuitive behavior of a function named isreal is to test whether the data passed to it represents a quantity in the space of reals, I don't see why you wouldn't apply the same reasoning to isinteger(). Surely, with a name like that, one is just as likely to suppose that it is assessing whether the data represents something in the space of integers.

Subject: Arrayfun bug?

From: James Tursa

Date: 24 Jan, 2010 01:15:05

Message: 16 of 24

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <hjg3t6$kli$1@fred.mathworks.com>...
>
> The evidence we've seen strongly suggests that isreal() is testing the class type (or rather its attributes) and doesn't inspect the contents of the data at all when it executes.

The evidence, imo, shows that isreal is simply checking for a non-NULL pi address. Nothing more.

> Now, you could argue, and I'd probably agree, that this is a poor name for this function, if this is what it meant to do, and that it should really be called
> isrealDataType() to avoid confusion. However, that must be what it is intended to do since other similarly named functions (e.g., isinteger) perform the same kind of test.

I guess we will just have to disagree on that one.

> Finally, if you think that the more intuitive behavior of a function named isreal is to test whether the data passed to it represents a quantity in the space of reals, I don't see why you wouldn't apply the same reasoning to isinteger().

For the reason I already stated. isinteger is testing for class itself, isreal is testing for the data in the class (or attribute of the class as you put it). Two different tests. So again, I think we will just disagree here.

I *will* agree with you that isreal is either inconsistently or misleadingly named based on some of the posted results in this thread, particularly with respect to arrayfun and its doc.

James Tursa

Subject: Arrayfun bug?

From: Matt J

Date: 24 Jan, 2010 02:06:09

Message: 17 of 24

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hjg6up$345$1@fred.mathworks.com>...

> For the reason I already stated. isinteger is testing for class itself, isreal is testing for the data in the class (or attribute of the class as you put it).
===========

Well, I was trying very hard to draw a distinction between "attributes" and "data"...

Just so I'm clear on what we're agreeing to disagree on, you do agree that
isreal(X) does not loop through, scanning the numeric content of each X(i) any more than size(X) does, right?

Like size(), isreal() simply looks at the non-data, header-like properties of the object X, the ones that keep a record of things like whether X is type sparse or whether any of the X(i) are non-trivially complex.

If you don't agree with that, i.e., if you do think isreal scans each X(i) ,what evidence do you see of that or that that is the intended behavior?

Subject: Arrayfun bug?

From: James Tursa

Date: 24 Jan, 2010 02:59:03

Message: 18 of 24

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <hjg9uh$c0v$1@fred.mathworks.com>...
> "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hjg6up$345$1@fred.mathworks.com>...
>
> > For the reason I already stated. isinteger is testing for class itself, isreal is testing for the data in the class (or attribute of the class as you put it).
> ===========
>
> Well, I was trying very hard to draw a distinction between "attributes" and "data"...
>
> Just so I'm clear on what we're agreeing to disagree on, you do agree that
> isreal(X) does not loop through, scanning the numeric content of each X(i) any more than size(X) does, right?
>
> Like size(), isreal() simply looks at the non-data, header-like properties of the object X, the ones that keep a record of things like whether X is type sparse ...

Yes. Like I wrote earlier, isreal *seems* to only look at the pi (pointer to imaginary data area) value of a variable, which is part of the header information. I think we agree on that.

> ... or whether any of the X(i) are non-trivially complex.

No. Now you are stating something that is not based on the header info only.

> If you don't agree with that, i.e., if you do think isreal scans each X(i) ,what evidence do you see of that or that that is the intended behavior?

I seem to have not made my point very well. The specific example I posted with the mex routine showed that isreal does *not* scan the imaginary data itself. Where did you get the idea I was saying the opposite?

In practical terms, the distinction usually doesn't make a difference. I would guess that all MATLAB supplied functions scan the imaginary part of the result and free the imaginary data & NULL the pi pointer whenever all the imaginary parts are zero. I would be surprised to find out otherwise. Any m-files using only MATLAB functions would then inherit this behavior. However, I haven't seen anything in the doc that makes this a requirement vs just a good memory management technique. In particular, I don't recall seeing anything in the mex doc that requires this behavior, but I certainly haven't read all the mex doc so maybe I missed it. I routinely do it anyway with my mex routines, but that is more because I am not sure if I would break any MATLAB function if I didn't vs knowing that it would be invalid. I suppose TMW could just declare such variables to be invalid, but that still
wouldn't solve the arrayfun inconsistency.

James Tursa

Subject: Arrayfun bug?

From: Matt J

Date: 24 Jan, 2010 14:13:04

Message: 19 of 24

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hjgd1n$pkr$1@fred.mathworks.com>...

> I seem to have not made my point very well. The specific example I posted with the mex routine showed that isreal does *not* scan the imaginary data itself. Where did you get the idea I was saying the opposite?
====================

OK, now things are clear. I got the idea you were saying the opposite because you continued to use language like, "isreal is testing for the the data in the class", which made me think you were saying isreal is actually looking at the data, rather than just a pointer to the data.

Anyway, I do agree that there is a distinction between examining the class name and examining whether pi is NULL or not, but I think it is only a significant distinction under certain assumptions about what isreal is meant to do.

By analyzing whether pi is null or not, isreal is basically accomplishing the same kind of thing as isinteger, i.e., determining that the object holding the data has a certain format. It obviously doesn't reveal anything about the data content because, as you pointed out, it would be possible to use mex files to cheat and to create an array with zero imaginary data, but non-NULL pi.

The question is whether the intended role of isreal is truly to determine whether the imaginary data is non-zero or whether it is simply to test whether a non-NULL pi is being used. Well, again I argue, if it is not the purpose of isinteger to check whether its argument truly has integer values, I don't see why the purpose of isreal has to be to check whether its argument truly has real values (even though it would be good if there existed some function, say of a different name, that does so).


> In practical terms, the distinction usually doesn't make a difference. I would guess that all MATLAB supplied functions scan the imaginary part of the result and free the imaginary data & NULL the pi pointer whenever all the imaginary parts are zero.
=====================

Well, I guess it's pretty obvious that subsasgn() always does a full scan of the imaginary part. We see this in very standard scenarios like the example below.
Clearly, the assignment b(1)=0 had to have resulted in a full scan of the data in order for MATLAB to have known a conversion to a purely real array was possible.
But I would hate to think that *all* MATLAB supplied functions do these scans, because it would really slow things down.

>> a=rand(200,200,200); a(1)=i;
>> b=a; b(1)=0;
>> whos a b
  Name Size Bytes Class Attributes

  a 200x200x200 128000000 double complex
  b 200x200x200 64000000 double

++++++++++++++++++++++++++++++
I routinely do it anyway with my mex routines, but that is more because I am not sure if I would break any MATLAB function if I didn't
============================

At minimum, you would want to do this for the sake of speed. MATLAB might do unnecessary complex arithmetic on the arrays generated by your mex if you didn't always de-allocate the zero imaginary part.

Subject: Arrayfun bug?

From: Steven Lord

Date: 27 Jan, 2010 15:15:19

Message: 20 of 24


"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message
news:hjdioa$glq$1@fred.mathworks.com...
> "Matt Fig" <spamanon@yahoo.com> wrote in message
> <hjdhs6$np1$1@fred.mathworks.com>...
>
>> To me this does seem like a bug because of this line in the doc:
>>
>> "A = arrayfun(fun, S) applies the
>> function specified by fun to each element of array S,
>> and returns the results in array A. The value A returned
>> by arrayfun is the same size as S, and
>> the (I,J,...)th element of A is equal
>> to fun(S(I,J,...))"
> ================
>
> That is a genuine inconsistency, but one could equally well suppose the
> documentation, and not the software, is in error. I guess we'll have to
> let Steve L. or someone else of authority make the official pronouncement.

It does seem like this line needs to be worded more carefully. It shouldn't
use the word 'equal' but should probably say something like 'essentially
equivalent to'.

As James hypothesized later in this thread, ISREAL basically just checks to
make sure the array has an imaginary part -- it doesn't care what's actually
_in_ that imaginary part. So ISREAL on complex(1, 0) will return false,
since the input will have an imaginary part even though that imaginary part
is all zeros. This is described in a little more depth in the reference
page for ISREAL:

http://www.mathworks.com/access/helpdesk/help/techdoc/ref/isreal.html

Compare ISREAL, which returns a scalar, against ISFINITE which returns an
array the same size and shape as its input. ISREAL is looking at a property
of the matrix as a whole, while ISFINITE looks at each element to determine
if it is finite or not.

>> isfinite([pi NaN Inf -Inf])
ans =
     1 0 0 0

>> isreal([pi NaN Inf -Inf])
ans =
     1

[And yes, the IS prefix for a function has at least two different
"meanings" -- some of the IS* functions look at a property of the array as a
whole, some look at properties of the elements. I understand it can be
confusing determining which is which.]

I will ask our documentation staff to examine this section of the ARRAYFUN
documentation to see if we can clarify this without getting too deep into
the gory details.

--
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ

Subject: Arrayfun bug?

From: Jason

Date: 21 Feb, 2012 20:02:11

Message: 21 of 24

"Steven Lord" <slord@mathworks.com> wrote in message <hjpla3$4d4$1@fred.mathworks.com>...
>
> "Matt J " <mattjacREMOVE@THISieee.spam> wrote in message
> news:hjdioa$glq$1@fred.mathworks.com...
> > "Matt Fig" <spamanon@yahoo.com> wrote in message
> > <hjdhs6$np1$1@fred.mathworks.com>...
> >
> >> To me this does seem like a bug because of this line in the doc:
> >>
> >> "A = arrayfun(fun, S) applies the
> >> function specified by fun to each element of array S,
> >> and returns the results in array A. The value A returned
> >> by arrayfun is the same size as S, and
> >> the (I,J,...)th element of A is equal
> >> to fun(S(I,J,...))"
> > ================
> >
> > That is a genuine inconsistency, but one could equally well suppose the
> > documentation, and not the software, is in error. I guess we'll have to
> > let Steve L. or someone else of authority make the official pronouncement.
>
> It does seem like this line needs to be worded more carefully. It shouldn't
> use the word 'equal' but should probably say something like 'essentially
> equivalent to'.
>
> As James hypothesized later in this thread, ISREAL basically just checks to
> make sure the array has an imaginary part -- it doesn't care what's actually
> _in_ that imaginary part. So ISREAL on complex(1, 0) will return false,
> since the input will have an imaginary part even though that imaginary part
> is all zeros. This is described in a little more depth in the reference
> page for ISREAL:
>
> http://www.mathworks.com/access/helpdesk/help/techdoc/ref/isreal.html
>
> Compare ISREAL, which returns a scalar, against ISFINITE which returns an
> array the same size and shape as its input. ISREAL is looking at a property
> of the matrix as a whole, while ISFINITE looks at each element to determine
> if it is finite or not.
>
> >> isfinite([pi NaN Inf -Inf])
> ans =
> 1 0 0 0
>
> >> isreal([pi NaN Inf -Inf])
> ans =
> 1
>
> [And yes, the IS prefix for a function has at least two different
> "meanings" -- some of the IS* functions look at a property of the array as a
> whole, some look at properties of the elements. I understand it can be
> confusing determining which is which.]
>
> I will ask our documentation staff to examine this section of the ARRAYFUN
> documentation to see if we can clarify this without getting too deep into
> the gory details.
>
> --
> Steve Lord
> slord@mathworks.com
> comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
>


I know this is an old post but wanted to comment anyways. I'm running Matlab 2010 so perhaps this has in fact been addressed in the newest documentation, but I'm not sure that minor language change would have helped me. My variation of the problem was that I had an array (named Veq) with a combination of real and complex values and I wanted to replace all the complex values with zero. So I was doing:
>> Veq(~arrayfun(@isreal,Veq)) = 0;

This would replace all values in the array with 0, apparently for the same reasons described above, even though I knew there were real values.

Fortunately I found this thread easily but not before I wasted a bit of time trying to understand what was happening. To appreciate the confusion, consider these two cases:

>> find(arrayfun(@isreal,Veq))

ans =

   Empty matrix: 0-by-1

>> find(arrayfun(@isreal,Veq(190:195)))

ans =

     1
     2
     3
     4
     5
     6

If I understand the discussion here correctly, my array Veq is being stored as complex since some of the values have complex parts, so when isreal is called all it sees is memory allocated for a complex part and returns 0 for everything. But when I index the array over a small subset that contains only real numbers, those values are converted to real values before isreal can evaluate them.

If I have that correct then my argument would be that when a value being store as complex is displayed it should always show the complex part, something like '1 + 0.0000i'. As it is, the value appears on the screen as if it's real when in fact it's being stored as complex. Perhaps there is a display setting somewhere to change that behavior.

I hope at least the documentation is clarified. The behavior may seem obvious to programmers but to us tinkerers who rarely have to worry too much about memory allocation it can cause much heartache. Thanks to those that fleshed this out in this thread, you saved me even more heartache.

Subject: Arrayfun bug?

From: James Tursa

Date: 21 Feb, 2012 20:29:11

Message: 22 of 24

"Jason" wrote in message <ji0t83$omj$1@newscl01ah.mathworks.com>...
> "Steven Lord" <slord@mathworks.com> wrote in message <hjpla3$4d4$1@fred.mathworks.com>...
>
> I know this is an old post but wanted to comment anyways. I'm running Matlab 2010 so perhaps this has in fact been addressed in the newest documentation, but I'm not sure that minor language change would have helped me. My variation of the problem was that I had an array (named Veq) with a combination of real and complex values and I wanted to replace all the complex values with zero. So I was doing:
> >> Veq(~arrayfun(@isreal,Veq)) = 0;
>
> This would replace all values in the array with 0, apparently for the same reasons described above, even though I knew there were real values.
>
> Fortunately I found this thread easily but not before I wasted a bit of time trying to understand what was happening. To appreciate the confusion, consider these two cases:
>
> >> find(arrayfun(@isreal,Veq))
>
> ans =
>
> Empty matrix: 0-by-1
>
> >> find(arrayfun(@isreal,Veq(190:195)))
>
> ans =
>
> 1
> 2
> 3
> 4
> 5
> 6
>
> If I understand the discussion here correctly, my array Veq is being stored as complex since some of the values have complex parts, so when isreal is called all it sees is memory allocated for a complex part and returns 0 for everything. But when I index the array over a small subset that contains only real numbers, those values are converted to real values before isreal can evaluate them.

Yes. That is what is happening.

>
> If I have that correct then my argument would be that when a value being store as complex is displayed it should always show the complex part, something like '1 + 0.0000i'. As it is, the value appears on the screen as if it's real when in fact it's being stored as complex. Perhaps there is a display setting somewhere to change that behavior.

That would certainly help the user in these situations, IMO. (But others might argue it clutters up the screen.)

>
> I hope at least the documentation is clarified. The behavior may seem obvious to programmers but to us tinkerers who rarely have to worry too much about memory allocation it can cause much heartache. Thanks to those that fleshed this out in this thread, you saved me even more heartache.

I don't think the distinction is obvious at first even to programmers. For you case, and other similar cases, maybe include these examples in the doc with alternate approaches. E.g., using imag(x)==0 instead of the arrayfun+isreal approach to determine a result consistent with a for-loop approach. Etc.

Maybe it's time for an FEX mex submission that behaves elementally as expected ...

James Tursa

Subject: Arrayfun bug?

From: Matt J

Date: 21 Feb, 2012 20:39:11

Message: 23 of 24

"Jason" wrote in message <ji0t83$omj$1@newscl01ah.mathworks.com>...
>
My variation of the problem was that I had an array (named Veq) with a combination of real and complex values and I wanted to replace all the complex values with zero. So I was doing:
> >> Veq(~arrayfun(@isreal,Veq)) = 0;
===============

As a side note, you probably would accomplish this truncation better by doing

Veq=Veq.*(Veq==conj(Veq));

As you probably know, arrayfun is not highly optimized for speed.

Subject: Arrayfun bug?

From: Steven_Lord

Date: 21 Feb, 2012 21:41:18

Message: 24 of 24



"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message
news:ji0vdf$2s5$1@newscl01ah.mathworks.com...
> "Jason" wrote in message <ji0t83$omj$1@newscl01ah.mathworks.com>...
>>
> My variation of the problem was that I had an array (named Veq) with a
> combination of real and complex values and I wanted to replace all the
> complex values with zero. So I was doing:
>> >> Veq(~arrayfun(@isreal,Veq)) = 0;
> ===============
> As a side note, you probably would accomplish this truncation better by
> doing
>
> Veq=Veq.*(Veq==conj(Veq));
>
> As you probably know, arrayfun is not highly optimized for speed.

I would probably use:

imaginaryPartNonzero = imag(Veq) ~= 0;
Veq(imaginaryPartNonzero) = 0;

Convert to a one-liner if appropriate.

--
Steve Lord
slord@mathworks.com
To contact Technical Support use the Contact Us link on
http://www.mathworks.com

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us