[Numpy-discussion] byteswapping a complex scalar

Travis Oliphant oliphant at enthought.com
Thu Oct 8 08:09:44 EDT 2009


On Oct 7, 2009, at 10:28 AM, Michael Droettboom wrote:

> I'm noticing an inconsistency as to how complex numbers are  
> byteswapped
> as arrays vs. scalars, and wondering if I'm doing something wrong.
>
>>>> x = np.array([-1j], '<c8')
>>>> x.tostring().encode('hex')
> '00000000000080bf'
> # This is a little-endian representation, in the order (real, imag)
>
> # When I swap the whole array, it swaps each of the (real, imag) parts
> separately
>>>> y = x.byteswap()
>>>> y.tostring().encode('hex')
> '00000000bf800000'
> # and this round-trips fine
>>>> z = np.fromstring(y.tostring(), dtype='>c8')
>>>> assert z[0] == -1j
>>>>
>
> # When I swap the scalar, it seems to swap the entire 8 bytes
>>>> y = x[0].byteswap()
>>>> y.tostring().encode('hex')
> 'bf80000000000000'
> # ...and this doesn't round-trip
>>>> z = np.fromstring(y.tostring(), dtype='>c8')
>>>> assert z[0] == -1j
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> AssertionError
>>>>
>
> Any thoughts?

I think this is a bug.  You should file a ticket and mark it  
critical.    As I look at the scalar implementation (in  
gentype_byteswap in scalartypes.c.src), it looks like it's basing it  
just on the size (Hmm.... I don't know why it's not using the copyswap  
in the descr field....).   This works for many types, but not complex  
numbers which should have real and imaginary parts handled separately.

There are two ways to fix this that I can see:

	 1) fix the gentype implementation to use the copyswap function  
pointer from the datatype object
          2) over-ride the byteswap in the complex scalar Python type  
(there is a base-class complex scalar type where it could be placed)
                to do the right thing.

I would probably do #1 if I get a chance to work on it (because  
strings shouldn't be byteswapped either and they currently are, I  
see...)

x = np.array(['abcd'])

Compare:

x.byteswap()[0]
x[0].byteswap()


The work around is to byteswap before extraction:

x.byteswap()[0]

Thanks for the bug-report.

-Travis




More information about the NumPy-Discussion mailing list