comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/doc/byteswapping.py @ 87:2a2c65a20a8b

Add Python libs and headers
author Chris Cannam
date Wed, 25 Feb 2015 14:05:22 +0000
parents
children
comparison
equal deleted inserted replaced
86:413a9d26189e 87:2a2c65a20a8b
1 """
2
3 =============================
4 Byteswapping and byte order
5 =============================
6
7 Introduction to byte ordering and ndarrays
8 ==========================================
9
10 The ``ndarray`` is an object that provide a python array interface to data
11 in memory.
12
13 It often happens that the memory that you want to view with an array is
14 not of the same byte ordering as the computer on which you are running
15 Python.
16
17 For example, I might be working on a computer with a little-endian CPU -
18 such as an Intel Pentium, but I have loaded some data from a file
19 written by a computer that is big-endian. Let's say I have loaded 4
20 bytes from a file written by a Sun (big-endian) computer. I know that
21 these 4 bytes represent two 16-bit integers. On a big-endian machine, a
22 two-byte integer is stored with the Most Significant Byte (MSB) first,
23 and then the Least Significant Byte (LSB). Thus the bytes are, in memory order:
24
25 #. MSB integer 1
26 #. LSB integer 1
27 #. MSB integer 2
28 #. LSB integer 2
29
30 Let's say the two integers were in fact 1 and 770. Because 770 = 256 *
31 3 + 2, the 4 bytes in memory would contain respectively: 0, 1, 3, 2.
32 The bytes I have loaded from the file would have these contents:
33
34 >>> big_end_str = chr(0) + chr(1) + chr(3) + chr(2)
35 >>> big_end_str
36 '\\x00\\x01\\x03\\x02'
37
38 We might want to use an ``ndarray`` to access these integers. In that
39 case, we can create an array around this memory, and tell numpy that
40 there are two integers, and that they are 16 bit and big-endian:
41
42 >>> import numpy as np
43 >>> big_end_arr = np.ndarray(shape=(2,),dtype='>i2', buffer=big_end_str)
44 >>> big_end_arr[0]
45 1
46 >>> big_end_arr[1]
47 770
48
49 Note the array ``dtype`` above of ``>i2``. The ``>`` means 'big-endian'
50 (``<`` is little-endian) and ``i2`` means 'signed 2-byte integer'. For
51 example, if our data represented a single unsigned 4-byte little-endian
52 integer, the dtype string would be ``<u4``.
53
54 In fact, why don't we try that?
55
56 >>> little_end_u4 = np.ndarray(shape=(1,),dtype='<u4', buffer=big_end_str)
57 >>> little_end_u4[0] == 1 * 256**1 + 3 * 256**2 + 2 * 256**3
58 True
59
60 Returning to our ``big_end_arr`` - in this case our underlying data is
61 big-endian (data endianness) and we've set the dtype to match (the dtype
62 is also big-endian). However, sometimes you need to flip these around.
63
64 Changing byte ordering
65 ======================
66
67 As you can imagine from the introduction, there are two ways you can
68 affect the relationship between the byte ordering of the array and the
69 underlying memory it is looking at:
70
71 * Change the byte-ordering information in the array dtype so that it
72 interprets the undelying data as being in a different byte order.
73 This is the role of ``arr.newbyteorder()``
74 * Change the byte-ordering of the underlying data, leaving the dtype
75 interpretation as it was. This is what ``arr.byteswap()`` does.
76
77 The common situations in which you need to change byte ordering are:
78
79 #. Your data and dtype endianess don't match, and you want to change
80 the dtype so that it matches the data.
81 #. Your data and dtype endianess don't match, and you want to swap the
82 data so that they match the dtype
83 #. Your data and dtype endianess match, but you want the data swapped
84 and the dtype to reflect this
85
86 Data and dtype endianness don't match, change dtype to match data
87 -----------------------------------------------------------------
88
89 We make something where they don't match:
90
91 >>> wrong_end_dtype_arr = np.ndarray(shape=(2,),dtype='<i2', buffer=big_end_str)
92 >>> wrong_end_dtype_arr[0]
93 256
94
95 The obvious fix for this situation is to change the dtype so it gives
96 the correct endianness:
97
98 >>> fixed_end_dtype_arr = wrong_end_dtype_arr.newbyteorder()
99 >>> fixed_end_dtype_arr[0]
100 1
101
102 Note the the array has not changed in memory:
103
104 >>> fixed_end_dtype_arr.tobytes() == big_end_str
105 True
106
107 Data and type endianness don't match, change data to match dtype
108 ----------------------------------------------------------------
109
110 You might want to do this if you need the data in memory to be a certain
111 ordering. For example you might be writing the memory out to a file
112 that needs a certain byte ordering.
113
114 >>> fixed_end_mem_arr = wrong_end_dtype_arr.byteswap()
115 >>> fixed_end_mem_arr[0]
116 1
117
118 Now the array *has* changed in memory:
119
120 >>> fixed_end_mem_arr.tobytes() == big_end_str
121 False
122
123 Data and dtype endianness match, swap data and dtype
124 ----------------------------------------------------
125
126 You may have a correctly specified array dtype, but you need the array
127 to have the opposite byte order in memory, and you want the dtype to
128 match so the array values make sense. In this case you just do both of
129 the previous operations:
130
131 >>> swapped_end_arr = big_end_arr.byteswap().newbyteorder()
132 >>> swapped_end_arr[0]
133 1
134 >>> swapped_end_arr.tobytes() == big_end_str
135 False
136
137 An easier way of casting the data to a specific dtype and byte ordering
138 can be achieved with the ndarray astype method:
139
140 >>> swapped_end_arr = big_end_arr.astype('<i2')
141 >>> swapped_end_arr[0]
142 1
143 >>> swapped_end_arr.tobytes() == big_end_str
144 False
145
146 """
147 from __future__ import division, absolute_import, print_function