Package python :: Module encoder
[hide private]
[frames] | no frames]

Source Code for Module python.encoder

  1  from math import frexp, fabs, ldexp 
  2  import sys 
  3   
  4  """ 
  5  The purpose of this module is to provide functions that 
  6  perform operations that really should be part of the python 
  7  standard, but surprisingly are not.  Apparently file i/o 
  8  in python is controlled by one and only one module and 
  9  reads and writes string ONLY.  This was surprising.  So 
 10  below are functions that form the bit representation of 
 11  int, longs, and floats and converts them to a character 
 12  string for maxiumum efficiency.  Hard to get better 
 13  compression than this I think. 
 14  """ 
 15   
16 -def _frexp(f):
17 """ 18 This is q think wrapper around python's frexp that returns 19 a mantissa and exponent in a form that is a little more 20 convenient for the the fileio module. Namely the exponent 21 offset form is preferable since there's now only one sign 22 to worry about. This greatly simplifies file i/o. The 23 mantissa is converted to an integer (* 10**15 to minimize 24 precision loss and fits into 52 bits) and the exponent is 25 shifted by 1023 to guarantee it is an unsigned integer and 26 fits into 11 bits. 27 @param f: The float value to be coverted to be decomposed into mantissa and exponent. 28 """ 29 (m,e) = frexp(f) 30 mant = int( m * 10**15 ) 31 exponent = e + 1023 32 return (mant,exponent) 33
34 -def _ldexp(m,e):
35 """ 36 This function performs the inverse of _frexp. Given a 37 mantissa and exponent, it returns the float representation. 38 @param m: mantissa assumed to be type long. 39 @param e: exponent assumed to be type int. 40 """ 41 return ldexp(m / 10.**15, e - 1023)
42
43 -def _bitstring_to_charstring(bit_string):
44 """ 45 This function takes a bit_string (i.e. '10010011') and returns 46 a string of characters ('\x93' in this example) that can be fed 47 to python's file write method. 48 """ 49 if not len(bit_string) % 8 : 50 result = "" 51 for chunk in [bit_string[n:n+8] for n in range(0,len(bit_string),8)]: 52 result += "%c" % chr(int("%s"% chunk,2)) 53 return result 54 else: 55 raise Error('Malformed bit string. Must be an integral number of bytes (i.e. 8 bits).')
56
57 -def _charstring_to_bitstring(char_string):
58 """ 59 This function takes a character string (i.e. '\x93') and returns 60 a string of bits ('10010011' in this example) that can be converted 61 to the correct type. 62 """ 63 bit_str = "" 64 for ch in char_string : 65 bit_str += bin( ord(ch) ).lstrip('0b').zfill(8) 66 return bit_str
67
68 -def _encode_mantissa_as_bitstring(mant):
69 """ 70 This is expecting an integer. The purpose of this function is to 71 return the bit_string representation of the mantissa. The length 72 of the string is 52 characters long and is meant to be combined 73 with the 11 bit exponent and 1 sign bit to form a 64 bit string 74 representation of a double precision float. 75 """ 76 mant_bin_rep = [0 for j in range(52)] 77 for n in reversed(range(52)): 78 f,mant = divmod(mant,2**n) 79 mant_bin_rep[n] = int(f) 80 mant_bin_rep.reverse() 81 result = "" 82 for b in mant_bin_rep: 83 result += "%d" % b 84 return result
85
86 -def _encode_exponent_as_bitstring(exponent):
87 """ 88 This is expecting an integer. The purpose of this function is to 89 return the bit_string representation of the exponent. The length 90 of the string is 11 characters long and is meant to be combined 91 with the 52 bit exponent and 1 sign bit to form a 64 bit string 92 representation of a double precision float. 93 """ 94 exp_bin_rep = [0 for j in range(11)] 95 for n in reversed(range(11)): 96 f,exponent = divmod(exponent,2**n) 97 exp_bin_rep[n] = int(f) 98 exp_bin_rep.reverse() 99 result = "" 100 for b in exp_bin_rep: 101 result += "%d" % b 102 return result
103
104 -def encode_unsigned(i):
105 """ 106 This function 'encodes' both int and long types and returns a string 107 that can be fed to the pyhton file's write method. 108 """ 109 if type(i) == type(int()): 110 nbytes = 4 111 if type(i) == type(long()): 112 nbytes = 8 113 return _bitstring_to_charstring( bin(i).lstrip('0b').zfill(nbytes*8) )
114
115 -def decode_unsigned(char_string):
116 """ 117 The function decodes a string of characters and returns the integer (or long) value. 118 """ 119 bit_str = _charstring_to_bitstring(char_string) 120 if len(char_string) == 4 : 121 return int(bit_str ,2) 122 if len(char_string) == 8 : 123 return long(bit_str,2)
124
125 -def encode_float(f):
126 """ 127 This function translates a float to its 8 byte 128 character string repesentation so that python's 129 file write method can write it. The 64 bit representation 130 is a follows: 131 1. 1 bit for the sign 132 133 2. 11 bits for the exponent 134 135 3. 52 bits for the mantissa 136 137 So read as a string the SIGN is in the 0th position, the EXPONENT is 1-11, 138 and the MANTISSA is 12-52. 139 m / 10.**15, e - 1023 140 f = (-1)**SIGN * (MANTISSA/10**15) * 2**(EXPONENT - 1023 ) 141 """ 142 if type(f) != type(float()): 143 print "this is not a float" 144 sys.exit() 145 146 (m,e) = _frexp(fabs(f)) 147 148 if f < 0 : sign = 1 149 else : sign = 0 150 result = "%d" % sign 151 result += _encode_exponent_as_bitstring(e) 152 result += _encode_mantissa_as_bitstring( fabs(m) ) 153 return _bitstring_to_charstring(result)
154
155 -def decode_float(s):
156 """ 157 This function translates an 8 byte character string repesentation 158 to a float. See the coreresponding _frexp function for the byte 159 layout and interpretation. 160 """ 161 if len(s) != 8 : 162 print "this is not right - len('%s') = %d " % (s,len(s)) 163 sys.exit() 164 bin_str = _charstring_to_bitstring(s) 165 if bin_str[0] == '0' : sign = +1 166 if bin_str[0] == '1' : sign = -1 167 exponent = int(bin_str[1:12],2) 168 mantissa = long(bin_str[12:],2) 169 return sign * _ldexp(mantissa,exponent)
170