# Copyright (C) Martin v. Löwis 2002 -*- coding: iso-8859-1 -*- # Use of this module is in accordance with the license agreement # in the accompanying LICENSE.HTML file. """Implementation of the CORBA long double (128-bit precision) type. """ import CORBA, types, struct class LongDouble: """Implementation of the CORBA long double type.""" def __init__(self, val, byte_order = 0): """Constructor. 'val' is a floating point number equal to this value.""" # Fnorb-internal: Can also pass 16-byte string and byte # order, which are a CDR representation of this value. if isinstance(val, types.FloatType): self.float = val self.long = None else: if byte_order: # little endian val = map(None, val) val.reverse() val = "".join(val) self.float = None self.long = val def _fnorb_from_float(self): "Convert self.float into self.long.""" # FIXME: Need to support inf, NaN x = struct.pack(">d", self.float) # unpack sign and exponent b0 = ord(x[0]) b1 = ord(x[1]) sign = b0 & 0x80 exp = ((b0 & 0x7f) << 4) + ((b1 & 0xF0) >> 4) # perform fraction computation in long int f = b1 & 0xfl for b in x[2:]: b = ord(b) f = (f << 8) + b # Reformat as long double # add 4 bits to get a total of 7 bytes fraction f <<= 4 # rebias exponent if exp: # -1023 + 16383 exp = exp + 15360 b0 = chr(sign | (exp >> 8)) b1 = chr(exp & 0xFF) n = chr(0) bytes = [b0,b1,None,None,None,None,None,None,None, n,n,n,n,n,n,n] for i in range(7): bytes[8-i] = chr(f & 0xFF) f >>= 8 assert f==0 self.long = "".join(bytes) def _fnorb_to_float(self): "Convert self.long to self.float." x = self.long # unpack sign and exponent b0 = ord(x[0]) b1 = ord(x[1]) sign = b0 & 0x80 exp = ((b0 & 0x7f) << 8) + b1 f = 0l # Need only 7 bytes for b in x[2:9]: b = ord(b) f = (f << 8) + b # Generate double representation # Drop 4 additional bits of precision # FIXME: need to do rounding f >>= 4 # rebias exponent if exp: # -16383+1023 exp -= 15360 if exp <= 0 or exp >= 2048: raise ValueError, "value too large for float" b0 = chr(sign | (exp >> 4)) b1 = (exp & 0xF) << 4 # need to add fraction MSB later bytes = [b0, None, 0, 0, 0, 0, 0, 0] for i in range(6): bytes[7-i] = chr(f & 0xFF) f >>= 8 assert f < 16 bytes[1] = chr(b1 | f) self.float = struct.unpack(">d", "".join(bytes))[0] def __float__(self): """Return the float value nearest to this long double.""" if self.float is None: self._fnorb_to_float() return self.float # mandated by language mapping to_float = __float__ def big_endian_bytes(self): """Return the long double in big-endian representation.""" if self.long is None: self._fnorb_from_float() return self.long def little_endian_bytes(self): """Return the long dobule in little-endian representation.""" bytes = map(None, self.big_endian_bytes()) bytes.reverse() bytes = "".join(bytes)