**You are now following this question**

- You will see updates in your activity feed.
- You may receive emails, depending on your notification preferences.

2 views (last 30 days)

Show older comments

Why column (:) changes my data? (R2020b)

>> z=complex(3,0)

z =

3.000000000000000 + 0.000000000000000i

>> isreal(z)

ans =

logical

0

>> isreal(reshape(z,[],1))

ans =

logical

0

>> isreal(z(:)) %%%% <= only column returns 1

ans =

logical

1

Walter Roberson
on 18 Oct 2020

Interesting. I wonder if debugging would show a different data pointer, unlike reshape?

Bruno Luong
on 18 Oct 2020

The weird thing is actually no, the pointer stays the the same with format debug

I believe there are a flag of complex in the mxArray structure, this one must (wrongly?) be set by (:)

>> z

Structure address = 1b8e0bac460

m = 1

n = 1

pr = 1b8f7d92e20

3.0000 + 0.0000i

>> reshape(z,[],1)

Structure address = 1b8e0bac460

m = 1

n = 1

pr = 1b8f7d92e20

3.0000 + 0.0000i

>> z(:)

Structure address = 1b8e0bac460

m = 1

n = 1

pr = 1b8f7d92e20

3

VBBV
on 18 Oct 2020

Bcoz z is declared using complex function with two arguments, real numbès 3 and 0. The output is one complex number with one row and one col. For which the real part exists and equal to 3.

Use of : operator makes z as vector with two col and one row. So may be using it isreal(z(:)) makes z as real vector with real values only

Bruno Luong
on 18 Oct 2020

@Vasishta, Na. Your explanation does not make sense.

z(:)

should be the same as

reshape(z,[],1)

and it's one row one column and I expected it remains complex, as Z.

Walter Roberson
on 18 Oct 2020

Vasishta:

When you use : as the only subscript, the result always has exactly 1 column, even if the original array had dimensions that were only 0 such as zeros(0,0)

Walter Roberson
on 19 Oct 2020

Visashta:

The Tips section of complex() is telling you that complex() is a special function that can explicitly construct variables that have complex part that is all zero, but that the form A+B*i is considered an expression adding A and i*B and that since that is an expression, any all-zero imaginary part will be dropped.

Yes, complex part all-zero is a special case in MATLAB, and the boundaries of that special case are exactly what we are exploring here. It has always been the case that an all-zero complex part will not be lost when you copy or pass a variable, but that it would normally be lost if you use the variable in an expression. The question then arises whether calling reshape() or indexing with (:) should be considered an expression for the purposes of losing the all-zero part. Bruno demonstrated that reshape() does not lose the all-zero complex component, which fits in with the known implementation of reshape() as being about changing the dimension header while using exactly the same data pointer(s) .

Indexing with (:) has long been discussed as being a short-cut for reshape() into a column vector, and if that is the case then because reshape() does not lose the all-zero complex part, it would be unexpected that (:) would lose the all-zero complex part.

We can then ask the question of whether (:) is instead considered an expression rather than just a shortcut to reshape() into a single column. But if it were an expression, then we would expect that for real-valued z, z(:) would copy the data instead of sharing it, leading to a different data pointer. A minor bit of testing shows that is not the case, that when z only contains real values that z(:) shares data.

So... z(:) with complex z is somehow being treated specially, and losing all-zero complex part. z(:) with complex z is giving back a different data pointer.

Next we test

>> format debug

>> z = complex([1 2 3],4)

z =

Structure address = 1dc3db9a0

m = 1

n = 3

pr = 6040044bac60

1.0000 + 4.0000i 2.0000 + 4.0000i 3.0000 + 4.0000i

>> reshape(z,[],1)

ans =

Structure address = 1dc3d95a0

m = 3

n = 1

pr = 6040044bac60

1.0000 + 4.0000i

2.0000 + 4.0000i

3.0000 + 4.0000i

>> z(:)

ans =

Structure address = 1dc3d8d00

m = 3

n = 1

pr = 608005e83260

1.0000 + 4.0000i

2.0000 + 4.0000i

3.0000 + 4.0000i

Notice that when we did the reshape() that the data pointer stayed the same, but when we did the (:) that the data pointer changed. That does not happen when z has no complex part.

>> z1 = [1 2 3]

z1 =

Structure address = 1dc3da500

m = 1

n = 3

pr = 60800d076ca0

1 2 3

>> reshape(z1,[],1)

ans =

Structure address = 1dc3d9c60

m = 3

n = 1

pr = 60800d076ca0

1

2

3

>> z1(:)

ans =

Structure address = 1dc3d8d00

m = 3

n = 1

pr = 60800d076ca0

1

2

3

The problem therefor expands a bit beyond what Bruno originally posted, becoming instead the question:

What is (:) treated like an expression for complex z, but treated as reshape() for non-complex z?

With it being treated as an expression, losing the all-zero part would be automatic.

Walter Roberson
on 19 Oct 2020

Bruno's original example shows the same data pointer for scalar z. With non-scalar z, the data pointer is changed.

Other forms of indexing are expected to be treated as an expression.

>> z1 = [1 2 3]

z1 =

Structure address = 1dc3da500

m = 1

n = 3

pr = 60800d076ca0

1 2 3

>> z1(:)

ans =

Structure address = 1ed9c1960

m = 3

n = 1

pr = 60800d076ca0

1

2

3

>> z1(1:3)

ans =

Structure address = 19e7fcb20

m = 1

n = 3

pr = 60800d06ffa0

1 2 3

This is at least consistent between real and complex: this kind of indexing creates new data structures even for real-only data. It is also explicitly documented as creating unshared data: indexing at 1:end in particular is the documented way to create unshared copies of objects (though at the moment I do not recall at the moment whether it creates deep or shallow copies.)

Bruno Luong
on 19 Oct 2020

@Vanishta, you miss my point, the COMPLEX command allocates real+imaginary internally, even if imagnary part is 0. That is user intention of using complex command.

The whole purpose of the TIP part of the document is actually tells that user is allowed to create complex array with 0s value in imaginary part.

I expect (:) to preserve that allocation (and keep the data pointer constant) as with RESHAPE. Which is NOT the case.

Why doing such thing, you might ask? Because if I do change a subset of elements of the initial array, it will be faster (assumming array are not shared)

>> format debug

>> z=complex(1:3,0)

z =

Structure address = 2258b2d6a40

m = 1

n = 3

pr = 225a25023c0

1.0000 + 0.0000i 2.0000 + 0.0000i 3.0000 + 0.0000i

>> z(3)=1i % I might do this kind of assigment in for-loop

z =

Structure address = 2258b2d6a40

m = 1

n = 3

pr = 225a25023c0

1.0000 + 0.0000i 2.0000 + 0.0000i 0.0000 + 1.0000i

Unfortunately (:) operator would erase my allocation with COMPLEX.

Walter Roberson
on 18 Oct 2020

For reasons I do not understand, z(:) is being treated as an expression. If you make z larger but complex, then reshape(z,[],1) keeps the same data pointer, but z(:) creates a new data pointer each time -- which is not the case if z is not complex.

I have two speculations at the moment:

- Hypothetically, since array indexing is treated as an expression, Mathworks might have wanted consistency around dropping the complex part of expressions when the complex part was all zero. This explanation is a bit weak as it does not explain why they did not treat reshape() the same way, and does not explain why scalar z keeps the same data pointer (but non-scalar z does not.)
- Hypothetically, it might have to do with the change to representation of complex in R2018a. This explanation is a bit weak as it does not explain why they did not treat reshape() the same way, and does not explain why scalar z keeps the same data pointer (but non-scalar z does not.) On the other hand, this hypothesis has the merit that it would be testable by going back to R2017b and seeing if (:) had the same behaviour there.

per isakson
on 19 Oct 2020

>> z=complex(3,0)

z =

3.0000 + 0.0000i

>> isreal(z)

ans =

logical

0

>> isreal(z(:))

ans =

logical

1

>> version

ans =

'9.3.0.713579 (R2017b)'

>>

Walter Roberson
on 19 Oct 2020

Thanks, per... that eliminates (2) .

z(:) is also supposed to be z(1:end) but z(1:end) is documented as making copies. There thus seems to be a conflict here between whether z(:) is z(1:end) "copied" or is reshape(z,[],1) (uncopied), and that conflict seems to be resolved different ways depending upon whether z is real-only or has complex components.

Bruno Luong
on 19 Oct 2020

Walter; I too guess it's 1).

To me (:) would be less intrusive than what I just discover. I have tendency to use it a lot, but possibly I would think twice now.

Walter Roberson
on 19 Oct 2020

Hmmm... what is the difference between

z(:)

subsref(z,struct('type',{'()'}, 'subs', {{':'}}))

The second of those always creates a new data pointer even for real data, but the first of them does not create a new data pointer for real-valued z, or for scalar complex valued z (but the scalar part potentially loses complex 0)

Jan
on 28 Jul 2021

Just a check of Per's argument in the current Matlab version:

version

ans = '9.10.0.1716447 (R2021a) Update 4'

z=complex(3, 0)

z = 3.0000 + 0.0000i

isreal(z)

ans = logical

0

isreal(z(:))

ans = logical

1

Did somebody ask MathWorks about this behavior already?

Bruno Luong
on 28 Jul 2021

How to ask TMW a behavior that is not documented nor a bug?

Jan
on 28 Jul 2021

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

Start Hunting!**An Error Occurred**

Unable to complete the action because of changes made to the page. Reload the page to see its updated state.

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

Select web siteYou can also select a web site from the following list:

Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.

- América Latina (Español)
- Canada (English)
- United States (English)

- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)

- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)