File indexing completed on 2026-04-09 07:48:48
0001
0002 """
0003 intpack.py
0004 ------------
0005
0006 Thinking about twos-complement representation of signed integers
0007 and bit packing. See SSys::unsigned_as_int
0008
0009 When packing signed ints have to be more careful with the masking
0010 to avoid getting "leaking" bits as -1:0xffffffff
0011
0012 ::
0013
0014 In [15]: ( 0 << 16 )
0015 Out[15]: 0
0016 In [16]: ( 0 << 16 ) | -1
0017 Out[16]: -1
0018 In [17]: pack = ( 0 << 16 ) | -1
0019 In [18]: pack >> 16
0020 Out[18]: -1
0021 In [19]: pack = ( ( 0 & 0xffff) << 16 ) | ( -1 & 0xffff )
0022 In [20]: "%x" % pack
0023 Out[20]: 'ffff'
0024 In [21]: pack >> 16
0025 Out[21]: 0
0026
0027 """
0028 import sys, binascii as ba, numpy as np
0029 x_ = lambda _:ba.hexlify(_)
0030
0031 num_bytes = 4
0032 signed_max = (0x1 << (num_bytes*8 - 1)) - 1
0033
0034 ii = list(range(-10,10)) + list(range(signed_max - 10, signed_max+1)) + list(range(-(signed_max+1), -signed_max+10))
0035
0036 assert sys.byteorder == 'little'
0037
0038
0039 i2big_ = lambda _:ba.hexlify(_.to_bytes(2, "big", signed=True )).decode()
0040 i4big_ = lambda _:ba.hexlify(_.to_bytes(4, "big", signed=True )).decode()
0041
0042
0043
0044
0045 for i in ii:
0046 u = np.uint32(i)
0047 v = u.view(np.int32)
0048 assert v == i
0049
0050 uhi = ( u & 0xffff0000 ) >> 16
0051 ulo = ( u & 0x0000ffff ) >> 0
0052
0053 l = i.to_bytes(num_bytes, "little", signed=True )
0054 b = i.to_bytes(num_bytes, "big", signed=True )
0055
0056 print("i:%12d u:%12d x:%8x xhi:%4x xlo:%4x little:%10s big:%10s " % (i,u,u,uhi,ulo,x_(l), x_(b)))
0057 pass
0058
0059 print("(endianness is implementation detail that only very rarely need to think about even when masking and packing, only relevant when doing very low level debug eg with xxd)")
0060 print("(splitting a 16 bit value across two adjacent 8 bit fields and then reinterpreting them as 16 bit is one example where would need to consider endianness)")
0061 print("little: least significant byte is first in memory")
0062 print(" big: least significant byte is last in memory")
0063 print(" x: hex string presentation looks like big-endian, the less common endianness" )
0064 print(" sys.byteorder : %s " % sys.byteorder)
0065
0066
0067
0068
0069
0070 n0 = np.arange(0, -100, -1, dtype=np.int32)
0071 n1 = -1000 + n0
0072
0073 nn = np.zeros(len(n0), dtype=np.uint32)
0074
0075 nn[:] = (( n0 & 0xffff ) << 16 ) | ((n1 & 0xffff) << 0 )
0076
0077
0078
0079 n0chk = ( n0 & 0xffff ).view(np.int16)[::2]
0080 assert np.all( n0chk == n0 )
0081
0082 n1chk = ( n1 & 0xffff ).view(np.int16)[::2]
0083 assert np.all( n1chk == n1 )
0084
0085 nn_0 = (nn >> 16).view(np.int16)[::2]
0086 assert np.all( n0 == nn_0 )
0087
0088 nn_1 = (nn & 0xffff).view(np.int16)[::2]
0089 assert np.all( n1 == nn_1 )
0090
0091
0092
0093 p0 = np.arange(0, 100, dtype=np.uint32)
0094 p1 = 1000 + p0
0095 pp = np.zeros( len(p0), dtype=np.uint32)
0096
0097 pp[:] = (( p0 & 0xffff ) << 16 ) | ((p1 & 0xffff) << 0 )
0098
0099 p0chk = p0 & 0xffff
0100 assert np.all( p0chk == p0 )
0101
0102 p0chk_ = ( p0 & 0xffff ).view(np.int16)[::2]
0103 assert np.all( p0chk_ == p0 )
0104
0105 p1chk = p1 & 0xffff
0106 assert np.all( p1chk == p1 )
0107
0108 p1chk_ = ( p1 & 0xffff ).view(np.int16)[::2]
0109 assert np.all( p1chk_ == p1 )
0110
0111
0112
0113 r0 = np.arange(-0x7fff-1-1, 0x7fff+1+1, dtype=np.int32)
0114 r1 = r0[::-1]
0115
0116 rr = np.zeros( len(r0), dtype=np.uint32 )
0117 rr[:] = ((r0 & 0xffff) << 16 ) | ((r1 & 0xffff) << 0)
0118
0119 rr_0 = (rr >> 16).view(np.int16)[::2]
0120 rr_1 = (rr & 0xffff).view(np.int16)[::2]
0121
0122
0123 assert len(np.where( rr_0 != r0 )[0]) == 2
0124 assert len(np.where( rr_1 != r1 )[0]) == 2
0125
0126
0127
0128