0

The following MATLAB code snippet, which creates two arrays of complex numbers,

x = complex(1:2,0:1);
y = complex(zeros(1,2),0);
whos x y

prints

  Name      Size            Bytes  Class     Attributes

  x         1x2                32  double    complex   
  y         1x2                32  double    complex

as expected. However, after these two additional statements,

y(1) = x(1);
whos x y

the following gets printed:

  Name      Size            Bytes  Class     Attributes

  x         1x2                32  double    complex   
  y         1x2                16  double

How can one prevent the complex attribute from being dropped?

For the record, Octave does the same.

In practice, x is a function argument whose first entry happens to have a zero imaginary part, and y is the return value that is being preallocated.

Fabio Somenzi
  • 193
  • 3
  • 8

2 Answers2

3

If you want to make sure that the complex data type is maintained, explicitly cast the number to complex. Therefore:

y(1) = complex(x(1));

Because x(1) only has a real component, MATLAB automatically converts this to real in order to save space. As you can see, it would be more efficient to simply store the real component if the complex number is purely real as it's 8 bytes a number in comparison to complex where it's 16 bytes a number - 8 for the real component and 8 for the imaginary component.

Also in your code,y would technically be all real as there are no imaginary components. If y had at least one value that was complex valued, y would still be maintained as complex. Take a look at this code:

x = complex(1:2,0:1);
y = complex(zeros(1,2), [3 5]);
whos x y

Name      Size            Bytes  Class     Attributes

  x         1x2                32  double    complex   
  y         1x2                32  double    complex 

Now, let's try that assignment and examining the classes of x and y:

y(1) = x(1);
whos x y

Name      Size            Bytes  Class     Attributes

x         1x2                32  double    complex   
y         1x2                32  double    complex 

Also, as a sidenote, you shouldn't be concerned with x being converted to purely real. As soon as you place at least one complex valued number into this array, x automatically gets promoted to complex. Try, for example:

x = 1:5;
whos x

Name      Size            Bytes  Class     Attributes

x         1x5                40  double  

Now using the same x array, try:

x(3) = 1 + 4i;
whos x

Name      Size            Bytes  Class     Attributes

x         1x5                80  double    complex 

Edit

Going with your comments, what you can do to make sure that the array will stay complex would be to add an infinitesimal number to the imaginary part of x(1). A number small enough so that numerical differences are virtually zero, but enough to respect that y is still a complex valued array. As such:

x = complex(1:2,0:1);
y = complex(zeros(1,2),0);
y(1) = x(1) + i*eps;
who x y

Name      Size            Bytes  Class     Attributes

x         1x2                32  double    complex   
y         1x2                32  double    complex  

eps stands for machine epsilon. If you display y and show more significant digits, this is what we see:

format long
y

y =

  1.000000000000000 + 0.000000000000000i  0.000000000000000 + 0.000000000000000i

Try that and see if that works for you.

rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • Casting `x(1)` has no effect if `y` is initially all 0. It seems to work in your example because `y(2)` has nonzero imaginary part. – Fabio Somenzi Dec 06 '14 at 03:49
  • @FabioSomenzi - I see. However, you shouldn't be concerned with `x` being converted to purely real. See my edit on what happens if you start with a purely real array and then assign a complex valued number to any location in it. – rayryeng Dec 06 '14 at 03:52
  • Depending on how the complex attribute is implemented, I may be worrying for a matter of little import, but I'd like the allocation for the return value to be done once and for all. – Fabio Somenzi Dec 06 '14 at 03:53
  • 1
    @FabioSomenzi - Even if you start with a purely real array, as soon as you assign a complex valued number to any location in it, the array gets promoted to `complex`. As such, I don't really see any cause for concern. – rayryeng Dec 06 '14 at 03:54
  • @FabioSomenzi - Is there any particular reason why you would want to do that and not let MATLAB handle the memory required to store the array? At the end if your computation yields no complex valued numbers, why not just allow the array to be purely real? If you determined the imaginary component through `imag`, you would still get all zero values. I don't quite comprehend why the `complex` data type needs to be maintained if it isn't required. Please take no offense btw. I'm just having a hard time determining the reason for enforcing `complex` when it may not be required. – rayryeng Dec 06 '14 at 04:02
  • 1
    In the actual function, the probability that all values of `x` are real is minuscule. However, `x(1)` is usually real. So, as things stand, `y` changes size in most calls. (In fact, initializing it as an array of doubles causes it to change size only once per call, whereas initializing it as an array of complexes usually causes it to change size twice.) I'd like `y` to be allocated with the right size once and for all for efficiency. – Fabio Somenzi Dec 06 '14 at 04:52
  • @FabioSomenzi - Why don't you try adding a small floating point constant to the imaginary part of `x(1)`?... that way you'll ensure that the array is complex. I'll modify my answer. – rayryeng Dec 06 '14 at 05:02
  • Adding a small imaginary number may work in some circumstances, but you should check what you say about `eps` (i.e., `eps - e == eps` for every `e < eps`) because it is not even true of `realmin`, which is much smaller. While `1+eps/2 == 1` has value 1, `eps + 1e-17 == eps` has value 0, even though `1e-17 < eps`. – Fabio Somenzi Dec 06 '14 at 16:31
  • I misread machine epsilon so I will change by statement. Also I'm glad you found what you were looking for, even though I find it very unorthodox. – rayryeng Dec 06 '14 at 17:37
0

I think I found what I was looking for in this answer. In sum, an array of complex numbers has two memory blocks for the data: one to store the real parts and one to store the imaginary parts. The best course of action should be to initialize y to an array of doubles of the right size and let MATLAB add the second memory block on demand. The number of memory allocations is at most two, and there seems to be no way to reduce it.

Community
  • 1
  • 1
Fabio Somenzi
  • 193
  • 3
  • 8