Sleepyhead
Sleepyhead

Reputation: 1021

taking real or imaginary part makes array not C-contigous in numpy

I have a numpy-array and I need it to be C- of F-contiguous (for paraview):

t=np.linspace(0,10) y=exp(1j*t) So far it is contiguous, which I check by y.flags. But when I take either real or imaginary part of this array - it becomes non-contiguous, for example y.real.flags shows that. If I on the other hand take abs(y) or angle(y) - they are both contiguous, so I can actually find real and imaginary part by doing cos or sin of angle(y). Why is taking real or imag make array non-contiguous? Bug?

Upvotes: 0

Views: 79

Answers (1)

abarnert
abarnert

Reputation: 366093

y.real and y.imag are just giving you views into the y array that skip every other 8 bytes. Notice that OWNDATA: False flag? That's what it means: they're just a view onto someone else's data. That's also why they're not contiguous. It's not a bug, it's an optimization.

abs and angle have to build a whole new array. Which is contiguous, but it also means you just spent linear time and space instead of a constant few dozen bytes and nanoseconds.

Of course if want to build a whole new array, you can always do that explicitly:

>>> y.real.copy().flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

Or:

>>> np.ascontiguousarray(y.real).flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

copy of course always copies; I believe ascontiguousarray copies only if the array isn't already contiguous. That doesn't seem to be guaranteed in the docs, but I'm pretty sure it just calls require. (Anyway, either one will be a lot faster than cos(angle(y)).)

Upvotes: 1

Related Questions