3

I am looking at the answer to this question and can't wrap my head around how the as_strided function is viewing this array.

This piece of code is part of the answer:

>>> a = np.lib.stride_tricks.as_strided(np.array([1, 512, 0, 3], dtype=np.int16), 
                                        shape=(3,), strides=(3,))
>>> a
array([1, 2, 3], dtype=int16)

>>> a.strides[0]
3

>>> a.itemsize
2 

Assuming each element of the passed array is 2 bytes long, we have the following byte representation of the array:

-------------------------------------------------------------------------------------
         1          |        512          |        0            |          3
-------------------------------------------------------------------------------------
0000 0000 0000 0001 | 0000 0010 0000 0000 | 0000 0000 0000 0000 | 0000 0000 0000 0011

So, considering each element to be read is of 2 bytes and the stride to reach the next element is 3 bytes:

  1. the first element read is 1 (0000 0000 0000 0001),
  2. the second element to be read is after skipping 3 bytes comes out to be 0 (0000 0000 | 0000 0000), half are bytes from the number 512 and the other half from the number 0
  3. the last element to be read after another stride of 3 bytes is 3: 0000 0000 0000 0011

So, where am I going wrong? how is the middle element 2 in the strided output and not 0

Rafay Khan
  • 1,070
  • 13
  • 25
  • In most uses the `as_strided` strides will be a multiple of the base strides of the input, in this case 2. Using 3 is deliberately asking for confusion. – hpaulj Jul 21 '19 at 15:11
  • Yeah, I do understand that which why this example seemed interesting to me as it was manipulating the bits and bytes change the underlying data. – Rafay Khan Jul 21 '19 at 15:34

1 Answers1

5

The little-endian memory layout of np.array([1, 512, 0, 3], dtype=np.int16) actually looks like this in memory (due to being little-endian, the individual entry bytes are actually in the reverse order from how you would write them):

(value)
-----------------------------------------------------------------------------------------
         1           |        512           |         0            |          3
-----------------------------------------------------------------------------------------
0000 0001  0000 0000 | 0000 0000  0000 0010 | 0000 0000  0000 0000 | 0000 0011  0000 0000
-----------------------------------------------------------------------------------------
        0          1           2          3           4          5           6          7
(byte number)

stride=3 means to move 3 bytes between items, so you'll get byte numbers 0-1, 3-4, 6-7.

These are 0000 0001 0000 0000, 0000 0010 0000 0000, 0000 0011 0000 0000, again interpreted as little-endian.

The strides of an array tell us how many bytes we have to skip in memory to move to the next position along a certain axis.

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ndarray.strides.html

cidermole
  • 5,662
  • 1
  • 15
  • 21
  • Sheesh! Thanks a bunch, I've spent considerable time figuring this out and completely looked over the "Endianness" of the underlying data. – Rafay Khan Jul 21 '19 at 13:32