Mercurial > hg > vamp-build-and-test
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 |